diff options
Diffstat (limited to 'src')
321 files changed, 67405 insertions, 50797 deletions
diff --git a/src/.asan-blacklist b/src/.asan-blacklist index 7636f8fa82..928d81bd5a 100644 --- a/src/.asan-blacklist +++ b/src/.asan-blacklist @@ -1,3 +1,3 @@ # multiqueue.h pointer arithmetic is not accepted by asan fun:multiqueue_node_data -fun:dictwatcher_node_data +fun:tv_dict_watcher_node_data diff --git a/src/.valgrind.supp b/src/.valgrind.supp index 8b630fcaaf..cce22bd632 100644 --- a/src/.valgrind.supp +++ b/src/.valgrind.supp @@ -10,7 +10,7 @@ Memcheck:Leak fun:malloc fun:uv_spawn - fun:pipe_process_spawn + fun:libuv_process_spawn fun:process_spawn fun:job_start } diff --git a/src/clint.py b/src/clint.py index e0f4d3eec5..4a41650ec4 100755 --- a/src/clint.py +++ b/src/clint.py @@ -182,6 +182,7 @@ _ERROR_CATEGORIES = [ 'build/include_order', 'build/printf_format', 'build/storage_class', + 'build/useless_fattr', 'readability/alt_tokens', 'readability/bool', 'readability/braces', @@ -571,7 +572,8 @@ class _CppLintState(object): for category, count in self.errors_by_category.items(): sys.stderr.write('Category \'%s\' errors found: %d\n' % (category, count)) - sys.stderr.write('Total errors found: %d\n' % self.error_count) + if self.error_count: + sys.stderr.write('Total errors found: %d\n' % self.error_count) def SuppressErrorsFrom(self, fname): """Open file and read a list of suppressed errors from it""" @@ -1224,6 +1226,10 @@ def CheckForHeaderGuard(filename, lines, error): lines: An array of strings, each representing a line of the file. error: The function to call with any errors found. """ + if filename.endswith('.c.h') or FileInfo(filename).RelativePath() in set(( + 'func_attr.h', + )): + return cppvar = GetHeaderGuardCPPVariable(filename) @@ -2268,11 +2274,14 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error): # //!< Header comment # or they begin with multiple slashes followed by a space: # //////// Header comment + # or they are Vim {{{ fold markers match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or Search(r'^/$', line[commentend:]) or Search(r'^!< ', line[commentend:]) or Search(r'^/< ', line[commentend:]) or - Search(r'^/+ ', line[commentend:])) + Search(r'^/+ ', line[commentend:]) or + Search(r'^(?:\{{3}|\}{3})\d*(?: |$)', + line[commentend:])) if not match: error(filename, linenum, 'whitespace/comments', 4, 'Should have a space between // and comment') @@ -2520,6 +2529,8 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error): r'(?<!\bklist_t)' r'(?<!\bkliter_t)' r'(?<!\bkhash_t)' + r'(?<!\bkbtree_t)' + r'(?<!\bkbitr_t)' r'\((?:const )?(?:struct )?[a-zA-Z_]\w*(?: *\*(?:const)?)*\)' r' +' r'-?(?:\*+|&)?(?:\w+|\+\+|--|\()', cast_line) @@ -2591,16 +2602,24 @@ def CheckBraces(filename, clean_lines, linenum, error): else: func_start_linenum = end_linenum + 1 while not clean_lines.lines[func_start_linenum] == '{': - if not Match(r'^(?:\s*\b(?:FUNC_ATTR|REAL_FATTR)_\w+\b(?:\(\d+(, \d+)*\))?)+$', - clean_lines.lines[func_start_linenum]): - if clean_lines.lines[func_start_linenum].endswith('{'): + attrline = Match(r'^((?!# *define).*?)(?:FUNC_ATTR|FUNC_API|REAL_FATTR)_\w+(?:\(\d+(, \d+)*\))?', + clean_lines.lines[func_start_linenum]) + if attrline: + if len(attrline.group(1)) != 2: + error(filename, func_start_linenum, + 'whitespace/indent', 5, + 'Function attribute line should have 2-space ' + 'indent') + + func_start_linenum += 1 + else: + func_start = clean_lines.lines[func_start_linenum] + if not func_start.startswith('enum ') and func_start.endswith('{'): error(filename, func_start_linenum, 'readability/braces', 5, 'Brace starting function body must be placed ' 'after the function signature') break - else: - func_start_linenum += 1 # An else clause should be on the same line as the preceding closing brace. # If there is no preceding closing brace, there should be one. @@ -3166,11 +3185,20 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension, # Check if some verboten C functions are being used. if Search(r'\bsprintf\b', line): error(filename, linenum, 'runtime/printf', 5, - 'Never use sprintf. Use snprintf instead.') - match = Search(r'\b(strcpy|strcat)\b', line) + 'Use snprintf instead of sprintf.') + match = Search(r'\b(strncpy|STRNCPY)\b', line) + if match: + error(filename, linenum, 'runtime/printf', 4, + 'Use xstrlcpy or snprintf instead of %s (unless this is from Vim)' + % match.group(1)) + match = Search(r'\b(strcpy)\b', line) + if match: + error(filename, linenum, 'runtime/printf', 4, + 'Use xstrlcpy or snprintf instead of %s' % match.group(1)) + match = Search(r'\b(STRNCAT|strncat|strcat|vim_strcat)\b', line) if match: error(filename, linenum, 'runtime/printf', 4, - 'Almost always, snprintf is better than %s' % match.group(1)) + 'Use xstrlcat or snprintf instead of %s' % match.group(1)) # Check for suspicious usage of "if" like # } if (a == b) { @@ -3434,8 +3462,9 @@ def ProcessFile(filename, vlevel, extra_check_functions=[]): # When reading from stdin, the extension is unknown, so no cpplint tests # should rely on the extension. if filename != '-' and file_extension not in _valid_extensions: - sys.stderr.write('Ignoring %s; not a valid file name ' - '(%s)\n' % (filename, ', '.join(_valid_extensions))) + sys.stderr.write('Ignoring {}; only linting {} files\n'.format( + filename, + ', '.join('.{}'.format(ext) for ext in _valid_extensions))) else: ProcessFileData(filename, file_extension, lines, Error, extra_check_functions) @@ -3565,7 +3594,7 @@ def main(): if __name__ == '__main__': main() -# vim: ts=4 sts=4 sw=4 +# vim: ts=4 sts=4 sw=4 foldmarker=â–¶,â–² # Ignore "too complex" warnings when using pymode. # pylama:ignore=C901 diff --git a/src/coverity-model.c b/src/coverity-model.c new file mode 100644 index 0000000000..3c38e4ae4d --- /dev/null +++ b/src/coverity-model.c @@ -0,0 +1,70 @@ +// Coverity Scan model +// +// This is a modeling file for Coverity Scan. Modeling helps to avoid false +// positives. +// +// - A model file can't import any header files. +// - Therefore only some built-in primitives like int, char and void are +// available but not wchar_t, NULL etc. +// - Modeling doesn't need full structs and typedefs. Rudimentary structs +// and similar types are sufficient. +// - An uninitialized local pointer is not an error. It signifies that the +// variable could be either NULL or have some data. +// +// Coverity Scan doesn't pick up modifications automatically. The model file +// must be uploaded by an admin in the analysis settings of +// http://scan.coverity.com/projects/neovim-neovim +// + +// Issue 105985 +// +// Teach coverity that uv_pipe_open saves fd on success (0 return value) +// and doesn't save it on failure (return value != 0). + +struct uv_pipe_s { + int something; +}; + +int uv_pipe_open(struct uv_pipe_s *handle, int fd) +{ + int result; + if (result == 0) { + __coverity_escape__(fd); + } + return result; +} + +// Issue 2422 +// +// Teach coverity about jemalloc functions, so that it understands +// they are equivalent to malloc ones. + +void *je_malloc(size_t size) +{ + return __coverity_alloc__(size); +} + +void je_free(void *ptr) +{ + __coverity_free__(ptr); +} + +void *je_calloc(size_t count, size_t size) +{ + return je_malloc(count * size); +} + +void *je_realloc(void *ptr, size_t size) +{ + je_free(ptr); + return je_malloc(size); +} + +// Hint Coverity that adding item to d avoids losing track +// of the memory allocated for item. +typedef struct {} dictitem_T; +typedef struct {} dict_T; +int tv_dict_add(dict_T *const d, dictitem_T *const item) +{ + __coverity_escape__(item); +} diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index f2b75dca2a..e2f1f16635 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -10,44 +10,72 @@ if(USE_GCOV) endif() endif() +if(WIN32) + # tell MinGW compiler to enable wmain + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -municode") +endif() + +set(TOUCHES_DIR ${PROJECT_BINARY_DIR}/touches) +set(GENERATOR_DIR ${CMAKE_CURRENT_LIST_DIR}/generators) set(GENERATED_DIR ${PROJECT_BINARY_DIR}/src/nvim/auto) -set(DISPATCH_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gendispatch.lua) -file(GLOB API_HEADERS api/*.h) -file(GLOB MSGPACK_RPC_HEADERS msgpack_rpc/*.h) +set(API_DISPATCH_GENERATOR ${GENERATOR_DIR}/gen_api_dispatch.lua) +set(API_UI_EVENTS_GENERATOR ${GENERATOR_DIR}/gen_api_ui_events.lua) set(API_METADATA ${PROJECT_BINARY_DIR}/api_metadata.mpack) set(FUNCS_DATA ${PROJECT_BINARY_DIR}/funcs_data.mpack) -set(HEADER_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gendeclarations.lua) +set(MSGPACK_LUA_C_BINDINGS ${GENERATED_DIR}/msgpack_lua_c_bindings.generated.c) +set(HEADER_GENERATOR ${GENERATOR_DIR}/gen_declarations.lua) set(GENERATED_INCLUDES_DIR ${PROJECT_BINARY_DIR}/include) set(GENERATED_API_DISPATCH ${GENERATED_DIR}/api/private/dispatch_wrappers.generated.h) set(GENERATED_FUNCS_METADATA ${GENERATED_DIR}/api/private/funcs_metadata.generated.h) +set(GENERATED_UI_EVENTS ${GENERATED_DIR}/ui_events.generated.h) +set(GENERATED_UI_EVENTS_CALL ${GENERATED_DIR}/ui_events_call.generated.h) +set(GENERATED_UI_EVENTS_REMOTE ${GENERATED_DIR}/ui_events_remote.generated.h) +set(GENERATED_UI_EVENTS_BRIDGE ${GENERATED_DIR}/ui_events_bridge.generated.h) +set(GENERATED_UI_EVENTS_METADATA ${GENERATED_DIR}/api/private/ui_events_metadata.generated.h) set(GENERATED_EX_CMDS_ENUM ${GENERATED_INCLUDES_DIR}/ex_cmds_enum.generated.h) set(GENERATED_EX_CMDS_DEFS ${GENERATED_DIR}/ex_cmds_defs.generated.h) -set(GENERATED_FUNCS_HASH_INPUT ${GENERATED_DIR}/funcs.generated.h.gperf) set(GENERATED_FUNCS ${GENERATED_DIR}/funcs.generated.h) set(GENERATED_EVENTS_ENUM ${GENERATED_INCLUDES_DIR}/auevents_enum.generated.h) set(GENERATED_EVENTS_NAMES_MAP ${GENERATED_DIR}/auevents_name_map.generated.h) set(GENERATED_OPTIONS ${GENERATED_DIR}/options.generated.h) -set(EX_CMDS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genex_cmds.lua) -set(FUNCS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/geneval.lua) -set(EVENTS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gen_events.lua) -set(OPTIONS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genoptions.lua) -set(EVENTS_LIST_FILE ${PROJECT_SOURCE_DIR}/src/nvim/auevents.lua) -set(EX_CMDS_DEFS_FILE ${PROJECT_SOURCE_DIR}/src/nvim/ex_cmds.lua) -set(EVAL_DEFS_FILE ${PROJECT_SOURCE_DIR}/src/nvim/eval.lua) -set(OPTIONS_LIST_FILE ${PROJECT_SOURCE_DIR}/src/nvim/options.lua) -set(UNICODE_TABLES_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genunicodetables.lua) +set(EX_CMDS_GENERATOR ${GENERATOR_DIR}/gen_ex_cmds.lua) +set(FUNCS_GENERATOR ${GENERATOR_DIR}/gen_eval.lua) +set(EVENTS_GENERATOR ${GENERATOR_DIR}/gen_events.lua) +set(OPTIONS_GENERATOR ${GENERATOR_DIR}/gen_options.lua) +set(UNICODE_TABLES_GENERATOR ${GENERATOR_DIR}/gen_unicode_tables.lua) set(UNICODE_DIR ${PROJECT_SOURCE_DIR}/unicode) -file(GLOB UNICODE_FILES ${UNICODE_DIR}/*.txt) set(GENERATED_UNICODE_TABLES ${GENERATED_DIR}/unicode_tables.generated.h) +set(VIM_MODULE_FILE ${GENERATED_DIR}/lua/vim_module.generated.h) +set(VIM_MODULE_SOURCE ${PROJECT_SOURCE_DIR}/src/nvim/lua/vim.lua) +set(CHAR_BLOB_GENERATOR ${GENERATOR_DIR}/gen_char_blob.lua) +set(LINT_SUPPRESS_FILE ${PROJECT_BINARY_DIR}/errors.json) +set(LINT_SUPPRESS_URL_BASE "https://raw.githubusercontent.com/neovim/doc/gh-pages/reports/clint") +set(LINT_SUPPRESS_URL "${LINT_SUPPRESS_URL_BASE}/errors.json") +set(LINT_PRG ${PROJECT_SOURCE_DIR}/src/clint.py) +set(DOWNLOAD_SCRIPT ${PROJECT_SOURCE_DIR}/cmake/Download.cmake) +set(LINT_SUPPRESSES_ROOT ${PROJECT_BINARY_DIR}/errors) +set(LINT_SUPPRESSES_URL "${LINT_SUPPRESS_URL_BASE}/errors.tar.gz") +set(LINT_SUPPRESSES_ARCHIVE ${LINT_SUPPRESSES_ROOT}/errors.tar.gz) +set(LINT_SUPPRESSES_TOUCH_FILE "${TOUCHES_DIR}/unpacked-clint-errors-archive") +set(LINT_SUPPRESSES_INSTALL_SCRIPT "${PROJECT_SOURCE_DIR}/cmake/InstallClintErrors.cmake") + +file(GLOB UNICODE_FILES ${UNICODE_DIR}/*.txt) +file(GLOB API_HEADERS api/*.h) +list(REMOVE_ITEM API_HEADERS ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h) +file(GLOB MSGPACK_RPC_HEADERS msgpack_rpc/*.h) include_directories(${GENERATED_DIR}) include_directories(${CACHED_GENERATED_DIR}) include_directories(${GENERATED_INCLUDES_DIR}) +file(MAKE_DIRECTORY ${TOUCHES_DIR}) file(MAKE_DIRECTORY ${GENERATED_DIR}) file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}) +file(MAKE_DIRECTORY ${LINT_SUPPRESSES_ROOT}) +file(MAKE_DIRECTORY ${LINT_SUPPRESSES_ROOT}/src) -file(GLOB NEOVIM_SOURCES *.c) +file(GLOB NVIM_SOURCES *.c) +file(GLOB NVIM_HEADERS *.h) foreach(subdir os @@ -57,6 +85,7 @@ foreach(subdir tui event eval + lua ) if(${subdir} MATCHES "tui" AND NOT FEAT_TUI) continue() @@ -65,18 +94,21 @@ foreach(subdir file(MAKE_DIRECTORY ${GENERATED_DIR}/${subdir}) file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/${subdir}) file(GLOB sources ${subdir}/*.c) - list(APPEND NEOVIM_SOURCES ${sources}) + file(GLOB headers ${subdir}/*.h) + list(APPEND NVIM_SOURCES ${sources}) + list(APPEND NVIM_HEADERS ${headers}) endforeach() -file(GLOB_RECURSE NEOVIM_HEADERS *.h) file(GLOB UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c) # Sort file lists to ensure generated files are created in the same order from # build to build. -list(SORT NEOVIM_SOURCES) -list(SORT NEOVIM_HEADERS) +list(SORT NVIM_SOURCES) +list(SORT NVIM_HEADERS) + +list(APPEND LINT_NVIM_SOURCES ${NVIM_SOURCES} ${NVIM_HEADERS}) -foreach(sfile ${NEOVIM_SOURCES}) +foreach(sfile ${NVIM_SOURCES}) get_filename_component(f ${sfile} NAME) if(${f} MATCHES "^(regexp_nfa.c)$") list(APPEND to_remove ${sfile}) @@ -84,13 +116,15 @@ foreach(sfile ${NEOVIM_SOURCES}) if(WIN32 AND ${f} MATCHES "^(pty_process_unix.c)$") list(APPEND to_remove ${sfile}) endif() + if(NOT WIN32 AND ${f} MATCHES "^(pty_process_win.c)$") + list(APPEND to_remove ${sfile}) + endif() endforeach() -list(REMOVE_ITEM NEOVIM_SOURCES ${to_remove}) +list(REMOVE_ITEM NVIM_SOURCES ${to_remove}) # Legacy files that do not yet pass -Wconversion. set(CONV_SOURCES - buffer.c diff.c edit.c eval.c @@ -105,12 +139,13 @@ set(CONV_SOURCES screen.c search.c spell.c + spellfile.c syntax.c tag.c window.c) foreach(sfile ${CONV_SOURCES}) - if(NOT EXISTS "${PROJECT_SOURCE_DIR}/src/nvim/${sfile}") + if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/${sfile}") message(FATAL_ERROR "${sfile} doesn't exist (it was added to CONV_SOURCES)") endif() endforeach() @@ -144,7 +179,7 @@ if(CLANG_ASAN_UBSAN OR CLANG_MSAN OR CLANG_TSAN) endif() get_directory_property(gen_includes INCLUDE_DIRECTORIES) -foreach(gen_include ${gen_includes}) +foreach(gen_include ${gen_includes} ${LUA_PREFERRED_INCLUDE_DIRS}) list(APPEND gen_cflags "-I${gen_include}") endforeach() string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type) @@ -152,12 +187,28 @@ separate_arguments(C_FLAGS_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS}) separate_arguments(C_FLAGS_${build_type}_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS_${build_type}}) set(gen_cflags ${gen_cflags} ${C_FLAGS_${build_type}_ARRAY} ${C_FLAGS_ARRAY}) -foreach(sfile ${NEOVIM_SOURCES} - "${PROJECT_SOURCE_DIR}/src/nvim/regexp_nfa.c" - ${GENERATED_API_DISPATCH}) +function(get_preproc_output varname iname) + if(MSVC) + set(${varname} /P /Fi${iname} PARENT_SCOPE) + else() + set(${varname} -E -o ${iname} PARENT_SCOPE) + endif() +endfunction() + +# NVIM_GENERATED_FOR_HEADERS: generated headers to be included in headers +# NVIM_GENERATED_FOR_SOURCES: generated headers to be included in sources +# NVIM_GENERATED_SOURCES: generated source files +# These lists must be mutually exclusive. +foreach(sfile ${NVIM_SOURCES} + "${CMAKE_CURRENT_LIST_DIR}/regexp_nfa.c" + ${GENERATED_API_DISPATCH} + "${GENERATED_UI_EVENTS_CALL}" + "${GENERATED_UI_EVENTS_REMOTE}" + "${GENERATED_UI_EVENTS_BRIDGE}" + ) get_filename_component(full_d ${sfile} PATH) - file(RELATIVE_PATH d "${PROJECT_SOURCE_DIR}/src/nvim" "${full_d}") - if(${d} MATCHES "^([.][.]|auto/)") + file(RELATIVE_PATH d "${CMAKE_CURRENT_LIST_DIR}" "${full_d}") + if(${d} MATCHES "^[.][.]|auto/") file(RELATIVE_PATH d "${GENERATED_DIR}" "${full_d}") endif() get_filename_component(f ${sfile} NAME) @@ -166,26 +217,22 @@ foreach(sfile ${NEOVIM_SOURCES} set(f "${d}/${f}") set(r "${d}/${r}") endif() - set(gf1 "${GENERATED_DIR}/${r}.c.generated.h") - set(gf2 "${GENERATED_INCLUDES_DIR}/${r}.h.generated.h") - set(gf3 "${GENERATED_DIR}/${r}.i") + set(gf_c_h "${GENERATED_DIR}/${r}.c.generated.h") + set(gf_h_h "${GENERATED_INCLUDES_DIR}/${r}.h.generated.h") + set(gf_i "${GENERATED_DIR}/${r}.i") - if(MSVC) - set(PREPROC_OUTPUT /P /Fi${gf3}) - else() - set(PREPROC_OUTPUT -E -o ${gf3}) - endif() + get_preproc_output(PREPROC_OUTPUT ${gf_i}) add_custom_command( - OUTPUT "${gf1}" "${gf2}" + OUTPUT "${gf_c_h}" "${gf_h_h}" COMMAND ${CMAKE_C_COMPILER} ${sfile} ${PREPROC_OUTPUT} ${gen_cflags} ${C_FLAGS_ARRAY} - COMMAND "${LUA_PRG}" "${HEADER_GENERATOR}" "${sfile}" "${gf1}" "${gf2}" "${gf3}" + COMMAND "${LUA_PRG}" "${HEADER_GENERATOR}" "${sfile}" "${gf_c_h}" "${gf_h_h}" "${gf_i}" DEPENDS "${HEADER_GENERATOR}" "${sfile}" ) - list(APPEND NEOVIM_GENERATED_SOURCES "${gf1}") - list(APPEND NEOVIM_GENERATED_SOURCES "${gf2}") + list(APPEND NVIM_GENERATED_FOR_SOURCES "${gf_c_h}") + list(APPEND NVIM_GENERATED_FOR_HEADERS "${gf_h_h}") if(${d} MATCHES "^api$" AND NOT ${f} MATCHES "^api/helpers.c$") - list(APPEND API_HEADERS ${gf2}) + list(APPEND API_HEADERS ${gf_h_h}) endif() endforeach() @@ -198,33 +245,74 @@ add_custom_command(OUTPUT ${GENERATED_UNICODE_TABLES} ${UNICODE_FILES} ) -add_custom_command(OUTPUT ${GENERATED_API_DISPATCH} ${GENERATED_FUNCS_METADATA} - ${API_METADATA} - COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR} - ${API_HEADERS} ${GENERATED_API_DISPATCH} +add_custom_command( + OUTPUT ${GENERATED_API_DISPATCH} ${GENERATED_FUNCS_METADATA} + ${API_METADATA} ${MSGPACK_LUA_C_BINDINGS} + COMMAND ${LUA_PRG} ${API_DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR} + ${GENERATED_API_DISPATCH} ${GENERATED_FUNCS_METADATA} ${API_METADATA} + ${MSGPACK_LUA_C_BINDINGS} + ${API_HEADERS} DEPENDS ${API_HEADERS} ${MSGPACK_RPC_HEADERS} - ${DISPATCH_GENERATOR} + ${API_DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/api/dispatch_deprecated.lua ) -list(APPEND NEOVIM_GENERATED_SOURCES - "${PROJECT_BINARY_DIR}/config/auto/pathdef.c" - "${GENERATED_API_DISPATCH}" +add_custom_command( + OUTPUT ${VIM_MODULE_FILE} + COMMAND ${LUA_PRG} ${CHAR_BLOB_GENERATOR} ${VIM_MODULE_SOURCE} + ${VIM_MODULE_FILE} vim_module + DEPENDS + ${CHAR_BLOB_GENERATOR} + ${VIM_MODULE_SOURCE} +) + +list(APPEND NVIM_GENERATED_SOURCES + "${MSGPACK_LUA_C_BINDINGS}" +) + +add_custom_command( + OUTPUT ${GENERATED_UI_EVENTS} + ${GENERATED_UI_EVENTS_CALL} + ${GENERATED_UI_EVENTS_REMOTE} + ${GENERATED_UI_EVENTS_BRIDGE} + ${GENERATED_UI_EVENTS_METADATA} + COMMAND ${LUA_PRG} ${API_UI_EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR} + ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h + ${GENERATED_UI_EVENTS} + ${GENERATED_UI_EVENTS_CALL} + ${GENERATED_UI_EVENTS_REMOTE} + ${GENERATED_UI_EVENTS_BRIDGE} + ${GENERATED_UI_EVENTS_METADATA} + DEPENDS + ${API_UI_EVENTS_GENERATOR} + ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h +) + +list(APPEND NVIM_GENERATED_FOR_HEADERS "${GENERATED_EX_CMDS_ENUM}" - "${GENERATED_EX_CMDS_DEFS}" "${GENERATED_EVENTS_ENUM}" +) + +list(APPEND NVIM_GENERATED_FOR_SOURCES + "${GENERATED_API_DISPATCH}" + "${GENERATED_EX_CMDS_DEFS}" "${GENERATED_EVENTS_NAMES_MAP}" "${GENERATED_OPTIONS}" "${GENERATED_UNICODE_TABLES}" + "${VIM_MODULE_FILE}" +) + +list(APPEND NVIM_GENERATED_SOURCES + "${PROJECT_BINARY_DIR}/config/auto/pathdef.c" ) add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS} COMMAND ${LUA_PRG} ${EX_CMDS_GENERATOR} - ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_INCLUDES_DIR} ${GENERATED_DIR} - DEPENDS ${EX_CMDS_GENERATOR} ${EX_CMDS_DEFS_FILE} + ${CMAKE_CURRENT_LIST_DIR} ${GENERATED_INCLUDES_DIR} ${GENERATED_DIR} + DEPENDS ${EX_CMDS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/ex_cmds.lua ) if(NOT GPERF_PRG) @@ -232,26 +320,34 @@ if(NOT GPERF_PRG) endif() add_custom_command(OUTPUT ${GENERATED_FUNCS} ${FUNCS_DATA} COMMAND ${LUA_PRG} ${FUNCS_GENERATOR} - ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_DIR} ${API_METADATA} ${FUNCS_DATA} + ${CMAKE_CURRENT_LIST_DIR} ${GENERATED_DIR} ${API_METADATA} ${FUNCS_DATA} COMMAND ${GPERF_PRG} - ${GENERATED_FUNCS_HASH_INPUT} --output-file=${GENERATED_FUNCS} - DEPENDS ${FUNCS_GENERATOR} ${EVAL_DEFS_FILE} ${API_METADATA} + ${GENERATED_DIR}/funcs.generated.h.gperf --output-file=${GENERATED_FUNCS} + DEPENDS ${FUNCS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/eval.lua ${API_METADATA} ) -list(APPEND NEOVIM_GENERATED_SOURCES +list(APPEND NVIM_GENERATED_FOR_SOURCES "${GENERATED_FUNCS}") add_custom_command(OUTPUT ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP} COMMAND ${LUA_PRG} ${EVENTS_GENERATOR} - ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP} - DEPENDS ${EVENTS_GENERATOR} ${EVENTS_LIST_FILE} + ${CMAKE_CURRENT_LIST_DIR} ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP} + DEPENDS ${EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/auevents.lua ) add_custom_command(OUTPUT ${GENERATED_OPTIONS} COMMAND ${LUA_PRG} ${OPTIONS_GENERATOR} - ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_OPTIONS} - DEPENDS ${OPTIONS_GENERATOR} ${OPTIONS_LIST_FILE} + ${CMAKE_CURRENT_LIST_DIR} ${GENERATED_OPTIONS} + DEPENDS ${OPTIONS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/options.lua ) +# NVIM_GENERATED_FOR_SOURCES and NVIM_GENERATED_FOR_HEADERS must be mutually exclusive. +foreach(hfile ${NVIM_GENERATED_FOR_HEADERS}) + list(FIND NVIM_GENERATED_FOR_SOURCES ${hfile} hfile_idx) + if(NOT ${hfile_idx} EQUAL -1) + message(FATAL_ERROR "File included in both NVIM_GENERATED_FOR_HEADERS and NVIM_GENERATED_FOR_SOURCES") + endif() +endforeach() + # Our dependencies come first. if (LibIntl_FOUND) @@ -262,6 +358,10 @@ if(Iconv_LIBRARIES) list(APPEND NVIM_LINK_LIBRARIES ${Iconv_LIBRARIES}) endif() +if(WIN32) + list(APPEND NVIM_LINK_LIBRARIES ${WINPTY_LIBRARIES}) +endif() + # Put these last on the link line, since multiple things may depend on them. list(APPEND NVIM_LINK_LIBRARIES ${LIBUV_LIBRARIES} @@ -279,31 +379,120 @@ if(UNIX) ) endif() -set(NVIM_EXEC_LINK_LIBRARIES ${NVIM_LINK_LIBRARIES}) +set(NVIM_EXEC_LINK_LIBRARIES ${NVIM_LINK_LIBRARIES} ${LUA_PREFERRED_LIBRARIES}) + +if(CMAKE_VERSION VERSION_LESS "2.8.8") + # Use include_directories() because INCLUDE_DIRECTORIES target property + # is not supported + include_directories(${LUA_PREFERRED_INCLUDE_DIRS}) +endif() # Don't use jemalloc in the unit test library. if(JEMALLOC_FOUND) list(APPEND NVIM_EXEC_LINK_LIBRARIES ${JEMALLOC_LIBRARIES}) endif() -add_executable(nvim ${NEOVIM_GENERATED_SOURCES} ${NEOVIM_SOURCES} - ${NEOVIM_HEADERS}) +add_executable(nvim ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS} + ${NVIM_GENERATED_SOURCES} ${NVIM_SOURCES} ${NVIM_HEADERS}) target_link_libraries(nvim ${NVIM_EXEC_LINK_LIBRARIES}) install_helper(TARGETS nvim) +set_property(TARGET nvim APPEND PROPERTY + INCLUDE_DIRECTORIES ${LUA_PREFERRED_INCLUDE_DIRS}) + if(WIN32) - # Copy DLLs to bin/ and install them along with nvim - add_custom_target(nvim_dll_deps ALL DEPENDS nvim + # Copy DLLs and third-party tools to bin/ and install them along with nvim + add_custom_target(nvim_runtime_deps ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + install(DIRECTORY ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_custom_target(nvim_dll_deps DEPENDS nvim COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps COMMAND ${CMAKE_COMMAND} "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}" -DBINARY="${PROJECT_BINARY_DIR}/bin/nvim${CMAKE_EXECUTABLE_SUFFIX}" -DDST=${PROJECT_BINARY_DIR}/windows_runtime_deps - -P ${PROJECT_SOURCE_DIR}/cmake/WindowsDllCopy.cmake - COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps/ - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - install(DIRECTORY ${PROJECT_BINARY_DIR}/windows_runtime_deps/ - DESTINATION ${CMAKE_INSTALL_BINDIR}) + -P ${PROJECT_SOURCE_DIR}/cmake/WindowsDllCopy.cmake) + add_dependencies(nvim_runtime_deps nvim_dll_deps) + + add_custom_target(external_blobs + COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps/platforms + + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/ca-bundle.crt" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/cat.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/curl.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/diff.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/tee.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/tidy.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/win32yank.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/winpty-agent.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/D3Dcompiler_47.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libEGL.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libgcc_s_dw2-1.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libGLESV2.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libstdc++-6.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libwinpthread-1.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/nvim-qt.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Core.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Gui.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Network.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Svg.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Widgets.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/winpty.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/platforms/qwindows.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/platforms/ + ) + add_dependencies(nvim_runtime_deps external_blobs) +endif() + +add_library( + libnvim + STATIC + EXCLUDE_FROM_ALL + ${NVIM_SOURCES} ${NVIM_GENERATED_SOURCES} + ${NVIM_HEADERS} ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS} +) +set_property(TARGET libnvim APPEND PROPERTY + INCLUDE_DIRECTORIES ${LUA_PREFERRED_INCLUDE_DIRS}) +set_target_properties( + libnvim + PROPERTIES + POSITION_INDEPENDENT_CODE ON + OUTPUT_NAME nvim +) +set_property( + TARGET libnvim + APPEND_STRING PROPERTY COMPILE_FLAGS " -DMAKE_LIB " +) + +if(LUAJIT_FOUND) + set(NVIM_TEST_LINK_LIBRARIES ${NVIM_LINK_LIBRARIES} ${LUAJIT_LIBRARIES}) + add_library( + nvim-test + MODULE + EXCLUDE_FROM_ALL + ${NVIM_SOURCES} ${NVIM_GENERATED_SOURCES} + ${NVIM_HEADERS} ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS} + ${UNIT_TEST_FIXTURES} + ) + target_link_libraries(nvim-test ${NVIM_TEST_LINK_LIBRARIES}) + target_link_libraries(libnvim ${NVIM_TEST_LINK_LIBRARIES}) + set_property( + TARGET nvim-test + APPEND PROPERTY INCLUDE_DIRECTORIES ${LUAJIT_INCLUDE_DIRS} + ) + set_target_properties( + nvim-test + PROPERTIES + POSITION_INDEPENDENT_CODE ON + ) + set_property( + TARGET nvim-test + APPEND_STRING PROPERTY COMPILE_FLAGS " -DUNIT_TESTING " + ) endif() if(CLANG_ASAN_UBSAN) @@ -330,17 +519,111 @@ elseif(CLANG_TSAN) set_property(TARGET nvim APPEND_STRING PROPERTY LINK_FLAGS "-fsanitize=thread ") endif() -add_library(libnvim STATIC EXCLUDE_FROM_ALL ${NEOVIM_GENERATED_SOURCES} - ${NEOVIM_SOURCES} ${NEOVIM_HEADERS}) -target_link_libraries(libnvim ${NVIM_LINK_LIBRARIES}) -set_target_properties(libnvim PROPERTIES - POSITION_INDEPENDENT_CODE ON - OUTPUT_NAME nvim) -set_property(TARGET libnvim APPEND_STRING PROPERTY COMPILE_FLAGS " -DMAKE_LIB ") - -add_library(nvim-test MODULE EXCLUDE_FROM_ALL ${NEOVIM_GENERATED_SOURCES} - ${NEOVIM_SOURCES} ${UNIT_TEST_FIXTURES} ${NEOVIM_HEADERS}) -target_link_libraries(nvim-test ${NVIM_LINK_LIBRARIES}) -set_property(TARGET nvim-test APPEND_STRING PROPERTY COMPILE_FLAGS -DUNIT_TESTING) +function(get_test_target prefix sfile relative_path_var target_var) + get_filename_component(full_d "${sfile}" PATH) + file(RELATIVE_PATH d "${PROJECT_SOURCE_DIR}/src/nvim" "${full_d}") + if(d MATCHES "^[.][.]") + file(RELATIVE_PATH d "${GENERATED_DIR}" "${full_d}") + endif() + get_filename_component(r "${sfile}" NAME) + if(NOT d MATCHES "^[.]?$") + set(r "${d}/${r}") + endif() + string(REGEX REPLACE "[/.]" "-" suffix "${r}") + set(${relative_path_var} ${r} PARENT_SCOPE) + if(prefix STREQUAL "") + set(${target_var} "${suffix}" PARENT_SCOPE) + else() + set(${target_var} "${prefix}-${suffix}" PARENT_SCOPE) + endif() +endfunction() + +set(NO_SINGLE_CHECK_HEADERS + os/win_defs.h + os/pty_process_win.h + regexp_defs.h + syntax_defs.h + terminal.h + undo.h + undo_defs.h +) +foreach(hfile ${NVIM_HEADERS}) + get_test_target(test-includes "${hfile}" relative_path texe) + + if(NOT ${hfile} MATCHES "[.](c|in)[.]h$") + set(tsource "${GENERATED_DIR}/${relative_path}.test-include.c") + write_file("${tsource}" "#include \"${hfile}\"\nint main(int argc, char **argv) { return 0; }") + add_executable( + ${texe} + EXCLUDE_FROM_ALL + ${tsource} ${NVIM_HEADERS} ${NVIM_GENERATED_FOR_HEADERS}) + set_property( + TARGET ${texe} + APPEND PROPERTY INCLUDE_DIRECTORIES ${LUA_PREFERRED_INCLUDE_DIRS} + ) + + list(FIND NO_SINGLE_CHECK_HEADERS "${relative_path}" hfile_exclude_idx) + if(${hfile_exclude_idx} EQUAL -1) + list(APPEND HEADER_CHECK_TARGETS ${texe}) + endif() + endif() +endforeach() +add_custom_target(check-single-includes DEPENDS ${HEADER_CHECK_TARGETS}) + +function(add_download output url allow_failure) + add_custom_command( + OUTPUT "${output}" + COMMAND + ${CMAKE_COMMAND} + -DURL=${url} -DFILE=${output} + -DALLOW_FAILURE=${allow_failure} + -P ${DOWNLOAD_SCRIPT} + DEPENDS ${DOWNLOAD_SCRIPT} + ) +endfunction() + +add_download(${LINT_SUPPRESSES_ARCHIVE} ${LINT_SUPPRESSES_URL} off) + +add_custom_command( + OUTPUT ${LINT_SUPPRESSES_TOUCH_FILE} + WORKING_DIRECTORY ${LINT_SUPPRESSES_ROOT}/src + COMMAND ${CMAKE_COMMAND} -E tar xfz ${LINT_SUPPRESSES_ARCHIVE} + COMMAND + ${CMAKE_COMMAND} + -DTARGET=${LINT_SUPPRESSES_ROOT} + -P ${LINT_SUPPRESSES_INSTALL_SCRIPT} + COMMAND ${CMAKE_COMMAND} -E touch ${LINT_SUPPRESSES_TOUCH_FILE} + DEPENDS + ${LINT_SUPPRESSES_ARCHIVE} ${LINT_SUPPRESSES_INSTALL_SCRIPT} +) + +add_download(${LINT_SUPPRESS_FILE} ${LINT_SUPPRESS_URL} off) + +set(LINT_NVIM_REL_SOURCES) +foreach(sfile ${LINT_NVIM_SOURCES}) + get_test_target("" "${sfile}" r suffix) + set(suppress_file ${LINT_SUPPRESSES_ROOT}/${suffix}.json) + set(suppress_url "${LINT_SUPPRESS_URL_BASE}/${suffix}.json") + set(rsfile src/nvim/${r}) + set(touch_file "${TOUCHES_DIR}/ran-clint-${suffix}") + add_custom_command( + OUTPUT ${touch_file} + COMMAND ${LINT_PRG} --suppress-errors=${suppress_file} ${rsfile} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + COMMAND ${CMAKE_COMMAND} -E touch ${touch_file} + DEPENDS ${LINT_PRG} ${sfile} ${LINT_SUPPRESSES_TOUCH_FILE} + ) + list(APPEND LINT_TARGETS ${touch_file}) + list(APPEND LINT_NVIM_REL_SOURCES ${rsfile}) +endforeach() +add_custom_target(clint DEPENDS ${LINT_TARGETS}) + +add_custom_target( + clint-full + COMMAND + ${LINT_PRG} --suppress-errors=${LINT_SUPPRESS_FILE} ${LINT_NVIM_REL_SOURCES} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + DEPENDS ${LINT_PRG} ${LINT_NVIM_SOURCES} ${LINT_SUPPRESS_FILE} +) add_subdirectory(po) diff --git a/src/nvim/README.md b/src/nvim/README.md index f16c6de12f..0caf71e2c5 100644 --- a/src/nvim/README.md +++ b/src/nvim/README.md @@ -1,23 +1,43 @@ -## Source code overview +Nvim core source +================ -Since Neovim has inherited most code from Vim, some information in [its -README](https://raw.githubusercontent.com/vim/vim/master/src/README.txt) still -applies. +Module-specific details are documented at the top of each module (`terminal.c`, +`screen.c`, ...). -This document aims to give a high level overview of how Neovim works internally, -focusing on parts that are different from Vim. Currently this is still a work in -progress, especially because I have avoided adding too many details about parts -that are constantly changing. As the code becomes more organized and stable, -this document will be updated to reflect the changes. +See `:help development` for more guidelines. -If you are looking for module-specific details, it is best to read the source -code. Some files are extensively commented at the top (e.g. terminal.c, -screen.c). +Logs +---- -### Top-level program loops +Low-level log messages sink to `$NVIM_LOG_FILE`. -First let's understand what a Vim-like program does by analyzing the workflow of -a typical editing session: +You can use `LOG_CALLSTACK();` anywhere in the source to log the current +stacktrace. To log in an alternate file, e.g. stderr, use +`LOG_CALLSTACK_TO_FILE(FILE*)`. (Currently Linux-only.) + +UI events are logged at level 0 (`DEBUG_LOG_LEVEL`). + + rm -rf build/ + make CMAKE_EXTRA_FLAGS="-DMIN_LOG_LEVEL=0" + +Filename conventions +-------------------- + +The source files use extensions to hint about their purpose. + +- `*.c`, `*.generated.c` - full C files, with all includes, etc. +- `*.c.h` - parametrized C files, contain all necessary includes, but require + defining macros before actually using. Example: `typval_encode.c.h` +- `*.h` - full headers, with all includes. Does *not* apply to `*.generated.h`. +- `*.h.generated.h` - exported functions’ declarations. +- `*.c.generated.h` - static functions’ declarations. + +Nvim lifecycle +-------------- + +Following describes how Nvim processes input. + +Consider a typical Vim-like editing session: 01. Vim dispays the welcome screen 02. User types: `:` @@ -41,16 +61,14 @@ a typical editing session: 21. User types: `word<ESC>` 22. Vim inserts "word" at the beginning and returns to normal mode -Note that we have split user actions into sequences of inputs that change the -state of the editor. While there's no documentation about a "g command -mode" (step 16), internally it is implemented similarly to "operator-pending -mode". +Note that we split user actions into sequences of inputs that change the state +of the editor. While there's no documentation about a "g command mode" (step +16), internally it is implemented similarly to "operator-pending mode". -From this we can see that Vim has the behavior of a input-driven state -machine (more specifically, a pushdown automaton since it requires a stack for +From this we can see that Vim has the behavior of an input-driven state machine +(more specifically, a pushdown automaton since it requires a stack for transitioning back from states). Assuming each state has a callback responsible -for handling keys, this pseudocode (a python-like language) shows a good -representation of the main program loop: +for handling keys, this pseudocode represents the main program loop: ```py def state_enter(state_callback, data): @@ -126,12 +144,11 @@ def insert_state(data, key): return true ``` -While the actual code is much more complicated, the above gives an idea of how -Neovim is organized internally. Some states like the `g_command_state` or -`get_operator_count_state` do not have a dedicated `state_enter` callback, but -are implicitly embedded into other states (this will change later as we continue -the refactoring effort). To start reading the actual code, here's the -recommended order: +The above gives an idea of how Nvim is organized internally. Some states like +the `g_command_state` or `get_operator_count_state` do not have a dedicated +`state_enter` callback, but are implicitly embedded into other states (this +will change later as we continue the refactoring effort). To start reading the +actual code, here's the recommended order: 1. `state_enter()` function (state.c). This is the actual program loop, note that a `VimState` structure is used, which contains function pointers @@ -152,16 +169,17 @@ modes managed by the `state_enter` loop: - insert mode: `insert_{enter,check,execute}()`(`edit.c`) - terminal mode: `terminal_{enter,execute}()`(`terminal.c`) -### Async event support +Async event support +------------------- -One of the features Neovim added is the support for handling arbitrary +One of the features Nvim added is the support for handling arbitrary asynchronous events, which can include: -- msgpack-rpc requests +- RPC requests - job control callbacks -- timers (not implemented yet but the support code is already there) +- timers -Neovim implements this functionality by entering another event loop while +Nvim implements this functionality by entering another event loop while waiting for characters, so instead of: ```py @@ -171,7 +189,7 @@ def state_enter(state_callback, data): while state_callback(data, key) # invoke the callback for the current state ``` -Neovim program loop is more like: +Nvim program loop is more like: ```py def state_enter(state_callback, data): @@ -182,9 +200,9 @@ def state_enter(state_callback, data): where `event` is something the operating system delivers to us, including (but not limited to) user input. The `read_next_event()` part is internally -implemented by libuv, the platform layer used by Neovim. +implemented by libuv, the platform layer used by Nvim. -Since Neovim inherited its code from Vim, the states are not prepared to receive +Since Nvim inherited its code from Vim, the states are not prepared to receive "arbitrary events", so we use a special key to represent those (When a state receives an "arbitrary event", it normally doesn't do anything other update the screen). diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index eaaae943d2..82de8fd4a2 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1,3 +1,6 @@ +// 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 + // Much of this code was adapted from 'if_py_both.h' from the original // vim source #include <stdbool.h> @@ -32,6 +35,7 @@ /// @param[out] err Error details, if any /// @return Line count Integer nvim_buf_line_count(Buffer buffer, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -61,7 +65,7 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err) index = convert_index(index); Array slice = nvim_buf_get_lines(0, buffer, index, index+1, true, err); - if (!err->set && slice.size) { + if (!ERROR_SET(err) && slice.size) { rv = slice.items[0].data.string; } @@ -132,7 +136,6 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer, return nvim_buf_get_lines(0, buffer, start , end, false, err); } - /// Retrieves a line range from the buffer /// /// Indexing is zero-based, end-exclusive. Negative indices are interpreted @@ -154,6 +157,7 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, Integer end, Boolean strict_indexing, Error *err) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; buf_T *buf = find_buffer_by_handle(buffer, err); @@ -167,7 +171,7 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, end = normalize_index(buf, end, &oob); if (strict_indexing && oob) { - api_set_error(err, Validation, _("Index out of bounds")); + api_set_error(err, kErrorTypeValidation, "Index out of bounds"); return rv; } @@ -183,7 +187,7 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, int64_t lnum = start + (int64_t)i; if (lnum > LONG_MAX) { - api_set_error(err, Validation, _("Line index is too high")); + api_set_error(err, kErrorTypeValidation, "Line index is too high"); goto end; } @@ -191,7 +195,7 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, Object str = STRING_OBJ(cstr_to_string(bufstr)); // Vim represents NULs as NLs, but this may confuse clients. - if (channel_id != INTERNAL_CALL) { + if (channel_id != VIML_INTERNAL_CALL) { strchrsub(str.data.string.data, '\n', '\0'); } @@ -199,7 +203,7 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, } end: - if (err->set) { + if (ERROR_SET(err)) { for (size_t i = 0; i < rv.size; i++) { xfree(rv.items[i].data.string.data); } @@ -266,6 +270,7 @@ void nvim_buf_set_lines(uint64_t channel_id, Boolean strict_indexing, ArrayOf(String) replacement, // NOLINT Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -278,54 +283,58 @@ void nvim_buf_set_lines(uint64_t channel_id, end = normalize_index(buf, end, &oob); if (strict_indexing && oob) { - api_set_error(err, Validation, _("Index out of bounds")); + api_set_error(err, kErrorTypeValidation, "Index out of bounds"); return; } if (start > end) { api_set_error(err, - Validation, - _("Argument \"start\" is higher than \"end\"")); + kErrorTypeValidation, + "Argument \"start\" is higher than \"end\""); return; } - buf_T *save_curbuf = NULL; + for (size_t i = 0; i < replacement.size; i++) { + if (replacement.items[i].type != kObjectTypeString) { + api_set_error(err, + kErrorTypeValidation, + "All items in the replacement array must be strings"); + return; + } + // Disallow newlines in the middle of the line. + if (channel_id != VIML_INTERNAL_CALL) { + const String l = replacement.items[i].data.string; + if (memchr(l.data, NL, l.size)) { + api_set_error(err, kErrorTypeValidation, + "String cannot contain newlines"); + return; + } + } + } + win_T *save_curwin = NULL; tabpage_T *save_curtab = NULL; size_t new_len = replacement.size; size_t old_len = (size_t)(end - start); - ssize_t extra = 0; // lines added to text, can be negative + ptrdiff_t extra = 0; // lines added to text, can be negative char **lines = (new_len != 0) ? xcalloc(new_len, sizeof(char *)) : NULL; for (size_t i = 0; i < new_len; i++) { - if (replacement.items[i].type != kObjectTypeString) { - api_set_error(err, - Validation, - _("All items in the replacement array must be strings")); - goto end; - } - - String l = replacement.items[i].data.string; + const String l = replacement.items[i].data.string; - // Fill lines[i] with l's contents. Disallow newlines in the middle of a - // line and convert NULs to newlines to avoid truncation. - lines[i] = xmallocz(l.size); - for (size_t j = 0; j < l.size; j++) { - if (l.data[j] == '\n' && channel_id != INTERNAL_CALL) { - api_set_error(err, Exception, _("string cannot contain newlines")); - new_len = i + 1; - goto end; - } - lines[i][j] = (char) (l.data[j] == '\0' ? '\n' : l.data[j]); - } + // Fill lines[i] with l's contents. Convert NULs to newlines as required by + // NL-used-for-NUL. + lines[i] = xmemdupz(l.data, l.size); + memchrsub(lines[i], NUL, NL, l.size); } try_start(); + bufref_T save_curbuf = { NULL, 0, 0 }; switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf); if (u_save((linenr_T)(start - 1), (linenr_T)end) == FAIL) { - api_set_error(err, Exception, _("Failed to save undo information")); + api_set_error(err, kErrorTypeException, "Failed to save undo information"); goto end; } @@ -335,13 +344,13 @@ void nvim_buf_set_lines(uint64_t channel_id, size_t to_delete = (new_len < old_len) ? (size_t)(old_len - new_len) : 0; for (size_t i = 0; i < to_delete; i++) { if (ml_delete((linenr_T)start, false) == FAIL) { - api_set_error(err, Exception, _("Failed to delete line")); + api_set_error(err, kErrorTypeException, "Failed to delete line"); goto end; } } - if ((ssize_t)to_delete > 0) { - extra -= (ssize_t)to_delete; + if (to_delete > 0) { + extra -= (ptrdiff_t)to_delete; } // For as long as possible, replace the existing old_len with the @@ -352,12 +361,12 @@ void nvim_buf_set_lines(uint64_t channel_id, int64_t lnum = start + (int64_t)i; if (lnum > LONG_MAX) { - api_set_error(err, Validation, _("Index value is too high")); + api_set_error(err, kErrorTypeValidation, "Index value is too high"); goto end; } if (ml_replace((linenr_T)lnum, (char_u *)lines[i], false) == FAIL) { - api_set_error(err, Exception, _("Failed to replace line")); + api_set_error(err, kErrorTypeException, "Failed to replace line"); goto end; } // Mark lines that haven't been passed to the buffer as they need @@ -370,12 +379,12 @@ void nvim_buf_set_lines(uint64_t channel_id, int64_t lnum = start + (int64_t)i - 1; if (lnum > LONG_MAX) { - api_set_error(err, Validation, _("Index value is too high")); + api_set_error(err, kErrorTypeValidation, "Index value is too high"); goto end; } if (ml_append((linenr_T)lnum, (char_u *)lines[i], 0, false) == FAIL) { - api_set_error(err, Exception, _("Failed to insert line")); + api_set_error(err, kErrorTypeException, "Failed to insert line"); goto end; } @@ -389,14 +398,14 @@ void nvim_buf_set_lines(uint64_t channel_id, // changed range, and move any in the remainder of the buffer. // Only adjust marks if we managed to switch to a window that holds // the buffer, otherwise line numbers will be invalid. - if (save_curbuf == NULL) { - mark_adjust((linenr_T)start, (linenr_T)(end - 1), MAXLNUM, extra); + if (save_curbuf.br_buf == NULL) { + mark_adjust((linenr_T)start, (linenr_T)(end - 1), MAXLNUM, extra, false); } - changed_lines((linenr_T)start, 0, (linenr_T)end, extra); + changed_lines((linenr_T)start, 0, (linenr_T)end, (long)extra); - if (buf == curbuf) { - fix_cursor((linenr_T)start, (linenr_T)end, extra); + if (save_curbuf.br_buf == NULL) { + fix_cursor((linenr_T)start, (linenr_T)end, (linenr_T)extra); } end: @@ -405,7 +414,7 @@ end: } xfree(lines); - restore_win_for_buf(save_curwin, save_curtab, save_curbuf); + restore_win_for_buf(save_curwin, save_curtab, &save_curbuf); try_end(err); } @@ -416,6 +425,7 @@ end: /// @param[out] err Error details, if any /// @return Variable value Object nvim_buf_get_var(Buffer buffer, String name, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -426,6 +436,43 @@ Object nvim_buf_get_var(Buffer buffer, String name, Error *err) return dict_get_value(buf->b_vars, name, err); } +/// Gets a changed tick of a buffer +/// +/// @param[in] buffer Buffer handle. +/// +/// @return `b:changedtick` value. +Integer nvim_buf_get_changedtick(Buffer buffer, Error *err) + FUNC_API_SINCE(2) +{ + const buf_T *const buf = find_buffer_by_handle(buffer, err); + + if (!buf) { + return -1; + } + + return buf->b_changedtick; +} + +/// Get a list of dictionaries describing buffer-local mappings +/// Note that the buffer key in the dictionary will represent the buffer +/// handle where the mapping is present +/// +/// @param mode The abbreviation for the mode +/// @param buffer_id Buffer handle +/// @param[out] err Error details, if any +/// @returns An array of maparg() like dictionaries describing mappings +ArrayOf(Dictionary) nvim_buf_get_keymap(Buffer buffer, String mode, Error *err) + FUNC_API_SINCE(3) +{ + buf_T *buf = find_buffer_by_handle(buffer, err); + + if (!buf) { + return (Array)ARRAY_DICT_INIT; + } + + return keymap_array(mode, buf); +} + /// Sets a buffer-scoped (b:) variable /// /// @param buffer Buffer handle @@ -433,6 +480,7 @@ Object nvim_buf_get_var(Buffer buffer, String name, Error *err) /// @param value Variable value /// @param[out] err Error details, if any void nvim_buf_set_var(Buffer buffer, String name, Object value, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -440,7 +488,7 @@ void nvim_buf_set_var(Buffer buffer, String name, Object value, Error *err) return; } - dict_set_value(buf->b_vars, name, value, false, false, err); + dict_set_var(buf->b_vars, name, value, false, false, err); } /// Removes a buffer-scoped (b:) variable @@ -449,6 +497,7 @@ void nvim_buf_set_var(Buffer buffer, String name, Object value, Error *err) /// @param name Variable name /// @param[out] err Error details, if any void nvim_buf_del_var(Buffer buffer, String name, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -456,7 +505,7 @@ void nvim_buf_del_var(Buffer buffer, String name, Error *err) return; } - dict_set_value(buf->b_vars, name, NIL, true, false, err); + dict_set_var(buf->b_vars, name, NIL, true, false, err); } /// Sets a buffer-scoped (b:) variable @@ -479,7 +528,7 @@ Object buffer_set_var(Buffer buffer, String name, Object value, Error *err) return (Object) OBJECT_INIT; } - return dict_set_value(buf->b_vars, name, value, false, true, err); + return dict_set_var(buf->b_vars, name, value, false, true, err); } /// Removes a buffer-scoped (b:) variable @@ -498,7 +547,7 @@ Object buffer_del_var(Buffer buffer, String name, Error *err) return (Object) OBJECT_INIT; } - return dict_set_value(buf->b_vars, name, NIL, true, true, err); + return dict_set_var(buf->b_vars, name, NIL, true, true, err); } @@ -509,6 +558,7 @@ Object buffer_del_var(Buffer buffer, String name, Error *err) /// @param[out] err Error details, if any /// @return Option value Object nvim_buf_get_option(Buffer buffer, String name, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -527,6 +577,7 @@ Object nvim_buf_get_option(Buffer buffer, String name, Error *err) /// @param value Option value /// @param[out] err Error details, if any void nvim_buf_set_option(Buffer buffer, String name, Object value, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -539,10 +590,15 @@ void nvim_buf_set_option(Buffer buffer, String name, Object value, Error *err) /// Gets the buffer number /// +/// @deprecated The buffer number now is equal to the object id, +/// so there is no need to use this function. +/// /// @param buffer Buffer handle /// @param[out] err Error details, if any /// @return Buffer number Integer nvim_buf_get_number(Buffer buffer, Error *err) + FUNC_API_SINCE(1) + FUNC_API_DEPRECATED_SINCE(2) { Integer rv = 0; buf_T *buf = find_buffer_by_handle(buffer, err); @@ -560,6 +616,7 @@ Integer nvim_buf_get_number(Buffer buffer, Error *err) /// @param[out] err Error details, if any /// @return Buffer name String nvim_buf_get_name(Buffer buffer, Error *err) + FUNC_API_SINCE(1) { String rv = STRING_INIT; buf_T *buf = find_buffer_by_handle(buffer, err); @@ -577,6 +634,7 @@ String nvim_buf_get_name(Buffer buffer, Error *err) /// @param name Buffer name /// @param[out] err Error details, if any void nvim_buf_set_name(Buffer buffer, String name, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -597,7 +655,7 @@ void nvim_buf_set_name(Buffer buffer, String name, Error *err) } if (ren_ret == FAIL) { - api_set_error(err, Exception, _("Failed to rename buffer")); + api_set_error(err, kErrorTypeException, "Failed to rename buffer"); } } @@ -606,9 +664,12 @@ void nvim_buf_set_name(Buffer buffer, String name, Error *err) /// @param buffer Buffer handle /// @return true if the buffer is valid, false otherwise Boolean nvim_buf_is_valid(Buffer buffer) + FUNC_API_SINCE(1) { Error stub = ERROR_INIT; - return find_buffer_by_handle(buffer, &stub) != NULL; + Boolean ret = find_buffer_by_handle(buffer, &stub) != NULL; + api_clear_error(&stub); + return ret; } /// Inserts a sequence of lines to a buffer at a certain index @@ -637,6 +698,7 @@ void buffer_insert(Buffer buffer, /// @param[out] err Error details, if any /// @return (row, col) tuple ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; buf_T *buf = find_buffer_by_handle(buffer, err); @@ -646,25 +708,26 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err) } if (name.size != 1) { - api_set_error(err, Validation, _("Mark name must be a single character")); + api_set_error(err, kErrorTypeValidation, + "Mark name must be a single character"); return rv; } pos_T *posp; - buf_T *savebuf; char mark = *name.data; try_start(); - switch_buffer(&savebuf, buf); + bufref_T save_buf; + switch_buffer(&save_buf, buf); posp = getmark(mark, false); - restore_buffer(savebuf); + restore_buffer(&save_buf); if (try_end(err)) { return rv; } if (posp == NULL) { - api_set_error(err, Validation, _("Invalid mark name")); + api_set_error(err, kErrorTypeValidation, "Invalid mark name"); return rv; } @@ -711,6 +774,7 @@ Integer nvim_buf_add_highlight(Buffer buffer, Integer col_start, Integer col_end, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); if (!buf) { @@ -718,11 +782,11 @@ Integer nvim_buf_add_highlight(Buffer buffer, } if (line < 0 || line >= MAXLNUM) { - api_set_error(err, Validation, _("Line number outside range")); + api_set_error(err, kErrorTypeValidation, "Line number outside range"); return 0; } if (col_start < 0 || col_start > MAXCOL) { - api_set_error(err, Validation, _("Column value outside range")); + api_set_error(err, kErrorTypeValidation, "Column value outside range"); return 0; } if (col_end < 0 || col_end > MAXCOL) { @@ -751,6 +815,7 @@ void nvim_buf_clear_highlight(Buffer buffer, Integer line_start, Integer line_end, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); if (!buf) { @@ -758,7 +823,7 @@ void nvim_buf_clear_highlight(Buffer buffer, } if (line_start < 0 || line_start >= MAXLNUM) { - api_set_error(err, Validation, _("Line number outside range")); + api_set_error(err, kErrorTypeValidation, "Line number outside range"); return; } if (line_end < 0 || line_end > MAXLNUM) { diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h index 223aab09dc..2144c80d6a 100644 --- a/src/nvim/api/private/defs.h +++ b/src/nvim/api/private/defs.h @@ -5,12 +5,16 @@ #include <stdbool.h> #include <string.h> +#include "nvim/func_attr.h" + #define ARRAY_DICT_INIT {.size = 0, .capacity = 0, .items = NULL} #define STRING_INIT {.data = NULL, .size = 0} #define OBJECT_INIT { .type = kObjectTypeNil } -#define ERROR_INIT { .set = false } +#define ERROR_INIT { .type = kErrorTypeNone, .msg = NULL } #define REMOTE_TYPE(type) typedef handle_T type +#define ERROR_SET(e) ((e)->type != kErrorTypeNone) + #ifdef INCLUDE_GENERATED_DECLARATIONS # define ArrayOf(...) Array # define DictionaryOf(...) Dictionary @@ -20,6 +24,7 @@ typedef int handle_T; // Basic types typedef enum { + kErrorTypeNone = -1, kErrorTypeException, kErrorTypeValidation } ErrorType; @@ -33,13 +38,31 @@ typedef enum { /// Used as the message ID of notifications. #define NO_RESPONSE UINT64_MAX -/// Used as channel_id when the call is local. -#define INTERNAL_CALL UINT64_MAX +/// Mask for all internal calls +#define INTERNAL_CALL_MASK (((uint64_t)1) << (sizeof(uint64_t) * 8 - 1)) + +/// Internal call from VimL code +#define VIML_INTERNAL_CALL INTERNAL_CALL_MASK + +/// Internal call from lua code +#define LUA_INTERNAL_CALL (VIML_INTERNAL_CALL + 1) + +static inline bool is_internal_call(uint64_t channel_id) + REAL_FATTR_ALWAYS_INLINE REAL_FATTR_CONST; + +/// Check whether call is internal +/// +/// @param[in] channel_id Channel id. +/// +/// @return true if channel_id refers to internal channel. +static inline bool is_internal_call(const uint64_t channel_id) +{ + return !!(channel_id & INTERNAL_CALL_MASK); +} typedef struct { ErrorType type; - char msg[1024]; - bool set; + char *msg; } Error; typedef bool Boolean; @@ -76,16 +99,17 @@ typedef struct { } Dictionary; typedef enum { - kObjectTypeBuffer, - kObjectTypeWindow, - kObjectTypeTabpage, - kObjectTypeNil, + kObjectTypeNil = 0, kObjectTypeBoolean, kObjectTypeInteger, kObjectTypeFloat, kObjectTypeString, kObjectTypeArray, kObjectTypeDictionary, + // EXT types, cannot be split or reordered, see #EXT_OBJECT_TYPE_SHIFT + kObjectTypeBuffer, + kObjectTypeWindow, + kObjectTypeTabpage, } ObjectType; struct object { diff --git a/src/nvim/api/private/dispatch.c b/src/nvim/api/private/dispatch.c index 9b3bcc380a..f8eebcdb10 100644 --- a/src/nvim/api/private/dispatch.c +++ b/src/nvim/api/private/dispatch.c @@ -1,3 +1,6 @@ +// 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 <inttypes.h> #include <stdbool.h> #include <stdint.h> diff --git a/src/nvim/api/private/handle.c b/src/nvim/api/private/handle.c index acb0fb332a..eb96192af2 100644 --- a/src/nvim/api/private/handle.c +++ b/src/nvim/api/private/handle.c @@ -1,3 +1,6 @@ +// 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> diff --git a/src/nvim/api/private/handle.h b/src/nvim/api/private/handle.h index 30bbfbee1b..26e9dc3314 100644 --- a/src/nvim/api/private/handle.h +++ b/src/nvim/api/private/handle.h @@ -10,8 +10,11 @@ void handle_register_##name(type *name); \ void handle_unregister_##name(type *name); +// handle_get_buffer handle_register_buffer, handle_unregister_buffer HANDLE_DECLS(buf_T, buffer) +// handle_get_window handle_register_window, handle_unregister_window HANDLE_DECLS(win_T, window) +// handle_get_tabpage handle_register_tabpage, handle_unregister_tabpage HANDLE_DECLS(tabpage_T, tabpage) void handle_init(void); diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 7daa4d7207..e736e29e2d 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -1,3 +1,6 @@ +// 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 <inttypes.h> #include <stdbool.h> @@ -14,12 +17,14 @@ #include "nvim/window.h" #include "nvim/memory.h" #include "nvim/eval.h" +#include "nvim/eval/typval.h" #include "nvim/map_defs.h" #include "nvim/map.h" #include "nvim/option.h" #include "nvim/option_defs.h" #include "nvim/version.h" #include "nvim/lib/kvec.h" +#include "nvim/getchar.h" /// Helper structure for vim_to_object typedef struct { @@ -29,9 +34,75 @@ typedef struct { #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/private/helpers.c.generated.h" # include "api/private/funcs_metadata.generated.h" +# include "api/private/ui_events_metadata.generated.h" #endif +/// Start block that may cause VimL exceptions while evaluating another code +/// +/// Used when caller is supposed to be operating when other VimL code is being +/// processed and that “other VimL code†must not be affected. +/// +/// @param[out] tstate Location where try state should be saved. +void try_enter(TryState *const tstate) +{ + *tstate = (TryState) { + .current_exception = current_exception, + .msg_list = (const struct msglist *const *)msg_list, + .private_msg_list = NULL, + .trylevel = trylevel, + .got_int = got_int, + .did_throw = did_throw, + .need_rethrow = need_rethrow, + .did_emsg = did_emsg, + }; + msg_list = &tstate->private_msg_list; + current_exception = NULL; + trylevel = 1; + got_int = false; + did_throw = false; + need_rethrow = false; + did_emsg = false; +} + +/// End try block, set the error message if any and restore previous state +/// +/// @warning Return is consistent with most functions (false on error), not with +/// try_end (true on error). +/// +/// @param[in] tstate Previous state to restore. +/// @param[out] err Location where error should be saved. +/// +/// @return false if error occurred, true otherwise. +bool try_leave(const TryState *const tstate, Error *const err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + const bool ret = !try_end(err); + assert(trylevel == 0); + assert(!need_rethrow); + assert(!got_int); + assert(!did_throw); + assert(!did_emsg); + assert(msg_list == &tstate->private_msg_list); + assert(*msg_list == NULL); + assert(current_exception == NULL); + msg_list = (struct msglist **)tstate->msg_list; + current_exception = tstate->current_exception; + trylevel = tstate->trylevel; + got_int = tstate->got_int; + did_throw = tstate->did_throw; + need_rethrow = tstate->need_rethrow; + did_emsg = tstate->did_emsg; + return ret; +} + /// Start block that may cause vimscript exceptions +/// +/// Each try_start() call should be mirrored by try_end() call. +/// +/// To be used as a replacement of `:try … catch … endtry` in C code, in cases +/// when error flag could not already be set. If there may be pending error +/// state at the time try_start() is executed which needs to be preserved, +/// try_enter()/try_leave() pair should be used instead. void try_start(void) { ++trylevel; @@ -44,7 +115,9 @@ void try_start(void) /// @return true if an error occurred bool try_end(Error *err) { - --trylevel; + // Note: all globals manipulated here should be saved/restored in + // try_enter/try_leave. + trylevel--; // Without this it stops processing all subsequent VimL commands and // generates strange error messages if I e.g. try calling Test() in a @@ -57,7 +130,7 @@ bool try_end(Error *err) discard_current_exception(); } - api_set_error(err, Exception, _("Keyboard interrupt")); + api_set_error(err, kErrorTypeException, "Keyboard interrupt"); got_int = false; } else if (msg_list != NULL && *msg_list != NULL) { int should_free; @@ -65,19 +138,18 @@ bool try_end(Error *err) ET_ERROR, NULL, &should_free); - xstrlcpy(err->msg, msg, sizeof(err->msg)); - err->set = true; + api_set_error(err, kErrorTypeException, "%s", msg); free_global_msglist(); if (should_free) { xfree(msg); } } else if (did_throw) { - api_set_error(err, Exception, "%s", current_exception->value); + api_set_error(err, kErrorTypeException, "%s", current_exception->value); discard_current_exception(); } - return err->set; + return ERROR_SET(err); } /// Recursively expands a vimscript value in a dict @@ -87,18 +159,17 @@ bool try_end(Error *err) /// @param[out] err Details of an error that may have occurred Object dict_get_value(dict_T *dict, String key, Error *err) { - hashitem_T *hi = hash_find(&dict->dv_hashtab, (uint8_t *) key.data); + dictitem_T *const di = tv_dict_find(dict, key.data, (ptrdiff_t)key.size); - if (HASHITEM_EMPTY(hi)) { - api_set_error(err, Validation, _("Key not found")); - return (Object) OBJECT_INIT; + if (di == NULL) { + api_set_error(err, kErrorTypeValidation, "Key '%s' not found", key.data); + return (Object)OBJECT_INIT; } - dictitem_T *di = dict_lookup(hi); return vim_to_object(&di->di_tv); } -/// Set a value in a dict. Objects are recursively expanded into their +/// Set a value in a scope dict. Objects are recursively expanded into their /// vimscript equivalents. /// /// @param dict The vimscript dict @@ -109,42 +180,55 @@ Object dict_get_value(dict_T *dict, String key, Error *err) /// @param retval If true the old value will be converted and returned. /// @param[out] err Details of an error that may have occurred /// @return The old value if `retval` is true and the key was present, else NIL -Object dict_set_value(dict_T *dict, String key, Object value, bool del, - bool retval, Error *err) +Object dict_set_var(dict_T *dict, String key, Object value, bool del, + bool retval, Error *err) { Object rv = OBJECT_INIT; if (dict->dv_lock) { - api_set_error(err, Exception, _("Dictionary is locked")); + api_set_error(err, kErrorTypeException, "Dictionary is locked"); return rv; } if (key.size == 0) { - api_set_error(err, Validation, _("Empty dictionary keys aren't allowed")); + api_set_error(err, kErrorTypeValidation, + "Empty variable names aren't allowed"); return rv; } if (key.size > INT_MAX) { - api_set_error(err, Validation, _("Key length is too high")); + api_set_error(err, kErrorTypeValidation, "Key length is too high"); return rv; } - dictitem_T *di = dict_find(dict, (uint8_t *)key.data, (int)key.size); + dictitem_T *di = tv_dict_find(dict, key.data, (ptrdiff_t)key.size); + + if (di != NULL) { + if (di->di_flags & DI_FLAGS_RO) { + api_set_error(err, kErrorTypeException, "Key is read-only: %s", key.data); + return rv; + } else if (di->di_flags & DI_FLAGS_FIX) { + api_set_error(err, kErrorTypeException, "Key is fixed: %s", key.data); + return rv; + } else if (di->di_flags & DI_FLAGS_LOCK) { + api_set_error(err, kErrorTypeException, "Key is locked: %s", key.data); + return rv; + } + } if (del) { // Delete the key if (di == NULL) { // Doesn't exist, fail - api_set_error(err, Validation, _("Key \"%s\" doesn't exist"), key.data); + api_set_error(err, kErrorTypeValidation, "Key does not exist: %s", + key.data); } else { // Return the old value if (retval) { rv = vim_to_object(&di->di_tv); } // Delete the entry - hashitem_T *hi = hash_find(&dict->dv_hashtab, di->di_key); - hash_remove(&dict->dv_hashtab, hi); - dictitem_free(di); + tv_dict_item_remove(dict, di); } } else { // Update the key @@ -157,20 +241,20 @@ Object dict_set_value(dict_T *dict, String key, Object value, bool del, if (di == NULL) { // Need to create an entry - di = dictitem_alloc((uint8_t *) key.data); - dict_add(dict, di); + di = tv_dict_item_alloc_len(key.data, key.size); + tv_dict_add(dict, di); } else { // Return the old value if (retval) { rv = vim_to_object(&di->di_tv); } - clear_tv(&di->di_tv); + tv_clear(&di->di_tv); } // Update the value - copy_tv(&tv, &di->di_tv); + tv_copy(&tv, &di->di_tv); // Clear the temporary variable - clear_tv(&tv); + tv_clear(&tv); } return rv; @@ -189,7 +273,7 @@ Object get_option_from(void *from, int type, String name, Error *err) Object rv = OBJECT_INIT; if (name.size == 0) { - api_set_error(err, Validation, _("Empty option name")); + api_set_error(err, kErrorTypeValidation, "Empty option name"); return rv; } @@ -201,8 +285,8 @@ Object get_option_from(void *from, int type, String name, Error *err) if (!flags) { api_set_error(err, - Validation, - _("Invalid option name \"%s\""), + kErrorTypeValidation, + "Invalid option name \"%s\"", name.data); return rv; } @@ -220,14 +304,14 @@ Object get_option_from(void *from, int type, String name, Error *err) rv.data.string.size = strlen(stringval); } else { api_set_error(err, - Exception, - _("Unable to get value for option \"%s\""), + kErrorTypeException, + "Unable to get value for option \"%s\"", name.data); } } else { api_set_error(err, - Exception, - _("Unknown type for option \"%s\""), + kErrorTypeException, + "Unknown type for option \"%s\"", name.data); } @@ -244,7 +328,7 @@ Object get_option_from(void *from, int type, String name, Error *err) void set_option_to(void *to, int type, String name, Object value, Error *err) { if (name.size == 0) { - api_set_error(err, Validation, _("Empty option name")); + api_set_error(err, kErrorTypeValidation, "Empty option name"); return; } @@ -252,8 +336,8 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) if (flags == 0) { api_set_error(err, - Validation, - _("Invalid option name \"%s\""), + kErrorTypeValidation, + "Invalid option name \"%s\"", name.data); return; } @@ -261,15 +345,15 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) if (value.type == kObjectTypeNil) { if (type == SREQ_GLOBAL) { api_set_error(err, - Exception, - _("Unable to unset option \"%s\""), + kErrorTypeException, + "Unable to unset option \"%s\"", name.data); return; } else if (!(flags & SOPT_GLOBAL)) { api_set_error(err, - Exception, - _("Cannot unset option \"%s\" " - "because it doesn't have a global value"), + kErrorTypeException, + "Cannot unset option \"%s\" " + "because it doesn't have a global value", name.data); return; } else { @@ -278,13 +362,13 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) } } - int opt_flags = (type ? OPT_LOCAL : OPT_GLOBAL); + int opt_flags = (type == SREQ_GLOBAL) ? OPT_GLOBAL : OPT_LOCAL; if (flags & SOPT_BOOL) { if (value.type != kObjectTypeBoolean) { api_set_error(err, - Validation, - _("Option \"%s\" requires a boolean value"), + kErrorTypeValidation, + "Option \"%s\" requires a boolean value", name.data); return; } @@ -294,16 +378,16 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) } else if (flags & SOPT_NUM) { if (value.type != kObjectTypeInteger) { api_set_error(err, - Validation, - _("Option \"%s\" requires an integer value"), + kErrorTypeValidation, + "Option \"%s\" requires an integer value", name.data); return; } if (value.data.integer > INT_MAX || value.data.integer < INT_MIN) { api_set_error(err, - Validation, - _("Value for option \"%s\" is outside range"), + kErrorTypeValidation, + "Value for option \"%s\" is outside range", name.data); return; } @@ -313,8 +397,8 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) } else { if (value.type != kObjectTypeString) { api_set_error(err, - Validation, - _("Option \"%s\" requires a string value"), + kErrorTypeValidation, + "Option \"%s\" requires a string value", name.data); return; } @@ -338,7 +422,7 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) #define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER TYPVAL_ENCODE_CONV_NUMBER #define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ - kv_push(edata->stack, FLOATING_OBJ((Float)(flt))) + kv_push(edata->stack, FLOAT_OBJ((Float)(flt))) #define TYPVAL_ENCODE_CONV_STRING(tv, str, len) \ do { \ @@ -380,7 +464,7 @@ static inline void typval_encode_list_start(EncodedData *const edata, kv_push(edata->stack, ARRAY_OBJ(((Array) { .capacity = len, .size = 0, - .items = xmalloc(len * sizeof(*((Object *)NULL)->data.array.items)), + .items = xmalloc(len * sizeof(*((Object)OBJECT_INIT).data.array.items)), }))); } @@ -422,7 +506,8 @@ static inline void typval_encode_dict_start(EncodedData *const edata, kv_push(edata->stack, DICTIONARY_OBJ(((Dictionary) { .capacity = len, .size = 0, - .items = xmalloc(len * sizeof(*((Object *)NULL)->data.dictionary.items)), + .items = xmalloc(len * sizeof( + *((Object)OBJECT_INIT).data.dictionary.items)), }))); } @@ -546,13 +631,13 @@ buf_T *find_buffer_by_handle(Buffer buffer, Error *err) buf_T *rv = handle_get_buffer(buffer); if (!rv) { - api_set_error(err, Validation, _("Invalid buffer id")); + api_set_error(err, kErrorTypeValidation, "Invalid buffer id"); } return rv; } -win_T * find_window_by_handle(Window window, Error *err) +win_T *find_window_by_handle(Window window, Error *err) { if (window == 0) { return curwin; @@ -561,13 +646,13 @@ win_T * find_window_by_handle(Window window, Error *err) win_T *rv = handle_get_window(window); if (!rv) { - api_set_error(err, Validation, _("Invalid window id")); + api_set_error(err, kErrorTypeValidation, "Invalid window id"); } return rv; } -tabpage_T * find_tab_by_handle(Tabpage tabpage, Error *err) +tabpage_T *find_tab_by_handle(Tabpage tabpage, Error *err) { if (tabpage == 0) { return curtab; @@ -576,7 +661,7 @@ tabpage_T * find_tab_by_handle(Tabpage tabpage, Error *err) tabpage_T *rv = handle_get_tabpage(tabpage); if (!rv) { - api_set_error(err, Validation, _("Invalid tabpage id")); + api_set_error(err, kErrorTypeValidation, "Invalid tabpage id"); } return rv; @@ -613,7 +698,7 @@ String cstr_as_string(char *str) FUNC_ATTR_PURE if (str == NULL) { return (String) STRING_INIT; } - return (String) {.data = str, .size = strlen(str)}; + return (String) { .data = str, .size = strlen(str) }; } /// Converts from type Object to a VimL value. @@ -644,7 +729,7 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err) case kObjectTypeInteger: if (obj.data.integer > VARNUMBER_MAX || obj.data.integer < VARNUMBER_MIN) { - api_set_error(err, Validation, _("Integer value outside range")); + api_set_error(err, kErrorTypeValidation, "Integer value outside range"); return false; } @@ -668,20 +753,20 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err) break; case kObjectTypeArray: { - list_T *list = list_alloc(); + list_T *const list = tv_list_alloc(); for (uint32_t i = 0; i < obj.data.array.size; i++) { Object item = obj.data.array.items[i]; - listitem_T *li = listitem_alloc(); + listitem_T *li = tv_list_item_alloc(); if (!object_to_vim(item, &li->li_tv, err)) { // cleanup - listitem_free(li); - list_free(list); + tv_list_item_free(li); + tv_list_free(list); return false; } - list_append(list, li); + tv_list_append(list, li); } list->lv_refcount++; @@ -691,30 +776,30 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err) } case kObjectTypeDictionary: { - dict_T *dict = dict_alloc(); + dict_T *const dict = tv_dict_alloc(); for (uint32_t i = 0; i < obj.data.dictionary.size; i++) { KeyValuePair item = obj.data.dictionary.items[i]; String key = item.key; if (key.size == 0) { - api_set_error(err, Validation, - _("Empty dictionary keys aren't allowed")); + api_set_error(err, kErrorTypeValidation, + "Empty dictionary keys aren't allowed"); // cleanup - dict_free(dict); + tv_dict_free(dict); return false; } - dictitem_T *di = dictitem_alloc((uint8_t *)key.data); + dictitem_T *const di = tv_dict_item_alloc(key.data); if (!object_to_vim(item.value, &di->di_tv, err)) { // cleanup - dictitem_free(di); - dict_free(dict); + tv_dict_item_free(di); + tv_dict_free(dict); return false; } - dict_add(dict, di); + tv_dict_add(dict, di); } dict->dv_refcount++; @@ -786,6 +871,17 @@ void api_free_dictionary(Dictionary value) xfree(value.items); } +void api_clear_error(Error *value) + FUNC_ATTR_NONNULL_ALL +{ + if (!ERROR_SET(value)) { + return; + } + xfree(value->msg); + value->msg = NULL; + value->type = kErrorTypeNone; +} + Dictionary api_metadata(void) { static Dictionary metadata = ARRAY_DICT_INIT; @@ -793,6 +889,7 @@ Dictionary api_metadata(void) if (!metadata.size) { PUT(metadata, "version", DICTIONARY_OBJ(version_dict())); init_function_metadata(&metadata); + init_ui_event_metadata(&metadata); init_error_type_metadata(&metadata); init_type_metadata(&metadata); } @@ -816,6 +913,22 @@ static void init_function_metadata(Dictionary *metadata) PUT(*metadata, "functions", functions); } +static void init_ui_event_metadata(Dictionary *metadata) +{ + msgpack_unpacked unpacked; + msgpack_unpacked_init(&unpacked); + if (msgpack_unpack_next(&unpacked, + (const char *)ui_events_metadata, + sizeof(ui_events_metadata), + NULL) != MSGPACK_UNPACK_SUCCESS) { + abort(); + } + Object ui_events; + msgpack_rpc_to_object(&unpacked.data, &ui_events); + msgpack_unpacked_destroy(&unpacked); + PUT(*metadata, "ui_events", ui_events); +} + static void init_error_type_metadata(Dictionary *metadata) { Dictionary types = ARRAY_DICT_INIT; @@ -837,15 +950,18 @@ static void init_type_metadata(Dictionary *metadata) Dictionary types = ARRAY_DICT_INIT; Dictionary buffer_metadata = ARRAY_DICT_INIT; - PUT(buffer_metadata, "id", INTEGER_OBJ(kObjectTypeBuffer)); + PUT(buffer_metadata, "id", + INTEGER_OBJ(kObjectTypeBuffer - EXT_OBJECT_TYPE_SHIFT)); PUT(buffer_metadata, "prefix", STRING_OBJ(cstr_to_string("nvim_buf_"))); Dictionary window_metadata = ARRAY_DICT_INIT; - PUT(window_metadata, "id", INTEGER_OBJ(kObjectTypeWindow)); + PUT(window_metadata, "id", + INTEGER_OBJ(kObjectTypeWindow - EXT_OBJECT_TYPE_SHIFT)); PUT(window_metadata, "prefix", STRING_OBJ(cstr_to_string("nvim_win_"))); Dictionary tabpage_metadata = ARRAY_DICT_INIT; - PUT(tabpage_metadata, "id", INTEGER_OBJ(kObjectTypeTabpage)); + PUT(tabpage_metadata, "id", + INTEGER_OBJ(kObjectTypeTabpage - EXT_OBJECT_TYPE_SHIFT)); PUT(tabpage_metadata, "prefix", STRING_OBJ(cstr_to_string("nvim_tabpage_"))); PUT(types, "Buffer", DICTIONARY_OBJ(buffer_metadata)); @@ -855,6 +971,24 @@ static void init_type_metadata(Dictionary *metadata) PUT(*metadata, "types", DICTIONARY_OBJ(types)); } +String copy_string(String str) +{ + if (str.data != NULL) { + return (String){ .data = xmemdupz(str.data, str.size), .size = str.size }; + } else { + return (String)STRING_INIT; + } +} + +Array copy_array(Array array) +{ + Array rv = ARRAY_DICT_INIT; + for (size_t i = 0; i < array.size; i++) { + ADD(rv, copy_object(array.items[i])); + } + return rv; +} + /// Creates a deep clone of an object Object copy_object(Object obj) { @@ -866,15 +1000,10 @@ Object copy_object(Object obj) return obj; case kObjectTypeString: - return STRING_OBJ(cstr_to_string(obj.data.string.data)); + return STRING_OBJ(copy_string(obj.data.string)); - case kObjectTypeArray: { - Array rv = ARRAY_DICT_INIT; - for (size_t i = 0; i < obj.data.array.size; i++) { - ADD(rv, copy_object(obj.data.array.items[i])); - } - return ARRAY_OBJ(rv); - } + case kObjectTypeArray: + return ARRAY_OBJ(copy_array(obj.data.array)); case kObjectTypeDictionary: { Dictionary rv = ARRAY_DICT_INIT; @@ -899,7 +1028,7 @@ static void set_option_value_for(char *key, { win_T *save_curwin = NULL; tabpage_T *save_curtab = NULL; - buf_T *save_curbuf = NULL; + bufref_T save_curbuf = { NULL, 0, 0 }; try_start(); switch (opt_type) @@ -912,8 +1041,8 @@ static void set_option_value_for(char *key, return; } api_set_error(err, - Exception, - _("Problem while switching windows")); + kErrorTypeException, + "Problem while switching windows"); return; } set_option_value_err(key, numval, stringval, opt_flags, err); @@ -922,14 +1051,14 @@ static void set_option_value_for(char *key, case SREQ_BUF: switch_buffer(&save_curbuf, (buf_T *)from); set_option_value_err(key, numval, stringval, opt_flags, err); - restore_buffer(save_curbuf); + restore_buffer(&save_curbuf); break; case SREQ_GLOBAL: set_option_value_err(key, numval, stringval, opt_flags, err); break; } - if (err->set) { + if (ERROR_SET(err)) { return; } @@ -945,15 +1074,69 @@ static void set_option_value_err(char *key, { char *errmsg; - if ((errmsg = (char *)set_option_value((uint8_t *)key, - numval, - (uint8_t *)stringval, - opt_flags))) - { + if ((errmsg = set_option_value(key, numval, stringval, opt_flags))) { if (try_end(err)) { return; } - api_set_error(err, Exception, "%s", errmsg); + api_set_error(err, kErrorTypeException, "%s", errmsg); } } + +void api_set_error(Error *err, ErrorType errType, const char *format, ...) + FUNC_ATTR_NONNULL_ALL +{ + assert(kErrorTypeNone != errType); + va_list args1; + va_list args2; + va_start(args1, format); + va_copy(args2, args1); + int len = vsnprintf(NULL, 0, format, args1); + va_end(args1); + assert(len >= 0); + // Limit error message to 1 MB. + size_t bufsize = MIN((size_t)len + 1, 1024 * 1024); + err->msg = xmalloc(bufsize); + vsnprintf(err->msg, bufsize, format, args2); + va_end(args2); + + err->type = errType; +} + +/// Get an array containing dictionaries describing mappings +/// based on mode and buffer id +/// +/// @param mode The abbreviation for the mode +/// @param buf The buffer to get the mapping array. NULL for global +/// @returns An array of maparg() like dictionaries describing mappings +ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf) +{ + Array mappings = ARRAY_DICT_INIT; + dict_T *const dict = tv_dict_alloc(); + + // Convert the string mode to the integer mode + // that is stored within each mapblock + char_u *p = (char_u *)mode.data; + int int_mode = get_map_mode(&p, 0); + + // Determine the desired buffer value + long buffer_value = (buf == NULL) ? 0 : buf->handle; + + for (int i = 0; i < MAX_MAPHASH; i++) { + for (const mapblock_T *current_maphash = get_maphash(i, buf); + current_maphash; + current_maphash = current_maphash->m_next) { + // Check for correct mode + if (int_mode & current_maphash->m_mode) { + mapblock_fill_dict(dict, current_maphash, buffer_value, false); + ADD(mappings, vim_to_object( + (typval_T[]) { { .v_type = VAR_DICT, .vval.v_dict = dict } })); + + tv_dict_clear(dict); + } + } + } + tv_dict_free(dict); + + return mappings; +} diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index 9fe8c351cf..87f334ac30 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -6,17 +6,9 @@ #include "nvim/api/private/defs.h" #include "nvim/vim.h" #include "nvim/memory.h" +#include "nvim/ex_eval.h" #include "nvim/lib/kvec.h" -#define api_set_error(err, errtype, ...) \ - do { \ - snprintf((err)->msg, \ - sizeof((err)->msg), \ - __VA_ARGS__); \ - (err)->set = true; \ - (err)->type = kErrorType##errtype; \ - } while (0) - #define OBJECT_OBJ(o) o #define BOOLEAN_OBJ(b) ((Object) { \ @@ -27,7 +19,7 @@ .type = kObjectTypeInteger, \ .data.integer = i }) -#define FLOATING_OBJ(f) ((Object) { \ +#define FLOAT_OBJ(f) ((Object) { \ .type = kObjectTypeFloat, \ .data.floating = f }) @@ -91,6 +83,21 @@ #define api_free_window(value) #define api_free_tabpage(value) +/// Structure used for saving state for :try +/// +/// Used when caller is supposed to be operating when other VimL code is being +/// processed and that “other VimL code†must not be affected. +typedef struct { + except_T *current_exception; + struct msglist *private_msg_list; + const struct msglist *const *msg_list; + int trylevel; + int got_int; + int did_throw; + int need_rethrow; + int did_emsg; +} TryState; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/private/helpers.h.generated.h" #endif diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c index 9e61ec1871..b6830d9fcf 100644 --- a/src/nvim/api/tabpage.c +++ b/src/nvim/api/tabpage.c @@ -1,3 +1,6 @@ +// 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 <stdbool.h> #include <stdint.h> #include <stdlib.h> @@ -15,6 +18,7 @@ /// @param[out] err Error details, if any /// @return List of windows in `tabpage` ArrayOf(Window) nvim_tabpage_list_wins(Tabpage tabpage, Error *err) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -44,6 +48,7 @@ ArrayOf(Window) nvim_tabpage_list_wins(Tabpage tabpage, Error *err) /// @param[out] err Error details, if any /// @return Variable value Object nvim_tabpage_get_var(Tabpage tabpage, String name, Error *err) + FUNC_API_SINCE(1) { tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -64,6 +69,7 @@ void nvim_tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err) + FUNC_API_SINCE(1) { tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -71,7 +77,7 @@ void nvim_tabpage_set_var(Tabpage tabpage, return; } - dict_set_value(tab->tp_vars, name, value, false, false, err); + dict_set_var(tab->tp_vars, name, value, false, false, err); } /// Removes a tab-scoped (t:) variable @@ -80,6 +86,7 @@ void nvim_tabpage_set_var(Tabpage tabpage, /// @param name Variable name /// @param[out] err Error details, if any void nvim_tabpage_del_var(Tabpage tabpage, String name, Error *err) + FUNC_API_SINCE(1) { tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -87,7 +94,7 @@ void nvim_tabpage_del_var(Tabpage tabpage, String name, Error *err) return; } - dict_set_value(tab->tp_vars, name, NIL, true, false, err); + dict_set_var(tab->tp_vars, name, NIL, true, false, err); } /// Sets a tab-scoped (t:) variable @@ -110,7 +117,7 @@ Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err) return (Object) OBJECT_INIT; } - return dict_set_value(tab->tp_vars, name, value, false, true, err); + return dict_set_var(tab->tp_vars, name, value, false, true, err); } /// Removes a tab-scoped (t:) variable @@ -129,7 +136,7 @@ Object tabpage_del_var(Tabpage tabpage, String name, Error *err) return (Object) OBJECT_INIT; } - return dict_set_value(tab->tp_vars, name, NIL, true, true, err); + return dict_set_var(tab->tp_vars, name, NIL, true, true, err); } /// Gets the current window in a tabpage @@ -138,6 +145,7 @@ Object tabpage_del_var(Tabpage tabpage, String name, Error *err) /// @param[out] err Error details, if any /// @return Window handle Window nvim_tabpage_get_win(Tabpage tabpage, Error *err) + FUNC_API_SINCE(1) { Window rv = 0; tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -165,6 +173,7 @@ Window nvim_tabpage_get_win(Tabpage tabpage, Error *err) /// @param[out] err Error details, if any /// @return Tabpage number Integer nvim_tabpage_get_number(Tabpage tabpage, Error *err) + FUNC_API_SINCE(1) { Integer rv = 0; tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -181,8 +190,11 @@ Integer nvim_tabpage_get_number(Tabpage tabpage, Error *err) /// @param tabpage Tabpage handle /// @return true if the tabpage is valid, false otherwise Boolean nvim_tabpage_is_valid(Tabpage tabpage) + FUNC_API_SINCE(1) { Error stub = ERROR_INIT; - return find_tab_by_handle(tabpage, &stub) != NULL; + Boolean ret = find_tab_by_handle(tabpage, &stub) != NULL; + api_clear_error(&stub); + return ret; } diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 9178538110..573be23d8e 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -1,3 +1,6 @@ +// 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 <stddef.h> #include <stdint.h> @@ -12,9 +15,11 @@ #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/popupmnu.h" +#include "nvim/cursor_shape.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/ui.c.generated.h" +# include "ui_events_remote.generated.h" #endif typedef struct { @@ -25,13 +30,13 @@ typedef struct { static PMap(uint64_t) *connected_uis = NULL; void remote_ui_init(void) - FUNC_API_NOEXPORT + FUNC_API_NOEXPORT { connected_uis = pmap_new(uint64_t)(); } void remote_ui_disconnect(uint64_t channel_id) - FUNC_API_NOEXPORT + FUNC_API_NOEXPORT { UI *ui = pmap_get(uint64_t)(connected_uis, channel_id); if (!ui) { @@ -48,27 +53,27 @@ void remote_ui_disconnect(uint64_t channel_id) void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictionary options, Error *err) - FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { if (pmap_has(uint64_t)(connected_uis, channel_id)) { - api_set_error(err, Exception, _("UI already attached for channel")); + api_set_error(err, kErrorTypeException, "UI already attached for channel"); return; } if (width <= 0 || height <= 0) { - api_set_error(err, Validation, - _("Expected width > 0 and height > 0")); + api_set_error(err, kErrorTypeValidation, + "Expected width > 0 and height > 0"); return; } UI *ui = xcalloc(1, sizeof(UI)); ui->width = (int)width; ui->height = (int)height; ui->rgb = true; - ui->pum_external = false; ui->resize = remote_ui_resize; ui->clear = remote_ui_clear; ui->eol_clear = remote_ui_eol_clear; ui->cursor_goto = remote_ui_cursor_goto; + ui->mode_info_set = remote_ui_mode_info_set; ui->update_menu = remote_ui_update_menu; ui->busy_start = remote_ui_busy_start; ui->busy_stop = remote_ui_busy_stop; @@ -90,9 +95,11 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, ui->set_icon = remote_ui_set_icon; ui->event = remote_ui_event; + memset(ui->ui_ext, 0, sizeof(ui->ui_ext)); + for (size_t i = 0; i < options.size; i++) { ui_set_option(ui, options.items[i].key, options.items[i].value, err); - if (err->set) { + if (ERROR_SET(err)) { xfree(ui); return; } @@ -118,10 +125,10 @@ void ui_attach(uint64_t channel_id, Integer width, Integer height, } void nvim_ui_detach(uint64_t channel_id, Error *err) - FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { if (!pmap_has(uint64_t)(connected_uis, channel_id)) { - api_set_error(err, Exception, _("UI is not attached for channel")); + api_set_error(err, kErrorTypeException, "UI is not attached for channel"); return; } remote_ui_disconnect(channel_id); @@ -130,16 +137,16 @@ void nvim_ui_detach(uint64_t channel_id, Error *err) void nvim_ui_try_resize(uint64_t channel_id, Integer width, Integer height, Error *err) - FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { if (!pmap_has(uint64_t)(connected_uis, channel_id)) { - api_set_error(err, Exception, _("UI is not attached for channel")); + api_set_error(err, kErrorTypeException, "UI is not attached for channel"); return; } if (width <= 0 || height <= 0) { - api_set_error(err, Validation, - _("Expected width > 0 and height > 0")); + api_set_error(err, kErrorTypeValidation, + "Expected width > 0 and height > 0"); return; } @@ -151,37 +158,61 @@ void nvim_ui_try_resize(uint64_t channel_id, Integer width, void nvim_ui_set_option(uint64_t channel_id, String name, Object value, Error *error) - FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { if (!pmap_has(uint64_t)(connected_uis, channel_id)) { - api_set_error(error, Exception, _("UI is not attached for channel")); + api_set_error(error, kErrorTypeException, "UI is not attached for channel"); return; } UI *ui = pmap_get(uint64_t)(connected_uis, channel_id); ui_set_option(ui, name, value, error); - if (!error->set) { + if (!ERROR_SET(error)) { ui_refresh(); } } -static void ui_set_option(UI *ui, String name, Object value, Error *error) { - if (strcmp(name.data, "rgb") == 0) { +static void ui_set_option(UI *ui, String name, Object value, Error *error) +{ +#define UI_EXT_OPTION(o, e) \ + do { \ + if (strequal(name.data, #o)) { \ + if (value.type != kObjectTypeBoolean) { \ + api_set_error(error, kErrorTypeValidation, #o " must be a Boolean"); \ + return; \ + } \ + ui->ui_ext[(e)] = value.data.boolean; \ + return; \ + } \ + } while (0) + + if (strequal(name.data, "rgb")) { if (value.type != kObjectTypeBoolean) { - api_set_error(error, Validation, _("rgb must be a Boolean")); + api_set_error(error, kErrorTypeValidation, "rgb must be a Boolean"); return; } ui->rgb = value.data.boolean; - } else if (strcmp(name.data, "popupmenu_external") == 0) { + return; + } + + UI_EXT_OPTION(ext_cmdline, kUICmdline); + UI_EXT_OPTION(ext_popupmenu, kUIPopupmenu); + UI_EXT_OPTION(ext_tabline, kUITabline); + UI_EXT_OPTION(ext_wildmenu, kUIWildmenu); + + if (strequal(name.data, "popupmenu_external")) { + // LEGACY: Deprecated option, use `ui_ext` instead. if (value.type != kObjectTypeBoolean) { - api_set_error(error, Validation, - _("popupmenu_external must be a Boolean")); + api_set_error(error, kErrorTypeValidation, + "popupmenu_external must be a Boolean"); return; } - ui->pum_external = value.data.boolean; - } else { - api_set_error(error, Validation, _("No such ui option")); + ui->ui_ext[kUIPopupmenu] = value.data.boolean; + return; } + + api_set_error(error, kErrorTypeValidation, "No such ui option"); +#undef UI_EXT_OPTION } static void push_call(UI *ui, char *name, Array args) @@ -206,97 +237,6 @@ static void push_call(UI *ui, char *name, Array args) kv_A(data->buffer, kv_size(data->buffer) - 1).data.array = call; } -static void remote_ui_resize(UI *ui, int width, int height) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(width)); - ADD(args, INTEGER_OBJ(height)); - push_call(ui, "resize", args); -} - -static void remote_ui_clear(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "clear", args); -} - -static void remote_ui_eol_clear(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "eol_clear", args); -} - -static void remote_ui_cursor_goto(UI *ui, int row, int col) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(row)); - ADD(args, INTEGER_OBJ(col)); - push_call(ui, "cursor_goto", args); -} - -static void remote_ui_update_menu(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "update_menu", args); -} - -static void remote_ui_busy_start(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "busy_start", args); -} - -static void remote_ui_busy_stop(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "busy_stop", args); -} - -static void remote_ui_mouse_on(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "mouse_on", args); -} - -static void remote_ui_mouse_off(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "mouse_off", args); -} - -static void remote_ui_mode_change(UI *ui, int mode) -{ - Array args = ARRAY_DICT_INIT; - if (mode == INSERT) { - ADD(args, STRING_OBJ(cstr_to_string("insert"))); - } else if (mode == REPLACE) { - ADD(args, STRING_OBJ(cstr_to_string("replace"))); - } else if (mode == CMDLINE) { - ADD(args, STRING_OBJ(cstr_to_string("cmdline"))); - } else { - assert(mode == NORMAL); - ADD(args, STRING_OBJ(cstr_to_string("normal"))); - } - push_call(ui, "mode_change", args); -} - -static void remote_ui_set_scroll_region(UI *ui, int top, int bot, int left, - int right) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(top)); - ADD(args, INTEGER_OBJ(bot)); - ADD(args, INTEGER_OBJ(left)); - ADD(args, INTEGER_OBJ(right)); - push_call(ui, "set_scroll_region", args); -} - -static void remote_ui_scroll(UI *ui, int count) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(count)); - push_call(ui, "scroll", args); -} static void remote_ui_highlight_set(UI *ui, HlAttrs attrs) { @@ -339,72 +279,13 @@ static void remote_ui_highlight_set(UI *ui, HlAttrs attrs) push_call(ui, "highlight_set", args); } -static void remote_ui_put(UI *ui, uint8_t *data, size_t size) -{ - Array args = ARRAY_DICT_INIT; - String str = { .data = xmemdupz(data, size), .size = size }; - ADD(args, STRING_OBJ(str)); - push_call(ui, "put", args); -} - -static void remote_ui_bell(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "bell", args); -} - -static void remote_ui_visual_bell(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "visual_bell", args); -} - -static void remote_ui_update_fg(UI *ui, int fg) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(fg)); - push_call(ui, "update_fg", args); -} - -static void remote_ui_update_bg(UI *ui, int bg) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(bg)); - push_call(ui, "update_bg", args); -} - -static void remote_ui_update_sp(UI *ui, int sp) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(sp)); - push_call(ui, "update_sp", args); -} - static void remote_ui_flush(UI *ui) { UIData *data = ui->data; - channel_send_event(data->channel_id, "redraw", data->buffer); - data->buffer = (Array)ARRAY_DICT_INIT; -} - -static void remote_ui_suspend(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "suspend", args); -} - -static void remote_ui_set_title(UI *ui, char *title) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(cstr_to_string(title))); - push_call(ui, "set_title", args); -} - -static void remote_ui_set_icon(UI *ui, char *icon) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(cstr_to_string(icon))); - push_call(ui, "set_icon", args); + if (data->buffer.size > 0) { + channel_send_event(data->channel_id, "redraw", data->buffer); + data->buffer = (Array)ARRAY_DICT_INIT; + } } static void remote_ui_event(UI *ui, char *name, Array args, bool *args_consumed) diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h new file mode 100644 index 0000000000..1b5d17584f --- /dev/null +++ b/src/nvim/api/ui_events.in.h @@ -0,0 +1,71 @@ +#ifndef NVIM_API_UI_EVENTS_IN_H +#define NVIM_API_UI_EVENTS_IN_H + +// This file is not compiled, just parsed for definitons +#ifdef INCLUDE_GENERATED_DECLARATIONS +# error "don't include this file, include nvim/ui.h" +#endif + +#include "nvim/api/private/defs.h" +#include "nvim/func_attr.h" +#include "nvim/ui.h" + +void resize(Integer rows, Integer columns) + FUNC_API_SINCE(3); +void clear(void) + FUNC_API_SINCE(3); +void eol_clear(void) + FUNC_API_SINCE(3); +void cursor_goto(Integer row, Integer col) + FUNC_API_SINCE(3); +void mode_info_set(Boolean enabled, Array cursor_styles) + FUNC_API_SINCE(3); +void update_menu(void) + FUNC_API_SINCE(3); +void busy_start(void) + FUNC_API_SINCE(3); +void busy_stop(void) + FUNC_API_SINCE(3); +void mouse_on(void) + FUNC_API_SINCE(3); +void mouse_off(void) + FUNC_API_SINCE(3); +void mode_change(String mode, Integer mode_idx) + FUNC_API_SINCE(3); +void set_scroll_region(Integer top, Integer bot, Integer left, Integer right) + FUNC_API_SINCE(3); +void scroll(Integer count) + FUNC_API_SINCE(3); +void highlight_set(HlAttrs attrs) + FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL FUNC_API_BRIDGE_IMPL; +void put(String str) + FUNC_API_SINCE(3); +void bell(void) + FUNC_API_SINCE(3); +void visual_bell(void) + FUNC_API_SINCE(3); +void flush(void) + FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL; +void update_fg(Integer fg) + FUNC_API_SINCE(3); +void update_bg(Integer bg) + FUNC_API_SINCE(3); +void update_sp(Integer sp) + FUNC_API_SINCE(3); +void suspend(void) + FUNC_API_SINCE(3) FUNC_API_BRIDGE_IMPL; +void set_title(String title) + FUNC_API_SINCE(3); +void set_icon(String icon) + FUNC_API_SINCE(3); + +void popupmenu_show(Array items, Integer selected, Integer row, Integer col) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void popupmenu_hide(void) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void popupmenu_select(Integer selected) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void tabline_update(Tabpage current, Array tabs) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; + +#endif // NVIM_API_UI_EVENTS_IN_H diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index b17b59f7a6..cfbe34b848 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1,3 +1,6 @@ +// 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 <inttypes.h> @@ -10,8 +13,10 @@ #include "nvim/ascii.h" #include "nvim/api/private/helpers.h" #include "nvim/api/private/defs.h" +#include "nvim/api/private/dispatch.h" #include "nvim/api/buffer.h" #include "nvim/msgpack_rpc/channel.h" +#include "nvim/lua/executor.h" #include "nvim/vim.h" #include "nvim/buffer.h" #include "nvim/file_search.h" @@ -22,7 +27,9 @@ #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/eval.h" +#include "nvim/eval/typval.h" #include "nvim/option.h" +#include "nvim/state.h" #include "nvim/syntax.h" #include "nvim/getchar.h" #include "nvim/os/input.h" @@ -39,6 +46,7 @@ /// @param command Ex-command string /// @param[out] err Error details (including actual VimL error), if any void nvim_command(String command, Error *err) + FUNC_API_SINCE(1) { // Run the command try_start(); @@ -56,6 +64,7 @@ void nvim_command(String command, Error *err) /// @see feedkeys() /// @see vim_strsave_escape_csi void nvim_feedkeys(String keys, String mode, Boolean escape_csi) + FUNC_API_SINCE(1) { bool remap = true; bool insert = false; @@ -122,43 +131,44 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi) /// @return Number of bytes actually written (can be fewer than /// requested if the buffer becomes full). Integer nvim_input(String keys) - FUNC_API_ASYNC + FUNC_API_SINCE(1) FUNC_API_ASYNC { return (Integer)input_enqueue(keys); } -/// Replaces any terminal codes with the internal representation +/// Replaces terminal codes and |keycodes| (<CR>, <Esc>, ...) in a string with +/// the internal representation. /// +/// @param str String to be converted. +/// @param from_part Legacy Vim parameter. Usually true. +/// @param do_lt Also translate <lt>. Ignored if `special` is false. +/// @param special Replace |keycodes|, e.g. <CR> becomes a "\n" char. /// @see replace_termcodes /// @see cpoptions String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Boolean special) + FUNC_API_SINCE(1) { if (str.size == 0) { // Empty string - return str; + return (String) { .data = NULL, .size = 0 }; } char *ptr = NULL; - // Set 'cpoptions' the way we want it. - // FLAG_CPO_BSLASH set - backslashes are *not* treated specially - // FLAG_CPO_KEYCODE set - keycodes are *not* reverse-engineered - // FLAG_CPO_SPECI unset - <Key> sequences *are* interpreted - // The third from end parameter of replace_termcodes() is true so that the - // <lt> sequence is recognised - needed for a real backslash. replace_termcodes((char_u *)str.data, str.size, (char_u **)&ptr, from_part, do_lt, special, CPO_TO_CPO_FLAGS); return cstr_as_string(ptr); } String nvim_command_output(String str, Error *err) + FUNC_API_SINCE(1) { do_cmdline_cmd("redir => v:command_output"); nvim_command(str, err); do_cmdline_cmd("redir END"); - if (err->set) { - return (String) STRING_INIT; + if (ERROR_SET(err)) { + return (String)STRING_INIT; } return cstr_to_string((char *)get_vim_var_str(VV_COMMAND_OUTPUT)); @@ -172,27 +182,30 @@ String nvim_command_output(String str, Error *err) /// @param[out] err Error details, if any /// @return Evaluation result or expanded object Object nvim_eval(String expr, Error *err) + FUNC_API_SINCE(1) { Object rv = OBJECT_INIT; // Evaluate the expression try_start(); - typval_T *expr_result = eval_expr((char_u *)expr.data, NULL); - if (!expr_result) { - api_set_error(err, Exception, _("Failed to evaluate expression")); + typval_T rettv; + if (eval0((char_u *)expr.data, &rettv, NULL, true) == FAIL) { + api_set_error(err, kErrorTypeException, "Failed to evaluate expression"); } if (!try_end(err)) { // No errors, convert the result - rv = vim_to_object(expr_result); + rv = vim_to_object(&rettv); } - // Free the vim object - free_tv(expr_result); + // Free the Vim object + tv_clear(&rettv); + return rv; } -/// Calls a VimL function with the given arguments. +/// Calls a VimL function with the given arguments +/// /// On VimL error: Returns a generic error; v:errmsg is not updated. /// /// @param fname Function to call @@ -200,11 +213,12 @@ Object nvim_eval(String expr, Error *err) /// @param[out] err Error details, if any /// @return Result of the function call Object nvim_call_function(String fname, Array args, Error *err) + FUNC_API_SINCE(1) { Object rv = OBJECT_INIT; if (args.size > MAX_FUNC_ARGS) { - api_set_error(err, Validation, - _("Function called with too many arguments.")); + api_set_error(err, kErrorTypeValidation, + "Function called with too many arguments."); return rv; } @@ -221,27 +235,45 @@ Object nvim_call_function(String fname, Array args, Error *err) // Call the function typval_T rettv; int dummy; - int r = call_func((char_u *) fname.data, (int) fname.size, - &rettv, (int) args.size, vim_args, + int r = call_func((char_u *)fname.data, (int)fname.size, + &rettv, (int)args.size, vim_args, NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy, - true, - NULL, NULL); + true, NULL, NULL); if (r == FAIL) { - api_set_error(err, Exception, _("Error calling function.")); + api_set_error(err, kErrorTypeException, "Error calling function."); } if (!try_end(err)) { rv = vim_to_object(&rettv); } - clear_tv(&rettv); + tv_clear(&rettv); free_vim_args: while (i > 0) { - clear_tv(&vim_args[--i]); + tv_clear(&vim_args[--i]); } return rv; } +/// Execute lua code. Parameters might be passed, they are available inside +/// the chunk as `...`. The chunk can return a value. +/// +/// To evaluate an expression, it must be prefixed with "return ". For +/// instance, to call a lua function with arguments sent in and get its +/// return value back, use the code "return my_function(...)". +/// +/// @param code lua code to execute +/// @param args Arguments to the code +/// @param[out] err Details of an error encountered while parsing +/// or executing the lua code. +/// +/// @return Return value of lua code if present or NIL. +Object nvim_execute_lua(String code, Array args, Error *err) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY +{ + return executor_exec_lua_api(code, args, err); +} + /// Calculates the number of display cells occupied by `text`. /// <Tab> counts as one cell. /// @@ -249,9 +281,10 @@ free_vim_args: /// @param[out] err Error details, if any /// @return Number of cells Integer nvim_strwidth(String str, Error *err) + FUNC_API_SINCE(1) { if (str.size > INT_MAX) { - api_set_error(err, Validation, _("String length is too high")); + api_set_error(err, kErrorTypeValidation, "String length is too high"); return 0; } @@ -262,9 +295,10 @@ Integer nvim_strwidth(String str, Error *err) /// /// @return List of paths ArrayOf(String) nvim_list_runtime_paths(void) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; - uint8_t *rtp = p_rtp; + char_u *rtp = p_rtp; if (*rtp == NUL) { // No paths @@ -278,13 +312,14 @@ ArrayOf(String) nvim_list_runtime_paths(void) } rtp++; } + rv.size++; // Allocate memory for the copies - rv.items = xmalloc(sizeof(Object) * rv.size); + rv.items = xmalloc(sizeof(*rv.items) * rv.size); // Reset the position rtp = p_rtp; // Start copying - for (size_t i = 0; i < rv.size && *rtp != NUL; i++) { + for (size_t i = 0; i < rv.size; i++) { rv.items[i].type = kObjectTypeString; rv.items[i].data.string.data = xmalloc(MAXPATHL); // Copy the path from 'runtimepath' to rv.items[i] @@ -303,21 +338,22 @@ ArrayOf(String) nvim_list_runtime_paths(void) /// @param dir Directory path /// @param[out] err Error details, if any void nvim_set_current_dir(String dir, Error *err) + FUNC_API_SINCE(1) { if (dir.size >= MAXPATHL) { - api_set_error(err, Validation, _("Directory string is too long")); + api_set_error(err, kErrorTypeValidation, "Directory string is too long"); return; } char string[MAXPATHL]; - strncpy(string, dir.data, dir.size); + memcpy(string, dir.data, dir.size); string[dir.size] = NUL; try_start(); - if (vim_chdir((char_u *)string)) { + if (vim_chdir((char_u *)string, kCdScopeGlobal)) { if (!try_end(err)) { - api_set_error(err, Exception, _("Failed to change directory")); + api_set_error(err, kErrorTypeException, "Failed to change directory"); } return; } @@ -331,6 +367,7 @@ void nvim_set_current_dir(String dir, Error *err) /// @param[out] err Error details, if any /// @return Current line string String nvim_get_current_line(Error *err) + FUNC_API_SINCE(1) { return buffer_get_line(curbuf->handle, curwin->w_cursor.lnum - 1, err); } @@ -340,6 +377,7 @@ String nvim_get_current_line(Error *err) /// @param line Line contents /// @param[out] err Error details, if any void nvim_set_current_line(String line, Error *err) + FUNC_API_SINCE(1) { buffer_set_line(curbuf->handle, curwin->w_cursor.lnum - 1, line, err); } @@ -348,6 +386,7 @@ void nvim_set_current_line(String line, Error *err) /// /// @param[out] err Error details, if any void nvim_del_current_line(Error *err) + FUNC_API_SINCE(1) { buffer_del_line(curbuf->handle, curwin->w_cursor.lnum - 1, err); } @@ -358,6 +397,7 @@ void nvim_del_current_line(Error *err) /// @param[out] err Error details, if any /// @return Variable value Object nvim_get_var(String name, Error *err) + FUNC_API_SINCE(1) { return dict_get_value(&globvardict, name, err); } @@ -368,8 +408,9 @@ Object nvim_get_var(String name, Error *err) /// @param value Variable value /// @param[out] err Error details, if any void nvim_set_var(String name, Object value, Error *err) + FUNC_API_SINCE(1) { - dict_set_value(&globvardict, name, value, false, false, err); + dict_set_var(&globvardict, name, value, false, false, err); } /// Removes a global (g:) variable @@ -377,8 +418,9 @@ void nvim_set_var(String name, Object value, Error *err) /// @param name Variable name /// @param[out] err Error details, if any void nvim_del_var(String name, Error *err) + FUNC_API_SINCE(1) { - dict_set_value(&globvardict, name, NIL, true, false, err); + dict_set_var(&globvardict, name, NIL, true, false, err); } /// Sets a global variable @@ -394,7 +436,7 @@ void nvim_del_var(String name, Error *err) /// or if previous value was `v:null`. Object vim_set_var(String name, Object value, Error *err) { - return dict_set_value(&globvardict, name, value, false, true, err); + return dict_set_var(&globvardict, name, value, false, true, err); } /// Removes a global variable @@ -406,7 +448,7 @@ Object vim_set_var(String name, Object value, Error *err) /// @return Old value Object vim_del_var(String name, Error *err) { - return dict_set_value(&globvardict, name, NIL, true, true, err); + return dict_set_var(&globvardict, name, NIL, true, true, err); } /// Gets a v: variable @@ -415,6 +457,7 @@ Object vim_del_var(String name, Error *err) /// @param[out] err Error details, if any /// @return Variable value Object nvim_get_vvar(String name, Error *err) + FUNC_API_SINCE(1) { return dict_get_value(&vimvardict, name, err); } @@ -423,8 +466,9 @@ Object nvim_get_vvar(String name, Error *err) /// /// @param name Option name /// @param[out] err Error details, if any -/// @return Option value +/// @return Option value (global) Object nvim_get_option(String name, Error *err) + FUNC_API_SINCE(1) { return get_option_from(NULL, SREQ_GLOBAL, name, err); } @@ -435,32 +479,38 @@ Object nvim_get_option(String name, Error *err) /// @param value New option value /// @param[out] err Error details, if any void nvim_set_option(String name, Object value, Error *err) + FUNC_API_SINCE(1) { set_option_to(NULL, SREQ_GLOBAL, name, value, err); } -/// Writes a message to vim output buffer +/// Writes a message to the Vim output buffer. Does not append "\n", the +/// message is buffered (won't display) until a linefeed is written. /// /// @param str Message void nvim_out_write(String str) + FUNC_API_SINCE(1) { write_msg(str, false); } -/// Writes a message to vim error buffer +/// Writes a message to the Vim error buffer. Does not append "\n", the +/// message is buffered (won't display) until a linefeed is written. /// /// @param str Message void nvim_err_write(String str) + FUNC_API_SINCE(1) { write_msg(str, true); } -/// Writes a message to vim error buffer. Appends a linefeed to ensure all -/// contents are written. +/// Writes a message to the Vim error buffer. Appends "\n", so the buffer is +/// flushed (and displayed). /// /// @param str Message /// @see nvim_err_write() void nvim_err_writeln(String str) + FUNC_API_SINCE(1) { nvim_err_write(str); nvim_err_write((String) { .data = "\n", .size = 1 }); @@ -470,6 +520,7 @@ void nvim_err_writeln(String str) /// /// @return List of buffer handles ArrayOf(Buffer) nvim_list_bufs(void) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; @@ -491,6 +542,7 @@ ArrayOf(Buffer) nvim_list_bufs(void) /// /// @return Buffer handle Buffer nvim_get_current_buf(void) + FUNC_API_SINCE(1) { return curbuf->handle; } @@ -500,6 +552,7 @@ Buffer nvim_get_current_buf(void) /// @param id Buffer handle /// @param[out] err Error details, if any void nvim_set_current_buf(Buffer buffer, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -511,8 +564,8 @@ void nvim_set_current_buf(Buffer buffer, Error *err) int result = do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, buf->b_fnum, 0); if (!try_end(err) && result == FAIL) { api_set_error(err, - Exception, - _("Failed to switch to buffer %d"), + kErrorTypeException, + "Failed to switch to buffer %d", buffer); } } @@ -521,6 +574,7 @@ void nvim_set_current_buf(Buffer buffer, Error *err) /// /// @return List of window handles ArrayOf(Window) nvim_list_wins(void) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; @@ -542,6 +596,7 @@ ArrayOf(Window) nvim_list_wins(void) /// /// @return Window handle Window nvim_get_current_win(void) + FUNC_API_SINCE(1) { return curwin->handle; } @@ -550,6 +605,7 @@ Window nvim_get_current_win(void) /// /// @param handle Window handle void nvim_set_current_win(Window window, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -561,8 +617,8 @@ void nvim_set_current_win(Window window, Error *err) goto_tabpage_win(win_find_tabpage(win), win); if (!try_end(err) && win != curwin) { api_set_error(err, - Exception, - _("Failed to switch to window %d"), + kErrorTypeException, + "Failed to switch to window %d", window); } } @@ -571,6 +627,7 @@ void nvim_set_current_win(Window window, Error *err) /// /// @return List of tabpage handles ArrayOf(Tabpage) nvim_list_tabpages(void) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; @@ -592,6 +649,7 @@ ArrayOf(Tabpage) nvim_list_tabpages(void) /// /// @return Tabpage handle Tabpage nvim_get_current_tabpage(void) + FUNC_API_SINCE(1) { return curtab->handle; } @@ -601,6 +659,7 @@ Tabpage nvim_get_current_tabpage(void) /// @param handle Tabpage handle /// @param[out] err Error details, if any void nvim_set_current_tabpage(Tabpage tabpage, Error *err) + FUNC_API_SINCE(1) { tabpage_T *tp = find_tab_by_handle(tabpage, err); @@ -612,8 +671,8 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err) goto_tabpage_tp(tp, true, true); if (!try_end(err) && tp != curtab) { api_set_error(err, - Exception, - _("Failed to switch to tabpage %d"), + kErrorTypeException, + "Failed to switch to tabpage %d", tabpage); } } @@ -623,7 +682,7 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err) /// @param channel_id Channel id (passed automatically by the dispatcher) /// @param event Event type string void nvim_subscribe(uint64_t channel_id, String event) - FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { size_t length = (event.size < METHOD_MAXLEN ? event.size : METHOD_MAXLEN); char e[METHOD_MAXLEN + 1]; @@ -637,7 +696,7 @@ void nvim_subscribe(uint64_t channel_id, String event) /// @param channel_id Channel id (passed automatically by the dispatcher) /// @param event Event type string void nvim_unsubscribe(uint64_t channel_id, String event) - FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { size_t length = (event.size < METHOD_MAXLEN ? event.size : @@ -649,11 +708,13 @@ void nvim_unsubscribe(uint64_t channel_id, String event) } Integer nvim_get_color_by_name(String name) + FUNC_API_SINCE(1) { - return name_to_color((uint8_t *)name.data); + return name_to_color((char_u *)name.data); } Dictionary nvim_get_color_map(void) + FUNC_API_SINCE(1) { Dictionary colors = ARRAY_DICT_INIT; @@ -665,8 +726,37 @@ Dictionary nvim_get_color_map(void) } +/// Gets the current mode. +/// mode: Mode string. |mode()| +/// blocking: true if Nvim is waiting for input. +/// +/// @returns Dictionary { "mode": String, "blocking": Boolean } +Dictionary nvim_get_mode(void) + FUNC_API_SINCE(2) FUNC_API_ASYNC +{ + Dictionary rv = ARRAY_DICT_INIT; + char *modestr = get_mode(); + bool blocked = input_blocking(); + + PUT(rv, "mode", STRING_OBJ(cstr_as_string(modestr))); + PUT(rv, "blocking", BOOLEAN_OBJ(blocked)); + + return rv; +} + +/// Get a list of dictionaries describing global (i.e. non-buffer) mappings +/// Note that the "buffer" key will be 0 to represent false. +/// +/// @param mode The abbreviation for the mode +/// @returns An array of maparg() like dictionaries describing mappings +ArrayOf(Dictionary) nvim_get_keymap(String mode) + FUNC_API_SINCE(3) +{ + return keymap_array(mode, NULL); +} + Array nvim_get_api_info(uint64_t channel_id) - FUNC_API_ASYNC FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_ASYNC FUNC_API_REMOTE_ONLY { Array rv = ARRAY_DICT_INIT; @@ -699,7 +789,7 @@ Array nvim_get_api_info(uint64_t channel_id) /// which resulted in an error, the error type and the error message. If an /// error ocurred, the values from all preceding calls will still be returned. Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) - FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { Array rv = ARRAY_DICT_INIT; Array results = ARRAY_DICT_INIT; @@ -709,30 +799,30 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) for (i = 0; i < calls.size; i++) { if (calls.items[i].type != kObjectTypeArray) { api_set_error(err, - Validation, - _("All items in calls array must be arrays")); + kErrorTypeValidation, + "All items in calls array must be arrays"); goto validation_error; } Array call = calls.items[i].data.array; if (call.size != 2) { api_set_error(err, - Validation, - _("All items in calls array must be arrays of size 2")); + kErrorTypeValidation, + "All items in calls array must be arrays of size 2"); goto validation_error; } if (call.items[0].type != kObjectTypeString) { api_set_error(err, - Validation, - _("name must be String")); + kErrorTypeValidation, + "Name must be String"); goto validation_error; } String name = call.items[0].data.string; if (call.items[1].type != kObjectTypeArray) { api_set_error(err, - Validation, - _("args must be Array")); + kErrorTypeValidation, + "Args must be Array"); goto validation_error; } Array args = call.items[1].data.array; @@ -740,7 +830,7 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) MsgpackRpcRequestHandler handler = msgpack_rpc_get_handler_for(name.data, name.size); Object result = handler.fn(channel_id, args, &nested_error); - if (nested_error.set) { + if (ERROR_SET(&nested_error)) { // error handled after loop break; } @@ -749,7 +839,7 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) } ADD(rv, ARRAY_OBJ(results)); - if (nested_error.set) { + if (ERROR_SET(&nested_error)) { Array errval = ARRAY_DICT_INIT; ADD(errval, INTEGER_OBJ((Integer)i)); ADD(errval, INTEGER_OBJ(nested_error.type)); @@ -758,10 +848,12 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) } else { ADD(rv, NIL); } - return rv; + goto theend; validation_error: api_free_array(results); +theend: + api_clear_error(&nested_error); return rv; } @@ -780,7 +872,7 @@ static void write_msg(String message, bool to_err) #define PUSH_CHAR(i, pos, line_buf, msg) \ if (message.data[i] == NL || pos == LINE_BUFFER_SIZE - 1) { \ line_buf[pos] = NUL; \ - msg((uint8_t *)line_buf); \ + msg((char_u *)line_buf); \ pos = 0; \ continue; \ } \ @@ -798,3 +890,57 @@ static void write_msg(String message, bool to_err) --no_wait_return; msg_end(); } + +// Functions used for testing purposes + +/// Returns object given as argument +/// +/// This API function is used for testing. One should not rely on its presence +/// in plugins. +/// +/// @param[in] obj Object to return. +/// +/// @return its argument. +Object nvim__id(Object obj) +{ + return copy_object(obj); +} + +/// Returns array given as argument +/// +/// This API function is used for testing. One should not rely on its presence +/// in plugins. +/// +/// @param[in] arr Array to return. +/// +/// @return its argument. +Array nvim__id_array(Array arr) +{ + return copy_object(ARRAY_OBJ(arr)).data.array; +} + +/// Returns dictionary given as argument +/// +/// This API function is used for testing. One should not rely on its presence +/// in plugins. +/// +/// @param[in] dct Dictionary to return. +/// +/// @return its argument. +Dictionary nvim__id_dictionary(Dictionary dct) +{ + return copy_object(DICTIONARY_OBJ(dct)).data.dictionary; +} + +/// Returns floating-point value given as argument +/// +/// This API function is used for testing. One should not rely on its presence +/// in plugins. +/// +/// @param[in] flt Value to return. +/// +/// @return its argument. +Float nvim__id_float(Float flt) +{ + return flt; +} diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index 1f555a6a05..9bc91ef8fb 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -1,3 +1,6 @@ +// 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 <stdbool.h> #include <stdint.h> #include <stdlib.h> @@ -19,6 +22,7 @@ /// @param[out] err Error details, if any /// @return Buffer handle Buffer nvim_win_get_buf(Window window, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -35,6 +39,7 @@ Buffer nvim_win_get_buf(Window window, Error *err) /// @param[out] err Error details, if any /// @return (row, col) tuple ArrayOf(Integer, 2) nvim_win_get_cursor(Window window, Error *err) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; win_T *win = find_window_by_handle(window, err); @@ -53,18 +58,19 @@ ArrayOf(Integer, 2) nvim_win_get_cursor(Window window, Error *err) /// @param pos (row, col) tuple representing the new position /// @param[out] err Error details, if any void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); - if (pos.size != 2 || pos.items[0].type != kObjectTypeInteger - || pos.items[1].type != kObjectTypeInteger) { - api_set_error(err, - Validation, - _("Argument \"pos\" must be a [row, col] array")); + if (!win) { return; } - if (!win) { + if (pos.size != 2 || pos.items[0].type != kObjectTypeInteger + || pos.items[1].type != kObjectTypeInteger) { + api_set_error(err, + kErrorTypeValidation, + "Argument \"pos\" must be a [row, col] array"); return; } @@ -72,12 +78,12 @@ void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err) int64_t col = pos.items[1].data.integer; if (row <= 0 || row > win->w_buffer->b_ml.ml_line_count) { - api_set_error(err, Validation, _("Cursor position outside buffer")); + api_set_error(err, kErrorTypeValidation, "Cursor position outside buffer"); return; } if (col > MAXCOL || col < 0) { - api_set_error(err, Validation, _("Column value outside range")); + api_set_error(err, kErrorTypeValidation, "Column value outside range"); return; } @@ -99,6 +105,7 @@ void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err) /// @param[out] err Error details, if any /// @return Height as a count of rows Integer nvim_win_get_height(Window window, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -116,6 +123,7 @@ Integer nvim_win_get_height(Window window, Error *err) /// @param height Height as a count of rows /// @param[out] err Error details, if any void nvim_win_set_height(Window window, Integer height, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -124,7 +132,7 @@ void nvim_win_set_height(Window window, Integer height, Error *err) } if (height > INT_MAX || height < INT_MIN) { - api_set_error(err, Validation, _("Height value outside range")); + api_set_error(err, kErrorTypeValidation, "Height value outside range"); return; } @@ -142,6 +150,7 @@ void nvim_win_set_height(Window window, Integer height, Error *err) /// @param[out] err Error details, if any /// @return Width as a count of columns Integer nvim_win_get_width(Window window, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -159,6 +168,7 @@ Integer nvim_win_get_width(Window window, Error *err) /// @param width Width as a count of columns /// @param[out] err Error details, if any void nvim_win_set_width(Window window, Integer width, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -167,7 +177,7 @@ void nvim_win_set_width(Window window, Integer width, Error *err) } if (width > INT_MAX || width < INT_MIN) { - api_set_error(err, Validation, _("Width value outside range")); + api_set_error(err, kErrorTypeValidation, "Width value outside range"); return; } @@ -186,6 +196,7 @@ void nvim_win_set_width(Window window, Integer width, Error *err) /// @param[out] err Error details, if any /// @return Variable value Object nvim_win_get_var(Window window, String name, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -203,6 +214,7 @@ Object nvim_win_get_var(Window window, String name, Error *err) /// @param value Variable value /// @param[out] err Error details, if any void nvim_win_set_var(Window window, String name, Object value, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -210,7 +222,7 @@ void nvim_win_set_var(Window window, String name, Object value, Error *err) return; } - dict_set_value(win->w_vars, name, value, false, false, err); + dict_set_var(win->w_vars, name, value, false, false, err); } /// Removes a window-scoped (w:) variable @@ -219,6 +231,7 @@ void nvim_win_set_var(Window window, String name, Object value, Error *err) /// @param name Variable name /// @param[out] err Error details, if any void nvim_win_del_var(Window window, String name, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -226,7 +239,7 @@ void nvim_win_del_var(Window window, String name, Error *err) return; } - dict_set_value(win->w_vars, name, NIL, true, false, err); + dict_set_var(win->w_vars, name, NIL, true, false, err); } /// Sets a window-scoped (w:) variable @@ -249,7 +262,7 @@ Object window_set_var(Window window, String name, Object value, Error *err) return (Object) OBJECT_INIT; } - return dict_set_value(win->w_vars, name, value, false, true, err); + return dict_set_var(win->w_vars, name, value, false, true, err); } /// Removes a window-scoped (w:) variable @@ -268,7 +281,7 @@ Object window_del_var(Window window, String name, Error *err) return (Object) OBJECT_INIT; } - return dict_set_value(win->w_vars, name, NIL, true, true, err); + return dict_set_var(win->w_vars, name, NIL, true, true, err); } /// Gets a window option value @@ -278,6 +291,7 @@ Object window_del_var(Window window, String name, Error *err) /// @param[out] err Error details, if any /// @return Option value Object nvim_win_get_option(Window window, String name, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -296,6 +310,7 @@ Object nvim_win_get_option(Window window, String name, Error *err) /// @param value Option value /// @param[out] err Error details, if any void nvim_win_set_option(Window window, String name, Object value, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -312,6 +327,7 @@ void nvim_win_set_option(Window window, String name, Object value, Error *err) /// @param[out] err Error details, if any /// @return (row, col) tuple with the window position ArrayOf(Integer, 2) nvim_win_get_position(Window window, Error *err) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; win_T *win = find_window_by_handle(window, err); @@ -330,6 +346,7 @@ ArrayOf(Integer, 2) nvim_win_get_position(Window window, Error *err) /// @param[out] err Error details, if any /// @return Tabpage that contains the window Tabpage nvim_win_get_tabpage(Window window, Error *err) + FUNC_API_SINCE(1) { Tabpage rv = 0; win_T *win = find_window_by_handle(window, err); @@ -347,6 +364,7 @@ Tabpage nvim_win_get_tabpage(Window window, Error *err) /// @param[out] err Error details, if any /// @return Window number Integer nvim_win_get_number(Window window, Error *err) + FUNC_API_SINCE(1) { int rv = 0; win_T *win = find_window_by_handle(window, err); @@ -366,8 +384,11 @@ Integer nvim_win_get_number(Window window, Error *err) /// @param window Window handle /// @return true if the window is valid, false otherwise Boolean nvim_win_is_valid(Window window) + FUNC_API_SINCE(1) { Error stub = ERROR_INIT; - return find_window_by_handle(window, &stub) != NULL; + Boolean ret = find_window_by_handle(window, &stub) != NULL; + api_clear_error(&stub); + return ret; } diff --git a/src/nvim/arabic.c b/src/nvim/arabic.c index db97bd9dc4..1ef51d2a2a 100644 --- a/src/nvim/arabic.c +++ b/src/nvim/arabic.c @@ -1,3 +1,6 @@ +// 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 + /// @file arabic.c /// /// Functions for Arabic language. diff --git a/src/nvim/ascii.h b/src/nvim/ascii.h index 44ff540b40..adde91f9ec 100644 --- a/src/nvim/ascii.h +++ b/src/nvim/ascii.h @@ -8,9 +8,11 @@ // Definitions of various common control characters. -#define CharOrd(x) ((x) < 'a' ? (x) - 'A' : (x) - 'a') -#define CharOrdLow(x) ((x) - 'a') -#define CharOrdUp(x) ((x) - 'A') +#define CharOrd(x) ((uint8_t)(x) < 'a' \ + ? (uint8_t)(x) - 'A'\ + : (uint8_t)(x) - 'a') +#define CharOrdLow(x) ((uint8_t)(x) - 'a') +#define CharOrdUp(x) ((uint8_t)(x) - 'A') #define ROT13(c, a) (((((c) - (a)) + 13) % 26) + (a)) #define NUL '\000' @@ -18,15 +20,14 @@ #define BS '\010' #define TAB '\011' #define NL '\012' -#define NL_STR (char_u *)"\012" +#define NL_STR "\012" #define FF '\014' #define CAR '\015' /* CR is used by Mac OS X */ #define ESC '\033' -#define ESC_STR (char_u *)"\033" -#define ESC_STR_nc "\033" +#define ESC_STR "\033" #define DEL 0x7f -#define DEL_STR (char_u *)"\177" -#define CSI 0x9b /* Control Sequence Introducer */ +#define DEL_STR "\177" +#define CSI 0x9b // Control Sequence Introducer #define CSI_STR "\233" #define DCS 0x90 /* Device Control String */ #define STERM 0x9c /* String Terminator */ diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua index 8d891effae..68a47c244f 100644 --- a/src/nvim/auevents.lua +++ b/src/nvim/auevents.lua @@ -28,6 +28,7 @@ return { 'CursorHoldI', -- idem, in Insert mode 'CursorMoved', -- cursor was moved 'CursorMovedI', -- cursor was moved in Insert mode + 'DirChanged', -- directory changed 'EncodingChanged', -- after changing the 'encoding' option 'FileAppendCmd', -- append to a file using command 'FileAppendPost', -- after appending to a file @@ -89,6 +90,7 @@ return { 'VimLeave', -- before exiting Vim 'VimLeavePre', -- before exiting Vim and writing ShaDa file 'VimResized', -- after Vim window was resized + 'WinNew', -- when entering a new window 'WinEnter', -- after entering a window 'WinLeave', -- before leaving a window }, @@ -101,6 +103,7 @@ return { -- List of neovim-specific events or aliases for the purpose of generating -- syntax file neovim_specific = { + DirChanged=true, TabClosed=true, TabNew=true, TabNewEntered=true, diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index d9fdc80c60..724a8578ac 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1,3 +1,6 @@ +// 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 + /* * buffer.c: functions for dealing with the buffer structure */ @@ -21,6 +24,7 @@ #include <inttypes.h> #include "nvim/api/private/handle.h" +#include "nvim/api/private/helpers.h" #include "nvim/ascii.h" #include "nvim/assert.h" #include "nvim/vim.h" @@ -70,6 +74,12 @@ #include "nvim/os/time.h" #include "nvim/os/input.h" +typedef enum { + kBLSUnchanged = 0, + kBLSChanged = 1, + kBLSDeleted = 2, +} BufhlLineStatus; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "buffer.c.generated.h" #endif @@ -78,6 +88,60 @@ static char *msg_loclist = N_("[Location List]"); static char *msg_qflist = N_("[Quickfix List]"); static char *e_auabort = N_("E855: Autocommands caused command to abort"); +// Number of times free_buffer() was called. +static int buf_free_count = 0; + +// Read data from buffer for retrying. +static int +read_buffer( + int read_stdin, // read file from stdin, otherwise fifo + exarg_T *eap, // for forced 'ff' and 'fenc' or NULL + int flags) // extra flags for readfile() +{ + int retval = OK; + linenr_T line_count; + + // + // Read from the buffer which the text is already filled in and append at + // the end. This makes it possible to retry when 'fileformat' or + // 'fileencoding' was guessed wrong. + // + line_count = curbuf->b_ml.ml_line_count; + retval = readfile( + read_stdin ? NULL : curbuf->b_ffname, + read_stdin ? NULL : curbuf->b_fname, + (linenr_T)line_count, (linenr_T)0, (linenr_T)MAXLNUM, eap, + flags | READ_BUFFER); + if (retval == OK) { + // Delete the binary lines. + while (--line_count >= 0) { + ml_delete((linenr_T)1, false); + } + } else { + // Delete the converted lines. + while (curbuf->b_ml.ml_line_count > line_count) { + ml_delete(line_count, false); + } + } + // Put the cursor on the first line. + curwin->w_cursor.lnum = 1; + curwin->w_cursor.col = 0; + + if (read_stdin) { + // Set or reset 'modified' before executing autocommands, so that + // it can be changed there. + if (!readonlymode && !bufempty()) { + changed(); + } else if (retval != FAIL) { + unchanged(curbuf, false); + } + + apply_autocmds_retval(EVENT_STDINREADPOST, NULL, NULL, false, + curbuf, &retval); + } + return retval; +} + /* * Open current buffer, that is: open the memfile and read the file into * memory. @@ -91,8 +155,9 @@ open_buffer ( ) { int retval = OK; - buf_T *old_curbuf; + bufref_T old_curbuf; long old_tw = curbuf->b_p_tw; + int read_fifo = false; /* * The 'readonly' flag is only set when BF_NEVERLOADED is being reset. @@ -133,23 +198,55 @@ open_buffer ( return FAIL; } - /* The autocommands in readfile() may change the buffer, but only AFTER - * reading the file. */ - old_curbuf = curbuf; - modified_was_set = FALSE; + // The autocommands in readfile() may change the buffer, but only AFTER + // reading the file. + set_bufref(&old_curbuf, curbuf); + modified_was_set = false; /* mark cursor position as being invalid */ curwin->w_valid = 0; if (curbuf->b_ffname != NULL) { int old_msg_silent = msg_silent; +#ifdef UNIX + int save_bin = curbuf->b_p_bin; + int perm; + + perm = os_getperm((const char *)curbuf->b_ffname); + if (perm >= 0 && (0 +# ifdef S_ISFIFO + || S_ISFIFO(perm) +# endif +# ifdef S_ISSOCK + || S_ISSOCK(perm) +# endif +# ifdef OPEN_CHR_FILES + || (S_ISCHR(perm) + && is_dev_fd_file(curbuf->b_ffname)) +# endif + ) + ) { + read_fifo = true; + } + if (read_fifo) { + curbuf->b_p_bin = true; + } +#endif if (shortmess(SHM_FILEINFO)) { msg_silent = 1; } retval = readfile(curbuf->b_ffname, curbuf->b_fname, (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, eap, - flags | READ_NEW); + flags | READ_NEW | (read_fifo ? READ_FIFO : 0)); +#ifdef UNIX + if (read_fifo) { + curbuf->b_p_bin = save_bin; + if (retval == OK) { + retval = read_buffer(false, eap, flags); + } + } +#endif msg_silent = old_msg_silent; // Help buffer is filtered. @@ -158,7 +255,6 @@ open_buffer ( } } else if (read_stdin) { int save_bin = curbuf->b_p_bin; - linenr_T line_count; /* * First read the text in binary mode into the buffer. @@ -172,56 +268,31 @@ open_buffer ( flags | (READ_NEW + READ_STDIN)); curbuf->b_p_bin = save_bin; if (retval == OK) { - line_count = curbuf->b_ml.ml_line_count; - retval = readfile(NULL, NULL, (linenr_T)line_count, - (linenr_T)0, (linenr_T)MAXLNUM, eap, - flags | READ_BUFFER); - if (retval == OK) { - /* Delete the binary lines. */ - while (--line_count >= 0) - ml_delete((linenr_T)1, FALSE); - } else { - /* Delete the converted lines. */ - while (curbuf->b_ml.ml_line_count > line_count) - ml_delete(line_count, FALSE); - } - /* Put the cursor on the first line. */ - curwin->w_cursor.lnum = 1; - curwin->w_cursor.col = 0; - - /* Set or reset 'modified' before executing autocommands, so that - * it can be changed there. */ - if (!readonlymode && !bufempty()) - changed(); - else if (retval != FAIL) - unchanged(curbuf, FALSE); - apply_autocmds_retval(EVENT_STDINREADPOST, NULL, NULL, FALSE, - curbuf, &retval); + retval = read_buffer(true, eap, flags); } } /* if first time loading this buffer, init b_chartab[] */ if (curbuf->b_flags & BF_NEVERLOADED) { - (void)buf_init_chartab(curbuf, FALSE); + (void)buf_init_chartab(curbuf, false); parse_cino(curbuf); } - /* - * Set/reset the Changed flag first, autocmds may change the buffer. - * Apply the automatic commands, before processing the modelines. - * So the modelines have priority over auto commands. - */ - /* When reading stdin, the buffer contents always needs writing, so set - * the changed flag. Unless in readonly mode: "ls | nvim -R -". - * When interrupted and 'cpoptions' contains 'i' set changed flag. */ + // Set/reset the Changed flag first, autocmds may change the buffer. + // Apply the automatic commands, before processing the modelines. + // So the modelines have priority over auto commands. + + // When reading stdin, the buffer contents always needs writing, so set + // the changed flag. Unless in readonly mode: "ls | nvim -R -". + // When interrupted and 'cpoptions' contains 'i' set changed flag. if ((got_int && vim_strchr(p_cpo, CPO_INTMOD) != NULL) - || modified_was_set /* ":set modified" used in autocmd */ - || (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL) - ) + || modified_was_set // ":set modified" used in autocmd + || (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL)) { changed(); - else if (retval != FAIL && !read_stdin) - unchanged(curbuf, FALSE); - save_file_ff(curbuf); /* keep this fileformat */ + } else if (retval != FAIL && !read_stdin && !read_fifo) { + unchanged(curbuf, false); + } + save_file_ff(curbuf); // keep this fileformat /* require "!" to overwrite the file, because it wasn't read completely */ if (aborting()) @@ -246,11 +317,11 @@ open_buffer ( * The autocommands may have changed the current buffer. Apply the * modelines to the correct buffer, if it still exists and is loaded. */ - if (buf_valid(old_curbuf) && old_curbuf->b_ml.ml_mfp != NULL) { + if (bufref_valid(&old_curbuf) && old_curbuf.br_buf->b_ml.ml_mfp != NULL) { aco_save_T aco; - /* Go to the buffer that was opened. */ - aucmd_prepbuf(&aco, old_curbuf); + // Go to the buffer that was opened. + aucmd_prepbuf(&aco, old_curbuf.br_buf); do_modelines(0); curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED); @@ -264,14 +335,45 @@ open_buffer ( return retval; } -/// Check that "buf" points to a valid buffer (in the buffer list). +/// Store "buf" in "bufref" and set the free count. +/// +/// @param bufref Reference to be used for the buffer. +/// @param buf The buffer to reference. +void set_bufref(bufref_T *bufref, buf_T *buf) +{ + bufref->br_buf = buf; + bufref->br_fnum = buf->b_fnum; + bufref->br_buf_free_count = buf_free_count; +} + +/// Return true if "bufref->br_buf" points to the same buffer as when +/// set_bufref() was called and it is a valid buffer. +/// Only goes through the buffer list if buf_free_count changed. +/// Also checks if b_fnum is still the same, a :bwipe followed by :new might get +/// the same allocated memory, but it's a different buffer. +/// +/// @param bufref Buffer reference to check for. +bool bufref_valid(bufref_T *bufref) +{ + return bufref->br_buf_free_count == buf_free_count + ? true + : buf_valid(bufref->br_buf) && bufref->br_fnum == bufref->br_buf->b_fnum; +} + +/// Check that "buf" points to a valid buffer in the buffer list. +/// +/// Can be slow if there are many buffers, prefer using bufref_valid(). +/// +/// @param buf The buffer to check for. bool buf_valid(buf_T *buf) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { if (buf == NULL) { return false; } - FOR_ALL_BUFFERS(bp) { + // Assume that we more often have a recent buffer, + // start with the last one. + for (buf_T *bp = lastbuf; bp != NULL; bp = bp->b_prev) { if (bp == buf) { return true; } @@ -303,6 +405,10 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) bool del_buf = (action == DOBUF_DEL || action == DOBUF_WIPE); bool wipe_buf = (action == DOBUF_WIPE); + bool is_curwin = (curwin != NULL && curwin->w_buffer == buf); + win_T *the_curwin = curwin; + tabpage_T *the_curtab = curtab; + // Force unloading or deleting when 'bufhidden' says so, but not for terminal // buffers. // The caller must take care of NOT deleting/freeing when 'bufhidden' is @@ -326,6 +432,13 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) wipe_buf = true; } + // Disallow deleting the buffer when it is locked (already being closed or + // halfway a command that relies on it). Unloading is allowed. + if (buf->b_locked > 0 && (del_buf || wipe_buf)) { + EMSG(_("E937: Attempt to delete a buffer that is in use")); + return; + } + if (win_valid_any_tab(win)) { // Set b_last_cursor when closing the last window for the buffer. // Remember the last cursor position and window options of the buffer. @@ -339,35 +452,36 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) win->w_cursor.col, TRUE); } + bufref_T bufref; + set_bufref(&bufref, buf); + /* When the buffer is no longer in a window, trigger BufWinLeave */ if (buf->b_nwindows == 1) { - buf->b_closing = true; - apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, - FALSE, buf); - if (!buf_valid(buf)) { - /* Autocommands deleted the buffer. */ + buf->b_locked++; + if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, false, + buf) && !bufref_valid(&bufref)) { + // Autocommands deleted the buffer. EMSG(_(e_auabort)); return; } - buf->b_closing = false; + buf->b_locked--; if (abort_if_last && one_window()) { /* Autocommands made this the only window. */ EMSG(_(e_auabort)); return; } - /* When the buffer becomes hidden, but is not unloaded, trigger - * BufHidden */ + // When the buffer becomes hidden, but is not unloaded, trigger + // BufHidden if (!unload_buf) { - buf->b_closing = true; - apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, - FALSE, buf); - if (!buf_valid(buf)) { - /* Autocommands deleted the buffer. */ + buf->b_locked++; + if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, false, + buf) && !bufref_valid(&bufref)) { + // Autocommands deleted the buffer. EMSG(_(e_auabort)); return; } - buf->b_closing = false; + buf->b_locked--; if (abort_if_last && one_window()) { /* Autocommands made this the only window. */ EMSG(_(e_auabort)); @@ -377,6 +491,16 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) if (aborting()) /* autocmds may abort script processing */ return; } + + // If the buffer was in curwin and the window has changed, go back to that + // window, if it still exists. This avoids that ":edit x" triggering a + // "tabnext" BufUnload autocmd leaves a window behind without a buffer. + if (is_curwin && curwin != the_curwin && win_valid_any_tab(the_curwin)) { + block_autocmds(); + goto_tabpage_win(the_curtab, the_curwin); + unblock_autocmds(); + } + int nwindows = buf->b_nwindows; /* decrease the link count from windows (unless not in any window) */ @@ -390,7 +514,7 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) if (buf->terminal) { terminal_close(buf->terminal, NULL); - } + } /* Always remove the buffer when there is no file name. */ if (buf->b_ffname == NULL) @@ -403,23 +527,29 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) /* Remember if we are closing the current buffer. Restore the number of * windows, so that autocommands in buf_freeall() don't get confused. */ bool is_curbuf = (buf == curbuf); + + // When closing the current buffer stop Visual mode before freeing + // anything. + if (is_curbuf && VIsual_active +#if defined(EXITFREE) + && !entered_free_all_mem +#endif + ) { + end_visual_mode(); + } + buf->b_nwindows = nwindows; buf_freeall(buf, (del_buf ? BFA_DEL : 0) + (wipe_buf ? BFA_WIPE : 0)); - if (win_valid_any_tab(win) && win->w_buffer == buf) { - win->w_buffer = NULL; // make sure we don't use the buffer now - } - /* Autocommands may have deleted the buffer. */ - if (!buf_valid(buf)) + if (!bufref_valid(&bufref)) { + // Autocommands may have deleted the buffer. return; - if (aborting()) /* autocmds may abort script processing */ + } + if (aborting()) { + // Autocmds may abort script processing. return; - - /* Autocommands may have opened or closed windows for this buffer. - * Decrement the count for the close we do here. */ - if (buf->b_nwindows > 0) - --buf->b_nwindows; + } /* * It's possible that autocommands change curbuf to the one being deleted. @@ -431,6 +561,16 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) if (buf == curbuf && !is_curbuf) return; + if (win_valid_any_tab(win) && win->w_buffer == buf) { + win->w_buffer = NULL; // make sure we don't use the buffer now + } + + // Autocommands may have opened or closed windows for this buffer. + // Decrement the count for the close we do here. + if (buf->b_nwindows > 0) { + buf->b_nwindows--; + } + /* Change directories when the 'acd' option is set. */ do_autochdir(); @@ -508,25 +648,32 @@ void buf_freeall(buf_T *buf, int flags) tabpage_T *the_curtab = curtab; // Make sure the buffer isn't closed by autocommands. - buf->b_closing = true; - if (buf->b_ml.ml_mfp != NULL) { - apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, false, buf); - if (!buf_valid(buf)) { // autocommands may delete the buffer - return; - } + buf->b_locked++; + + bufref_T bufref; + set_bufref(&bufref, buf); + + if ((buf->b_ml.ml_mfp != NULL) + && apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, false, buf) + && !bufref_valid(&bufref)) { + // Autocommands deleted the buffer. + return; } - if ((flags & BFA_DEL) && buf->b_p_bl) { - apply_autocmds(EVENT_BUFDELETE, buf->b_fname, buf->b_fname, FALSE, buf); - if (!buf_valid(buf)) /* autocommands may delete the buffer */ - return; + if ((flags & BFA_DEL) + && buf->b_p_bl + && apply_autocmds(EVENT_BUFDELETE, buf->b_fname, buf->b_fname, false, buf) + && !bufref_valid(&bufref)) { + // Autocommands may delete the buffer. + return; } - if (flags & BFA_WIPE) { - apply_autocmds(EVENT_BUFWIPEOUT, buf->b_fname, buf->b_fname, - FALSE, buf); - if (!buf_valid(buf)) /* autocommands may delete the buffer */ - return; + if ((flags & BFA_WIPE) + && apply_autocmds(EVENT_BUFWIPEOUT, buf->b_fname, buf->b_fname, false, + buf) + && !bufref_valid(&bufref)) { + // Autocommands may delete the buffer. + return; } - buf->b_closing = false; + buf->b_locked--; // If the buffer was in curwin and the window has changed, go back to that // window, if it still exists. This avoids that ":edit x" triggering a @@ -548,10 +695,11 @@ void buf_freeall(buf_T *buf, int flags) */ if (buf == curbuf && !is_curbuf) return; - diff_buf_delete(buf); /* Can't use 'diff' for unloaded buffer. */ - /* Remove any ownsyntax, unless exiting. */ - if (firstwin != NULL && curwin->w_buffer == buf) + diff_buf_delete(buf); // Can't use 'diff' for unloaded buffer. + // Remove any ownsyntax, unless exiting. + if (curwin != NULL && curwin->w_buffer == buf) { reset_synblock(curwin); + } /* No folds in an empty buffer. */ FOR_ALL_TAB_WINDOWS(tp, win) { @@ -577,10 +725,11 @@ void buf_freeall(buf_T *buf, int flags) static void free_buffer(buf_T *buf) { handle_unregister_buffer(buf); - free_buffer_stuff(buf, TRUE); + buf_free_count++; + free_buffer_stuff(buf, true); unref_var_dict(buf->b_vars); aubuflocal_remove(buf); - dict_unref(buf->additional_data); + tv_dict_unref(buf->additional_data); clear_fmark(&buf->b_last_cursor); clear_fmark(&buf->b_last_insert); clear_fmark(&buf->b_last_change); @@ -616,8 +765,18 @@ free_buffer_stuff ( free_buf_options(buf, true); ga_clear(&buf->b_s.b_langp); } + { + // Avoid loosing b:changedtick when deleting buffer: clearing variables + // implies using clear_tv() on b:changedtick and that sets changedtick to + // zero. + hashitem_T *const changedtick_hi = hash_find( + &buf->b_vars->dv_hashtab, (const char_u *)"changedtick"); + assert(changedtick_hi != NULL); + hash_remove(&buf->b_vars->dv_hashtab, changedtick_hi); + } vars_clear(&buf->b_vars->dv_hashtab); // free all internal variables hash_init(&buf->b_vars->dv_hashtab); + buf_init_changedtick(buf); uc_clear(&buf->b_ucmds); // clear local user commands buf_delete_signs(buf); // delete any signs bufhl_clear_all(buf); // delete any highligts @@ -650,11 +809,13 @@ static void clear_wininfo(buf_T *buf) */ void goto_buffer(exarg_T *eap, int start, int dir, int count) { - (void)do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO, - start, dir, count, eap->forceit); - buf_T *old_curbuf = curbuf; + bufref_T old_curbuf; + set_bufref(&old_curbuf, curbuf); swap_exists_action = SEA_DIALOG; + (void)do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO, + start, dir, count, eap->forceit); + if (swap_exists_action == SEA_QUIT && *eap->cmd == 's') { cleanup_T cs; @@ -671,18 +832,20 @@ void goto_buffer(exarg_T *eap, int start, int dir, int count) * new aborting error, interrupt, or uncaught exception. */ leave_cleanup(&cs); } else { - handle_swap_exists(old_curbuf); + handle_swap_exists(&old_curbuf); } } -/* - * Handle the situation of swap_exists_action being set. - * It is allowed for "old_curbuf" to be NULL or invalid. - */ -void handle_swap_exists(buf_T *old_curbuf) +/// Handle the situation of swap_exists_action being set. +/// +/// It is allowed for "old_curbuf" to be NULL or invalid. +/// +/// @param old_curbuf The buffer to check for. +void handle_swap_exists(bufref_T *old_curbuf) { cleanup_T cs; long old_tw = curbuf->b_p_tw; + buf_T *buf; if (swap_exists_action == SEA_QUIT) { /* Reset the error/interrupt/exception state here so that @@ -695,13 +858,18 @@ void handle_swap_exists(buf_T *old_curbuf) swap_exists_action = SEA_NONE; // don't want it again swap_exists_did_quit = true; close_buffer(curwin, curbuf, DOBUF_UNLOAD, false); - if (!buf_valid(old_curbuf) || old_curbuf == curbuf) { - old_curbuf = buflist_new(NULL, NULL, 1L, BLN_CURBUF | BLN_LISTED); + if (old_curbuf == NULL + || !bufref_valid(old_curbuf) + || old_curbuf->br_buf == curbuf) { + buf = buflist_new(NULL, NULL, 1L, BLN_CURBUF | BLN_LISTED); + } else { + buf = old_curbuf->br_buf; } - if (old_curbuf != NULL) { - enter_buffer(old_curbuf); - if (old_tw != curbuf->b_p_tw) + if (buf != NULL) { + enter_buffer(buf); + if (old_tw != curbuf->b_p_tw) { check_colorcolumn(curwin); + } } /* If "old_curbuf" is NULL we are in big trouble here... */ @@ -724,7 +892,7 @@ void handle_swap_exists(buf_T *old_curbuf) * new aborting error, interrupt, or uncaught exception. */ leave_cleanup(&cs); } - swap_exists_action = SEA_NONE; + swap_exists_action = SEA_NONE; // -V519 } /* @@ -852,6 +1020,9 @@ static int empty_curbuf(int close_others, int forceit, int action) return FAIL; } + bufref_T bufref; + set_bufref(&bufref, buf); + if (close_others) { /* Close any other windows on this buffer, then make it empty. */ close_windows(buf, TRUE); @@ -861,15 +1032,17 @@ static int empty_curbuf(int close_others, int forceit, int action) retval = do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, forceit ? ECMD_FORCEIT : 0, curwin); - /* - * do_ecmd() may create a new buffer, then we have to delete - * the old one. But do_ecmd() may have done that already, check - * if the buffer still exists. - */ - if (buf != curbuf && buf_valid(buf) && buf->b_nwindows == 0) - close_buffer(NULL, buf, action, FALSE); - if (!close_others) - need_fileinfo = FALSE; + // do_ecmd() may create a new buffer, then we have to delete + // the old one. But do_ecmd() may have done that already, check + // if the buffer still exists. + if (buf != curbuf && bufref_valid(&bufref) && buf->b_nwindows == 0) { + close_buffer(NULL, buf, action, false); + } + + if (!close_others) { + need_fileinfo = false; + } + return retval; } /* @@ -971,6 +1144,8 @@ do_buffer ( */ if (unload) { int forward; + bufref_T bufref; + set_bufref(&bufref, buf); /* When unloading or deleting a buffer that's already unloaded and * unlisted: fail silently. */ @@ -979,15 +1154,16 @@ do_buffer ( if (!forceit && (buf->terminal || bufIsChanged(buf))) { if ((p_confirm || cmdmod.confirm) && p_write && !buf->terminal) { - dialog_changed(buf, FALSE); - if (!buf_valid(buf)) - /* Autocommand deleted buffer, oops! It's not changed - * now. */ + dialog_changed(buf, false); + if (!bufref_valid(&bufref)) { + // Autocommand deleted buffer, oops! It's not changed now. return FAIL; - /* If it's still changed fail silently, the dialog already - * mentioned why it fails. */ - if (bufIsChanged(buf)) + } + // If it's still changed fail silently, the dialog already + // mentioned why it fails. + if (bufIsChanged(buf)) { return FAIL; + } } else { if (buf->terminal) { EMSG2(_("E89: %s will be killed(add ! to override)"), @@ -1001,6 +1177,11 @@ do_buffer ( } } + // When closing the current buffer stop Visual mode. + if (buf == curbuf && VIsual_active) { + end_visual_mode(); + } + /* * If deleting the last (listed) buffer, make it empty. * The last (listed) buffer cannot be unloaded. @@ -1021,9 +1202,9 @@ do_buffer ( * a window with this buffer. */ while (buf == curbuf - && !(curwin->w_closing || curwin->w_buffer->b_closing) - && (firstwin != lastwin || first_tabpage->tp_next != NULL)) { - if (win_close(curwin, FALSE) == FAIL) + && !(curwin->w_closing || curwin->w_buffer->b_locked > 0) + && (!ONE_WINDOW || first_tabpage->tp_next != NULL)) { + if (win_close(curwin, false) == FAIL) break; } @@ -1031,27 +1212,26 @@ do_buffer ( * If the buffer to be deleted is not the current one, delete it here. */ if (buf != curbuf) { - close_windows(buf, FALSE); - if (buf != curbuf && buf_valid(buf) && buf->b_nwindows <= 0) - close_buffer(NULL, buf, action, FALSE); + close_windows(buf, false); + if (buf != curbuf && bufref_valid(&bufref) && buf->b_nwindows <= 0) { + close_buffer(NULL, buf, action, false); + } return OK; } - /* - * Deleting the current buffer: Need to find another buffer to go to. - * There should be another, otherwise it would have been handled - * above. However, autocommands may have deleted all buffers. - * First use au_new_curbuf, if it is valid. - * Then prefer the buffer we most recently visited. - * Else try to find one that is loaded, after the current buffer, - * then before the current buffer. - * Finally use any buffer. - */ - buf = NULL; /* selected buffer */ - bp = NULL; /* used when no loaded buffer found */ - if (au_new_curbuf != NULL && buf_valid(au_new_curbuf)) - buf = au_new_curbuf; - else if (curwin->w_jumplistlen > 0) { + // Deleting the current buffer: Need to find another buffer to go to. + // There should be another, otherwise it would have been handled + // above. However, autocommands may have deleted all buffers. + // First use au_new_curbuf.br_buf, if it is valid. + // Then prefer the buffer we most recently visited. + // Else try to find one that is loaded, after the current buffer, + // then before the current buffer. + // Finally use any buffer. + buf = NULL; // Selected buffer. + bp = NULL; // Used when no loaded buffer found. + if (au_new_curbuf.br_buf != NULL && bufref_valid(&au_new_curbuf)) { + buf = au_new_curbuf.br_buf; + } else if (curwin->w_jumplistlen > 0) { int jumpidx; jumpidx = curwin->w_jumplistidx - 1; @@ -1156,10 +1336,13 @@ do_buffer ( */ if (action == DOBUF_GOTO && !can_abandon(curbuf, forceit)) { if ((p_confirm || cmdmod.confirm) && p_write) { - dialog_changed(curbuf, FALSE); - if (!buf_valid(buf)) - /* Autocommand deleted buffer, oops! */ + bufref_T bufref; + set_bufref(&bufref, buf); + dialog_changed(curbuf, false); + if (!bufref_valid(&bufref)) { + // Autocommand deleted buffer, oops! return FAIL; + } } if (bufIsChanged(curbuf)) { EMSG(_(e_nowrtmsg)); @@ -1207,14 +1390,18 @@ void set_curbuf(buf_T *buf, int action) /* close_windows() or apply_autocmds() may change curbuf */ prevbuf = curbuf; + bufref_T bufref; + set_bufref(&bufref, prevbuf); - apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf); - if (buf_valid(prevbuf) && !aborting()) { - if (prevbuf == curwin->w_buffer) + if (!apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf) + || (bufref_valid(&bufref) && !aborting())) { + if (prevbuf == curwin->w_buffer) { reset_synblock(curwin); - if (unload) - close_windows(prevbuf, FALSE); - if (buf_valid(prevbuf) && !aborting()) { + } + if (unload) { + close_windows(prevbuf, false); + } + if (bufref_valid(&bufref) && !aborting()) { win_T *previouswin = curwin; if (prevbuf == curbuf) u_sync(FALSE); @@ -1278,7 +1465,9 @@ void enter_buffer(buf_T *buf) curwin->w_valid = 0; if (buf->terminal) { - terminal_resize(buf->terminal, curwin->w_width, curwin->w_height); + terminal_resize(buf->terminal, + (uint16_t)curwin->w_width, + (uint16_t)curwin->w_height); } /* Make sure the buffer is loaded. */ @@ -1344,6 +1533,26 @@ void do_autochdir(void) static int top_file_num = 1; ///< highest file number +/// Initialize b:changedtick and changedtick_val attribute +/// +/// @param[out] buf Buffer to intialize for. +static inline void buf_init_changedtick(buf_T *const buf) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL +{ + STATIC_ASSERT(sizeof("changedtick") <= sizeof(buf->changedtick_di.di_key), + "buf->changedtick_di cannot hold large enough keys"); + buf->changedtick_di = (ChangedtickDictItem) { + .di_flags = DI_FLAGS_RO|DI_FLAGS_FIX, // Must not include DI_FLAGS_ALLOC. + .di_tv = (typval_T) { + .v_type = VAR_NUMBER, + .v_lock = VAR_FIXED, + .vval.v_number = buf->b_changedtick, + }, + .di_key = "changedtick", + }; + tv_dict_add(buf->b_vars, (dictitem_T *)&buf->changedtick_di); +} + /// Add a file name to the buffer list. /// If the same file name already exists return a pointer to that buffer. /// If it does not exist, or if fname == NULL, a new entry is created. @@ -1351,6 +1560,8 @@ static int top_file_num = 1; ///< highest file number /// If (flags & BLN_LISTED) is TRUE, add new buffer to buffer list. /// If (flags & BLN_DUMMY) is TRUE, don't count it as a real buffer. /// If (flags & BLN_NEW) is TRUE, don't use an existing buffer. +/// If (flags & BLN_NOOPT) is TRUE, don't copy options from the current buffer +/// if the buffer already exists. /// This is the ONLY way to create a new buffer. /// /// @param ffname full path of fname or relative @@ -1364,7 +1575,7 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags) { buf_T *buf; - fname_expand(curbuf, &ffname, &sfname); /* will allocate ffname */ + fname_expand(curbuf, &ffname, &sfname); // will allocate ffname /* * If file name already exists in the list, update the entry. @@ -1378,16 +1589,20 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags) && (buf = buflist_findname_file_id(ffname, &file_id, file_id_valid)) != NULL) { xfree(ffname); - if (lnum != 0) - buflist_setfpos(buf, curwin, lnum, (colnr_T)0, FALSE); - /* copy the options now, if 'cpo' doesn't have 's' and not done - * already */ - buf_copy_options(buf, 0); + if (lnum != 0) { + buflist_setfpos(buf, curwin, lnum, (colnr_T)0, false); + } + if ((flags & BLN_NOOPT) == 0) { + // Copy the options now, if 'cpo' doesn't have 's' and not done already. + buf_copy_options(buf, 0); + } if ((flags & BLN_LISTED) && !buf->b_p_bl) { - buf->b_p_bl = TRUE; + buf->b_p_bl = true; + bufref_T bufref; + set_bufref(&bufref, buf); if (!(flags & BLN_DUMMY)) { - apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf); - if (!buf_valid(buf)) { + if (apply_autocmds(EVENT_BUFADD, NULL, NULL, false, buf) + && !bufref_valid(&bufref)) { return NULL; } } @@ -1427,8 +1642,9 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags) if (buf != curbuf || curbuf == NULL) { buf = xcalloc(1, sizeof(buf_T)); // init b: variables - buf->b_vars = dict_alloc(); + buf->b_vars = tv_dict_alloc(); init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE); + buf_init_changedtick(buf); } if (ffname != NULL) { @@ -1520,18 +1736,21 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags) // Tricky: these autocommands may change the buffer list. They could also // split the window with re-using the one empty buffer. This may result in // unexpectedly losing the empty buffer. - apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, buf); - if (!buf_valid(buf)) { + bufref_T bufref; + set_bufref(&bufref, buf); + if (apply_autocmds(EVENT_BUFNEW, NULL, NULL, false, buf) + && !bufref_valid(&bufref)) { return NULL; } - if (flags & BLN_LISTED) { - apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf); - if (!buf_valid(buf)) { - return NULL; - } + if ((flags & BLN_LISTED) + && apply_autocmds(EVENT_BUFADD, NULL, NULL, false, buf) + && !bufref_valid(&bufref)) { + return NULL; } - if (aborting()) /* autocmds may abort script processing */ + if (aborting()) { + // Autocmds may abort script processing. return NULL; + } } return buf; @@ -1555,6 +1774,7 @@ void free_buf_options(buf_T *buf, int free_p_ff) clear_string_option(&buf->b_p_inex); clear_string_option(&buf->b_p_inde); clear_string_option(&buf->b_p_indk); + clear_string_option(&buf->b_p_fp); clear_string_option(&buf->b_p_fex); clear_string_option(&buf->b_p_kp); clear_string_option(&buf->b_p_mps); @@ -1597,16 +1817,15 @@ void free_buf_options(buf_T *buf, int free_p_ff) clear_string_option(&buf->b_p_bkc); } -/* - * get alternate file n - * set linenr to lnum or altfpos.lnum if lnum == 0 - * also set cursor column to altfpos.col if 'startofline' is not set. - * if (options & GETF_SETMARK) call setpcmark() - * if (options & GETF_ALT) we are jumping to an alternate file. - * if (options & GETF_SWITCH) respect 'switchbuf' settings when jumping - * - * return FAIL for failure, OK for success - */ + +/// Get alternate file "n". +/// Set linenr to "lnum" or altfpos.lnum if "lnum" == 0. +/// Also set cursor column to altfpos.col if 'startofline' is not set. +/// if (options & GETF_SETMARK) call setpcmark() +/// if (options & GETF_ALT) we are jumping to an alternate file. +/// if (options & GETF_SWITCH) respect 'switchbuf' settings when jumping +/// +/// Return FAIL for failure, OK for success. int buflist_getfile(int n, linenr_T lnum, int options, int forceit) { buf_T *buf; @@ -1687,9 +1906,7 @@ int buflist_getfile(int n, linenr_T lnum, int options, int forceit) return FAIL; } -/* - * go to the last know line number for the current buffer - */ +// Go to the last known line number for the current buffer. void buflist_getfpos(void) { pos_T *fpos; @@ -1754,7 +1971,8 @@ buf_T *buflist_findname(char_u *ffname) static buf_T *buflist_findname_file_id(char_u *ffname, FileID *file_id, bool file_id_valid) { - FOR_ALL_BUFFERS(buf) { + // Start at the last buffer, expect to find a match sooner. + FOR_ALL_BUFFERS_BACKWARDS(buf) { if ((buf->b_flags & BF_DUMMY) == 0 && !otherfile_buf(buf, ffname, file_id, file_id_valid)) { return buf; @@ -1828,7 +2046,7 @@ int buflist_findpat( return -1; } - FOR_ALL_BUFFERS(buf) { + FOR_ALL_BUFFERS_BACKWARDS(buf) { if (buf->b_p_bl == find_listed && (!diffmode || diff_mode_buf(buf)) && buflist_match(®match, buf, false) != NULL) { @@ -1942,7 +2160,7 @@ int ExpandBufnames(char_u *pat, int *num_file, char_u ***file, int options) if (count == 0) /* no match found, break here */ break; if (round == 1) { - *file = xmalloc(count * sizeof(**file)); + *file = xmalloc((size_t)count * sizeof(**file)); } } vim_regfree(regmatch.regprog); @@ -1997,21 +2215,14 @@ static char_u *fname_match(regmatch_T *rmp, char_u *name, bool ignore_case) return match; } -/* - * find file in buffer list by number - */ +/// Find a file in the buffer list by buffer number. buf_T *buflist_findnr(int nr) { if (nr == 0) { nr = curwin->w_alt_fnum; } - FOR_ALL_BUFFERS(buf) { - if (buf->b_fnum == nr) { - return buf; - } - } - return NULL; + return handle_get_buffer((handle_T)nr); } /* @@ -2169,7 +2380,7 @@ void get_winopts(buf_T *buf) /* Set 'foldlevel' to 'foldlevelstart' if it's not negative. */ if (p_fdls >= 0) curwin->w_p_fdl = p_fdls; - check_colorcolumn(curwin); + didset_window_options(curwin); } /* @@ -2193,9 +2404,7 @@ linenr_T buflist_findlnum(buf_T *buf) return buflist_findfpos(buf)->lnum; } -/* - * List all know file names (for :files and :buffers command). - */ +// List all known file names (for :files and :buffers command). void buflist_list(exarg_T *eap) { buf_T *buf; @@ -2220,12 +2429,17 @@ void buflist_list(exarg_T *eap) && (buf == curbuf || curwin->w_alt_fnum != buf->b_fnum))) { continue; } - msg_putchar('\n'); - if (buf_spname(buf) != NULL) + if (buf_spname(buf) != NULL) { STRLCPY(NameBuff, buf_spname(buf), MAXPATHL); - else - home_replace(buf, buf->b_fname, NameBuff, MAXPATHL, TRUE); + } else { + home_replace(buf, buf->b_fname, NameBuff, MAXPATHL, true); + } + if (message_filtered(NameBuff)) { + continue; + } + + msg_putchar('\n'); len = vim_snprintf((char *)IObuff, IOSIZE - 20, "%3d%c%c%c%c%c \"%s\"", buf->b_fnum, buf->b_p_bl ? ' ' : 'u', @@ -2579,7 +2793,7 @@ fileinfo ( else name = curbuf->b_ffname; home_replace(shorthelp ? curbuf : NULL, name, p, - (int)(IOSIZE - (p - buffer)), TRUE); + (size_t)(IOSIZE - (p - buffer)), true); } vim_snprintf_add((char *)buffer, IOSIZE, "\"%s%s%s%s%s%s", @@ -2689,9 +2903,10 @@ void maketitle(void) if (p_title) { if (p_titlelen > 0) { - maxlen = p_titlelen * Columns / 100; - if (maxlen < 10) + maxlen = (int)(p_titlelen * Columns / 100); + if (maxlen < 10) { maxlen = 10; + } } t_str = buf; @@ -2743,7 +2958,7 @@ void maketitle(void) buf[off++] = ' '; buf[off++] = '('; home_replace(curbuf, curbuf->b_ffname, - buf + off, SPACE_FOR_DIR - off, TRUE); + buf + off, (size_t)(SPACE_FOR_DIR - off), true); #ifdef BACKSLASH_IN_FILENAME /* avoid "c:/name" to be reduced to "c" */ if (isalpha(buf[off]) && buf[off + 1] == ':') @@ -2850,13 +3065,13 @@ static bool ti_change(char_u *str, char_u **last) return false; } -/* - * Put current window title back (used after calling a shell) - */ + +/// Set current window title void resettitle(void) { - ui_set_title((char *)lasttitle); - ui_set_icon((char *)lasticon); + ui_call_set_title(cstr_as_string((char *)lasttitle)); + ui_call_set_icon(cstr_as_string((char *)lasticon)); + ui_flush(); } # if defined(EXITFREE) @@ -2908,13 +3123,13 @@ int build_stl_str_hl( size_t outlen, char_u *fmt, int use_sandbox, - int fillchar, + char_u fillchar, int maxwidth, struct stl_hlrec *hltab, StlClickRecord *tabtab ) { - int groupitem[STL_MAX_ITEM]; + int groupitems[STL_MAX_ITEM]; struct stl_item { // Where the item starts in the status line output buffer char_u *start; @@ -2934,7 +3149,7 @@ int build_stl_str_hl( ClickFunc, Trunc } type; - } item[STL_MAX_ITEM]; + } items[STL_MAX_ITEM]; #define TMPLEN 70 char_u tmp[TMPLEN]; char_u *usefmt = fmt; @@ -3036,16 +3251,16 @@ int build_stl_str_hl( if (groupdepth > 0) { continue; } - item[curitem].type = Separate; - item[curitem++].start = out_p; + items[curitem].type = Separate; + items[curitem++].start = out_p; continue; } // STL_TRUNCMARK: Where to begin truncating if the statusline is too long. if (*fmt_p == STL_TRUNCMARK) { fmt_p++; - item[curitem].type = Trunc; - item[curitem++].start = out_p; + items[curitem].type = Trunc; + items[curitem++].start = out_p; continue; } @@ -3061,7 +3276,7 @@ int build_stl_str_hl( // Determine how long the group is. // Note: We set the current output position to null // so `vim_strsize` will work. - char_u *t = item[groupitem[groupdepth]].start; + char_u *t = items[groupitems[groupdepth]].start; *out_p = NUL; long group_len = vim_strsize(t); @@ -3071,11 +3286,11 @@ int build_stl_str_hl( // move the output pointer back to where the group started. // Note: This erases any non-item characters that were in the group. // Otherwise there would be no reason to do this step. - if (curitem > groupitem[groupdepth] + 1 - && item[groupitem[groupdepth]].minwid == 0) { + if (curitem > groupitems[groupdepth] + 1 + && items[groupitems[groupdepth]].minwid == 0) { bool has_normal_items = false; - for (long n = groupitem[groupdepth] + 1; n < curitem; n++) { - if (item[n].type == Normal || item[n].type == Highlight) { + for (long n = groupitems[groupdepth] + 1; n < curitem; n++) { + if (items[n].type == Normal || items[n].type == Highlight) { has_normal_items = true; break; } @@ -3089,18 +3304,18 @@ int build_stl_str_hl( // If the group is longer than it is allowed to be // truncate by removing bytes from the start of the group text. - if (group_len > item[groupitem[groupdepth]].maxwid) { + if (group_len > items[groupitems[groupdepth]].maxwid) { // { Determine the number of bytes to remove long n; if (has_mbyte) { /* Find the first character that should be included. */ n = 0; - while (group_len >= item[groupitem[groupdepth]].maxwid) { + while (group_len >= items[groupitems[groupdepth]].maxwid) { group_len -= ptr2cells(t + n); n += (*mb_ptr2len)(t + n); } } else { - n = (long)(out_p - t) - item[groupitem[groupdepth]].maxwid + 1; + n = (long)(out_p - t) - items[groupitems[groupdepth]].maxwid + 1; } // } @@ -3110,25 +3325,26 @@ int build_stl_str_hl( // { Move the truncated output memmove(t + 1, t + n, (size_t)(out_p - (t + n))); out_p = out_p - n + 1; - /* Fill up space left over by half a double-wide char. */ - while (++group_len < item[groupitem[groupdepth]].minwid) + // Fill up space left over by half a double-wide char. + while (++group_len < items[groupitems[groupdepth]].minwid) { *out_p++ = fillchar; + } // } - /* correct the start of the items for the truncation */ - for (int idx = groupitem[groupdepth] + 1; idx < curitem; idx++) { + // correct the start of the items for the truncation + for (int idx = groupitems[groupdepth] + 1; idx < curitem; idx++) { // Shift everything back by the number of removed bytes - item[idx].start -= n; + items[idx].start -= n; // If the item was partially or completely truncated, set its // start to the start of the group - if (item[idx].start < t) { - item[idx].start = t; + if (items[idx].start < t) { + items[idx].start = t; } } // If the group is shorter than the minimum width, add padding characters. - } else if (abs(item[groupitem[groupdepth]].minwid) > group_len) { - long min_group_width = item[groupitem[groupdepth]].minwid; + } else if (abs(items[groupitems[groupdepth]].minwid) > group_len) { + long min_group_width = items[groupitems[groupdepth]].minwid; // If the group is left-aligned, add characters to the right. if (min_group_width < 0) { min_group_width = 0 - min_group_width; @@ -3147,8 +3363,8 @@ int build_stl_str_hl( // } // Adjust item start positions - for (int n = groupitem[groupdepth] + 1; n < curitem; n++) { - item[n].start += group_len; + for (int n = groupitems[groupdepth] + 1; n < curitem; n++) { + items[n].start += group_len; } // Prepend the fill characters @@ -3186,9 +3402,9 @@ int build_stl_str_hl( // User highlight groups override the min width field // to denote the styling to use. if (*fmt_p == STL_USER_HL) { - item[curitem].type = Highlight; - item[curitem].start = out_p; - item[curitem].minwid = minwid > 9 ? 1 : minwid; + items[curitem].type = Highlight; + items[curitem].start = out_p; + items[curitem].minwid = minwid > 9 ? 1 : minwid; fmt_p++; curitem++; continue; @@ -3220,20 +3436,21 @@ int build_stl_str_hl( if (*fmt_p == STL_TABPAGENR || *fmt_p == STL_TABCLOSENR) { if (*fmt_p == STL_TABCLOSENR) { if (minwid == 0) { - /* %X ends the close label, go back to the previously - * define tab label nr. */ - for (long n = curitem - 1; n >= 0; --n) - if (item[n].type == TabPage && item[n].minwid >= 0) { - minwid = item[n].minwid; + // %X ends the close label, go back to the previous tab label nr. + for (long n = curitem - 1; n >= 0; n--) { + if (items[n].type == TabPage && items[n].minwid >= 0) { + minwid = items[n].minwid; break; } - } else - /* close nrs are stored as negative values */ + } + } else { + // close nrs are stored as negative values minwid = -minwid; + } } - item[curitem].type = TabPage; - item[curitem].start = out_p; - item[curitem].minwid = minwid; + items[curitem].type = TabPage; + items[curitem].start = out_p; + items[curitem].minwid = minwid; fmt_p++; curitem++; continue; @@ -3248,10 +3465,10 @@ int build_stl_str_hl( if (*fmt_p != STL_CLICK_FUNC) { break; } - item[curitem].type = ClickFunc; - item[curitem].start = out_p; - item[curitem].cmd = xmemdupz(t, (size_t) (((char *) fmt_p - t))); - item[curitem].minwid = minwid; + items[curitem].type = ClickFunc; + items[curitem].start = out_p; + items[curitem].cmd = xmemdupz(t, (size_t)(((char *)fmt_p - t))); + items[curitem].minwid = minwid; fmt_p++; curitem++; continue; @@ -3274,11 +3491,11 @@ int build_stl_str_hl( // Denotes the start of a new group if (*fmt_p == '(') { - groupitem[groupdepth++] = curitem; - item[curitem].type = Group; - item[curitem].start = out_p; - item[curitem].minwid = minwid; - item[curitem].maxwid = maxwid; + groupitems[groupdepth++] = curitem; + items[curitem].type = Group; + items[curitem].start = out_p; + items[curitem].minwid = minwid; + items[curitem].maxwid = maxwid; fmt_p++; curitem++; continue; @@ -3305,7 +3522,7 @@ int build_stl_str_hl( case STL_FULLPATH: case STL_FILENAME: { - // Set fillable to false to that ' ' in the filename will not + // Set fillable to false so that ' ' in the filename will not // get replaced with the fillchar fillable = false; if (buf_spname(wp->w_buffer) != NULL) { @@ -3358,7 +3575,7 @@ int build_stl_str_hl( curbuf = o_curbuf; // Remove the variable we just stored - do_unlet((char_u *)"g:actual_curbuf", true); + do_unlet(S_LEN("g:actual_curbuf"), true); // } @@ -3440,7 +3657,7 @@ int build_stl_str_hl( case STL_KEYMAP: fillable = false; - if (get_keymap_str(wp, tmp, TMPLEN)) + if (get_keymap_str(wp, (char_u *)"<%s>", tmp, TMPLEN)) str = tmp; break; case STL_PAGENUM: @@ -3453,6 +3670,7 @@ int build_stl_str_hl( case STL_OFFSET_X: base = kNumBaseHexadecimal; + // fallthrough case STL_OFFSET: { long l = ml_find_line_or_offset(wp->w_buffer, wp->w_cursor.lnum, NULL); @@ -3463,6 +3681,7 @@ int build_stl_str_hl( } case STL_BYTEVAL_X: base = kNumBaseHexadecimal; + // fallthrough case STL_BYTEVAL: num = byteval; if (num == NL) @@ -3510,7 +3729,7 @@ int build_stl_str_hl( wp->w_buffer->b_p_ft); // Uppercase the file extension for (char_u *t = tmp; *t != 0; t++) { - *t = TOUPPER_LOC(*t); + *t = (char_u)TOUPPER_LOC(*t); } str = tmp; } @@ -3557,9 +3776,9 @@ int build_stl_str_hl( // Create a highlight item based on the name if (*fmt_p == '#') { - item[curitem].type = Highlight; - item[curitem].start = out_p; - item[curitem].minwid = -syn_namen2id(t, (int)(fmt_p - t)); + items[curitem].type = Highlight; + items[curitem].start = out_p; + items[curitem].minwid = -syn_namen2id(t, (int)(fmt_p - t)); curitem++; fmt_p++; } @@ -3570,8 +3789,8 @@ int build_stl_str_hl( // If we made it this far, the item is normal and starts at // our current position in the output buffer. // Non-normal items would have `continued`. - item[curitem].start = out_p; - item[curitem].type = Normal; + items[curitem].start = out_p; + items[curitem].type = Normal; // Copy the item string into the output buffer if (str != NULL && *str) { @@ -3687,7 +3906,8 @@ int build_stl_str_hl( } // } - size_t remaining_buf_len = (out_end_p - out_p) + 1; + assert(out_end_p >= out_p); + size_t remaining_buf_len = (size_t)(out_end_p - out_p) + 1; // If the number is going to take up too much room // Figure out the approximate number in "scientific" type notation. @@ -3702,7 +3922,7 @@ int build_stl_str_hl( // { Reduce the number by base^n while (num_chars-- > maxwid) { - num /= base; + num /= (long)base; } // } @@ -3727,7 +3947,7 @@ int build_stl_str_hl( // Otherwise, there was nothing to print so mark the item as empty } else { - item[curitem].type = Empty; + items[curitem].type = Empty; } // Only free the string buffer if we allocated it. @@ -3752,8 +3972,7 @@ int build_stl_str_hl( } // We have now processed the entire statusline format string. - // What follows is post-processing to handle alignment and - // highlighting factors. + // What follows is post-processing to handle alignment and highlighting. int width = vim_strsize(out); if (maxwidth > 0 && width > maxwidth) { @@ -3768,16 +3987,17 @@ int build_stl_str_hl( // Otherwise, look for the truncation item } else { // Default to truncating at the first item - trunc_p = item[0].start; + trunc_p = items[0].start; item_idx = 0; - for (int i = 0; i < itemcnt; i++) - if (item[i].type == Trunc) { - // Truncate at %< item. - trunc_p = item[i].start; + for (int i = 0; i < itemcnt; i++) { + if (items[i].type == Trunc) { + // Truncate at %< items. + trunc_p = items[i].start; item_idx = i; break; } + } } // If the truncation point we found is beyond the maximum @@ -3807,7 +4027,7 @@ int build_stl_str_hl( // Ignore any items in the statusline that occur after // the truncation point for (int i = 0; i < itemcnt; i++) { - if (item[i].start > trunc_p) { + if (items[i].start > trunc_p) { itemcnt = i; break; } @@ -3862,12 +4082,12 @@ int build_stl_str_hl( for (int i = item_idx; i < itemcnt; i++) { // Items starting at or after the end of the truncated section need // to be moved backwards. - if (item[i].start >= trunc_end_p) { - item[i].start -= item_offset; + if (items[i].start >= trunc_end_p) { + items[i].start -= item_offset; // Anything inside the truncated area is set to start // at the `<` truncation character. } else { - item[i].start = trunc_p; + items[i].start = trunc_p; } } // } @@ -3878,12 +4098,12 @@ int build_stl_str_hl( // add characters at the separate marker (if there is one) to // fill up the available space. } else if (width < maxwidth - && STRLEN(out) + maxwidth - width + 1 < outlen) { + && STRLEN(out) + (size_t)(maxwidth - width) + 1 < outlen) { // Find how many separators there are, which we will use when // figuring out how many groups there are. int num_separators = 0; for (int i = 0; i < itemcnt; i++) { - if (item[i].type == Separate) { + if (items[i].type == Separate) { num_separators++; } } @@ -3895,7 +4115,7 @@ int build_stl_str_hl( int separator_locations[STL_MAX_ITEM]; int index = 0; for (int i = 0; i < itemcnt; i++) { - if (item[i].type == Separate) { + if (items[i].type == Separate) { separator_locations[index] = i; index++; } @@ -3906,18 +4126,18 @@ int build_stl_str_hl( standard_spaces * (num_separators - 1); for (int i = 0; i < num_separators; i++) { - int dislocation = (i == (num_separators - 1)) ? - final_spaces : standard_spaces; - char_u *sep_loc = item[separator_locations[i]].start + dislocation; - STRMOVE(sep_loc, item[separator_locations[i]].start); - for (char_u *s = item[separator_locations[i]].start; s < sep_loc; s++) { + int dislocation = (i == (num_separators - 1)) + ? final_spaces : standard_spaces; + char_u *seploc = items[separator_locations[i]].start + dislocation; + STRMOVE(seploc, items[separator_locations[i]].start); + for (char_u *s = items[separator_locations[i]].start; s < seploc; s++) { *s = fillchar; } for (int item_idx = separator_locations[i] + 1; item_idx < itemcnt; item_idx++) { - item[item_idx].start += dislocation; + items[item_idx].start += dislocation; } } @@ -3929,9 +4149,9 @@ int build_stl_str_hl( if (hltab != NULL) { struct stl_hlrec *sp = hltab; for (long l = 0; l < itemcnt; l++) { - if (item[l].type == Highlight) { - sp->start = item[l].start; - sp->userhl = item[l].minwid; + if (items[l].type == Highlight) { + sp->start = items[l].start; + sp->userhl = items[l].minwid; sp++; } } @@ -3943,14 +4163,14 @@ int build_stl_str_hl( if (tabtab != NULL) { StlClickRecord *cur_tab_rec = tabtab; for (long l = 0; l < itemcnt; l++) { - if (item[l].type == TabPage) { - cur_tab_rec->start = (char *) item[l].start; - if (item[l].minwid == 0) { + if (items[l].type == TabPage) { + cur_tab_rec->start = (char *)items[l].start; + if (items[l].minwid == 0) { cur_tab_rec->def.type = kStlClickDisabled; cur_tab_rec->def.tabnr = 0; } else { - int tabnr = item[l].minwid; - if (item[l].minwid > 0) { + int tabnr = items[l].minwid; + if (items[l].minwid > 0) { cur_tab_rec->def.type = kStlClickTabSwitch; } else { cur_tab_rec->def.type = kStlClickTabClose; @@ -3960,11 +4180,11 @@ int build_stl_str_hl( } cur_tab_rec->def.func = NULL; cur_tab_rec++; - } else if (item[l].type == ClickFunc) { - cur_tab_rec->start = (char *) item[l].start; + } else if (items[l].type == ClickFunc) { + cur_tab_rec->start = (char *)items[l].start; cur_tab_rec->def.type = kStlClickFuncRun; - cur_tab_rec->def.tabnr = item[l].minwid; - cur_tab_rec->def.func = item[l].cmd; + cur_tab_rec->def.tabnr = items[l].minwid; + cur_tab_rec->def.func = items[l].cmd; cur_tab_rec++; } } @@ -4059,14 +4279,12 @@ void fname_expand(buf_T *buf, char_u **ffname, char_u **sfname) #ifdef WIN32 if (!buf->b_p_bin) { - char_u *rfname; - // If the file name is a shortcut file, use the file it links to. - rfname = os_resolve_shortcut(*ffname); + char *rfname = os_resolve_shortcut((const char *)(*ffname)); if (rfname != NULL) { xfree(*ffname); - *ffname = rfname; - *sfname = rfname; + *ffname = (char_u *)rfname; + *sfname = (char_u *)rfname; } } #endif @@ -4116,6 +4334,8 @@ do_arg_all ( win_T *new_curwin = NULL; tabpage_T *new_curtab = NULL; + assert(firstwin != NULL); // satisfy coverity + if (ARGCOUNT <= 0) { /* Don't give an error message. We don't want it when the ":all" * command is in the .vimrc. */ @@ -4124,7 +4344,7 @@ do_arg_all ( setpcmark(); opened_len = ARGCOUNT; - opened = xcalloc(opened_len, 1); + opened = xcalloc((size_t)opened_len, 1); /* Autocommands may do anything to the argument list. Make sure it's not * freed while we are working here by "locking" it. We still have to @@ -4198,24 +4418,27 @@ do_arg_all ( || !bufIsChanged(buf)) { /* If the buffer was changed, and we would like to hide it, * try autowriting. */ - if (!P_HID(buf) && buf->b_nwindows <= 1 - && bufIsChanged(buf)) { - (void)autowrite(buf, FALSE); - /* check if autocommands removed the window */ - if (!win_valid(wp) || !buf_valid(buf)) { - wpnext = firstwin; /* start all over... */ + if (!P_HID(buf) && buf->b_nwindows <= 1 && bufIsChanged(buf)) { + bufref_T bufref; + set_bufref(&bufref, buf); + (void)autowrite(buf, false); + // Check if autocommands removed the window. + if (!win_valid(wp) || !bufref_valid(&bufref)) { + wpnext = firstwin; // Start all over... continue; } } - /* don't close last window */ - if (firstwin == lastwin - && (first_tabpage->tp_next == NULL || !had_tab)) - use_firstwin = TRUE; - else { + // don't close last window + if (ONE_WINDOW + && (first_tabpage->tp_next == NULL || !had_tab)) { + use_firstwin = true; + } else { win_close(wp, !P_HID(buf) && !bufIsChanged(buf)); - /* check if autocommands removed the next window */ - if (!win_valid(wpnext)) - wpnext = firstwin; /* start all over... */ + // check if autocommands removed the next window + if (!win_valid(wpnext)) { + // start all over... + wpnext = firstwin; + } } } } @@ -4306,19 +4529,23 @@ do_arg_all ( /* Remove the "lock" on the argument list. */ alist_unlink(alist); - --autocmd_no_enter; - /* restore last referenced tabpage's curwin */ + autocmd_no_enter--; + // restore last referenced tabpage's curwin if (last_curtab != new_curtab) { - if (valid_tabpage(last_curtab)) - goto_tabpage_tp(last_curtab, TRUE, TRUE); - if (win_valid(last_curwin)) + if (valid_tabpage(last_curtab)) { + goto_tabpage_tp(last_curtab, true, true); + } + if (win_valid(last_curwin)) { win_enter(last_curwin, false); + } + } + // to window with first arg + if (valid_tabpage(new_curtab)) { + goto_tabpage_tp(new_curtab, true, true); } - /* to window with first arg */ - if (valid_tabpage(new_curtab)) - goto_tabpage_tp(new_curtab, TRUE, TRUE); - if (win_valid(new_curwin)) + if (win_valid(new_curwin)) { win_enter(new_curwin, false); + } --autocmd_no_leave; xfree(opened); @@ -4335,8 +4562,8 @@ void ex_buffer_all(exarg_T *eap) bool p_ea_save; int open_wins = 0; int r; - int count; /* Maximum number of windows to open. */ - int all; /* When TRUE also load inactive buffers. */ + long count; // Maximum number of windows to open. + int all; // When TRUE also load inactive buffers. int had_tab = cmdmod.tab; tabpage_T *tpnext; @@ -4367,9 +4594,9 @@ void ex_buffer_all(exarg_T *eap) ? wp->w_height + wp->w_status_height < Rows - p_ch - tabline_height() : wp->w_width != Columns) - || (had_tab > 0 && wp != firstwin) - ) && firstwin != lastwin - && !(wp->w_closing || wp->w_buffer->b_closing) + || (had_tab > 0 && wp != firstwin)) + && !ONE_WINDOW + && !(wp->w_closing || wp->w_buffer->b_locked > 0) ) { win_close(wp, FALSE); wpnext = firstwin; /* just in case an autocommand does @@ -4417,7 +4644,9 @@ void ex_buffer_all(exarg_T *eap) } if (wp == NULL && split_ret == OK) { - /* Split the window and put the buffer in it */ + bufref_T bufref; + set_bufref(&bufref, buf); + // Split the window and put the buffer in it. p_ea_save = p_ea; p_ea = true; /* use space from all windows */ split_ret = win_split(0, WSP_ROOM | WSP_BELOW); @@ -4429,7 +4658,8 @@ void ex_buffer_all(exarg_T *eap) /* Open the buffer in this window. */ swap_exists_action = SEA_DIALOG; set_curbuf(buf, DOBUF_GOTO); - if (!buf_valid(buf)) { /* autocommands deleted the buffer!!! */ + if (!bufref_valid(&bufref)) { + // Autocommands deleted the buffer. swap_exists_action = SEA_NONE; break; } @@ -4857,7 +5087,7 @@ int buf_findsign( for (sign = buf->b_signlist; sign != NULL; sign = sign->next) { if (sign->id == id) { - return sign->lnum; + return (int)sign->lnum; } } @@ -4971,6 +5201,30 @@ void sign_mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_a // bufhl: plugin highlights associated with a buffer +/// Get reference to line in kbtree_t +/// +/// @param b the three +/// @param line the linenumber to lookup +/// @param put if true, put a new line when not found +/// if false, return NULL when not found +BufhlLine *bufhl_tree_ref(BufhlInfo *b, linenr_T line, bool put) +{ + BufhlLine t = BUFHLLINE_INIT(line); + + // kp_put() only works if key is absent, try get first + BufhlLine **pp = kb_get(bufhl, b, &t); + if (pp) { + return *pp; + } else if (!put) { + return NULL; + } + + BufhlLine *p = xmalloc(sizeof(*p)); + *p = (BufhlLine)BUFHLLINE_INIT(line); + kb_put(bufhl, b, p); + return p; +} + /// Adds a highlight to buffer. /// /// Unlike matchaddpos() highlights follow changes to line numbering (as lines @@ -5008,13 +5262,10 @@ int bufhl_add_hl(buf_T *buf, // no highlight group or invalid line, just return src_id return src_id; } - if (!buf->b_bufhl_info) { - buf->b_bufhl_info = map_new(linenr_T, bufhl_vec_T)(); - } - bufhl_vec_T* lineinfo = map_ref(linenr_T, bufhl_vec_T)(buf->b_bufhl_info, - lnum, true); - bufhl_hl_item_T *hlentry = kv_pushp(*lineinfo); + BufhlLine *lineinfo = bufhl_tree_ref(&buf->b_bufhl_info, lnum, true); + + BufhlItem *hlentry = kv_pushp(lineinfo->items); hlentry->src_id = src_id; hlentry->hl_id = hl_id; hlentry->start = col_start; @@ -5036,20 +5287,24 @@ int bufhl_add_hl(buf_T *buf, void bufhl_clear_line_range(buf_T *buf, int src_id, linenr_T line_start, - linenr_T line_end) { - if (!buf->b_bufhl_info) { - return; - } - linenr_T line; + linenr_T line_end) +{ linenr_T first_changed = MAXLNUM, last_changed = -1; - // In the case line_start - line_end << bufhl_info->size - // it might be better to reverse this, i e loop over the lines - // to clear on. - bufhl_vec_T unused; - map_foreach(buf->b_bufhl_info, line, unused, { - (void)unused; + + kbitr_t(bufhl) itr; + BufhlLine *l, t = BUFHLLINE_INIT(line_start); + if (!kb_itr_get(bufhl, &buf->b_bufhl_info, &t, &itr)) { + kb_itr_next(bufhl, &buf->b_bufhl_info, &itr); + } + for (; kb_itr_valid(&itr); kb_itr_next(bufhl, &buf->b_bufhl_info, &itr)) { + l = kb_itr_key(&itr); + linenr_T line = l->line; + if (line > line_end) { + break; + } if (line_start <= line && line <= line_end) { - if (bufhl_clear_line(buf->b_bufhl_info, src_id, line)) { + BufhlLineStatus status = bufhl_clear_line(l, src_id, line); + if (status != kBLSUnchanged) { if (line > last_changed) { last_changed = line; } @@ -5057,8 +5312,12 @@ void bufhl_clear_line_range(buf_T *buf, first_changed = line; } } + if (status == kBLSDeleted) { + kb_del_itr(bufhl, &buf->b_bufhl_info, &itr); + xfree(l); + } } - }) + } if (last_changed != -1) { changed_lines_buf(buf, first_changed, last_changed+1, 0); @@ -5071,40 +5330,40 @@ void bufhl_clear_line_range(buf_T *buf, /// @param bufhl_info The highlight info for the buffer /// @param src_id Highlight source group to clear, or -1 to clear all groups. /// @param lnum Linenr where the highlight should be cleared -static bool bufhl_clear_line(bufhl_info_T *bufhl_info, int src_id, int lnum) { - bufhl_vec_T* lineinfo = map_ref(linenr_T, bufhl_vec_T)(bufhl_info, - lnum, false); - size_t oldsize = kv_size(*lineinfo); +static BufhlLineStatus bufhl_clear_line(BufhlLine *lineinfo, int src_id, + linenr_T lnum) +{ + size_t oldsize = kv_size(lineinfo->items); if (src_id < 0) { - kv_size(*lineinfo) = 0; + kv_size(lineinfo->items) = 0; } else { - size_t newind = 0; - for (size_t i = 0; i < kv_size(*lineinfo); i++) { - if (kv_A(*lineinfo, i).src_id != src_id) { - if (i != newind) { - kv_A(*lineinfo, newind) = kv_A(*lineinfo, i); + size_t newidx = 0; + for (size_t i = 0; i < kv_size(lineinfo->items); i++) { + if (kv_A(lineinfo->items, i).src_id != src_id) { + if (i != newidx) { + kv_A(lineinfo->items, newidx) = kv_A(lineinfo->items, i); } - newind++; + newidx++; } } - kv_size(*lineinfo) = newind; + kv_size(lineinfo->items) = newidx; } - if (kv_size(*lineinfo) == 0) { - kv_destroy(*lineinfo); - map_del(linenr_T, bufhl_vec_T)(bufhl_info, lnum); + if (kv_size(lineinfo->items) == 0) { + kv_destroy(lineinfo->items); + return kBLSDeleted; } - return kv_size(*lineinfo) != oldsize; + return kv_size(lineinfo->items) != oldsize ? kBLSChanged : kBLSUnchanged; } /// Remove all highlights and free the highlight data -void bufhl_clear_all(buf_T* buf) { - if (!buf->b_bufhl_info) { - return; - } +void bufhl_clear_all(buf_T *buf) +{ bufhl_clear_line_range(buf, -1, 1, MAXLNUM); - map_free(linenr_T, bufhl_vec_T)(buf->b_bufhl_info); - buf->b_bufhl_info = NULL; + kb_destroy(bufhl, (&buf->b_bufhl_info)); + kb_init(&buf->b_bufhl_info); + kv_destroy(buf->b_bufhl_move_space); + kv_init(buf->b_bufhl_move_space); } /// Adjust a placed highlight for inserted/deleted lines. @@ -5112,29 +5371,49 @@ void bufhl_mark_adjust(buf_T* buf, linenr_T line1, linenr_T line2, long amount, - long amount_after) { - if (!buf->b_bufhl_info) { + long amount_after, + bool end_temp) +{ + kbitr_t(bufhl) itr; + BufhlLine *l, t = BUFHLLINE_INIT(line1); + if (end_temp && amount < 0) { + // Move all items from b_bufhl_move_space to the btree. + for (size_t i = 0; i < kv_size(buf->b_bufhl_move_space); i++) { + l = kv_A(buf->b_bufhl_move_space, i); + l->line += amount; + kb_put(bufhl, &buf->b_bufhl_info, l); + } + kv_size(buf->b_bufhl_move_space) = 0; return; } - bufhl_info_T *newmap = map_new(linenr_T, bufhl_vec_T)(); - linenr_T line; - bufhl_vec_T lineinfo; - map_foreach(buf->b_bufhl_info, line, lineinfo, { - if (line >= line1 && line <= line2) { + if (!kb_itr_get(bufhl, &buf->b_bufhl_info, &t, &itr)) { + kb_itr_next(bufhl, &buf->b_bufhl_info, &itr); + } + for (; kb_itr_valid(&itr); kb_itr_next(bufhl, &buf->b_bufhl_info, &itr)) { + l = kb_itr_key(&itr); + if (l->line >= line1 && l->line <= line2) { + if (end_temp && amount > 0) { + kb_del_itr(bufhl, &buf->b_bufhl_info, &itr); + kv_push(buf->b_bufhl_move_space, l); + } if (amount == MAXLNUM) { - bufhl_clear_line(buf->b_bufhl_info, -1, line); - continue; + if (bufhl_clear_line(l, -1, l->line) == kBLSDeleted) { + kb_del_itr(bufhl, &buf->b_bufhl_info, &itr); + xfree(l); + } else { + assert(false); + } } else { - line += amount; + l->line += amount; } - } else if (line > line2) { - line += amount_after; + } else if (l->line > line2) { + if (amount_after == 0) { + break; + } + l->line += amount_after; } - map_put(linenr_T, bufhl_vec_T)(newmap, line, lineinfo); - }); - map_free(linenr_T, bufhl_vec_T)(buf->b_bufhl_info); - buf->b_bufhl_info = newmap; + } } @@ -5144,13 +5423,14 @@ void bufhl_mark_adjust(buf_T* buf, /// @param lnum The line number /// @param[out] info The highligts for the line /// @return true if there was highlights to display -bool bufhl_start_line(buf_T *buf, linenr_T lnum, bufhl_lineinfo_T *info) { - if (!buf->b_bufhl_info) { +bool bufhl_start_line(buf_T *buf, linenr_T lnum, BufhlLineInfo *info) +{ + BufhlLine *lineinfo = bufhl_tree_ref(&buf->b_bufhl_info, lnum, false); + if (!lineinfo) { return false; } - info->valid_to = -1; - info->entries = map_get(linenr_T, bufhl_vec_T)(buf->b_bufhl_info, lnum); + info->entries = lineinfo->items; return kv_size(info->entries) > 0; } @@ -5164,14 +5444,15 @@ bool bufhl_start_line(buf_T *buf, linenr_T lnum, bufhl_lineinfo_T *info) { /// @param info The info returned by bufhl_start_line /// @param col The column to get the attr for /// @return The highilight attr to display at the column -int bufhl_get_attr(bufhl_lineinfo_T *info, colnr_T col) { +int bufhl_get_attr(BufhlLineInfo *info, colnr_T col) +{ if (col <= info->valid_to) { return info->current; } int attr = 0; info->valid_to = MAXCOL; for (size_t i = 0; i < kv_size(info->entries); i++) { - bufhl_hl_item_T entry = kv_A(info->entries, i); + BufhlItem entry = kv_A(info->entries, i); if (entry.start <= col && col <= entry.stop) { int entry_attr = syn_id2attr(entry.hl_id); attr = hl_combine_attr(attr, entry_attr); @@ -5286,8 +5567,8 @@ void buf_open_scratch(handle_T bufnr, char *bufname) { (void)do_ecmd((int)bufnr, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL); (void)setfname(curbuf, (char_u *)bufname, NULL, true); - set_option_value((char_u *)"bh", 0L, (char_u *)"hide", OPT_LOCAL); - set_option_value((char_u *)"bt", 0L, (char_u *)"nofile", OPT_LOCAL); - set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL); + set_option_value("bh", 0L, "hide", OPT_LOCAL); + set_option_value("bt", 0L, "nofile", OPT_LOCAL); + set_option_value("swf", 0L, NULL, OPT_LOCAL); RESET_BINDING(curwin); } diff --git a/src/nvim/buffer.h b/src/nvim/buffer.h index 36cbec7e60..faeeed121c 100644 --- a/src/nvim/buffer.h +++ b/src/nvim/buffer.h @@ -1,10 +1,14 @@ #ifndef NVIM_BUFFER_H #define NVIM_BUFFER_H +#include "nvim/vim.h" #include "nvim/window.h" #include "nvim/pos.h" // for linenr_T #include "nvim/ex_cmds_defs.h" // for exarg_T #include "nvim/screen.h" // for StlClickRecord +#include "nvim/func_attr.h" +#include "nvim/eval.h" +#include "nvim/macros.h" // Values for buflist_getfile() enum getf_values { @@ -15,9 +19,11 @@ enum getf_values { // Values for buflist_new() flags enum bln_values { - BLN_CURBUF = 1, // May re-use curbuf for new buffer - BLN_LISTED = 2, // Put new buffer in buffer list - BLN_DUMMY = 4, // Allocating dummy buffer + BLN_CURBUF = 1, // May re-use curbuf for new buffer + BLN_LISTED = 2, // Put new buffer in buffer list + BLN_DUMMY = 4, // Allocating dummy buffer + // TODO(mhinz): merge patch that introduces BLN_NEW + BLN_NOOPT = 16, // Don't copy options to existing buffer }; // Values for action argument for do_buffer() @@ -55,35 +61,64 @@ enum bfa_values { static inline void switch_to_win_for_buf(buf_T *buf, win_T **save_curwinp, tabpage_T **save_curtabp, - buf_T **save_curbufp) + bufref_T *save_curbuf) { win_T *wp; tabpage_T *tp; if (!find_win_for_buf(buf, &wp, &tp) - || switch_win(save_curwinp, save_curtabp, wp, tp, true) == FAIL) - switch_buffer(save_curbufp, buf); + || switch_win(save_curwinp, save_curtabp, wp, tp, true) == FAIL) { + switch_buffer(save_curbuf, buf); + } } static inline void restore_win_for_buf(win_T *save_curwin, tabpage_T *save_curtab, - buf_T *save_curbuf) + bufref_T *save_curbuf) { - if (save_curbuf == NULL) { + if (save_curbuf->br_buf == NULL) { restore_win(save_curwin, save_curtab, true); } else { restore_buffer(save_curbuf); } } +static inline void buf_set_changedtick(buf_T *const buf, + const varnumber_T changedtick) + REAL_FATTR_NONNULL_ALL REAL_FATTR_ALWAYS_INLINE; + +/// Set b_changedtick and corresponding variable +/// +/// @param[out] buf Buffer to set changedtick in. +/// @param[in] changedtick New value. +static inline void buf_set_changedtick(buf_T *const buf, + const varnumber_T changedtick) +{ +#ifndef NDEBUG + dictitem_T *const changedtick_di = tv_dict_find( + buf->b_vars, S_LEN("changedtick")); + assert(changedtick_di != NULL); + assert(changedtick_di->di_tv.v_type == VAR_NUMBER); + assert(changedtick_di->di_tv.v_lock == VAR_FIXED); + // For some reason formatc does not like the below. +# ifndef UNIT_TESTING_LUA_PREPROCESSING + assert(changedtick_di->di_flags == (DI_FLAGS_RO|DI_FLAGS_FIX)); +# endif + assert(changedtick_di == (dictitem_T *)&buf->changedtick_di); + assert(&buf->b_changedtick // -V501 + == &buf->changedtick_di.di_tv.vval.v_number); +#endif + buf->b_changedtick = changedtick; +} + #define WITH_BUFFER(b, code) \ do { \ - buf_T *save_curbuf = NULL; \ win_T *save_curwin = NULL; \ tabpage_T *save_curtab = NULL; \ + bufref_T save_curbuf = { NULL, 0, 0 }; \ switch_to_win_for_buf(b, &save_curwin, &save_curtab, &save_curbuf); \ code; \ - restore_win_for_buf(save_curwin, save_curtab, save_curbuf); \ + restore_win_for_buf(save_curwin, save_curtab, &save_curbuf); \ } while (0) diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 2b66a07f48..559dffb945 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -8,14 +8,22 @@ typedef struct file_buffer buf_T; // Forward declaration +// Reference to a buffer that stores the value of buf_free_count. +// bufref_valid() only needs to check "buf" when the count differs. +typedef struct { + buf_T *br_buf; + int br_fnum; + int br_buf_free_count; +} bufref_T; + // for garray_T #include "nvim/garray.h" +// for HLF_COUNT +#include "nvim/highlight_defs.h" // for pos_T, lpos_T and linenr_T #include "nvim/pos.h" // for the number window-local and buffer-local options #include "nvim/option_defs.h" -// for optional iconv support -#include "nvim/iconv.h" // for jump list and tag stack sizes in a buffer and mark types #include "nvim/mark_defs.h" // for u_header_T; needs buf_T. @@ -23,7 +31,7 @@ typedef struct file_buffer buf_T; // Forward declaration // for hashtab_T #include "nvim/hashtab.h" // for dict_T -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" // for proftime_T #include "nvim/profile.h" // for String @@ -31,7 +39,7 @@ typedef struct file_buffer buf_T; // Forward declaration // for Map(K, V) #include "nvim/map.h" -#define MODIFIABLE(buf) (!buf->terminal && buf->b_p_ma) +#define MODIFIABLE(buf) (buf->b_p_ma) /* * Flags for w_valid. @@ -83,36 +91,23 @@ typedef struct file_buffer buf_T; // Forward declaration typedef struct window_S win_T; typedef struct wininfo_S wininfo_T; typedef struct frame_S frame_T; -typedef int scid_T; /* script ID */ // for struct memline (it needs memfile_T) #include "nvim/memline_defs.h" - // for struct memfile, bhdr_T, blocknr_T... (it needs buf_T) #include "nvim/memfile_defs.h" -/* - * This is here because regexp_defs.h needs win_T and buf_T. regprog_T is - * used below. - */ +// for regprog_T. Needs win_T and buf_T. #include "nvim/regexp_defs.h" - -// for synstate_T (needs reg_extmatch_T, win_T and buf_T) +// for synstate_T (needs reg_extmatch_T, win_T, buf_T) #include "nvim/syntax_defs.h" - // for signlist_T #include "nvim/sign_defs.h" - // for bufhl_*_T #include "nvim/bufhl_defs.h" -typedef Map(linenr_T, bufhl_vec_T) bufhl_info_T; - -// for FileID -#include "nvim/os/fs_defs.h" - -// for Terminal -#include "nvim/terminal.h" +#include "nvim/os/fs_defs.h" // for FileID +#include "nvim/terminal.h" // for Terminal /* * The taggy struct is used to store the information about a :tag command. @@ -239,6 +234,8 @@ typedef struct { # define w_p_crb_save w_onebuf_opt.wo_crb_save char_u *wo_scl; # define w_p_scl w_onebuf_opt.wo_scl // 'signcolumn' + char_u *wo_winhl; +# define w_p_winhl w_onebuf_opt.wo_winhl // 'winhighlight' int wo_scriptID[WV_COUNT]; /* SIDs for window-local options */ # define w_p_scriptID w_onebuf_opt.wo_scriptID @@ -325,25 +322,6 @@ typedef struct { } tasave_T; /* - * Used for conversion of terminal I/O and script files. - */ -typedef struct { - int vc_type; /* zero or one of the CONV_ values */ - int vc_factor; /* max. expansion factor */ -# ifdef USE_ICONV - iconv_t vc_fd; /* for CONV_ICONV */ -# endif - bool vc_fail; /* fail for invalid char, don't use '?' */ -} vimconv_T; - -#define CONV_NONE 0 -#define CONV_TO_UTF8 1 -#define CONV_9_TO_UTF8 2 -#define CONV_TO_LATIN1 3 -#define CONV_TO_LATIN9 4 -#define CONV_ICONV 5 - -/* * Structure used for mappings and abbreviations. */ typedef struct mapblock mapblock_T; @@ -453,6 +431,16 @@ typedef struct { char_u *b_syn_isk; // iskeyword option } synblock_T; +/// Type used for changedtick_di member in buf_T +/// +/// Primary exists so that literals of relevant type can be made. +typedef TV_DICTITEM_STRUCT(sizeof("changedtick")) ChangedtickDictItem; + +#define BUF_HAS_QF_ENTRY 1 +#define BUF_HAS_LL_ENTRY 2 + +// Maximum number of maphash blocks we will have +#define MAX_MAPHASH 256 /* * buffer: structure that holds information about one file @@ -473,9 +461,9 @@ struct file_buffer { int b_nwindows; /* nr of windows open on this buffer */ - int b_flags; /* various BF_ flags */ - bool b_closing; /* buffer is being closed, don't let - autocommands close it too. */ + int b_flags; // various BF_ flags + int b_locked; // Buffer is being closed or referenced, don't + // let autocommands wipe it out. /* * b_ffname has the full path of the file (NULL for no name). @@ -492,7 +480,9 @@ struct file_buffer { int b_changed; // 'modified': Set to true if something in the // file has been changed and not written out. - int b_changedtick; // incremented for each change, also for undo +/// Change identifier incremented for each change, including undo +#define b_changedtick changedtick_di.di_tv.vval.v_number + ChangedtickDictItem changedtick_di; // b:changedtick dictionary item. bool b_saving; /* Set to true if we are in the middle of saving the buffer. */ @@ -540,8 +530,8 @@ struct file_buffer { */ uint64_t b_chartab[4]; - /* Table used for mappings local to a buffer. */ - mapblock_T *(b_maphash[256]); + // Table used for mappings local to a buffer. + mapblock_T *(b_maphash[MAX_MAPHASH]); /* First abbreviation local to a buffer. */ mapblock_T *b_first_abbr; @@ -611,7 +601,7 @@ struct file_buffer { int b_p_bomb; ///< 'bomb' char_u *b_p_bh; ///< 'bufhidden' char_u *b_p_bt; ///< 'buftype' - bool b_has_qf_entry; ///< quickfix exists for buffer + int b_has_qf_entry; ///< quickfix exists for buffer int b_p_bl; ///< 'buflisted' int b_p_cin; ///< 'cindent' char_u *b_p_cino; ///< 'cinoptions' @@ -641,6 +631,7 @@ struct file_buffer { char_u *b_p_inde; ///< 'indentexpr' uint32_t b_p_inde_flags; ///< flags for 'indentexpr' char_u *b_p_indk; ///< 'indentkeys' + char_u *b_p_fp; ///< 'formatprg' char_u *b_p_fex; ///< 'formatexpr' uint32_t b_p_fex_flags; ///< flags for 'formatexpr' char_u *b_p_kp; ///< 'keywordprg' @@ -654,6 +645,7 @@ struct file_buffer { char_u *b_p_qe; ///< 'quoteescape' int b_p_ro; ///< 'readonly' long b_p_sw; ///< 'shiftwidth' + long b_p_scbk; ///< 'scrollback' int b_p_si; ///< 'smartindent' long b_p_sts; ///< 'softtabstop' long b_p_sts_nopaste; ///< b_p_sts saved for paste mode @@ -734,8 +726,8 @@ struct file_buffer { int b_bad_char; /* "++bad=" argument when edit started or 0 */ int b_start_bomb; /* 'bomb' when it was read */ - dictitem_T b_bufvar; /* variable for "b:" Dictionary */ - dict_T *b_vars; /* internal variables, local to buffer */ + ScopeDictDictItem b_bufvar; ///< Variable for "b:" Dictionary. + dict_T *b_vars; ///< b: scope dictionary. /* When a buffer is created, it starts without a swap file. b_may_swap is * then set to indicate that a swap file may be opened later. It is reset @@ -768,7 +760,9 @@ struct file_buffer { int b_mapped_ctrl_c; // modes where CTRL-C is mapped - bufhl_info_T *b_bufhl_info; // buffer stored highlights + BufhlInfo b_bufhl_info; // buffer stored highlights + + kvec_t(BufhlLine *) b_bufhl_move_space; // temporary space for highlights }; /* @@ -823,10 +817,9 @@ struct tabpage_S { buf_T *(tp_diffbuf[DB_COUNT]); int tp_diff_invalid; ///< list of diffs is outdated frame_T *(tp_snapshot[SNAP_COUNT]); ///< window layout snapshots - dictitem_T tp_winvar; ///< variable for "t:" Dictionary - dict_T *tp_vars; ///< internal variables, local to tab page - char_u *localdir; ///< Absolute path of local directory or - ///< NULL + ScopeDictDictItem tp_winvar; ///< Variable for "t:" Dictionary. + dict_T *tp_vars; ///< Internal variables, local to tab page. + char_u *tp_localdir; ///< Absolute path of local cwd or NULL. }; /* @@ -945,6 +938,14 @@ struct window_S { synblock_T *w_s; /* for :ownsyntax */ + int w_hl_id_normal; ///< 'winhighlight' normal id + int w_hl_attr_normal; ///< 'winhighlight' normal final attrs + + int w_hl_ids[HLF_COUNT]; ///< 'winhighlight' id + int w_hl_attrs[HLF_COUNT]; ///< 'winhighlight' final attrs + + int w_hl_needs_update; ///< attrs need to be recalculated + win_T *w_prev; /* link to previous window */ win_T *w_next; /* link to next window */ bool w_closing; /* window is being closed, don't let @@ -1118,8 +1119,8 @@ struct window_S { long w_scbind_pos; - dictitem_T w_winvar; /* variable for "w:" Dictionary */ - dict_T *w_vars; /* internal variables, local to window */ + ScopeDictDictItem w_winvar; ///< Variable for "w:" dictionary. + dict_T *w_vars; ///< Dictionary with w: variables. int w_farsi; /* for the window dependent Farsi functions */ @@ -1174,4 +1175,9 @@ struct window_S { qf_info_T *w_llist_ref; }; +static inline int win_hl_attr(win_T *wp, int hlf) +{ + return wp->w_hl_attrs[hlf]; +} + #endif // NVIM_BUFFER_DEFS_H diff --git a/src/nvim/bufhl_defs.h b/src/nvim/bufhl_defs.h index e47bb2a238..14b1afa7d9 100644 --- a/src/nvim/bufhl_defs.h +++ b/src/nvim/bufhl_defs.h @@ -3,23 +3,32 @@ #include "nvim/pos.h" #include "nvim/lib/kvec.h" +#include "nvim/lib/kbtree.h" + // bufhl: buffer specific highlighting -struct bufhl_hl_item -{ +typedef struct { int src_id; int hl_id; // highlight group colnr_T start; // first column to highlight colnr_T stop; // last column to highlight -}; -typedef struct bufhl_hl_item bufhl_hl_item_T; +} BufhlItem; -typedef kvec_t(struct bufhl_hl_item) bufhl_vec_T; +typedef kvec_t(BufhlItem) BufhlItemVec; + +typedef struct { + linenr_T line; + BufhlItemVec items; +} BufhlLine; +#define BUFHLLINE_INIT(l) { l, KV_INITIAL_VALUE } typedef struct { - bufhl_vec_T entries; + BufhlItemVec entries; int current; colnr_T valid_to; -} bufhl_lineinfo_T; +} BufhlLineInfo; +#define BUFHL_CMP(a, b) ((int)(((a)->line - (b)->line))) +KBTREE_INIT(bufhl, BufhlLine *, BUFHL_CMP, 10) // -V512 +typedef kbtree_t(bufhl) BufhlInfo; #endif // NVIM_BUFHL_DEFS_H diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 4d150c3230..403ef65c4f 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -1,3 +1,6 @@ +// 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 + /// @file charset.c /// /// Code related to character sets. @@ -15,6 +18,7 @@ #include "nvim/func_attr.h" #include "nvim/indent.h" #include "nvim/main.h" +#include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" @@ -41,8 +45,10 @@ static bool chartab_initialized = false; (buf)->b_chartab[(unsigned)(c) >> 6] |= (1ull << ((c) & 0x3f)) #define RESET_CHARTAB(buf, c) \ (buf)->b_chartab[(unsigned)(c) >> 6] &= ~(1ull << ((c) & 0x3f)) +#define GET_CHARTAB_TAB(chartab, c) \ + ((chartab)[(unsigned)(c) >> 6] & (1ull << ((c) & 0x3f))) #define GET_CHARTAB(buf, c) \ - ((buf)->b_chartab[(unsigned)(c) >> 6] & (1ull << ((c) & 0x3f))) + GET_CHARTAB_TAB((buf)->b_chartab, c) // Table used below, see init_chartab() for an explanation static char_u g_chartab[256]; @@ -88,7 +94,6 @@ int buf_init_chartab(buf_T *buf, int global) { int c; int c2; - char_u *p; int i; bool tilde; bool do_isalpha; @@ -142,7 +147,8 @@ int buf_init_chartab(buf_T *buf, int global) // Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint' // 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) { + for (i = global ? 0 : 3; i <= 3; i++) { + const char_u *p; if (i == 0) { // first round: 'isident' p = p_isi; @@ -167,7 +173,7 @@ int buf_init_chartab(buf_T *buf, int global) } if (ascii_isdigit(*p)) { - c = getdigits_int(&p); + c = getdigits_int((char_u **)&p); } else { c = mb_ptr2char_adv(&p); } @@ -177,7 +183,7 @@ int buf_init_chartab(buf_T *buf, int global) ++p; if (ascii_isdigit(*p)) { - c2 = getdigits_int(&p); + c2 = getdigits_int((char_u **)&p); } else { c2 = mb_ptr2char_adv(&p); } @@ -210,8 +216,8 @@ int buf_init_chartab(buf_T *buf, int global) // work properly when 'encoding' is "latin1" and the locale is // "C". if (!do_isalpha - || vim_islower(c) - || vim_isupper(c) + || mb_islower(c) + || mb_isupper(c) || (p_altkeymap && (F_isalpha(c) || F_isdigit(c)))) { if (i == 0) { // (re)set ID flag @@ -415,11 +421,11 @@ char_u* str_foldcase(char_u *str, int orglen, char_u *buf, int buflen) while (STR_CHAR(i) != NUL) { int c = utf_ptr2char(STR_PTR(i)); int olen = utf_ptr2len(STR_PTR(i)); - int lc = utf_tolower(c); + int lc = mb_tolower(c); // Only replace the character when it is not an invalid // sequence (ASCII character or more than one byte) and - // utf_tolower() doesn't return the original character. + // mb_tolower() doesn't return the original character. if (((c < 0x80) || (olen > 1)) && (c != lc)) { int nlen = utf_char2len(lc); @@ -486,7 +492,8 @@ char_u* transchar(int c) c = K_SECOND(c); } - if ((!chartab_initialized && (((c >= ' ') && (c <= '~')) || F_ischar(c))) + if ((!chartab_initialized && (((c >= ' ') && (c <= '~')) + || (p_altkeymap && F_ischar(c)))) || ((c < 256) && vim_isprintc_strict(c))) { // printable character transchar_buf[i] = (char_u)c; @@ -538,18 +545,8 @@ void transchar_nonprint(char_u *buf, int c) buf[1] = (char_u)(c ^ 0x40); buf[2] = NUL; - } else if (c >= 0x80) { - transchar_hex(buf, c); - } else if ((c >= ' ' + 0x80) && (c <= '~' + 0x80)) { - // 0xa0 - 0xfe - buf[0] = '|'; - buf[1] = (char_u)(c - 0x80); - buf[2] = NUL; } else { - // 0x80 - 0x9f and 0xff - buf[0] = '~'; - buf[1] = (char_u)((c - 0x80) ^ 0x40); - buf[2] = NUL; + transchar_hex(buf, c); } } @@ -633,7 +630,7 @@ int char2cells(int c) /// @param p /// /// @return number of display cells. -int ptr2cells(char_u *p) +int ptr2cells(const char_u *p) { // For UTF-8 we need to look at more bytes if the first byte is >= 0x80. if (*p >= 0x80) { @@ -775,6 +772,20 @@ bool vim_iswordc(int c) return vim_iswordc_buf(c, curbuf); } +/// Check that "c" is a keyword character +/// Letters and characters from 'iskeyword' option for given buffer. +/// For multi-byte characters mb_get_class() is used (builtin rules). +/// +/// @param[in] c Character to check. +/// @param[in] chartab Buffer chartab. +bool vim_iswordc_tab(const int c, const uint64_t *const chartab) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL +{ + return (c >= 0x100 + ? (utf_class(c) >= 2) + : (c > 0 && GET_CHARTAB_TAB(chartab, c) != 0)); +} + /// Check that "c" is a keyword character: /// Letters and characters from 'iskeyword' option for given buffer. /// For multi-byte characters mb_get_class() is used (builtin rules). @@ -784,10 +795,7 @@ bool vim_iswordc(int c) bool vim_iswordc_buf(int c, buf_T *buf) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(2) { - if (c >= 0x100) { - return utf_class(c) >= 2; - } - return c > 0 && c < 0x100 && GET_CHARTAB(buf, c) != 0; + return vim_iswordc_tab(c, buf->b_chartab); } /// Just like vim_iswordc() but uses a pointer to the (multi-byte) character. @@ -973,10 +981,8 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he mb_ptr_adv(s); c = *s; - if (!((c != NUL) - && (vim_isbreak(c) - || (!vim_isbreak(c) - && ((col2 == col) || !vim_isbreak(*ps)))))) { + if (!(c != NUL + && (vim_isbreak(c) || col2 == col || !vim_isbreak(*ps)))) { break; } @@ -1159,7 +1165,13 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, // continue until the NUL posptr = NULL; } else { + // Special check for an empty line, which can happen on exit, when + // ml_get_buf() always returns an empty string. + if (*ptr == NUL) { + pos->col = 0; + } posptr = ptr + pos->col; + posptr -= utf_head_off(line, posptr); } // This function is used very often, do some speed optimizations. @@ -1346,7 +1358,7 @@ void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left, colnr_T to1; colnr_T to2; - if (ltp(pos1, pos2)) { + if (lt(*pos1, *pos2)) { getvvcol(wp, pos1, &from1, NULL, &to1); getvvcol(wp, pos2, &from2, NULL, &to2); } else { @@ -1373,32 +1385,35 @@ void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left, /// skipwhite: skip over ' ' and '\t'. /// -/// @param q +/// @param[in] q String to skip in. /// /// @return Pointer to character after the skipped whitespace. -char_u* skipwhite(char_u *q) +char_u *skipwhite(const char_u *q) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_RET { - char_u *p = q; + const char_u *p = q; while (ascii_iswhite(*p)) { - // skip to next non-white p++; } - return p; + return (char_u *)p; } -/// skip over digits +/// Skip over digits /// -/// @param q +/// @param[in] q String to skip digits in. /// /// @return Pointer to the character after the skipped digits. -char_u* skipdigits(char_u *q) +char_u *skipdigits(const char_u *q) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_RET { - char_u *p = q; + const char_u *p = q; while (ascii_isdigit(*p)) { // skip to next non-digit p++; } - return p; + return (char_u *)p; } /// skip over binary digits @@ -1483,78 +1498,17 @@ char_u* skiptohex(char_u *q) return p; } -// Vim's own character class functions. These exist because many library -// islower()/toupper() etc. do not work properly: they crash when used with -// invalid values or can't handle latin1 when the locale is C. -// Speed is most important here. - -/// Check that the character is lower-case -/// -/// @param c character to check -bool vim_islower(int c) - FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT -{ - if (c <= '@') { - return false; - } - - if (c >= 0x80) { - return utf_islower(c); - } - return islower(c); -} - -/// Check that the character is upper-case +/// Skip over text until ' ' or '\t' or NUL /// -/// @param c character to check -bool vim_isupper(int c) - FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT -{ - if (c <= '@') { - return false; - } - - if (c >= 0x80) { - return utf_isupper(c); - } - return isupper(c); -} - -int vim_toupper(int c) -{ - if (c <= '@') { - return c; - } - - if (c >= 0x80) { - return utf_toupper(c); - } - return TOUPPER_LOC(c); -} - -int vim_tolower(int c) -{ - if (c <= '@') { - return c; - } - - if (c >= 0x80) { - return utf_tolower(c); - } - return TOLOWER_LOC(c); -} - -/// skiptowhite: skip over text until ' ' or '\t' or NUL. -/// -/// @param p +/// @param[in] p Text to skip over. /// /// @return Pointer to the next whitespace or NUL character. -char_u* skiptowhite(char_u *p) +char_u *skiptowhite(const char_u *p) { while (*p != ' ' && *p != '\t' && *p != NUL) { p++; } - return p; + return (char_u *)p; } /// skiptowhite_esc: Like skiptowhite(), but also skip escaped chars @@ -1665,13 +1619,13 @@ bool vim_isblankline(char_u *lbuf) /// @param unptr Returns the unsigned result. /// @param maxlen Max length of string to check. void vim_str2nr(const char_u *const start, int *const prep, int *const len, - const int what, long *const nptr, unsigned long *const unptr, - const int maxlen) + const int what, varnumber_T *const nptr, + uvarnumber_T *const unptr, const int maxlen) { const char_u *ptr = start; int pre = 0; // default is decimal bool negative = false; - unsigned long un = 0; + uvarnumber_T un = 0; if (ptr[0] == '-') { negative = true; @@ -1727,7 +1681,12 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, n += 2; // skip over "0b" } while ('0' <= *ptr && *ptr <= '1') { - un = 2 * un + (unsigned long)(*ptr - '0'); + // avoid ubsan error for overflow + if (un < UVARNUMBER_MAX / 2) { + un = 2 * un + (uvarnumber_T)(*ptr - '0'); + } else { + un = UVARNUMBER_MAX; + } ptr++; if (n++ == maxlen) { break; @@ -1736,7 +1695,12 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, } else if ((pre == '0') || what == STR2NR_OCT + STR2NR_FORCE) { // octal while ('0' <= *ptr && *ptr <= '7') { - un = 8 * un + (unsigned long)(*ptr - '0'); + // avoid ubsan error for overflow + if (un < UVARNUMBER_MAX / 8) { + un = 8 * un + (uvarnumber_T)(*ptr - '0'); + } else { + un = UVARNUMBER_MAX; + } ptr++; if (n++ == maxlen) { break; @@ -1749,7 +1713,12 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, n += 2; // skip over "0x" } while (ascii_isxdigit(*ptr)) { - un = 16 * un + (unsigned long)hex2nr(*ptr); + // avoid ubsan error for overflow + if (un < UVARNUMBER_MAX / 16) { + un = 16 * un + (uvarnumber_T)hex2nr(*ptr); + } else { + un = UVARNUMBER_MAX; + } ptr++; if (n++ == maxlen) { break; @@ -1758,7 +1727,12 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, } else { // decimal while (ascii_isdigit(*ptr)) { - un = 10 * un + (unsigned long)(*ptr - '0'); + // avoid ubsan error for overflow + if (un < UVARNUMBER_MAX / 10) { + un = 10 * un + (uvarnumber_T)(*ptr - '0'); + } else { + un = UVARNUMBER_MAX; + } ptr++; if (n++ == maxlen) { break; @@ -1775,11 +1749,18 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, } if (nptr != NULL) { - if (negative) { - // account for leading '-' for decimal numbers - *nptr = -(long)un; + if (negative) { // account for leading '-' for decimal numbers + // avoid ubsan error for overflow + if (un > VARNUMBER_MAX) { + *nptr = VARNUMBER_MIN; + } else { + *nptr = -(varnumber_T)un; + } } else { - *nptr = (long)un; + if (un > VARNUMBER_MAX) { + un = VARNUMBER_MAX; + } + *nptr = (varnumber_T)un; } } diff --git a/src/nvim/charset.h b/src/nvim/charset.h index 78d6f2a76c..c69582c4c6 100644 --- a/src/nvim/charset.h +++ b/src/nvim/charset.h @@ -1,6 +1,20 @@ #ifndef NVIM_CHARSET_H #define NVIM_CHARSET_H +#include "nvim/types.h" +#include "nvim/pos.h" +#include "nvim/buffer_defs.h" + +/// Return the folded-case equivalent of the given character +/// +/// @param[in] c Character to transform. +/// +/// @return Folded variant. +#define CH_FOLD(c) \ + utf_fold((sizeof(c) == sizeof(char)) \ + ?((int)(uint8_t)(c)) \ + :((int)(c))) + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "charset.h.generated.h" #endif diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c index 3ba9da34f2..60002f3cea 100644 --- a/src/nvim/cursor.c +++ b/src/nvim/cursor.c @@ -1,3 +1,6 @@ +// 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 <stdbool.h> #include <inttypes.h> @@ -12,6 +15,7 @@ #include "nvim/state.h" #include "nvim/vim.h" #include "nvim/ascii.h" +#include "nvim/mark.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "cursor.c.generated.h" @@ -227,9 +231,10 @@ static int coladvance2( } } - /* prevent from moving onto a trail byte */ - if (has_mbyte) - mb_adjustpos(curbuf, pos); + // Prevent from moving onto a trail byte. + if (has_mbyte) { + mark_mb_adjustpos(curbuf, pos); + } if (col < wcol) return FAIL; @@ -294,6 +299,26 @@ linenr_T get_cursor_rel_lnum(win_T *wp, linenr_T lnum) return (lnum < cursor) ? -retval : retval; } +// Make sure "pos.lnum" and "pos.col" are valid in "buf". +// This allows for the col to be on the NUL byte. +void check_pos(buf_T *buf, pos_T *pos) +{ + char_u *line; + colnr_T len; + + if (pos->lnum > buf->b_ml.ml_line_count) { + pos->lnum = buf->b_ml.ml_line_count; + } + + if (pos->col > 0) { + line = ml_get_buf(buf, pos->lnum, false); + len = (colnr_T)STRLEN(line); + if (pos->col > len) { + pos->col = len; + } + } +} + /* * Make sure curwin->w_cursor.lnum is valid. */ @@ -318,9 +343,8 @@ void check_cursor_col(void) check_cursor_col_win(curwin); } -/* - * Make sure win->w_cursor.col is valid. - */ +/// Make sure win->w_cursor.col is valid. Special handling of insert-mode. +/// @see mb_check_adjust_col void check_cursor_col_win(win_T *win) { colnr_T len; @@ -342,9 +366,10 @@ void check_cursor_col_win(win_T *win) win->w_cursor.col = len; } else { win->w_cursor.col = len - 1; - /* Move the cursor to the head byte. */ - if (has_mbyte) - mb_adjustpos(win->w_buffer, &win->w_cursor); + // Move the cursor to the head byte. + if (has_mbyte) { + mark_mb_adjustpos(win->w_buffer, &win->w_cursor); + } } } else if (win->w_cursor.col < 0) { win->w_cursor.col = 0; diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c index b50462664c..97fc3a3ca3 100644 --- a/src/nvim/cursor_shape.c +++ b/src/nvim/cursor_shape.c @@ -1,3 +1,6 @@ +// 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 "nvim/vim.h" @@ -7,40 +10,75 @@ #include "nvim/charset.h" #include "nvim/strings.h" #include "nvim/syntax.h" +#include "nvim/api/private/helpers.h" +#include "nvim/ui.h" -/* - * Handling of cursor and mouse pointer shapes in various modes. - */ - -static cursorentry_T shape_table[SHAPE_IDX_COUNT] = +/// Handling of cursor and mouse pointer shapes in various modes. +cursorentry_T shape_table[SHAPE_IDX_COUNT] = { - /* The values will be filled in from the 'guicursor' and 'mouseshape' - * defaults when Vim starts. - * Adjust the SHAPE_IDX_ defines when making changes! */ - {0, 0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 0L, 0L, 0L, 0, 0, "e", SHAPE_MOUSE}, - {0, 0, 0, 0L, 0L, 0L, 0, 0, "s", SHAPE_MOUSE}, - {0, 0, 0, 0L, 0L, 0L, 0, 0, "sd", SHAPE_MOUSE}, - {0, 0, 0, 0L, 0L, 0L, 0, 0, "vs", SHAPE_MOUSE}, - {0, 0, 0, 0L, 0L, 0L, 0, 0, "vd", SHAPE_MOUSE}, - {0, 0, 0, 0L, 0L, 0L, 0, 0, "m", SHAPE_MOUSE}, - {0, 0, 0, 0L, 0L, 0L, 0, 0, "ml", SHAPE_MOUSE}, - {0, 0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR}, + // Values are set by 'guicursor' and 'mouseshape'. + // Adjust the SHAPE_IDX_ defines when changing this! + { "normal", 0, 0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE }, + { "visual", 0, 0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE }, + { "insert", 0, 0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE }, + { "replace", 0, 0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE }, + { "cmdline_normal", 0, 0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE }, + { "cmdline_insert", 0, 0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE }, + { "cmdline_replace", 0, 0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE }, + { "operator", 0, 0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE }, + { "visual_select", 0, 0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE }, + { "cmdline_hover", 0, 0, 0, 0L, 0L, 0L, 0, 0, "e", SHAPE_MOUSE }, + { "statusline_hover", 0, 0, 0, 0L, 0L, 0L, 0, 0, "s", SHAPE_MOUSE }, + { "statusline_drag", 0, 0, 0, 0L, 0L, 0L, 0, 0, "sd", SHAPE_MOUSE }, + { "vsep_hover", 0, 0, 0, 0L, 0L, 0L, 0, 0, "vs", SHAPE_MOUSE }, + { "vsep_drag", 0, 0, 0, 0L, 0L, 0L, 0, 0, "vd", SHAPE_MOUSE }, + { "more", 0, 0, 0, 0L, 0L, 0L, 0, 0, "m", SHAPE_MOUSE }, + { "more_lastline", 0, 0, 0, 0L, 0L, 0L, 0, 0, "ml", SHAPE_MOUSE }, + { "showmatch", 0, 0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR }, }; -/* - * Parse the 'guicursor' option ("what" is SHAPE_CURSOR) or 'mouseshape' - * ("what" is SHAPE_MOUSE). - * Returns error message for an illegal option, NULL otherwise. - */ +/// Converts cursor_shapes into an Array of Dictionaries +/// @return Array of the form {[ "cursor_shape": ... ], ...} +Array mode_style_array(void) +{ + Array all = ARRAY_DICT_INIT; + + for (int i = 0; i < SHAPE_IDX_COUNT; i++) { + Dictionary dic = ARRAY_DICT_INIT; + cursorentry_T *cur = &shape_table[i]; + if (cur->used_for & SHAPE_MOUSE) { + PUT(dic, "mouse_shape", INTEGER_OBJ(cur->mshape)); + } + if (cur->used_for & SHAPE_CURSOR) { + String shape_str; + switch (cur->shape) { + case SHAPE_BLOCK: shape_str = cstr_to_string("block"); break; + case SHAPE_VER: shape_str = cstr_to_string("vertical"); break; + case SHAPE_HOR: shape_str = cstr_to_string("horizontal"); break; + default: shape_str = cstr_to_string("unknown"); + } + PUT(dic, "cursor_shape", STRING_OBJ(shape_str)); + PUT(dic, "cell_percentage", INTEGER_OBJ(cur->percentage)); + PUT(dic, "blinkwait", INTEGER_OBJ(cur->blinkwait)); + PUT(dic, "blinkon", INTEGER_OBJ(cur->blinkon)); + PUT(dic, "blinkoff", INTEGER_OBJ(cur->blinkoff)); + PUT(dic, "hl_id", INTEGER_OBJ(cur->id)); + PUT(dic, "id_lm", INTEGER_OBJ(cur->id_lm)); + } + PUT(dic, "name", STRING_OBJ(cstr_to_string(cur->full_name))); + PUT(dic, "short_name", STRING_OBJ(cstr_to_string(cur->name))); + + ADD(all, DICTIONARY_OBJ(dic)); + } + + return all; +} + +/// Parse the 'guicursor' option +/// +/// @param what SHAPE_CURSOR or SHAPE_MOUSE ('mouseshape') +/// +/// @returns error message for an illegal option, NULL otherwise. char_u *parse_shape_opt(int what) { char_u *modep; @@ -55,14 +93,13 @@ char_u *parse_shape_opt(int what) int found_ve = false; /* found "ve" flag */ int round; - /* - * First round: check for errors; second round: do it for real. - */ - for (round = 1; round <= 2; ++round) { - /* - * Repeat for all comma separated parts. - */ + // First round: check for errors; second round: do it for real. + for (round = 1; round <= 2; round++) { + // Repeat for all comma separated parts. modep = p_guicursor; + if (*p_guicursor == NUL) { + modep = (char_u *)"a:block-blinkon0"; + } while (*modep != NUL) { colonp = vim_strchr(modep, ':'); if (colonp == NULL) @@ -71,19 +108,18 @@ char_u *parse_shape_opt(int what) return (char_u *)N_("E546: Illegal mode"); commap = vim_strchr(modep, ','); - /* - * Repeat for all mode's before the colon. - * For the 'a' mode, we loop to handle all the modes. - */ + // Repeat for all modes before the colon. + // For the 'a' mode, we loop to handle all the modes. all_idx = -1; assert(modep < colonp); while (modep < colonp || all_idx >= 0) { if (all_idx < 0) { - /* Find the mode. */ - if (modep[1] == '-' || modep[1] == ':') + // Find the mode + if (modep[1] == '-' || modep[1] == ':') { len = 1; - else + } else { len = 2; + } if (len == 1 && TOLOWER_ASC(modep[0]) == 'a') { all_idx = SHAPE_IDX_COUNT - 1; @@ -100,15 +136,15 @@ char_u *parse_shape_opt(int what) modep += len + 1; } - if (all_idx >= 0) + if (all_idx >= 0) { idx = all_idx--; - else if (round == 2) { + } else if (round == 2) { { - /* Set the defaults, for the missing parts */ + // Set the defaults, for the missing parts shape_table[idx].shape = SHAPE_BLOCK; - shape_table[idx].blinkwait = 700L; - shape_table[idx].blinkon = 400L; - shape_table[idx].blinkoff = 250L; + shape_table[idx].blinkwait = 0L; + shape_table[idx].blinkon = 0L; + shape_table[idx].blinkoff = 0L; } } @@ -208,6 +244,55 @@ char_u *parse_shape_opt(int what) shape_table[SHAPE_IDX_VE].id_lm = shape_table[SHAPE_IDX_V].id_lm; } } - + ui_mode_info_set(); return NULL; } + + +/// Map cursor mode from string to integer +/// +/// @param mode Fullname of the mode whose id we are looking for +/// @return -1 in case of failure, else the matching SHAPE_ID* integer +int cursor_mode_str2int(const char *mode) +{ + for (int current_mode = 0; current_mode < SHAPE_IDX_COUNT; current_mode++) { + if (strcmp(shape_table[current_mode].full_name, mode) == 0) { + return current_mode; + } + } + WLOG("Unknown mode %s", mode); + return -1; +} + + +/// Return the index into shape_table[] for the current mode. +int cursor_get_mode_idx(void) +{ + if (State == SHOWMATCH) { + return SHAPE_IDX_SM; + } else if (State & VREPLACE_FLAG) { + return SHAPE_IDX_R; + } else if (State & REPLACE_FLAG) { + return SHAPE_IDX_R; + } else if (State & INSERT) { + return SHAPE_IDX_I; + } else if (State & CMDLINE) { + if (cmdline_at_end()) { + return SHAPE_IDX_C; + } else if (cmdline_overstrike()) { + return SHAPE_IDX_CR; + } else { + return SHAPE_IDX_CI; + } + } else if (finish_op) { + return SHAPE_IDX_O; + } else if (VIsual_active) { + if (*p_sel == 'e') { + return SHAPE_IDX_VE; + } else { + return SHAPE_IDX_V; + } + } else { + return SHAPE_IDX_N; + } +} diff --git a/src/nvim/cursor_shape.h b/src/nvim/cursor_shape.h index 9ce1b6e0a0..2c466603f0 100644 --- a/src/nvim/cursor_shape.h +++ b/src/nvim/cursor_shape.h @@ -1,32 +1,37 @@ #ifndef NVIM_CURSOR_SHAPE_H #define NVIM_CURSOR_SHAPE_H -/* - * struct to store values from 'guicursor' and 'mouseshape' - */ -/* Indexes in shape_table[] */ -#define SHAPE_IDX_N 0 /* Normal mode */ -#define SHAPE_IDX_V 1 /* Visual mode */ -#define SHAPE_IDX_I 2 /* Insert mode */ -#define SHAPE_IDX_R 3 /* Replace mode */ -#define SHAPE_IDX_C 4 /* Command line Normal mode */ -#define SHAPE_IDX_CI 5 /* Command line Insert mode */ -#define SHAPE_IDX_CR 6 /* Command line Replace mode */ -#define SHAPE_IDX_O 7 /* Operator-pending mode */ -#define SHAPE_IDX_VE 8 /* Visual mode with 'selection' exclusive */ -#define SHAPE_IDX_CLINE 9 /* On command line */ -#define SHAPE_IDX_STATUS 10 /* A status line */ -#define SHAPE_IDX_SDRAG 11 /* dragging a status line */ -#define SHAPE_IDX_VSEP 12 /* A vertical separator line */ -#define SHAPE_IDX_VDRAG 13 /* dragging a vertical separator line */ -#define SHAPE_IDX_MORE 14 /* Hit-return or More */ -#define SHAPE_IDX_MOREL 15 /* Hit-return or More in last line */ -#define SHAPE_IDX_SM 16 /* showing matching paren */ -#define SHAPE_IDX_COUNT 17 - -#define SHAPE_BLOCK 0 /* block cursor */ -#define SHAPE_HOR 1 /* horizontal bar cursor */ -#define SHAPE_VER 2 /* vertical bar cursor */ +#include "nvim/types.h" +#include "nvim/api/private/defs.h" + +/// struct to store values from 'guicursor' and 'mouseshape' +/// Indexes in shape_table[] +typedef enum { +SHAPE_IDX_N = 0, ///< Normal mode +SHAPE_IDX_V = 1, ///< Visual mode +SHAPE_IDX_I = 2, ///< Insert mode +SHAPE_IDX_R = 3, ///< Replace mode +SHAPE_IDX_C = 4, ///< Command line Normal mode +SHAPE_IDX_CI = 5, ///< Command line Insert mode +SHAPE_IDX_CR = 6, ///< Command line Replace mode +SHAPE_IDX_O = 7, ///< Operator-pending mode +SHAPE_IDX_VE = 8, ///< Visual mode with 'selection' exclusive +SHAPE_IDX_CLINE = 9, ///< On command line +SHAPE_IDX_STATUS = 10, ///< On status line +SHAPE_IDX_SDRAG = 11, ///< dragging a status line +SHAPE_IDX_VSEP = 12, ///< On vertical separator line +SHAPE_IDX_VDRAG = 13, ///< dragging a vertical separator line +SHAPE_IDX_MORE = 14, ///< Hit-return or More +SHAPE_IDX_MOREL = 15, ///< Hit-return or More in last line +SHAPE_IDX_SM = 16, ///< showing matching paren +SHAPE_IDX_COUNT = 17 +} ModeShape; + +typedef enum { +SHAPE_BLOCK = 0, ///< block cursor +SHAPE_HOR = 1, ///< horizontal bar cursor +SHAPE_VER = 2 ///< vertical bar cursor +} CursorShape; #define MSHAPE_NUMBERED 1000 /* offset for shapes identified by number */ #define MSHAPE_HIDE 1 /* hide mouse pointer */ @@ -35,18 +40,20 @@ #define SHAPE_CURSOR 2 /* used for text cursor shape */ typedef struct cursor_entry { - int shape; /* one of the SHAPE_ defines */ - int mshape; /* one of the MSHAPE defines */ - int percentage; /* percentage of cell for bar */ - long blinkwait; /* blinking, wait time before blinking starts */ - long blinkon; /* blinking, on time */ - long blinkoff; /* blinking, off time */ - int id; /* highlight group ID */ - int id_lm; /* highlight group ID for :lmap mode */ - char *name; /* mode name (fixed) */ - char used_for; /* SHAPE_MOUSE and/or SHAPE_CURSOR */ + char *full_name; ///< mode description + CursorShape shape; ///< cursor shape: one of the SHAPE_ defines + int mshape; ///< mouse shape: one of the MSHAPE defines + int percentage; ///< percentage of cell for bar + long blinkwait; ///< blinking, wait time before blinking starts + long blinkon; ///< blinking, on time + long blinkoff; ///< blinking, off time + int id; ///< highlight group ID + int id_lm; ///< highlight group ID for :lmap mode + char *name; ///< mode short name + char used_for; ///< SHAPE_MOUSE and/or SHAPE_CURSOR } cursorentry_T; +extern cursorentry_T shape_table[SHAPE_IDX_COUNT]; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "cursor_shape.h.generated.h" diff --git a/src/nvim/diff.c b/src/nvim/diff.c index f7b96ba3e1..17de4284ce 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -1,3 +1,6 @@ +// 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 + /// @file diff.c /// /// Code for diff'ing two, three or four buffers. @@ -129,7 +132,7 @@ void diff_buf_add(buf_T *buf) } } - EMSGN(_("E96: Can not diff more than %" PRId64 " buffers"), DB_COUNT); + EMSGN(_("E96: Cannot diff more than %" PRId64 " buffers"), DB_COUNT); } /// Find buffer "buf" in the list of diff buffers for the current tab page. @@ -1004,7 +1007,12 @@ theend: void ex_diffsplit(exarg_T *eap) { win_T *old_curwin = curwin; - buf_T *old_curbuf = curbuf; + bufref_T old_curbuf; + set_bufref(&old_curbuf, curbuf); + + // Need to compute w_fraction when no redraw happened yet. + validate_cursor(); + set_fraction(curwin); // don't use a new tab page, each tab page has its own diffs cmdmod.tab = 0; @@ -1022,15 +1030,15 @@ void ex_diffsplit(exarg_T *eap) if (win_valid(old_curwin)) { diff_win_options(old_curwin, true); - if (buf_valid(old_curbuf)) { + if (bufref_valid(&old_curbuf)) { // Move the cursor position to that of the old window. curwin->w_cursor.lnum = diff_get_corresponding_line( - old_curbuf, - old_curwin->w_cursor.lnum, - curbuf, - curwin->w_cursor.lnum); + old_curbuf.br_buf, old_curwin->w_cursor.lnum); } } + // Now that lines are folded scroll to show the cursor at the same + // relative position. + scroll_to_fraction(curwin, curwin->w_height); } } } @@ -1068,8 +1076,8 @@ void diff_win_options(win_T *wp, int addbuf) if (!wp->w_p_diff) { wp->w_p_wrap_save = wp->w_p_wrap; } - wp->w_p_wrap = FALSE; - curwin = wp; + wp->w_p_wrap = false; + curwin = wp; // -V519 curbuf = curwin->w_buffer; if (!wp->w_p_diff) { @@ -1153,10 +1161,13 @@ void ex_diffoff(exarg_T *eap) } foldUpdateAll(wp); - - // make sure topline is not halfway through a fold - changed_window_setting_win(wp); } + // remove filler lines + wp->w_topfill = 0; + + // make sure topline is not halfway a fold and cursor is + // invalidated + changed_window_setting_win(wp); // Note: 'sbo' is not restored, it's a global option. diff_buf_adjust(wp); @@ -1575,7 +1586,7 @@ static int diff_cmp(char_u *s1, char_u *s2) } if ((diff_flags & DIFF_ICASE) && !(diff_flags & DIFF_IWHITE)) { - return mb_stricmp(s1, s2); + return mb_stricmp((const char *)s1, (const char *)s2); } // Ignore white space changes and possibly ignore case. @@ -2297,7 +2308,7 @@ void ex_diffgetput(exarg_T *eap) // Adjust marks. This will change the following entries! if (added != 0) { - mark_adjust(lnum, lnum + count - 1, (long)MAXLNUM, (long)added); + mark_adjust(lnum, lnum + count - 1, (long)MAXLNUM, (long)added, false); if (curwin->w_cursor.lnum >= lnum) { // Adjust the cursor position if it's in/after the changed // lines. @@ -2449,25 +2460,17 @@ int diff_move_to(int dir, long count) return OK; } -/// Finds the corresponding line in a diff. -/// -/// @param buf1 -/// @param lnum1 -/// @param buf2 -/// @param lnum3 -/// -/// @return The corresponding line. -linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1, buf_T *buf2, - linenr_T lnum3) +/// Return the line number in the current window that is closest to "lnum1" in +/// "buf1" in diff mode. +static linenr_T diff_get_corresponding_line_int(buf_T *buf1, linenr_T lnum1) { int idx1; int idx2; diff_T *dp; int baseline = 0; - linenr_T lnum2; idx1 = diff_buf_idx(buf1); - idx2 = diff_buf_idx(buf2); + idx2 = diff_buf_idx(curbuf); if ((idx1 == DB_COUNT) || (idx2 == DB_COUNT) @@ -2487,15 +2490,9 @@ linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1, buf_T *buf2, for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) { if (dp->df_lnum[idx1] > lnum1) { - lnum2 = lnum1 - baseline; - - // don't end up past the end of the file - if (lnum2 > buf2->b_ml.ml_line_count) { - lnum2 = buf2->b_ml.ml_line_count; - } - - return lnum2; - } else if ((dp->df_lnum[idx1] + dp->df_count[idx1]) > lnum1) { + return lnum1 - baseline; + } + if ((dp->df_lnum[idx1] + dp->df_count[idx1]) > lnum1) { // Inside the diffblock baseline = lnum1 - dp->df_lnum[idx1]; @@ -2504,30 +2501,42 @@ linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1, buf_T *buf2, } return dp->df_lnum[idx2] + baseline; - } else if ((dp->df_lnum[idx1] == lnum1) - && (dp->df_count[idx1] == 0) - && (dp->df_lnum[idx2] <= lnum3) - && ((dp->df_lnum[idx2] + dp->df_count[idx2]) > lnum3)) { + } + if ((dp->df_lnum[idx1] == lnum1) + && (dp->df_count[idx1] == 0) + && (dp->df_lnum[idx2] <= curwin->w_cursor.lnum) + && ((dp->df_lnum[idx2] + dp->df_count[idx2]) + > curwin->w_cursor.lnum)) { // Special case: if the cursor is just after a zero-count // block (i.e. all filler) and the target cursor is already // inside the corresponding block, leave the target cursor // unmoved. This makes repeated CTRL-W W operations work // as expected. - return lnum3; + return curwin->w_cursor.lnum; } baseline = (dp->df_lnum[idx1] + dp->df_count[idx1]) - - (dp->df_lnum[idx2] + dp->df_count[idx2]); + - (dp->df_lnum[idx2] + dp->df_count[idx2]); } // If we get here then the cursor is after the last diff - lnum2 = lnum1 - baseline; + return lnum1 - baseline; +} + +/// Finds the corresponding line in a diff. +/// +/// @param buf1 +/// @param lnum1 +/// +/// @return The corresponding line. +linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1) +{ + linenr_T lnum = diff_get_corresponding_line_int(buf1, lnum1); // don't end up past the end of the file - if (lnum2 > buf2->b_ml.ml_line_count) { - lnum2 = buf2->b_ml.ml_line_count; + if (lnum > curbuf->b_ml.ml_line_count) { + return curbuf->b_ml.ml_line_count; } - - return lnum2; + return lnum; } /// For line "lnum" in the current window find the equivalent lnum in window diff --git a/src/nvim/diff.h b/src/nvim/diff.h index f6cef1cafd..3624ce29bb 100644 --- a/src/nvim/diff.h +++ b/src/nvim/diff.h @@ -1,6 +1,9 @@ #ifndef NVIM_DIFF_H #define NVIM_DIFF_H +#include "nvim/pos.h" +#include "nvim/ex_cmds_defs.h" + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "diff.h.generated.h" #endif diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c index 6ba6e659a6..bfb1b94738 100644 --- a/src/nvim/digraph.c +++ b/src/nvim/digraph.c @@ -1,3 +1,6 @@ +// 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 + /// @file digraph.c /// /// code for digraphs @@ -790,6 +793,7 @@ static digr_T digraphdefault[] = { '/', '-', 0x2020 }, { '/', '=', 0x2021 }, { '.', '.', 0x2025 }, + { ',', '.', 0x2026 }, { '%', '0', 0x2030 }, { '1', '\'', 0x2032 }, { '2', '\'', 0x2033 }, @@ -1448,10 +1452,8 @@ int get_digraph(int cmdline) { int cc; no_mapping++; - allow_keys++; int c = plain_vgetc(); no_mapping--; - allow_keys--; if (c != ESC) { // ESC cancels CTRL-K @@ -1468,10 +1470,8 @@ int get_digraph(int cmdline) add_to_showcmd(c); } no_mapping++; - allow_keys++; cc = plain_vgetc(); no_mapping--; - allow_keys--; if (cc != ESC) { // ESC cancels CTRL-K @@ -1573,7 +1573,8 @@ int getdigraph(int char1, int char2, int meta_char) if (((retval = getexactdigraph(char1, char2, meta_char)) == char2) && (char1 != char2) - && ((retval = getexactdigraph(char2, char1, meta_char)) == char1)) { + && ((retval = getexactdigraph(char2, char1, meta_char)) // -V764 + == char1)) { return char2; } return retval; @@ -1679,11 +1680,7 @@ static void printdigraph(digr_T *dp) int list_width; - if ((dy_flags & DY_UHEX) || has_mbyte) { - list_width = 13; - } else { - list_width = 11; - } + list_width = 13; if (dp->result != 0) { if (msg_col > Columns - list_width) { @@ -1704,15 +1701,11 @@ static void printdigraph(digr_T *dp) *p++ = dp->char2; *p++ = ' '; - if (has_mbyte) { - // add a space to draw a composing char on - if (enc_utf8 && utf_iscomposing(dp->result)) { - *p++ = ' '; - } - p += (*mb_char2bytes)(dp->result, p); - } else { - *p++ = (char_u)dp->result; + // add a space to draw a composing char on + if (utf_iscomposing(dp->result)) { + *p++ = ' '; } + p += (*mb_char2bytes)(dp->result, p); if (char2cells(dp->result) == 1) { *p++ = ' '; diff --git a/src/nvim/digraph.h b/src/nvim/digraph.h index b623969e08..1b73ccaf3f 100644 --- a/src/nvim/digraph.h +++ b/src/nvim/digraph.h @@ -1,6 +1,9 @@ #ifndef NVIM_DIGRAPH_H #define NVIM_DIGRAPH_H +#include "nvim/types.h" +#include "nvim/ex_cmds_defs.h" + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "digraph.h.generated.h" #endif diff --git a/src/nvim/edit.c b/src/nvim/edit.c index bb946337b5..17f0b8ef82 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1,3 +1,6 @@ +// 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 + /* * edit.c: functions for Insert mode */ @@ -15,6 +18,7 @@ #include "nvim/cursor.h" #include "nvim/digraph.h" #include "nvim/eval.h" +#include "nvim/eval/typval.h" #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" #include "nvim/farsi.h" @@ -458,7 +462,7 @@ static void insert_enter(InsertState *s) // Always update o_lnum, so that a "CTRL-O ." that adds a line // still puts the cursor back after the inserted text. - if (ins_at_eol && gchar_cursor() == NUL) { + if (ins_at_eol) { o_lnum = curwin->w_cursor.lnum; } @@ -689,11 +693,9 @@ static int insert_execute(VimState *state, int key) if (s->c == Ctrl_BSL) { // may need to redraw when no more chars available now ins_redraw(false); - ++no_mapping; - ++allow_keys; + no_mapping++; s->c = plain_vgetc(); - --no_mapping; - --allow_keys; + no_mapping--; if (s->c != Ctrl_N && s->c != Ctrl_G && s->c != Ctrl_O) { // it's something else vungetc(s->c); @@ -800,9 +802,9 @@ static int insert_handle_key(InsertState *s) if (!p_im) { goto normalchar; // insert CTRL-Z as normal char } - stuffReadbuff((char_u *)":st\r"); - s->c = Ctrl_O; - // FALLTHROUGH + do_cmdline_cmd("stop"); + ui_cursor_shape(); // may need to update cursor shape + break; case Ctrl_O: // execute one command if (ctrl_x_mode == CTRL_X_OMNI) { @@ -844,6 +846,11 @@ static int insert_handle_key(InsertState *s) return 0; // exit insert mode + case ' ': + if (mod_mask != 4) { + goto normalchar; + } + // FALLTHROUGH case K_ZERO: // Insert the previously inserted text. case NUL: case Ctrl_A: @@ -1419,7 +1426,7 @@ static void ins_ctrl_v(void) edit_putchar('^', TRUE); did_putchar = TRUE; } - AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */ + AppendToRedobuff(CTRL_V_STR); add_to_showcmd_c(Ctrl_V); @@ -1859,8 +1866,9 @@ static bool check_compl_option(bool dict_opt) : (*curbuf->b_p_tsr == NUL && *p_tsr == NUL)) { ctrl_x_mode = 0; edit_submode = NULL; - msg_attr(dict_opt ? (char_u *)_("'dictionary' option is empty") - : (char_u *)_("'thesaurus' option is empty"), hl_attr(HLF_E)); + msg_attr((dict_opt + ? _("'dictionary' option is empty") + : _("'thesaurus' option is empty")), hl_attr(HLF_E)); if (emsg_silent == 0) { vim_beep(BO_COMPL); setcursor(); @@ -1972,7 +1980,6 @@ static bool ins_compl_accept_char(int c) */ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int dir, int flags) { - char_u *p; int i, c; int actual_len; /* Take multi-byte characters */ int actual_compl_length; /* into account. */ @@ -1982,11 +1989,11 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int int was_letter = FALSE; if (p_ic && curbuf->b_p_inf && len > 0) { - /* Infer case of completed part. */ + // Infer case of completed part. - /* Find actual length of completion. */ + // Find actual length of completion. if (has_mbyte) { - p = str; + const char_u *p = str; actual_len = 0; while (*p != NUL) { mb_ptr_adv(p); @@ -1997,7 +2004,7 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int /* Find actual length of original text. */ if (has_mbyte) { - p = compl_orig_text; + const char_u *p = compl_orig_text; actual_compl_length = 0; while (*p != NUL) { mb_ptr_adv(p); @@ -2013,27 +2020,35 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int /* Allocate wide character array for the completion and fill it. */ wca = xmalloc(actual_len * sizeof(*wca)); - p = str; - for (i = 0; i < actual_len; ++i) - if (has_mbyte) - wca[i] = mb_ptr2char_adv(&p); - else - wca[i] = *(p++); + { + const char_u *p = str; + for (i = 0; i < actual_len; i++) { + if (has_mbyte) { + wca[i] = mb_ptr2char_adv(&p); + } else { + wca[i] = *(p++); + } + } + } - /* Rule 1: Were any chars converted to lower? */ - p = compl_orig_text; - for (i = 0; i < min_len; ++i) { - if (has_mbyte) - c = mb_ptr2char_adv(&p); - else - c = *(p++); - if (vim_islower(c)) { - has_lower = TRUE; - if (vim_isupper(wca[i])) { - /* Rule 1 is satisfied. */ - for (i = actual_compl_length; i < actual_len; ++i) - wca[i] = vim_tolower(wca[i]); - break; + // Rule 1: Were any chars converted to lower? + { + const char_u *p = compl_orig_text; + for (i = 0; i < min_len; i++) { + if (has_mbyte) { + c = mb_ptr2char_adv(&p); + } else { + c = *(p++); + } + if (mb_islower(c)) { + has_lower = true; + if (mb_isupper(wca[i])) { + // Rule 1 is satisfied. + for (i = actual_compl_length; i < actual_len; i++) { + wca[i] = mb_tolower(wca[i]); + } + break; + } } } } @@ -2043,84 +2058,110 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int * upper case. */ if (!has_lower) { - p = compl_orig_text; - for (i = 0; i < min_len; ++i) { - if (has_mbyte) + const char_u *p = compl_orig_text; + for (i = 0; i < min_len; i++) { + if (has_mbyte) { c = mb_ptr2char_adv(&p); - else + } else { c = *(p++); - if (was_letter && vim_isupper(c) && vim_islower(wca[i])) { - /* Rule 2 is satisfied. */ - for (i = actual_compl_length; i < actual_len; ++i) - wca[i] = vim_toupper(wca[i]); + } + if (was_letter && mb_isupper(c) && mb_islower(wca[i])) { + // Rule 2 is satisfied. + for (i = actual_compl_length; i < actual_len; i++) { + wca[i] = mb_toupper(wca[i]); + } break; } - was_letter = vim_islower(c) || vim_isupper(c); + was_letter = mb_islower(c) || mb_isupper(c); } } - /* Copy the original case of the part we typed. */ - p = compl_orig_text; - for (i = 0; i < min_len; ++i) { - if (has_mbyte) - c = mb_ptr2char_adv(&p); - else - c = *(p++); - if (vim_islower(c)) - wca[i] = vim_tolower(wca[i]); - else if (vim_isupper(c)) - wca[i] = vim_toupper(wca[i]); + // Copy the original case of the part we typed. + { + const char_u *p = compl_orig_text; + for (i = 0; i < min_len; i++) { + if (has_mbyte) { + c = mb_ptr2char_adv(&p); + } else { + c = *(p++); + } + if (mb_islower(c)) { + wca[i] = mb_tolower(wca[i]); + } else if (mb_isupper(c)) { + wca[i] = mb_toupper(wca[i]); + } + } } - /* - * Generate encoding specific output from wide character array. - * Multi-byte characters can occupy up to five bytes more than - * ASCII characters, and we also need one byte for NUL, so stay - * six bytes away from the edge of IObuff. - */ - p = IObuff; - i = 0; - while (i < actual_len && (p - IObuff + 6) < IOSIZE) - if (has_mbyte) - p += (*mb_char2bytes)(wca[i++], p); - else - *(p++) = wca[i++]; - *p = NUL; + // Generate encoding specific output from wide character array. + // Multi-byte characters can occupy up to five bytes more than + // ASCII characters, and we also need one byte for NUL, so stay + // six bytes away from the edge of IObuff. + { + char_u *p = IObuff; + i = 0; + while (i < actual_len && (p - IObuff + 6) < IOSIZE) { + if (has_mbyte) { + p += (*mb_char2bytes)(wca[i++], p); + } else { + *(p++) = wca[i++]; + } + } + *p = NUL; + } xfree(wca); - return ins_compl_add(IObuff, len, icase, fname, NULL, dir, - flags, FALSE); + return ins_compl_add(IObuff, len, icase, fname, NULL, false, dir, flags, + false); } - return ins_compl_add(str, len, icase, fname, NULL, dir, flags, FALSE); + return ins_compl_add(str, len, icase, fname, NULL, false, dir, flags, false); } -/* - * Add a match to the list of matches. - * If the given string is already in the list of completions, then return - * NOTDONE, otherwise add it to the list and return OK. If there is an error - * then FAIL is returned. - */ -static int -ins_compl_add ( - char_u *str, - int len, - int icase, - char_u *fname, - char_u **cptext, /* extra text for popup menu or NULL */ - int cdir, - int flags, - int adup /* accept duplicate match */ -) +/// Add a match to the list of matches +/// +/// @param[in] str Match to add. +/// @param[in] len Match length, -1 to use #STRLEN. +/// @param[in] icase Whether case is to be ignored. +/// @param[in] fname File name match comes from. May be NULL. +/// @param[in] cptext Extra text for popup menu. May be NULL. If not NULL, +/// must have exactly #CPT_COUNT items. +/// @param[in] cptext_allocated If true, will not copy cptext strings. +/// +/// @note Will free strings in case of error. +/// cptext itself will not be freed. +/// @param[in] cdir Completion direction. +/// @param[in] adup True if duplicate matches are to be accepted. +/// +/// @return NOTDONE if the given string is already in the list of completions, +/// otherwise it is added to the list and OK is returned. FAIL will be +/// returned in case of error. +static int ins_compl_add(char_u *const str, int len, + const bool icase, char_u *const fname, + char_u *const *const cptext, + const bool cptext_allocated, + const Direction cdir, int flags, const bool adup) + FUNC_ATTR_NONNULL_ARG(1) { compl_T *match; - int dir = (cdir == 0 ? compl_direction : cdir); + int dir = (cdir == kDirectionNotSet ? compl_direction : cdir); os_breakcheck(); - if (got_int) +#define FREE_CPTEXT(cptext, cptext_allocated) \ + do { \ + if (cptext != NULL && cptext_allocated) { \ + for (size_t i = 0; i < CPT_COUNT; i++) { \ + xfree(cptext[i]); \ + } \ + } \ + } while (0) + if (got_int) { + FREE_CPTEXT(cptext, cptext_allocated); return FAIL; - if (len < 0) + } + if (len < 0) { len = (int)STRLEN(str); + } /* * If the same match is already present, don't add it. @@ -2128,10 +2169,12 @@ ins_compl_add ( if (compl_first_match != NULL && !adup) { match = compl_first_match; do { - if ( !(match->cp_flags & ORIGINAL_TEXT) - && STRNCMP(match->cp_str, str, len) == 0 - && match->cp_str[len] == NUL) + if (!(match->cp_flags & ORIGINAL_TEXT) + && STRNCMP(match->cp_str, str, len) == 0 + && match->cp_str[len] == NUL) { + FREE_CPTEXT(cptext, cptext_allocated); return NOTDONE; + } match = match->cp_next; } while (match != NULL && match != compl_first_match); } @@ -2162,16 +2205,26 @@ ins_compl_add ( else if (fname != NULL) { match->cp_fname = vim_strsave(fname); flags |= FREE_FNAME; - } else + } else { match->cp_fname = NULL; + } match->cp_flags = flags; if (cptext != NULL) { int i; - for (i = 0; i < CPT_COUNT; ++i) - if (cptext[i] != NULL && *cptext[i] != NUL) - match->cp_text[i] = vim_strsave(cptext[i]); + for (i = 0; i < CPT_COUNT; i++) { + if (cptext[i] == NULL) { + continue; + } + if (*cptext[i] != NUL) { + match->cp_text[i] = (cptext_allocated + ? cptext[i] + : (char_u *)xstrdup((char *)cptext[i])); + } else if (cptext_allocated) { + xfree(cptext[i]); + } + } } /* @@ -2252,9 +2305,10 @@ static void ins_compl_longest_match(compl_T *match) c1 = *p; c2 = *s; } - if (match->cp_icase ? (vim_tolower(c1) != vim_tolower(c2)) - : (c1 != c2)) + if (match->cp_icase ? (mb_tolower(c1) != mb_tolower(c2)) + : (c1 != c2)) { break; + } if (has_mbyte) { mb_ptr_adv(p); mb_ptr_adv(s); @@ -2294,9 +2348,10 @@ static void ins_compl_add_matches(int num_matches, char_u **matches, int icase) for (i = 0; i < num_matches && add_r != FAIL; i++) if ((add_r = ins_compl_add(matches[i], -1, icase, - NULL, NULL, dir, 0, FALSE)) == OK) - /* if dir was BACKWARD then honor it just once */ + NULL, NULL, false, dir, 0, false)) == OK) { + // If dir was BACKWARD then honor it just once. dir = FORWARD; + } FreeWild(num_matches, matches); } @@ -2351,6 +2406,7 @@ void set_completion(colnr_T startcol, list_T *list) ins_compl_prep(' '); } ins_compl_clear(); + ins_compl_free(); compl_direction = FORWARD; if (startcol > curwin->w_cursor.col) @@ -2360,8 +2416,8 @@ void set_completion(colnr_T startcol, list_T *list) /* compl_pattern doesn't need to be set */ compl_orig_text = vim_strnsave(get_cursor_line_ptr() + compl_col, compl_length); - if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, 0, - ORIGINAL_TEXT, FALSE) != OK) { + if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, false, 0, + ORIGINAL_TEXT, false) != OK) { return; } @@ -2373,6 +2429,7 @@ void set_completion(colnr_T startcol, list_T *list) compl_used_match = TRUE; compl_cont_status = 0; int save_w_wrow = curwin->w_wrow; + int save_w_leftcol = curwin->w_leftcol; compl_curr_match = compl_first_match; if (compl_no_insert || compl_no_select) { @@ -2387,7 +2444,7 @@ void set_completion(colnr_T startcol, list_T *list) // Lazily show the popup menu, unless we got interrupted. if (!compl_interrupted) { - show_pum(save_w_wrow); + show_pum(save_w_wrow, save_w_leftcol); } ui_flush(); @@ -2882,7 +2939,7 @@ static void ins_compl_clear(void) compl_orig_text = NULL; compl_enter_selects = FALSE; // clear v:completed_item - set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc()); + set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc()); } /// Check that Insert completion is active. @@ -2907,11 +2964,14 @@ static int ins_compl_bs(void) p = line + curwin->w_cursor.col; mb_ptr_back(line, p); - /* Stop completion when the whole word was deleted. For Omni completion - * allow the word to be deleted, we won't match everything. */ + // Stop completion when the whole word was deleted. For Omni completion + // allow the word to be deleted, we won't match everything. + // Respect the 'backspace' option. if ((int)(p - line) - (int)compl_col < 0 || ((int)(p - line) - (int)compl_col == 0 - && ctrl_x_mode != CTRL_X_OMNI) || ctrl_x_mode == CTRL_X_EVAL) { + && ctrl_x_mode != CTRL_X_OMNI) || ctrl_x_mode == CTRL_X_EVAL + || (!can_bs(BS_START) && (int)(p - line) - (int)compl_col + - compl_length < 0)) { return K_BS; } @@ -3000,6 +3060,9 @@ static void ins_compl_addleader(int c) { int cc; + if (stop_arrow() == FAIL) { + return; + } if (has_mbyte && (cc = (*mb_char2len)(c)) > 1) { char_u buf[MB_MAXBYTES + 1]; @@ -3368,10 +3431,10 @@ static void ins_compl_fixRedoBufForLeader(char_u *ptr_arg) len -= (*mb_head_off)(p, p + len); for (p += len; *p != NUL; mb_ptr_adv(p)) AppendCharToRedobuff(K_BS); - } else + } else { len = 0; - if (ptr != NULL) - AppendToRedobuffLit(ptr + len, -1); + } + AppendToRedobuffLit(ptr + len, -1); } /* @@ -3421,7 +3484,6 @@ expand_by_function ( { list_T *matchlist = NULL; dict_T *matchdict = NULL; - char_u *args[2]; char_u *funcname; pos_T pos; win_T *curwin_save; @@ -3432,9 +3494,8 @@ expand_by_function ( if (*funcname == NUL) return; - /* Call 'completefunc' to obtain the list of matches. */ - args[0] = (char_u *)"0"; - args[1] = base; + // Call 'completefunc' to obtain the list of matches. + const char_u *const args[2] = { (char_u *)"0", base }; pos = curwin->w_cursor; curwin_save = curwin; @@ -3450,8 +3511,8 @@ expand_by_function ( matchdict = rettv.vval.v_dict; break; default: - /* TODO: Give error message? */ - clear_tv(&rettv); + // TODO(brammool): Give error message? + tv_clear(&rettv); break; } } @@ -3473,10 +3534,12 @@ expand_by_function ( ins_compl_add_dict(matchdict); theend: - if (matchdict != NULL) - dict_unref(matchdict); - if (matchlist != NULL) - list_unref(matchlist); + if (matchdict != NULL) { + tv_dict_unref(matchdict); + } + if (matchlist != NULL) { + tv_list_unref(matchlist); + } } /* @@ -3505,53 +3568,60 @@ static void ins_compl_add_dict(dict_T *dict) dictitem_T *di_refresh; dictitem_T *di_words; - /* Check for optional "refresh" item. */ - compl_opt_refresh_always = FALSE; - di_refresh = dict_find(dict, (char_u *)"refresh", 7); + // Check for optional "refresh" item. + compl_opt_refresh_always = false; + di_refresh = tv_dict_find(dict, S_LEN("refresh")); if (di_refresh != NULL && di_refresh->di_tv.v_type == VAR_STRING) { - char_u *v = di_refresh->di_tv.vval.v_string; + const char *v = (const char *)di_refresh->di_tv.vval.v_string; - if (v != NULL && STRCMP(v, (char_u *)"always") == 0) - compl_opt_refresh_always = TRUE; + if (v != NULL && strcmp(v, "always") == 0) { + compl_opt_refresh_always = true; + } } - /* Add completions from a "words" list. */ - di_words = dict_find(dict, (char_u *)"words", 5); - if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST) + // Add completions from a "words" list. + di_words = tv_dict_find(dict, S_LEN("words")); + if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST) { ins_compl_add_list(di_words->di_tv.vval.v_list); + } } -/* - * Add a match to the list of matches from a typeval_T. - * If the given string is already in the list of completions, then return - * NOTDONE, otherwise add it to the list and return OK. If there is an error - * then FAIL is returned. - */ -int ins_compl_add_tv(typval_T *tv, int dir) -{ - char_u *word; - int icase = FALSE; - int adup = FALSE; - int aempty = FALSE; - char_u *(cptext[CPT_COUNT]); +/// Add a match to the list of matches from VimL object +/// +/// @param[in] tv Object to get matches from. +/// @param[in] dir Completion direction. +/// +/// @return NOTDONE if the given string is already in the list of completions, +/// otherwise it is added to the list and OK is returned. FAIL will be +/// returned in case of error. +int ins_compl_add_tv(typval_T *const tv, const Direction dir) + FUNC_ATTR_NONNULL_ALL +{ + const char *word; + bool icase = false; + bool adup = false; + bool aempty = false; + char *(cptext[CPT_COUNT]); if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) { - word = get_dict_string(tv->vval.v_dict, "word", false); - cptext[CPT_ABBR] = get_dict_string(tv->vval.v_dict, "abbr", false); - cptext[CPT_MENU] = get_dict_string(tv->vval.v_dict, "menu", false); - cptext[CPT_KIND] = get_dict_string(tv->vval.v_dict, "kind", false); - cptext[CPT_INFO] = get_dict_string(tv->vval.v_dict, "info", false); - - icase = get_dict_number(tv->vval.v_dict, "icase"); - adup = get_dict_number(tv->vval.v_dict, "dup"); - aempty = get_dict_number(tv->vval.v_dict, "empty"); + word = tv_dict_get_string(tv->vval.v_dict, "word", false); + cptext[CPT_ABBR] = tv_dict_get_string(tv->vval.v_dict, "abbr", true); + cptext[CPT_MENU] = tv_dict_get_string(tv->vval.v_dict, "menu", true); + cptext[CPT_KIND] = tv_dict_get_string(tv->vval.v_dict, "kind", true); + cptext[CPT_INFO] = tv_dict_get_string(tv->vval.v_dict, "info", true); + + icase = (bool)tv_dict_get_number(tv->vval.v_dict, "icase"); + adup = (bool)tv_dict_get_number(tv->vval.v_dict, "dup"); + aempty = (bool)tv_dict_get_number(tv->vval.v_dict, "empty"); } else { - word = get_tv_string_chk(tv); + word = (const char *)tv_get_string_chk(tv); memset(cptext, 0, sizeof(cptext)); } - if (word == NULL || (!aempty && *word == NUL)) + if (word == NULL || (!aempty && *word == NUL)) { return FAIL; - return ins_compl_add(word, -1, icase, NULL, cptext, dir, 0, adup); + } + return ins_compl_add((char_u *)word, -1, icase, NULL, + (char_u **)cptext, true, dir, 0, adup); } /* @@ -3847,13 +3917,11 @@ static int ins_compl_get_exp(pos_T *ini) if ((compl_cont_status & CONT_ADDING) && len == compl_length) { if (pos->lnum < ins_buf->b_ml.ml_line_count) { - /* Try next line, if any. the new word will be - * "join" as if the normal command "J" was used. - * IOSIZE is always greater than - * compl_length, so the next STRNCPY always - * works -- Acevedo */ + // Try next line, if any. the new word will be "join" as if the + // normal command "J" was used. IOSIZE is always greater than + // compl_length, so the next STRNCPY always works -- Acevedo STRNCPY(IObuff, ptr, len); - ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE); + ptr = ml_get_buf(ins_buf, pos->lnum + 1, false); tmp_ptr = ptr = skipwhite(ptr); /* Find start of next word. */ tmp_ptr = find_word_start(tmp_ptr); @@ -3968,7 +4036,7 @@ static void ins_compl_delete(void) // causes flicker, thus we can't do that. changed_cline_bef_curs(); // clear v:completed_item - set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc()); + set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc()); } // Insert the new text being completed. @@ -3983,17 +4051,21 @@ static void ins_compl_insert(int in_compl_func) // Set completed item. // { word, abbr, menu, kind, info } - dict_T *dict = dict_alloc(); - dict_add_nr_str(dict, "word", 0L, - EMPTY_IF_NULL(compl_shown_match->cp_str)); - dict_add_nr_str(dict, "abbr", 0L, - EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_ABBR])); - dict_add_nr_str(dict, "menu", 0L, - EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_MENU])); - dict_add_nr_str(dict, "kind", 0L, - EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_KIND])); - dict_add_nr_str(dict, "info", 0L, - EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_INFO])); + dict_T *dict = tv_dict_alloc(); + tv_dict_add_str(dict, S_LEN("word"), + (const char *)EMPTY_IF_NULL(compl_shown_match->cp_str)); + tv_dict_add_str( + dict, S_LEN("abbr"), + (const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_ABBR])); + tv_dict_add_str( + dict, S_LEN("menu"), + (const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_MENU])); + tv_dict_add_str( + dict, S_LEN("kind"), + (const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_KIND])); + tv_dict_add_str( + dict, S_LEN("info"), + (const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_INFO])); set_vim_var_dict(VV_COMPLETED_ITEM, dict); if (!in_compl_func) { compl_curr_match = compl_shown_match; @@ -4331,7 +4403,9 @@ static int ins_complete(int c, bool enable_pum) colnr_T curs_col; /* cursor column */ int n; int save_w_wrow; + int save_w_leftcol; int insert_match; + int save_did_ai = did_ai; compl_direction = ins_compl_key2dir(c); insert_match = ins_compl_use_match(c); @@ -4533,7 +4607,6 @@ static int ins_complete(int c, bool enable_pum) * Call user defined function 'completefunc' with "a:findstart" * set to 1 to obtain the length of text to use for completion. */ - char_u *args[2]; int col; char_u *funcname; pos_T pos; @@ -4547,11 +4620,12 @@ static int ins_complete(int c, bool enable_pum) if (*funcname == NUL) { EMSG2(_(e_notset), ctrl_x_mode == CTRL_X_FUNCTION ? "completefunc" : "omnifunc"); + // restore did_ai, so that adding comment leader works + did_ai = save_did_ai; return FAIL; } - args[0] = (char_u *)"1"; - args[1] = NULL; + const char_u *const args[2] = { (char_u *)"1", NULL }; pos = curwin->w_cursor; curwin_save = curwin; curbuf_save = curbuf; @@ -4651,8 +4725,8 @@ static int ins_complete(int c, bool enable_pum) /* Always add completion for the original text. */ xfree(compl_orig_text); compl_orig_text = vim_strnsave(line + compl_col, compl_length); - if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, 0, - ORIGINAL_TEXT, FALSE) != OK) { + if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, false, 0, + ORIGINAL_TEXT, false) != OK) { xfree(compl_pattern); compl_pattern = NULL; xfree(compl_orig_text); @@ -4680,6 +4754,7 @@ static int ins_complete(int c, bool enable_pum) * Find next match (and following matches). */ save_w_wrow = curwin->w_wrow; + save_w_leftcol = curwin->w_leftcol; n = ins_compl_next(true, ins_compl_key2count(c), insert_match, false); /* may undisplay the popup menu */ @@ -4803,9 +4878,9 @@ static int ins_complete(int c, bool enable_pum) if (!shortmess(SHM_COMPLETIONMENU)) { if (edit_submode_extra != NULL) { if (!p_smd) { - msg_attr(edit_submode_extra, - edit_submode_highl < HLF_COUNT - ? hl_attr(edit_submode_highl) : 0); + msg_attr((const char *)edit_submode_extra, + (edit_submode_highl < HLF_COUNT + ? hl_attr(edit_submode_highl) : 0)); } } else { msg_clr_cmdline(); // necessary for "noshowmode" @@ -4814,7 +4889,7 @@ static int ins_complete(int c, bool enable_pum) // Show the popup menu, unless we got interrupted. if (enable_pum && !compl_interrupted) { - show_pum(save_w_wrow); + show_pum(save_w_wrow, save_w_leftcol); } compl_was_interrupted = compl_interrupted; compl_interrupted = FALSE; @@ -4840,14 +4915,17 @@ static unsigned quote_meta(char_u *dest, char_u *src, int len) if (ctrl_x_mode == CTRL_X_DICTIONARY || ctrl_x_mode == CTRL_X_THESAURUS) break; + // fallthrough case '~': if (!p_magic) /* quote these only if magic is set */ break; + // fallthrough case '\\': if (ctrl_x_mode == CTRL_X_DICTIONARY || ctrl_x_mode == CTRL_X_THESAURUS) break; - case '^': /* currently it's not needed. */ + // fallthrough + case '^': // currently it's not needed. case '$': m++; if (dest != NULL) @@ -5730,15 +5808,16 @@ comp_textwidth ( */ static void redo_literal(int c) { - char_u buf[10]; + char buf[10]; - /* Only digits need special treatment. Translate them into a string of - * three digits. */ + // Only digits need special treatment. Translate them into a string of + // three digits. if (ascii_isdigit(c)) { - vim_snprintf((char *)buf, sizeof(buf), "%03d", c); + vim_snprintf(buf, sizeof(buf), "%03d", c); AppendToRedobuff(buf); - } else + } else { AppendCharToRedobuff(c); + } } // start_arrow() is called when an arrow key is used in insert mode. @@ -5767,8 +5846,8 @@ static void start_arrow_common(pos_T *end_insert_pos, bool end_change) { if (!arrow_used && end_change) { // something has been inserted AppendToRedobuff(ESC_STR); - stop_insert(end_insert_pos, FALSE, FALSE); - arrow_used = TRUE; /* this means we stopped the current insert */ + stop_insert(end_insert_pos, false, false); + arrow_used = true; // This means we stopped the current insert. } check_spell_redraw(); } @@ -5825,7 +5904,7 @@ int stop_arrow(void) vr_lines_changed = 1; } ResetRedobuff(); - AppendToRedobuff((char_u *)"1i"); /* pretend we start an insertion */ + AppendToRedobuff("1i"); // Pretend we start an insertion. new_insert_skip = 2; } else if (ins_need_undo) { if (u_save_cursor() == OK) @@ -6290,12 +6369,13 @@ stuff_inserted ( } do { - stuffReadbuff(ptr); - /* a trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^" */ - if (last) - stuffReadbuff((char_u *)(last == '0' - ? "\026\060\064\070" - : "\026^")); + stuffReadbuff((const char *)ptr); + // A trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^". + if (last) { + stuffReadbuff((last == '0' + ? "\026\060\064\070" + : "\026^")); + } } while (--count > 0); if (last) @@ -7052,8 +7132,8 @@ static void ins_ctrl_g(void) */ static void ins_ctrl_hat(void) { - if (map_to_exists_mode((char_u *)"", LANGMAP, FALSE)) { - /* ":lmap" mappings exists, Toggle use of ":lmap" mappings. */ + if (map_to_exists_mode("", LANGMAP, false)) { + // ":lmap" mappings exists, Toggle use of ":lmap" mappings. if (State & LANGMAP) { curbuf->b_p_iminsert = B_IMODE_NONE; State &= ~LANGMAP; @@ -7088,13 +7168,12 @@ static bool ins_esc(long *count, int cmdchar, bool nomove) disabled_redraw = false; } if (!arrow_used) { - /* - * Don't append the ESC for "r<CR>" and "grx". - * When 'insertmode' is set only CTRL-L stops Insert mode. Needed for - * when "count" is non-zero. - */ - if (cmdchar != 'r' && cmdchar != 'v') - AppendToRedobuff(p_im ? (char_u *)"\014" : ESC_STR); + // Don't append the ESC for "r<CR>" and "grx". + // When 'insertmode' is set only CTRL-L stops Insert mode. Needed for + // when "count" is non-zero. + if (cmdchar != 'r' && cmdchar != 'v') { + AppendToRedobuff(p_im ? "\014" : ESC_STR); + } /* * Repeating insert may take a long time. Check for @@ -7248,7 +7327,8 @@ static bool ins_start_select(int c) // Execute the key in (insert) Select mode. stuffcharReadbuff(Ctrl_O); if (mod_mask) { - char_u buf[4] = { K_SPECIAL, KS_MODIFIER, mod_mask, NUL }; + const char buf[] = { (char)K_SPECIAL, (char)KS_MODIFIER, + (char)(uint8_t)mod_mask, NUL }; stuffReadbuff(buf); } stuffcharReadbuff(c); @@ -8056,11 +8136,11 @@ static bool ins_tab(void) return true; } - did_ai = FALSE; - did_si = FALSE; - can_si = FALSE; - can_si_back = FALSE; - AppendToRedobuff((char_u *)"\t"); + did_ai = false; + did_si = false; + can_si = false; + can_si_back = false; + AppendToRedobuff("\t"); if (p_sta && ind) { // insert tab in indent, use "shiftwidth" temp = get_sw_value(curbuf); @@ -8287,17 +8367,16 @@ static int ins_digraph(void) } - /* don't map the digraph chars. This also prevents the - * mode message to be deleted when ESC is hit */ - ++no_mapping; - ++allow_keys; + // don't map the digraph chars. This also prevents the + // mode message to be deleted when ESC is hit + no_mapping++; c = plain_vgetc(); - --no_mapping; - --allow_keys; - if (did_putchar) - /* when the line fits in 'columns' the '?' is at the start of the next - * line and will not be removed by the redraw */ + no_mapping--; + if (did_putchar) { + // when the line fits in 'columns' the '?' is at the start of the next + // line and will not be removed by the redraw edit_unputchar(); + } if (IS_SPECIAL(c) || mod_mask) { /* special key */ clear_showcmd(); @@ -8317,18 +8396,17 @@ static int ins_digraph(void) } add_to_showcmd_c(c); } - ++no_mapping; - ++allow_keys; + no_mapping++; cc = plain_vgetc(); - --no_mapping; - --allow_keys; - if (did_putchar) - /* when the line fits in 'columns' the '?' is at the start of the - * next line and will not be removed by a redraw */ + no_mapping--; + if (did_putchar) { + // when the line fits in 'columns' the '?' is at the start of the + // next line and will not be removed by a redraw edit_unputchar(); + } if (cc != ESC) { - AppendToRedobuff((char_u *)CTRL_V_STR); - c = getdigraph(c, cc, TRUE); + AppendToRedobuff(CTRL_V_STR); + c = getdigraph(c, cc, true); clear_showcmd(); return c; } @@ -8390,12 +8468,13 @@ static int ins_ctrl_ey(int tc) if (c != NUL) { long tw_save; - /* The character must be taken literally, insert like it - * was typed after a CTRL-V, and pretend 'textwidth' - * wasn't set. Digits, 'o' and 'x' are special after a - * CTRL-V, don't use it for these. */ - if (c < 256 && !isalnum(c)) - AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */ + // The character must be taken literally, insert like it + // was typed after a CTRL-V, and pretend 'textwidth' + // wasn't set. Digits, 'o' and 'x' are special after a + // CTRL-V, don't use it for these. + if (c < 256 && !isalnum(c)) { + AppendToRedobuff(CTRL_V_STR); + } tw_save = curbuf->b_p_tw; curbuf->b_p_tw = -1; insert_special(c, TRUE, FALSE); @@ -8542,15 +8621,16 @@ static char_u *do_insert_char_pre(int c) return res; } -static void show_pum(int save_w_wrow) +static void show_pum(int prev_w_wrow, int prev_w_leftcol) { // RedrawingDisabled may be set when invoked through complete(). int n = RedrawingDisabled; RedrawingDisabled = 0; - // If the cursor moved we need to remove the pum first. + // If the cursor moved or the display scrolled we need to remove the pum + // first. setcursor(); - if (save_w_wrow != curwin->w_wrow) { + if (prev_w_wrow != curwin->w_wrow || prev_w_leftcol != curwin->w_leftcol) { ins_compl_del_pum(); } diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 17e89e5757..d6ee13857a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1,8 +1,12 @@ +// 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 + /* * eval.c: Expression evaluation. */ #include <assert.h> +#include <float.h> #include <inttypes.h> #include <stdarg.h> #include <string.h> @@ -30,6 +34,7 @@ #include "nvim/ex_eval.h" #include "nvim/ex_getln.h" #include "nvim/fileio.h" +#include "nvim/os/fileio.h" #include "nvim/func_attr.h" #include "nvim/fold.h" #include "nvim/getchar.h" @@ -42,6 +47,7 @@ #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" +#include "nvim/menu.h" #include "nvim/message.h" #include "nvim/misc1.h" #include "nvim/keymap.h" @@ -93,7 +99,13 @@ #include "nvim/lib/kvec.h" #include "nvim/lib/khash.h" #include "nvim/lib/queue.h" -#include "nvim/eval/typval_encode.h" +#include "nvim/lua/executor.h" +#include "nvim/eval/typval.h" +#include "nvim/eval/executor.h" +#include "nvim/eval/gc.h" +#include "nvim/macros.h" + +// TODO(ZyX-I): Remove DICT_MAXNEST, make users be non-recursive instead #define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */ @@ -131,31 +143,28 @@ * "newkey" is the key for the new item. */ typedef struct lval_S { - char_u *ll_name; /* start of variable name (can be NULL) */ - char_u *ll_exp_name; /* NULL or expanded name in allocated memory. */ - typval_T *ll_tv; /* Typeval of item being used. If "newkey" - isn't NULL it's the Dict to which to add - the item. */ - listitem_T *ll_li; /* The list item or NULL. */ - list_T *ll_list; /* The list or NULL. */ - int ll_range; /* TRUE when a [i:j] range was used */ - long ll_n1; /* First index for list */ - long ll_n2; /* Second index for list range */ - int ll_empty2; /* Second index is empty: [i:] */ - dict_T *ll_dict; /* The Dictionary or NULL */ - dictitem_T *ll_di; /* The dictitem or NULL */ - char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */ + const char *ll_name; ///< Start of variable name (can be NULL). + size_t ll_name_len; ///< Length of the .ll_name. + char *ll_exp_name; ///< NULL or expanded name in allocated memory. + typval_T *ll_tv; ///< Typeval of item being used. If "newkey" + ///< isn't NULL it's the Dict to which to add the item. + listitem_T *ll_li; ///< The list item or NULL. + list_T *ll_list; ///< The list or NULL. + int ll_range; ///< TRUE when a [i:j] range was used. + long ll_n1; ///< First index for list. + long ll_n2; ///< Second index for list range. + int ll_empty2; ///< Second index is empty: [i:]. + dict_T *ll_dict; ///< The Dictionary or NULL. + dictitem_T *ll_di; ///< The dictitem or NULL. + char_u *ll_newkey; ///< New key for Dict in allocated memory or NULL. } lval_T; static char *e_letunexp = N_("E18: Unexpected characters in :let"); -static char *e_listidx = N_("E684: list index out of range: %" PRId64); -static char *e_undefvar = N_("E121: Undefined variable: %s"); static char *e_missbrac = N_("E111: Missing ']'"); static char *e_listarg = N_("E686: Argument of %s must be a List"); static char *e_listdictarg = N_( "E712: Argument of %s must be a List or Dictionary"); -static char *e_emptykey = N_("E713: Cannot use empty key for Dictionary"); static char *e_listreq = N_("E714: List required"); static char *e_dictreq = N_("E715: Dictionary required"); static char *e_stringreq = N_("E928: String required"); @@ -166,15 +175,20 @@ static char *e_funcexts = N_( static char *e_funcdict = N_("E717: Dictionary entry already exists"); static char *e_funcref = N_("E718: Funcref required"); static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary"); -static char *e_letwrong = N_("E734: Wrong variable type for %s="); static char *e_nofunc = N_("E130: Unknown function: %s"); static char *e_illvar = N_("E461: Illegal variable name: %s"); -static char *e_float_as_string = N_("E806: using Float as a String"); +static const char *e_readonlyvar = N_( + "E46: Cannot change read-only variable \"%.*s\""); + +// TODO(ZyX-I): move to eval/executor +static char *e_letwrong = N_("E734: Wrong variable type for %s="); -static char_u * const empty_string = (char_u *)""; static char_u * const namespace_char = (char_u *)"abglstvw"; -static dictitem_T globvars_var; /* variable used for g: */ +/// Variable used for g: +static ScopeDictDictItem globvars_var; + +/// g: value #define globvarht globvardict.dv_hashtab /* @@ -185,12 +199,15 @@ static hashtab_T compat_hashtab; hashtab_T func_hashtab; +// Used for checking if local variables or arguments used in a lambda. +static int *eval_lavars_used = NULL; + /* * Array to hold the hashtab with variables local to each sourced script. * Each item holds a variable (nameless) that points to the dict_T. */ typedef struct { - dictitem_T sv_var; + ScopeDictDictItem sv_var; dict_T sv_dict; } scriptvar_T; @@ -200,61 +217,72 @@ static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T *), 4, NULL}; static int echo_attr = 0; /* attributes used for ":echo" */ -/* Values for trans_function_name() argument: */ -#define TFN_INT 1 /* internal function name OK */ -#define TFN_QUIET 2 /* no error messages */ -#define TFN_NO_AUTOLOAD 4 /* do not use script autoloading */ - -/* Values for get_lval() flags argument: */ -#define GLV_QUIET TFN_QUIET /* no error messages */ -#define GLV_NO_AUTOLOAD TFN_NO_AUTOLOAD /* do not use script autoloading */ - -/* function flags */ -#define FC_ABORT 1 /* abort function on error */ -#define FC_RANGE 2 /* function accepts range */ -#define FC_DICT 4 /* Dict function, uses "self" */ - -/* The names of packages that once were loaded are remembered. */ -static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL}; - -// List heads for garbage collection. Although there can be a reference loop -// from partial to dict to partial, we don't need to keep track of the partial, -// since it will get freed when the dict is unused and gets freed. -static dict_T *first_dict = NULL; // list of all dicts -static list_T *first_list = NULL; // list of all lists +/// trans_function_name() flags +typedef enum { + TFN_INT = 1, ///< May use internal function name + TFN_QUIET = 2, ///< Do not emit error messages. + TFN_NO_AUTOLOAD = 4, ///< Do not use script autoloading. + TFN_NO_DEREF = 8, ///< Do not dereference a Funcref. + TFN_READ_ONLY = 16, ///< Will not change the variable. +} TransFunctionNameFlags; + +/// get_lval() flags +typedef enum { + GLV_QUIET = TFN_QUIET, ///< Do not emit error messages. + GLV_NO_AUTOLOAD = TFN_NO_AUTOLOAD, ///< Do not use script autoloading. + GLV_READ_ONLY = TFN_READ_ONLY, ///< Indicates that caller will not change + ///< the value (prevents error message). +} GetLvalFlags; + +// function flags +#define FC_ABORT 0x01 // abort function on error +#define FC_RANGE 0x02 // function accepts range +#define FC_DICT 0x04 // Dict function, uses "self" +#define FC_CLOSURE 0x08 // closure, uses outer scope variables +#define FC_DELETED 0x10 // :delfunction used while uf_refcount > 0 +#define FC_REMOVED 0x20 // function redefined while uf_refcount > 0 + +// The names of packages that once were loaded are remembered. +static garray_T ga_loaded = { 0, 0, sizeof(char_u *), 4, NULL }; #define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j] #define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j] -#define VAR_SHORT_LEN 20 /* short variable name length */ -#define FIXVAR_CNT 12 /* number of fixed variables */ - -/* structure to hold info for a function that is currently being executed. */ -typedef struct funccall_S funccall_T; +/// Short variable name length +#define VAR_SHORT_LEN 20 +/// Number of fixed variables used for arguments +#define FIXVAR_CNT 12 struct funccall_S { - ufunc_T *func; /* function being called */ - int linenr; /* next line to be executed */ - int returned; /* ":return" used */ - struct /* fixed variables for arguments */ - { - dictitem_T var; /* variable (without room for name) */ - char_u room[VAR_SHORT_LEN]; /* room for the name */ - } fixvar[FIXVAR_CNT]; - dict_T l_vars; /* l: local function variables */ - dictitem_T l_vars_var; /* variable for l: scope */ - dict_T l_avars; /* a: argument variables */ - dictitem_T l_avars_var; /* variable for a: scope */ - list_T l_varlist; /* list for a:000 */ - listitem_T l_listitems[MAX_FUNC_ARGS]; /* listitems for a:000 */ - typval_T *rettv; /* return value */ - linenr_T breakpoint; /* next line with breakpoint or zero */ - int dbg_tick; /* debug_tick when breakpoint was set */ - int level; /* top nesting level of executed function */ - proftime_T prof_child; /* time spent in a child */ - funccall_T *caller; /* calling function or NULL */ + ufunc_T *func; ///< Function being called. + int linenr; ///< Next line to be executed. + int returned; ///< ":return" used. + /// Fixed variables for arguments. + TV_DICTITEM_STRUCT(VAR_SHORT_LEN + 1) fixvar[FIXVAR_CNT]; + dict_T l_vars; ///< l: local function variables. + ScopeDictDictItem l_vars_var; ///< Variable for l: scope. + dict_T l_avars; ///< a: argument variables. + ScopeDictDictItem l_avars_var; ///< Variable for a: scope. + list_T l_varlist; ///< List for a:000. + listitem_T l_listitems[MAX_FUNC_ARGS]; ///< List items for a:000. + typval_T *rettv; ///< Return value. + linenr_T breakpoint; ///< Next line with breakpoint or zero. + int dbg_tick; ///< Debug_tick when breakpoint was set. + int level; ///< Top nesting level of executed function. + proftime_T prof_child; ///< Time spent in a child. + funccall_T *caller; ///< Calling function or NULL. + int fc_refcount; ///< Number of user functions that reference this funccall. + int fc_copyID; ///< CopyID used for garbage collection. + garray_T fc_funcs; ///< List of ufunc_T* which keep a reference to "func". }; +///< Structure used by trans_function_name() +typedef struct { + dict_T *fd_dict; ///< Dictionary used. + char_u *fd_newkey; ///< New key in "dict" in allocated memory. + dictitem_T *fd_di; ///< Dictionary item used. +} funcdict_T; + /* * Info used by a ":for" loop. */ @@ -266,15 +294,6 @@ typedef struct { } forinfo_T; /* - * Struct used by trans_function_name() - */ -typedef struct { - dict_T *fd_dict; /* Dictionary used */ - char_u *fd_newkey; /* new key in "dict" in allocated memory */ - dictitem_T *fd_di; /* Dictionary item used */ -} funcdict_T; - -/* * enum used by var_flavour() */ typedef enum { @@ -305,8 +324,8 @@ typedef enum { // variables with the VV_ defines. static struct vimvar { char *vv_name; ///< Name of the variable, without v:. - dictitem16_T vv_di; ///< Value and name for key (max 16 chars) - char vv_flags; ///< Flags: #VV_COMPAT, #VV_RO, #VV_RO_SBX. + TV_DICTITEM_STRUCT(17) vv_di; ///< Value and name for key (max 16 chars). + char vv_flags; ///< Flags: #VV_COMPAT, #VV_RO, #VV_RO_SBX. } vimvars[] = { // VV_ tails differing from upcased string literals: @@ -389,6 +408,7 @@ static struct vimvar { VV(VV__NULL_LIST, "_null_list", VAR_LIST, VV_RO), VV(VV__NULL_DICT, "_null_dict", VAR_DICT, VV_RO), VV(VV_VIM_DID_ENTER, "vim_did_enter", VAR_NUMBER, VV_RO), + VV(VV_TESTING, "testing", VAR_NUMBER, 0), VV(VV_TYPE_NUMBER, "t_number", VAR_NUMBER, VV_RO), VV(VV_TYPE_STRING, "t_string", VAR_NUMBER, VV_RO), VV(VV_TYPE_FUNC, "t_func", VAR_NUMBER, VV_RO), @@ -410,23 +430,11 @@ static struct vimvar { #define vv_dict vv_di.di_tv.vval.v_dict #define vv_tv vv_di.di_tv -static dictitem_T vimvars_var; // variable used for v: -#define vimvarht vimvardict.dv_hashtab +/// Variable used for v: +static ScopeDictDictItem vimvars_var; -typedef enum { - kCallbackNone, - kCallbackFuncref, - kCallbackPartial, -} CallbackType; - -typedef struct { - union { - char_u *funcref; - partial_T *partial; - } data; - CallbackType type; -} Callback; -#define CALLBACK_NONE ((Callback){ .type = kCallbackNone }) +/// v: hashtab +#define vimvarht vimvardict.dv_hashtab typedef struct { union { @@ -440,18 +448,11 @@ typedef struct { bool rpc; int refcount; Callback on_stdout, on_stderr, on_exit; - int *status_ptr; + varnumber_T *status_ptr; uint64_t id; MultiQueue *events; } TerminalJobData; -typedef struct dict_watcher { - Callback callback; - char *key_pattern; - QUEUE node; - bool busy; // prevent recursion if the dict is changed in the callback -} DictWatcher; - typedef struct { TerminalJobData *data; Callback *callback; @@ -467,6 +468,7 @@ typedef struct { int refcount; long timeout; bool stopped; + bool paused; Callback callback; } timer_T; @@ -486,6 +488,24 @@ typedef struct fst { KHASH_MAP_INIT_STR(functions, VimLFuncDef) +/// Type of assert_* check being performed +typedef enum +{ + ASSERT_EQUAL, + ASSERT_NOTEQUAL, + ASSERT_MATCH, + ASSERT_NOTMATCH, + ASSERT_INRANGE, + ASSERT_OTHER, +} assert_type_T; + +/// Type for dict_list function +typedef enum { + kDictListKeys, ///< List dictionary keys. + kDictListValues, ///< List dictionary values. + kDictListItems, ///< List dictionary contents: [keys, values]. +} DictListType; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval.c.generated.h" #endif @@ -498,6 +518,14 @@ static PMap(uint64_t) *jobs = NULL; static uint64_t last_timer_id = 0; static PMap(uint64_t) *timers = NULL; +/// Dummy va_list for passing to vim_snprintf +/// +/// Used because: +/// - passing a NULL pointer doesn't work when va_list isn't a pointer +/// - locally in the function results in a "used before set" warning +/// - using va_start() to initialize it gives "function with fixed args" error +static va_list dummy_ap; + static const char *const msgpack_type_names[] = { [kMPNil] = "nil", [kMPBoolean] = "boolean", @@ -558,19 +586,19 @@ void eval_init(void) } vimvars[VV_VERSION].vv_nr = VIM_VERSION_100; - dict_T *const msgpack_types_dict = dict_alloc(); + dict_T *const msgpack_types_dict = tv_dict_alloc(); for (size_t i = 0; i < ARRAY_SIZE(msgpack_type_names); i++) { - list_T *const type_list = list_alloc(); + list_T *const type_list = tv_list_alloc(); type_list->lv_lock = VAR_FIXED; type_list->lv_refcount = 1; - dictitem_T *const di = dictitem_alloc((char_u *) msgpack_type_names[i]); - di->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; + dictitem_T *const di = tv_dict_item_alloc(msgpack_type_names[i]); + di->di_flags |= DI_FLAGS_RO|DI_FLAGS_FIX; di->di_tv = (typval_T) { .v_type = VAR_LIST, .vval = { .v_list = type_list, }, }; eval_msgpack_type_lists[i] = type_list; - if (dict_add(msgpack_types_dict, di) == FAIL) { + if (tv_dict_add(msgpack_types_dict, di) == FAIL) { // There must not be duplicate items in this dictionary by definition. assert(false); } @@ -578,12 +606,12 @@ void eval_init(void) msgpack_types_dict->dv_lock = VAR_FIXED; set_vim_var_dict(VV_MSGPACK_TYPES, msgpack_types_dict); - set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc()); + set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc()); - dict_T *v_event = dict_alloc(); + dict_T *v_event = tv_dict_alloc(); v_event->dv_lock = VAR_FIXED; set_vim_var_dict(VV_EVENT, v_event); - set_vim_var_list(VV_ERRORS, list_alloc()); + set_vim_var_list(VV_ERRORS, tv_list_alloc()); set_vim_var_nr(VV_SEARCHFORWARD, 1L); set_vim_var_nr(VV_HLSEARCH, 1L); set_vim_var_nr(VV_COUNT1, 1); @@ -614,7 +642,7 @@ void eval_clear(void) xfree(p->vv_str); p->vv_str = NULL; } else if (p->vv_di.di_tv.v_type == VAR_LIST) { - list_unref(p->vv_list); + tv_list_unref(p->vv_list); p->vv_list = NULL; } } @@ -640,12 +668,11 @@ void eval_clear(void) xfree(SCRIPT_SV(i)); ga_clear(&ga_scripts); - /* unreferenced lists and dicts */ - (void)garbage_collect(); + // unreferenced lists and dicts + (void)garbage_collect(false); - /* functions */ + // functions free_all_functions(); - hash_clear(&func_hashtab); } #endif @@ -703,18 +730,17 @@ int current_func_returned(void) */ void set_internal_string_var(char_u *name, char_u *value) { - char_u *val = vim_strsave(value); - typval_T *tvp = xcalloc(1, sizeof(typval_T)); + const typval_T tv = { + .v_type = VAR_STRING, + .vval.v_string = value, + }; - tvp->v_type = VAR_STRING; - tvp->vval.v_string = val; - set_var(name, tvp, FALSE); - free_tv(tvp); + set_var((const char *)name, STRLEN(name), (typval_T *)&tv, true); } static lval_T *redir_lval = NULL; -static garray_T redir_ga; /* only valid when redir_lval is not NULL */ -static char_u *redir_endp = NULL; +static garray_T redir_ga; // Only valid when redir_lval is not NULL. +static char_u *redir_endp = NULL; static char_u *redir_varname = NULL; /* @@ -745,11 +771,11 @@ var_redir_start ( /* The output is stored in growarray "redir_ga" until redirection ends. */ ga_init(&redir_ga, (int)sizeof(char), 500); - /* Parse the variable name (can be a dict or list entry). */ - redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, 0, - FNE_CHECK_START); - if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != - NUL) { + // Parse the variable name (can be a dict or list entry). + redir_endp = (char_u *)get_lval(redir_varname, NULL, redir_lval, false, false, + 0, FNE_CHECK_START); + if (redir_endp == NULL || redir_lval->ll_name == NULL + || *redir_endp != NUL) { clear_lval(redir_lval); if (redir_endp != NULL && *redir_endp != NUL) /* Trailing characters are present after the variable name */ @@ -823,12 +849,13 @@ void var_redir_stop(void) ga_append(&redir_ga, NUL); /* Append the trailing NUL. */ tv.v_type = VAR_STRING; tv.vval.v_string = redir_ga.ga_data; - /* Call get_lval() again, if it's inside a Dict or List it may - * have changed. */ - redir_endp = get_lval(redir_varname, NULL, redir_lval, - FALSE, FALSE, 0, FNE_CHECK_START); - if (redir_endp != NULL && redir_lval->ll_name != NULL) - set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)"."); + // Call get_lval() again, if it's inside a Dict or List it may + // have changed. + redir_endp = (char_u *)get_lval(redir_varname, NULL, redir_lval, + false, false, 0, FNE_CHECK_START); + if (redir_endp != NULL && redir_lval->ll_name != NULL) { + set_var_lval(redir_lval, redir_endp, &tv, false, (char_u *)"."); + } clear_lval(redir_lval); } @@ -846,7 +873,7 @@ void var_redir_stop(void) int eval_charconvert(const char *const enc_from, const char *const enc_to, const char *const fname_from, const char *const fname_to) { - int err = false; + bool err = false; set_vim_var_string(VV_CC_FROM, enc_from, -1); set_vim_var_string(VV_CC_TO, enc_to, -1); @@ -868,7 +895,7 @@ int eval_charconvert(const char *const enc_from, const char *const enc_to, int eval_printexpr(const char *const fname, const char *const args) { - int err = false; + bool err = false; set_vim_var_string(VV_FNAME_IN, fname, -1); set_vim_var_string(VV_CMDARG, args, -1); @@ -888,7 +915,7 @@ int eval_printexpr(const char *const fname, const char *const args) void eval_diff(const char *const origfile, const char *const newfile, const char *const outfile) { - int err = FALSE; + bool err = false; set_vim_var_string(VV_FNAME_IN, origfile, -1); set_vim_var_string(VV_FNAME_NEW, newfile, -1); @@ -902,7 +929,7 @@ void eval_diff(const char *const origfile, const char *const newfile, void eval_patch(const char *const origfile, const char *const difffile, const char *const outfile) { - int err; + bool err = false; set_vim_var_string(VV_FNAME_IN, origfile, -1); set_vim_var_string(VV_FNAME_DIFF, difffile, -1); @@ -921,56 +948,61 @@ void eval_patch(const char *const origfile, const char *const difffile, int eval_to_bool ( char_u *arg, - int *error, + bool *error, char_u **nextcmd, int skip /* only parse, don't execute */ ) { typval_T tv; - int retval = FALSE; + bool retval = false; - if (skip) - ++emsg_skip; - if (eval0(arg, &tv, nextcmd, !skip) == FAIL) - *error = TRUE; - else { - *error = FALSE; + if (skip) { + emsg_skip++; + } + if (eval0(arg, &tv, nextcmd, !skip) == FAIL) { + *error = true; + } else { + *error = false; if (!skip) { - retval = (get_tv_number_chk(&tv, error) != 0); - clear_tv(&tv); + retval = (tv_get_number_chk(&tv, error) != 0); + tv_clear(&tv); } } - if (skip) - --emsg_skip; + if (skip) { + emsg_skip--; + } return retval; } -/* - * Top level evaluation function, returning a string. If "skip" is TRUE, - * only parsing to "nextcmd" is done, without reporting errors. Return - * pointer to allocated memory, or NULL for failure or when "skip" is TRUE. - */ -char_u * -eval_to_string_skip ( - char_u *arg, - char_u **nextcmd, - int skip /* only parse, don't execute */ -) +/// Top level evaluation function, returning a string +/// +/// @param[in] arg String to evaluate. +/// @param nextcmd Pointer to the start of the next Ex command. +/// @param[in] skip If true, only do parsing to nextcmd without reporting +/// errors or actually evaluating anything. +/// +/// @return [allocated] string result of evaluation or NULL in case of error or +/// when skipping. +char *eval_to_string_skip(const char *arg, const char **nextcmd, + const bool skip) + FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT { typval_T tv; - char_u *retval; + char *retval; - if (skip) - ++emsg_skip; - if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip) + if (skip) { + emsg_skip++; + } + if (eval0((char_u *)arg, &tv, (char_u **)nextcmd, !skip) == FAIL || skip) { retval = NULL; - else { - retval = vim_strsave(get_tv_string(&tv)); - clear_tv(&tv); + } else { + retval = xstrdup(tv_get_string(&tv)); + tv_clear(&tv); + } + if (skip) { + emsg_skip--; } - if (skip) - --emsg_skip; return retval; } @@ -996,31 +1028,33 @@ int skip_expr(char_u **pp) char_u *eval_to_string(char_u *arg, char_u **nextcmd, int convert) { typval_T tv; - char_u *retval; + char *retval; garray_T ga; - char_u numbuf[NUMBUFLEN]; - if (eval0(arg, &tv, nextcmd, TRUE) == FAIL) + if (eval0(arg, &tv, nextcmd, true) == FAIL) { retval = NULL; - else { + } else { if (convert && tv.v_type == VAR_LIST) { ga_init(&ga, (int)sizeof(char), 80); if (tv.vval.v_list != NULL) { - list_join(&ga, tv.vval.v_list, "\n"); - if (tv.vval.v_list->lv_len > 0) + tv_list_join(&ga, tv.vval.v_list, "\n"); + if (tv.vval.v_list->lv_len > 0) { ga_append(&ga, NL); + } } ga_append(&ga, NUL); - retval = (char_u *)ga.ga_data; + retval = (char *)ga.ga_data; } else if (convert && tv.v_type == VAR_FLOAT) { - vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv.vval.v_float); - retval = vim_strsave(numbuf); - } else - retval = vim_strsave(get_tv_string(&tv)); - clear_tv(&tv); + char numbuf[NUMBUFLEN]; + vim_snprintf(numbuf, NUMBUFLEN, "%g", tv.vval.v_float); + retval = xstrdup(numbuf); + } else { + retval = xstrdup(tv_get_string(&tv)); + } + tv_clear(&tv); } - return retval; + return (char_u *)retval; } /* @@ -1049,19 +1083,19 @@ char_u *eval_to_string_safe(char_u *arg, char_u **nextcmd, int use_sandbox) * Evaluates "expr" silently. * Returns -1 for an error. */ -int eval_to_number(char_u *expr) +varnumber_T eval_to_number(char_u *expr) { typval_T rettv; - int retval; + varnumber_T retval; char_u *p = skipwhite(expr); ++emsg_off; - if (eval1(&p, &rettv, TRUE) == FAIL) + if (eval1(&p, &rettv, true) == FAIL) { retval = -1; - else { - retval = get_tv_number_chk(&rettv, NULL); - clear_tv(&rettv); + } else { + retval = tv_get_number_chk(&rettv, NULL); + tv_clear(&rettv); } --emsg_off; @@ -1118,11 +1152,12 @@ list_T *eval_spell_expr(char_u *badword, char_u *expr) if (p_verbose == 0) ++emsg_off; - if (eval1(&p, &rettv, TRUE) == OK) { - if (rettv.v_type != VAR_LIST) - clear_tv(&rettv); - else + if (eval1(&p, &rettv, true) == OK) { + if (rettv.v_type != VAR_LIST) { + tv_clear(&rettv); + } else { list = rettv.vval.v_list; + } } if (p_verbose == 0) @@ -1138,54 +1173,39 @@ list_T *eval_spell_expr(char_u *badword, char_u *expr) * Return -1 if anything isn't right. * Used to get the good word and score from the eval_spell_expr() result. */ -int get_spellword(list_T *list, char_u **pp) +int get_spellword(list_T *list, const char **pp) { listitem_T *li; li = list->lv_first; - if (li == NULL) + if (li == NULL) { return -1; - *pp = get_tv_string(&li->li_tv); + } + *pp = tv_get_string(&li->li_tv); li = li->li_next; - if (li == NULL) + if (li == NULL) { return -1; - return get_tv_number(&li->li_tv); -} - -/* - * Top level evaluation function. - * Returns an allocated typval_T with the result. - * Returns NULL when there is an error. - */ -typval_T *eval_expr(char_u *arg, char_u **nextcmd) -{ - typval_T *tv = xmalloc(sizeof(typval_T)); - - if (eval0(arg, tv, nextcmd, TRUE) == FAIL) { - xfree(tv); - return NULL; } - - return tv; + return tv_get_number(&li->li_tv); } -// Call some vimL function and return the result in "*rettv". +// Call some vim script function and return the result in "*rettv". // Uses argv[argc] for the function arguments. Only Number and String // arguments are currently supported. // // Return OK or FAIL. int call_vim_function( - char_u *func, + const char_u *func, int argc, - char_u **argv, + const char_u *const *const argv, int safe, // use the sandbox int str_arg_only, // all arguments are strings typval_T *rettv ) { - long n; + varnumber_T n; int len; int doesrange; void *save_funccalp = NULL; @@ -1212,7 +1232,7 @@ int call_vim_function( argvars[i].vval.v_number = n; } else { argvars[i].v_type = VAR_STRING; - argvars[i].vval.v_string = argv[i]; + argvars[i].vval.v_string = (char_u *)argv[i]; } } @@ -1221,8 +1241,8 @@ int call_vim_function( ++sandbox; } - rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */ - ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars, + rettv->v_type = VAR_UNKNOWN; // tv_clear() uses this. + ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars, NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &doesrange, true, NULL, NULL); if (safe) { @@ -1232,74 +1252,72 @@ int call_vim_function( xfree(argvars); if (ret == FAIL) { - clear_tv(rettv); + tv_clear(rettv); } return ret; } -/* - * Call vimL function "func" and return the result as a number. - * Returns -1 when calling the function fails. - * Uses argv[argc] for the function arguments. - */ -long -call_func_retnr ( - char_u *func, - int argc, - char_u **argv, - int safe /* use the sandbox */ -) +/// Call Vim script function and return the result as a number +/// +/// @param[in] func Function name. +/// @param[in] argc Number of arguments. +/// @param[in] argv Array with string arguments. +/// @param[in] safe Use with sandbox. +/// +/// @return -1 when calling function fails, result of function otherwise. +varnumber_T call_func_retnr(char_u *func, int argc, + const char_u *const *const argv, int safe) { typval_T rettv; - long retval; + varnumber_T retval; /* All arguments are passed as strings, no conversion to number. */ if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL) return -1; - retval = get_tv_number_chk(&rettv, NULL); - clear_tv(&rettv); + retval = tv_get_number_chk(&rettv, NULL); + tv_clear(&rettv); return retval; } -/* - * Call vimL function "func" and return the result as a string. - * Returns NULL when calling the function fails. - * Uses argv[argc] for the function arguments. - */ -void * -call_func_retstr ( - char_u *func, - int argc, - char_u **argv, - int safe /* use the sandbox */ -) +/// Call Vim script function and return the result as a string +/// +/// @param[in] func Function name. +/// @param[in] argc Number of arguments. +/// @param[in] argv Array with string arguments. +/// @param[in] safe Use the sandbox. +/// +/// @return [allocated] NULL when calling function fails, allocated string +/// otherwise. +char *call_func_retstr(const char *const func, const int argc, + const char_u *const *const argv, + const bool safe) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC { typval_T rettv; - char_u *retval; - - /* All arguments are passed as strings, no conversion to number. */ - if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL) + // All arguments are passed as strings, no conversion to number. + if (call_vim_function((const char_u *)func, argc, argv, safe, true, &rettv) + == FAIL) { return NULL; + } - retval = vim_strsave(get_tv_string(&rettv)); - clear_tv(&rettv); + char *const retval = xstrdup(tv_get_string(&rettv)); + tv_clear(&rettv); return retval; } -/* - * Call vimL function "func" and return the result as a List. - * Uses argv[argc] for the function arguments. - * Returns NULL when there is something wrong. - */ -void * -call_func_retlist ( - char_u *func, - int argc, - char_u **argv, - int safe /* use the sandbox */ -) +/// Call Vim script function and return the result as a List +/// +/// @param[in] func Function name. +/// @param[in] argc Number of arguments. +/// @param[in] argv Array with string arguments. +/// @param[in] safe Use the sandbox. +/// +/// @return [allocated] NULL when calling function fails or return tv is not a +/// List, allocated List otherwise. +void *call_func_retlist(char_u *func, int argc, const char_u *const *const argv, + int safe) { typval_T rettv; @@ -1308,7 +1326,7 @@ call_func_retlist ( return NULL; if (rettv.v_type != VAR_LIST) { - clear_tv(&rettv); + tv_clear(&rettv); return NULL; } @@ -1380,7 +1398,7 @@ void prof_child_exit(proftime_T *tm /* where waittime was stored */ int eval_foldexpr(char_u *arg, int *cp) { typval_T tv; - int retval; + varnumber_T retval; char_u *s; int use_sandbox = was_set_insecurely((char_u *)"foldexpr", OPT_LOCAL); @@ -1406,14 +1424,14 @@ int eval_foldexpr(char_u *arg, int *cp) *cp = *s++; retval = atol((char *)s); } - clear_tv(&tv); + tv_clear(&tv); } --emsg_off; if (use_sandbox) --sandbox; --textlock; - return retval; + return (int)retval; } /* @@ -1437,22 +1455,24 @@ void ex_let(exarg_T *eap) char_u *argend; int first = TRUE; - argend = skip_var_list(arg, &var_count, &semicolon); - if (argend == NULL) + argend = (char_u *)skip_var_list(arg, &var_count, &semicolon); + if (argend == NULL) { return; - if (argend > arg && argend[-1] == '.') /* for var.='str' */ - --argend; + } + if (argend > arg && argend[-1] == '.') { // For var.='str'. + argend--; + } expr = skipwhite(argend); if (*expr != '=' && !(vim_strchr((char_u *)"+-.", *expr) != NULL && expr[1] == '=')) { // ":let" without "=": list variables - if (*arg == '[') + if (*arg == '[') { EMSG(_(e_invarg)); - else if (!ends_excmd(*arg)) - /* ":let var1 var2" */ - arg = list_arg_vars(eap, arg, &first); - else if (!eap->skip) { - /* ":let" */ + } else if (!ends_excmd(*arg)) { + // ":let var1 var2" + arg = (char_u *)list_arg_vars(eap, (const char *)arg, &first); + } else if (!eap->skip) { + // ":let" list_glob_vars(&first); list_buf_vars(&first); list_win_vars(&first); @@ -1478,13 +1498,13 @@ void ex_let(exarg_T *eap) ++emsg_skip; i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip); if (eap->skip) { - if (i != FAIL) - clear_tv(&rettv); - --emsg_skip; + if (i != FAIL) { + tv_clear(&rettv); + } + emsg_skip--; } else if (i != FAIL) { - (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count, - op); - clear_tv(&rettv); + (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, op); + tv_clear(&rettv); } } } @@ -1507,7 +1527,7 @@ ex_let_vars ( char_u *nextchars ) { - char_u *arg = arg_start; + char_u *arg = arg_start; list_T *l; int i; listitem_T *item; @@ -1530,7 +1550,7 @@ ex_let_vars ( return FAIL; } - i = list_len(l); + i = tv_list_len(l); if (semicolon == 0 && var_count < i) { EMSG(_("E687: Less targets than List items")); return FAIL; @@ -1552,9 +1572,9 @@ ex_let_vars ( if (*arg == ';') { /* Put the rest of the list (may be empty) in the var after ';'. * Create a new list for this. */ - l = list_alloc(); + l = tv_list_alloc(); while (item != NULL) { - list_append_tv(l, &item->li_tv); + tv_list_append_tv(l, &item->li_tv); item = item->li_next; } @@ -1563,11 +1583,12 @@ ex_let_vars ( ltv.vval.v_list = l; l->lv_refcount = 1; - arg = ex_let_one(skipwhite(arg + 1), <v, FALSE, - (char_u *)"]", nextchars); - clear_tv(<v); - if (arg == NULL) + arg = ex_let_one(skipwhite(arg + 1), <v, false, + (char_u *)"]", nextchars); + tv_clear(<v); + if (arg == NULL) { return FAIL; + } break; } else if (*arg != ',' && *arg != ']') { EMSG2(_(e_intern2), "ex_let_vars()"); @@ -1585,9 +1606,11 @@ ex_let_vars ( * for "[var, var; var]" set "semicolon". * Return NULL for an error. */ -static char_u *skip_var_list(char_u *arg, int *var_count, int *semicolon) +static const char_u *skip_var_list(const char_u *arg, int *var_count, + int *semicolon) { - char_u *p, *s; + const char_u *p; + const char_u *s; if (*arg == '[') { /* "[var, var]": find the matching ']'. */ @@ -1624,7 +1647,7 @@ static char_u *skip_var_list(char_u *arg, int *var_count, int *semicolon) * Skip one (assignable) variable name, including @r, $VAR, &option, d.key, * l[idx]. */ -static char_u *skip_var_one(char_u *arg) +static const char_u *skip_var_one(const char_u *arg) { if (*arg == '@' && arg[1] != NUL) return arg + 2; @@ -1636,7 +1659,8 @@ static char_u *skip_var_one(char_u *arg) * List variables for hashtab "ht" with prefix "prefix". * If "empty" is TRUE also list NULL strings as empty strings. */ -static void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *first) +static void list_hashtable_vars(hashtab_T *ht, const char *prefix, int empty, + int *first) { hashitem_T *hi; dictitem_T *di; @@ -1645,11 +1669,12 @@ static void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *f todo = (int)ht->ht_used; for (hi = ht->ht_array; todo > 0 && !got_int; ++hi) { if (!HASHITEM_EMPTY(hi)) { - --todo; - di = HI2DI(hi); + todo--; + di = TV_DICT_HI2DI(hi); if (empty || di->di_tv.v_type != VAR_STRING - || di->di_tv.vval.v_string != NULL) + || di->di_tv.vval.v_string != NULL) { list_one_var(di, prefix, first); + } } } } @@ -1659,7 +1684,7 @@ static void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *f */ static void list_glob_vars(int *first) { - list_hashtable_vars(&globvarht, (char_u *)"", TRUE, first); + list_hashtable_vars(&globvarht, "", true, first); } /* @@ -1667,14 +1692,7 @@ static void list_glob_vars(int *first) */ static void list_buf_vars(int *first) { - char_u numbuf[NUMBUFLEN]; - - list_hashtable_vars(&curbuf->b_vars->dv_hashtab, (char_u *)"b:", - TRUE, first); - - sprintf((char *)numbuf, "%" PRId64, (int64_t)curbuf->b_changedtick); - list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER, - numbuf, first); + list_hashtable_vars(&curbuf->b_vars->dv_hashtab, "b:", true, first); } /* @@ -1682,8 +1700,7 @@ static void list_buf_vars(int *first) */ static void list_win_vars(int *first) { - list_hashtable_vars(&curwin->w_vars->dv_hashtab, - (char_u *)"w:", TRUE, first); + list_hashtable_vars(&curwin->w_vars->dv_hashtab, "w:", true, first); } /* @@ -1691,8 +1708,7 @@ static void list_win_vars(int *first) */ static void list_tab_vars(int *first) { - list_hashtable_vars(&curtab->tp_vars->dv_hashtab, - (char_u *)"t:", TRUE, first); + list_hashtable_vars(&curtab->tp_vars->dv_hashtab, "t:", true, first); } /* @@ -1700,7 +1716,7 @@ static void list_tab_vars(int *first) */ static void list_vim_vars(int *first) { - list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE, first); + list_hashtable_vars(&vimvarht, "v:", false, first); } /* @@ -1708,9 +1724,9 @@ static void list_vim_vars(int *first) */ static void list_script_vars(int *first) { - if (current_SID > 0 && current_SID <= ga_scripts.ga_len) - list_hashtable_vars(&SCRIPT_VARS(current_SID), - (char_u *)"s:", FALSE, first); + if (current_SID > 0 && current_SID <= ga_scripts.ga_len) { + list_hashtable_vars(&SCRIPT_VARS(current_SID), "s:", false, first); + } } /* @@ -1718,36 +1734,37 @@ static void list_script_vars(int *first) */ static void list_func_vars(int *first) { - if (current_funccal != NULL) - list_hashtable_vars(¤t_funccal->l_vars.dv_hashtab, - (char_u *)"l:", FALSE, first); + if (current_funccal != NULL) { + list_hashtable_vars(¤t_funccal->l_vars.dv_hashtab, "l:", false, + first); + } } /* * List variables in "arg". */ -static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first) +static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first) { int error = FALSE; int len; - char_u *name; - char_u *name_start; - char_u *arg_subsc; - char_u *tofree; + const char *name; + const char *name_start; typval_T tv; while (!ends_excmd(*arg) && !got_int) { if (error || eap->skip) { - arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START); + arg = (const char *)find_name_end((char_u *)arg, NULL, NULL, + FNE_INCL_BR | FNE_CHECK_START); if (!ascii_iswhite(*arg) && !ends_excmd(*arg)) { emsg_severe = TRUE; EMSG(_(e_trailing)); break; } } else { - /* get_name_len() takes care of expanding curly braces */ + // get_name_len() takes care of expanding curly braces name_start = name = arg; - len = get_name_len(&arg, &tofree, TRUE, TRUE); + char *tofree; + len = get_name_len(&arg, &tofree, true, true); if (len <= 0) { /* This is mainly to keep test 49 working: when expanding * curly braces fails overrule the exception error message. */ @@ -1761,14 +1778,15 @@ static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first) if (tofree != NULL) { name = tofree; } - if (get_var_tv(name, len, &tv, NULL, true, false) == FAIL) { + if (get_var_tv((const char *)name, len, &tv, NULL, true, false) + == FAIL) { error = true; } else { // handle d.key, l[idx], f(expr) - arg_subsc = arg; - if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL) - error = TRUE; - else { + const char *const arg_subsc = arg; + if (handle_subscript(&arg, &tv, true, true) == FAIL) { + error = true; + } else { if (arg == arg_subsc && len == 2 && name[1] == ':') { switch (*name) { case 'g': list_glob_vars(first); break; @@ -1782,20 +1800,18 @@ static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first) EMSG2(_("E738: Can't list variables for %s"), name); } } else { - int c; - - char_u *s = (char_u *) encode_tv2echo(&tv, NULL); - c = *arg; - *arg = NUL; - list_one_var_a((char_u *)"", - arg == arg_subsc ? name : name_start, - tv.v_type, - s == NULL ? (char_u *)"" : s, - first); - *arg = c; + char *const s = encode_tv2echo(&tv, NULL); + const char *const used_name = (arg == arg_subsc + ? name + : name_start); + const ptrdiff_t name_size = (used_name == tofree + ? (ptrdiff_t)strlen(used_name) + : (arg - used_name)); + list_one_var_a("", used_name, name_size, + tv.v_type, s == NULL ? "" : s, first); xfree(s); } - clear_tv(&tv); + tv_clear(&tv); } } } @@ -1803,152 +1819,153 @@ static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first) xfree(tofree); } - arg = skipwhite(arg); + arg = (const char *)skipwhite((const char_u *)arg); } return arg; } -/* - * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value. - * Returns a pointer to the char just after the var name. - * Returns NULL if there is an error. - */ -static char_u * -ex_let_one ( - char_u *arg, /* points to variable name */ - typval_T *tv, /* value to assign to variable */ - int copy, /* copy value from "tv" */ - char_u *endchars, /* valid chars after variable name or NULL */ - char_u *op /* "+", "-", "." or NULL*/ -) -{ - int c1; - char_u *name; - char_u *p; - char_u *arg_end = NULL; +// TODO(ZyX-I): move to eval/ex_cmds + +/// Set one item of `:let var = expr` or `:let [v1, v2] = list` to its value +/// +/// @param[in] arg Start of the variable name. +/// @param[in] tv Value to assign to the variable. +/// @param[in] copy If true, copy value from `tv`. +/// @param[in] endchars Valid characters after variable name or NULL. +/// @param[in] op Operation performed: *op is `+`, `-`, `.` for `+=`, etc. +/// NULL for `=`. +/// +/// @return a pointer to the char just after the var name or NULL in case of +/// error. +static char_u *ex_let_one(char_u *arg, typval_T *const tv, + const bool copy, const char_u *const endchars, + const char_u *const op) + FUNC_ATTR_NONNULL_ARG(1, 2) FUNC_ATTR_WARN_UNUSED_RESULT +{ + char_u *arg_end = NULL; int len; int opt_flags; - char_u *tofree = NULL; + char_u *tofree = NULL; /* * ":let $VAR = expr": Set environment variable. */ if (*arg == '$') { - /* Find the end of the name. */ - ++arg; - name = arg; - len = get_env_len(&arg); - if (len == 0) + // Find the end of the name. + arg++; + char *name = (char *)arg; + len = get_env_len((const char_u **)&arg); + if (len == 0) { EMSG2(_(e_invarg2), name - 1); - else { - if (op != NULL && (*op == '+' || *op == '-')) + } else { + if (op != NULL && (*op == '+' || *op == '-')) { EMSG2(_(e_letwrong), op); - else if (endchars != NULL - && vim_strchr(endchars, *skipwhite(arg)) == NULL) + } else if (endchars != NULL + && vim_strchr(endchars, *skipwhite(arg)) == NULL) { EMSG(_(e_letunexp)); - else if (!check_secure()) { - c1 = name[len]; + } else if (!check_secure()) { + const char c1 = name[len]; name[len] = NUL; - p = get_tv_string_chk(tv); + const char *p = tv_get_string_chk(tv); if (p != NULL && op != NULL && *op == '.') { - char *s = vim_getenv((char *)name); + char *s = vim_getenv(name); if (s != NULL) { - p = tofree = concat_str((char_u *)s, p); + tofree = concat_str((const char_u *)s, (const char_u *)p); + p = (const char *)tofree; xfree(s); } } if (p != NULL) { - vim_setenv((char *)name, (char *)p); - if (STRICMP(name, "HOME") == 0) + vim_setenv(name, p); + if (STRICMP(name, "HOME") == 0) { init_homedir(); - else if (didset_vim && STRICMP(name, "VIM") == 0) - didset_vim = FALSE; - else if (didset_vimruntime - && STRICMP(name, "VIMRUNTIME") == 0) - didset_vimruntime = FALSE; + } else if (didset_vim && STRICMP(name, "VIM") == 0) { + didset_vim = false; + } else if (didset_vimruntime + && STRICMP(name, "VIMRUNTIME") == 0) { + didset_vimruntime = false; + } arg_end = arg; } name[len] = c1; xfree(tofree); } } - } - /* - * ":let &option = expr": Set option value. - * ":let &l:option = expr": Set local option value. - * ":let &g:option = expr": Set global option value. - */ - else if (*arg == '&') { - /* Find the end of the name. */ - p = find_option_end(&arg, &opt_flags); - if (p == NULL || (endchars != NULL - && vim_strchr(endchars, *skipwhite(p)) == NULL)) + // ":let &option = expr": Set option value. + // ":let &l:option = expr": Set local option value. + // ":let &g:option = expr": Set global option value. + } else if (*arg == '&') { + // Find the end of the name. + char *const p = (char *)find_option_end((const char **)&arg, &opt_flags); + if (p == NULL + || (endchars != NULL + && vim_strchr(endchars, *skipwhite((const char_u *)p)) == NULL)) { EMSG(_(e_letunexp)); - else { - long n; + } else { int opt_type; long numval; - char_u *stringval = NULL; - char_u *s; + char *stringval = NULL; - c1 = *p; + const char c1 = *p; *p = NUL; - n = get_tv_number(tv); - s = get_tv_string_chk(tv); /* != NULL if number or string */ + varnumber_T n = tv_get_number(tv); + const char *s = tv_get_string_chk(tv); // != NULL if number or string. if (s != NULL && op != NULL && *op != '=') { - opt_type = get_option_value(arg, &numval, - &stringval, opt_flags); + opt_type = get_option_value(arg, &numval, (char_u **)&stringval, + opt_flags); if ((opt_type == 1 && *op == '.') - || (opt_type == 0 && *op != '.')) + || (opt_type == 0 && *op != '.')) { EMSG2(_(e_letwrong), op); - else { - if (opt_type == 1) { /* number */ - if (*op == '+') + } else { + if (opt_type == 1) { // number + if (*op == '+') { n = numval + n; - else + } else { n = numval - n; - } else if (opt_type == 0 && stringval != NULL) { /* string */ - s = concat_str(stringval, s); - xfree(stringval); - stringval = s; + } + } else if (opt_type == 0 && stringval != NULL) { // string + char *const oldstringval = stringval; + stringval = (char *)concat_str((const char_u *)stringval, + (const char_u *)s); + xfree(oldstringval); + s = stringval; } } } if (s != NULL) { - set_option_value(arg, n, s, opt_flags); - arg_end = p; + set_option_value((const char *)arg, n, s, opt_flags); + arg_end = (char_u *)p; } *p = c1; xfree(stringval); } - } - /* - * ":let @r = expr": Set register contents. - */ - else if (*arg == '@') { - ++arg; - if (op != NULL && (*op == '+' || *op == '-')) - EMSG2(_(e_letwrong), op); - else if (endchars != NULL - && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) - EMSG(_(e_letunexp)); - else { - char_u *ptofree = NULL; + // ":let @r = expr": Set register contents. + } else if (*arg == '@') { + arg++; + if (op != NULL && (*op == '+' || *op == '-')) { + emsgf(_(e_letwrong), op); + } else if (endchars != NULL + && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) { + emsgf(_(e_letunexp)); + } else { char_u *s; - p = get_tv_string_chk(tv); + char_u *ptofree = NULL; + const char *p = tv_get_string_chk(tv); if (p != NULL && op != NULL && *op == '.') { s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc); if (s != NULL) { - p = ptofree = concat_str(s, p); + ptofree = concat_str(s, (const char_u *)p); + p = (const char *)ptofree; xfree(s); } } if (p != NULL) { - write_reg_contents(*arg == '@' ? '"' : *arg, p, STRLEN(p), false); + write_reg_contents(*arg == '@' ? '"' : *arg, + (const char_u *)p, STRLEN(p), false); arg_end = arg + 1; } xfree(ptofree); @@ -1961,11 +1978,11 @@ ex_let_one ( else if (eval_isnamec1(*arg) || *arg == '{') { lval_T lv; - p = get_lval(arg, tv, &lv, FALSE, FALSE, 0, FNE_CHECK_START); + char_u *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, *skipwhite(p)) == NULL) { EMSG(_(e_letunexp)); - else { + } else { set_var_lval(&lv, p, tv, copy, op); arg_end = p; } @@ -1977,57 +1994,41 @@ ex_let_one ( return arg_end; } -/* - * If "arg" is equal to "b:changedtick" give an error and return TRUE. - */ -static int check_changedtick(char_u *arg) -{ - if (STRNCMP(arg, "b:changedtick", 13) == 0 && !eval_isnamec(arg[13])) { - EMSG2(_(e_readonlyvar), arg); - return TRUE; - } - return FALSE; -} +// TODO(ZyX-I): move to eval/executor -/* - * Get an lval: variable, Dict item or List item that can be assigned a value - * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]", - * "name.key", "name.key[expr]" etc. - * Indexing only works if "name" is an existing List or Dictionary. - * "name" points to the start of the name. - * If "rettv" is not NULL it points to the value to be assigned. - * "unlet" is TRUE for ":unlet": slightly different behavior when something is - * wrong; must end in space or cmd separator. - * - * flags: - * GLV_QUIET: do not give error messages - * GLV_NO_AUTOLOAD: do not use script autoloading - * - * Returns a pointer to just after the name, including indexes. - * When an evaluation error occurs "lp->ll_name" is NULL; - * Returns NULL for a parsing error. Still need to free items in "lp"! - */ -static char_u * -get_lval ( - char_u *name, - typval_T *rettv, - lval_T *lp, - int unlet, - int skip, - int flags, /* GLV_ values */ - int fne_flags /* flags for find_name_end() */ -) +/// Get an lvalue +/// +/// Lvalue may be +/// - variable: "name", "na{me}" +/// - dictionary item: "dict.key", "dict['key']" +/// - list item: "list[expr]" +/// - list slice: "list[expr:expr]" +/// +/// Indexing only works if trying to use it with an existing List or Dictionary. +/// +/// @param[in] name Name to parse. +/// @param rettv Pointer to the value to be assigned or NULL. +/// @param[out] lp Lvalue definition. When evaluation errors occur `->ll_name` +/// is NULL. +/// @param[in] unlet True if using `:unlet`. This results in slightly +/// different behaviour when something is wrong; must end in +/// space or cmd separator. +/// @param[in] skip True when skipping. +/// @param[in] flags @see GetLvalFlags. +/// @param[in] fne_flags Flags for find_name_end(). +/// +/// @return A pointer to just after the name, including indexes. Returns NULL +/// for a parsing error, but it is still needed to free items in lp. +static char_u *get_lval(char_u *const name, typval_T *const rettv, + lval_T *const lp, const bool unlet, const bool skip, + const int flags, const int fne_flags) + FUNC_ATTR_NONNULL_ARG(1, 3) { - char_u *p; - char_u *expr_start, *expr_end; - int cc; dictitem_T *v; typval_T var1; typval_T var2; int empty1 = FALSE; listitem_T *ni; - char_u *key = NULL; - int len; hashtab_T *ht; int quiet = flags & GLV_QUIET; @@ -2035,13 +2036,19 @@ get_lval ( memset(lp, 0, sizeof(lval_T)); if (skip) { - /* When skipping just find the end of the name. */ - lp->ll_name = name; - return find_name_end(name, NULL, NULL, FNE_INCL_BR | fne_flags); + // When skipping just find the end of the name. + lp->ll_name = (const char *)name; + return (char_u *)find_name_end((const char_u *)name, NULL, NULL, + FNE_INCL_BR | fne_flags); } - /* Find the end of the name. */ - p = find_name_end(name, &expr_start, &expr_end, fne_flags); + // Find the end of the name. + char_u *expr_start; + char_u *expr_end; + char_u *p = (char_u *)find_name_end(name, + (const char_u **)&expr_start, + (const char_u **)&expr_end, + fne_flags); if (expr_start != NULL) { /* Don't expand the name when we already know there is an error. */ if (unlet && !ascii_iswhite(*p) && !ends_excmd(*p) @@ -2050,7 +2057,9 @@ get_lval ( return NULL; } - lp->ll_exp_name = make_expanded_name(name, expr_start, expr_end, p); + lp->ll_exp_name = (char *)make_expanded_name(name, expr_start, expr_end, + (char_u *)p); + lp->ll_name = lp->ll_exp_name; if (lp->ll_exp_name == NULL) { /* Report an invalid expression in braces, unless the * expression evaluation has been cancelled due to an @@ -2060,23 +2069,28 @@ get_lval ( EMSG2(_(e_invarg2), name); return NULL; } + lp->ll_name_len = 0; + } else { + lp->ll_name_len = strlen(lp->ll_name); } - lp->ll_name = lp->ll_exp_name; - } else - lp->ll_name = name; + } else { + lp->ll_name = (const char *)name; + lp->ll_name_len = (size_t)((const char *)p - lp->ll_name); + } - /* Without [idx] or .key we are done. */ - if ((*p != '[' && *p != '.') || lp->ll_name == NULL) + // Without [idx] or .key we are done. + if ((*p != '[' && *p != '.') || lp->ll_name == NULL) { return p; + } - cc = *p; - *p = NUL; - v = find_var(lp->ll_name, &ht, flags & GLV_NO_AUTOLOAD); - if (v == NULL && !quiet) - EMSG2(_(e_undefvar), lp->ll_name); - *p = cc; - if (v == NULL) + v = find_var(lp->ll_name, lp->ll_name_len, &ht, flags & GLV_NO_AUTOLOAD); + if (v == NULL && !quiet) { + emsgf(_("E121: Undefined variable: %.*s"), + (int)lp->ll_name_len, lp->ll_name); + } + if (v == NULL) { return NULL; + } /* * Loop until no more [idx] or .key is following. @@ -2096,29 +2110,32 @@ get_lval ( return NULL; } - len = -1; + int len = -1; + char_u *key = NULL; if (*p == '.') { key = p + 1; - for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len) - ; + for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; len++) { + } if (len == 0) { - if (!quiet) - EMSG(_(e_emptykey)); + if (!quiet) { + EMSG(_("E713: Cannot use empty key after .")); + } return NULL; } p = key + len; } else { /* Get the index [expr] or the first index [expr: ]. */ p = skipwhite(p + 1); - if (*p == ':') - empty1 = TRUE; - else { - empty1 = FALSE; - if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */ + if (*p == ':') { + empty1 = true; + } else { + empty1 = false; + if (eval1(&p, &var1, true) == FAIL) { // Recursive! return NULL; - if (get_tv_string_chk(&var1) == NULL) { - /* not a number or string */ - clear_tv(&var1); + } + if (!tv_check_str(&var1)) { + // Not a number or string. + tv_clear(&var1); return NULL; } } @@ -2126,35 +2143,41 @@ get_lval ( /* Optionally get the second index [ :expr]. */ if (*p == ':') { if (lp->ll_tv->v_type == VAR_DICT) { - if (!quiet) + if (!quiet) { EMSG(_(e_dictrange)); - if (!empty1) - clear_tv(&var1); + } + if (!empty1) { + tv_clear(&var1); + } return NULL; } if (rettv != NULL && (rettv->v_type != VAR_LIST || rettv->vval.v_list == NULL)) { - if (!quiet) - EMSG(_("E709: [:] requires a List value")); - if (!empty1) - clear_tv(&var1); + if (!quiet) { + emsgf(_("E709: [:] requires a List value")); + } + if (!empty1) { + tv_clear(&var1); + } return NULL; } p = skipwhite(p + 1); - if (*p == ']') - lp->ll_empty2 = TRUE; - else { - lp->ll_empty2 = FALSE; - if (eval1(&p, &var2, TRUE) == FAIL) { /* recursive! */ - if (!empty1) - clear_tv(&var1); + if (*p == ']') { + lp->ll_empty2 = true; + } else { + lp->ll_empty2 = false; + if (eval1(&p, &var2, true) == FAIL) { // Recursive! + if (!empty1) { + tv_clear(&var1); + } return NULL; } - if (get_tv_string_chk(&var2) == NULL) { - /* not a number or string */ - if (!empty1) - clear_tv(&var1); - clear_tv(&var2); + if (!tv_check_str(&var2)) { + // Not a number or string. + if (!empty1) { + tv_clear(&var1); + } + tv_clear(&var2); return NULL; } } @@ -2163,12 +2186,15 @@ get_lval ( lp->ll_range = FALSE; if (*p != ']') { - if (!quiet) - EMSG(_(e_missbrac)); - if (!empty1) - clear_tv(&var1); - if (lp->ll_range && !lp->ll_empty2) - clear_tv(&var2); + if (!quiet) { + emsgf(_(e_missbrac)); + } + if (!empty1) { + tv_clear(&var1); + } + if (lp->ll_range && !lp->ll_empty2) { + tv_clear(&var2); + } return NULL; } @@ -2179,15 +2205,15 @@ get_lval ( if (lp->ll_tv->v_type == VAR_DICT) { if (len == -1) { // "[key]": get key from "var1" - key = get_tv_string_chk(&var1); // is number or string + key = (char_u *)tv_get_string(&var1); // is number or string if (key == NULL) { - clear_tv(&var1); + tv_clear(&var1); return NULL; } } lp->ll_list = NULL; lp->ll_dict = lp->ll_tv->vval.v_dict; - lp->ll_di = dict_find(lp->ll_dict, key, len); + lp->ll_di = tv_dict_find(lp->ll_dict, (const char *)key, len); /* When assigning to a scope dictionary check that a function and * variable name is valid (only variable name unless it is l: or @@ -2199,16 +2225,19 @@ get_lval ( if (len != -1) { prevval = key[len]; key[len] = NUL; - } else - prevval = 0; /* avoid compiler warning */ - wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE - && rettv->v_type == VAR_FUNC - && var_check_func_name(key, lp->ll_di == NULL)) - || !valid_varname(key); - if (len != -1) + } else { + prevval = 0; // Avoid compiler warning. + } + wrong = ((lp->ll_dict->dv_scope == VAR_DEF_SCOPE + && tv_is_func(*rettv) + && !var_check_func_name((const char *)key, lp->ll_di == NULL)) + || !valid_varname((const char *)key)); + if (len != -1) { key[len] = prevval; - if (wrong) + } + if (wrong) { return NULL; + } } if (lp->ll_di == NULL) { @@ -2220,51 +2249,61 @@ get_lval ( /* Key does not exist in dict: may need to add it. */ if (*p == '[' || *p == '.' || unlet) { - if (!quiet) - EMSG2(_(e_dictkey), key); - if (len == -1) - clear_tv(&var1); + if (!quiet) { + emsgf(_(e_dictkey), key); + } + if (len == -1) { + tv_clear(&var1); + } return NULL; } - if (len == -1) + if (len == -1) { lp->ll_newkey = vim_strsave(key); - else + } else { lp->ll_newkey = vim_strnsave(key, len); - if (len == -1) - clear_tv(&var1); + } + if (len == -1) { + tv_clear(&var1); + } break; - } else if (var_check_ro(lp->ll_di->di_flags, name, false)) { - // existing variable, need to check if it can be changed + // 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))) { + if (len == -1) { + tv_clear(&var1); + } return NULL; } - if (len == -1) - clear_tv(&var1); + if (len == -1) { + tv_clear(&var1); + } lp->ll_tv = &lp->ll_di->di_tv; } else { - /* - * Get the number and item for the only or first index of the List. - */ - if (empty1) + // Get the number and item for the only or first index of the List. + if (empty1) { lp->ll_n1 = 0; - else { - lp->ll_n1 = get_tv_number(&var1); /* is number or string */ - clear_tv(&var1); + } else { + lp->ll_n1 = (long)tv_get_number(&var1); // Is number or string. + tv_clear(&var1); } lp->ll_dict = NULL; lp->ll_list = lp->ll_tv->vval.v_list; - lp->ll_li = list_find(lp->ll_list, lp->ll_n1); + lp->ll_li = tv_list_find(lp->ll_list, lp->ll_n1); if (lp->ll_li == NULL) { if (lp->ll_n1 < 0) { lp->ll_n1 = 0; - lp->ll_li = list_find(lp->ll_list, lp->ll_n1); + lp->ll_li = tv_list_find(lp->ll_list, lp->ll_n1); } } if (lp->ll_li == NULL) { - if (lp->ll_range && !lp->ll_empty2) - clear_tv(&var2); - if (!quiet) + if (lp->ll_range && !lp->ll_empty2) { + tv_clear(&var2); + } + if (!quiet) { EMSGN(_(e_listidx), lp->ll_n1); + } return NULL; } @@ -2275,24 +2314,26 @@ get_lval ( * Otherwise "lp->ll_n2" is set to the second index. */ if (lp->ll_range && !lp->ll_empty2) { - lp->ll_n2 = get_tv_number(&var2); /* is number or string */ - clear_tv(&var2); + lp->ll_n2 = (long)tv_get_number(&var2); // Is number or string. + tv_clear(&var2); if (lp->ll_n2 < 0) { - ni = list_find(lp->ll_list, lp->ll_n2); + ni = tv_list_find(lp->ll_list, lp->ll_n2); if (ni == NULL) { if (!quiet) EMSGN(_(e_listidx), lp->ll_n2); return NULL; } - lp->ll_n2 = list_idx_of_item(lp->ll_list, ni); + lp->ll_n2 = tv_list_idx_of_item(lp->ll_list, ni); } - /* Check that lp->ll_n2 isn't before lp->ll_n1. */ - if (lp->ll_n1 < 0) - lp->ll_n1 = list_idx_of_item(lp->ll_list, lp->ll_li); + // Check that lp->ll_n2 isn't before lp->ll_n1. + if (lp->ll_n1 < 0) { + lp->ll_n1 = tv_list_idx_of_item(lp->ll_list, lp->ll_li); + } if (lp->ll_n2 < lp->ll_n1) { - if (!quiet) + if (!quiet) { EMSGN(_(e_listidx), lp->ll_n2); + } return NULL; } } @@ -2304,6 +2345,8 @@ get_lval ( return p; } +// TODO(ZyX-I): move to eval/executor + /* * Clear lval "lp" that was filled by get_lval(). */ @@ -2313,44 +2356,48 @@ static void clear_lval(lval_T *lp) xfree(lp->ll_newkey); } +// TODO(ZyX-I): move to eval/executor + /* * Set a variable that was parsed by get_lval() to "rettv". * "endp" points to just after the parsed name. * "op" is NULL, "+" for "+=", "-" for "-=", "." for ".=" or "=" for "=". */ -static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op) +static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, + int copy, const char_u *op) { int cc; listitem_T *ri; dictitem_T *di; if (lp->ll_tv == NULL) { - if (!check_changedtick(lp->ll_name)) { - cc = *endp; - *endp = NUL; - if (op != NULL && *op != '=') { - typval_T tv; - - // handle +=, -= and .= - di = NULL; - if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name), - &tv, &di, true, false) == OK) { - if ((di == NULL - || (!var_check_ro(di->di_flags, lp->ll_name, false) - && !tv_check_lock(di->di_tv.v_lock, lp->ll_name, false))) - && tv_op(&tv, rettv, op) == OK) { - set_var(lp->ll_name, &tv, false); - } - clear_tv(&tv); + cc = *endp; + *endp = NUL; + if (op != NULL && *op != '=') { + typval_T tv; + + // handle +=, -= and .= + di = NULL; + if (get_var_tv((const char *)lp->ll_name, (int)STRLEN(lp->ll_name), + &tv, &di, true, false) == OK) { + if ((di == NULL + || (!var_check_ro(di->di_flags, (const char *)lp->ll_name, + TV_CSTRING) + && !tv_check_lock(di->di_tv.v_lock, (const char *)lp->ll_name, + TV_CSTRING))) + && eexe_mod_op(&tv, rettv, (const char *)op) == OK) { + set_var(lp->ll_name, lp->ll_name_len, &tv, false); } - } else - set_var(lp->ll_name, rettv, copy); - *endp = cc; + tv_clear(&tv); + } + } else { + set_var(lp->ll_name, lp->ll_name_len, rettv, copy); } + *endp = cc; } else if (tv_check_lock(lp->ll_newkey == NULL ? lp->ll_tv->v_lock : lp->ll_tv->vval.v_dict->dv_lock, - lp->ll_name, false)) { + (const char *)lp->ll_name, TV_CSTRING)) { } else if (lp->ll_range) { listitem_T *ll_li = lp->ll_li; int ll_n1 = lp->ll_n1; @@ -2358,7 +2405,8 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, ch // Check whether any of the list items is locked for (listitem_T *ri = rettv->vval.v_list->lv_first; ri != NULL && ll_li != NULL; ) { - if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name, false)) { + if (tv_check_lock(ll_li->li_tv.v_lock, (const char *)lp->ll_name, + TV_CSTRING)) { return; } ri = ri->li_next; @@ -2373,18 +2421,18 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, ch * Assign the List values to the list items. */ for (ri = rettv->vval.v_list->lv_first; ri != NULL; ) { - if (op != NULL && *op != '=') - tv_op(&lp->ll_li->li_tv, &ri->li_tv, op); - else { - clear_tv(&lp->ll_li->li_tv); - copy_tv(&ri->li_tv, &lp->ll_li->li_tv); + if (op != NULL && *op != '=') { + eexe_mod_op(&lp->ll_li->li_tv, &ri->li_tv, (const char *)op); + } else { + tv_clear(&lp->ll_li->li_tv); + tv_copy(&ri->li_tv, &lp->ll_li->li_tv); } ri = ri->li_next; if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == lp->ll_n1)) break; if (lp->ll_li->li_next == NULL) { - /* Need to add an empty item. */ - list_append_number(lp->ll_list, 0); + // Need to add an empty item. + tv_list_append_number(lp->ll_list, 0); assert(lp->ll_li->li_next); } lp->ll_li = lp->ll_li->li_next; @@ -2397,198 +2445,60 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, ch : lp->ll_n1 != lp->ll_n2) EMSG(_("E711: List value has not enough items")); } else { - typval_T oldtv; + typval_T oldtv = TV_INITIAL_VALUE; dict_T *dict = lp->ll_dict; - bool watched = is_watched(dict); + bool watched = tv_dict_is_watched(dict); - if (watched) { - init_tv(&oldtv); - } - - /* - * Assign to a List or Dictionary item. - */ + // Assign to a List or Dictionary item. if (lp->ll_newkey != NULL) { if (op != NULL && *op != '=') { EMSG2(_(e_letwrong), op); return; } - /* Need to add an item to the Dictionary. */ - di = dictitem_alloc(lp->ll_newkey); - if (dict_add(lp->ll_tv->vval.v_dict, di) == FAIL) { + // Need to add an item to the Dictionary. + di = tv_dict_item_alloc((const char *)lp->ll_newkey); + if (tv_dict_add(lp->ll_tv->vval.v_dict, di) == FAIL) { xfree(di); return; } lp->ll_tv = &di->di_tv; } else { if (watched) { - copy_tv(lp->ll_tv, &oldtv); + tv_copy(lp->ll_tv, &oldtv); } if (op != NULL && *op != '=') { - tv_op(lp->ll_tv, rettv, op); + eexe_mod_op(lp->ll_tv, rettv, (const char *)op); goto notify; } else { - clear_tv(lp->ll_tv); + tv_clear(lp->ll_tv); } } // Assign the value to the variable or list item. if (copy) { - copy_tv(rettv, lp->ll_tv); + tv_copy(rettv, lp->ll_tv); } else { *lp->ll_tv = *rettv; lp->ll_tv->v_lock = 0; - init_tv(rettv); + tv_init(rettv); } notify: if (watched) { if (oldtv.v_type == VAR_UNKNOWN) { - dictwatcher_notify(dict, (char *)lp->ll_newkey, lp->ll_tv, NULL); + tv_dict_watcher_notify(dict, (char *)lp->ll_newkey, lp->ll_tv, NULL); } else { dictitem_T *di = lp->ll_di; - dictwatcher_notify(dict, (char *)di->di_key, lp->ll_tv, &oldtv); - clear_tv(&oldtv); - } - } - } -} - -/* - * Handle "tv1 += tv2", "tv1 -= tv2" and "tv1 .= tv2" - * Returns OK or FAIL. - */ -static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op) -{ - long n; - char_u numbuf[NUMBUFLEN]; - char_u *s; - - // Can't do anything with a Funcref, a Dict or special value on the right. - if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT) { - switch (tv1->v_type) { - case VAR_DICT: - case VAR_FUNC: - case VAR_PARTIAL: - case VAR_SPECIAL: - break; - - case VAR_LIST: - if (*op != '+' || tv2->v_type != VAR_LIST) - break; - /* List += List */ - if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL) - list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL); - return OK; - - case VAR_NUMBER: - case VAR_STRING: - if (tv2->v_type == VAR_LIST) - break; - if (*op == '+' || *op == '-') { - /* nr += nr or nr -= nr*/ - n = get_tv_number(tv1); - if (tv2->v_type == VAR_FLOAT) { - float_T f = n; - - if (*op == '+') - f += tv2->vval.v_float; - else - f -= tv2->vval.v_float; - clear_tv(tv1); - tv1->v_type = VAR_FLOAT; - tv1->vval.v_float = f; - } else { - if (*op == '+') - n += get_tv_number(tv2); - else - n -= get_tv_number(tv2); - clear_tv(tv1); - tv1->v_type = VAR_NUMBER; - tv1->vval.v_number = n; - } - } else { - if (tv2->v_type == VAR_FLOAT) - break; - - /* str .= str */ - s = get_tv_string(tv1); - s = concat_str(s, get_tv_string_buf(tv2, numbuf)); - clear_tv(tv1); - tv1->v_type = VAR_STRING; - tv1->vval.v_string = s; + tv_dict_watcher_notify(dict, (char *)di->di_key, lp->ll_tv, &oldtv); + tv_clear(&oldtv); } - return OK; - - case VAR_FLOAT: - { - float_T f; - - if (*op == '.' || (tv2->v_type != VAR_FLOAT - && tv2->v_type != VAR_NUMBER - && tv2->v_type != VAR_STRING)) - break; - if (tv2->v_type == VAR_FLOAT) - f = tv2->vval.v_float; - else - f = get_tv_number(tv2); - if (*op == '+') - tv1->vval.v_float += f; - else - tv1->vval.v_float -= f; - } - return OK; - - case VAR_UNKNOWN: - assert(false); } } - - EMSG2(_(e_letwrong), op); - return FAIL; } -/* - * Add a watcher to a list. - */ -void list_add_watch(list_T *l, listwatch_T *lw) -{ - lw->lw_next = l->lv_watch; - l->lv_watch = lw; -} - -/* - * Remove a watcher from a list. - * No warning when it isn't found... - */ -void list_rem_watch(list_T *l, listwatch_T *lwrem) -{ - listwatch_T *lw, **lwp; - - lwp = &l->lv_watch; - for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next) { - if (lw == lwrem) { - *lwp = lw->lw_next; - break; - } - lwp = &lw->lw_next; - } -} - -/* - * Just before removing an item from a list: advance watchers to the next - * item. - */ -static void list_fix_watch(list_T *l, listitem_T *item) -{ - listwatch_T *lw; - - for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next) - if (lw->lw_item == item) - lw->lw_item = item->li_next; -} +// TODO(ZyX-I): move to eval/ex_cmds /* * Evaluate the expression used in a ":for var in expr" command. @@ -2596,14 +2506,14 @@ static void list_fix_watch(list_T *l, listitem_T *item) * Set "*errp" to TRUE for an error, FALSE otherwise; * Return a pointer that holds the info. Null when there is an error. */ -void *eval_for_line(char_u *arg, int *errp, char_u **nextcmdp, int skip) +void *eval_for_line(const char_u *arg, bool *errp, char_u **nextcmdp, int skip) { forinfo_T *fi = xcalloc(1, sizeof(forinfo_T)); - char_u *expr; + const char_u *expr; typval_T tv; list_T *l; - *errp = TRUE; /* default: there is an error */ + *errp = true; // Default: there is an error. expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon); if (expr == NULL) @@ -2618,20 +2528,20 @@ void *eval_for_line(char_u *arg, int *errp, char_u **nextcmdp, int skip) if (skip) ++emsg_skip; if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK) { - *errp = FALSE; + *errp = false; if (!skip) { l = tv.vval.v_list; if (tv.v_type != VAR_LIST) { EMSG(_(e_listreq)); - clear_tv(&tv); + tv_clear(&tv); } else if (l == NULL) { // a null list is like an empty list: do nothing - clear_tv(&tv); + tv_clear(&tv); } else { /* No need to increment the refcount, it's already set for the * list being used in "tv". */ fi->fi_list = l; - list_add_watch(l, &fi->fi_lw); + tv_list_watch_add(l, &fi->fi_lw); fi->fi_lw.lw_item = l->lv_first; } } @@ -2642,6 +2552,8 @@ void *eval_for_line(char_u *arg, int *errp, char_u **nextcmdp, int skip) return fi; } +// TODO(ZyX-I): move to eval/ex_cmds + /* * Use the first item in a ":for" list. Advance to the next. * Assign the values to the variable (list). "arg" points to the first one. @@ -2665,6 +2577,8 @@ int next_for_item(void *fi_void, char_u *arg) return result; } +// TODO(ZyX-I): move to eval/ex_cmds + /* * Free the structure used to store info used by ":for". */ @@ -2673,8 +2587,8 @@ void free_for_info(void *fi_void) forinfo_T *fi = (forinfo_T *)fi_void; if (fi != NULL && fi->fi_list != NULL) { - list_rem_watch(fi->fi_list, &fi->fi_lw); - list_unref(fi->fi_list); + tv_list_watch_remove(fi->fi_list, &fi->fi_lw); + tv_list_unref(fi->fi_list); } xfree(fi); } @@ -2762,6 +2676,7 @@ void set_context_for_expression(expand_T *xp, char_u *arg, cmdidx_T cmdidx) xp->xp_pattern = arg; } +// TODO(ZyX-I): move to eval/ex_cmds /* * ":1,25call func(arg1, arg2)" function call. @@ -2781,13 +2696,14 @@ void ex_call(exarg_T *eap) partial_T *partial = NULL; if (eap->skip) { - /* trans_function_name() doesn't work well when skipping, use eval0() - * instead to skip to any following command, e.g. for: - * :if 0 | call dict.foo().bar() | endif */ - ++emsg_skip; - if (eval0(eap->arg, &rettv, &eap->nextcmd, FALSE) != FAIL) - clear_tv(&rettv); - --emsg_skip; + // trans_function_name() doesn't work well when skipping, use eval0() + // instead to skip to any following command, e.g. for: + // :if 0 | call dict.foo().bar() | endif. + emsg_skip++; + if (eval0(eap->arg, &rettv, &eap->nextcmd, false) != FAIL) { + tv_clear(&rettv); + } + emsg_skip--; return; } @@ -2809,13 +2725,13 @@ void ex_call(exarg_T *eap) // contents. For VAR_PARTIAL get its partial, unless we already have one // from trans_function_name(). len = (int)STRLEN(tofree); - name = deref_func_name(tofree, &len, + name = deref_func_name((const char *)tofree, &len, partial != NULL ? NULL : &partial, false); /* Skip white space to allow ":call func ()". Not good, but required for * backward compatibility. */ startarg = skipwhite(arg); - rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */ + rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this. if (*startarg != '(') { EMSG2(_("E107: Missing parentheses: %s"), eap->arg); @@ -2829,12 +2745,13 @@ void ex_call(exarg_T *eap) * call, and the loop is broken. */ if (eap->skip) { - ++emsg_skip; - lnum = eap->line2; /* do it once, also with an invalid range */ - } else + emsg_skip++; + lnum = eap->line2; // Do it once, also with an invalid range. + } else { lnum = eap->line1; - for (; lnum <= eap->line2; ++lnum) { - if (!eap->skip && eap->addr_count > 0) { + } + for (; lnum <= eap->line2; lnum++) { + if (!eap->skip && eap->addr_count > 0) { // -V560 curwin->w_cursor.lnum = lnum; curwin->w_cursor.col = 0; curwin->w_cursor.coladd = 0; @@ -2847,15 +2764,17 @@ void ex_call(exarg_T *eap) break; } - /* Handle a function returning a Funcref, Dictionary or List. */ - if (handle_subscript(&arg, &rettv, !eap->skip, TRUE) == FAIL) { - failed = TRUE; + // Handle a function returning a Funcref, Dictionary or List. + if (handle_subscript((const char **)&arg, &rettv, !eap->skip, true) + == FAIL) { + failed = true; break; } - clear_tv(&rettv); - if (doesrange || eap->skip) + tv_clear(&rettv); + if (doesrange || eap->skip) { // -V560 break; + } /* Stop when immediately aborting on error, or when an interrupt * occurred or an exception was thrown but not caught. @@ -2877,10 +2796,12 @@ void ex_call(exarg_T *eap) } end: - dict_unref(fudi.fd_dict); + tv_dict_unref(fudi.fd_dict); xfree(tofree); } +// TODO(ZyX-I): move to eval/ex_cmds + /* * ":unlet[!] var1 ... " command. */ @@ -2889,6 +2810,8 @@ void ex_unlet(exarg_T *eap) ex_unletlock(eap, eap->arg, 0); } +// TODO(ZyX-I): move to eval/ex_cmds + /* * ":lockvar" and ":unlockvar" commands */ @@ -2907,22 +2830,25 @@ void ex_lockvar(exarg_T *eap) ex_unletlock(eap, arg, deep); } +// TODO(ZyX-I): move to eval/ex_cmds + /* * ":unlet", ":lockvar" and ":unlockvar" are quite similar. */ static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep) { char_u *arg = argstart; - char_u *name_end; - int error = FALSE; + bool error = false; lval_T lv; do { - /* Parse the name and find the end. */ - name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, 0, - FNE_CHECK_START); - if (lv.ll_name == NULL) - error = TRUE; /* error but continue parsing */ + // Parse the name and find the end. + char_u *const name_end = (char_u *)get_lval(arg, NULL, &lv, true, + eap->skip || error, + 0, FNE_CHECK_START); + if (lv.ll_name == NULL) { + error = true; // error, but continue parsing. + } if (name_end == NULL || (!ascii_iswhite(*name_end) && !ends_excmd(*name_end))) { if (name_end != NULL) { @@ -2940,8 +2866,9 @@ static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep) error = TRUE; } else { if (do_lock_var(&lv, name_end, deep, - eap->cmdidx == CMD_lockvar) == FAIL) - error = TRUE; + eap->cmdidx == CMD_lockvar) == FAIL) { + error = true; + } } } @@ -2954,7 +2881,9 @@ static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep) eap->nextcmd = check_nextcmd(arg); } -static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit) +// TODO(ZyX-I): move to eval/ex_cmds + +static int do_unlet_var(lval_T *const lp, char_u *const name_end, int forceit) { int ret = OK; int cc; @@ -2963,16 +2892,18 @@ static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit) cc = *name_end; *name_end = NUL; - /* Normal name or expanded name. */ - if (check_changedtick(lp->ll_name)) - ret = FAIL; - else if (do_unlet(lp->ll_name, forceit) == FAIL) + // Normal name or expanded name. + if (do_unlet(lp->ll_name, lp->ll_name_len, forceit) == FAIL) { ret = FAIL; + } *name_end = cc; } else if ((lp->ll_list != NULL - && tv_check_lock(lp->ll_list->lv_lock, lp->ll_name, false)) + && tv_check_lock(lp->ll_list->lv_lock, (const char *)lp->ll_name, + lp->ll_name_len)) || (lp->ll_dict != NULL - && tv_check_lock(lp->ll_dict->dv_lock, lp->ll_name, false))) { + && tv_check_lock(lp->ll_dict->dv_lock, + (const char *)lp->ll_name, + lp->ll_name_len))) { return FAIL; } else if (lp->ll_range) { listitem_T *li; @@ -2981,7 +2912,8 @@ static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit) while (ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= ll_n1)) { li = ll_li->li_next; - if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name, false)) { + if (tv_check_lock(ll_li->li_tv.v_lock, (const char *)lp->ll_name, + lp->ll_name_len)) { return false; } ll_li = li; @@ -2991,33 +2923,33 @@ static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit) /* Delete a range of List items. */ while (lp->ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1)) { li = lp->ll_li->li_next; - listitem_remove(lp->ll_list, lp->ll_li); + tv_list_item_remove(lp->ll_list, lp->ll_li); lp->ll_li = li; ++lp->ll_n1; } } else { if (lp->ll_list != NULL) { // unlet a List item. - listitem_remove(lp->ll_list, lp->ll_li); + tv_list_item_remove(lp->ll_list, lp->ll_li); } else { // unlet a Dictionary item. dict_T *d = lp->ll_dict; dictitem_T *di = lp->ll_di; - bool watched = is_watched(d); + bool watched = tv_dict_is_watched(d); char *key = NULL; typval_T oldtv; if (watched) { - copy_tv(&di->di_tv, &oldtv); + tv_copy(&di->di_tv, &oldtv); // need to save key because dictitem_remove will free it key = xstrdup((char *)di->di_key); } - dictitem_remove(d, di); + tv_dict_item_remove(d, di); if (watched) { - dictwatcher_notify(d, key, NULL, &oldtv); - clear_tv(&oldtv); + tv_dict_watcher_notify(d, key, NULL, &oldtv); + tv_clear(&oldtv); xfree(key); } } @@ -3026,21 +2958,24 @@ static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit) return ret; } -/* - * "unlet" a variable. Return OK if it existed, FAIL if not. - * When "forceit" is TRUE don't complain if the variable doesn't exist. - */ -int do_unlet(char_u *name, int forceit) +// TODO(ZyX-I): move to eval/ex_cmds + +/// unlet a variable +/// +/// @param[in] name Variable name to unlet. +/// @param[in] name_len Variable name length. +/// @param[in] fonceit If true, do not complain if variable doesn’t exist. +/// +/// @return OK if it existed, FAIL otherwise. +int do_unlet(const char *const name, const size_t name_len, const int forceit) + FUNC_ATTR_NONNULL_ALL { - hashtab_T *ht; - hashitem_T *hi; - char_u *varname; - dict_T *d; - dictitem_T *di; + const char *varname; dict_T *dict; - ht = find_var_ht_dict(name, &varname, &dict); + hashtab_T *ht = find_var_ht_dict(name, name_len, &varname, &dict); if (ht != NULL && *varname != NUL) { + dict_T *d; if (ht == &globvarht) { d = &globvardict; } else if (current_funccal != NULL @@ -3049,38 +2984,41 @@ int do_unlet(char_u *name, int forceit) } else if (ht == &compat_hashtab) { d = &vimvardict; } else { - di = find_var_in_ht(ht, *name, (char_u *)"", false); + dictitem_T *const di = find_var_in_ht(ht, *name, "", 0, false); d = di->di_tv.vval.v_dict; } if (d == NULL) { EMSG2(_(e_intern2), "do_unlet()"); return FAIL; } - hi = hash_find(ht, varname); - if (!HASHITEM_EMPTY(hi)) { - di = HI2DI(hi); - if (var_check_fixed(di->di_flags, name, false) - || var_check_ro(di->di_flags, name, false) - || tv_check_lock(d->dv_lock, name, false)) { + hashitem_T *hi = hash_find(ht, (const char_u *)varname); + if (HASHITEM_EMPTY(hi)) { + hi = find_hi_in_scoped_ht((const char *)name, &ht); + } + if (hi != NULL && !HASHITEM_EMPTY(hi)) { + dictitem_T *const di = TV_DICT_HI2DI(hi); + if (var_check_fixed(di->di_flags, (const char *)name, TV_CSTRING) + || var_check_ro(di->di_flags, (const char *)name, TV_CSTRING) + || tv_check_lock(d->dv_lock, (const char *)name, TV_CSTRING)) { return FAIL; } - if (d == NULL || tv_check_lock(d->dv_lock, name, false)) { + if (tv_check_lock(d->dv_lock, (const char *)name, TV_CSTRING)) { return FAIL; } typval_T oldtv; - bool watched = is_watched(dict); + bool watched = tv_dict_is_watched(dict); if (watched) { - copy_tv(&di->di_tv, &oldtv); + tv_copy(&di->di_tv, &oldtv); } delete_var(ht, hi); if (watched) { - dictwatcher_notify(dict, (char *)varname, NULL, &oldtv); - clear_tv(&oldtv); + tv_dict_watcher_notify(dict, varname, NULL, &oldtv); + tv_clear(&oldtv); } return OK; } @@ -3091,162 +3029,74 @@ int do_unlet(char_u *name, int forceit) return FAIL; } +// TODO(ZyX-I): move to eval/ex_cmds + /* * Lock or unlock variable indicated by "lp". * "deep" is the levels to go (-1 for unlimited); * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar". */ -static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock) +static int do_lock_var(lval_T *lp, char_u *const name_end, const int deep, + const bool lock) { int ret = OK; - int cc; - dictitem_T *di; - if (deep == 0) /* nothing to do */ + if (deep == 0) { // Nothing to do. return OK; + } if (lp->ll_tv == NULL) { - cc = *name_end; - *name_end = NUL; - - /* Normal name or expanded name. */ - if (check_changedtick(lp->ll_name)) + // Normal name or expanded name. + dictitem_T *const di = find_var( + (const char *)lp->ll_name, lp->ll_name_len, NULL, + true); + if (di == NULL) { ret = FAIL; - else { - di = find_var(lp->ll_name, NULL, TRUE); - if (di == NULL) - ret = FAIL; - else { - if (lock) - di->di_flags |= DI_FLAGS_LOCK; - else - di->di_flags &= ~DI_FLAGS_LOCK; - item_lock(&di->di_tv, deep, lock); + } else if ((di->di_flags & DI_FLAGS_FIX) + && di->di_tv.v_type != VAR_DICT + && di->di_tv.v_type != VAR_LIST) { + // For historical reasons this error is not given for Lists and + // Dictionaries. E.g. b: dictionary may be locked/unlocked. + emsgf(_("E940: Cannot lock or unlock variable %s"), lp->ll_name); + } else { + if (lock) { + di->di_flags |= DI_FLAGS_LOCK; + } else { + di->di_flags &= ~DI_FLAGS_LOCK; } + tv_item_lock(&di->di_tv, deep, lock); } - *name_end = cc; } else if (lp->ll_range) { listitem_T *li = lp->ll_li; /* (un)lock a range of List items. */ while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1)) { - item_lock(&li->li_tv, deep, lock); + tv_item_lock(&li->li_tv, deep, lock); li = li->li_next; ++lp->ll_n1; } } else if (lp->ll_list != NULL) { // (un)lock a List item. - item_lock(&lp->ll_li->li_tv, deep, lock); + tv_item_lock(&lp->ll_li->li_tv, deep, lock); } else { // (un)lock a Dictionary item. - item_lock(&lp->ll_di->di_tv, deep, lock); + tv_item_lock(&lp->ll_di->di_tv, deep, lock); } return ret; } /* - * Lock or unlock an item. "deep" is nr of levels to go. - */ -static void item_lock(typval_T *tv, int deep, int lock) -{ - static int recurse = 0; - list_T *l; - listitem_T *li; - dict_T *d; - hashitem_T *hi; - int todo; - - if (recurse >= DICT_MAXNEST) { - EMSG(_("E743: variable nested too deep for (un)lock")); - return; - } - if (deep == 0) - return; - ++recurse; - - /* lock/unlock the item itself */ - if (lock) - tv->v_lock |= VAR_LOCKED; - else - tv->v_lock &= ~VAR_LOCKED; - - switch (tv->v_type) { - case VAR_LIST: - if ((l = tv->vval.v_list) != NULL) { - if (lock) - l->lv_lock |= VAR_LOCKED; - else - l->lv_lock &= ~VAR_LOCKED; - if (deep < 0 || deep > 1) - /* recursive: lock/unlock the items the List contains */ - for (li = l->lv_first; li != NULL; li = li->li_next) - item_lock(&li->li_tv, deep - 1, lock); - } - break; - case VAR_DICT: - if ((d = tv->vval.v_dict) != NULL) { - if (lock) - d->dv_lock |= VAR_LOCKED; - else - d->dv_lock &= ~VAR_LOCKED; - if (deep < 0 || deep > 1) { - /* recursive: lock/unlock the items the List contains */ - todo = (int)d->dv_hashtab.ht_used; - for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - item_lock(&HI2DI(hi)->di_tv, deep - 1, lock); - } - } - } - } - break; - case VAR_NUMBER: - case VAR_FLOAT: - case VAR_STRING: - case VAR_FUNC: - case VAR_PARTIAL: - case VAR_SPECIAL: - break; - case VAR_UNKNOWN: - assert(false); - } - --recurse; -} - -/* - * Return TRUE if typeval "tv" is locked: Either that value is locked itself - * or it refers to a List or Dictionary that is locked. - */ -static int tv_islocked(typval_T *tv) -{ - return (tv->v_lock & VAR_LOCKED) - || (tv->v_type == VAR_LIST - && tv->vval.v_list != NULL - && (tv->vval.v_list->lv_lock & VAR_LOCKED)) - || (tv->v_type == VAR_DICT - && tv->vval.v_dict != NULL - && (tv->vval.v_dict->dv_lock & VAR_LOCKED)); -} - -/* * Delete all "menutrans_" variables. */ void del_menutrans_vars(void) { - hashitem_T *hi; - int todo; - hash_lock(&globvarht); - todo = (int)globvarht.ht_used; - for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0) - delete_var(&globvarht, hi); + HASHTAB_ITER(&globvarht, hi, { + if (STRNCMP(hi->hi_key, "menutrans_", 10) == 0) { + delete_var(&globvarht, hi); } - } + }); hash_unlock(&globvarht); } @@ -3322,10 +3172,6 @@ char_u *get_user_var_name(expand_T *xp, int idx) ++hi; return cat_prefix_varname('b', hi->hi_key); } - if (bdone == ht->ht_used) { - ++bdone; - return (char_u *)"b:changedtick"; - } /* w: variables */ ht = &curwin->w_vars->dv_hashtab; @@ -3362,6 +3208,7 @@ char_u *get_user_var_name(expand_T *xp, int idx) return NULL; } +// TODO(ZyX-I): move to eval/expressions /// Return TRUE if "pat" matches "text". /// Does not use 'cpo' and always uses 'magic'. @@ -3398,6 +3245,8 @@ typedef enum { , TYPE_NOMATCH /* !~ */ } exptype_T; +// TODO(ZyX-I): move to eval/expressions + /* * The "evaluate" argument: When FALSE, the argument is only parsed but not * executed. The function may return OK, but the rettv will be of type @@ -3411,7 +3260,7 @@ typedef enum { * Note: "rettv.v_lock" is not set. * Return OK or FAIL. */ -static int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate) +int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate) { int ret; char_u *p; @@ -3419,15 +3268,15 @@ static int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate) p = skipwhite(arg); ret = eval1(&p, rettv, evaluate); if (ret == FAIL || !ends_excmd(*p)) { - if (ret != FAIL) - clear_tv(rettv); - /* - * Report the invalid expression unless the expression evaluation has - * been cancelled due to an aborting error, an interrupt, or an - * exception. - */ - if (!aborting()) - EMSG2(_(e_invexpr2), arg); + if (ret != FAIL) { + tv_clear(rettv); + } + // Report the invalid expression unless the expression evaluation has + // been cancelled due to an aborting error, an interrupt, or an + // exception. + if (!aborting()) { + emsgf(_(e_invexpr2), arg); + } ret = FAIL; } if (nextcmd != NULL) @@ -3436,6 +3285,8 @@ static int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate) return ret; } +// TODO(ZyX-I): move to eval/expressions + /* * Handle top level expression: * expr2 ? expr1 : expr1 @@ -3461,13 +3312,15 @@ static int eval1(char_u **arg, typval_T *rettv, int evaluate) if ((*arg)[0] == '?') { result = FALSE; if (evaluate) { - int error = FALSE; + bool error = false; - if (get_tv_number_chk(rettv, &error) != 0) - result = TRUE; - clear_tv(rettv); - if (error) + if (tv_get_number_chk(rettv, &error) != 0) { + result = true; + } + tv_clear(rettv); + if (error) { return FAIL; + } } /* @@ -3481,9 +3334,10 @@ static int eval1(char_u **arg, typval_T *rettv, int evaluate) * Check for the ":". */ if ((*arg)[0] != ':') { - EMSG(_("E109: Missing ':' after '?'")); - if (evaluate && result) - clear_tv(rettv); + emsgf(_("E109: Missing ':' after '?'")); + if (evaluate && result) { + tv_clear(rettv); + } return FAIL; } @@ -3491,9 +3345,10 @@ static int eval1(char_u **arg, typval_T *rettv, int evaluate) * Get the third variable. */ *arg = skipwhite(*arg + 1); - if (eval1(arg, &var2, evaluate && !result) == FAIL) { /* recursive! */ - if (evaluate && result) - clear_tv(rettv); + if (eval1(arg, &var2, evaluate && !result) == FAIL) { // Recursive! + if (evaluate && result) { + tv_clear(rettv); + } return FAIL; } if (evaluate && !result) @@ -3503,6 +3358,8 @@ static int eval1(char_u **arg, typval_T *rettv, int evaluate) return OK; } +// TODO(ZyX-I): move to eval/expressions + /* * Handle first level expression: * expr2 || expr2 || expr2 logical OR @@ -3517,7 +3374,7 @@ static int eval2(char_u **arg, typval_T *rettv, int evaluate) typval_T var2; long result; int first; - int error = FALSE; + bool error = false; /* * Get the first variable. @@ -3532,12 +3389,14 @@ static int eval2(char_u **arg, typval_T *rettv, int evaluate) result = FALSE; while ((*arg)[0] == '|' && (*arg)[1] == '|') { if (evaluate && first) { - if (get_tv_number_chk(rettv, &error) != 0) - result = TRUE; - clear_tv(rettv); - if (error) + if (tv_get_number_chk(rettv, &error) != 0) { + result = true; + } + tv_clear(rettv); + if (error) { return FAIL; - first = FALSE; + } + first = false; } /* @@ -3551,11 +3410,13 @@ static int eval2(char_u **arg, typval_T *rettv, int evaluate) * Compute the result. */ if (evaluate && !result) { - if (get_tv_number_chk(&var2, &error) != 0) - result = TRUE; - clear_tv(&var2); - if (error) + if (tv_get_number_chk(&var2, &error) != 0) { + result = true; + } + tv_clear(&var2); + if (error) { return FAIL; + } } if (evaluate) { rettv->v_type = VAR_NUMBER; @@ -3566,6 +3427,8 @@ static int eval2(char_u **arg, typval_T *rettv, int evaluate) return OK; } +// TODO(ZyX-I): move to eval/expressions + /* * Handle second level expression: * expr3 && expr3 && expr3 logical AND @@ -3580,7 +3443,7 @@ static int eval3(char_u **arg, typval_T *rettv, int evaluate) typval_T var2; long result; int first; - int error = FALSE; + bool error = false; /* * Get the first variable. @@ -3595,12 +3458,14 @@ static int eval3(char_u **arg, typval_T *rettv, int evaluate) result = TRUE; while ((*arg)[0] == '&' && (*arg)[1] == '&') { if (evaluate && first) { - if (get_tv_number_chk(rettv, &error) == 0) - result = FALSE; - clear_tv(rettv); - if (error) + if (tv_get_number_chk(rettv, &error) == 0) { + result = false; + } + tv_clear(rettv); + if (error) { return FAIL; - first = FALSE; + } + first = false; } /* @@ -3614,11 +3479,13 @@ static int eval3(char_u **arg, typval_T *rettv, int evaluate) * Compute the result. */ if (evaluate && result) { - if (get_tv_number_chk(&var2, &error) == 0) - result = FALSE; - clear_tv(&var2); - if (error) + if (tv_get_number_chk(&var2, &error) == 0) { + result = false; + } + tv_clear(&var2); + if (error) { return FAIL; + } } if (evaluate) { rettv->v_type = VAR_NUMBER; @@ -3629,6 +3496,8 @@ static int eval3(char_u **arg, typval_T *rettv, int evaluate) return OK; } +// TODO(ZyX-I): move to eval/expressions + /* * Handle third level expression: * var1 == var2 @@ -3655,9 +3524,7 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate) exptype_T type = TYPE_UNKNOWN; int type_is = FALSE; /* TRUE for "is" and "isnot" */ int len = 2; - long n1, n2; - char_u *s1, *s2; - char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; + varnumber_T n1, n2; int ic; /* @@ -3725,7 +3592,7 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate) */ *arg = skipwhite(p + len); if (eval5(arg, &var2, evaluate) == FAIL) { - clear_tv(rettv); + tv_clear(rettv); return FAIL; } @@ -3747,15 +3614,15 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate) } else { EMSG(_("E692: Invalid operation for List")); } - clear_tv(rettv); - clear_tv(&var2); + tv_clear(rettv); + tv_clear(&var2); return FAIL; } else { - /* Compare two Lists for being equal or unequal. */ - n1 = list_equal(rettv->vval.v_list, var2.vval.v_list, - ic, FALSE); - if (type == TYPE_NEQUAL) + // Compare two Lists for being equal or unequal. + n1 = tv_list_equal(rettv->vval.v_list, var2.vval.v_list, ic, false); + if (type == TYPE_NEQUAL) { n1 = !n1; + } } } else if (rettv->v_type == VAR_DICT || var2.v_type == VAR_DICT) { if (type_is) { @@ -3769,23 +3636,22 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate) EMSG(_("E735: Can only compare Dictionary with Dictionary")); else EMSG(_("E736: Invalid operation for Dictionary")); - clear_tv(rettv); - clear_tv(&var2); + tv_clear(rettv); + tv_clear(&var2); return FAIL; } else { - /* Compare two Dictionaries for being equal or unequal. */ - n1 = dict_equal(rettv->vval.v_dict, var2.vval.v_dict, - ic, FALSE); - if (type == TYPE_NEQUAL) + // Compare two Dictionaries for being equal or unequal. + n1 = tv_dict_equal(rettv->vval.v_dict, var2.vval.v_dict, + ic, false); + if (type == TYPE_NEQUAL) { n1 = !n1; + } } - } else if (rettv->v_type == VAR_FUNC || var2.v_type == VAR_FUNC - || rettv->v_type == VAR_PARTIAL - || var2.v_type == VAR_PARTIAL) { + } else if (tv_is_func(*rettv) || tv_is_func(var2)) { if (type != TYPE_EQUAL && type != TYPE_NEQUAL) { EMSG(_("E694: Invalid operation for Funcrefs")); - clear_tv(rettv); - clear_tv(&var2); + tv_clear(rettv); + tv_clear(&var2); return FAIL; } if ((rettv->v_type == VAR_PARTIAL @@ -3820,25 +3686,27 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate) && type != TYPE_MATCH && type != TYPE_NOMATCH) { float_T f1, f2; - if (rettv->v_type == VAR_FLOAT) + if (rettv->v_type == VAR_FLOAT) { f1 = rettv->vval.v_float; - else - f1 = get_tv_number(rettv); - if (var2.v_type == VAR_FLOAT) + } else { + f1 = tv_get_number(rettv); + } + if (var2.v_type == VAR_FLOAT) { f2 = var2.vval.v_float; - else - f2 = get_tv_number(&var2); - n1 = FALSE; + } else { + f2 = tv_get_number(&var2); + } + n1 = false; switch (type) { - case TYPE_EQUAL: n1 = (f1 == f2); break; - case TYPE_NEQUAL: n1 = (f1 != f2); break; - case TYPE_GREATER: n1 = (f1 > f2); break; - case TYPE_GEQUAL: n1 = (f1 >= f2); break; - case TYPE_SMALLER: n1 = (f1 < f2); break; - case TYPE_SEQUAL: n1 = (f1 <= f2); break; - case TYPE_UNKNOWN: - case TYPE_MATCH: - case TYPE_NOMATCH: break; /* avoid gcc warning */ + case TYPE_EQUAL: n1 = (f1 == f2); break; + case TYPE_NEQUAL: n1 = (f1 != f2); break; + case TYPE_GREATER: n1 = (f1 > f2); break; + case TYPE_GEQUAL: n1 = (f1 >= f2); break; + case TYPE_SMALLER: n1 = (f1 < f2); break; + case TYPE_SEQUAL: n1 = (f1 <= f2); break; + case TYPE_UNKNOWN: + case TYPE_MATCH: + case TYPE_NOMATCH: break; } } /* @@ -3847,48 +3715,51 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate) */ else if ((rettv->v_type == VAR_NUMBER || var2.v_type == VAR_NUMBER) && type != TYPE_MATCH && type != TYPE_NOMATCH) { - n1 = get_tv_number(rettv); - n2 = get_tv_number(&var2); + n1 = tv_get_number(rettv); + n2 = tv_get_number(&var2); switch (type) { - case TYPE_EQUAL: n1 = (n1 == n2); break; - case TYPE_NEQUAL: n1 = (n1 != n2); break; - case TYPE_GREATER: n1 = (n1 > n2); break; - case TYPE_GEQUAL: n1 = (n1 >= n2); break; - case TYPE_SMALLER: n1 = (n1 < n2); break; - case TYPE_SEQUAL: n1 = (n1 <= n2); break; - case TYPE_UNKNOWN: - case TYPE_MATCH: - case TYPE_NOMATCH: break; /* avoid gcc warning */ + case TYPE_EQUAL: n1 = (n1 == n2); break; + case TYPE_NEQUAL: n1 = (n1 != n2); break; + case TYPE_GREATER: n1 = (n1 > n2); break; + case TYPE_GEQUAL: n1 = (n1 >= n2); break; + case TYPE_SMALLER: n1 = (n1 < n2); break; + case TYPE_SEQUAL: n1 = (n1 <= n2); break; + case TYPE_UNKNOWN: + case TYPE_MATCH: + case TYPE_NOMATCH: break; } } else { - s1 = get_tv_string_buf(rettv, buf1); - s2 = get_tv_string_buf(&var2, buf2); - if (type != TYPE_MATCH && type != TYPE_NOMATCH) - i = ic ? mb_stricmp(s1, s2) : STRCMP(s1, s2); - else + char buf1[NUMBUFLEN]; + char buf2[NUMBUFLEN]; + const char *const s1 = tv_get_string_buf(rettv, buf1); + const char *const s2 = tv_get_string_buf(&var2, buf2); + if (type != TYPE_MATCH && type != TYPE_NOMATCH) { + i = mb_strcmp_ic((bool)ic, s1, s2); + } else { i = 0; - n1 = FALSE; + } + n1 = false; switch (type) { - case TYPE_EQUAL: n1 = (i == 0); break; - case TYPE_NEQUAL: n1 = (i != 0); break; - case TYPE_GREATER: n1 = (i > 0); break; - case TYPE_GEQUAL: n1 = (i >= 0); break; - case TYPE_SMALLER: n1 = (i < 0); break; - case TYPE_SEQUAL: n1 = (i <= 0); break; - - case TYPE_MATCH: - case TYPE_NOMATCH: - n1 = pattern_match(s2, s1, ic); - if (type == TYPE_NOMATCH) { - n1 = !n1; + case TYPE_EQUAL: n1 = (i == 0); break; + case TYPE_NEQUAL: n1 = (i != 0); break; + case TYPE_GREATER: n1 = (i > 0); break; + case TYPE_GEQUAL: n1 = (i >= 0); break; + case TYPE_SMALLER: n1 = (i < 0); break; + case TYPE_SEQUAL: n1 = (i <= 0); break; + + case TYPE_MATCH: + case TYPE_NOMATCH: { + n1 = pattern_match((char_u *)s2, (char_u *)s1, ic); + if (type == TYPE_NOMATCH) { + n1 = !n1; + } + break; } - break; - - case TYPE_UNKNOWN: break; /* avoid gcc warning */ + case TYPE_UNKNOWN: break; // Avoid gcc warning. } } - clear_tv(rettv); - clear_tv(&var2); + tv_clear(rettv); + tv_clear(&var2); rettv->v_type = VAR_NUMBER; rettv->vval.v_number = n1; } @@ -3897,6 +3768,8 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate) return OK; } +// TODO(ZyX-I): move to eval/expressions + /* * Handle fourth level expression: * + number addition @@ -3913,10 +3786,8 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate) typval_T var2; typval_T var3; int op; - long n1, n2; + varnumber_T n1, n2; float_T f1 = 0, f2 = 0; - char_u *s1, *s2; - char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; char_u *p; /* @@ -3934,17 +3805,16 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate) break; if ((op != '+' || rettv->v_type != VAR_LIST) - && (op == '.' || rettv->v_type != VAR_FLOAT) - ) { - /* For "list + ...", an illegal use of the first operand as - * a number cannot be determined before evaluating the 2nd - * operand: if this is also a list, all is ok. - * For "something . ...", "something - ..." or "non-list + ...", - * we know that the first operand needs to be a string or number - * without evaluating the 2nd operand. So check before to avoid - * side effects after an error. */ - if (evaluate && get_tv_string_chk(rettv) == NULL) { - clear_tv(rettv); + && (op == '.' || rettv->v_type != VAR_FLOAT)) { + // For "list + ...", an illegal use of the first operand as + // a number cannot be determined before evaluating the 2nd + // operand: if this is also a list, all is ok. + // For "something . ...", "something - ..." or "non-list + ...", + // we know that the first operand needs to be a string or number + // without evaluating the 2nd operand. So check before to avoid + // side effects after an error. + if (evaluate && !tv_check_str(rettv)) { + tv_clear(rettv); return FAIL; } } @@ -3954,7 +3824,7 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate) */ *arg = skipwhite(*arg + 1); if (eval6(arg, &var2, evaluate, op == '.') == FAIL) { - clear_tv(rettv); + tv_clear(rettv); return FAIL; } @@ -3963,41 +3833,44 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate) * Compute the result. */ if (op == '.') { - s1 = get_tv_string_buf(rettv, buf1); /* already checked */ - s2 = get_tv_string_buf_chk(&var2, buf2); - if (s2 == NULL) { /* type error ? */ - clear_tv(rettv); - clear_tv(&var2); + char buf1[NUMBUFLEN]; + char buf2[NUMBUFLEN]; + // s1 already checked + const char *const s1 = tv_get_string_buf(rettv, buf1); + const char *const s2 = tv_get_string_buf_chk(&var2, buf2); + if (s2 == NULL) { // Type error? + tv_clear(rettv); + tv_clear(&var2); return FAIL; } - p = concat_str(s1, s2); - clear_tv(rettv); + p = concat_str((const char_u *)s1, (const char_u *)s2); + tv_clear(rettv); rettv->v_type = VAR_STRING; rettv->vval.v_string = p; } else if (op == '+' && rettv->v_type == VAR_LIST && var2.v_type == VAR_LIST) { - /* concatenate Lists */ - if (list_concat(rettv->vval.v_list, var2.vval.v_list, - &var3) == FAIL) { - clear_tv(rettv); - clear_tv(&var2); + // Concatenate Lists. + if (tv_list_concat(rettv->vval.v_list, var2.vval.v_list, &var3) + == FAIL) { + tv_clear(rettv); + tv_clear(&var2); return FAIL; } - clear_tv(rettv); + tv_clear(rettv); *rettv = var3; } else { - int error = FALSE; + bool error = false; if (rettv->v_type == VAR_FLOAT) { f1 = rettv->vval.v_float; n1 = 0; } else { - n1 = get_tv_number_chk(rettv, &error); + n1 = tv_get_number_chk(rettv, &error); if (error) { /* This can only happen for "list + non-list". For * "non-list + ..." or "something - ...", we returned * before evaluating the 2nd operand. */ - clear_tv(rettv); + tv_clear(rettv); return FAIL; } if (var2.v_type == VAR_FLOAT) @@ -4007,16 +3880,16 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate) f2 = var2.vval.v_float; n2 = 0; } else { - n2 = get_tv_number_chk(&var2, &error); + n2 = tv_get_number_chk(&var2, &error); if (error) { - clear_tv(rettv); - clear_tv(&var2); + tv_clear(rettv); + tv_clear(&var2); return FAIL; } if (rettv->v_type == VAR_FLOAT) f2 = n2; } - clear_tv(rettv); + tv_clear(rettv); /* If there is a float on either side the result is a float. */ if (rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT) { @@ -4035,37 +3908,36 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate) rettv->vval.v_number = n1; } } - clear_tv(&var2); + tv_clear(&var2); } } return OK; } -/* - * Handle fifth level expression: - * * number multiplication - * / number division - * % number modulo - * - * "arg" must point to the first non-white of the expression. - * "arg" is advanced to the next non-white after the recognized expression. - * - * Return OK or FAIL. - */ -static int -eval6 ( - char_u **arg, - typval_T *rettv, - int evaluate, - int want_string /* after "." operator */ -) +// TODO(ZyX-I): move to eval/expressions + +/// Handle fifth level expression: +/// - * number multiplication +/// - / number division +/// - % number modulo +/// +/// @param[in,out] arg Points to the first non-whitespace character of the +/// expression. Is advanced to the next non-whitespace +/// character after the recognized expression. +/// @param[out] rettv Location where result is saved. +/// @param[in] evaluate If not true, rettv is not populated. +/// @param[in] want_string True if "." is string_concatenation, otherwise +/// float +/// @return OK or FAIL. +static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string) + FUNC_ATTR_NO_SANITIZE_UNDEFINED { typval_T var2; int op; - long n1, n2; - int use_float = FALSE; + varnumber_T n1, n2; + bool use_float = false; float_T f1 = 0, f2; - int error = FALSE; + bool error = false; /* * Get the first variable. @@ -4084,15 +3956,18 @@ eval6 ( if (evaluate) { if (rettv->v_type == VAR_FLOAT) { f1 = rettv->vval.v_float; - use_float = TRUE; + use_float = true; n1 = 0; - } else - n1 = get_tv_number_chk(rettv, &error); - clear_tv(rettv); - if (error) + } else { + n1 = tv_get_number_chk(rettv, &error); + } + tv_clear(rettv); + if (error) { return FAIL; - } else + } + } else { n1 = 0; + } /* * Get the second variable. @@ -4105,17 +3980,19 @@ eval6 ( if (var2.v_type == VAR_FLOAT) { if (!use_float) { f1 = n1; - use_float = TRUE; + use_float = true; } f2 = var2.vval.v_float; n2 = 0; } else { - n2 = get_tv_number_chk(&var2, &error); - clear_tv(&var2); - if (error) + n2 = tv_get_number_chk(&var2, &error); + tv_clear(&var2); + if (error) { return FAIL; - if (use_float) + } + if (use_float) { f2 = n2; + } } /* @@ -4146,18 +4023,20 @@ eval6 ( rettv->v_type = VAR_FLOAT; rettv->vval.v_float = f1; } else { - if (op == '*') + if (op == '*') { n1 = n1 * n2; - else if (op == '/') { - if (n2 == 0) { /* give an error message? */ - if (n1 == 0) - n1 = -0x7fffffffL - 1L; /* similar to NaN */ - else if (n1 < 0) - n1 = -0x7fffffffL; - else - n1 = 0x7fffffffL; - } else + } else if (op == '/') { + if (n2 == 0) { // give an error message? + if (n1 == 0) { + n1 = VARNUMBER_MIN; // similar to NaN + } else if (n1 < 0) { + n1 = -VARNUMBER_MAX; + } else { + n1 = VARNUMBER_MAX; + } + } else { n1 = n1 / n2; + } } else { if (n2 == 0) /* give an error message? */ n1 = 0; @@ -4173,6 +4052,8 @@ eval6 ( return OK; } +// TODO(ZyX-I): move to eval/expressions + // Handle sixth level expression: // number number constant // "string" string constant @@ -4204,18 +4085,18 @@ static int eval7( int want_string // after "." operator ) { - long n; + varnumber_T n; int len; char_u *s; char_u *start_leader, *end_leader; int ret = OK; char_u *alias; - // Initialise variable so that clear_tv() can't mistake this for a + // Initialise variable so that tv_clear() can't mistake this for a // string and free a string that isn't there. rettv->v_type = VAR_UNKNOWN; - // Skip '!' and '-' characters. They are handled later. + // Skip '!', '-' and '+' characters. They are handled later. start_leader = *arg; while (**arg == '!' || **arg == '-' || **arg == '+') { *arg = skipwhite(*arg + 1); @@ -4292,14 +4173,19 @@ static int eval7( case '[': ret = get_list_tv(arg, rettv, evaluate); break; + // Lambda: {arg, arg -> expr} // Dictionary: {key: val, key: val} - case '{': ret = get_dict_tv(arg, rettv, evaluate); + case '{': ret = get_lambda_tv(arg, rettv, evaluate); + if (ret == NOTDONE) { + ret = get_dict_tv(arg, rettv, evaluate); + } break; // Option value: &name - case '&': ret = get_option_tv(arg, rettv, evaluate); + case '&': { + ret = get_option_tv((const char **)arg, rettv, evaluate); break; - + } // Environment variable: $VAR. case '$': ret = get_env_tv(arg, rettv, evaluate); break; @@ -4322,7 +4208,7 @@ static int eval7( ++*arg; } else if (ret == OK) { EMSG(_("E110: Missing ')'")); - clear_tv(rettv); + tv_clear(rettv); ret = FAIL; } break; @@ -4335,7 +4221,7 @@ static int eval7( // Must be a variable or function name. // Can also be a curly-braces kind of name: {expr}. s = *arg; - len = get_name_len(arg, &alias, evaluate, true); + len = get_name_len((const char **)arg, (char **)&alias, evaluate, true); if (alias != NULL) { s = alias; } @@ -4345,20 +4231,31 @@ static int eval7( } else { if (**arg == '(') { // recursive! partial_T *partial; + + if (!evaluate) { + check_vars((const char *)s, len); + } + // If "s" is the name of a variable of type VAR_FUNC // use its contents. - s = deref_func_name(s, &len, &partial, !evaluate); + s = deref_func_name((const char *)s, &len, &partial, !evaluate); + + // Need to make a copy, in case evaluating the arguments makes + // the name invalid. + s = xmemdupz(s, len); // Invoke the function. ret = get_func_tv(s, len, rettv, arg, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &len, evaluate, partial, NULL); + xfree(s); + // If evaluate is false rettv->v_type was not set in // get_func_tv, but it's needed in handle_subscript() to parse // what follows. So set it here. if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(') { - rettv->vval.v_string = empty_string; + rettv->vval.v_string = (char_u *)tv_empty_string; rettv->v_type = VAR_FUNC; } @@ -4367,13 +4264,14 @@ static int eval7( // an exception was thrown but not caught. if (aborting()) { if (ret == OK) { - clear_tv(rettv); + tv_clear(rettv); } ret = FAIL; } } else if (evaluate) { - ret = get_var_tv(s, len, rettv, NULL, true, false); + ret = get_var_tv((const char *)s, len, rettv, NULL, true, false); } else { + check_vars((const char *)s, len); ret = OK; } } @@ -4385,22 +4283,22 @@ static int eval7( // Handle following '[', '(' and '.' for expr[expr], expr.name, // expr(expr). if (ret == OK) { - ret = handle_subscript(arg, rettv, evaluate, true); + ret = handle_subscript((const char **)arg, rettv, evaluate, true); } // Apply logical NOT and unary '-', from right to left, ignore '+'. if (ret == OK && evaluate && end_leader > start_leader) { - int error = false; - int val = 0; + bool error = false; + varnumber_T val = 0; float_T f = 0.0; if (rettv->v_type == VAR_FLOAT) { f = rettv->vval.v_float; } else { - val = get_tv_number_chk(rettv, &error); + val = tv_get_number_chk(rettv, &error); } if (error) { - clear_tv(rettv); + tv_clear(rettv); ret = FAIL; } else { while (end_leader > start_leader) { @@ -4420,10 +4318,10 @@ static int eval7( } } if (rettv->v_type == VAR_FLOAT) { - clear_tv(rettv); + tv_clear(rettv); rettv->vval.v_float = f; } else { - clear_tv(rettv); + tv_clear(rettv); rettv->v_type = VAR_NUMBER; rettv->vval.v_number = val; } @@ -4433,6 +4331,8 @@ static int eval7( return ret; } +// TODO(ZyX-I): move to eval/expressions + /* * Evaluate an "[expr]" or "[expr:expr]" index. Also "dict.key". * "*arg" points to the '[' or '.'. @@ -4446,12 +4346,11 @@ eval_index ( int verbose /* give error messages */ ) { - int empty1 = FALSE, empty2 = FALSE; - typval_T var1, var2; + bool empty1 = false; + bool empty2 = false; long n1, n2 = 0; - long len = -1; - int range = FALSE; - char_u *s; + ptrdiff_t len = -1; + int range = false; char_u *key = NULL; switch (rettv->v_type) { @@ -4488,8 +4387,8 @@ eval_index ( } } - init_tv(&var1); - init_tv(&var2); + typval_T var1 = TV_INITIAL_VALUE; + typval_T var2 = TV_INITIAL_VALUE; if (**arg == '.') { /* * dict.name @@ -4507,13 +4406,13 @@ eval_index ( * Get the (first) variable from inside the []. */ *arg = skipwhite(*arg + 1); - if (**arg == ':') - empty1 = TRUE; - else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */ + if (**arg == ':') { + empty1 = true; + } else if (eval1(arg, &var1, evaluate) == FAIL) { // Recursive! return FAIL; - else if (evaluate && get_tv_string_chk(&var1) == NULL) { - /* not a number or string */ - clear_tv(&var1); + } else if (evaluate && !tv_check_str(&var1)) { + // Not a number or string. + tv_clear(&var1); return FAIL; } @@ -4523,28 +4422,32 @@ eval_index ( if (**arg == ':') { range = TRUE; *arg = skipwhite(*arg + 1); - if (**arg == ']') - empty2 = TRUE; - else if (eval1(arg, &var2, evaluate) == FAIL) { /* recursive! */ - if (!empty1) - clear_tv(&var1); + if (**arg == ']') { + empty2 = true; + } else if (eval1(arg, &var2, evaluate) == FAIL) { // Recursive! + if (!empty1) { + tv_clear(&var1); + } return FAIL; - } else if (evaluate && get_tv_string_chk(&var2) == NULL) { - /* not a number or string */ - if (!empty1) - clear_tv(&var1); - clear_tv(&var2); + } else if (evaluate && !tv_check_str(&var2)) { + // Not a number or string. + if (!empty1) { + tv_clear(&var1); + } + tv_clear(&var2); return FAIL; } } /* Check for the ']'. */ if (**arg != ']') { - if (verbose) - EMSG(_(e_missbrac)); - clear_tv(&var1); - if (range) - clear_tv(&var2); + if (verbose) { + emsgf(_(e_missbrac)); + } + tv_clear(&var1); + if (range) { + tv_clear(&var2); + } return FAIL; } *arg = skipwhite(*arg + 1); /* skip the ']' */ @@ -4553,168 +4456,181 @@ eval_index ( if (evaluate) { n1 = 0; if (!empty1 && rettv->v_type != VAR_DICT) { - n1 = get_tv_number(&var1); - clear_tv(&var1); + n1 = tv_get_number(&var1); + tv_clear(&var1); } if (range) { - if (empty2) + if (empty2) { n2 = -1; - else { - n2 = get_tv_number(&var2); - clear_tv(&var2); + } else { + n2 = tv_get_number(&var2); + tv_clear(&var2); } } switch (rettv->v_type) { - case VAR_NUMBER: - case VAR_STRING: - s = get_tv_string(rettv); - len = (long)STRLEN(s); - if (range) { - /* The resulting variable is a substring. If the indexes - * are out of range the result is empty. */ + case VAR_NUMBER: + case VAR_STRING: { + const char *const s = tv_get_string(rettv); + char *v; + len = (ptrdiff_t)strlen(s); + if (range) { + // The resulting variable is a substring. If the indexes + // are out of range the result is empty. + if (n1 < 0) { + n1 = len + n1; + if (n1 < 0) { + n1 = 0; + } + } + if (n2 < 0) { + n2 = len + n2; + } else if (n2 >= len) { + n2 = len; + } + if (n1 >= len || n2 < 0 || n1 > n2) { + v = NULL; + } else { + v = xmemdupz(s + n1, (size_t)(n2 - n1 + 1)); + } + } else { + // The resulting variable is a string of a single + // character. If the index is too big or negative the + // result is empty. + if (n1 >= len || n1 < 0) { + v = NULL; + } else { + v = xmemdupz(s + n1, 1); + } + } + tv_clear(rettv); + rettv->v_type = VAR_STRING; + rettv->vval.v_string = (char_u *)v; + break; + } + case VAR_LIST: { + len = tv_list_len(rettv->vval.v_list); if (n1 < 0) { n1 = len + n1; - if (n1 < 0) - n1 = 0; } - if (n2 < 0) - n2 = len + n2; - else if (n2 >= len) - n2 = len; - if (n1 >= len || n2 < 0 || n1 > n2) - s = NULL; - else - s = vim_strnsave(s + n1, (int)(n2 - n1 + 1)); - } else { - /* The resulting variable is a string of a single - * character. If the index is too big or negative the - * result is empty. */ - if (n1 >= len || n1 < 0) - s = NULL; - else - s = vim_strnsave(s + n1, 1); - } - clear_tv(rettv); - rettv->v_type = VAR_STRING; - rettv->vval.v_string = s; - break; - - case VAR_LIST: - len = list_len(rettv->vval.v_list); - if (n1 < 0) - n1 = len + n1; - if (!empty1 && (n1 < 0 || n1 >= len)) { - /* For a range we allow invalid values and return an empty - * list. A list index out of range is an error. */ - if (!range) { - if (verbose) - EMSGN(_(e_listidx), n1); - return FAIL; + if (!empty1 && (n1 < 0 || n1 >= len)) { + // For a range we allow invalid values and return an empty + // list. A list index out of range is an error. + if (!range) { + if (verbose) { + EMSGN(_(e_listidx), n1); + } + return FAIL; + } + n1 = len; } - n1 = len; - } - if (range) { - list_T *l; - listitem_T *item; - - if (n2 < 0) - n2 = len + n2; - else if (n2 >= len) - n2 = len - 1; - if (!empty2 && (n2 < 0 || n2 + 1 < n1)) - n2 = -1; - l = list_alloc(); - item = list_find(rettv->vval.v_list, n1); - while (n1++ <= n2) { - list_append_tv(l, &item->li_tv); - item = item->li_next; + if (range) { + list_T *l; + listitem_T *item; + + if (n2 < 0) { + n2 = len + n2; + } else if (n2 >= len) { + n2 = len - 1; + } + if (!empty2 && (n2 < 0 || n2 + 1 < n1)) { + n2 = -1; + } + l = tv_list_alloc(); + item = tv_list_find(rettv->vval.v_list, n1); + while (n1++ <= n2) { + tv_list_append_tv(l, &item->li_tv); + item = item->li_next; + } + tv_clear(rettv); + rettv->v_type = VAR_LIST; + rettv->vval.v_list = l; + l->lv_refcount++; + } else { + tv_copy(&tv_list_find(rettv->vval.v_list, n1)->li_tv, &var1); + tv_clear(rettv); + *rettv = var1; } - clear_tv(rettv); - rettv->v_type = VAR_LIST; - rettv->vval.v_list = l; - ++l->lv_refcount; - } else { - copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv, &var1); - clear_tv(rettv); - *rettv = var1; - } - break; - - case VAR_DICT: - if (range) { - if (verbose) - EMSG(_(e_dictrange)); - if (len == -1) - clear_tv(&var1); - return FAIL; + break; } - { - dictitem_T *item; + case VAR_DICT: { + if (range) { + if (verbose) { + emsgf(_(e_dictrange)); + } + if (len == -1) { + tv_clear(&var1); + } + return FAIL; + } if (len == -1) { - key = get_tv_string_chk(&var1); + key = (char_u *)tv_get_string_chk(&var1); if (key == NULL) { - clear_tv(&var1); + tv_clear(&var1); return FAIL; } } - item = dict_find(rettv->vval.v_dict, key, (int)len); + dictitem_T *const item = tv_dict_find(rettv->vval.v_dict, + (const char *)key, len); - if (item == NULL && verbose) - EMSG2(_(e_dictkey), key); - if (len == -1) - clear_tv(&var1); - if (item == NULL) + if (item == NULL && verbose) { + emsgf(_(e_dictkey), key); + } + if (len == -1) { + tv_clear(&var1); + } + if (item == NULL) { return FAIL; + } - copy_tv(&item->di_tv, &var1); - clear_tv(rettv); + tv_copy(&item->di_tv, &var1); + tv_clear(rettv); *rettv = var1; + break; + } + case VAR_SPECIAL: + case VAR_FUNC: + case VAR_FLOAT: + case VAR_PARTIAL: + case VAR_UNKNOWN: { + break; // Not evaluating, skipping over subscript } - break; - case VAR_SPECIAL: - case VAR_FUNC: - case VAR_PARTIAL: - case VAR_FLOAT: - case VAR_UNKNOWN: - break; // Not evaluating, skipping over subscript } } return OK; } -/* - * Get an option value. - * "arg" points to the '&' or '+' before the option name. - * "arg" is advanced to character after the option name. - * Return OK or FAIL. - */ -static int -get_option_tv ( - char_u **arg, - typval_T *rettv, /* when NULL, only check if option exists */ - int evaluate -) +// TODO(ZyX-I): move to eval/executor + +/// Get an option value +/// +/// @param[in,out] arg Points to the '&' or '+' before the option name. Is +/// advanced to the character after the option name. +/// @param[out] rettv Location where result is saved. +/// @param[in] evaluate If not true, rettv is not populated. +/// +/// @return OK or FAIL. +static int get_option_tv(const char **const arg, typval_T *const rettv, + const bool evaluate) + FUNC_ATTR_NONNULL_ARG(1) { - char_u *option_end; long numval; char_u *stringval; int opt_type; int c; - int working = (**arg == '+'); /* has("+option") */ + bool working = (**arg == '+'); // has("+option") int ret = OK; int opt_flags; - /* - * Isolate the option name and find its value. - */ - option_end = find_option_end(arg, &opt_flags); + // Isolate the option name and find its value. + char *option_end = (char *)find_option_end(arg, &opt_flags); if (option_end == NULL) { - if (rettv != NULL) + if (rettv != NULL) { EMSG2(_("E112: Option name missing: %s"), *arg); + } return FAIL; } @@ -4725,8 +4641,8 @@ get_option_tv ( c = *option_end; *option_end = NUL; - opt_type = get_option_value(*arg, &numval, - rettv == NULL ? NULL : &stringval, opt_flags); + opt_type = get_option_value((char_u *)(*arg), &numval, + rettv == NULL ? NULL : &stringval, opt_flags); if (opt_type == -3) { /* invalid name */ if (rettv != NULL) @@ -4856,7 +4772,7 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate) // Special key, e.g.: "\<C-W>" case '<': - extra = trans_special((const char_u **) &p, STRLEN(p), name, true); + extra = trans_special((const char_u **)&p, STRLEN(p), name, true, true); if (extra != 0) { name += extra; break; @@ -4871,7 +4787,10 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate) } *name = NUL; - *arg = p + 1; + if (*p != NUL) { // just in case + p++; + } + *arg = p; return OK; } @@ -4930,18 +4849,35 @@ static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate) return OK; } +/// @return the function name of the partial. +char_u *partial_name(partial_T *pt) +{ + if (pt->pt_name != NULL) { + return pt->pt_name; + } + return pt->pt_func->uf_name; +} + +// TODO(ZyX-I): Move to eval/typval.h + static void partial_free(partial_T *pt) { for (int i = 0; i < pt->pt_argc; i++) { - clear_tv(&pt->pt_argv[i]); + tv_clear(&pt->pt_argv[i]); } xfree(pt->pt_argv); - dict_unref(pt->pt_dict); - func_unref(pt->pt_name); - xfree(pt->pt_name); + tv_dict_unref(pt->pt_dict); + if (pt->pt_name != NULL) { + func_unref(pt->pt_name); + xfree(pt->pt_name); + } else { + func_ptr_unref(pt->pt_func); + } xfree(pt); } +// TODO(ZyX-I): Move to eval/typval.h + /// Unreference a closure: decrement the reference count and free it when it /// becomes zero. void partial_unref(partial_T *pt) @@ -4960,7 +4896,7 @@ static int get_list_tv(char_u **arg, typval_T *rettv, int evaluate) listitem_T *item; if (evaluate) { - l = list_alloc(); + l = tv_list_alloc(); } *arg = skipwhite(*arg + 1); @@ -4968,10 +4904,10 @@ static int get_list_tv(char_u **arg, typval_T *rettv, int evaluate) if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */ goto failret; if (evaluate) { - item = listitem_alloc(); + item = tv_list_item_alloc(); item->li_tv = tv; item->li_tv.v_lock = 0; - list_append(l, item); + tv_list_append(l, item); } if (**arg == ']') @@ -4987,7 +4923,7 @@ static int get_list_tv(char_u **arg, typval_T *rettv, int evaluate) EMSG2(_("E697: Missing end of List ']': %s"), *arg); failret: if (evaluate) { - list_free(l); + tv_list_free(l); } return FAIL; } @@ -5002,196 +4938,7 @@ failret: return OK; } -/* - * Allocate an empty header for a list. - * Caller should take care of the reference count. - */ -list_T *list_alloc(void) FUNC_ATTR_NONNULL_RET -{ - list_T *list = xcalloc(1, sizeof(list_T)); - - /* Prepend the list to the list of lists for garbage collection. */ - if (first_list != NULL) - first_list->lv_used_prev = list; - list->lv_used_prev = NULL; - list->lv_used_next = first_list; - first_list = list; - return list; -} - -/* - * Allocate an empty list for a return value. - */ -static list_T *rettv_list_alloc(typval_T *rettv) -{ - list_T *l = list_alloc(); - rettv->vval.v_list = l; - rettv->v_type = VAR_LIST; - rettv->v_lock = VAR_UNLOCKED; - l->lv_refcount++; - return l; -} - -/// Unreference a list: decrement the reference count and free it when it -/// becomes zero. -void list_unref(list_T *l) { - if (l != NULL && --l->lv_refcount <= 0) { - list_free(l); - } -} - -/// Free a list, including all items it points to. -/// Ignores the reference count. -static void list_free_contents(list_T *l) { - listitem_T *item; - - for (item = l->lv_first; item != NULL; item = l->lv_first) { - // Remove the item before deleting it. - l->lv_first = item->li_next; - clear_tv(&item->li_tv); - xfree(item); - } -} - -static void list_free_list(list_T *l) { - // Remove the list from the list of lists for garbage collection. - if (l->lv_used_prev == NULL) { - first_list = l->lv_used_next; - } else { - l->lv_used_prev->lv_used_next = l->lv_used_next; - } - if (l->lv_used_next != NULL) { - l->lv_used_next->lv_used_prev = l->lv_used_prev; - } - - xfree(l); -} - -void list_free(list_T *l) { - if (!in_free_unref_items) { - list_free_contents(l); - list_free_list(l); - } -} - -/* - * Allocate a list item. - * It is not initialized, don't forget to set v_lock. - */ -listitem_T *listitem_alloc(void) FUNC_ATTR_NONNULL_RET -{ - return xmalloc(sizeof(listitem_T)); -} - -/* - * Free a list item. Also clears the value. Does not notify watchers. - */ -void listitem_free(listitem_T *item) -{ - clear_tv(&item->li_tv); - xfree(item); -} - -/* - * Remove a list item from a List and free it. Also clears the value. - */ -void listitem_remove(list_T *l, listitem_T *item) -{ - vim_list_remove(l, item, item); - listitem_free(item); -} - -/* - * Get the number of items in a list. - */ -static long list_len(list_T *l) -{ - if (l == NULL) - return 0L; - return l->lv_len; -} - -/* - * Return TRUE when two lists have exactly the same values. - */ -static int -list_equal ( - list_T *l1, - list_T *l2, - int ic, /* ignore case for strings */ - int recursive /* TRUE when used recursively */ -) -{ - listitem_T *item1, *item2; - - if (l1 == NULL || l2 == NULL) - return FALSE; - if (l1 == l2) - return TRUE; - if (list_len(l1) != list_len(l2)) - return FALSE; - - for (item1 = l1->lv_first, item2 = l2->lv_first; - item1 != NULL && item2 != NULL; - item1 = item1->li_next, item2 = item2->li_next) - if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive)) - return FALSE; - return item1 == NULL && item2 == NULL; -} - -/* - * Return the dictitem that an entry in a hashtable points to. - */ -dictitem_T *dict_lookup(hashitem_T *hi) -{ - return HI2DI(hi); -} - -/* - * Return TRUE when two dictionaries have exactly the same key/values. - */ -static int -dict_equal ( - dict_T *d1, - dict_T *d2, - int ic, /* ignore case for strings */ - int recursive /* TRUE when used recursively */ -) -{ - hashitem_T *hi; - dictitem_T *item2; - int todo; - - if (d1 == NULL && d2 == NULL) { - return true; - } - if (d1 == NULL || d2 == NULL) { - return false; - } - if (d1 == d2) { - return true; - } - if (dict_len(d1) != dict_len(d2)) { - return false; - } - - todo = (int)d1->dv_hashtab.ht_used; - for (hi = d1->dv_hashtab.ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - item2 = dict_find(d2, hi->hi_key, -1); - if (item2 == NULL) - return FALSE; - if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic, recursive)) - return FALSE; - --todo; - } - } - return TRUE; -} - -static int tv_equal_recurse_limit; - -static bool func_equal( +bool func_equal( typval_T *tv1, typval_T *tv2, bool ic // ignore case @@ -5202,12 +4949,12 @@ static bool func_equal( // empty and NULL function name considered the same s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string - : tv1->vval.v_partial->pt_name; + : partial_name(tv1->vval.v_partial); if (s1 != NULL && *s1 == NUL) { s1 = NULL; } s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string - : tv2->vval.v_partial->pt_name; + : partial_name(tv2->vval.v_partial); if (s2 != NULL && *s2 == NUL) { s2 = NULL; } @@ -5226,7 +4973,7 @@ static bool func_equal( if (d1 != d2) { return false; } - } else if (!dict_equal(d1, d2, ic, true)) { + } else if (!tv_dict_equal(d1, d2, ic, true)) { return false; } @@ -5245,550 +4992,6 @@ static bool func_equal( return true; } -/* - * Return TRUE if "tv1" and "tv2" have the same value. - * Compares the items just like "==" would compare them, but strings and - * numbers are different. Floats and numbers are also different. - */ -static int -tv_equal ( - typval_T *tv1, - typval_T *tv2, - int ic, /* ignore case */ - int recursive /* TRUE when used recursively */ -) -{ - char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; - char_u *s1, *s2; - static int recursive_cnt = 0; /* catch recursive loops */ - int r; - - /* Catch lists and dicts that have an endless loop by limiting - * recursiveness to a limit. We guess they are equal then. - * A fixed limit has the problem of still taking an awful long time. - * Reduce the limit every time running into it. That should work fine for - * deeply linked structures that are not recursively linked and catch - * recursiveness quickly. */ - if (!recursive) - tv_equal_recurse_limit = 1000; - if (recursive_cnt >= tv_equal_recurse_limit) { - --tv_equal_recurse_limit; - return TRUE; - } - - // For VAR_FUNC and VAR_PARTIAL only compare the function name. - if ((tv1->v_type == VAR_FUNC - || (tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial != NULL)) - && (tv2->v_type == VAR_FUNC - || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial != NULL))) { - recursive_cnt++; - r = func_equal(tv1, tv2, ic); - recursive_cnt--; - return r; - } - if (tv1->v_type != tv2->v_type) { - return false; - } - - switch (tv1->v_type) { - case VAR_LIST: - ++recursive_cnt; - r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, TRUE); - --recursive_cnt; - return r; - - case VAR_DICT: - ++recursive_cnt; - r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, TRUE); - --recursive_cnt; - return r; - - case VAR_NUMBER: - return tv1->vval.v_number == tv2->vval.v_number; - - case VAR_FLOAT: - return tv1->vval.v_float == tv2->vval.v_float; - - case VAR_STRING: - s1 = get_tv_string_buf(tv1, buf1); - s2 = get_tv_string_buf(tv2, buf2); - return (ic ? mb_stricmp(s1, s2) : STRCMP(s1, s2)) == 0; - - case VAR_SPECIAL: - return tv1->vval.v_special == tv2->vval.v_special; - - case VAR_FUNC: - case VAR_PARTIAL: - case VAR_UNKNOWN: - // VAR_UNKNOWN can be the result of an invalid expression, let’s say it does - // not equal anything, not even self. - return false; - } - - assert(false); - return false; -} - -/* - * Locate item with index "n" in list "l" and return it. - * A negative index is counted from the end; -1 is the last item. - * Returns NULL when "n" is out of range. - */ -listitem_T *list_find(list_T *l, long n) -{ - listitem_T *item; - long idx; - - if (l == NULL) - return NULL; - - /* Negative index is relative to the end. */ - if (n < 0) - n = l->lv_len + n; - - /* Check for index out of range. */ - if (n < 0 || n >= l->lv_len) - return NULL; - - /* When there is a cached index may start search from there. */ - if (l->lv_idx_item != NULL) { - if (n < l->lv_idx / 2) { - /* closest to the start of the list */ - item = l->lv_first; - idx = 0; - } else if (n > (l->lv_idx + l->lv_len) / 2) { - /* closest to the end of the list */ - item = l->lv_last; - idx = l->lv_len - 1; - } else { - /* closest to the cached index */ - item = l->lv_idx_item; - idx = l->lv_idx; - } - } else { - if (n < l->lv_len / 2) { - /* closest to the start of the list */ - item = l->lv_first; - idx = 0; - } else { - /* closest to the end of the list */ - item = l->lv_last; - idx = l->lv_len - 1; - } - } - - while (n > idx) { - /* search forward */ - item = item->li_next; - ++idx; - } - while (n < idx) { - /* search backward */ - item = item->li_prev; - --idx; - } - - /* cache the used index */ - l->lv_idx = idx; - l->lv_idx_item = item; - - return item; -} - -/* - * Get list item "l[idx]" as a number. - */ -static long -list_find_nr ( - list_T *l, - long idx, - int *errorp /* set to TRUE when something wrong */ -) -{ - listitem_T *li; - - li = list_find(l, idx); - if (li == NULL) { - if (errorp != NULL) - *errorp = TRUE; - return -1L; - } - return get_tv_number_chk(&li->li_tv, errorp); -} - -/* - * Get list item "l[idx - 1]" as a string. Returns NULL for failure. - */ -char_u *list_find_str(list_T *l, long idx) -{ - listitem_T *li; - - li = list_find(l, idx - 1); - if (li == NULL) { - EMSGN(_(e_listidx), idx); - return NULL; - } - return get_tv_string(&li->li_tv); -} - -/* - * Locate "item" list "l" and return its index. - * Returns -1 when "item" is not in the list. - */ -static long list_idx_of_item(list_T *l, listitem_T *item) -{ - long idx = 0; - listitem_T *li; - - if (l == NULL) - return -1; - idx = 0; - for (li = l->lv_first; li != NULL && li != item; li = li->li_next) - ++idx; - if (li == NULL) - return -1; - return idx; -} - -/* - * Append item "item" to the end of list "l". - */ -void list_append(list_T *l, listitem_T *item) -{ - if (l->lv_last == NULL) { - /* empty list */ - l->lv_first = item; - l->lv_last = item; - item->li_prev = NULL; - } else { - l->lv_last->li_next = item; - item->li_prev = l->lv_last; - l->lv_last = item; - } - ++l->lv_len; - item->li_next = NULL; -} - -/* - * Append typval_T "tv" to the end of list "l". - */ -void list_append_tv(list_T *l, typval_T *tv) -{ - listitem_T *li = listitem_alloc(); - copy_tv(tv, &li->li_tv); - list_append(l, li); -} - -/* - * Add a list to a list. - */ -void list_append_list(list_T *list, list_T *itemlist) -{ - listitem_T *li = listitem_alloc(); - - li->li_tv.v_type = VAR_LIST; - li->li_tv.v_lock = 0; - li->li_tv.vval.v_list = itemlist; - list_append(list, li); - ++itemlist->lv_refcount; -} - -/* - * Add a dictionary to a list. Used by getqflist(). - */ -void list_append_dict(list_T *list, dict_T *dict) -{ - listitem_T *li = listitem_alloc(); - - li->li_tv.v_type = VAR_DICT; - li->li_tv.v_lock = 0; - li->li_tv.vval.v_dict = dict; - list_append(list, li); - ++dict->dv_refcount; -} - -/// Make a copy of "str" and append it as an item to list "l" -/// -/// @param[out] l List to append to. -/// @param[in] str String to append. -/// @param[in] len Length of the appended string. May be negative, in this -/// case string is considered to be usual zero-terminated -/// string. -void list_append_string(list_T *l, const char_u *str, int len) - FUNC_ATTR_NONNULL_ARG(1) -{ - if (str == NULL) { - list_append_allocated_string(l, NULL); - } else { - list_append_allocated_string(l, (len >= 0 - ? xmemdupz((char *) str, len) - : xstrdup((char *) str))); - } -} - -/// Append given string to the list -/// -/// Unlike list_append_string this function does not copy the string. -/// -/// @param[out] l List to append to. -/// @param[in] str String to append. -void list_append_allocated_string(list_T *l, char *const str) - FUNC_ATTR_NONNULL_ARG(1) -{ - listitem_T *li = listitem_alloc(); - - list_append(l, li); - li->li_tv.v_type = VAR_STRING; - li->li_tv.v_lock = 0; - li->li_tv.vval.v_string = (char_u *) str; -} - -/* - * Append "n" to list "l". - */ -void list_append_number(list_T *l, varnumber_T n) -{ - listitem_T *li = listitem_alloc(); - li->li_tv.v_type = VAR_NUMBER; - li->li_tv.v_lock = 0; - li->li_tv.vval.v_number = n; - list_append(l, li); -} - -/* - * Insert typval_T "tv" in list "l" before "item". - * If "item" is NULL append at the end. - */ -void list_insert_tv(list_T *l, typval_T *tv, listitem_T *item) -{ - listitem_T *ni = listitem_alloc(); - - copy_tv(tv, &ni->li_tv); - list_insert(l, ni, item); -} - -void list_insert(list_T *l, listitem_T *ni, listitem_T *item) -{ - if (item == NULL) - /* Append new item at end of list. */ - list_append(l, ni); - else { - /* Insert new item before existing item. */ - ni->li_prev = item->li_prev; - ni->li_next = item; - if (item->li_prev == NULL) { - l->lv_first = ni; - ++l->lv_idx; - } else { - item->li_prev->li_next = ni; - l->lv_idx_item = NULL; - } - item->li_prev = ni; - ++l->lv_len; - } -} - -/* - * Extend "l1" with "l2". - * If "bef" is NULL append at the end, otherwise insert before this item. - */ -static void list_extend(list_T *l1, list_T *l2, listitem_T *bef) -{ - listitem_T *item; - int todo = l2->lv_len; - - /* We also quit the loop when we have inserted the original item count of - * the list, avoid a hang when we extend a list with itself. */ - for (item = l2->lv_first; item != NULL && --todo >= 0; item = item->li_next) { - list_insert_tv(l1, &item->li_tv, bef); - } -} - -/* - * Concatenate lists "l1" and "l2" into a new list, stored in "tv". - * Return FAIL on failure to copy. - */ -static int list_concat(list_T *l1, list_T *l2, typval_T *tv) -{ - list_T *l; - - if (l1 == NULL || l2 == NULL) - return FAIL; - - /* make a copy of the first list. */ - l = list_copy(NULL, l1, false, 0); - if (l == NULL) - return FAIL; - tv->v_type = VAR_LIST; - tv->vval.v_list = l; - - /* append all items from the second list */ - list_extend(l, l2, NULL); - return OK; -} - -/// Make a copy of list -/// -/// @param[in] conv If non-NULL, then all internal strings will be converted. -/// @param[in] orig Original list to copy. -/// @param[in] deep If false, then shallow copy will be done. -/// @param[in] copyID See var_item_copy(). -/// -/// @return Copied list. May be NULL in case original list is NULL or some -/// failure happens. The refcount of the new list is set to 1. -static list_T *list_copy(const vimconv_T *const conv, - list_T *const orig, - const bool deep, - const int copyID) - FUNC_ATTR_WARN_UNUSED_RESULT -{ - listitem_T *item; - listitem_T *ni; - - if (orig == NULL) - return NULL; - - list_T *copy = list_alloc(); - if (copyID != 0) { - /* Do this before adding the items, because one of the items may - * refer back to this list. */ - orig->lv_copyID = copyID; - orig->lv_copylist = copy; - } - for (item = orig->lv_first; item != NULL && !got_int; - item = item->li_next) { - ni = listitem_alloc(); - if (deep) { - if (var_item_copy(conv, &item->li_tv, &ni->li_tv, deep, copyID) == FAIL) { - xfree(ni); - break; - } - } else - copy_tv(&item->li_tv, &ni->li_tv); - list_append(copy, ni); - } - ++copy->lv_refcount; - if (item != NULL) { - list_unref(copy); - copy = NULL; - } - - return copy; -} - -/// Remove items "item" to "item2" from list "l". -/// @warning Does not free the listitem or the value! -void vim_list_remove(list_T *l, listitem_T *item, listitem_T *item2) -{ - // notify watchers - for (listitem_T *ip = item; ip != NULL; ip = ip->li_next) { - --l->lv_len; - list_fix_watch(l, ip); - if (ip == item2) { - break; - } - } - - if (item2->li_next == NULL) { - l->lv_last = item->li_prev; - } else { - item2->li_next->li_prev = item->li_prev; - } - if (item->li_prev == NULL) { - l->lv_first = item2->li_next; - } else { - item->li_prev->li_next = item2->li_next; - } - l->lv_idx_item = NULL; -} - -typedef struct join_S { - char_u *s; - char_u *tofree; -} join_T; - -/// Join list into a string, helper function -/// -/// @param[out] gap Garray where result will be saved. -/// @param[in] l List to join. -/// @param[in] sep Used separator. -/// @param[in] join_gap Garray to keep each list item string. -/// -/// @return OK in case of success, FAIL otherwise. -static int list_join_inner(garray_T *const gap, list_T *const l, - const char *const sep, garray_T *const join_gap) - FUNC_ATTR_NONNULL_ALL -{ - int sumlen = 0; - bool first = true; - listitem_T *item; - - /* Stringify each item in the list. */ - for (item = l->lv_first; item != NULL && !got_int; item = item->li_next) { - char *s; - size_t len; - s = encode_tv2echo(&item->li_tv, &len); - if (s == NULL) { - return FAIL; - } - - sumlen += (int) len; - - join_T *const p = GA_APPEND_VIA_PTR(join_T, join_gap); - p->tofree = p->s = (char_u *) s; - - line_breakcheck(); - } - - /* Allocate result buffer with its total size, avoid re-allocation and - * multiple copy operations. Add 2 for a tailing ']' and NUL. */ - if (join_gap->ga_len >= 2) - sumlen += (int)STRLEN(sep) * (join_gap->ga_len - 1); - ga_grow(gap, sumlen + 2); - - for (int i = 0; i < join_gap->ga_len && !got_int; ++i) { - if (first) { - first = false; - } else { - ga_concat(gap, (const char_u *) sep); - } - const join_T *const p = ((const join_T *)join_gap->ga_data) + i; - - if (p->s != NULL) - ga_concat(gap, p->s); - line_breakcheck(); - } - - return OK; -} - -/// Join list into a string using given separator -/// -/// @param[out] gap Garray where result will be saved. -/// @param[in] l Joined list. -/// @param[in] sep Separator. -/// -/// @return OK in case of success, FAIL otherwise. -static int list_join(garray_T *const gap, list_T *const l, - const char *const sep) - FUNC_ATTR_NONNULL_ALL -{ - if (l->lv_len < 1) { - return OK; - } - - garray_T join_ga; - int retval; - - ga_init(&join_ga, (int)sizeof(join_T), l->lv_len); - retval = list_join_inner(gap, l, sep, &join_ga); - -# define FREE_JOIN_TOFREE(join) xfree((join)->tofree) - GA_DEEP_CLEAR(&join_ga, join_T, FREE_JOIN_TOFREE); - - return retval; -} - /// Get next (unique) copy ID /// /// Used for traversing nested structures e.g. when serializing them or garbage @@ -5805,6 +5008,9 @@ int get_copyID(void) return current_copyID; } +// Used by get_func_tv() +static garray_T funcargs = GA_EMPTY_INIT_VALUE; + /* * Garbage collection for lists and dictionaries. * @@ -5827,19 +5033,22 @@ int get_copyID(void) /// Do garbage collection for lists and dicts. /// +/// @param testing true if called from test_garbagecollect_now(). /// @returns true if some memory was freed. -bool garbage_collect(void) +bool garbage_collect(bool testing) { bool abort = false; #define ABORTING(func) abort = abort || func - // Only do this once. - want_garbage_collect = false; - may_garbage_collect = false; - garbage_collect_at_exit = false; + if (!testing) { + // Only do this once. + want_garbage_collect = false; + may_garbage_collect = false; + garbage_collect_at_exit = false; + } - // We advance by two because we add one for items referenced through - // previous_funccal. + // We advance by two (COPYID_INC) because we add one for items referenced + // through previous_funccal. const int copyID = get_copyID(); // 1. Go through all accessible variables and mark all lists and dicts @@ -5849,6 +5058,7 @@ bool garbage_collect(void) // referenced through previous_funccal. This must be first, because if // the item is referenced elsewhere the funccal must not be freed. for (funccall_T *fc = previous_funccal; fc != NULL; fc = fc->caller) { + fc->fc_copyID = copyID + 1; ABORTING(set_ref_in_ht)(&fc->l_vars.dv_hashtab, copyID + 1, NULL); ABORTING(set_ref_in_ht)(&fc->l_avars.dv_hashtab, copyID + 1, NULL); } @@ -5894,7 +5104,8 @@ bool garbage_collect(void) do { yankreg_T reg; char name = NUL; - reg_iter = op_register_iter(reg_iter, &name, ®); + bool is_unnamed = false; + reg_iter = op_register_iter(reg_iter, &name, ®, &is_unnamed); if (name != NUL) { ABORTING(set_ref_dict)(reg.additional_data, copyID); } @@ -5924,10 +5135,14 @@ bool garbage_collect(void) // function-local variables for (funccall_T *fc = current_funccal; fc != NULL; fc = fc->caller) { + fc->fc_copyID = copyID; ABORTING(set_ref_in_ht)(&fc->l_vars.dv_hashtab, copyID, NULL); ABORTING(set_ref_in_ht)(&fc->l_avars.dv_hashtab, copyID, NULL); } + // named functions (matters for closures) + ABORTING(set_ref_in_functions(copyID)); + // Jobs { TerminalJobData *data; @@ -5946,6 +5161,12 @@ bool garbage_collect(void) }) } + // function call arguments, if v:testing is set. + for (int i = 0; i < funcargs.ga_len; i++) { + ABORTING(set_ref_in_item)(((typval_T **)funcargs.ga_data)[i], + copyID, NULL, NULL); + } + // v: vars ABORTING(set_ref_in_ht)(&vimvarht, copyID, NULL); @@ -6000,7 +5221,7 @@ bool garbage_collect(void) if (did_free_funccal) { // When a funccal was freed some more items might be garbage // collected, so run again. - (void)garbage_collect(); + (void)garbage_collect(testing); } } else if (p_verbose > 0) { verb_msg((char_u *)_( @@ -6012,7 +5233,7 @@ bool garbage_collect(void) /// Free lists and dictionaries that are no longer referenced. /// -/// Note: This function may only be called from garbage_collect(). +/// @note This function may only be called from garbage_collect(). /// /// @param copyID Free lists/dictionaries that don't have this ID. /// @return true, if something was freed. @@ -6025,19 +5246,19 @@ static int free_unref_items(int copyID) // Let all "free" functions know that we are here. This means no // dictionaries, lists, or jobs are to be freed, because we will // do that here. - in_free_unref_items = true; + tv_in_free_unref_items = true; // PASS 1: free the contents of the items. We don't free the items // themselves yet, so that it is possible to decrement refcount counters. // Go through the list of dicts and free items without the copyID. // Don't free dicts that are referenced internally. - for (dict_T *dd = first_dict; dd != NULL; dd = dd->dv_used_next) { + for (dict_T *dd = gc_first_dict; dd != NULL; dd = dd->dv_used_next) { if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)) { // Free the Dictionary and ordinary items it contains, but don't // recurse into Lists and Dictionaries, they will be in the list // of dicts or list of lists. - dict_free_contents(dd); + tv_dict_free_contents(dd); did_free = true; } } @@ -6045,36 +5266,36 @@ static int free_unref_items(int copyID) // Go through the list of lists and free items without the copyID. // But don't free a list that has a watcher (used in a for loop), these // are not referenced anywhere. - for (list_T *ll = first_list; ll != NULL; ll = ll->lv_used_next) { + for (list_T *ll = gc_first_list; ll != NULL; ll = ll->lv_used_next) { if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK) && ll->lv_watch == NULL) { // Free the List and ordinary items it contains, but don't recurse // into Lists and Dictionaries, they will be in the list of dicts // or list of lists. - list_free_contents(ll); + tv_list_free_contents(ll); did_free = true; } } // PASS 2: free the items themselves. - for (dd = first_dict; dd != NULL; dd = dd_next) { + for (dd = gc_first_dict; dd != NULL; dd = dd_next) { dd_next = dd->dv_used_next; if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)) { - dict_free_dict(dd); + tv_dict_free_dict(dd); } } - for (ll = first_list; ll != NULL; ll = ll_next) { + for (ll = gc_first_list; ll != NULL; ll = ll_next) { ll_next = ll->lv_used_next; if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK) && ll->lv_watch == NULL) { // Free the List and ordinary items it contains, but don't recurse // into Lists and Dictionaries, they will be in the list of dicts // or list of lists. - list_free_list(ll); + tv_list_free_list(ll); } } - in_free_unref_items = false; + tv_in_free_unref_items = false; return did_free; } @@ -6097,14 +5318,10 @@ bool set_ref_in_ht(hashtab_T *ht, int copyID, list_stack_T **list_stack) // Mark each item in the hashtab. If the item contains a hashtab // it is added to ht_stack, if it contains a list it is added to // list_stack. - int todo = (int)cur_ht->ht_used; - for (hashitem_T *hi = cur_ht->ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - abort = abort || set_ref_in_item(&HI2DI(hi)->di_tv, copyID, &ht_stack, - list_stack); - } - } + HASHTAB_ITER(cur_ht, hi, { + abort = abort || set_ref_in_item( + &TV_DICT_HI2DI(hi)->di_tv, copyID, &ht_stack, list_stack); + }); } if (ht_stack == NULL) { @@ -6196,21 +5413,10 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, QUEUE *w = NULL; DictWatcher *watcher = NULL; QUEUE_FOREACH(w, &dd->watchers) { - watcher = dictwatcher_node_data(w); + watcher = tv_dict_watcher_node_data(w); set_ref_in_callback(&watcher->callback, copyID, ht_stack, list_stack); } } - if (tv->v_type == VAR_PARTIAL) { - partial_T *pt = tv->vval.v_partial; - int i; - - if (pt != NULL) { - for (i = 0; i < pt->pt_argc; i++) { - abort = abort || set_ref_in_item(&pt->pt_argv[i], copyID, - ht_stack, list_stack); - } - } - } break; } @@ -6240,6 +5446,7 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, // A partial does not have a copyID, because it cannot contain itself. if (pt != NULL) { + abort = set_ref_in_func(pt->pt_name, pt->pt_func, copyID); if (pt->pt_dict != NULL) { typval_T dtv; @@ -6256,6 +5463,8 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, break; } case VAR_FUNC: + abort = set_ref_in_func(tv->vval.v_string, NULL, copyID); + break; case VAR_UNKNOWN: case VAR_SPECIAL: case VAR_FLOAT: @@ -6267,6 +5476,29 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, return abort; } +/// Set "copyID" in all functions available by name. +bool set_ref_in_functions(int copyID) +{ + int todo; + hashitem_T *hi = NULL; + bool abort = false; + ufunc_T *fp; + + todo = (int)func_hashtab.ht_used; + for (hi = func_hashtab.ht_array; todo > 0 && !got_int; hi++) { + if (!HASHITEM_EMPTY(hi)) { + todo--; + fp = HI2UF(hi); + if (!func_name_refcount(fp->uf_name)) { + abort = abort || set_ref_in_func(NULL, fp, copyID); + } + } + } + return abort; +} + + + /// Mark all lists and dicts referenced in given mark /// /// @returns true if setting references failed somehow. @@ -6313,447 +5545,17 @@ static inline bool set_ref_dict(dict_T *dict, int copyID) return false; } -/* - * Allocate an empty header for a dictionary. - */ -dict_T *dict_alloc(void) FUNC_ATTR_NONNULL_RET -{ - dict_T *d = xmalloc(sizeof(dict_T)); - - /* Add the dict to the list of dicts for garbage collection. */ - if (first_dict != NULL) - first_dict->dv_used_prev = d; - d->dv_used_next = first_dict; - d->dv_used_prev = NULL; - first_dict = d; - - hash_init(&d->dv_hashtab); - d->dv_lock = 0; - d->dv_scope = 0; - d->dv_refcount = 0; - d->dv_copyID = 0; - QUEUE_INIT(&d->watchers); - - return d; -} - -/* - * Allocate an empty dict for a return value. - */ -static void rettv_dict_alloc(typval_T *rettv) -{ - dict_T *d = dict_alloc(); - - rettv->vval.v_dict = d; - rettv->v_type = VAR_DICT; - rettv->v_lock = VAR_UNLOCKED; - d->dv_refcount++; -} - -/// Clear all the keys of a Dictionary. "d" remains a valid empty Dictionary. -/// -/// @param d The Dictionary to clear -void dict_clear(dict_T *d) - FUNC_ATTR_NONNULL_ALL -{ - hash_lock(&d->dv_hashtab); - assert(d->dv_hashtab.ht_locked > 0); - - size_t todo = d->dv_hashtab.ht_used; - for (hashitem_T *hi = d->dv_hashtab.ht_array; todo > 0; hi++) { - if (!HASHITEM_EMPTY(hi)) { - dictitem_free(HI2DI(hi)); - hash_remove(&d->dv_hashtab, hi); - todo--; - } - } - - hash_unlock(&d->dv_hashtab); -} - - -/* - * Unreference a Dictionary: decrement the reference count and free it when it - * becomes zero. - */ -void dict_unref(dict_T *d) -{ - if (d != NULL && --d->dv_refcount <= 0) { - dict_free(d); - } -} - -/// Free a Dictionary, including all items it contains. -/// Ignores the reference count. -static void dict_free_contents(dict_T *d) { - int todo; - hashitem_T *hi; - dictitem_T *di; - - - /* Lock the hashtab, we don't want it to resize while freeing items. */ - hash_lock(&d->dv_hashtab); - assert(d->dv_hashtab.ht_locked > 0); - todo = (int)d->dv_hashtab.ht_used; - for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - /* Remove the item before deleting it, just in case there is - * something recursive causing trouble. */ - di = HI2DI(hi); - hash_remove(&d->dv_hashtab, hi); - clear_tv(&di->di_tv); - xfree(di); - --todo; - } - } - - while (!QUEUE_EMPTY(&d->watchers)) { - QUEUE *w = QUEUE_HEAD(&d->watchers); - DictWatcher *watcher = dictwatcher_node_data(w); - dictwatcher_free(watcher); - QUEUE_REMOVE(w); - } - - hash_clear(&d->dv_hashtab); -} - -static void dict_free_dict(dict_T *d) { - // Remove the dict from the list of dicts for garbage collection. - if (d->dv_used_prev == NULL) { - first_dict = d->dv_used_next; - } else { - d->dv_used_prev->dv_used_next = d->dv_used_next; - } - if (d->dv_used_next != NULL) { - d->dv_used_next->dv_used_prev = d->dv_used_prev; - } - - xfree(d); -} - -void dict_free(dict_T *d) { - if (!in_free_unref_items) { - dict_free_contents(d); - dict_free_dict(d); - } -} - -/* - * Allocate a Dictionary item. - * The "key" is copied to the new item. - * Note that the value of the item "di_tv" still needs to be initialized! - */ -dictitem_T *dictitem_alloc(char_u *key) FUNC_ATTR_NONNULL_RET -{ - dictitem_T *di = xmalloc(offsetof(dictitem_T, di_key) + STRLEN(key) + 1); -#ifndef __clang_analyzer__ - STRCPY(di->di_key, key); -#endif - di->di_flags = DI_FLAGS_ALLOC; - return di; -} - -/* - * Make a copy of a Dictionary item. - */ -static dictitem_T *dictitem_copy(dictitem_T *org) FUNC_ATTR_NONNULL_RET -{ - dictitem_T *di = xmalloc(sizeof(dictitem_T) + STRLEN(org->di_key)); - - STRCPY(di->di_key, org->di_key); - di->di_flags = DI_FLAGS_ALLOC; - copy_tv(&org->di_tv, &di->di_tv); - - return di; -} - -/* - * Remove item "item" from Dictionary "dict" and free it. - */ -static void dictitem_remove(dict_T *dict, dictitem_T *item) +static bool set_ref_in_funccal(funccall_T *fc, int copyID) { - hashitem_T *hi; - - hi = hash_find(&dict->dv_hashtab, item->di_key); - if (HASHITEM_EMPTY(hi)) { - EMSG2(_(e_intern2), "dictitem_remove()"); - } else { - hash_remove(&dict->dv_hashtab, hi); - } - dictitem_free(item); -} - -/* - * Free a dict item. Also clears the value. - */ -void dictitem_free(dictitem_T *item) -{ - clear_tv(&item->di_tv); - if (item->di_flags & DI_FLAGS_ALLOC) { - xfree(item); - } -} - -/// Make a copy of dictionary -/// -/// @param[in] conv If non-NULL, then all internal strings will be converted. -/// @param[in] orig Original dictionary to copy. -/// @param[in] deep If false, then shallow copy will be done. -/// @param[in] copyID See var_item_copy(). -/// -/// @return Copied dictionary. May be NULL in case original dictionary is NULL -/// or some failure happens. The refcount of the new dictionary is set -/// to 1. -static dict_T *dict_copy(const vimconv_T *const conv, - dict_T *const orig, - const bool deep, - const int copyID) -{ - dictitem_T *di; - int todo; - hashitem_T *hi; - - if (orig == NULL) - return NULL; - - dict_T *copy = dict_alloc(); - { - if (copyID != 0) { - orig->dv_copyID = copyID; - orig->dv_copydict = copy; - } - todo = (int)orig->dv_hashtab.ht_used; - for (hi = orig->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - - if (conv == NULL || conv->vc_type == CONV_NONE) { - di = dictitem_alloc(hi->hi_key); - } else { - char *const key = (char *) string_convert((vimconv_T *) conv, - hi->hi_key, NULL); - if (key == NULL) { - di = dictitem_alloc(hi->hi_key); - } else { - di = dictitem_alloc((char_u *) key); - xfree(key); - } - } - if (deep) { - if (var_item_copy(conv, &HI2DI(hi)->di_tv, &di->di_tv, deep, - copyID) == FAIL) { - xfree(di); - break; - } - } else - copy_tv(&HI2DI(hi)->di_tv, &di->di_tv); - if (dict_add(copy, di) == FAIL) { - dictitem_free(di); - break; - } - } - } - - ++copy->dv_refcount; - if (todo > 0) { - dict_unref(copy); - copy = NULL; - } - } - - return copy; -} - -/* - * Add item "item" to Dictionary "d". - * Returns FAIL when key already exists. - */ -int dict_add(dict_T *d, dictitem_T *item) -{ - return hash_add(&d->dv_hashtab, item->di_key); -} - -/* - * Add a number or string entry to dictionary "d". - * When "str" is NULL use number "nr", otherwise use "str". - * Returns FAIL when key already exists. - */ -int dict_add_nr_str(dict_T *d, char *key, long nr, char_u *str) -{ - dictitem_T *item; - - item = dictitem_alloc((char_u *)key); - item->di_tv.v_lock = 0; - if (str == NULL) { - item->di_tv.v_type = VAR_NUMBER; - item->di_tv.vval.v_number = nr; - } else { - item->di_tv.v_type = VAR_STRING; - item->di_tv.vval.v_string = vim_strsave(str); - } - if (dict_add(d, item) == FAIL) { - dictitem_free(item); - return FAIL; - } - return OK; -} - -/* - * Add a list entry to dictionary "d". - * Returns FAIL when key already exists. - */ -int dict_add_list(dict_T *d, char *key, list_T *list) -{ - dictitem_T *item = dictitem_alloc((char_u *)key); - - item->di_tv.v_lock = 0; - item->di_tv.v_type = VAR_LIST; - item->di_tv.vval.v_list = list; - if (dict_add(d, item) == FAIL) { - dictitem_free(item); - return FAIL; - } - ++list->lv_refcount; - return OK; -} - -/// Add a dict entry to dictionary "d". -/// Returns FAIL when out of memory and when key already exists. -int dict_add_dict(dict_T *d, char *key, dict_T *dict) -{ - dictitem_T *item = dictitem_alloc((char_u *)key); - - item->di_tv.v_lock = 0; - item->di_tv.v_type = VAR_DICT; - item->di_tv.vval.v_dict = dict; - if (dict_add(d, item) == FAIL) { - dictitem_free(item); - return FAIL; - } - dict->dv_refcount++; - return OK; -} - -/// Set all existing keys in "dict" as read-only. -/// -/// This does not protect against adding new keys to the Dictionary. -/// -/// @param dict The dict whose keys should be frozen -void dict_set_keys_readonly(dict_T *dict) - FUNC_ATTR_NONNULL_ALL -{ - size_t todo = dict->dv_hashtab.ht_used; - for (hashitem_T *hi = dict->dv_hashtab.ht_array; todo > 0 ; hi++) { - if (HASHITEM_EMPTY(hi)) { - continue; - } - todo--; - HI2DI(hi)->di_flags |= DI_FLAGS_RO | DI_FLAGS_FIX; - } -} - -/* - * Get the number of items in a Dictionary. - */ -static long dict_len(dict_T *d) -{ - if (d == NULL) - return 0L; - return (long)d->dv_hashtab.ht_used; -} - -/* - * Find item "key[len]" in Dictionary "d". - * If "len" is negative use strlen(key). - * Returns NULL when not found. - */ -dictitem_T *dict_find(dict_T *d, char_u *key, int len) -{ -#define AKEYLEN 200 - char_u buf[AKEYLEN]; - char_u *akey; - char_u *tofree = NULL; - hashitem_T *hi; - - if (d == NULL) { - return NULL; - } - if (len < 0) { - akey = key; - } else if (len >= AKEYLEN) { - tofree = akey = vim_strnsave(key, len); - } else { - /* Avoid a malloc/free by using buf[]. */ - STRLCPY(buf, key, len + 1); - akey = buf; - } - - hi = hash_find(&d->dv_hashtab, akey); - xfree(tofree); - if (HASHITEM_EMPTY(hi)) - return NULL; - return HI2DI(hi); -} - -/// Get a function from a dictionary -/// @param[out] result The address where a pointer to the wanted callback -/// will be left. -/// @return true/false on success/failure. -static bool get_dict_callback(dict_T *d, char *key, Callback *result) -{ - dictitem_T *di = dict_find(d, (uint8_t *)key, -1); - - if (di == NULL) { - result->type = kCallbackNone; - return true; - } - - if (di->di_tv.v_type != VAR_FUNC && di->di_tv.v_type != VAR_STRING - && di->di_tv.v_type != VAR_PARTIAL) { - EMSG(_("Argument is not a function or function name")); - result->type = kCallbackNone; - return false; - } - - typval_T tv; - copy_tv(&di->di_tv, &tv); - set_selfdict(&tv, d); - bool res = callback_from_typval(result, &tv); - clear_tv(&tv); - return res; -} - -/// Get a string item from a dictionary. -/// -/// @param save whether memory should be allocated for the return value -/// -/// @return the entry or NULL if the entry doesn't exist. -char_u *get_dict_string(dict_T *d, char *key, bool save) -{ - dictitem_T *di; - char_u *s; - - di = dict_find(d, (char_u *)key, -1); - if (di == NULL) { - return NULL; - } - s = get_tv_string(&di->di_tv); - if (save) { - s = vim_strsave(s); - } - return s; -} + bool abort = false; -/// Get a number item from a dictionary. -/// -/// @return the entry or 0 if the entry doesn't exist. -long get_dict_number(dict_T *d, char *key) -{ - dictitem_T *di = dict_find(d, (char_u *)key, -1); - if (di == NULL) { - return 0; + if (fc->fc_copyID != copyID) { + fc->fc_copyID = copyID; + abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL); + abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL); + abort = abort || set_ref_in_func(NULL, fc->func, copyID); } - return get_tv_number(&di->di_tv); + return abort; } /* @@ -6768,7 +5570,7 @@ static int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate) char_u *key = NULL; dictitem_T *item; char_u *start = skipwhite(*arg + 1); - char_u buf[NUMBUFLEN]; + char buf[NUMBUFLEN]; /* * First check if it's not a curly-braces thing: {expr}. @@ -6785,7 +5587,7 @@ static int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate) } if (evaluate) { - d = dict_alloc(); + d = tv_dict_alloc(); } tvkey.v_type = VAR_UNKNOWN; tv.v_type = VAR_UNKNOWN; @@ -6796,38 +5598,39 @@ static int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate) goto failret; if (**arg != ':') { EMSG2(_("E720: Missing colon in Dictionary: %s"), *arg); - clear_tv(&tvkey); + tv_clear(&tvkey); goto failret; } if (evaluate) { - key = get_tv_string_buf_chk(&tvkey, buf); + key = (char_u *)tv_get_string_buf_chk(&tvkey, buf); if (key == NULL) { - // "key" is NULL when get_tv_string_buf_chk() gave an errmsg - clear_tv(&tvkey); + // "key" is NULL when tv_get_string_buf_chk() gave an errmsg + tv_clear(&tvkey); goto failret; } } *arg = skipwhite(*arg + 1); - if (eval1(arg, &tv, evaluate) == FAIL) { /* recursive! */ - if (evaluate) - clear_tv(&tvkey); + if (eval1(arg, &tv, evaluate) == FAIL) { // Recursive! + if (evaluate) { + tv_clear(&tvkey); + } goto failret; } if (evaluate) { - item = dict_find(d, key, -1); + item = tv_dict_find(d, (const char *)key, -1); if (item != NULL) { EMSG2(_("E721: Duplicate key in Dictionary: \"%s\""), key); - clear_tv(&tvkey); - clear_tv(&tv); + tv_clear(&tvkey); + tv_clear(&tv); goto failret; } - item = dictitem_alloc(key); - clear_tv(&tvkey); + item = tv_dict_item_alloc((const char *)key); + tv_clear(&tvkey); item->di_tv = tv; item->di_tv.v_lock = 0; - if (dict_add(d, item) == FAIL) { - dictitem_free(item); + if (tv_dict_add(d, item) == FAIL) { + tv_dict_item_free(item); } } @@ -6844,7 +5647,7 @@ static int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate) EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg); failret: if (evaluate) { - dict_free(d); + tv_dict_free(d); } return FAIL; } @@ -6859,6 +5662,232 @@ failret: return OK; } +/// Get function arguments. +static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, + int *varargs, bool skip) +{ + bool mustend = false; + char_u *arg = *argp; + char_u *p = arg; + int c; + int i; + + if (newargs != NULL) { + ga_init(newargs, (int)sizeof(char_u *), 3); + } + + if (varargs != NULL) { + *varargs = false; + } + + // Isolate the arguments: "arg1, arg2, ...)" + while (*p != endchar) { + if (p[0] == '.' && p[1] == '.' && p[2] == '.') { + if (varargs != NULL) { + *varargs = true; + } + p += 3; + mustend = true; + } else { + arg = p; + while (ASCII_ISALNUM(*p) || *p == '_') { + p++; + } + if (arg == p || isdigit(*arg) + || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0) + || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0)) { + if (!skip) { + EMSG2(_("E125: Illegal argument: %s"), arg); + } + break; + } + if (newargs != NULL) { + ga_grow(newargs, 1); + c = *p; + *p = NUL; + arg = vim_strsave(arg); + if (arg == NULL) { + *p = c; + goto err_ret; + } + + // Check for duplicate argument name. + for (i = 0; i < newargs->ga_len; i++) { + if (STRCMP(((char_u **)(newargs->ga_data))[i], arg) == 0) { + EMSG2(_("E853: Duplicate argument name: %s"), arg); + xfree(arg); + goto err_ret; + } + } + ((char_u **)(newargs->ga_data))[newargs->ga_len] = arg; + newargs->ga_len++; + + *p = c; + } + if (*p == ',') { + p++; + } else { + mustend = true; + } + } + p = skipwhite(p); + if (mustend && *p != endchar) { + if (!skip) { + EMSG2(_(e_invarg2), *argp); + } + break; + } + } + if (*p != endchar) { + goto err_ret; + } + p++; // skip "endchar" + + *argp = p; + return OK; + +err_ret: + if (newargs != NULL) { + ga_clear_strings(newargs); + } + return FAIL; +} + +/// Register function "fp" as using "current_funccal" as its scope. +static void register_closure(ufunc_T *fp) +{ + if (fp->uf_scoped == current_funccal) { + // no change + return; + } + funccal_unref(fp->uf_scoped, fp, false); + fp->uf_scoped = current_funccal; + current_funccal->fc_refcount++; + ga_grow(¤t_funccal->fc_funcs, 1); + ((ufunc_T **)current_funccal->fc_funcs.ga_data) + [current_funccal->fc_funcs.ga_len++] = fp; +} + +/// Parse a lambda expression and get a Funcref from "*arg". +/// +/// @return OK or FAIL. Returns NOTDONE for dict or {expr}. +static int get_lambda_tv(char_u **arg, typval_T *rettv, bool evaluate) +{ + garray_T newargs = GA_EMPTY_INIT_VALUE; + garray_T *pnewargs; + ufunc_T *fp = NULL; + int varargs; + int ret; + char_u *start = skipwhite(*arg + 1); + char_u *s, *e; + static int lambda_no = 0; + int *old_eval_lavars = eval_lavars_used; + int eval_lavars = false; + + // First, check if this is a lambda expression. "->" must exists. + ret = get_function_args(&start, '-', NULL, NULL, true); + if (ret == FAIL || *start != '>') { + return NOTDONE; + } + + // Parse the arguments again. + if (evaluate) { + pnewargs = &newargs; + } else { + pnewargs = NULL; + } + *arg = skipwhite(*arg + 1); + ret = get_function_args(arg, '-', pnewargs, &varargs, false); + if (ret == FAIL || **arg != '>') { + goto errret; + } + + // Set up a flag for checking local variables and arguments. + if (evaluate) { + eval_lavars_used = &eval_lavars; + } + + // Get the start and the end of the expression. + *arg = skipwhite(*arg + 1); + s = *arg; + ret = skip_expr(arg); + if (ret == FAIL) { + goto errret; + } + e = *arg; + *arg = skipwhite(*arg); + if (**arg != '}') { + goto errret; + } + (*arg)++; + + if (evaluate) { + int len, flags = 0; + char_u *p; + char_u name[20]; + partial_T *pt; + garray_T newlines; + + lambda_no++; + snprintf((char *)name, sizeof(name), "<lambda>%d", lambda_no); + + fp = (ufunc_T *)xcalloc(1, sizeof(ufunc_T) + STRLEN(name)); + pt = (partial_T *)xcalloc(1, sizeof(partial_T)); + if (pt == NULL) { + xfree(fp); + goto errret; + } + + ga_init(&newlines, (int)sizeof(char_u *), 1); + ga_grow(&newlines, 1); + + // Add "return " before the expression. + len = 7 + e - s + 1; + p = (char_u *)xmalloc(len); + ((char_u **)(newlines.ga_data))[newlines.ga_len++] = p; + STRCPY(p, "return "); + STRLCPY(p + 7, s, e - s + 1); + + fp->uf_refcount = 1; + STRCPY(fp->uf_name, name); + hash_add(&func_hashtab, UF2HIKEY(fp)); + fp->uf_args = newargs; + fp->uf_lines = newlines; + if (current_funccal != NULL && eval_lavars) { + flags |= FC_CLOSURE; + register_closure(fp); + } else { + fp->uf_scoped = NULL; + } + + fp->uf_tml_count = NULL; + fp->uf_tml_total = NULL; + fp->uf_tml_self = NULL; + fp->uf_profiling = false; + if (prof_def_func()) { + func_do_profile(fp); + } + fp->uf_varargs = true; + fp->uf_flags = flags; + fp->uf_calls = 0; + fp->uf_script_ID = current_SID; + + pt->pt_func = fp; + pt->pt_refcount = 1; + rettv->vval.v_partial = pt; + rettv->v_type = VAR_PARTIAL; + } + + eval_lavars_used = old_eval_lavars; + return OK; + +errret: + ga_clear_strings(&newargs); + xfree(fp); + eval_lavars_used = old_eval_lavars; + return FAIL; +} + /// Convert the string to a floating point number /// /// This uses strtod(). setlocale(LC_NUMERIC, "C") has been used earlier to @@ -6873,6 +5902,19 @@ size_t string2float(const char *const text, float_T *const ret_value) { char *s = NULL; + // MS-Windows does not deal with "inf" and "nan" properly + if (STRNICMP(text, "inf", 3) == 0) { + *ret_value = INFINITY; + return 3; + } + if (STRNICMP(text, "-inf", 3) == 0) { + *ret_value = -INFINITY; + return 4; + } + if (STRNICMP(text, "nan", 3) == 0) { + *ret_value = NAN; + return 3; + } *ret_value = strtod(text, &s); return (size_t) (s - text); } @@ -6893,7 +5935,7 @@ static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate) ++*arg; name = *arg; - len = get_env_len(arg); + len = get_env_len((const char_u **)arg); if (evaluate) { if (len == 0) { @@ -6981,64 +6023,67 @@ char_u *get_expr_name(expand_T *xp, int idx) return get_user_var_name(xp, ++intidx); } - - - /// Find internal function in hash functions /// /// @param[in] name Name of the function. /// /// Returns pointer to the function definition or NULL if not found. -static VimLFuncDef *find_internal_func(const char *const name) +static const VimLFuncDef *find_internal_func(const char *const name) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL { size_t len = strlen(name); return find_internal_func_gperf(name, len); } -/// Check if "name" is a variable of type VAR_FUNC. If so, return the function -/// name it contains, otherwise return "name". -/// If "partialp" is not NULL, and "name" is of type VAR_PARTIAL also set -/// "partialp". -static char_u *deref_func_name( - char_u *name, int *lenp, - partial_T **partialp, bool no_autoload -) +/// Return name of the function corresponding to `name` +/// +/// If `name` points to variable that is either a function or partial then +/// corresponding function name is returned. Otherwise it returns `name` itself. +/// +/// @param[in] name Function name to check. +/// @param[in,out] lenp Location where length of the returned name is stored. +/// Must be set to the length of the `name` argument. +/// @param[out] partialp Location where partial will be stored if found +/// function appears to be a partial. May be NULL if this +/// is not needed. +/// @param[in] no_autoload If true, do not source autoload scripts if function +/// was not found. +/// +/// @return name of the function. +static char_u *deref_func_name(const char *name, int *lenp, + partial_T **const partialp, bool no_autoload) + FUNC_ATTR_NONNULL_ARG(1, 2) { - dictitem_T *v; - int cc; if (partialp != NULL) { *partialp = NULL; } - cc = name[*lenp]; - name[*lenp] = NUL; - v = find_var(name, NULL, no_autoload); - name[*lenp] = cc; + dictitem_T *const v = find_var(name, (size_t)(*lenp), NULL, no_autoload); if (v != NULL && v->di_tv.v_type == VAR_FUNC) { - if (v->di_tv.vval.v_string == NULL) { + if (v->di_tv.vval.v_string == NULL) { // just in case *lenp = 0; - return (char_u *)""; /* just in case */ + return (char_u *)""; } *lenp = (int)STRLEN(v->di_tv.vval.v_string); return v->di_tv.vval.v_string; } if (v != NULL && v->di_tv.v_type == VAR_PARTIAL) { - partial_T *pt = v->di_tv.vval.v_partial; + partial_T *const pt = v->di_tv.vval.v_partial; - if (pt == NULL) { + if (pt == NULL) { // just in case *lenp = 0; - return (char_u *)""; // just in case + return (char_u *)""; } if (partialp != NULL) { *partialp = pt; } - *lenp = (int)STRLEN(pt->pt_name); - return pt->pt_name; + char_u *s = partial_name(pt); + *lenp = (int)STRLEN(s); + return s; } - return name; + return (char_u *)name; } /* @@ -7087,9 +6132,24 @@ get_func_tv ( ret = FAIL; if (ret == OK) { - ret = call_func(name, len, rettv, argcount, argvars, + int i = 0; + + if (get_vim_var_nr(VV_TESTING)) { + // Prepare for calling garbagecollect_for_testing(), need to know + // what variables are used on the call stack. + if (funcargs.ga_itemsize == 0) { + ga_init(&funcargs, (int)sizeof(typval_T *), 50); + } + for (i = 0; i < argcount; i++) { + ga_grow(&funcargs, 1); + ((typval_T **)funcargs.ga_data)[funcargs.ga_len++] = &argvars[i]; + } + } + ret = call_func(name, len, rettv, argcount, argvars, NULL, firstline, lastline, doesrange, evaluate, partial, selfdict); + + funcargs.ga_len -= i; } else if (!aborting()) { if (argcount == MAX_FUNC_ARGS) { emsg_funcname(N_("E740: Too many arguments for function %s"), name); @@ -7098,40 +6158,57 @@ get_func_tv ( } } - while (--argcount >= 0) - clear_tv(&argvars[argcount]); + while (--argcount >= 0) { + tv_clear(&argvars[argcount]); + } *arg = skipwhite(argp); return ret; } -#define ERROR_UNKNOWN 0 -#define ERROR_TOOMANY 1 -#define ERROR_TOOFEW 2 -#define ERROR_SCRIPT 3 -#define ERROR_DICT 4 -#define ERROR_NONE 5 -#define ERROR_OTHER 6 -#define ERROR_BOTH 7 +typedef enum { + ERROR_UNKNOWN = 0, + ERROR_TOOMANY, + ERROR_TOOFEW, + ERROR_SCRIPT, + ERROR_DICT, + ERROR_NONE, + ERROR_OTHER, + ERROR_BOTH, + ERROR_DELETED, +} FnameTransError; + #define FLEN_FIXED 40 -/// In a script change <SID>name() and s:name() to K_SNR 123_name(). -/// Change <SNR>123_name() to K_SNR 123_name(). -/// Use "fname_buf[FLEN_FIXED + 1]" when it fits, otherwise allocate memory -/// (slow). -static char_u * -fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error) { - int llen; +/// In a script transform script-local names into actually used names +/// +/// Transforms "<SID>" and "s:" prefixes to `K_SNR {N}` (e.g. K_SNR "123") and +/// "<SNR>" prefix to `K_SNR`. Uses `fname_buf` buffer that is supposed to have +/// #FLEN_FIXED + 1 length when it fits, otherwise it allocates memory. +/// +/// @param[in] name Name to transform. +/// @param fname_buf Buffer to save resulting function name to, if it fits. +/// Must have at least #FLEN_FIXED + 1 length. +/// @param[out] tofree Location where pointer to an allocated memory is saved +/// in case result does not fit into fname_buf. +/// @param[out] error Location where error type is saved, @see +/// FnameTransError. +/// +/// @return transformed name: either `fname_buf` or a pointer to an allocated +/// memory. +static char_u *fname_trans_sid(const char_u *const name, + char_u *const fname_buf, + char_u **const tofree, int *const error) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ char_u *fname; - int i; - - llen = eval_fname_script(name); + const int llen = eval_fname_script((const char *)name); if (llen > 0) { fname_buf[0] = K_SPECIAL; fname_buf[1] = KS_EXTRA; fname_buf[2] = (int)KE_SNR; - i = 3; - if (eval_fname_sid(name)) { // "<SID>" or "s:" + int i = 3; + if (eval_fname_sid((const char *)name)) { // "<SID>" or "s:" if (current_SID <= 0) { *error = ERROR_SCRIPT; } else { @@ -7154,23 +6231,60 @@ fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error) { } } } else { - fname = name; + fname = (char_u *)name; } return fname; } +/// Mark all lists and dicts referenced through function "name" with "copyID". +/// "list_stack" is used to add lists to be marked. Can be NULL. +/// "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) +{ + ufunc_T *fp = fp_in; + funccall_T *fc; + int error = ERROR_NONE; + char_u fname_buf[FLEN_FIXED + 1]; + char_u *tofree = NULL; + char_u *fname; + bool abort = false; + if (name == NULL && fp_in == NULL) { + return false; + } + + if (fp_in == NULL) { + 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) { + abort = abort || set_ref_in_funccal(fc, copyID); + } + } + xfree(tofree); + return abort; +} + /// Call a function with its resolved parameters +/// +/// "argv_func", when not NULL, can be used to fill in arguments only when the +/// invoked function uses them. It is called like this: +/// new_argcount = argv_func(current_argcount, argv, called_func_argcount) +/// /// Return FAIL when the function can't be called, OK otherwise. /// Also returns OK when an error was encountered while executing the function. int call_func( - char_u *funcname, // name of the function + const char_u *funcname, // name of the function int len, // length of "name" typval_T *rettv, // return value goes here int argcount_in, // number of "argvars" typval_T *argvars_in, // vars for arguments, must have "argcount" // PLUS ONE elements! + ArgvFunc argv_func, // function to fill in argvars linenr_T firstline, // first line of range linenr_T lastline, // last line of range int *doesrange, // return: function handled range @@ -7213,7 +6327,7 @@ call_func( } if (error == ERROR_NONE && partial->pt_argc > 0) { for (argv_clear = 0; argv_clear < partial->pt_argc; argv_clear++) { - copy_tv(&partial->pt_argv[argv_clear], &argv[argv_clear]); + tv_copy(&partial->pt_argv[argv_clear], &argv[argv_clear]); } for (int i = 0; i < argcount_in; i++) { argv[i + argv_clear] = argvars_in[i]; @@ -7237,44 +6351,53 @@ call_func( rettv->vval.v_number = 0; error = ERROR_UNKNOWN; - if (!builtin_function(rfname, -1)) { - /* - * User defined function. - */ - fp = find_func(rfname); + if (!builtin_function((const char *)rfname, -1)) { + // User defined function. + if (partial != NULL && partial->pt_func != NULL) { + fp = partial->pt_func; + } else { + fp = find_func(rfname); + } - /* Trigger FuncUndefined event, may load the function. */ + // Trigger FuncUndefined event, may load the function. if (fp == NULL && apply_autocmds(EVENT_FUNCUNDEFINED, rfname, rfname, TRUE, NULL) && !aborting()) { /* executed an autocommand, search for the function again */ fp = find_func(rfname); } - /* Try loading a package. */ - if (fp == NULL && script_autoload(rfname, TRUE) && !aborting()) { - /* loaded a package, search for the function again */ + // 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(rfname); } - if (fp != NULL) { - if (fp->uf_flags & FC_RANGE) - *doesrange = TRUE; - if (argcount < fp->uf_args.ga_len) + if (fp != NULL && (fp->uf_flags & FC_DELETED)) { + error = ERROR_DELETED; + } else if (fp != NULL) { + if (argv_func != NULL) { + argcount = argv_func(argcount, argvars, fp->uf_args.ga_len); + } + if (fp->uf_flags & FC_RANGE) { + *doesrange = true; + } + if (argcount < fp->uf_args.ga_len) { error = ERROR_TOOFEW; - else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len) + } else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len) { error = ERROR_TOOMANY; - else if ((fp->uf_flags & FC_DICT) && selfdict == NULL) + } else if ((fp->uf_flags & FC_DICT) && selfdict == NULL) { error = ERROR_DICT; - else { + } else { // Call the user function. call_user_func(fp, argcount, argvars, rettv, firstline, lastline, - (fp->uf_flags & FC_DICT) ? selfdict : NULL); + (fp->uf_flags & FC_DICT) ? selfdict : NULL); error = ERROR_NONE; } } } else { // Find the function name in the table, call its implementation. - VimLFuncDef *const fdef = find_internal_func((char *)fname); + const VimLFuncDef *const fdef = find_internal_func((const char *)fname); if (fdef != NULL) { if (argcount < fdef->min_argc) { error = ERROR_TOOFEW; @@ -7311,6 +6434,9 @@ call_func( case ERROR_UNKNOWN: emsg_funcname(N_("E117: Unknown function: %s"), name); break; + case ERROR_DELETED: + emsg_funcname(N_("E933: Function was deleted: %s"), name); + break; case ERROR_TOOMANY: emsg_funcname(e_toomanyarg, name); break; @@ -7330,7 +6456,7 @@ call_func( } while (argv_clear > 0) { - clear_tv(&argv[--argv_clear]); + tv_clear(&argv[--argv_clear]); } xfree(tofree); xfree(name); @@ -7360,11 +6486,13 @@ static void emsg_funcname(char *ermsg, char_u *name) */ static int non_zero_arg(typval_T *argvars) { - return (argvars[0].v_type == VAR_NUMBER - && argvars[0].vval.v_number != 0) - || (argvars[0].v_type == VAR_STRING - && argvars[0].vval.v_string != NULL - && *argvars[0].vval.v_string != NUL); + return ((argvars[0].v_type == VAR_NUMBER + && argvars[0].vval.v_number != 0) + || (argvars[0].v_type == VAR_SPECIAL + && argvars[0].vval.v_special == kSpecialVarTrue) + || (argvars[0].v_type == VAR_STRING + && argvars[0].vval.v_string != NULL + && *argvars[0].vval.v_string != NUL)); } /********************************************* @@ -7372,24 +6500,6 @@ static int non_zero_arg(typval_T *argvars) */ -/* - * Get the float value of "argvars[0]" into "f". - * Returns FAIL when the argument is not a Number or Float. - */ -static inline int get_float_arg(typval_T *argvars, float_T *f) -{ - if (argvars[0].v_type == VAR_FLOAT) { - *f = argvars[0].vval.v_float; - return OK; - } - if (argvars[0].v_type == VAR_NUMBER) { - *f = (float_T)argvars[0].vval.v_number; - return OK; - } - EMSG(_("E808: Number or Float required")); - return FAIL; -} - // Apply a floating point C function on a typval with one float_T. // // Some versions of glibc on i386 have an optimization that makes it harder to @@ -7401,7 +6511,7 @@ static void float_op_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) float_T (*function)(float_T) = (float_T (*)(float_T))fptr; rettv->v_type = VAR_FLOAT; - if (get_float_arg(argvars, &f) == OK) { + if (tv_get_float_chk(argvars, &f)) { rettv->vval.v_float = function(f); } else { rettv->vval.v_float = 0.0; @@ -7419,9 +6529,9 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) } Error err = ERROR_INIT; - Object result = fn(INTERNAL_CALL, args, &err); + Object result = fn(VIML_INTERNAL_CALL, args, &err); - if (err.set) { + if (ERROR_SET(&err)) { nvim_err_writeln(cstr_as_string(err.msg)); goto end; } @@ -7433,6 +6543,7 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) end: api_free_array(args); api_free_object(result); + api_clear_error(&err); } /* @@ -7444,15 +6555,16 @@ static void f_abs(typval_T *argvars, typval_T *rettv, FunPtr fptr) float_op_wrapper(argvars, rettv, (FunPtr)&fabs); } else { varnumber_T n; - int error = FALSE; + bool error = false; - n = get_tv_number_chk(&argvars[0], &error); - if (error) + n = tv_get_number_chk(&argvars[0], &error); + if (error) { rettv->vval.v_number = -1; - else if (n > 0) + } else if (n > 0) { rettv->vval.v_number = n; - else + } else { rettv->vval.v_number = -n; + } } } @@ -7466,13 +6578,13 @@ static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = 1; /* Default: Failed */ if (argvars[0].v_type == VAR_LIST) { if ((l = argvars[0].vval.v_list) != NULL - && !tv_check_lock(l->lv_lock, - (char_u *)N_("add() argument"), true)) { - list_append_tv(l, &argvars[1]); - copy_tv(&argvars[0], rettv); + && !tv_check_lock(l->lv_lock, "add() argument", TV_TRANSLATE)) { + tv_list_append_tv(l, &argvars[1]); + tv_copy(&argvars[0], rettv); } - } else + } else { EMSG(_(e_listreq)); + } } /* @@ -7480,8 +6592,8 @@ static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_and(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL) - & get_tv_number_chk(&argvars[1], NULL); + rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL) + & tv_get_number_chk(&argvars[1], NULL); } @@ -7499,7 +6611,6 @@ static void f_api_info(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr) { long lnum; - char_u *line; list_T *l = NULL; listitem_T *li = NULL; typval_T *tv; @@ -7512,7 +6623,7 @@ static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr) u_sync(TRUE); } - lnum = get_tv_lnum(argvars); + lnum = tv_get_lnum(argvars); if (lnum >= 0 && lnum <= curbuf->b_ml.ml_line_count && u_save(lnum, lnum + 1) == OK) { @@ -7523,21 +6634,23 @@ static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr) li = l->lv_first; } for (;; ) { - if (l == NULL) - tv = &argvars[1]; /* append a string */ - else if (li == NULL) - break; /* end of list */ - else - tv = &li->li_tv; /* append item from list */ - line = get_tv_string_chk(tv); - if (line == NULL) { /* type error */ - rettv->vval.v_number = 1; /* Failed */ + if (l == NULL) { + tv = &argvars[1]; // Append a string. + } else if (li == NULL) { + break; // End of list. + } else { + tv = &li->li_tv; // Append item from list. + } + const char *const line = tv_get_string_chk(tv); + if (line == NULL) { // Type error. + rettv->vval.v_number = 1; // Failed. break; } - ml_append(lnum + added, line, (colnr_T)0, FALSE); - ++added; - if (l == NULL) + ml_append(lnum + added, (char_u *)line, (colnr_T)0, false); + added++; + if (l == NULL) { break; + } li = li->li_next; } @@ -7582,16 +6695,19 @@ static void f_argv(typval_T *argvars, typval_T *rettv, FunPtr fptr) int idx; if (argvars[0].v_type != VAR_UNKNOWN) { - idx = get_tv_number_chk(&argvars[0], NULL); - if (idx >= 0 && idx < ARGCOUNT) - rettv->vval.v_string = vim_strsave(alist_name(&ARGLIST[idx])); - else + idx = (int)tv_get_number_chk(&argvars[0], NULL); + if (idx >= 0 && idx < ARGCOUNT) { + rettv->vval.v_string = (char_u *)xstrdup( + (const char *)alist_name(&ARGLIST[idx])); + } else { rettv->vval.v_string = NULL; + } rettv->v_type = VAR_STRING; } else { - rettv_list_alloc(rettv); - for (idx = 0; idx < ARGCOUNT; ++idx) { - list_append_string(rettv->vval.v_list, alist_name(&ARGLIST[idx]), -1); + tv_list_alloc_ret(rettv); + for (idx = 0; idx < ARGCOUNT; idx++) { + tv_list_append_string(rettv->vval.v_list, + (const char *)alist_name(&ARGLIST[idx]), -1); } } } @@ -7663,10 +6779,10 @@ static void assert_error(garray_T *gap) if (vp->vv_type != VAR_LIST || vimvars[VV_ERRORS].vv_list == NULL) { // Make sure v:errors is a list. - set_vim_var_list(VV_ERRORS, list_alloc()); + set_vim_var_list(VV_ERRORS, tv_list_alloc()); } - list_append_string(vimvars[VV_ERRORS].vv_list, - gap->ga_data, gap->ga_len); + tv_list_append_string(vimvars[VV_ERRORS].vv_list, + (const char *)gap->ga_data, (ptrdiff_t)gap->ga_len); } static void assert_equal_common(typval_T *argvars, assert_type_T atype) @@ -7695,12 +6811,23 @@ static void f_assert_notequal(typval_T *argvars, typval_T *rettv, FunPtr fptr) assert_equal_common(argvars, ASSERT_NOTEQUAL); } +/// "assert_report(msg) +static void f_assert_report(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + garray_T ga; + + prepare_assert_error(&ga); + ga_concat(&ga, (const char_u *)tv_get_string(&argvars[0])); + assert_error(&ga); + ga_clear(&ga); +} + /// "assert_exception(string[, msg])" function static void f_assert_exception(typval_T *argvars, typval_T *rettv, FunPtr fptr) { garray_T ga; - char *error = (char *)get_tv_string_chk(&argvars[0]); + const char *const error = tv_get_string_chk(&argvars[0]); if (vimvars[VV_EXCEPTION].vv_str == NULL) { prepare_assert_error(&ga); ga_concat(&ga, (char_u *)"v:exception is not set"); @@ -7719,22 +6846,22 @@ static void f_assert_exception(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "assert_fails(cmd [, error])" function static void f_assert_fails(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *cmd = get_tv_string_chk(&argvars[0]); + const char *const cmd = tv_get_string_chk(&argvars[0]); garray_T ga; called_emsg = false; suppress_errthrow = true; emsg_silent = true; - do_cmdline_cmd((char *)cmd); + do_cmdline_cmd(cmd); if (!called_emsg) { prepare_assert_error(&ga); - ga_concat(&ga, (char_u *)"command did not fail: "); - ga_concat(&ga, cmd); + ga_concat(&ga, (const char_u *)"command did not fail: "); + ga_concat(&ga, (const char_u *)cmd); assert_error(&ga); ga_clear(&ga); } else if (argvars[1].v_type != VAR_UNKNOWN) { - char_u buf[NUMBUFLEN]; - char *error = (char *)get_tv_string_buf_chk(&argvars[1], buf); + char buf[NUMBUFLEN]; + const char *const error = tv_get_string_buf_chk(&argvars[1], buf); if (error == NULL || strstr((char *)vimvars[VV_ERRMSG].vv_str, error) == NULL) { @@ -7753,14 +6880,39 @@ static void f_assert_fails(typval_T *argvars, typval_T *rettv, FunPtr fptr) set_vim_var_string(VV_ERRMSG, NULL, 0); } +void assert_inrange(typval_T *argvars) +{ + bool error = false; + const varnumber_T lower = tv_get_number_chk(&argvars[0], &error); + const varnumber_T upper = tv_get_number_chk(&argvars[1], &error); + const varnumber_T actual = tv_get_number_chk(&argvars[2], &error); + + if (error) { + return; + } + if (actual < lower || actual > upper) { + garray_T ga; + prepare_assert_error(&ga); + + char msg[55]; + vim_snprintf(msg, sizeof(msg), + "range %" PRIdVARNUMBER " - %" PRIdVARNUMBER ",", + lower, upper); + fill_assert_error(&ga, &argvars[3], (char_u *)msg, NULL, &argvars[2], + ASSERT_INRANGE); + assert_error(&ga); + ga_clear(&ga); + } +} + // Common for assert_true() and assert_false(). static void assert_bool(typval_T *argvars, bool is_true) { - int error = (int)false; + bool error = false; garray_T ga; if ((argvars[0].v_type != VAR_NUMBER - || (get_tv_number_chk(&argvars[0], &error) == 0) == is_true + || (tv_get_number_chk(&argvars[0], &error) == 0) == is_true || error) && (argvars[0].v_type != VAR_SPECIAL || (argvars[0].vval.v_special @@ -7784,14 +6936,15 @@ static void f_assert_false(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void assert_match_common(typval_T *argvars, assert_type_T atype) { - char_u buf1[NUMBUFLEN]; - char_u buf2[NUMBUFLEN]; - char_u *pat = get_tv_string_buf_chk(&argvars[0], buf1); - char_u *text = get_tv_string_buf_chk(&argvars[1], buf2); + char buf1[NUMBUFLEN]; + char buf2[NUMBUFLEN]; + const char *const pat = tv_get_string_buf_chk(&argvars[0], buf1); + const char *const text = tv_get_string_buf_chk(&argvars[1], buf2); if (pat == NULL || text == NULL) { EMSG(_(e_invarg)); - } else if (pattern_match(pat, text, false) != (atype == ASSERT_MATCH)) { + } else if (pattern_match((char_u *)pat, (char_u *)text, false) + != (atype == ASSERT_MATCH)) { garray_T ga; prepare_assert_error(&ga); fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1], atype); @@ -7800,6 +6953,12 @@ static void assert_match_common(typval_T *argvars, assert_type_T atype) } } +/// "assert_inrange(lower, upper[, msg])" function +static void f_assert_inrange(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + assert_inrange(argvars); +} + /// "assert_match(pattern, actual[, msg])" function static void f_assert_match(typval_T *argvars, typval_T *rettv, FunPtr fptr) { @@ -7823,14 +6982,15 @@ static void f_assert_true(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_atan2(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - float_T fx, fy; + float_T fx; + float_T fy; rettv->v_type = VAR_FLOAT; - if (get_float_arg(argvars, &fx) == OK - && get_float_arg(&argvars[1], &fy) == OK) + if (tv_get_float_chk(argvars, &fx) && tv_get_float_chk(&argvars[1], &fy)) { rettv->vval.v_float = atan2(fx, fy); - else + } else { rettv->vval.v_float = 0.0; + } } /* @@ -7954,17 +7114,17 @@ static buf_T *get_buf_tv(typval_T *tv, int curtab_only) */ static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - buf_T *buf; - - (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ - ++emsg_off; - buf = get_buf_tv(&argvars[0], FALSE); rettv->v_type = VAR_STRING; - if (buf != NULL && buf->b_fname != NULL) - rettv->vval.v_string = vim_strsave(buf->b_fname); - else - rettv->vval.v_string = NULL; - --emsg_off; + rettv->vval.v_string = NULL; + if (!tv_check_str_or_nr(&argvars[0])) { + return; + } + emsg_off++; + const buf_T *const buf = get_buf_tv(&argvars[0], false); + emsg_off--; + if (buf != NULL && buf->b_fname != NULL) { + rettv->vval.v_string = (char_u *)xstrdup((char *)buf->b_fname); + } } /* @@ -7972,36 +7132,36 @@ static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - buf_T *buf; - int error = FALSE; - char_u *name; + bool error = false; - (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ - ++emsg_off; - buf = get_buf_tv(&argvars[0], FALSE); - --emsg_off; + rettv->vval.v_number = -1; + if (!tv_check_str_or_nr(&argvars[0])) { + return; + } + emsg_off++; + const buf_T *buf = get_buf_tv(&argvars[0], false); + emsg_off--; - /* If the buffer isn't found and the second argument is not zero create a - * new buffer. */ + // If the buffer isn't found and the second argument is not zero create a + // new buffer. + const char *name; if (buf == NULL && argvars[1].v_type != VAR_UNKNOWN - && get_tv_number_chk(&argvars[1], &error) != 0 + && tv_get_number_chk(&argvars[1], &error) != 0 && !error - && (name = get_tv_string_chk(&argvars[0])) != NULL - && !error) - buf = buflist_new(name, NULL, (linenr_T)1, 0); + && (name = tv_get_string_chk(&argvars[0])) != NULL + && !error) { + buf = buflist_new((char_u *)name, NULL, 1, 0); + } - if (buf != NULL) + if (buf != NULL) { rettv->vval.v_number = buf->b_fnum; - else - rettv->vval.v_number = -1; + } } static void buf_win_common(typval_T *argvars, typval_T *rettv, bool get_nr) { - int error = false; - (void)get_tv_number_chk(&argvars[0], &error); // issue errmsg if type error - if (error) { // the argument has an invalid type + if (!tv_check_str_or_nr(&argvars[0])) { rettv->vval.v_number = -1; return; } @@ -8045,36 +7205,34 @@ static void f_bufwinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_byte2line(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - long boff = 0; - - boff = get_tv_number(&argvars[0]) - 1; /* boff gets -1 on type error */ - if (boff < 0) + long boff = tv_get_number(&argvars[0]) - 1; + if (boff < 0) { rettv->vval.v_number = -1; - else - rettv->vval.v_number = ml_find_line_or_offset(curbuf, - (linenr_T)0, &boff); + } else { + rettv->vval.v_number = (varnumber_T)ml_find_line_or_offset(curbuf, 0, + &boff); + } } static void byteidx(typval_T *argvars, typval_T *rettv, int comp) { - char_u *t; - char_u *str; - long idx; - - str = get_tv_string_chk(&argvars[0]); - idx = get_tv_number_chk(&argvars[1], NULL); + const char *const str = tv_get_string_chk(&argvars[0]); + varnumber_T idx = tv_get_number_chk(&argvars[1], NULL); rettv->vval.v_number = -1; - if (str == NULL || idx < 0) + if (str == NULL || idx < 0) { return; + } - t = str; + const char *t = str; for (; idx > 0; idx--) { - if (*t == NUL) /* EOL reached */ + if (*t == NUL) { // EOL reached. return; - if (enc_utf8 && comp) - t += utf_ptr2len(t); - else - t += (*mb_ptr2len)(t); + } + if (enc_utf8 && comp) { + t += utf_ptr2len((const char_u *)t); + } else { + t += (*mb_ptr2len)((const char_u *)t); + } } rettv->vval.v_number = (varnumber_T)(t - str); } @@ -8113,18 +7271,19 @@ int func_call(char_u *name, typval_T *args, partial_T *partial, /* Make a copy of each argument. This is needed to be able to set * v_lock to VAR_FIXED in the copy without changing the original list. */ - copy_tv(&item->li_tv, &argv[argc++]); + tv_copy(&item->li_tv, &argv[argc++]); } if (item == NULL) { - r = call_func(name, (int)STRLEN(name), rettv, argc, argv, + r = call_func(name, (int)STRLEN(name), rettv, argc, argv, NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy, true, partial, selfdict); } - /* Free the arguments. */ - while (argc > 0) - clear_tv(&argv[--argc]); + // Free the arguments. + while (argc > 0) { + tv_clear(&argv[--argc]); + } return r; } @@ -8132,24 +7291,24 @@ int func_call(char_u *name, typval_T *args, partial_T *partial, /// "call(func, arglist [, dict])" function static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *func; - partial_T *partial = NULL; - dict_T *selfdict = NULL; - if (argvars[1].v_type != VAR_LIST) { EMSG(_(e_listreq)); return; } - if (argvars[1].vval.v_list == NULL) + if (argvars[1].vval.v_list == NULL) { return; + } + char_u *func; + partial_T *partial = NULL; + dict_T *selfdict = NULL; if (argvars[0].v_type == VAR_FUNC) { func = argvars[0].vval.v_string; } else if (argvars[0].v_type == VAR_PARTIAL) { partial = argvars[0].vval.v_partial; - func = partial->pt_name; + func = partial_name(partial); } else { - func = get_tv_string(&argvars[0]); + func = (char_u *)tv_get_string(&argvars[0]); } if (*func == NUL) { return; // type error or empty name @@ -8179,18 +7338,14 @@ static void f_changenr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_char2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - if (has_mbyte) { - int utf8 = 0; - - if (argvars[1].v_type != VAR_UNKNOWN) - utf8 = get_tv_number_chk(&argvars[1], NULL); + if (argvars[1].v_type != VAR_UNKNOWN) { + if (!tv_check_num(&argvars[1])) { + return; + } + } - if (utf8) - rettv->vval.v_number = (*utf_ptr2char)(get_tv_string(&argvars[0])); - else - rettv->vval.v_number = (*mb_ptr2char)(get_tv_string(&argvars[0])); - } else - rettv->vval.v_number = get_tv_string(&argvars[0])[0]; + rettv->vval.v_number = utf_ptr2char( + (const char_u *)tv_get_string(&argvars[0])); } /* @@ -8202,7 +7357,7 @@ static void f_cindent(typval_T *argvars, typval_T *rettv, FunPtr fptr) linenr_T lnum; pos = curwin->w_cursor; - lnum = get_tv_lnum(argvars); + lnum = tv_get_lnum(argvars); if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) { curwin->w_cursor.lnum = lnum; rettv->vval.v_number = get_c_indent(); @@ -8261,8 +7416,6 @@ static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int startcol; - if ((State & INSERT) == 0) { EMSG(_("E785: complete() can only be used in Insert mode")); return; @@ -8278,9 +7431,10 @@ static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - startcol = get_tv_number_chk(&argvars[0], NULL); - if (startcol <= 0) + const colnr_T startcol = tv_get_number_chk(&argvars[0], NULL); + if (startcol <= 0) { return; + } set_completion(startcol - 1, argvars[1].vval.v_list); } @@ -8311,47 +7465,51 @@ static void f_complete_check(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *message; - char_u *buttons = NULL; - char_u buf[NUMBUFLEN]; - char_u buf2[NUMBUFLEN]; + char buf[NUMBUFLEN]; + char buf2[NUMBUFLEN]; + const char *message; + const char *buttons = NULL; int def = 1; int type = VIM_GENERIC; - char_u *typestr; - int error = FALSE; + const char *typestr; + bool error = false; - message = get_tv_string_chk(&argvars[0]); - if (message == NULL) - error = TRUE; + message = tv_get_string_chk(&argvars[0]); + if (message == NULL) { + error = true; + } if (argvars[1].v_type != VAR_UNKNOWN) { - buttons = get_tv_string_buf_chk(&argvars[1], buf); - if (buttons == NULL) - error = TRUE; + buttons = tv_get_string_buf_chk(&argvars[1], buf); + if (buttons == NULL) { + error = true; + } if (argvars[2].v_type != VAR_UNKNOWN) { - def = get_tv_number_chk(&argvars[2], &error); + def = tv_get_number_chk(&argvars[2], &error); if (argvars[3].v_type != VAR_UNKNOWN) { - typestr = get_tv_string_buf_chk(&argvars[3], buf2); - if (typestr == NULL) - error = TRUE; - else { + typestr = tv_get_string_buf_chk(&argvars[3], buf2); + if (typestr == NULL) { + error = true; + } else { switch (TOUPPER_ASC(*typestr)) { - case 'E': type = VIM_ERROR; break; - case 'Q': type = VIM_QUESTION; break; - case 'I': type = VIM_INFO; break; - case 'W': type = VIM_WARNING; break; - case 'G': type = VIM_GENERIC; break; + case 'E': type = VIM_ERROR; break; + case 'Q': type = VIM_QUESTION; break; + case 'I': type = VIM_INFO; break; + case 'W': type = VIM_WARNING; break; + case 'G': type = VIM_GENERIC; break; } } } } } - if (buttons == NULL || *buttons == NUL) - buttons = (char_u *)_("&Ok"); + if (buttons == NULL || *buttons == NUL) { + buttons = _("&Ok"); + } - if (!error) - rettv->vval.v_number = do_dialog(type, NULL, message, buttons, - def, NULL, FALSE); + if (!error) { + rettv->vval.v_number = do_dialog( + type, NULL, (char_u *)message, (char_u *)buttons, def, NULL, false); + } } /* @@ -8378,15 +7536,16 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) if ((l = argvars[0].vval.v_list) != NULL) { li = l->lv_first; if (argvars[2].v_type != VAR_UNKNOWN) { - int error = FALSE; + bool error = false; - ic = get_tv_number_chk(&argvars[2], &error); + ic = tv_get_number_chk(&argvars[2], &error); if (argvars[3].v_type != VAR_UNKNOWN) { - idx = get_tv_number_chk(&argvars[3], &error); + idx = tv_get_number_chk(&argvars[3], &error); if (!error) { - li = list_find(l, idx); - if (li == NULL) + li = tv_list_find(l, idx); + if (li == NULL) { EMSGN(_(e_listidx), idx); + } } } if (error) @@ -8403,20 +7562,22 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) hashitem_T *hi; if ((d = argvars[0].vval.v_dict) != NULL) { - int error = FALSE; + bool error = false; if (argvars[2].v_type != VAR_UNKNOWN) { - ic = get_tv_number_chk(&argvars[2], &error); - if (argvars[3].v_type != VAR_UNKNOWN) + ic = tv_get_number_chk(&argvars[2], &error); + if (argvars[3].v_type != VAR_UNKNOWN) { EMSG(_(e_invarg)); + } } todo = error ? 0 : (int)d->dv_hashtab.ht_used; for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) { if (!HASHITEM_EMPTY(hi)) { - --todo; - if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic, FALSE)) - ++n; + todo--; + if (tv_equal(&TV_DICT_HI2DI(hi)->di_tv, &argvars[1], ic, false)) { + n++; + } } } } @@ -8433,19 +7594,21 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_cscope_connection(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int num = 0; - char_u *dbpath = NULL; - char_u *prepend = NULL; - char_u buf[NUMBUFLEN]; + const char *dbpath = NULL; + const char *prepend = NULL; + char buf[NUMBUFLEN]; if (argvars[0].v_type != VAR_UNKNOWN && argvars[1].v_type != VAR_UNKNOWN) { - num = (int)get_tv_number(&argvars[0]); - dbpath = get_tv_string(&argvars[1]); - if (argvars[2].v_type != VAR_UNKNOWN) - prepend = get_tv_string_buf(&argvars[2], buf); + num = (int)tv_get_number(&argvars[0]); + dbpath = tv_get_string(&argvars[1]); + if (argvars[2].v_type != VAR_UNKNOWN) { + prepend = tv_get_string_buf(&argvars[2], buf); + } } - rettv->vval.v_number = cs_connection(num, dbpath, prepend); + rettv->vval.v_number = cs_connection(num, (char_u *)dbpath, + (char_u *)prepend); } /// "cursor(lnum, col)" function, or @@ -8478,10 +7641,10 @@ static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr) set_curswant = false; } } else { - line = get_tv_lnum(argvars); - col = get_tv_number_chk(&argvars[1], NULL); + line = tv_get_lnum(argvars); + col = (long)tv_get_number_chk(&argvars[1], NULL); if (argvars[2].v_type != VAR_UNKNOWN) { - coladd = get_tv_number_chk(&argvars[2], NULL); + coladd = (long)tv_get_number_chk(&argvars[2], NULL); } } if (line < 0 || col < 0 @@ -8514,10 +7677,11 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int noref = 0; - if (argvars[1].v_type != VAR_UNKNOWN) - noref = get_tv_number_chk(&argvars[1], NULL); + if (argvars[1].v_type != VAR_UNKNOWN) { + noref = tv_get_number_chk(&argvars[1], NULL); + } if (noref < 0 || noref > 1) { - EMSG(_(e_invarg)); + emsgf(_(e_invarg)); } else { var_item_copy(NULL, &argvars[0], rettv, true, (noref == 0 ? get_copyID() @@ -8528,34 +7692,32 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr) // "delete()" function static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u nbuf[NUMBUFLEN]; - char_u *name; - char_u *flags; - rettv->vval.v_number = -1; if (check_restricted() || check_secure()) { return; } - name = get_tv_string(&argvars[0]); + const char *const name = tv_get_string(&argvars[0]); if (name == NULL || *name == NUL) { EMSG(_(e_invarg)); return; } + char nbuf[NUMBUFLEN]; + const char *flags; if (argvars[1].v_type != VAR_UNKNOWN) { - flags = get_tv_string_buf(&argvars[1], nbuf); + flags = tv_get_string_buf(&argvars[1], nbuf); } else { - flags = (char_u *)""; + flags = ""; } if (*flags == NUL) { // delete a file - rettv->vval.v_number = os_remove((char *)name) == 0 ? 0 : -1; - } else if (STRCMP(flags, "d") == 0) { + rettv->vval.v_number = os_remove(name) == 0 ? 0 : -1; + } else if (strcmp(flags, "d") == 0) { // delete an empty directory - rettv->vval.v_number = os_rmdir((char *)name) == 0 ? 0 : -1; - } else if (STRCMP(flags, "rf") == 0) { + rettv->vval.v_number = os_rmdir(name) == 0 ? 0 : -1; + } else if (strcmp(flags, "rf") == 0) { // delete a directory recursively rettv->vval.v_number = delete_recursive(name); } else { @@ -8571,39 +7733,34 @@ static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[0].v_type != VAR_DICT) { - EMSG2(e_invarg2, "dict"); + emsgf(_(e_invarg2), "dict"); return; - } - - if (argvars[1].v_type != VAR_STRING && argvars[1].v_type != VAR_NUMBER) { - EMSG2(e_invarg2, "key"); + } else if (argvars[0].vval.v_dict == NULL) { + const char *const arg_errmsg = _("dictwatcheradd() argument"); + const size_t arg_errmsg_len = strlen(arg_errmsg); + emsgf(_(e_readonlyvar), (int)arg_errmsg_len, arg_errmsg); return; } - if (argvars[2].v_type != VAR_FUNC && argvars[2].v_type != VAR_STRING) { - EMSG2(e_invarg2, "funcref"); + if (argvars[1].v_type != VAR_STRING && argvars[1].v_type != VAR_NUMBER) { + emsgf(_(e_invarg2), "key"); return; } - char *key_pattern = (char *)get_tv_string_chk(argvars + 1); - assert(key_pattern); - const size_t key_len = STRLEN(argvars[1].vval.v_string); - - if (key_len == 0) { - EMSG(_(e_emptykey)); + const char *const key_pattern = tv_get_string_chk(argvars + 1); + if (key_pattern == NULL) { return; } + const size_t key_pattern_len = strlen(key_pattern); Callback callback; if (!callback_from_typval(&callback, &argvars[2])) { + emsgf(_(e_invarg2), "funcref"); return; } - DictWatcher *watcher = xmalloc(sizeof(DictWatcher)); - watcher->key_pattern = xmemdupz(key_pattern, key_len); - watcher->callback = callback; - watcher->busy = false; - QUEUE_INSERT_TAIL(&argvars[0].vval.v_dict->watchers, &watcher->node); + tv_dict_watcher_add(argvars[0].vval.v_dict, key_pattern, key_pattern_len, + callback); } // dictwatcherdel(dict, key, funcref) function @@ -8614,26 +7771,17 @@ static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[0].v_type != VAR_DICT) { - EMSG2(e_invarg2, "dict"); - return; - } - - if (argvars[1].v_type != VAR_STRING && argvars[1].v_type != VAR_NUMBER) { - EMSG2(e_invarg2, "key"); + emsgf(_(e_invarg2), "dict"); return; } if (argvars[2].v_type != VAR_FUNC && argvars[2].v_type != VAR_STRING) { - EMSG2(e_invarg2, "funcref"); + emsgf(_(e_invarg2), "funcref"); return; } - char *key_pattern = (char *)get_tv_string_chk(argvars + 1); - assert(key_pattern); - const size_t key_len = STRLEN(argvars[1].vval.v_string); - - if (key_len == 0) { - EMSG(_(e_emptykey)); + const char *const key_pattern = tv_get_string_chk(argvars + 1); + if (key_pattern == NULL) { return; } @@ -8642,28 +7790,12 @@ static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - dict_T *dict = argvars[0].vval.v_dict; - QUEUE *w = NULL; - DictWatcher *watcher = NULL; - bool matched = false; - QUEUE_FOREACH(w, &dict->watchers) { - watcher = dictwatcher_node_data(w); - if (callback_equal(&watcher->callback, &callback) - && !strcmp(watcher->key_pattern, key_pattern)) { - matched = true; - break; - } - } - - callback_free(&callback); - - if (!matched) { + if (!tv_dict_watcher_remove(argvars[0].vval.v_dict, key_pattern, + strlen(key_pattern), callback)) { EMSG("Couldn't find a watcher matching key and callback"); - return; } - QUEUE_REMOVE(w); - dictwatcher_free(watcher); + callback_free(&callback); } /* @@ -8679,7 +7811,7 @@ static void f_did_filetype(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_diff_filler(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars)); + rettv->vval.v_number = diff_check_fill(curwin, tv_get_lnum(argvars)); } /* @@ -8687,7 +7819,7 @@ static void f_diff_filler(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum = get_tv_lnum(argvars); + linenr_T lnum = tv_get_lnum(argvars); static linenr_T prev_lnum = 0; static int changedtick = 0; static int fnum = 0; @@ -8722,11 +7854,12 @@ static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (hlID == HLF_CHD || hlID == HLF_TXD) { - col = get_tv_number(&argvars[1]) - 1; /* ignore type error in {col} */ - if (col >= change_start && col <= change_end) - hlID = HLF_TXD; /* changed text */ - else - hlID = HLF_CHD; /* changed line */ + col = tv_get_number(&argvars[1]) - 1; // Ignore type error in {col}. + if (col >= change_start && col <= change_end) { + hlID = HLF_TXD; // Changed text. + } else { + hlID = HLF_CHD; // Changed line. + } } rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)hlID; } @@ -8777,10 +7910,11 @@ static void f_empty(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_escape(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u buf[NUMBUFLEN]; + char buf[NUMBUFLEN]; - rettv->vval.v_string = vim_strsave_escaped(get_tv_string(&argvars[0]), - get_tv_string_buf(&argvars[1], buf)); + rettv->vval.v_string = vim_strsave_escaped( + (const char_u *)tv_get_string(&argvars[0]), + (const char_u *)tv_get_string_buf(&argvars[1], buf)); rettv->v_type = VAR_STRING; } @@ -8789,16 +7923,15 @@ static void f_escape(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_eval(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *s; - - s = get_tv_string_chk(&argvars[0]); - if (s != NULL) - s = skipwhite(s); + const char *s = tv_get_string_chk(&argvars[0]); + if (s != NULL) { + s = (const char *)skipwhite((const char_u *)s); + } - char_u *p = s; - if (s == NULL || eval1(&s, rettv, TRUE) == FAIL) { - if (p != NULL && !aborting()) { - EMSG2(_(e_invexpr2), p); + const char *const expr_start = s; + if (s == NULL || eval1((char_u **)&s, rettv, true) == FAIL) { + if (expr_start != NULL && !aborting()) { + EMSG2(_(e_invexpr2), expr_start); } need_clr_eos = FALSE; rettv->v_type = VAR_NUMBER; @@ -8821,91 +7954,92 @@ static void f_eventhandler(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_executable(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *name = get_tv_string(&argvars[0]); + const char *name = tv_get_string(&argvars[0]); // Check in $PATH and also check directly if there is a directory name - rettv->vval.v_number = os_can_exe(name, NULL, true) - || (gettail_dir(name) != name && os_can_exe(name, NULL, false)); + rettv->vval.v_number = ( + os_can_exe((const char_u *)name, NULL, true) + || (gettail_dir(name) != name + && os_can_exe((const char_u *)name, NULL, false))); } -static char_u * get_list_line(int c, void *cookie, int indent) +static char_u *get_list_line(int c, void *cookie, int indent) { - listitem_T **p = (listitem_T **)cookie; - listitem_T *item = *p; - char_u buf[NUMBUFLEN]; - char_u *s; + const listitem_T **const p = (const listitem_T **)cookie; + const listitem_T *item = *p; if (item == NULL) { return NULL; } - s = get_tv_string_buf_chk(&item->li_tv, buf); + char buf[NUMBUFLEN]; + const char *const s = tv_get_string_buf_chk(&item->li_tv, buf); *p = item->li_next; - return s == NULL ? NULL : vim_strsave(s); + return (char_u *)(s == NULL ? NULL : xstrdup(s)); } // "execute(command)" function static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int save_msg_silent = msg_silent; - int save_emsg_silent = emsg_silent; - bool save_emsg_noredir = emsg_noredir; - garray_T *save_capture_ga = capture_ga; + const int save_msg_silent = msg_silent; + const int save_emsg_silent = emsg_silent; + const bool save_emsg_noredir = emsg_noredir; + garray_T *const save_capture_ga = capture_ga; - if (check_secure()) { - return; - } + if (check_secure()) { + return; + } - if (argvars[1].v_type != VAR_UNKNOWN) { - char_u buf[NUMBUFLEN]; - char_u *s = get_tv_string_buf_chk(&argvars[1], buf); + if (argvars[1].v_type != VAR_UNKNOWN) { + char buf[NUMBUFLEN]; + const char *const s = tv_get_string_buf_chk(&argvars[1], buf); - if (s == NULL) { - return; - } - if (STRNCMP(s, "silent", 6) == 0) { - msg_silent++; - } - if (STRCMP(s, "silent!") == 0) { - emsg_silent = true; - emsg_noredir = true; - } - } else { + if (s == NULL) { + return; + } + if (strncmp(s, "silent", 6) == 0) { msg_silent++; } - - garray_T capture_local; - ga_init(&capture_local, (int)sizeof(char), 80); - capture_ga = &capture_local; - - if (argvars[0].v_type != VAR_LIST) { - do_cmdline_cmd((char *)get_tv_string(&argvars[0])); - } else if (argvars[0].vval.v_list != NULL) { - list_T *list = argvars[0].vval.v_list; - list->lv_refcount++; - listitem_T *item = list->lv_first; - do_cmdline(NULL, get_list_line, (void *)&item, - DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT|DOCMD_KEYTYPED); - list->lv_refcount--; + if (strcmp(s, "silent!") == 0) { + emsg_silent = true; + emsg_noredir = true; } - msg_silent = save_msg_silent; - emsg_silent = save_emsg_silent; - emsg_noredir = save_emsg_noredir; + } else { + msg_silent++; + } - ga_append(capture_ga, NUL); - rettv->v_type = VAR_STRING; - rettv->vval.v_string = vim_strsave(capture_ga->ga_data); - ga_clear(capture_ga); + garray_T capture_local; + ga_init(&capture_local, (int)sizeof(char), 80); + capture_ga = &capture_local; - capture_ga = save_capture_ga; + if (argvars[0].v_type != VAR_LIST) { + do_cmdline_cmd(tv_get_string(&argvars[0])); + } else if (argvars[0].vval.v_list != NULL) { + list_T *const list = argvars[0].vval.v_list; + list->lv_refcount++; + listitem_T *const item = list->lv_first; + do_cmdline(NULL, get_list_line, (void *)&item, + DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT|DOCMD_KEYTYPED); + list->lv_refcount--; + } + msg_silent = save_msg_silent; + emsg_silent = save_emsg_silent; + emsg_noredir = save_emsg_noredir; + + ga_append(capture_ga, NUL); + rettv->v_type = VAR_STRING; + rettv->vval.v_string = vim_strsave(capture_ga->ga_data); + ga_clear(capture_ga); + + capture_ga = save_capture_ga; } /// "exepath()" function static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *arg = get_tv_string(&argvars[0]); + const char *arg = tv_get_string(&argvars[0]); char_u *path = NULL; - (void)os_can_exe(arg, &path, true); + (void)os_can_exe((const char_u *)arg, &path, true); rettv->v_type = VAR_STRING; rettv->vval.v_string = path; @@ -8916,53 +8050,55 @@ static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p; - char_u *name; - int n = FALSE; + int n = false; int len = 0; - p = get_tv_string(&argvars[0]); - if (*p == '$') { /* environment variable */ - /* first try "normal" environment variables (fast) */ - if (os_getenv((char *)(p + 1)) != NULL) - n = TRUE; - else { - /* try expanding things like $VIM and ${HOME} */ - p = expand_env_save(p); - if (p != NULL && *p != '$') - n = TRUE; - xfree(p); + const char *p = tv_get_string(&argvars[0]); + if (*p == '$') { // Environment variable. + // First try "normal" environment variables (fast). + if (os_getenv(p + 1) != NULL) { + n = true; + } else { + // Try expanding things like $VIM and ${HOME}. + char_u *const exp = expand_env_save((char_u *)p); + if (exp != NULL && *exp != '$') { + n = true; + } + xfree(exp); + } + } else if (*p == '&' || *p == '+') { // Option. + n = (get_option_tv(&p, NULL, true) == OK); + if (*skipwhite((const char_u *)p) != NUL) { + n = false; // Trailing garbage. } - } else if (*p == '&' || *p == '+') { /* option */ - n = (get_option_tv(&p, NULL, TRUE) == OK); - if (*skipwhite(p) != NUL) - n = FALSE; /* trailing garbage */ - } else if (*p == '*') { /* internal or user defined function */ - n = function_exists(p + 1); + } else if (*p == '*') { // Internal or user defined function. + n = function_exists(p + 1, false); } else if (*p == ':') { n = cmd_exists(p + 1); } else if (*p == '#') { - if (p[1] == '#') + if (p[1] == '#') { n = autocmd_supported(p + 2); - else + } else { n = au_exists(p + 1); - } else { /* internal variable */ - char_u *tofree; + } + } else { // Internal variable. typval_T tv; - /* get_name_len() takes care of expanding curly braces */ - name = p; - len = get_name_len(&p, &tofree, TRUE, FALSE); + // get_name_len() takes care of expanding curly braces + const char *name = p; + char *tofree; + len = get_name_len((const char **)&p, &tofree, true, false); if (len > 0) { if (tofree != NULL) { name = tofree; } n = (get_var_tv(name, len, &tv, NULL, false, true) == OK); if (n) { - /* handle d.key, l[idx], f(expr) */ - n = (handle_subscript(&p, &tv, TRUE, FALSE) == OK); - if (n) - clear_tv(&tv); + // Handle d.key, l[idx], f(expr). + n = (handle_subscript(&p, &tv, true, false) == OK); + if (n) { + tv_clear(&tv); + } } } if (*p != NUL) @@ -8979,32 +8115,31 @@ static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *s; size_t len; char_u *errormsg; int options = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND; expand_T xpc; - int error = FALSE; - char_u *result; + bool error = false; + char_u *result; rettv->v_type = VAR_STRING; if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN - && get_tv_number_chk(&argvars[2], &error) + && tv_get_number_chk(&argvars[2], &error) && !error) { rettv->v_type = VAR_LIST; rettv->vval.v_list = NULL; } - s = get_tv_string(&argvars[0]); + const char *s = tv_get_string(&argvars[0]); if (*s == '%' || *s == '#' || *s == '<') { - ++emsg_off; - result = eval_vars(s, s, &len, NULL, &errormsg, NULL); - --emsg_off; + emsg_off++; + result = eval_vars((char_u *)s, (char_u *)s, &len, NULL, &errormsg, NULL); + emsg_off--; if (rettv->v_type == VAR_LIST) { - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (result != NULL) { - list_append_string(rettv->vval.v_list, result, -1); + tv_list_append_string(rettv->vval.v_list, (const char *)result, -1); } } else rettv->vval.v_string = result; @@ -9012,94 +8147,44 @@ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) /* When the optional second argument is non-zero, don't remove matches * for 'wildignore' and don't put matches for 'suffixes' at the end. */ if (argvars[1].v_type != VAR_UNKNOWN - && get_tv_number_chk(&argvars[1], &error)) + && tv_get_number_chk(&argvars[1], &error)) { options |= WILD_KEEP_ALL; + } if (!error) { ExpandInit(&xpc); xpc.xp_context = EXPAND_FILES; - if (p_wic) + if (p_wic) { options += WILD_ICASE; - if (rettv->v_type == VAR_STRING) - rettv->vval.v_string = ExpandOne(&xpc, s, NULL, - options, WILD_ALL); - else { - rettv_list_alloc(rettv); - ExpandOne(&xpc, s, NULL, options, WILD_ALL_KEEP); + } + if (rettv->v_type == VAR_STRING) { + rettv->vval.v_string = ExpandOne(&xpc, (char_u *)s, NULL, options, + WILD_ALL); + } else { + tv_list_alloc_ret(rettv); + ExpandOne(&xpc, (char_u *)s, NULL, options, WILD_ALL_KEEP); for (int i = 0; i < xpc.xp_numfiles; i++) { - list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1); + tv_list_append_string(rettv->vval.v_list, + (const char *)xpc.xp_files[i], -1); } ExpandCleanup(&xpc); } - } else + } else { rettv->vval.v_string = NULL; + } } } -/* - * Go over all entries in "d2" and add them to "d1". - * When "action" is "error" then a duplicate key is an error. - * When "action" is "force" then a duplicate key is overwritten. - * Otherwise duplicate keys are ignored ("action" is "keep"). - */ -void dict_extend(dict_T *d1, dict_T *d2, char_u *action) -{ - dictitem_T *di1; - hashitem_T *hi2; - int todo; - bool watched = is_watched(d1); - char_u *arg_errmsg = (char_u *)N_("extend() argument"); - - todo = (int)d2->dv_hashtab.ht_used; - for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2) { - if (!HASHITEM_EMPTY(hi2)) { - --todo; - di1 = dict_find(d1, hi2->hi_key, -1); - if (d1->dv_scope != 0) { - /* Disallow replacing a builtin function in l: and g:. - * Check the key to be valid when adding to any - * scope. */ - if (d1->dv_scope == VAR_DEF_SCOPE - && HI2DI(hi2)->di_tv.v_type == VAR_FUNC - && var_check_func_name(hi2->hi_key, - di1 == NULL)) - break; - if (!valid_varname(hi2->hi_key)) - break; - } - if (di1 == NULL) { - di1 = dictitem_copy(HI2DI(hi2)); - if (dict_add(d1, di1) == FAIL) { - dictitem_free(di1); - } - - if (watched) { - dictwatcher_notify(d1, (char *)di1->di_key, &di1->di_tv, NULL); - } - } else if (*action == 'e') { - EMSG2(_("E737: Key already exists: %s"), hi2->hi_key); - break; - } else if (*action == 'f' && HI2DI(hi2) != di1) { - typval_T oldtv; - - if (tv_check_lock(di1->di_tv.v_lock, arg_errmsg, true) - || var_check_ro(di1->di_flags, arg_errmsg, true)) { - break; - } - if (watched) { - copy_tv(&di1->di_tv, &oldtv); - } - - clear_tv(&di1->di_tv); - copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv); - - if (watched) { - dictwatcher_notify(d1, (char *)di1->di_key, &di1->di_tv, &oldtv); - clear_tv(&oldtv); - } - } - } +/// "menu_get(path [, modes])" function +static void f_menu_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + tv_list_alloc_ret(rettv); + int modes = MENU_ALL_MODES; + if (argvars[1].v_type == VAR_STRING) { + const char_u *const strmodes = (char_u *)tv_get_string(&argvars[1]); + modes = get_menu_cmd_modes(strmodes, false, NULL, NULL); } + menu_get((char_u *)tv_get_string(&argvars[0]), modes, rettv->vval.v_list); } /* @@ -9108,27 +8193,33 @@ void dict_extend(dict_T *d1, dict_T *d2, char_u *action) */ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *arg_errmsg = (char_u *)N_("extend() argument"); + const char *const arg_errmsg = N_("extend() argument"); if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST) { - list_T *l1, *l2; - listitem_T *item; long before; - int error = FALSE; - - l1 = argvars[0].vval.v_list; - l2 = argvars[1].vval.v_list; - if (l1 != NULL && !tv_check_lock(l1->lv_lock, arg_errmsg, true) - && l2 != NULL) { + bool error = false; + + list_T *const l1 = argvars[0].vval.v_list; + list_T *const l2 = argvars[1].vval.v_list; + if (l1 == NULL) { + const bool locked = tv_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE); + (void)locked; + assert(locked == true); + } else if (l2 == NULL) { + // Do nothing + tv_copy(&argvars[0], rettv); + } else if (!tv_check_lock(l1->lv_lock, arg_errmsg, TV_TRANSLATE)) { + listitem_T *item; if (argvars[2].v_type != VAR_UNKNOWN) { - before = get_tv_number_chk(&argvars[2], &error); - if (error) - return; /* type error; errmsg already given */ + before = (long)tv_get_number_chk(&argvars[2], &error); + if (error) { + return; // Type error; errmsg already given. + } - if (before == l1->lv_len) + if (before == l1->lv_len) { item = NULL; - else { - item = list_find(l1, before); + } else { + item = tv_list_find(l1, before); if (item == NULL) { EMSGN(_(e_listidx), before); return; @@ -9136,43 +8227,50 @@ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } else item = NULL; - list_extend(l1, l2, item); + tv_list_extend(l1, l2, item); - copy_tv(&argvars[0], rettv); + tv_copy(&argvars[0], rettv); } } else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT) { - dict_T *d1, *d2; - char_u *action; - int i; - - d1 = argvars[0].vval.v_dict; - d2 = argvars[1].vval.v_dict; - if (d1 != NULL && !tv_check_lock(d1->dv_lock, arg_errmsg, true) - && d2 != NULL) { - /* Check the third argument. */ + dict_T *const d1 = argvars[0].vval.v_dict; + dict_T *const d2 = argvars[1].vval.v_dict; + if (d1 == NULL) { + const bool locked = tv_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 (!tv_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) { + const char *action = "force"; + // Check the third argument. if (argvars[2].v_type != VAR_UNKNOWN) { - static char *(av[]) = {"keep", "force", "error"}; + const char *const av[] = { "keep", "force", "error" }; - action = get_tv_string_chk(&argvars[2]); - if (action == NULL) - return; /* type error; errmsg already given */ - for (i = 0; i < 3; ++i) - if (STRCMP(action, av[i]) == 0) + action = tv_get_string_chk(&argvars[2]); + if (action == NULL) { + return; // Type error; error message already given. + } + size_t i; + for (i = 0; i < ARRAY_SIZE(av); i++) { + if (strcmp(action, av[i]) == 0) { break; + } + } if (i == 3) { EMSG2(_(e_invarg2), action); return; } - } else - action = (char_u *)"force"; + } - dict_extend(d1, d2, action); + tv_dict_extend(d1, d2, action); - copy_tv(&argvars[0], rettv); + tv_copy(&argvars[0], rettv); } - } else + } else { EMSG2(_(e_listdictarg), "extend()"); + } } /* @@ -9180,19 +8278,18 @@ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_feedkeys(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *keys, *flags = NULL; - char_u nbuf[NUMBUFLEN]; - - /* This is not allowed in the sandbox. If the commands would still be - * executed in the sandbox it would be OK, but it probably happens later, - * when "sandbox" is no longer set. */ - if (check_secure()) + // This is not allowed in the sandbox. If the commands would still be + // executed in the sandbox it would be OK, but it probably happens later, + // when "sandbox" is no longer set. + if (check_secure()) { return; + } - keys = get_tv_string(&argvars[0]); - + const char *const keys = tv_get_string(&argvars[0]); + char nbuf[NUMBUFLEN]; + const char *flags = NULL; if (argvars[1].v_type != VAR_UNKNOWN) { - flags = get_tv_string_buf(&argvars[1], nbuf); + flags = tv_get_string_buf(&argvars[1], nbuf); } nvim_feedkeys(cstr_as_string((char *)keys), @@ -9202,9 +8299,9 @@ static void f_feedkeys(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "filereadable()" function static void f_filereadable(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p = get_tv_string(&argvars[0]); + const char *const p = tv_get_string(&argvars[0]); rettv->vval.v_number = - (*p && !os_isdir(p) && os_file_is_readable((char*)p)); + (*p && !os_isdir((const char_u *)p) && os_file_is_readable(p)); } /* @@ -9213,60 +8310,60 @@ static void f_filereadable(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_filewritable(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char *filename = (char *)get_tv_string(&argvars[0]); + const char *filename = tv_get_string(&argvars[0]); rettv->vval.v_number = os_file_is_writable(filename); } static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) { - char_u *fname; - char_u *fresult = NULL; - char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path; - char_u *p; - char_u pathbuf[NUMBUFLEN]; + char_u *fresult = NULL; + char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path; int count = 1; - int first = TRUE; - int error = FALSE; + bool first = true; + bool error = false; rettv->vval.v_string = NULL; rettv->v_type = VAR_STRING; - fname = get_tv_string(&argvars[0]); + const char *fname = tv_get_string(&argvars[0]); + char pathbuf[NUMBUFLEN]; if (argvars[1].v_type != VAR_UNKNOWN) { - p = get_tv_string_buf_chk(&argvars[1], pathbuf); - if (p == NULL) - error = TRUE; - else { - if (*p != NUL) - path = p; + const char *p = tv_get_string_buf_chk(&argvars[1], pathbuf); + if (p == NULL) { + error = true; + } else { + if (*p != NUL) { + path = (char_u *)p; + } - if (argvars[2].v_type != VAR_UNKNOWN) - count = get_tv_number_chk(&argvars[2], &error); + if (argvars[2].v_type != VAR_UNKNOWN) { + count = tv_get_number_chk(&argvars[2], &error); + } } } if (count < 0) { - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); } if (*fname != NUL && !error) { do { if (rettv->v_type == VAR_STRING || rettv->v_type == VAR_LIST) xfree(fresult); - fresult = find_file_in_path_option(first ? fname : NULL, - first ? STRLEN(fname) : 0, + fresult = find_file_in_path_option(first ? (char_u *)fname : NULL, + first ? strlen(fname) : 0, 0, first, path, find_what, curbuf->b_ffname, (find_what == FINDFILE_DIR ? (char_u *)"" : curbuf->b_p_sua)); - first = FALSE; - - if (fresult != NULL && rettv->v_type == VAR_LIST) - list_append_string(rettv->vval.v_list, fresult, -1); + first = false; + if (fresult != NULL && rettv->v_type == VAR_LIST) { + tv_list_append_string(rettv->vval.v_list, (const char *)fresult, -1); + } } while ((rettv->v_type == VAR_LIST || --count > 0) && fresult != NULL); } @@ -9280,8 +8377,7 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) */ static void filter_map(typval_T *argvars, typval_T *rettv, int map) { - char_u buf[NUMBUFLEN]; - char_u *expr; + typval_T *expr; listitem_T *li, *nli; list_T *l = NULL; dictitem_T *di; @@ -9292,20 +8388,21 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map) typval_T save_key; int rem = false; int todo; - char_u *ermsg = (char_u *)(map ? "map()" : "filter()"); - char_u *arg_errmsg = (char_u *)(map ? N_("map() argument") - : N_("filter() argument")); + char_u *ermsg = (char_u *)(map ? "map()" : "filter()"); + const char *const arg_errmsg = (map + ? N_("map() argument") + : N_("filter() argument")); int save_did_emsg; int idx = 0; if (argvars[0].v_type == VAR_LIST) { if ((l = argvars[0].vval.v_list) == NULL - || (!map && tv_check_lock(l->lv_lock, arg_errmsg, true))) { + || (!map && tv_check_lock(l->lv_lock, arg_errmsg, TV_TRANSLATE))) { return; } } else if (argvars[0].v_type == VAR_DICT) { if ((d = argvars[0].vval.v_dict) == NULL - || (!map && tv_check_lock(d->dv_lock, arg_errmsg, true))) { + || (!map && tv_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE))) { return; } } else { @@ -9313,16 +8410,15 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map) return; } - expr = get_tv_string_buf_chk(&argvars[1], buf); - /* On type errors, the preceding call has already displayed an error - * message. Avoid a misleading error message for an empty string that - * was not passed as argument. */ - if (expr != NULL) { + expr = &argvars[1]; + // On type errors, the preceding call has already displayed an error + // message. Avoid a misleading error message for an empty string that + // was not passed as argument. + if (expr->v_type != VAR_UNKNOWN) { prepare_vimvar(VV_VAL, &save_val); - expr = skipwhite(expr); - /* We reset "did_emsg" to be able to detect whether an error - * occurred during evaluation of the expression. */ + // We reset "did_emsg" to be able to detect whether an error + // occurred during evaluation of the expression. save_did_emsg = did_emsg; did_emsg = FALSE; @@ -9337,24 +8433,25 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map) if (!HASHITEM_EMPTY(hi)) { --todo; - di = HI2DI(hi); + di = TV_DICT_HI2DI(hi); if (map - && (tv_check_lock(di->di_tv.v_lock, arg_errmsg, true) - || var_check_ro(di->di_flags, arg_errmsg, true))) { + && (tv_check_lock(di->di_tv.v_lock, arg_errmsg, TV_TRANSLATE) + || var_check_ro(di->di_flags, arg_errmsg, TV_TRANSLATE))) { break; } vimvars[VV_KEY].vv_str = vim_strsave(di->di_key); int r = filter_map_one(&di->di_tv, expr, map, &rem); - clear_tv(&vimvars[VV_KEY].vv_tv); - if (r == FAIL || did_emsg) + tv_clear(&vimvars[VV_KEY].vv_tv); + if (r == FAIL || did_emsg) { break; + } if (!map && rem) { - if (var_check_fixed(di->di_flags, arg_errmsg, true) - || var_check_ro(di->di_flags, arg_errmsg, true)) { + if (var_check_fixed(di->di_flags, arg_errmsg, TV_TRANSLATE) + || var_check_ro(di->di_flags, arg_errmsg, TV_TRANSLATE)) { break; } - dictitem_remove(d, di); + tv_dict_item_remove(d, di); } } } @@ -9363,7 +8460,8 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map) vimvars[VV_KEY].vv_type = VAR_NUMBER; for (li = l->lv_first; li != NULL; li = nli) { - if (map && tv_check_lock(li->li_tv.v_lock, arg_errmsg, true)) { + if (map + && tv_check_lock(li->li_tv.v_lock, arg_errmsg, TV_TRANSLATE)) { break; } nli = li->li_next; @@ -9371,9 +8469,10 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map) if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL || did_emsg) break; - if (!map && rem) - listitem_remove(l, li); - ++idx; + if (!map && rem) { + tv_list_item_remove(l, li); + } + idx++; } } @@ -9383,43 +8482,69 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map) did_emsg |= save_did_emsg; } - copy_tv(&argvars[0], rettv); + tv_copy(&argvars[0], rettv); } -static int filter_map_one(typval_T *tv, char_u *expr, int map, int *remp) +static int filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp) { typval_T rettv; - char_u *s; + typval_T argv[3]; int retval = FAIL; + int dummy; - copy_tv(tv, &vimvars[VV_VAL].vv_tv); - s = expr; - if (eval1(&s, &rettv, TRUE) == FAIL) - goto theend; - if (*s != NUL) { /* check for trailing chars after expr */ - EMSG2(_(e_invexpr2), s); - clear_tv(&rettv); - goto theend; + tv_copy(tv, &vimvars[VV_VAL].vv_tv); + argv[0] = vimvars[VV_KEY].vv_tv; + argv[1] = vimvars[VV_VAL].vv_tv; + if (expr->v_type == VAR_FUNC) { + const char_u *const s = expr->vval.v_string; + if (call_func(s, (int)STRLEN(s), &rettv, 2, argv, NULL, + 0L, 0L, &dummy, true, NULL, NULL) == FAIL) { + goto theend; + } + } else if (expr->v_type == VAR_PARTIAL) { + partial_T *partial = expr->vval.v_partial; + + const char_u *const s = partial_name(partial); + if (call_func(s, (int)STRLEN(s), &rettv, 2, argv, NULL, + 0L, 0L, &dummy, true, partial, NULL) == FAIL) { + goto theend; + } + } else { + char buf[NUMBUFLEN]; + const char *s = tv_get_string_buf_chk(expr, buf); + if (s == NULL) { + goto theend; + } + s = (const char *)skipwhite((const char_u *)s); + if (eval1((char_u **)&s, &rettv, true) == FAIL) { + goto theend; + } + + if (*s != NUL) { // check for trailing chars after expr + emsgf(_(e_invexpr2), s); + goto theend; + } } if (map) { - /* map(): replace the list item value */ - clear_tv(tv); + // map(): replace the list item value. + tv_clear(tv); rettv.v_lock = 0; *tv = rettv; } else { - int error = FALSE; - - /* filter(): when expr is zero remove the item */ - *remp = (get_tv_number_chk(&rettv, &error) == 0); - clear_tv(&rettv); - /* On type error, nothing has been removed; return FAIL to stop the - * loop. The error message was given by get_tv_number_chk(). */ - if (error) + bool error = false; + + // filter(): when expr is zero remove the item + *remp = (tv_get_number_chk(&rettv, &error) == 0); + tv_clear(&rettv); + // On type error, nothing has been removed; return FAIL to stop the + // loop. The error message was given by tv_get_number_chk(). + if (error) { goto theend; + } } retval = OK; theend: - clear_tv(&vimvars[VV_VAL].vv_tv); + tv_clear(&vimvars[VV_VAL].vv_tv); return retval; } @@ -9454,13 +8579,14 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { float_T f; - if (get_float_arg(argvars, &f) == OK) { - if (f < -0x7fffffff) - rettv->vval.v_number = -0x7fffffff; - else if (f > 0x7fffffff) - rettv->vval.v_number = 0x7fffffff; - else + if (tv_get_float_chk(argvars, &f)) { + if (f <= -VARNUMBER_MAX + DBL_EPSILON) { + rettv->vval.v_number = -VARNUMBER_MAX; + } else if (f >= VARNUMBER_MAX - DBL_EPSILON) { + rettv->vval.v_number = VARNUMBER_MAX; + } else { rettv->vval.v_number = (varnumber_T)f; + } } } @@ -9469,14 +8595,15 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - float_T fx, fy; + float_T fx; + float_T fy; rettv->v_type = VAR_FLOAT; - if (get_float_arg(argvars, &fx) == OK - && get_float_arg(&argvars[1], &fy) == OK) + if (tv_get_float_chk(argvars, &fx) && tv_get_float_chk(&argvars[1], &fy)) { rettv->vval.v_float = fmod(fx, fy); - else + } else { rettv->vval.v_float = 0.0; + } } /* @@ -9484,8 +8611,8 @@ static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_fnameescape(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_string = vim_strsave_fnameescape( - get_tv_string(&argvars[0]), FALSE); + rettv->vval.v_string = (char_u *)vim_strsave_fnameescape( + tv_get_string(&argvars[0]), false); rettv->v_type = VAR_STRING; } @@ -9494,27 +8621,26 @@ static void f_fnameescape(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *fname; - char_u *mods; - size_t usedlen = 0; + char_u *fbuf = NULL; size_t len; - char_u *fbuf = NULL; - char_u buf[NUMBUFLEN]; - - fname = get_tv_string_chk(&argvars[0]); - mods = get_tv_string_buf_chk(&argvars[1], buf); - if (fname == NULL || mods == NULL) + char buf[NUMBUFLEN]; + const char *fname = tv_get_string_chk(&argvars[0]); + const char *const mods = tv_get_string_buf_chk(&argvars[1], buf); + if (fname == NULL || mods == NULL) { fname = NULL; - else { - len = STRLEN(fname); - (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len); + } else { + len = strlen(fname); + size_t usedlen = 0; + (void)modify_fname((char_u *)mods, &usedlen, (char_u **)&fname, &fbuf, + &len); } rettv->v_type = VAR_STRING; - if (fname == NULL) + if (fname == NULL) { rettv->vval.v_string = NULL; - else - rettv->vval.v_string = vim_strnsave(fname, len); + } else { + rettv->vval.v_string = (char_u *)xmemdupz(fname, len); + } xfree(fbuf); } @@ -9524,16 +8650,16 @@ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void foldclosed_both(typval_T *argvars, typval_T *rettv, int end) { - linenr_T lnum; - linenr_T first, last; - - lnum = get_tv_lnum(argvars); + const linenr_T lnum = tv_get_lnum(argvars); if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) { - if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL)) { - if (end) + linenr_T first; + linenr_T last; + if (hasFoldingWin(curwin, lnum, &first, &last, false, NULL)) { + if (end) { rettv->vval.v_number = (varnumber_T)last; - else + } else { rettv->vval.v_number = (varnumber_T)first; + } return; } } @@ -9561,11 +8687,10 @@ static void f_foldclosedend(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; - - lnum = get_tv_lnum(argvars); - if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) + const linenr_T lnum = tv_get_lnum(argvars); + if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) { rettv->vval.v_number = foldLevel(lnum); + } } /* @@ -9573,24 +8698,28 @@ static void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; + linenr_T foldstart; + linenr_T foldend; + char_u *dashes; + linenr_T lnum; char_u *s; char_u *r; - int len; + int len; char *txt; rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - if ((linenr_T)vimvars[VV_FOLDSTART].vv_nr > 0 - && (linenr_T)vimvars[VV_FOLDEND].vv_nr - <= curbuf->b_ml.ml_line_count - && vimvars[VV_FOLDDASHES].vv_str != NULL) { + + foldstart = (linenr_T)get_vim_var_nr(VV_FOLDSTART); + foldend = (linenr_T)get_vim_var_nr(VV_FOLDEND); + dashes = get_vim_var_str(VV_FOLDDASHES); + if (foldstart > 0 && foldend <= curbuf->b_ml.ml_line_count + && dashes != NULL) { /* Find first non-empty line in the fold. */ - lnum = (linenr_T)vimvars[VV_FOLDSTART].vv_nr; - while (lnum < (linenr_T)vimvars[VV_FOLDEND].vv_nr) { - if (!linewhite(lnum)) + for (lnum = foldstart; lnum < foldend; ++lnum) { + if (!linewhite(lnum)) { break; - ++lnum; + } } /* Find interesting text in this line. */ @@ -9598,21 +8727,19 @@ static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr) /* skip C comment-start */ if (s[0] == '/' && (s[1] == '*' || s[1] == '/')) { s = skipwhite(s + 2); - if (*skipwhite(s) == NUL - && lnum + 1 < (linenr_T)vimvars[VV_FOLDEND].vv_nr) { + if (*skipwhite(s) == NUL && lnum + 1 < foldend) { s = skipwhite(ml_get(lnum + 1)); if (*s == '*') s = skipwhite(s + 1); } } - txt = _("+-%s%3ld lines: "); + unsigned long count = (unsigned long)(foldend - foldstart + 1); + txt = ngettext("+-%s%3ld line: ", "+-%s%3ld lines: ", count); r = xmalloc(STRLEN(txt) - + STRLEN(vimvars[VV_FOLDDASHES].vv_str) // for %s - + 20 // for %3ld - + STRLEN(s)); // concatenated - sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].vv_str, - (long)((linenr_T)vimvars[VV_FOLDEND].vv_nr - - (linenr_T)vimvars[VV_FOLDSTART].vv_nr + 1)); + + STRLEN(dashes) // for %s + + 20 // for %3ld + + STRLEN(s)); // concatenated + sprintf((char *)r, txt, dashes, count); len = (int)STRLEN(r); STRCAT(r, s); /* remove 'foldmarker' and 'commentstring' */ @@ -9626,24 +8753,24 @@ static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; char_u *text; - char_u buf[51]; + char_u buf[FOLD_TEXT_LEN]; foldinfo_T foldinfo; int fold_count; rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - lnum = get_tv_lnum(argvars); - /* treat illegal types and illegal string values for {lnum} the same */ - if (lnum < 0) + linenr_T lnum = tv_get_lnum(argvars); + // Treat illegal types and illegal string values for {lnum} the same. + if (lnum < 0) { lnum = 0; + } fold_count = foldedCount(curwin, lnum, &foldinfo); if (fold_count > 0) { - text = get_foldtext(curwin, lnum, lnum + fold_count - 1, - &foldinfo, buf); - if (text == buf) + text = get_foldtext(curwin, lnum, lnum + fold_count - 1, &foldinfo, buf); + if (text == buf) { text = vim_strsave(text); + } rettv->vval.v_string = text; } } @@ -9655,15 +8782,14 @@ static void f_foreground(typval_T *argvars, typval_T *rettv, FunPtr fptr) { } -/* - * "function()" function - */ -static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void common_function(typval_T *argvars, typval_T *rettv, + bool is_funcref, FunPtr fptr) { char_u *s; char_u *name; bool use_string = false; partial_T *arg_pt = NULL; + char_u *trans_name = NULL; if (argvars[0].v_type == VAR_FUNC) { // function(MyFunc, [arg], dict) @@ -9672,18 +8798,31 @@ static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr) && argvars[0].vval.v_partial != NULL) { // function(dict.MyFunc, [arg]) arg_pt = argvars[0].vval.v_partial; - s = arg_pt->pt_name; + s = partial_name(arg_pt); } else { // function('MyFunc', [arg], dict) - s = get_tv_string(&argvars[0]); + s = (char_u *)tv_get_string(&argvars[0]); use_string = true; } - if (s == NULL || *s == NUL || (use_string && ascii_isdigit(*s))) { - EMSG2(_(e_invarg2), s); - } else if (use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL - && !function_exists(s)) { + if ((use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL) || is_funcref) { + name = s; + trans_name = trans_function_name(&name, false, + TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD + | TFN_NO_DEREF, NULL, NULL); + if (*name != NUL) { + s = NULL; + } + } + if (s == NULL || *s == NUL || (use_string && ascii_isdigit(*s)) + || (is_funcref && trans_name == NULL)) { + emsgf(_(e_invarg2), (use_string + ? tv_get_string(&argvars[0]) + : (const char *)s)); // Don't check an autoload name for existence here. + } else if (trans_name != NULL + && (is_funcref ? find_func(trans_name) == NULL + : !translated_function_exists((const char *)trans_name))) { EMSG2(_("E700: Unknown function: %s"), s); } else { int dict_idx = 0; @@ -9724,7 +8863,7 @@ static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[dict_idx].v_type != VAR_DICT) { EMSG(_("E922: expected a dict")); xfree(name); - return; + goto theend; } if (argvars[dict_idx].vval.v_dict == NULL) { dict_idx = 0; @@ -9735,7 +8874,7 @@ static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr) EMSG(_("E923: Second argument of function() must be " "a list or a dict")); xfree(name); - return; + goto theend; } list = argvars[arg_idx].vval.v_list; if (list == NULL || list->lv_len == 0) { @@ -9743,61 +8882,64 @@ static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } } - if (dict_idx > 0 || arg_idx > 0 || arg_pt != NULL) { - partial_T *pt = (partial_T *)xcalloc(1, sizeof(partial_T)); + if (dict_idx > 0 || arg_idx > 0 || arg_pt != NULL || is_funcref) { + partial_T *const pt = xcalloc(1, sizeof(*pt)); // result is a VAR_PARTIAL - if (pt != NULL) { - if (arg_idx > 0 || (arg_pt != NULL && arg_pt->pt_argc > 0)) { - listitem_T *li; - int i = 0; - int arg_len = 0; - int lv_len = 0; - - if (arg_pt != NULL) { - arg_len = arg_pt->pt_argc; - } - if (list != NULL) { - lv_len = list->lv_len; - } - pt->pt_argc = arg_len + lv_len; - pt->pt_argv = (typval_T *)xmalloc(sizeof(typval_T) * pt->pt_argc); - if (pt->pt_argv == NULL) { - xfree(pt); - xfree(name); - return; - } else { - for (i = 0; i < arg_len; i++) { - copy_tv(&arg_pt->pt_argv[i], &pt->pt_argv[i]); - } - if (lv_len > 0) { - for (li = list->lv_first; li != NULL; li = li->li_next) { - copy_tv(&li->li_tv, &pt->pt_argv[i++]); - } - } + if (arg_idx > 0 || (arg_pt != NULL && arg_pt->pt_argc > 0)) { + const int arg_len = (arg_pt == NULL ? 0 : arg_pt->pt_argc); + const int lv_len = (list == NULL ? 0 : list->lv_len); + + pt->pt_argc = arg_len + lv_len; + pt->pt_argv = xmalloc(sizeof(pt->pt_argv[0]) * pt->pt_argc); + if (pt->pt_argv == NULL) { + xfree(pt); + xfree(name); + goto theend; + } + int i = 0; + for (; i < arg_len; i++) { + tv_copy(&arg_pt->pt_argv[i], &pt->pt_argv[i]); + } + if (lv_len > 0) { + for (listitem_T *li = list->lv_first; + li != NULL; + li = li->li_next) { + tv_copy(&li->li_tv, &pt->pt_argv[i++]); } } + } - // For "function(dict.func, [], dict)" and "func" is a partial - // use "dict". That is backwards compatible. - if (dict_idx > 0) { - // The dict is bound explicitly, pt_auto is false - pt->pt_dict = argvars[dict_idx].vval.v_dict; + // For "function(dict.func, [], dict)" and "func" is a partial + // use "dict". That is backwards compatible. + if (dict_idx > 0) { + // The dict is bound explicitly, pt_auto is false + pt->pt_dict = argvars[dict_idx].vval.v_dict; + (pt->pt_dict->dv_refcount)++; + } else if (arg_pt != NULL) { + // If the dict was bound automatically the result is also + // bound automatically. + pt->pt_dict = arg_pt->pt_dict; + pt->pt_auto = arg_pt->pt_auto; + if (pt->pt_dict != NULL) { (pt->pt_dict->dv_refcount)++; - } else if (arg_pt != NULL) { - // If the dict was bound automatically the result is also - // bound automatically. - pt->pt_dict = arg_pt->pt_dict; - pt->pt_auto = arg_pt->pt_auto; - if (pt->pt_dict != NULL) { - (pt->pt_dict->dv_refcount)++; - } } + } - pt->pt_refcount = 1; + pt->pt_refcount = 1; + if (arg_pt != NULL && arg_pt->pt_func != NULL) { + pt->pt_func = arg_pt->pt_func; + func_ptr_ref(pt->pt_func); + xfree(name); + } else if (is_funcref) { + pt->pt_func = find_func(trans_name); + func_ptr_ref(pt->pt_func); + xfree(name); + } else { pt->pt_name = name; - func_ref(pt->pt_name); + func_ref(name); } + rettv->v_type = VAR_PARTIAL; rettv->vval.v_partial = pt; } else { @@ -9807,17 +8949,30 @@ static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr) func_ref(name); } } +theend: + xfree(trans_name); +} + +static void f_funcref(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + common_function(argvars, rettv, true, fptr); +} + +static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + common_function(argvars, rettv, false, fptr); } /// "garbagecollect()" function static void f_garbagecollect(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - /* This is postponed until we are back at the toplevel, because we may be - * using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]". */ - want_garbage_collect = TRUE; + // This is postponed until we are back at the toplevel, because we may be + // using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]". + want_garbage_collect = true; - if (argvars[0].v_type != VAR_UNKNOWN && get_tv_number(&argvars[0]) == 1) - garbage_collect_at_exit = TRUE; + if (argvars[0].v_type != VAR_UNKNOWN && tv_get_number(&argvars[0]) == 1) { + garbage_collect_at_exit = true; + } } /* @@ -9833,20 +8988,21 @@ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type == VAR_LIST) { if ((l = argvars[0].vval.v_list) != NULL) { - int error = FALSE; + bool error = false; - li = list_find(l, get_tv_number_chk(&argvars[1], &error)); - if (!error && li != NULL) + li = tv_list_find(l, tv_get_number_chk(&argvars[1], &error)); + if (!error && li != NULL) { tv = &li->li_tv; + } } } else if (argvars[0].v_type == VAR_DICT) { if ((d = argvars[0].vval.v_dict) != NULL) { - di = dict_find(d, get_tv_string(&argvars[1]), -1); - if (di != NULL) + di = tv_dict_find(d, tv_get_string(&argvars[1]), -1); + if (di != NULL) { tv = &di->di_tv; + } } - } else if (argvars[0].v_type == VAR_PARTIAL - || argvars[0].v_type == VAR_FUNC) { + } else if (tv_is_func(argvars[0])) { partial_T *pt; partial_T fref_pt; @@ -9859,26 +9015,27 @@ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (pt != NULL) { - char_u *what = get_tv_string(&argvars[1]); + const char *const what = tv_get_string(&argvars[1]); - if (STRCMP(what, "func") == 0 || STRCMP(what, "name") == 0) { + if (strcmp(what, "func") == 0 || strcmp(what, "name") == 0) { rettv->v_type = (*what == 'f' ? VAR_FUNC : VAR_STRING); - if (pt->pt_name != NULL) { - rettv->vval.v_string = vim_strsave(pt->pt_name); + const char *const n = (const char *)partial_name(pt); + assert(n != NULL); + rettv->vval.v_string = (char_u *)xstrdup(n); + if (rettv->v_type == VAR_FUNC) { + func_ref(rettv->vval.v_string); } - } else if (STRCMP(what, "dict") == 0) { + } else if (strcmp(what, "dict") == 0) { rettv->v_type = VAR_DICT; rettv->vval.v_dict = pt->pt_dict; if (pt->pt_dict != NULL) { (pt->pt_dict->dv_refcount)++; } - } else if (STRCMP(what, "args") == 0) { + } else if (strcmp(what, "args") == 0) { rettv->v_type = VAR_LIST; - if (rettv_list_alloc(rettv) != NULL) { - int i; - - for (i = 0; i < pt->pt_argc; i++) { - list_append_tv(rettv->vval.v_list, &pt->pt_argv[i]); + if (tv_list_alloc_ret(rettv) != NULL) { + for (int i = 0; i < pt->pt_argc; i++) { + tv_list_append_tv(rettv->vval.v_list, &pt->pt_argv[i]); } } } else { @@ -9891,60 +9048,63 @@ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (tv == NULL) { - if (argvars[2].v_type != VAR_UNKNOWN) - copy_tv(&argvars[2], rettv); - } else - copy_tv(tv, rettv); + if (argvars[2].v_type != VAR_UNKNOWN) { + tv_copy(&argvars[2], rettv); + } + } else { + tv_copy(tv, rettv); + } } /// Returns information about signs placed in a buffer as list of dicts. static void get_buffer_signs(buf_T *buf, list_T *l) { for (signlist_T *sign = buf->b_signlist; sign; sign = sign->next) { - dict_T *d = dict_alloc(); + dict_T *const d = tv_dict_alloc(); - dict_add_nr_str(d, "id", sign->id, NULL); - dict_add_nr_str(d, "lnum", sign->lnum, NULL); - dict_add_nr_str(d, "name", 0L, sign_typenr2name(sign->typenr)); + tv_dict_add_nr(d, S_LEN("id"), sign->id); + tv_dict_add_nr(d, S_LEN("lnum"), sign->lnum); + tv_dict_add_str(d, S_LEN("name"), + (const char *)sign_typenr2name(sign->typenr)); - list_append_dict(l, d); + tv_list_append_dict(l, d); } } /// Returns buffer options, variables and other attributes in a dictionary. static dict_T *get_buffer_info(buf_T *buf) { - dict_T *dict = dict_alloc(); - - dict_add_nr_str(dict, "bufnr", buf->b_fnum, NULL); - dict_add_nr_str(dict, "name", 0L, - buf->b_ffname != NULL ? buf->b_ffname : (char_u *)""); - dict_add_nr_str(dict, "lnum", buflist_findlnum(buf), NULL); - dict_add_nr_str(dict, "loaded", buf->b_ml.ml_mfp != NULL, NULL); - dict_add_nr_str(dict, "listed", buf->b_p_bl, NULL); - dict_add_nr_str(dict, "changed", bufIsChanged(buf), NULL); - dict_add_nr_str(dict, "changedtick", buf->b_changedtick, NULL); - dict_add_nr_str(dict, "hidden", - buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0, - NULL); + dict_T *const dict = tv_dict_alloc(); + + tv_dict_add_nr(dict, S_LEN("bufnr"), buf->b_fnum); + tv_dict_add_str(dict, S_LEN("name"), + buf->b_ffname != NULL ? (const char *)buf->b_ffname : ""); + tv_dict_add_nr(dict, S_LEN("lnum"), + buf == curbuf ? curwin->w_cursor.lnum : buflist_findlnum(buf)); + tv_dict_add_nr(dict, S_LEN("loaded"), buf->b_ml.ml_mfp != NULL); + tv_dict_add_nr(dict, S_LEN("listed"), buf->b_p_bl); + tv_dict_add_nr(dict, S_LEN("changed"), bufIsChanged(buf)); + tv_dict_add_nr(dict, S_LEN("changedtick"), buf->b_changedtick); + tv_dict_add_nr(dict, S_LEN("hidden"), + buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0); // Get a reference to buffer variables - dict_add_dict(dict, "variables", buf->b_vars); + tv_dict_add_dict(dict, S_LEN("variables"), buf->b_vars); // List of windows displaying this buffer - list_T *windows = list_alloc(); + list_T *const windows = tv_list_alloc(); FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->w_buffer == buf) { - list_append_number(windows, (varnumber_T)wp->handle); + tv_list_append_number(windows, (varnumber_T)wp->handle); } } - dict_add_list(dict, "windows", windows); + tv_dict_add_list(dict, S_LEN("windows"), windows); if (buf->b_signlist != NULL) { // List of signs placed in this buffer - list_T *signs = list_alloc(); + list_T *const signs = tv_list_alloc(); get_buffer_signs(buf, signs); - dict_add_list(dict, "signs", signs); + tv_dict_add_list(dict, S_LEN("signs"), signs); } return dict; @@ -9958,7 +9118,7 @@ static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) bool sel_buflisted = false; bool sel_bufloaded = false; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); // List of all the buffers or selected buffers if (argvars[0].v_type == VAR_DICT) { @@ -9969,24 +9129,25 @@ static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) filtered = true; - di = dict_find(sel_d, (char_u *)"buflisted", -1); - if (di != NULL && get_tv_number(&di->di_tv)) { + di = tv_dict_find(sel_d, S_LEN("buflisted")); + if (di != NULL && tv_get_number(&di->di_tv)) { sel_buflisted = true; } - di = dict_find(sel_d, (char_u *)"bufloaded", -1); - if (di != NULL && get_tv_number(&di->di_tv)) { + di = tv_dict_find(sel_d, S_LEN("bufloaded")); + if (di != NULL && tv_get_number(&di->di_tv)) { sel_bufloaded = true; } } } else if (argvars[0].v_type != VAR_UNKNOWN) { // Information about one buffer. Argument specifies the buffer - (void)get_tv_number(&argvars[0]); // issue errmsg if type error - emsg_off++; - argbuf = get_buf_tv(&argvars[0], false); - emsg_off--; - if (argbuf == NULL) { - return; + if (tv_check_num(&argvars[0])) { // issue errmsg if type error + emsg_off++; + argbuf = get_buf_tv(&argvars[0], false); + emsg_off--; + if (argbuf == NULL) { + return; + } } } @@ -10000,9 +9161,9 @@ static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) continue; } - dict_T *d = get_buffer_info(buf); + dict_T *const d = get_buffer_info(buf); if (d != NULL) { - list_append_dict(rettv->vval.v_list, d); + tv_list_append_dict(rettv->vval.v_list, d); } if (argbuf != NULL) { return; @@ -10023,7 +9184,7 @@ static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retli rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; if (retlist) { - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); } if (buf == NULL || buf->b_ml.ml_mfp == NULL || start < 0) @@ -10044,33 +9205,54 @@ static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retli if (end > buf->b_ml.ml_line_count) end = buf->b_ml.ml_line_count; while (start <= end) { - list_append_string( - rettv->vval.v_list, ml_get_buf(buf, start++, FALSE), -1); + tv_list_append_string(rettv->vval.v_list, + (const char *)ml_get_buf(buf, start++, false), -1); } } } +/// Get the line number from VimL object +/// +/// @note Unlike tv_get_lnum(), this one supports only "$" special string. +/// +/// @param[in] tv Object to get value from. Is expected to be a number or +/// a special string "$". +/// @param[in] buf Buffer to take last line number from in case tv is "$". May +/// be NULL, in this case "$" results in zero return. +/// +/// @return Line number or 0 in case of error. +static linenr_T tv_get_lnum_buf(const typval_T *const tv, + const buf_T *const buf) + FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (tv->v_type == VAR_STRING + && tv->vval.v_string != NULL + && tv->vval.v_string[0] == '$' + && buf != NULL) { + return buf->b_ml.ml_line_count; + } + return tv_get_number_chk(tv, NULL); +} + /* * "getbufline()" function */ static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; - linenr_T end; - buf_T *buf; + buf_T *buf = NULL; - (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ - ++emsg_off; - buf = get_buf_tv(&argvars[0], FALSE); - --emsg_off; + if (tv_check_str_or_nr(&argvars[0])) { + emsg_off++; + buf = get_buf_tv(&argvars[0], false); + emsg_off--; + } - lnum = get_tv_lnum_buf(&argvars[1], buf); - if (argvars[2].v_type == VAR_UNKNOWN) - end = lnum; - else - end = get_tv_lnum_buf(&argvars[2], buf); + const linenr_T lnum = tv_get_lnum_buf(&argvars[1], buf); + const linenr_T end = (argvars[2].v_type == VAR_UNKNOWN + ? lnum + : tv_get_lnum_buf(&argvars[2], buf)); - get_buffer_lines(buf, lnum, end, TRUE, rettv); + get_buffer_lines(buf, lnum, end, true, rettv); } /* @@ -10078,26 +9260,25 @@ static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - buf_T *buf; - buf_T *save_curbuf; - char_u *varname; - dictitem_T *v; - int done = FALSE; - - (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ - varname = get_tv_string_chk(&argvars[1]); - ++emsg_off; - buf = get_buf_tv(&argvars[0], FALSE); + bool done = false; rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; + if (!tv_check_str_or_nr(&argvars[0])) { + goto f_getbufvar_end; + } + + const char *varname = tv_get_string_chk(&argvars[1]); + emsg_off++; + buf_T *const buf = get_buf_tv(&argvars[0], false); + if (buf != NULL && varname != NULL) { - /* set curbuf to be our buf, temporarily */ - save_curbuf = curbuf; + // set curbuf to be our buf, temporarily + buf_T *const save_curbuf = curbuf; curbuf = buf; - if (*varname == '&') { // buffer-local-option + if (*varname == '&') { // buffer-local-option if (varname[1] == NUL) { // get all buffer-local options in a dict dict_T *opts = get_winbuf_options(true); @@ -10112,30 +9293,27 @@ static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) // buffer-local-option done = true; } - } else if (STRCMP(varname, "changedtick") == 0) { - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = curbuf->b_changedtick; - done = true; } else { - /* Look up the variable. */ - /* Let getbufvar({nr}, "") return the "b:" dictionary. */ - v = find_var_in_ht(&curbuf->b_vars->dv_hashtab, - 'b', varname, FALSE); + // Look up the variable. + // Let getbufvar({nr}, "") return the "b:" dictionary. + dictitem_T *const v = find_var_in_ht(&curbuf->b_vars->dv_hashtab, 'b', + varname, strlen(varname), false); if (v != NULL) { - copy_tv(&v->di_tv, rettv); - done = TRUE; + tv_copy(&v->di_tv, rettv); + done = true; } } - /* restore previous notion of curbuf */ + // restore previous notion of curbuf curbuf = save_curbuf; } + emsg_off--; - if (!done && argvars[2].v_type != VAR_UNKNOWN) - /* use the default value */ - copy_tv(&argvars[2], rettv); - - --emsg_off; +f_getbufvar_end: + if (!done && argvars[2].v_type != VAR_UNKNOWN) { + // use the default value + tv_copy(&argvars[2], rettv); + } } /* @@ -10144,10 +9322,9 @@ static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { varnumber_T n; - int error = FALSE; + bool error = false; - ++no_mapping; - ++allow_keys; + no_mapping++; for (;; ) { // Position the cursor. Needed after a message that ends in a space, // or if event processing caused a redraw. @@ -10165,7 +9342,7 @@ static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } n = safe_vgetc(); - } else if (get_tv_number_chk(&argvars[0], &error) == 1) { + } else if (tv_get_number_chk(&argvars[0], &error) == 1) { // getchar(1): only check if char avail n = vpeekc_any(); } else if (error || vpeekc_any() == NUL) { @@ -10176,12 +9353,12 @@ static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) n = safe_vgetc(); } - if (n == K_IGNORE) + if (n == K_IGNORE) { continue; + } break; } - --no_mapping; - --allow_keys; + no_mapping--; vimvars[VV_MOUSE_WIN].vv_nr = 0; vimvars[VV_MOUSE_WINID].vv_nr = 0; @@ -10248,13 +9425,13 @@ static void f_getcharmod(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv_dict_alloc(rettv); + tv_dict_alloc_ret(rettv); dict_T *dict = rettv->vval.v_dict; - dict_add_nr_str(dict, "char", 0L, last_csearch()); - dict_add_nr_str(dict, "forward", last_csearch_forward(), NULL); - dict_add_nr_str(dict, "until", last_csearch_until(), NULL); + tv_dict_add_str(dict, S_LEN("char"), last_csearch()); + tv_dict_add_nr(dict, S_LEN("forward"), last_csearch_forward()); + tv_dict_add_nr(dict, S_LEN("until"), last_csearch_until()); } /* @@ -10305,7 +9482,7 @@ static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr) | WILD_NO_BEEP; if (argvars[2].v_type != VAR_UNKNOWN) { - filtered = get_tv_number_chk(&argvars[2], NULL); + filtered = (bool)tv_get_number_chk(&argvars[2], NULL); } if (p_wic) { @@ -10317,41 +9494,51 @@ static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr) options |= WILD_KEEP_ALL; } + if (argvars[0].v_type != VAR_STRING || argvars[1].v_type != VAR_STRING) { + EMSG(_(e_invarg)); + return; + } + + if (strcmp(tv_get_string(&argvars[1]), "cmdline") == 0) { + set_one_cmd_context(&xpc, tv_get_string(&argvars[0])); + xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); + goto theend; + } + ExpandInit(&xpc); - xpc.xp_pattern = get_tv_string(&argvars[0]); - xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); - xpc.xp_context = cmdcomplete_str_to_type(get_tv_string(&argvars[1])); + xpc.xp_pattern = (char_u *)tv_get_string(&argvars[0]); + xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); + xpc.xp_context = cmdcomplete_str_to_type( + (char_u *)tv_get_string(&argvars[1])); if (xpc.xp_context == EXPAND_NOTHING) { - if (argvars[1].v_type == VAR_STRING) { - EMSG2(_(e_invarg2), argvars[1].vval.v_string); - } else { - EMSG(_(e_invarg)); - } + EMSG2(_(e_invarg2), argvars[1].vval.v_string); return; } if (xpc.xp_context == EXPAND_MENUS) { set_context_in_menu_cmd(&xpc, (char_u *)"menu", xpc.xp_pattern, false); - xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); + xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); } if (xpc.xp_context == EXPAND_CSCOPE) { - set_context_in_cscope_cmd(&xpc, xpc.xp_pattern, CMD_cscope); - xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); + set_context_in_cscope_cmd(&xpc, (const char *)xpc.xp_pattern, CMD_cscope); + xpc.xp_pattern_len = (int)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); + xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); } +theend: pat = addstar(xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context); - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (pat != NULL) { ExpandOne(&xpc, pat, NULL, options, WILD_ALL_KEEP); for (int i = 0; i < xpc.xp_numfiles; i++) { - list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1); + tv_list_append_string(rettv->vval.v_list, (const char *)xpc.xp_files[i], + -1); } } xfree(pat); @@ -10452,13 +9639,15 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (from) { break; } - case kCdScopeTab: // FALLTHROUGH + // fallthrough + case kCdScopeTab: assert(tp); - from = tp->localdir; + from = tp->tp_localdir; if (from) { break; } - case kCdScopeGlobal: // FALLTHROUGH + // fallthrough + case kCdScopeGlobal: if (globaldir) { // `globaldir` is not always set. from = globaldir; } else if (os_dirname(cwd, MAXPATHL) == FAIL) { // Get the OS CWD. @@ -10495,20 +9684,21 @@ static void f_getfontname(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *perm = NULL; + char *perm = NULL; char_u flags[] = "rwx"; - char_u *filename = get_tv_string(&argvars[0]); + const char *filename = tv_get_string(&argvars[0]); int32_t file_perm = os_getperm(filename); if (file_perm >= 0) { - perm = vim_strsave((char_u *)"---------"); + perm = xstrdup("---------"); for (int i = 0; i < 9; i++) { - if (file_perm & (1 << (8 - i))) + if (file_perm & (1 << (8 - i))) { perm[i] = flags[i % 3]; + } } } rettv->v_type = VAR_STRING; - rettv->vval.v_string = perm; + rettv->vval.v_string = (char_u *)perm; } /* @@ -10516,16 +9706,16 @@ static void f_getfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getfsize(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char *fname = (char *)get_tv_string(&argvars[0]); + const char *fname = tv_get_string(&argvars[0]); rettv->v_type = VAR_NUMBER; FileInfo file_info; if (os_fileinfo(fname, &file_info)) { uint64_t filesize = os_fileinfo_size(&file_info); - if (os_isdir((char_u *)fname)) + if (os_isdir((const char_u *)fname)) { rettv->vval.v_number = 0; - else { + } else { rettv->vval.v_number = (varnumber_T)filesize; /* non-perfect check for overflow */ @@ -10543,7 +9733,7 @@ static void f_getfsize(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char *fname = (char *)get_tv_string(&argvars[0]); + const char *fname = tv_get_string(&argvars[0]); FileInfo file_info; if (os_fileinfo(fname, &file_info)) { @@ -10558,15 +9748,14 @@ static void f_getftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *fname; char_u *type = NULL; char *t; - fname = get_tv_string(&argvars[0]); + const char *fname = tv_get_string(&argvars[0]); rettv->v_type = VAR_STRING; FileInfo file_info; - if (os_fileinfo_link((char *)fname, &file_info)) { + if (os_fileinfo_link(fname, &file_info)) { uint64_t mode = file_info.stat.st_mode; #ifdef S_ISREG if (S_ISREG(mode)) @@ -10618,10 +9807,11 @@ static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr) default: t = "other"; } # else - if (os_isdir(fname)) + if (os_isdir((const char_u *)fname)) { t = "dir"; - else + } else { t = "file"; + } # endif #endif type = vim_strsave((char_u *)t); @@ -10634,22 +9824,52 @@ static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; linenr_T end; - int retlist; + bool retlist; - lnum = get_tv_lnum(argvars); + const linenr_T lnum = tv_get_lnum(argvars); if (argvars[1].v_type == VAR_UNKNOWN) { end = 0; - retlist = FALSE; + retlist = false; } else { - end = get_tv_lnum(&argvars[1]); - retlist = TRUE; + end = tv_get_lnum(&argvars[1]); + retlist = true; } get_buffer_lines(curbuf, lnum, end, retlist, rettv); } +static void get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, + typval_T *rettv) +{ + if (what_arg->v_type == VAR_UNKNOWN) { + tv_list_alloc_ret(rettv); + if (is_qf || wp != NULL) { + (void)get_errorlist(wp, -1, rettv->vval.v_list); + } + } else { + tv_dict_alloc_ret(rettv); + if (is_qf || wp != NULL) { + if (what_arg->v_type == VAR_DICT) { + dict_T *d = what_arg->vval.v_dict; + + if (d != NULL) { + get_errorlist_properties(wp, d, rettv->vval.v_dict); + } + } else { + EMSG(_(e_dictreq)); + } + } + } +} + +/// "getloclist()" function +static void f_getloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + win_T *wp = find_win_by_nr(&argvars[0], NULL); + get_qf_loc_list(false, wp, &argvars[1], rettv); +} + /* * "getmatches()" function */ @@ -10658,43 +9878,45 @@ static void f_getmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) matchitem_T *cur = curwin->w_match_head; int i; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); while (cur != NULL) { - dict_T *dict = dict_alloc(); + dict_T *dict = tv_dict_alloc(); if (cur->match.regprog == NULL) { // match added with matchaddpos() for (i = 0; i < MAXPOSMATCH; ++i) { llpos_T *llpos; - char buf[6]; + char buf[6]; llpos = &cur->pos.pos[i]; if (llpos->lnum == 0) { break; } - list_T *l = list_alloc(); - list_append_number(l, (varnumber_T)llpos->lnum); + list_T *l = tv_list_alloc(); + tv_list_append_number(l, (varnumber_T)llpos->lnum); if (llpos->col > 0) { - list_append_number(l, (varnumber_T)llpos->col); - list_append_number(l, (varnumber_T)llpos->len); + tv_list_append_number(l, (varnumber_T)llpos->col); + tv_list_append_number(l, (varnumber_T)llpos->len); } - sprintf(buf, "pos%d", i + 1); - dict_add_list(dict, buf, l); + int len = snprintf(buf, sizeof(buf), "pos%d", i + 1); + assert((size_t)len < sizeof(buf)); + tv_dict_add_list(dict, buf, (size_t)len, l); } } else { - dict_add_nr_str(dict, "pattern", 0L, cur->pattern); + tv_dict_add_str(dict, S_LEN("pattern"), (const char *)cur->pattern); } - dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id)); - dict_add_nr_str(dict, "priority", (long)cur->priority, NULL); - dict_add_nr_str(dict, "id", (long)cur->id, NULL); + tv_dict_add_str(dict, S_LEN("group"), + (const char *)syn_id2name(cur->hlg_id)); + tv_dict_add_nr(dict, S_LEN("priority"), (varnumber_T)cur->priority); + tv_dict_add_nr(dict, S_LEN("id"), (varnumber_T)cur->id); if (cur->conceal_char) { - char_u buf[MB_MAXBYTES + 1]; + char buf[MB_MAXBYTES + 1]; - buf[(*mb_char2bytes)((int)cur->conceal_char, buf)] = NUL; - dict_add_nr_str(dict, "conceal", 0L, (char_u *)&buf); + buf[(*mb_char2bytes)((int)cur->conceal_char, (char_u *)buf)] = NUL; + tv_dict_add_str(dict, S_LEN("conceal"), buf); } - list_append_dict(rettv->vval.v_list, dict); + tv_list_append_dict(rettv->vval.v_list, dict); cur = cur->next; } } @@ -10718,20 +9940,22 @@ static void getpos_both(typval_T *argvars, typval_T *rettv, bool getcurpos) fp = var2fpos(&argvars[0], true, &fnum); } - list_T *l = rettv_list_alloc(rettv); - list_append_number(l, (fnum != -1) ? (varnumber_T)fnum : (varnumber_T)0); - list_append_number(l, (fp != NULL) ? (varnumber_T)fp->lnum : (varnumber_T)0); - list_append_number(l, - (fp != NULL) - ? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1) - : (varnumber_T)0); - list_append_number(l, - (fp != NULL) ? (varnumber_T)fp->coladd : (varnumber_T)0); + list_T *l = tv_list_alloc_ret(rettv); + tv_list_append_number(l, (fnum != -1) ? (varnumber_T)fnum : (varnumber_T)0); + tv_list_append_number(l, ((fp != NULL) + ? (varnumber_T)fp->lnum + : (varnumber_T)0)); + tv_list_append_number( + l, ((fp != NULL) + ? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1) + : (varnumber_T)0)); + tv_list_append_number( + l, (fp != NULL) ? (varnumber_T)fp->coladd : (varnumber_T)0); if (getcurpos) { update_curswant(); - list_append_number(l, curwin->w_curswant == MAXCOL + tv_list_append_number(l, (curwin->w_curswant == MAXCOL ? (varnumber_T)MAXCOL - : (varnumber_T)curwin->w_curswant + 1); + : (varnumber_T)curwin->w_curswant + 1)); } } @@ -10751,58 +9975,48 @@ static void f_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) getpos_both(argvars, rettv, false); } -/* - * "getqflist()" and "getloclist()" functions - */ +/// "getqflist()" functions static void f_getqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv_list_alloc(rettv); - win_T *wp = NULL; - if (argvars[0].v_type != VAR_UNKNOWN) { /* getloclist() */ - wp = find_win_by_nr(&argvars[0], NULL); - if (wp == NULL) { - return; - } - } - (void)get_errorlist(wp, rettv->vval.v_list); + get_qf_loc_list(true, NULL, &argvars[0], rettv); } /// "getreg()" function static void f_getreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *strregname; - int regname; + const char *strregname; int arg2 = false; bool return_list = false; - int error = false; + bool error = false; if (argvars[0].v_type != VAR_UNKNOWN) { - strregname = get_tv_string_chk(&argvars[0]); + strregname = tv_get_string_chk(&argvars[0]); error = strregname == NULL; if (argvars[1].v_type != VAR_UNKNOWN) { - arg2 = get_tv_number_chk(&argvars[1], &error); + arg2 = tv_get_number_chk(&argvars[1], &error); if (!error && argvars[2].v_type != VAR_UNKNOWN) { - return_list = get_tv_number_chk(&argvars[2], &error); + return_list = tv_get_number_chk(&argvars[2], &error); } } } else { - strregname = vimvars[VV_REG].vv_str; + strregname = (const char *)vimvars[VV_REG].vv_str; } if (error) { return; } - regname = (strregname == NULL ? '"' : *strregname); - if (regname == 0) + int regname = (uint8_t)(strregname == NULL ? '"' : *strregname); + if (regname == 0) { regname = '"'; + } if (return_list) { rettv->v_type = VAR_LIST; rettv->vval.v_list = get_reg_contents(regname, (arg2 ? kGRegExprSrc : 0) | kGRegList); if (rettv->vval.v_list == NULL) { - rettv->vval.v_list = list_alloc(); + rettv->vval.v_list = tv_list_alloc(); } rettv->vval.v_list->lv_refcount++; } else { @@ -10816,23 +10030,24 @@ static void f_getreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getregtype(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *strregname; - int regname; + const char *strregname; if (argvars[0].v_type != VAR_UNKNOWN) { - strregname = get_tv_string_chk(&argvars[0]); - if (strregname == NULL) { /* type error; errmsg already given */ + strregname = tv_get_string_chk(&argvars[0]); + if (strregname == NULL) { // Type error; errmsg already given. rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; return; } - } else - /* Default to v:register */ - strregname = vimvars[VV_REG].vv_str; + } else { + // Default to v:register. + strregname = (const char *)vimvars[VV_REG].vv_str; + } - regname = (strregname == NULL ? '"' : *strregname); - if (regname == 0) + int regname = (uint8_t)(strregname == NULL ? '"' : *strregname); + if (regname == 0) { regname = '"'; + } colnr_T reglen = 0; char buf[NUMBUFLEN + 2]; @@ -10847,18 +10062,18 @@ static void f_getregtype(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// as a dictionary. static dict_T *get_tabpage_info(tabpage_T *tp, int tp_idx) { - dict_T *dict = dict_alloc(); + dict_T *const dict = tv_dict_alloc(); - dict_add_nr_str(dict, "tabnr", tp_idx, NULL); + tv_dict_add_nr(dict, S_LEN("tabnr"), tp_idx); - list_T *l = list_alloc(); + list_T *const l = tv_list_alloc(); FOR_ALL_WINDOWS_IN_TAB(wp, tp) { - list_append_number(l, (varnumber_T)wp->handle); + tv_list_append_number(l, (varnumber_T)wp->handle); } - dict_add_list(dict, "windows", l); + tv_dict_add_list(dict, S_LEN("windows"), l); // Make a reference to tabpage variables - dict_add_dict(dict, "variables", tp->tp_vars); + tv_dict_add_dict(dict, S_LEN("variables"), tp->tp_vars); return dict; } @@ -10868,11 +10083,11 @@ static void f_gettabinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) { tabpage_T *tparg = NULL; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (argvars[0].v_type != VAR_UNKNOWN) { // Information about one tab page - tparg = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL)); + tparg = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); if (tparg == NULL) { return; } @@ -10885,9 +10100,9 @@ static void f_gettabinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (tparg != NULL && tp != tparg) { continue; } - dict_T *d = get_tabpage_info(tp, tpnr); + dict_T *const d = get_tabpage_info(tp, tpnr); if (d != NULL) { - list_append_dict(rettv->vval.v_list, d); + tv_list_append_dict(rettv->vval.v_list, d); } if (tparg != NULL) { return; @@ -10903,14 +10118,13 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) win_T *oldcurwin; tabpage_T *tp, *oldtabpage; dictitem_T *v; - char_u *varname; bool done = false; rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - varname = get_tv_string_chk(&argvars[1]); - tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL)); + const char *const varname = tv_get_string_chk(&argvars[1]); + tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); if (tp != NULL && varname != NULL) { // Set tp to be our tabpage, temporarily. Also set the window to the // first window in the tabpage, otherwise the window is not valid. @@ -10918,9 +10132,10 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (switch_win(&oldcurwin, &oldtabpage, window, tp, true) == OK) { // look up the variable // Let gettabvar({nr}, "") return the "t:" dictionary. - v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', varname, FALSE); + v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', + varname, strlen(varname), false); if (v != NULL) { - copy_tv(&v->di_tv, rettv); + tv_copy(&v->di_tv, rettv); done = true; } } @@ -10930,7 +10145,7 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (!done && argvars[2].v_type != VAR_UNKNOWN) { - copy_tv(&argvars[2], rettv); + tv_copy(&argvars[2], rettv); } } @@ -10945,22 +10160,21 @@ static void f_gettabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// Returns information about a window as a dictionary. static dict_T *get_win_info(win_T *wp, int16_t tpnr, int16_t winnr) { - dict_T *dict = dict_alloc(); + dict_T *const dict = tv_dict_alloc(); - dict_add_nr_str(dict, "tabnr", tpnr, NULL); - dict_add_nr_str(dict, "winnr", winnr, NULL); - dict_add_nr_str(dict, "winid", wp->handle, NULL); - dict_add_nr_str(dict, "height", wp->w_height, NULL); - dict_add_nr_str(dict, "width", wp->w_width, NULL); - dict_add_nr_str(dict, "bufnr", wp->w_buffer->b_fnum, NULL); + tv_dict_add_nr(dict, S_LEN("tabnr"), tpnr); + tv_dict_add_nr(dict, S_LEN("winnr"), winnr); + tv_dict_add_nr(dict, S_LEN("winid"), wp->handle); + tv_dict_add_nr(dict, S_LEN("height"), wp->w_height); + tv_dict_add_nr(dict, S_LEN("width"), wp->w_width); + tv_dict_add_nr(dict, S_LEN("bufnr"), wp->w_buffer->b_fnum); - dict_add_nr_str(dict, "quickfix", bt_quickfix(wp->w_buffer), NULL); - dict_add_nr_str(dict, "loclist", - (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL), - NULL); + tv_dict_add_nr(dict, S_LEN("quickfix"), bt_quickfix(wp->w_buffer)); + tv_dict_add_nr(dict, S_LEN("loclist"), + (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL)); // Add a reference to window variables - dict_add_dict(dict, "variables", wp->w_vars); + tv_dict_add_dict(dict, S_LEN("variables"), wp->w_vars); return dict; } @@ -10970,7 +10184,7 @@ static void f_getwininfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) { win_T *wparg = NULL; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (argvars[0].v_type != VAR_UNKNOWN) { wparg = win_id2wp(argvars); @@ -10990,9 +10204,9 @@ static void f_getwininfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) continue; } winnr++; - dict_T *d = get_win_info(wp, tabnr, winnr); + dict_T *const d = get_win_info(wp, tabnr, winnr); if (d != NULL) { - list_append_dict(rettv->vval.v_list, d); + tv_list_append_dict(rettv->vval.v_list, d); } if (wparg != NULL) { // found information about a specific window @@ -11027,7 +10241,7 @@ find_win_by_nr ( tabpage_T *tp /* NULL for current tab page */ ) { - int nr = get_tv_number_chk(vp, NULL); + int nr = (int)tv_get_number_chk(vp, NULL); if (nr < 0) { return NULL; @@ -11062,7 +10276,7 @@ static win_T *find_tabwin(typval_T *wvp, typval_T *tvp) if (wvp->v_type != VAR_UNKNOWN) { if (tvp->v_type != VAR_UNKNOWN) { - long n = get_tv_number(tvp); + long n = tv_get_number(tvp); if (n >= 0) { tp = find_tabpage(n); } @@ -11097,23 +10311,23 @@ getwinvar ( ) { win_T *win, *oldcurwin; - char_u *varname; dictitem_T *v; tabpage_T *tp = NULL; tabpage_T *oldtabpage = NULL; bool done = false; - if (off == 1) - tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL)); - else + if (off == 1) { + tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); + } else { tp = curtab; + } win = find_win_by_nr(&argvars[off], tp); - varname = get_tv_string_chk(&argvars[off + 1]); - ++emsg_off; + const char *varname = tv_get_string_chk(&argvars[off + 1]); rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; + emsg_off++; if (win != NULL && varname != NULL) { // Set curwin to be our win, temporarily. Also set the tabpage, // otherwise the window is not valid. Only do this when needed, @@ -11139,9 +10353,10 @@ getwinvar ( } else { // Look up the variable. // Let getwinvar({nr}, "") return the "w:" dictionary. - v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w', varname, FALSE); + v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w', varname, + strlen(varname), false); if (v != NULL) { - copy_tv(&v->di_tv, rettv); + tv_copy(&v->di_tv, rettv); done = true; } } @@ -11152,12 +10367,12 @@ getwinvar ( restore_win(oldcurwin, oldtabpage, true); } } + emsg_off--; - if (!done && argvars[off + 2].v_type != VAR_UNKNOWN) - /* use the default return value */ - copy_tv(&argvars[off + 2], rettv); - - --emsg_off; + if (!done && argvars[off + 2].v_type != VAR_UNKNOWN) { + // use the default return value + tv_copy(&argvars[off + 2], rettv); + } } /* @@ -11167,21 +10382,22 @@ static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int options = WILD_SILENT|WILD_USE_NL; expand_T xpc; - int error = FALSE; + bool error = false; /* When the optional second argument is non-zero, don't remove matches * for 'wildignore' and don't put matches for 'suffixes' at the end. */ rettv->v_type = VAR_STRING; if (argvars[1].v_type != VAR_UNKNOWN) { - if (get_tv_number_chk(&argvars[1], &error)) + if (tv_get_number_chk(&argvars[1], &error)) { options |= WILD_KEEP_ALL; + } if (argvars[2].v_type != VAR_UNKNOWN) { - if (get_tv_number_chk(&argvars[2], &error)) { + if (tv_get_number_chk(&argvars[2], &error)) { rettv->v_type = VAR_LIST; rettv->vval.v_list = NULL; } if (argvars[3].v_type != VAR_UNKNOWN - && get_tv_number_chk(&argvars[3], &error)) { + && tv_get_number_chk(&argvars[3], &error)) { options |= WILD_ALLLINKS; } } @@ -11191,14 +10407,16 @@ static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr) xpc.xp_context = EXPAND_FILES; if (p_wic) options += WILD_ICASE; - if (rettv->v_type == VAR_STRING) - rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]), - NULL, options, WILD_ALL); - else { - rettv_list_alloc(rettv); - ExpandOne(&xpc, get_tv_string(&argvars[0]), NULL, options, WILD_ALL_KEEP); + if (rettv->v_type == VAR_STRING) { + rettv->vval.v_string = ExpandOne( + &xpc, (char_u *)tv_get_string(&argvars[0]), NULL, options, WILD_ALL); + } else { + tv_list_alloc_ret(rettv); + ExpandOne(&xpc, (char_u *)tv_get_string(&argvars[0]), NULL, options, + WILD_ALL_KEEP); for (int i = 0; i < xpc.xp_numfiles; i++) { - list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1); + tv_list_append_string(rettv->vval.v_list, (const char *)xpc.xp_files[i], + -1); } ExpandCleanup(&xpc); } @@ -11210,7 +10428,7 @@ static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int flags = 0; // Flags for globpath. - int error = false; + bool error = false; // Return a string, or a list if the optional third argument is non-zero. rettv->v_type = VAR_STRING; @@ -11218,36 +10436,36 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[2].v_type != VAR_UNKNOWN) { // When the optional second argument is non-zero, don't remove matches // for 'wildignore' and don't put matches for 'suffixes' at the end. - if (get_tv_number_chk(&argvars[2], &error)) { + if (tv_get_number_chk(&argvars[2], &error)) { flags |= WILD_KEEP_ALL; } if (argvars[3].v_type != VAR_UNKNOWN) { - if (get_tv_number_chk(&argvars[3], &error)) { + if (tv_get_number_chk(&argvars[3], &error)) { rettv->v_type = VAR_LIST; rettv->vval.v_list = NULL; } if (argvars[4].v_type != VAR_UNKNOWN - && get_tv_number_chk(&argvars[4], &error)) { + && tv_get_number_chk(&argvars[4], &error)) { flags |= WILD_ALLLINKS; } } } - char_u buf1[NUMBUFLEN]; - char_u *file = get_tv_string_buf_chk(&argvars[1], buf1); + char buf1[NUMBUFLEN]; + 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(get_tv_string(&argvars[0]), file, &ga, flags); + globpath((char_u *)tv_get_string(&argvars[0]), (char_u *)file, &ga, flags); if (rettv->v_type == VAR_STRING) { rettv->vval.v_string = ga_concat_strings_sep(&ga, "\n"); } else { - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); for (int i = 0; i < ga.ga_len; i++) { - list_append_string(rettv->vval.v_list, - ((char_u **)(ga.ga_data))[i], -1); + tv_list_append_string(rettv->vval.v_list, + ((const char **)(ga.ga_data))[i], -1); } } @@ -11260,18 +10478,19 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr) // "glob2regpat()" function static void f_glob2regpat(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *pat = get_tv_string_chk(&argvars[0]); // NULL on type error + const char *const pat = tv_get_string_chk(&argvars[0]); // NULL on type error rettv->v_type = VAR_STRING; - rettv->vval.v_string = (pat == NULL) - ? NULL - : file_pat_to_reg_pat(pat, NULL, NULL, false); + rettv->vval.v_string = ((pat == NULL) + ? NULL + : file_pat_to_reg_pat((char_u *)pat, NULL, NULL, + false)); } /// "has()" function static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - static char *(has_list[]) = { + static const char *const has_list[] = { #ifdef UNIX "unix", #endif @@ -11322,6 +10541,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) "insert_expand", "jumplist", "keymap", + "lambda", "langmap", "libcall", "linebreak", @@ -11338,6 +10558,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) "mouse", "multi_byte", "multi_lang", + "num64", "packages", "path_extra", "persistent_undo", @@ -11381,13 +10602,11 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) "winaltkeys", "writebackup", "nvim", - NULL }; bool n = false; - char *name = (char *)get_tv_string(&argvars[0]); - - for (int i = 0; has_list[i] != NULL; i++) { + const char *const name = tv_get_string(&argvars[0]); + for (size_t i = 0; i < ARRAY_SIZE(has_list); i++) { if (STRICMP(name, has_list[i]) == 0) { n = true; break; @@ -11426,6 +10645,10 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) #endif } else if (STRICMP(name, "syntax_items") == 0) { n = syntax_present(curwin); +#ifdef UNIX + } else if (STRICMP(name, "unnamedplus") == 0) { + n = eval_has_provider("clipboard"); +#endif } } @@ -11448,8 +10671,9 @@ static void f_has_key(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].vval.v_dict == NULL) return; - rettv->vval.v_number = dict_find(argvars[0].vval.v_dict, - get_tv_string(&argvars[1]), -1) != NULL; + rettv->vval.v_number = tv_dict_find(argvars[0].vval.v_dict, + tv_get_string(&argvars[1]), + -1) != NULL; } /// `haslocaldir([{win}[, {tab}]])` function @@ -11541,7 +10765,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr) break; case kCdScopeTab: assert(tp); - rettv->vval.v_number = tp->localdir ? 1 : 0; + rettv->vval.v_number = tp->tp_localdir ? 1 : 0; break; case kCdScopeGlobal: // The global scope never has a local directory @@ -11558,24 +10782,24 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_hasmapto(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *name; - char_u *mode; - char_u buf[NUMBUFLEN]; - int abbr = FALSE; - - name = get_tv_string(&argvars[0]); - if (argvars[1].v_type == VAR_UNKNOWN) - mode = (char_u *)"nvo"; - else { - mode = get_tv_string_buf(&argvars[1], buf); - if (argvars[2].v_type != VAR_UNKNOWN) - abbr = get_tv_number(&argvars[2]); + const char *mode; + const char *const name = tv_get_string(&argvars[0]); + bool abbr = false; + char buf[NUMBUFLEN]; + if (argvars[1].v_type == VAR_UNKNOWN) { + mode = "nvo"; + } else { + mode = tv_get_string_buf(&argvars[1], buf); + if (argvars[2].v_type != VAR_UNKNOWN) { + abbr = tv_get_number(&argvars[2]); + } } - if (map_to_exists(name, mode, abbr)) - rettv->vval.v_number = TRUE; - else - rettv->vval.v_number = FALSE; + if (map_to_exists(name, mode, abbr)) { + rettv->vval.v_number = true; + } else { + rettv->vval.v_number = false; + } } /* @@ -11584,20 +10808,19 @@ static void f_hasmapto(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { HistoryType histype; - char_u *str; - char_u buf[NUMBUFLEN]; rettv->vval.v_number = false; if (check_restricted() || check_secure()) { return; } - str = get_tv_string_chk(&argvars[0]); // NULL on type error - histype = str != NULL ? get_histtype(str, STRLEN(str), false) : HIST_INVALID; + const char *str = tv_get_string_chk(&argvars[0]); // NULL on type error + histype = str != NULL ? get_histtype(str, strlen(str), false) : HIST_INVALID; if (histype != HIST_INVALID) { - str = get_tv_string_buf(&argvars[1], buf); + char buf[NUMBUFLEN]; + str = tv_get_string_buf(&argvars[1], buf); if (*str != NUL) { init_history(); - add_to_history(histype, str, false, NUL); + add_to_history(histype, (char_u *)str, false, NUL); rettv->vval.v_number = true; return; } @@ -11610,23 +10833,21 @@ static void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_histdel(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int n; - char_u buf[NUMBUFLEN]; - char_u *str; - - str = get_tv_string_chk(&argvars[0]); // NULL on type error + const char *const str = tv_get_string_chk(&argvars[0]); // NULL on type error if (str == NULL) { n = 0; } else if (argvars[1].v_type == VAR_UNKNOWN) { // only one argument: clear entire history - n = clr_history(get_histtype(str, STRLEN(str), false)); + n = clr_history(get_histtype(str, strlen(str), false)); } else if (argvars[1].v_type == VAR_NUMBER) { // index given: remove that entry - n = del_history_idx(get_histtype(str, STRLEN(str), false), - (int) get_tv_number(&argvars[1])); + n = del_history_idx(get_histtype(str, strlen(str), false), + (int)tv_get_number(&argvars[1])); } else { // string given: remove all matching entries - n = del_history_entry(get_histtype(str, STRLEN(str), false), - get_tv_string_buf(&argvars[1], buf)); + char buf[NUMBUFLEN]; + n = del_history_entry(get_histtype(str, strlen(str), false), + (char_u *)tv_get_string_buf(&argvars[1], buf)); } rettv->vval.v_number = n; } @@ -11638,17 +10859,16 @@ static void f_histget(typval_T *argvars, typval_T *rettv, FunPtr fptr) { HistoryType type; int idx; - char_u *str; - str = get_tv_string_chk(&argvars[0]); // NULL on type error + const char *const str = tv_get_string_chk(&argvars[0]); // NULL on type error if (str == NULL) { rettv->vval.v_string = NULL; } else { - type = get_histtype(str, STRLEN(str), false); + type = get_histtype(str, strlen(str), false); if (argvars[1].v_type == VAR_UNKNOWN) { idx = get_history_idx(type); } else { - idx = (int)get_tv_number_chk(&argvars[1], NULL); + idx = (int)tv_get_number_chk(&argvars[1], NULL); } // -1 on type error rettv->vval.v_string = vim_strsave(get_history_entry(type, idx)); @@ -11663,9 +10883,9 @@ static void f_histnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int i; - char_u *history = get_tv_string_chk(&argvars[0]); + const char *const history = tv_get_string_chk(&argvars[0]); - i = history == NULL ? HIST_CMD - 1 : get_histtype(history, STRLEN(history), + i = history == NULL ? HIST_CMD - 1 : get_histtype(history, strlen(history), false); if (i != HIST_INVALID) { i = get_history_idx(i); @@ -11680,7 +10900,8 @@ static void f_histnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = syn_name2id(get_tv_string(&argvars[0])); + rettv->vval.v_number = syn_name2id( + (const char_u *)tv_get_string(&argvars[0])); } /* @@ -11688,7 +10909,8 @@ static void f_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_hlexists(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = highlight_exists(get_tv_string(&argvars[0])); + rettv->vval.v_number = highlight_exists( + (const char_u *)tv_get_string(&argvars[0])); } /* @@ -11708,25 +10930,27 @@ static void f_hostname(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_iconv(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u buf1[NUMBUFLEN]; - char_u buf2[NUMBUFLEN]; - char_u *from, *to, *str; vimconv_T vimconv; rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - str = get_tv_string(&argvars[0]); - from = enc_canonize(enc_skip(get_tv_string_buf(&argvars[1], buf1))); - to = enc_canonize(enc_skip(get_tv_string_buf(&argvars[2], buf2))); + const char *const str = tv_get_string(&argvars[0]); + char buf1[NUMBUFLEN]; + char_u *const from = enc_canonize(enc_skip( + (char_u *)tv_get_string_buf(&argvars[1], buf1))); + char buf2[NUMBUFLEN]; + char_u *const to = enc_canonize(enc_skip( + (char_u *)tv_get_string_buf(&argvars[2], buf2))); vimconv.vc_type = CONV_NONE; convert_setup(&vimconv, from, to); - /* If the encodings are equal, no conversion needed. */ - if (vimconv.vc_type == CONV_NONE) - rettv->vval.v_string = vim_strsave(str); - else - rettv->vval.v_string = string_convert(&vimconv, str, NULL); + // If the encodings are equal, no conversion needed. + if (vimconv.vc_type == CONV_NONE) { + rettv->vval.v_string = (char_u *)xstrdup(str); + } else { + rettv->vval.v_string = string_convert(&vimconv, (char_u *)str, NULL); + } convert_setup(&vimconv, NULL, NULL); xfree(from); @@ -11738,13 +10962,12 @@ static void f_iconv(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_indent(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; - - lnum = get_tv_lnum(argvars); - if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) + const linenr_T lnum = tv_get_lnum(argvars); + if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) { rettv->vval.v_number = get_indent_lnum(lnum); - else + } else { rettv->vval.v_number = -1; + } } /* @@ -11766,16 +10989,18 @@ static void f_index(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (l != NULL) { item = l->lv_first; if (argvars[2].v_type != VAR_UNKNOWN) { - int error = FALSE; + bool error = false; - /* Start at specified item. Use the cached index that list_find() - * sets, so that a negative number also works. */ - item = list_find(l, get_tv_number_chk(&argvars[2], &error)); + // Start at specified item. Use the cached index that tv_list_find() + // sets, so that a negative number also works. + item = tv_list_find(l, tv_get_number_chk(&argvars[2], &error)); idx = l->lv_idx; - if (argvars[3].v_type != VAR_UNKNOWN) - ic = get_tv_number_chk(&argvars[3], &error); - if (error) + if (argvars[3].v_type != VAR_UNKNOWN) { + ic = tv_get_number_chk(&argvars[3], &error); + } + if (error) { item = NULL; + } } for (; item != NULL; item = item->li_next, ++idx) @@ -11795,85 +11020,131 @@ static int inputsecret_flag = 0; * prompt. The third argument to f_inputdialog() specifies the value to return * when the user cancels the prompt. */ -static void get_user_input(typval_T *argvars, typval_T *rettv, int inputdialog) +void get_user_input(const typval_T *const argvars, + typval_T *const rettv, const bool inputdialog) + FUNC_ATTR_NONNULL_ALL { - char_u *prompt = get_tv_string_chk(&argvars[0]); - char_u *p = NULL; - int c; - char_u buf[NUMBUFLEN]; - int cmd_silent_save = cmd_silent; - char_u *defstr = (char_u *)""; - int xp_type = EXPAND_NOTHING; - char_u *xp_arg = NULL; - rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - cmd_silent = FALSE; /* Want to see the prompt. */ - if (prompt != NULL) { - /* Only the part of the message after the last NL is considered as - * prompt for the command line */ - p = vim_strrchr(prompt, '\n'); - if (p == NULL) - p = prompt; - else { - ++p; - c = *p; - *p = NUL; - msg_start(); - msg_clr_eos(); - msg_puts_attr(prompt, echo_attr); - msg_didout = FALSE; - msg_starthere(); - *p = c; + const char *prompt = ""; + const char *defstr = ""; + const char *cancelreturn = NULL; + const char *xp_name = NULL; + Callback input_callback = { .type = kCallbackNone }; + char prompt_buf[NUMBUFLEN]; + char defstr_buf[NUMBUFLEN]; + char cancelreturn_buf[NUMBUFLEN]; + char xp_name_buf[NUMBUFLEN]; + if (argvars[0].v_type == VAR_DICT) { + if (argvars[1].v_type != VAR_UNKNOWN) { + emsgf(_("E5050: {opts} must be the only argument")); + return; + } + dict_T *const dict = argvars[0].vval.v_dict; + prompt = tv_dict_get_string_buf_chk(dict, S_LEN("prompt"), prompt_buf, ""); + if (prompt == NULL) { + return; + } + defstr = tv_dict_get_string_buf_chk(dict, S_LEN("default"), defstr_buf, ""); + if (defstr == NULL) { + return; + } + char def[1] = { 0 }; + cancelreturn = tv_dict_get_string_buf_chk(dict, S_LEN("cancelreturn"), + cancelreturn_buf, def); + if (cancelreturn == NULL) { // error + return; + } + if (*cancelreturn == NUL) { + cancelreturn = NULL; + } + xp_name = tv_dict_get_string_buf_chk(dict, S_LEN("completion"), + xp_name_buf, def); + if (xp_name == NULL) { // error + return; + } + if (xp_name == def) { // default to NULL + xp_name = NULL; + } + if (!tv_dict_get_callback(dict, S_LEN("highlight"), &input_callback)) { + return; + } + } else { + prompt = tv_get_string_buf_chk(&argvars[0], prompt_buf); + if (prompt == NULL) { + return; } - cmdline_row = msg_row; - if (argvars[1].v_type != VAR_UNKNOWN) { - defstr = get_tv_string_buf_chk(&argvars[1], buf); - if (defstr != NULL) - stuffReadbuffSpec(defstr); - - if (!inputdialog && argvars[2].v_type != VAR_UNKNOWN) { - char_u *xp_name; - int xp_namelen; - uint32_t argt; - - /* input() with a third argument: completion */ - rettv->vval.v_string = NULL; - - xp_name = get_tv_string_buf_chk(&argvars[2], buf); - if (xp_name == NULL) - return; - - xp_namelen = (int)STRLEN(xp_name); - - if (parse_compl_arg(xp_name, xp_namelen, &xp_type, &argt, - &xp_arg) == FAIL) + defstr = tv_get_string_buf_chk(&argvars[1], defstr_buf); + if (defstr == NULL) { + return; + } + if (argvars[2].v_type != VAR_UNKNOWN) { + const char *const arg2 = tv_get_string_buf_chk(&argvars[2], + cancelreturn_buf); + if (arg2 == NULL) { return; + } + if (inputdialog) { + cancelreturn = arg2; + } else { + xp_name = arg2; + } } } + } - if (defstr != NULL) { - int save_ex_normal_busy = ex_normal_busy; - ex_normal_busy = 0; - rettv->vval.v_string = - getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr, - xp_type, xp_arg); - ex_normal_busy = save_ex_normal_busy; + int xp_type = EXPAND_NOTHING; + char *xp_arg = NULL; + if (xp_name != NULL) { + // input() with a third argument: completion + const int xp_namelen = (int)strlen(xp_name); + + uint32_t argt; + if (parse_compl_arg((char_u *)xp_name, xp_namelen, &xp_type, + &argt, (char_u **)&xp_arg) == FAIL) { + return; } - if (inputdialog && rettv->vval.v_string == NULL - && argvars[1].v_type != VAR_UNKNOWN - && argvars[2].v_type != VAR_UNKNOWN) - rettv->vval.v_string = vim_strsave(get_tv_string_buf( - &argvars[2], buf)); + } - xfree(xp_arg); + int cmd_silent_save = cmd_silent; - /* since the user typed this, no need to wait for return */ - need_wait_return = FALSE; - msg_didout = FALSE; + cmd_silent = false; // Want to see the prompt. + // Only the part of the message after the last NL is considered as + // prompt for the command line. + const char *p = strrchr(prompt, '\n'); + if (p == NULL) { + p = prompt; + } else { + p++; + msg_start(); + msg_clr_eos(); + msg_puts_attr_len(prompt, p - prompt, echo_attr); + msg_didout = false; + msg_starthere(); + } + cmdline_row = msg_row; + + stuffReadbuffSpec(defstr); + + const int save_ex_normal_busy = ex_normal_busy; + ex_normal_busy = 0; + rettv->vval.v_string = + (char_u *)getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr, + xp_type, xp_arg, input_callback); + ex_normal_busy = save_ex_normal_busy; + callback_free(&input_callback); + + if (rettv->vval.v_string == NULL && cancelreturn != NULL) { + rettv->vval.v_string = (char_u *)xstrdup(cancelreturn); } + + xfree(xp_arg); + + // Since the user typed this, no need to wait for return. + need_wait_return = false; + msg_didout = false; cmd_silent = cmd_silent_save; } @@ -11915,7 +11186,7 @@ static void f_inputlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) msg_clr_eos(); for (li = argvars[0].vval.v_list->lv_first; li != NULL; li = li->li_next) { - msg_puts(get_tv_string(&li->li_tv)); + msg_puts(tv_get_string(&li->li_tv)); msg_putchar('\n'); } @@ -11973,36 +11244,34 @@ static void f_inputsecret(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - long before = 0; - listitem_T *item; - list_T *l; - int error = FALSE; + list_T *l; + bool error = false; if (argvars[0].v_type != VAR_LIST) { EMSG2(_(e_listarg), "insert()"); } else if ((l = argvars[0].vval.v_list) != NULL - && !tv_check_lock(l->lv_lock, - (char_u *)N_("insert() argument"), true)) { + && !tv_check_lock(l->lv_lock, N_("insert() argument"), + TV_TRANSLATE)) { + long before = 0; if (argvars[2].v_type != VAR_UNKNOWN) { - before = get_tv_number_chk(&argvars[2], &error); + before = tv_get_number_chk(&argvars[2], &error); } if (error) { // type error; errmsg already given return; } - if (before == l->lv_len) - item = NULL; - else { - item = list_find(l, before); + listitem_T *item = NULL; + if (before != l->lv_len) { + item = tv_list_find(l, before); if (item == NULL) { EMSGN(_(e_listidx), before); l = NULL; } } if (l != NULL) { - list_insert_tv(l, &argvars[1], item); - copy_tv(&argvars[0], rettv); + tv_list_insert_tv(l, &argvars[1], item); + tv_copy(&argvars[0], rettv); } } } @@ -12012,7 +11281,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_invert(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = ~get_tv_number_chk(&argvars[0], NULL); + rettv->vval.v_number = ~tv_get_number_chk(&argvars[0], NULL); } /* @@ -12020,7 +11289,7 @@ static void f_invert(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_isdirectory(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = os_isdir(get_tv_string(&argvars[0])); + rettv->vval.v_number = os_isdir((const char_u *)tv_get_string(&argvars[0])); } /* @@ -12029,41 +11298,39 @@ static void f_isdirectory(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr) { lval_T lv; - char_u *end; dictitem_T *di; rettv->vval.v_number = -1; - end = get_lval(get_tv_string(&argvars[0]), NULL, &lv, FALSE, FALSE, - GLV_NO_AUTOLOAD, FNE_CHECK_START); + const char_u *const end = get_lval((char_u *)tv_get_string(&argvars[0]), + NULL, + &lv, false, false, + GLV_NO_AUTOLOAD|GLV_READ_ONLY, + FNE_CHECK_START); if (end != NULL && lv.ll_name != NULL) { - if (*end != NUL) + if (*end != NUL) { EMSG(_(e_trailing)); - else { + } else { if (lv.ll_tv == NULL) { - if (check_changedtick(lv.ll_name)) - rettv->vval.v_number = 1; /* always locked */ - else { - di = find_var(lv.ll_name, NULL, TRUE); - if (di != NULL) { - /* Consider a variable locked when: - * 1. the variable itself is locked - * 2. the value of the variable is locked. - * 3. the List or Dict value is locked. - */ - rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK) - || tv_islocked(&di->di_tv)); - } + di = find_var((const char *)lv.ll_name, lv.ll_name_len, NULL, true); + if (di != NULL) { + // Consider a variable locked when: + // 1. the variable itself is locked + // 2. the value of the variable is locked. + // 3. the List or Dict value is locked. + rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK) + || tv_islocked(&di->di_tv)); } - } else if (lv.ll_range) + } else if (lv.ll_range) { EMSG(_("E786: Range not allowed")); - else if (lv.ll_newkey != NULL) + } else if (lv.ll_newkey != NULL) { EMSG2(_(e_dictkey), lv.ll_newkey); - else if (lv.ll_list != NULL) - /* List item. */ + } else if (lv.ll_list != NULL) { + // List item. rettv->vval.v_number = tv_islocked(&lv.ll_li->li_tv); - else - /* Dictionary item. */ + } else { + // Dictionary item. rettv->vval.v_number = tv_islocked(&lv.ll_di->di_tv); + } } } @@ -12071,68 +11338,71 @@ static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr) } -/* - * Turn a dict into a list: - * "what" == 0: list of keys - * "what" == 1: list of values - * "what" == 2: list of items - */ -static void dict_list(typval_T *argvars, typval_T *rettv, int what) -{ - list_T *l2; - dictitem_T *di; - hashitem_T *hi; - listitem_T *li; - listitem_T *li2; - dict_T *d; - int todo; - - if (argvars[0].v_type != VAR_DICT) { - EMSG(_(e_dictreq)); +/// Turn a dictionary into a list +/// +/// @param[in] tv Dictionary to convert. Is checked for actually being +/// a dictionary, will give an error if not. +/// @param[out] rettv Location where result will be saved. +/// @param[in] what What to save in rettv. +static void dict_list(typval_T *const tv, typval_T *const rettv, + const DictListType what) +{ + if (tv->v_type != VAR_DICT) { + emsgf(_(e_dictreq)); return; } - if ((d = argvars[0].vval.v_dict) == NULL) + if (tv->vval.v_dict == NULL) { return; + } - rettv_list_alloc(rettv); - - todo = (int)d->dv_hashtab.ht_used; - for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - di = HI2DI(hi); + tv_list_alloc_ret(rettv); - li = listitem_alloc(); - list_append(rettv->vval.v_list, li); + TV_DICT_ITER(tv->vval.v_dict, di, { + listitem_T *const li = tv_list_item_alloc(); + tv_list_append(rettv->vval.v_list, li); - if (what == 0) { - /* keys() */ + switch (what) { + case kDictListKeys: { li->li_tv.v_type = VAR_STRING; - li->li_tv.v_lock = 0; + li->li_tv.v_lock = VAR_UNLOCKED; li->li_tv.vval.v_string = vim_strsave(di->di_key); - } else if (what == 1) { - /* values() */ - copy_tv(&di->di_tv, &li->li_tv); - } else { - /* items() */ - l2 = list_alloc(); + break; + } + case kDictListValues: { + tv_copy(&di->di_tv, &li->li_tv); + break; + } + case kDictListItems: { + // items() + list_T *const sub_l = tv_list_alloc(); li->li_tv.v_type = VAR_LIST; - li->li_tv.v_lock = 0; - li->li_tv.vval.v_list = l2; - ++l2->lv_refcount; - - li2 = listitem_alloc(); - list_append(l2, li2); - li2->li_tv.v_type = VAR_STRING; - li2->li_tv.v_lock = 0; - li2->li_tv.vval.v_string = vim_strsave(di->di_key); - - li2 = listitem_alloc(); - list_append(l2, li2); - copy_tv(&di->di_tv, &li2->li_tv); + li->li_tv.v_lock = VAR_UNLOCKED; + li->li_tv.vval.v_list = sub_l; + sub_l->lv_refcount++; + + listitem_T *sub_li = tv_list_item_alloc(); + tv_list_append(sub_l, sub_li); + sub_li->li_tv.v_type = VAR_STRING; + sub_li->li_tv.v_lock = VAR_UNLOCKED; + sub_li->li_tv.vval.v_string = vim_strsave(di->di_key); + + sub_li = tv_list_item_alloc(); + tv_list_append(sub_l, sub_li); + tv_copy(&di->di_tv, &sub_li->li_tv); + break; } } - } + }); +} + +/// "id()" function +static void f_id(typval_T *argvars, typval_T *rettv, FunPtr fptr) + FUNC_ATTR_NONNULL_ALL +{ + const int len = vim_vsnprintf(NULL, 0, "%p", dummy_ap, argvars); + rettv->v_type = VAR_STRING; + rettv->vval.v_string = xmalloc(len + 1); + vim_vsnprintf((char *)rettv->vval.v_string, len + 1, "%p", dummy_ap, argvars); } /* @@ -12263,8 +11533,8 @@ static void f_jobsend(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - ssize_t input_len; - char *input = (char *) save_tv_as_string(&argvars[1], &input_len, false); + ptrdiff_t input_len = 0; + char *input = save_tv_as_string(&argvars[1], &input_len, false); if (!input) { // Either the error has been handled by save_tv_as_string(), or there is no // input to send. @@ -12309,10 +11579,10 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = 1; } -static char **tv_to_argv(typval_T *cmd_tv, char **cmd, bool *executable) +static char **tv_to_argv(typval_T *cmd_tv, const char **cmd, bool *executable) { if (cmd_tv->v_type == VAR_STRING) { - char *cmd_str = (char *)get_tv_string(cmd_tv); + const char *cmd_str = tv_get_string(cmd_tv); if (cmd) { *cmd = cmd_str; } @@ -12333,8 +11603,8 @@ static char **tv_to_argv(typval_T *cmd_tv, char **cmd, bool *executable) assert(argl->lv_first); - const char_u *exe = get_tv_string_chk(&argl->lv_first->li_tv); - if (!exe || !os_can_exe(exe, NULL, true)) { + const char *exe = tv_get_string_chk(&argl->lv_first->li_tv); + if (!exe || !os_can_exe((const char_u *)exe, NULL, true)) { if (exe && executable) { *executable = false; } @@ -12342,16 +11612,16 @@ static char **tv_to_argv(typval_T *cmd_tv, char **cmd, bool *executable) } if (cmd) { - *cmd = (char *)exe; + *cmd = exe; } // Build the argument vector int i = 0; char **argv = xcalloc(argc + 1, sizeof(char *)); for (listitem_T *arg = argl->lv_first; arg != NULL; arg = arg->li_next) { - char *a = (char *)get_tv_string_chk(&arg->li_tv); + const char *a = tv_get_string_chk(&arg->li_tv); if (!a) { - // Did emsg in get_tv_string; just deallocate argv. + // Did emsg in tv_get_string_chk; just deallocate argv. shell_free_argv(argv); return NULL; } @@ -12387,23 +11657,26 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) dict_T *job_opts = NULL; - bool detach = false, rpc = false, pty = false; - Callback on_stdout = CALLBACK_NONE, on_stderr = CALLBACK_NONE, - on_exit = CALLBACK_NONE; + bool detach = false; + bool rpc = false; + bool pty = false; + Callback on_stdout = CALLBACK_NONE; + Callback on_stderr = CALLBACK_NONE; + Callback on_exit = CALLBACK_NONE; char *cwd = NULL; if (argvars[1].v_type == VAR_DICT) { job_opts = argvars[1].vval.v_dict; - detach = get_dict_number(job_opts, "detach") != 0; - rpc = get_dict_number(job_opts, "rpc") != 0; - pty = get_dict_number(job_opts, "pty") != 0; + detach = tv_dict_get_number(job_opts, "detach") != 0; + rpc = tv_dict_get_number(job_opts, "rpc") != 0; + pty = tv_dict_get_number(job_opts, "pty") != 0; if (pty && rpc) { EMSG2(_(e_invarg2), "job cannot have both 'pty' and 'rpc' options set"); shell_free_argv(argv); return; } - char *new_cwd = (char *)get_dict_string(job_opts, "cwd", false); + char *new_cwd = tv_dict_get_string(job_opts, "cwd", false); if (new_cwd && strlen(new_cwd) > 0) { cwd = new_cwd; // The new cwd must be a directory. @@ -12425,15 +11698,15 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) Process *proc = (Process *)&data->proc; if (pty) { - uint16_t width = get_dict_number(job_opts, "width"); + uint16_t width = (uint16_t)tv_dict_get_number(job_opts, "width"); if (width > 0) { data->proc.pty.width = width; } - uint16_t height = get_dict_number(job_opts, "height"); + uint16_t height = (uint16_t)tv_dict_get_number(job_opts, "height"); if (height > 0) { data->proc.pty.height = height; } - char *term = (char *)get_dict_string(job_opts, "TERM", true); + char *term = tv_dict_get_string(job_opts, "TERM", true); if (term) { data->proc.pty.term_name = term; } @@ -12493,7 +11766,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) } list_T *args = argvars[0].vval.v_list; - list_T *rv = list_alloc(); + list_T *rv = tv_list_alloc(); ui_busy_start(); MultiQueue *waiting_jobs = multiqueue_new_parent(loop_on_put, &main_loop); @@ -12504,11 +11777,11 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) TerminalJobData *data = NULL; if (arg->li_tv.v_type != VAR_NUMBER || !(data = find_job(arg->li_tv.vval.v_number))) { - list_append_number(rv, -3); + tv_list_append_number(rv, -3); } else { // append the list item and set the status pointer so we'll collect the // status code when the job exits - list_append_number(rv, -1); + tv_list_append_number(rv, -1); data->status_ptr = &rv->lv_last->li_tv.vval.v_number; // Process any pending events for the job because we'll temporarily // replace the parent queue @@ -12589,50 +11862,49 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_join(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - garray_T ga; - char_u *sep; - if (argvars[0].v_type != VAR_LIST) { EMSG(_(e_listreq)); return; } - if (argvars[0].vval.v_list == NULL) + if (argvars[0].vval.v_list == NULL) { return; - if (argvars[1].v_type == VAR_UNKNOWN) - sep = (char_u *)" "; - else - sep = get_tv_string_chk(&argvars[1]); + } + const char *const sep = (argvars[1].v_type == VAR_UNKNOWN + ? " " + : tv_get_string_chk(&argvars[1])); rettv->v_type = VAR_STRING; if (sep != NULL) { + garray_T ga; ga_init(&ga, (int)sizeof(char), 80); - list_join(&ga, argvars[0].vval.v_list, (char *) sep); + tv_list_join(&ga, argvars[0].vval.v_list, sep); ga_append(&ga, NUL); rettv->vval.v_string = (char_u *)ga.ga_data; - } else + } else { rettv->vval.v_string = NULL; + } } /// json_decode() function static void f_json_decode(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char numbuf[NUMBUFLEN]; - char *s = NULL; + const char *s = NULL; char *tofree = NULL; size_t len; if (argvars[0].v_type == VAR_LIST) { - if (!encode_vim_list_to_buf(argvars[0].vval.v_list, &len, &s)) { + if (!encode_vim_list_to_buf(argvars[0].vval.v_list, &len, &tofree)) { EMSG(_("E474: Failed to convert list to string")); return; } - tofree = s; + s = tofree; if (s == NULL) { assert(len == 0); s = ""; } } else { - s = (char *) get_tv_string_buf_chk(&argvars[0], (char_u *) numbuf); + s = tv_get_string_buf_chk(&argvars[0], numbuf); if (s) { len = strlen(s); } else { @@ -12685,24 +11957,28 @@ static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_len(typval_T *argvars, typval_T *rettv, FunPtr fptr) { switch (argvars[0].v_type) { - case VAR_STRING: - case VAR_NUMBER: - rettv->vval.v_number = (varnumber_T)STRLEN( - get_tv_string(&argvars[0])); - break; - case VAR_LIST: - rettv->vval.v_number = list_len(argvars[0].vval.v_list); - break; - case VAR_DICT: - rettv->vval.v_number = dict_len(argvars[0].vval.v_dict); - break; - case VAR_UNKNOWN: - case VAR_SPECIAL: - case VAR_FLOAT: - case VAR_FUNC: - case VAR_PARTIAL: - EMSG(_("E701: Invalid type for len()")); - break; + case VAR_STRING: + case VAR_NUMBER: { + rettv->vval.v_number = (varnumber_T)strlen( + tv_get_string(&argvars[0])); + break; + } + case VAR_LIST: { + rettv->vval.v_number = tv_list_len(argvars[0].vval.v_list); + break; + } + case VAR_DICT: { + rettv->vval.v_number = tv_dict_len(argvars[0].vval.v_dict); + break; + } + case VAR_UNKNOWN: + case VAR_SPECIAL: + case VAR_FLOAT: + case VAR_PARTIAL: + case VAR_FUNC: { + EMSG(_("E701: Invalid type for len()")); + break; + } } } @@ -12787,15 +12063,15 @@ static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_line2byte(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; - - lnum = get_tv_lnum(argvars); - if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1) + const linenr_T lnum = tv_get_lnum(argvars); + if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1) { rettv->vval.v_number = -1; - else + } else { rettv->vval.v_number = ml_find_line_or_offset(curbuf, lnum, NULL); - if (rettv->vval.v_number >= 0) - ++rettv->vval.v_number; + } + if (rettv->vval.v_number >= 0) { + rettv->vval.v_number++; + } } /* @@ -12803,17 +12079,15 @@ static void f_line2byte(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_lispindent(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - pos_T pos; - linenr_T lnum; - - pos = curwin->w_cursor; - lnum = get_tv_lnum(argvars); + const pos_T pos = curwin->w_cursor; + const linenr_T lnum = tv_get_lnum(argvars); if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) { curwin->w_cursor.lnum = lnum; rettv->vval.v_number = get_lisp_indent(); curwin->w_cursor = pos; - } else + } else { rettv->vval.v_number = -1; + } } /* @@ -12827,71 +12101,117 @@ static void f_localtime(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) { - char_u *keys; - char_u *which; - char_u buf[NUMBUFLEN]; - char_u *keys_buf = NULL; - char_u *rhs; + char_u *keys_buf = NULL; + char_u *rhs; int mode; int abbr = FALSE; int get_dict = FALSE; mapblock_T *mp; int buffer_local; - /* return empty string for failure */ + // Return empty string for failure. rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - keys = get_tv_string(&argvars[0]); - if (*keys == NUL) + char_u *keys = (char_u *)tv_get_string(&argvars[0]); + if (*keys == NUL) { return; + } + char buf[NUMBUFLEN]; + const char *which; if (argvars[1].v_type != VAR_UNKNOWN) { - which = get_tv_string_buf_chk(&argvars[1], buf); + which = tv_get_string_buf_chk(&argvars[1], buf); if (argvars[2].v_type != VAR_UNKNOWN) { - abbr = get_tv_number(&argvars[2]); - if (argvars[3].v_type != VAR_UNKNOWN) - get_dict = get_tv_number(&argvars[3]); + abbr = tv_get_number(&argvars[2]); + if (argvars[3].v_type != VAR_UNKNOWN) { + get_dict = tv_get_number(&argvars[3]); + } } - } else - which = (char_u *)""; - if (which == NULL) + } else { + which = ""; + } + if (which == NULL) { return; + } - mode = get_map_mode(&which, 0); + mode = get_map_mode((char_u **)&which, 0); - keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, false, + keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, true, CPO_TO_CPO_FLAGS); rhs = check_map(keys, mode, exact, false, abbr, &mp, &buffer_local); xfree(keys_buf); if (!get_dict) { - /* Return a string. */ - if (rhs != NULL) - rettv->vval.v_string = str2special_save(rhs, FALSE); + // Return a string. + if (rhs != NULL) { + rettv->vval.v_string = (char_u *)str2special_save( + (const char *)rhs, false, false); + } } else { - rettv_dict_alloc(rettv); + tv_dict_alloc_ret(rettv); if (rhs != NULL) { // Return a dictionary. - char_u *lhs = str2special_save(mp->m_keys, TRUE); - char_u *mapmode = map_mode_to_chars(mp->m_mode); - dict_T *dict = rettv->vval.v_dict; + mapblock_fill_dict(rettv->vval.v_dict, mp, buffer_local, true); + } + } +} + +/// luaeval() function implementation +static void f_luaeval(typval_T *argvars, typval_T *rettv, FunPtr fptr) + FUNC_ATTR_NONNULL_ALL +{ + const char *const str = (const char *)tv_get_string_chk(&argvars[0]); + if (str == NULL) { + return; + } - dict_add_nr_str(dict, "lhs", 0L, lhs); - dict_add_nr_str(dict, "rhs", 0L, mp->m_orig_str); - dict_add_nr_str(dict, "noremap", mp->m_noremap ? 1L : 0L, NULL); - dict_add_nr_str(dict, "expr", mp->m_expr ? 1L : 0L, NULL); - dict_add_nr_str(dict, "silent", mp->m_silent ? 1L : 0L, NULL); - dict_add_nr_str(dict, "sid", (long)mp->m_script_ID, NULL); - dict_add_nr_str(dict, "buffer", (long)buffer_local, NULL); - dict_add_nr_str(dict, "nowait", mp->m_nowait ? 1L : 0L, NULL); - dict_add_nr_str(dict, "mode", 0L, mapmode); + executor_eval_lua(cstr_as_string((char *)str), &argvars[1], rettv); +} - xfree(lhs); - xfree(mapmode); - } +/// Fill a dictionary with all applicable maparg() like dictionaries +/// +/// @param dict The dictionary to be filled +/// @param mp The maphash that contains the mapping information +/// @param buffer_value The "buffer" value +/// @param compatible True for compatible with old maparg() dict +void mapblock_fill_dict(dict_T *const dict, + const mapblock_T *const mp, + long buffer_value, + bool compatible) + FUNC_ATTR_NONNULL_ALL +{ + char *const lhs = str2special_save((const char *)mp->m_keys, + compatible, !compatible); + char *const mapmode = map_mode_to_chars(mp->m_mode); + varnumber_T noremap_value; + + if (compatible) { + // Keep old compatible behavior + // This is unable to determine whether a mapping is a <script> mapping + noremap_value = !!mp->m_noremap; + } else { + // Distinguish between <script> mapping + // If it's not a <script> mapping, check if it's a noremap + noremap_value = mp->m_noremap == REMAP_SCRIPT ? 2 : !!mp->m_noremap; } + + if (compatible) { + tv_dict_add_str(dict, S_LEN("rhs"), (const char *)mp->m_orig_str); + } else { + tv_dict_add_allocated_str(dict, S_LEN("rhs"), + str2special_save((const char *)mp->m_str, false, + true)); + } + tv_dict_add_allocated_str(dict, S_LEN("lhs"), lhs); + tv_dict_add_nr(dict, S_LEN("noremap"), noremap_value); + tv_dict_add_nr(dict, S_LEN("expr"), mp->m_expr ? 1 : 0); + tv_dict_add_nr(dict, S_LEN("silent"), mp->m_silent ? 1 : 0); + tv_dict_add_nr(dict, S_LEN("sid"), (varnumber_T)mp->m_script_ID); + tv_dict_add_nr(dict, S_LEN("buffer"), (varnumber_T)buffer_value); + tv_dict_add_nr(dict, S_LEN("nowait"), mp->m_nowait ? 1 : 0); + tv_dict_add_allocated_str(dict, S_LEN("mode"), mapmode); } /* @@ -12924,9 +12244,7 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) char_u *str = NULL; long len = 0; char_u *expr = NULL; - char_u *pat; regmatch_T regmatch; - char_u patbuf[NUMBUFLEN]; char_u *save_cpo; long start = 0; long nth = 1; @@ -12945,12 +12263,12 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) if (type == 3 || type == 4) { // type 3: return empty list when there are no matches. // type 4: return ["", -1, -1, -1] - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (type == 4) { - list_append_string(rettv->vval.v_list, (char_u *)"", 0); - list_append_number(rettv->vval.v_list, (varnumber_T)-1); - list_append_number(rettv->vval.v_list, (varnumber_T)-1); - list_append_number(rettv->vval.v_list, (varnumber_T)-1); + tv_list_append_string(rettv->vval.v_list, "", 0); + tv_list_append_number(rettv->vval.v_list, -1); + tv_list_append_number(rettv->vval.v_list, -1); + tv_list_append_number(rettv->vval.v_list, -1); } } else if (type == 2) { rettv->v_type = VAR_STRING; @@ -12962,25 +12280,29 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) goto theend; li = l->lv_first; } else { - expr = str = get_tv_string(&argvars[0]); + expr = str = (char_u *)tv_get_string(&argvars[0]); len = (long)STRLEN(str); } - pat = get_tv_string_buf_chk(&argvars[1], patbuf); - if (pat == NULL) + char patbuf[NUMBUFLEN]; + const char *const pat = tv_get_string_buf_chk(&argvars[1], patbuf); + if (pat == NULL) { goto theend; + } if (argvars[2].v_type != VAR_UNKNOWN) { - int error = FALSE; + bool error = false; - start = get_tv_number_chk(&argvars[2], &error); - if (error) + start = tv_get_number_chk(&argvars[2], &error); + if (error) { goto theend; + } if (l != NULL) { - li = list_find(l, start); - if (li == NULL) + li = tv_list_find(l, start); + if (li == NULL) { goto theend; - idx = l->lv_idx; /* use the cached index */ + } + idx = l->lv_idx; // Use the cached index. } else { if (start < 0) start = 0; @@ -12997,13 +12319,15 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) } } - if (argvars[3].v_type != VAR_UNKNOWN) - nth = get_tv_number_chk(&argvars[3], &error); - if (error) + if (argvars[3].v_type != VAR_UNKNOWN) { + nth = tv_get_number_chk(&argvars[3], &error); + } + if (error) { goto theend; + } } - regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); + regmatch.regprog = vim_regcomp((char_u *)pat, RE_MAGIC + RE_STRING); if (regmatch.regprog != NULL) { regmatch.rm_ic = p_ic; @@ -13062,29 +12386,32 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) /* return list with matched string and submatches */ for (i = 0; i < NSUBEXP; ++i) { if (regmatch.endp[i] == NULL) { - list_append_string(rettv->vval.v_list, (char_u *)"", 0); + tv_list_append_string(rettv->vval.v_list, NULL, 0); } else { - list_append_string(rettv->vval.v_list, - regmatch.startp[i], - (int)(regmatch.endp[i] - regmatch.startp[i])); + tv_list_append_string(rettv->vval.v_list, + (const char *)regmatch.startp[i], + (regmatch.endp[i] - regmatch.startp[i])); } } } else if (type == 2) { - /* return matched string */ - if (l != NULL) - copy_tv(&li->li_tv, rettv); - else - rettv->vval.v_string = vim_strnsave(regmatch.startp[0], - (int)(regmatch.endp[0] - regmatch.startp[0])); - } else if (l != NULL) + // Return matched string. + if (l != NULL) { + tv_copy(&li->li_tv, rettv); + } else { + rettv->vval.v_string = (char_u *)xmemdupz( + (const char *)regmatch.startp[0], + (size_t)(regmatch.endp[0] - regmatch.startp[0])); + } + } else if (l != NULL) { rettv->vval.v_number = idx; - else { - if (type != 0) + } else { + if (type != 0) { rettv->vval.v_number = (varnumber_T)(regmatch.startp[0] - str); - else + } else { rettv->vval.v_number = (varnumber_T)(regmatch.endp[0] - str); + } rettv->vval.v_number += (varnumber_T)(str - expr); } } @@ -13093,7 +12420,8 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) if (type == 4 && l == NULL) { // matchstrpos() without a list: drop the second item - listitem_remove(rettv->vval.v_list, rettv->vval.v_list->lv_first->li_next); + tv_list_item_remove(rettv->vval.v_list, + rettv->vval.v_list->lv_first->li_next); } theend: @@ -13114,40 +12442,42 @@ static void f_match(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u buf[NUMBUFLEN]; - char_u *grp = get_tv_string_buf_chk(&argvars[0], buf); /* group */ - char_u *pat = get_tv_string_buf_chk(&argvars[1], buf); /* pattern */ - int prio = 10; /* default priority */ + char grpbuf[NUMBUFLEN]; + char patbuf[NUMBUFLEN]; + const char *const grp = tv_get_string_buf_chk(&argvars[0], grpbuf); + const char *const pat = tv_get_string_buf_chk(&argvars[1], patbuf); + int prio = 10; int id = -1; - int error = false; - char_u *conceal_char = NULL; + bool error = false; + const char *conceal_char = NULL; rettv->vval.v_number = -1; - if (grp == NULL || pat == NULL) + if (grp == NULL || pat == NULL) { return; + } if (argvars[2].v_type != VAR_UNKNOWN) { - prio = get_tv_number_chk(&argvars[2], &error); + prio = tv_get_number_chk(&argvars[2], &error); if (argvars[3].v_type != VAR_UNKNOWN) { - id = get_tv_number_chk(&argvars[3], &error); + id = tv_get_number_chk(&argvars[3], &error); if (argvars[4].v_type != VAR_UNKNOWN) { if (argvars[4].v_type != VAR_DICT) { EMSG(_(e_dictreq)); return; } - if (dict_find(argvars[4].vval.v_dict, - (char_u *)"conceal", -1) != NULL) { - conceal_char = get_dict_string(argvars[4].vval.v_dict, - "conceal", false); + dictitem_T *di; + if ((di = tv_dict_find(argvars[4].vval.v_dict, S_LEN("conceal"))) + != NULL) { + conceal_char = tv_get_string(&di->di_tv); } } } } - if (error == true) { + if (error) { return; } if (id >= 1 && id <= 3) { - EMSGN("E798: ID is reserved for \":match\": %" PRId64, id); + EMSGN(_("E798: ID is reserved for \":match\": %" PRId64), id); return; } @@ -13158,10 +12488,9 @@ static void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = -1; - - char_u buf[NUMBUFLEN]; - char_u *group; - group = get_tv_string_buf_chk(&argvars[0], buf); + + char buf[NUMBUFLEN]; + const char *const group = tv_get_string_buf_chk(&argvars[0], buf); if (group == NULL) { return; } @@ -13177,24 +12506,24 @@ static void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - int error = false; + bool error = false; int prio = 10; int id = -1; - char_u *conceal_char = NULL; + const char *conceal_char = NULL; if (argvars[2].v_type != VAR_UNKNOWN) { - prio = get_tv_number_chk(&argvars[2], &error); + prio = tv_get_number_chk(&argvars[2], &error); if (argvars[3].v_type != VAR_UNKNOWN) { - id = get_tv_number_chk(&argvars[3], &error); + id = tv_get_number_chk(&argvars[3], &error); if (argvars[4].v_type != VAR_UNKNOWN) { if (argvars[4].v_type != VAR_DICT) { EMSG(_(e_dictreq)); return; } - if (dict_find(argvars[4].vval.v_dict, - (char_u *)"conceal", -1) != NULL) { - conceal_char = get_dict_string(argvars[4].vval.v_dict, - "conceal", false); + dictitem_T *di; + if ((di = tv_dict_find(argvars[4].vval.v_dict, S_LEN("conceal"))) + != NULL) { + conceal_char = tv_get_string(&di->di_tv); } } } @@ -13205,7 +12534,7 @@ static void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) // id == 3 is ok because matchaddpos() is supposed to substitute :3match if (id == 1 || id == 2) { - EMSGN("E798: ID is reserved for \"match\": %" PRId64, id); + EMSGN(_("E798: ID is reserved for \"match\": %" PRId64), id); return; } @@ -13218,19 +12547,20 @@ static void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_matcharg(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); - int id = get_tv_number(&argvars[0]); + int id = tv_get_number(&argvars[0]); if (id >= 1 && id <= 3) { matchitem_T *m; if ((m = (matchitem_T *)get_match(curwin, id)) != NULL) { - list_append_string(rettv->vval.v_list, syn_id2name(m->hlg_id), -1); - list_append_string(rettv->vval.v_list, m->pattern, -1); + tv_list_append_string(rettv->vval.v_list, + (const char *)syn_id2name(m->hlg_id), -1); + tv_list_append_string(rettv->vval.v_list, (const char *)m->pattern, -1); } else { - list_append_string(rettv->vval.v_list, NULL, -1); - list_append_string(rettv->vval.v_list, NULL, -1); + tv_list_append_string(rettv->vval.v_list, NULL, 0); + tv_list_append_string(rettv->vval.v_list, NULL, 0); } } } @@ -13241,7 +12571,7 @@ static void f_matcharg(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_matchdelete(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = match_delete(curwin, - (int)get_tv_number(&argvars[0]), TRUE); + (int)tv_get_number(&argvars[0]), true); } /* @@ -13274,54 +12604,53 @@ static void f_matchstrpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) find_some_match(argvars, rettv, 4); } -static void max_min(typval_T *argvars, typval_T *rettv, int domax) +/// Get maximal/minimal number value in a list or dictionary +/// +/// @param[in] tv List or dictionary to work with. If it contains something +/// that is not an integer number (or cannot be coerced to +/// it) error is given. +/// @param[out] rettv Location where result will be saved. Only assigns +/// vval.v_number, type is not touched. Returns zero for +/// empty lists/dictionaries. +/// @param[in] domax Determines whether maximal or minimal value is desired. +static void max_min(const typval_T *const tv, typval_T *const rettv, + const bool domax) + FUNC_ATTR_NONNULL_ALL { - long n = 0; - long i; - int error = FALSE; + varnumber_T n = 0; + bool error = false; - if (argvars[0].v_type == VAR_LIST) { - list_T *l; - listitem_T *li; - - l = argvars[0].vval.v_list; - if (l != NULL) { - li = l->lv_first; - if (li != NULL) { - n = get_tv_number_chk(&li->li_tv, &error); - for (;; ) { - li = li->li_next; - if (li == NULL) - break; - i = get_tv_number_chk(&li->li_tv, &error); - if (domax ? i > n : i < n) - n = i; + if (tv->v_type == VAR_LIST) { + const list_T *const l = tv->vval.v_list; + if (tv_list_len(l) != 0) { + n = tv_get_number_chk(&l->lv_first->li_tv, &error); + for (const listitem_T *li = l->lv_first->li_next; li != NULL && !error; + li = li->li_next) { + const varnumber_T i = tv_get_number_chk(&li->li_tv, &error); + if (domax ? i > n : i < n) { + n = i; } } } - } else if (argvars[0].v_type == VAR_DICT) { - dict_T *d; - int first = TRUE; - hashitem_T *hi; - int todo; - - d = argvars[0].vval.v_dict; - if (d != NULL) { - todo = (int)d->dv_hashtab.ht_used; - for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - i = get_tv_number_chk(&HI2DI(hi)->di_tv, &error); - if (first) { - n = i; - first = FALSE; - } else if (domax ? i > n : i < n) - n = i; + } else if (tv->v_type == VAR_DICT) { + if (tv->vval.v_dict != NULL) { + bool first = true; + TV_DICT_ITER(tv->vval.v_dict, di, { + const varnumber_T i = tv_get_number_chk(&di->di_tv, &error); + if (error) { + break; } - } + if (first) { + n = i; + first = true; + } else if (domax ? i > n : i < n) { + n = i; + } + }); } - } else - EMSG(_(e_listdictarg)); + } else { + EMSG2(_(e_listdictarg), domax ? "max()" : "min()"); + } rettv->vval.v_number = error ? 0 : n; } @@ -13346,28 +12675,29 @@ static void f_min(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_mkdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *dir; - char_u buf[NUMBUFLEN]; - int prot = 0755; + int prot = 0755; // -V536 rettv->vval.v_number = FAIL; if (check_restricted() || check_secure()) return; - dir = get_tv_string_buf(&argvars[0], buf); - if (*dir == NUL) + char buf[NUMBUFLEN]; + const char *const dir = tv_get_string_buf(&argvars[0], buf); + if (*dir == NUL) { rettv->vval.v_number = FAIL; - else { - if (*path_tail(dir) == NUL) - /* remove trailing slashes */ - *path_tail_with_sep(dir) = NUL; + } else { + if (*path_tail((char_u *)dir) == NUL) { + // Remove trailing slashes. + *path_tail_with_sep((char_u *)dir) = NUL; + } if (argvars[1].v_type != VAR_UNKNOWN) { - if (argvars[2].v_type != VAR_UNKNOWN) - prot = get_tv_number_chk(&argvars[2], NULL); - if (prot != -1 && STRCMP(get_tv_string(&argvars[1]), "p") == 0) { + if (argvars[2].v_type != VAR_UNKNOWN) { + prot = tv_get_number_chk(&argvars[2], NULL); + } + if (prot != -1 && strcmp(tv_get_string(&argvars[1]), "p") == 0) { char *failed_dir; - int ret = os_mkdir_recurse((char *) dir, prot, &failed_dir); + int ret = os_mkdir_recurse(dir, prot, &failed_dir); if (ret != 0) { EMSG3(_(e_mkdir), failed_dir, os_strerror(ret)); xfree(failed_dir); @@ -13383,59 +12713,18 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "mode()" function - */ +/// "mode()" function static void f_mode(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u buf[3]; - - buf[1] = NUL; - buf[2] = NUL; + char *mode = get_mode(); - if (VIsual_active) { - if (VIsual_select) - buf[0] = VIsual_mode + 's' - 'v'; - else - buf[0] = VIsual_mode; - } else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE - || State == CONFIRM) { - buf[0] = 'r'; - if (State == ASKMORE) - buf[1] = 'm'; - else if (State == CONFIRM) - buf[1] = '?'; - } else if (State == EXTERNCMD) - buf[0] = '!'; - else if (State & INSERT) { - if (State & VREPLACE_FLAG) { - buf[0] = 'R'; - buf[1] = 'v'; - } else if (State & REPLACE_FLAG) - buf[0] = 'R'; - else - buf[0] = 'i'; - } else if (State & CMDLINE) { - buf[0] = 'c'; - if (exmode_active) - buf[1] = 'v'; - } else if (exmode_active) { - buf[0] = 'c'; - buf[1] = 'e'; - } else if (State & TERM_FOCUS) { - buf[0] = 't'; - } else { - buf[0] = 'n'; - if (finish_op) - buf[1] = 'o'; + // Clear out the minor mode when the argument is not a non-zero number or + // non-empty string. + if (!non_zero_arg(&argvars[0])) { + mode[1] = NUL; } - /* Clear out the minor mode when the argument is not a non-zero number or - * non-empty string. */ - if (!non_zero_arg(&argvars[0])) - buf[1] = NUL; - - rettv->vval.v_string = vim_strsave(buf); + rettv->vval.v_string = (char_u *)mode; rettv->v_type = VAR_STRING; } @@ -13447,7 +12736,7 @@ static void f_msgpackdump(typval_T *argvars, typval_T *rettv, FunPtr fptr) EMSG2(_(e_listarg), "msgpackdump()"); return; } - list_T *ret_list = rettv_list_alloc(rettv); + list_T *ret_list = tv_list_alloc_ret(rettv); const list_T *list = argvars[0].vval.v_list; if (list == NULL) { return; @@ -13475,7 +12764,7 @@ static void f_msgpackparse(typval_T *argvars, typval_T *rettv, FunPtr fptr) EMSG2(_(e_listarg), "msgpackparse()"); return; } - list_T *ret_list = rettv_list_alloc(rettv); + list_T *ret_list = tv_list_alloc_ret(rettv); const list_T *list = argvars[0].vval.v_list; if (list == NULL || list->lv_first == NULL) { return; @@ -13520,9 +12809,9 @@ static void f_msgpackparse(typval_T *argvars, typval_T *rettv, FunPtr fptr) goto f_msgpackparse_exit; } if (result == MSGPACK_UNPACK_SUCCESS) { - listitem_T *li = listitem_alloc(); + listitem_T *li = tv_list_item_alloc(); li->li_tv.v_type = VAR_UNKNOWN; - list_append(ret_list, li); + tv_list_append(ret_list, li); if (msgpack_to_vim(unpacked.data, &li->li_tv) == FAIL) { EMSG2(_(e_invarg2), "Failed to convert msgpack string"); goto f_msgpackparse_exit; @@ -13553,13 +12842,14 @@ static void f_nextnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum; - for (lnum = get_tv_lnum(argvars);; ++lnum) { + for (lnum = tv_get_lnum(argvars);; lnum++) { if (lnum < 0 || lnum > curbuf->b_ml.ml_line_count) { lnum = 0; break; } - if (*skipwhite(ml_get(lnum)) != NUL) + if (*skipwhite(ml_get(lnum)) != NUL) { break; + } } rettv->vval.v_number = lnum; } @@ -13569,23 +12859,32 @@ static void f_nextnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_nr2char(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u buf[NUMBUFLEN]; - - if (has_mbyte) { - int utf8 = 0; + if (argvars[1].v_type != VAR_UNKNOWN) { + if (!tv_check_num(&argvars[1])) { + return; + } + } - if (argvars[1].v_type != VAR_UNKNOWN) - utf8 = get_tv_number_chk(&argvars[1], NULL); - if (utf8) - buf[(*utf_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL; - else - buf[(*mb_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL; - } else { - buf[0] = (char_u)get_tv_number(&argvars[0]); - buf[1] = NUL; + bool error = false; + const varnumber_T num = tv_get_number_chk(&argvars[0], &error); + if (error) { + return; } + if (num < 0) { + emsgf(_("E5070: Character number must not be less than zero")); + return; + } + if (num > INT_MAX) { + emsgf(_("E5071: Character number must not be greater than INT_MAX (%i)"), + INT_MAX); + return; + } + + char buf[MB_MAXBYTES]; + const int len = utf_char2bytes((int)num, (char_u *)buf); + rettv->v_type = VAR_STRING; - rettv->vval.v_string = vim_strsave(buf); + rettv->vval.v_string = xmemdupz(buf, (size_t)len); } /* @@ -13593,8 +12892,8 @@ static void f_nr2char(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_or(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL) - | get_tv_number_chk(&argvars[1], NULL); + rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL) + | tv_get_number_chk(&argvars[1], NULL); } /* @@ -13603,11 +12902,11 @@ static void f_or(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_pathshorten(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = get_tv_string_chk(&argvars[0]); - if (!rettv->vval.v_string) { + const char *const s = tv_get_string_chk(&argvars[0]); + if (!s) { return; } - rettv->vval.v_string = shorten_dir(vim_strsave(rettv->vval.v_string)); + rettv->vval.v_string = shorten_dir((char_u *)xstrdup(s)); } /* @@ -13615,14 +12914,15 @@ static void f_pathshorten(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_pow(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - float_T fx, fy; + float_T fx; + float_T fy; rettv->v_type = VAR_FLOAT; - if (get_float_arg(argvars, &fx) == OK - && get_float_arg(&argvars[1], &fy) == OK) + if (tv_get_float_chk(argvars, &fx) && tv_get_float_chk(&argvars[1], &fy)) { rettv->vval.v_float = pow(fx, fy); - else + } else { rettv->vval.v_float = 0.0; + } } /* @@ -13630,23 +12930,17 @@ static void f_pow(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_prevnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; - - lnum = get_tv_lnum(argvars); - if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) + linenr_T lnum = tv_get_lnum(argvars); + if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) { lnum = 0; - else - while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL) - --lnum; + } else { + while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL) { + lnum--; + } + } rettv->vval.v_number = lnum; } -/* This dummy va_list is here because: - * - passing a NULL pointer doesn't work when va_list isn't a pointer - * - locally in the function results in a "used before set" warning - * - using va_start() to initialize it gives "function with fixed args" error */ -static va_list ap; - /* * "printf()" function */ @@ -13655,19 +12949,18 @@ static void f_printf(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; { - char_u buf[NUMBUFLEN]; int len; int saved_did_emsg = did_emsg; - char *fmt; - /* Get the required length, allocate the buffer and do it for real. */ - did_emsg = FALSE; - fmt = (char *)get_tv_string_buf(&argvars[0], buf); - len = vim_vsnprintf(NULL, 0, fmt, ap, argvars + 1); + // Get the required length, allocate the buffer and do it for real. + did_emsg = false; + char buf[NUMBUFLEN]; + const char *fmt = tv_get_string_buf(&argvars[0], buf); + len = vim_vsnprintf(NULL, 0, fmt, dummy_ap, argvars + 1); if (!did_emsg) { char *s = xmalloc(len + 1); rettv->vval.v_string = (char_u *)s; - (void)vim_vsnprintf(s, len + 1, fmt, ap, argvars + 1); + (void)vim_vsnprintf(s, len + 1, fmt, dummy_ap, argvars + 1); } did_emsg |= saved_did_emsg; } @@ -13703,32 +12996,34 @@ static void f_py3eval(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_range(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - long start; - long end; - long stride = 1; - long i; - int error = FALSE; + varnumber_T start; + varnumber_T end; + varnumber_T stride = 1; + varnumber_T i; + bool error = false; - start = get_tv_number_chk(&argvars[0], &error); + start = tv_get_number_chk(&argvars[0], &error); if (argvars[1].v_type == VAR_UNKNOWN) { end = start - 1; start = 0; } else { - end = get_tv_number_chk(&argvars[1], &error); - if (argvars[2].v_type != VAR_UNKNOWN) - stride = get_tv_number_chk(&argvars[2], &error); + end = tv_get_number_chk(&argvars[1], &error); + if (argvars[2].v_type != VAR_UNKNOWN) { + stride = tv_get_number_chk(&argvars[2], &error); + } } - if (error) - return; /* type error; errmsg already given */ - if (stride == 0) - EMSG(_("E726: Stride is zero")); - else if (stride > 0 ? end + 1 < start : end - 1 > start) - EMSG(_("E727: Start past end")); - else { - rettv_list_alloc(rettv); + if (error) { + return; // Type error; errmsg already given. + } + if (stride == 0) { + emsgf(_("E726: Stride is zero")); + } else if (stride > 0 ? end + 1 < start : end - 1 > start) { + emsgf(_("E727: Start past end")); + } else { + tv_list_alloc_ret(rettv); for (i = start; stride > 0 ? i <= end : i >= end; i += stride) { - list_append_number(rettv->vval.v_list, (varnumber_T)i); + tv_list_append_number(rettv->vval.v_list, (varnumber_T)i); } } } @@ -13738,8 +13033,7 @@ static void f_range(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int binary = FALSE; - char_u *fname; + bool binary = false; FILE *fd; char_u buf[(IOSIZE/256)*256]; /* rounded to avoid odd + 1 */ int io_size = sizeof(buf); @@ -13753,19 +13047,21 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) char_u *start; /* start of current line */ if (argvars[1].v_type != VAR_UNKNOWN) { - if (STRCMP(get_tv_string(&argvars[1]), "b") == 0) - binary = TRUE; - if (argvars[2].v_type != VAR_UNKNOWN) - maxline = get_tv_number(&argvars[2]); + if (strcmp(tv_get_string(&argvars[1]), "b") == 0) { + binary = true; + } + if (argvars[2].v_type != VAR_UNKNOWN) { + maxline = tv_get_number(&argvars[2]); + } } - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); - /* Always open the file in binary mode, library functions have a mind of - * their own about CR-LF conversion. */ - fname = get_tv_string(&argvars[0]); - if (*fname == NUL || (fd = mch_fopen((char *)fname, READBIN)) == NULL) { - EMSG2(_(e_notopen), *fname == NUL ? (char_u *)_("<empty>") : fname); + // Always open the file in binary mode, library functions have a mind of + // their own about CR-LF conversion. + const char *const fname = tv_get_string(&argvars[0]); + if (*fname == NUL || (fd = mch_fopen(fname, READBIN)) == NULL) { + EMSG2(_(e_notopen), *fname == NUL ? _("<empty>") : fname); return; } @@ -13808,11 +13104,11 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) prevlen = prevsize = 0; } - li = listitem_alloc(); + li = tv_list_item_alloc(); li->li_tv.v_type = VAR_STRING; li->li_tv.v_lock = 0; li->li_tv.vval.v_string = s; - list_append(rettv->vval.v_list, li); + tv_list_append(rettv->vval.v_list, li); start = p + 1; /* step over newline */ if ((++cnt >= maxline && maxline >= 0) || readlen <= 0) @@ -13842,8 +13138,9 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) /* have to shuffle buf to close gap */ int adjust_prevlen = 0; - if (dest < buf) { - adjust_prevlen = (int)(buf - dest); /* must be 1 or 2 */ + if (dest < buf) { // -V782 + adjust_prevlen = (int)(buf - dest); // -V782 + // adjust_prevlen must be 1 or 2. dest = buf; } if (readlen > p - buf + 1) @@ -13887,8 +13184,8 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ if (maxline < 0) while (cnt > -maxline) { - listitem_remove(rettv->vval.v_list, rettv->vval.v_list->lv_first); - --cnt; + tv_list_item_remove(rettv->vval.v_list, rettv->vval.v_list->lv_first); + cnt--; } xfree(prev); @@ -13910,9 +13207,9 @@ static int list2proftime(typval_T *arg, proftime_T *tm) FUNC_ATTR_NONNULL_ALL return FAIL; } - int error = false; - varnumber_T n1 = list_find_nr(arg->vval.v_list, 0L, &error); - varnumber_T n2 = list_find_nr(arg->vval.v_list, 1L, &error); + bool error = false; + varnumber_T n1 = tv_list_find_nr(arg->vval.v_list, 0L, &error); + varnumber_T n2 = tv_list_find_nr(arg->vval.v_list, 1L, &error); if (error) { return FAIL; } @@ -13920,7 +13217,7 @@ static int list2proftime(typval_T *arg, proftime_T *tm) FUNC_ATTR_NONNULL_ALL // in f_reltime() we split up the 64-bit proftime_T into two 32-bit // values, now we combine them again. union { - struct { varnumber_T low, high; } split; + struct { int32_t low, high; } split; proftime_T prof; } u = { .split.high = n1, .split.low = n2 }; @@ -13961,7 +13258,7 @@ static void f_reltime(typval_T *argvars, typval_T *rettv, FunPtr fptr) // (varnumber_T is defined as int). For all our supported platforms, int's // are at least 32-bits wide. So we'll use two 32-bit values to store it. union { - struct { varnumber_T low, high; } split; + struct { int32_t low, high; } split; proftime_T prof; } u = { .prof = res }; @@ -13971,9 +13268,9 @@ static void f_reltime(typval_T *argvars, typval_T *rettv, FunPtr fptr) STATIC_ASSERT(sizeof(u.prof) == sizeof(u) && sizeof(u.split) == sizeof(u), "type punning will produce incorrect results on this platform"); - rettv_list_alloc(rettv); - list_append_number(rettv->vval.v_list, u.split.high); - list_append_number(rettv->vval.v_list, u.split.low); + tv_list_alloc_ret(rettv); + tv_list_append_number(rettv->vval.v_list, u.split.high); + tv_list_append_number(rettv->vval.v_list, u.split.low); } /// f_reltimestr - return a string that represents the value of {time} @@ -14003,28 +13300,27 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) listitem_T *li; long idx; long end; - char_u *key; dict_T *d; dictitem_T *di; - char_u *arg_errmsg = (char_u *)N_("remove() argument"); + const char *const arg_errmsg = N_("remove() argument"); if (argvars[0].v_type == VAR_DICT) { if (argvars[2].v_type != VAR_UNKNOWN) { EMSG2(_(e_toomanyarg), "remove()"); } else if ((d = argvars[0].vval.v_dict) != NULL - && !tv_check_lock(d->dv_lock, arg_errmsg, true)) { - key = get_tv_string_chk(&argvars[1]); + && !tv_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE)) { + const char *key = tv_get_string_chk(&argvars[1]); if (key != NULL) { - di = dict_find(d, key, -1); + di = tv_dict_find(d, key, -1); if (di == NULL) { EMSG2(_(e_dictkey), key); - } else if (!var_check_fixed(di->di_flags, arg_errmsg, true) - && !var_check_ro(di->di_flags, arg_errmsg, true)) { + } else if (!var_check_fixed(di->di_flags, arg_errmsg, TV_TRANSLATE) + && !var_check_ro(di->di_flags, arg_errmsg, TV_TRANSLATE)) { *rettv = di->di_tv; - init_tv(&di->di_tv); - dictitem_remove(d, di); - if (is_watched(d)) { - dictwatcher_notify(d, (char *)key, NULL, rettv); + di->di_tv = TV_INITIAL_VALUE; + tv_dict_item_remove(d, di); + if (tv_dict_is_watched(d)) { + tv_dict_watcher_notify(d, key, NULL, rettv); } } } @@ -14032,28 +13328,28 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) } else if (argvars[0].v_type != VAR_LIST) { EMSG2(_(e_listdictarg), "remove()"); } else if ((l = argvars[0].vval.v_list) != NULL - && !tv_check_lock(l->lv_lock, arg_errmsg, true)) { - int error = (int)false; + && !tv_check_lock(l->lv_lock, arg_errmsg, TV_TRANSLATE)) { + bool error = false; - idx = get_tv_number_chk(&argvars[1], &error); - if (error) - ; /* type error: do nothing, errmsg already given */ - else if ((item = list_find(l, idx)) == NULL) + idx = tv_get_number_chk(&argvars[1], &error); + if (error) { + // Type error: do nothing, errmsg already given. + } else if ((item = tv_list_find(l, idx)) == NULL) { EMSGN(_(e_listidx), idx); - else { + } else { if (argvars[2].v_type == VAR_UNKNOWN) { // Remove one item, return its value. - vim_list_remove(l, item, item); + tv_list_remove_items(l, item, item); *rettv = item->li_tv; xfree(item); } else { - /* Remove range of items, return list with values. */ - end = get_tv_number_chk(&argvars[2], &error); - if (error) - ; /* type error: do nothing */ - else if ((item2 = list_find(l, end)) == NULL) + // Remove range of items, return list with values. + end = tv_get_number_chk(&argvars[2], &error); + if (error) { + // Type error: do nothing. + } else if ((item2 = tv_list_find(l, end)) == NULL) { EMSGN(_(e_listidx), end); - else { + } else { int cnt = 0; for (li = item; li != NULL; li = li->li_next) { @@ -14061,11 +13357,11 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (li == item2) break; } - if (li == NULL) /* didn't find "item2" after "item" */ - EMSG(_(e_invrange)); - else { - vim_list_remove(l, item, item2); - l = rettv_list_alloc(rettv); + if (li == NULL) { // Didn't find "item2" after "item". + emsgf(_(e_invrange)); + } else { + tv_list_remove_items(l, item, item2); + l = tv_list_alloc_ret(rettv); l->lv_first = item; l->lv_last = item2; item->li_prev = NULL; @@ -14083,13 +13379,14 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_rename(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u buf[NUMBUFLEN]; - - if (check_restricted() || check_secure()) + if (check_restricted() || check_secure()) { rettv->vval.v_number = -1; - else - rettv->vval.v_number = vim_rename(get_tv_string(&argvars[0]), - get_tv_string_buf(&argvars[1], buf)); + } else { + char buf[NUMBUFLEN]; + rettv->vval.v_number = vim_rename( + (const char_u *)tv_get_string(&argvars[0]), + (const char_u *)tv_get_string_buf(&argvars[1], buf)); + } } /* @@ -14097,32 +13394,37 @@ static void f_rename(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_repeat(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p; - int n; - - n = get_tv_number(&argvars[1]); + varnumber_T n = tv_get_number(&argvars[1]); if (argvars[0].v_type == VAR_LIST) { - rettv_list_alloc(rettv); - if (argvars[0].vval.v_list != NULL) { - while (n-- > 0) { - list_extend(rettv->vval.v_list, argvars[0].vval.v_list, NULL); - } + tv_list_alloc_ret(rettv); + while (n-- > 0) { + tv_list_extend(rettv->vval.v_list, argvars[0].vval.v_list, NULL); } } else { - p = get_tv_string(&argvars[0]); rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; + if (n <= 0) { + return; + } - int slen = (int)STRLEN(p); - int len = slen * n; - if (len <= 0) + const char *const p = tv_get_string(&argvars[0]); + + const size_t slen = strlen(p); + if (slen == 0) { + return; + } + const size_t len = slen * n; + // Detect overflow. + if (len / n != slen) { return; + } - char_u *r = xmallocz(len); - for (int i = 0; i < n; i++) - memmove(r + i * slen, p, (size_t)slen); + char *const r = xmallocz(len); + for (varnumber_T i = 0; i < n; i++) { + memmove(r + i * slen, p, slen); + } - rettv->vval.v_string = r; + rettv->vval.v_string = (char_u *)r; } } @@ -14131,61 +13433,49 @@ static void f_repeat(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p; -#ifdef HAVE_READLINK - char_u *buf = NULL; -#endif - - p = get_tv_string(&argvars[0]); + rettv->v_type = VAR_STRING; + const char *fname = tv_get_string(&argvars[0]); #ifdef WIN32 - { - char_u *v = NULL; - - v = os_resolve_shortcut(p); - if (v != NULL) { - rettv->vval.v_string = v; - } else { - rettv->vval.v_string = vim_strsave(p); - } - } + char *const v = os_resolve_shortcut(fname); + rettv->vval.v_string = (char_u *)(v == NULL ? xstrdup(fname) : v); #else # ifdef HAVE_READLINK { - char_u *cpy; - int len; - char_u *remain = NULL; - char_u *q; - int is_relative_to_current = FALSE; - int has_trailing_pathsep = FALSE; + bool is_relative_to_current = false; + bool has_trailing_pathsep = false; int limit = 100; - p = vim_strsave(p); + char *p = xstrdup(fname); if (p[0] == '.' && (vim_ispathsep(p[1]) - || (p[1] == '.' && (vim_ispathsep(p[2]))))) - is_relative_to_current = TRUE; + || (p[1] == '.' && (vim_ispathsep(p[2]))))) { + is_relative_to_current = true; + } - len = STRLEN(p); - if (len > 0 && after_pathsep((char *)p, (char *)p + len)) { - has_trailing_pathsep = TRUE; - p[len - 1] = NUL; /* the trailing slash breaks readlink() */ + ptrdiff_t len = (ptrdiff_t)strlen(p); + if (len > 0 && after_pathsep(p, p + len)) { + has_trailing_pathsep = true; + p[len - 1] = NUL; // The trailing slash breaks readlink(). } - q = path_next_component(p); + char *q = (char *)path_next_component(p); + char *remain = NULL; if (*q != NUL) { - /* Separate the first path component in "p", and keep the - * remainder (beginning with the path separator). */ - remain = vim_strsave(q - 1); + // Separate the first path component in "p", and keep the + // remainder (beginning with the path separator). + remain = xstrdup(q - 1); q[-1] = NUL; } - buf = xmallocz(MAXPATHL); + char *const buf = xmallocz(MAXPATHL); + char *cpy; for (;; ) { for (;; ) { - len = readlink((char *)p, (char *)buf, MAXPATHL); - if (len <= 0) + len = readlink(p, buf, MAXPATHL); + if (len <= 0) { break; + } buf[len] = NUL; if (limit-- == 0) { @@ -14193,66 +13483,72 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr) xfree(remain); EMSG(_("E655: Too many symbolic links (cycle?)")); rettv->vval.v_string = NULL; - goto fail; + xfree(buf); + return; } - /* Ensure that the result will have a trailing path separator - * if the argument has one. */ - if (remain == NULL && has_trailing_pathsep) - add_pathsep((char *)buf); + // Ensure that the result will have a trailing path separator + // if the argument has one. */ + if (remain == NULL && has_trailing_pathsep) { + add_pathsep(buf); + } - /* Separate the first path component in the link value and - * concatenate the remainders. */ - q = path_next_component(vim_ispathsep(*buf) ? buf + 1 : buf); + // Separate the first path component in the link value and + // concatenate the remainders. */ + q = (char *)path_next_component(vim_ispathsep(*buf) ? buf + 1 : buf); if (*q != NUL) { cpy = remain; - remain = remain ? - concat_str(q - 1, remain) : (char_u *) xstrdup((char *)q - 1); + remain = (remain + ? (char *)concat_str((char_u *)q - 1, (char_u *)remain) + : xstrdup(q - 1)); xfree(cpy); q[-1] = NUL; } - q = path_tail(p); + q = (char *)path_tail((char_u *)p); if (q > p && *q == NUL) { - /* Ignore trailing path separator. */ + // Ignore trailing path separator. q[-1] = NUL; - q = path_tail(p); + q = (char *)path_tail((char_u *)p); } - if (q > p && !path_is_absolute_path(buf)) { - /* symlink is relative to directory of argument */ - cpy = xmalloc(STRLEN(p) + STRLEN(buf) + 1); - STRCPY(cpy, p); - STRCPY(path_tail(cpy), buf); - xfree(p); - p = cpy; + if (q > p && !path_is_absolute_path((const char_u *)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); + const size_t buf_len = strlen(buf); + p = xrealloc(p, p_len + buf_len + 1); + memcpy(path_tail((char_u *)p), buf, buf_len + 1); } else { xfree(p); - p = vim_strsave(buf); + p = xstrdup(buf); } } - if (remain == NULL) + if (remain == NULL) { break; + } - /* Append the first path component of "remain" to "p". */ - q = path_next_component(remain + 1); + // Append the first path component of "remain" to "p". + q = (char *)path_next_component(remain + 1); len = q - remain - (*q != NUL); - cpy = vim_strnsave(p, STRLEN(p) + len); - STRNCAT(cpy, remain, len); + const size_t p_len = strlen(p); + cpy = xmallocz(p_len + len); + memcpy(cpy, p, p_len + 1); + xstrlcat(cpy + p_len, remain, len + 1); xfree(p); p = cpy; - /* Shorten "remain". */ - if (*q != NUL) + // Shorten "remain". + if (*q != NUL) { STRMOVE(remain, q - 1); - else { + } else { xfree(remain); remain = NULL; } } - /* If the result is a relative path name, make it explicitly relative to - * the current directory if and only if the argument had this form. */ + // If the result is a relative path name, make it explicitly relative to + // the current directory if and only if the argument had this form. if (!vim_ispathsep(*p)) { if (is_relative_to_current && *p != NUL @@ -14262,42 +13558,40 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr) || (p[1] == '.' && (p[2] == NUL || vim_ispathsep(p[2])))))) { - /* Prepend "./". */ - cpy = concat_str((char_u *)"./", p); + // Prepend "./". + cpy = (char *)concat_str((const char_u *)"./", (const char_u *)p); xfree(p); p = cpy; } else if (!is_relative_to_current) { - /* Strip leading "./". */ + // Strip leading "./". q = p; - while (q[0] == '.' && vim_ispathsep(q[1])) + while (q[0] == '.' && vim_ispathsep(q[1])) { q += 2; - if (q > p) + } + if (q > p) { STRMOVE(p, p + 2); + } } } - /* Ensure that the result will have no trailing path separator - * if the argument had none. But keep "/" or "//". */ + // Ensure that the result will have no trailing path separator + // if the argument had none. But keep "/" or "//". if (!has_trailing_pathsep) { - q = p + STRLEN(p); - if (after_pathsep((char *)p, (char *)q)) - *path_tail_with_sep(p) = NUL; + q = p + strlen(p); + if (after_pathsep(p, q)) { + *path_tail_with_sep((char_u *)p) = NUL; + } } - rettv->vval.v_string = p; + rettv->vval.v_string = (char_u *)p; + xfree(buf); } # else - rettv->vval.v_string = vim_strsave(p); + rettv->vval.v_string = (char_u *)xstrdup(p); # endif #endif simplify_filename(rettv->vval.v_string); - -#ifdef HAVE_READLINK -fail: - xfree(buf); -#endif - rettv->v_type = VAR_STRING; } /* @@ -14305,25 +13599,23 @@ fail: */ static void f_reverse(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - list_T *l; - listitem_T *li, *ni; - + list_T *l; if (argvars[0].v_type != VAR_LIST) { EMSG2(_(e_listarg), "reverse()"); } else if ((l = argvars[0].vval.v_list) != NULL - && !tv_check_lock(l->lv_lock, - (char_u *)N_("reverse() argument"), true)) { - li = l->lv_last; + && !tv_check_lock(l->lv_lock, N_("reverse() argument"), + TV_TRANSLATE)) { + listitem_T *li = l->lv_last; l->lv_first = l->lv_last = NULL; l->lv_len = 0; while (li != NULL) { - ni = li->li_prev; - list_append(l, li); + listitem_T *const ni = li->li_prev; + tv_list_append(l, li); li = ni; } rettv->vval.v_list = l; rettv->v_type = VAR_LIST; - ++l->lv_refcount; + l->lv_refcount++; l->lv_idx = l->lv_len - l->lv_idx - 1; } } @@ -14345,40 +13637,45 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, FunPtr fptr) static int get_search_arg(typval_T *varp, int *flagsp) { int dir = FORWARD; - char_u *flags; - char_u nbuf[NUMBUFLEN]; int mask; if (varp->v_type != VAR_UNKNOWN) { - flags = get_tv_string_buf_chk(varp, nbuf); - if (flags == NULL) - return 0; /* type error; errmsg already given */ + char nbuf[NUMBUFLEN]; + const char *flags = tv_get_string_buf_chk(varp, nbuf); + if (flags == NULL) { + return 0; // Type error; errmsg already given. + } while (*flags != NUL) { switch (*flags) { - case 'b': dir = BACKWARD; break; - case 'w': p_ws = true; break; - case 'W': p_ws = false; break; - default: mask = 0; - if (flagsp != NULL) - switch (*flags) { - case 'c': mask = SP_START; break; - case 'e': mask = SP_END; break; - case 'm': mask = SP_RETCOUNT; break; - case 'n': mask = SP_NOMOVE; break; - case 'p': mask = SP_SUBPAT; break; - case 'r': mask = SP_REPEAT; break; - case 's': mask = SP_SETPCMARK; break; - case 'z': mask = SP_COLUMN; break; + case 'b': dir = BACKWARD; break; + case 'w': p_ws = true; break; + case 'W': p_ws = false; break; + default: { + mask = 0; + if (flagsp != NULL) { + switch (*flags) { + case 'c': mask = SP_START; break; + case 'e': mask = SP_END; break; + case 'm': mask = SP_RETCOUNT; break; + case 'n': mask = SP_NOMOVE; break; + case 'p': mask = SP_SUBPAT; break; + case 'r': mask = SP_REPEAT; break; + case 's': mask = SP_SETPCMARK; break; + case 'z': mask = SP_COLUMN; break; + } } - if (mask == 0) { - EMSG2(_(e_invarg2), flags); - dir = 0; - } else - *flagsp |= mask; + if (mask == 0) { + emsgf(_(e_invarg2), flags); + dir = 0; + } else { + *flagsp |= mask; + } + } } - if (dir == 0) + if (dir == 0) { break; - ++flags; + } + flags++; } } return dir; @@ -14388,7 +13685,6 @@ static int get_search_arg(typval_T *varp, int *flagsp) static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) { int flags; - char_u *pat; pos_T pos; pos_T save_cursor; bool save_p_ws = p_ws; @@ -14400,10 +13696,11 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) int options = SEARCH_KEEP; int subpatnum; - pat = get_tv_string(&argvars[0]); - dir = get_search_arg(&argvars[1], flagsp); /* may set p_ws */ - if (dir == 0) + const char *const pat = tv_get_string(&argvars[0]); + dir = get_search_arg(&argvars[1], flagsp); // May set p_ws. + if (dir == 0) { goto theend; + } flags = *flagsp; if (flags & SP_START) { options |= SEARCH_START; @@ -14417,13 +13714,15 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) /* Optional arguments: line number to stop searching and timeout. */ if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) { - lnum_stop = get_tv_number_chk(&argvars[2], NULL); - if (lnum_stop < 0) + lnum_stop = tv_get_number_chk(&argvars[2], NULL); + if (lnum_stop < 0) { goto theend; + } if (argvars[3].v_type != VAR_UNKNOWN) { - time_limit = get_tv_number_chk(&argvars[3], NULL); - if (time_limit < 0) + time_limit = tv_get_number_chk(&argvars[3], NULL); + if (time_limit < 0) { goto theend; + } } } @@ -14438,13 +13737,13 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) */ if (((flags & (SP_REPEAT | SP_RETCOUNT)) != 0) || ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK))) { - EMSG2(_(e_invarg2), get_tv_string(&argvars[1])); + EMSG2(_(e_invarg2), tv_get_string(&argvars[1])); goto theend; } pos = save_cursor = curwin->w_cursor; - subpatnum = searchit(curwin, curbuf, &pos, dir, pat, 1L, - options, RE_SEARCH, (linenr_T)lnum_stop, &tm); + subpatnum = searchit(curwin, curbuf, &pos, dir, (char_u *)pat, 1, + options, RE_SEARCH, (linenr_T)lnum_stop, &tm); if (subpatnum != FAIL) { if (flags & SP_SUBPAT) retval = subpatnum; @@ -14501,7 +13800,7 @@ static void f_rpcnotify(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (!channel_send_event((uint64_t)argvars[0].vval.v_number, - (char *)get_tv_string(&argvars[1]), + tv_get_string(&argvars[1]), args)) { EMSG2(_(e_invarg2), "Channel doesn't exist"); return; @@ -14568,7 +13867,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) Error err = ERROR_INIT; Object result = channel_send_call((uint64_t)argvars[0].vval.v_number, - (char *)get_tv_string(&argvars[1]), + tv_get_string(&argvars[1]), args, &err); @@ -14583,7 +13882,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) restore_funccal(save_funccalp); } - if (err.set) { + if (ERROR_SET(&err)) { nvim_err_writeln(cstr_as_string(err.msg)); goto end; } @@ -14594,6 +13893,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) end: api_free_object(result); + api_clear_error(&err); } // "rpcstart()" function (DEPRECATED) @@ -14643,7 +13943,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) // Copy arguments to the vector if (argsl > 0) { for (listitem_T *arg = args->lv_first; arg != NULL; arg = arg->li_next) { - argv[i++] = xstrdup((char *) get_tv_string(&arg->li_tv)); + argv[i++] = xstrdup(tv_get_string(&arg->li_tv)); } } @@ -14685,17 +13985,16 @@ static void f_rpcstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_screenattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int row; - int col; int c; - row = get_tv_number_chk(&argvars[0], NULL) - 1; - col = get_tv_number_chk(&argvars[1], NULL) - 1; + const int row = (int)tv_get_number_chk(&argvars[0], NULL) - 1; + const int col = (int)tv_get_number_chk(&argvars[1], NULL) - 1; if (row < 0 || row >= screen_Rows - || col < 0 || col >= screen_Columns) + || col < 0 || col >= screen_Columns) { c = -1; - else + } else { c = ScreenAttrs[LineOffset[row] + col]; + } rettv->vval.v_number = c; } @@ -14704,17 +14003,15 @@ static void f_screenattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_screenchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int row; - int col; int off; int c; - row = get_tv_number_chk(&argvars[0], NULL) - 1; - col = get_tv_number_chk(&argvars[1], NULL) - 1; + const int row = tv_get_number_chk(&argvars[0], NULL) - 1; + const int col = tv_get_number_chk(&argvars[1], NULL) - 1; if (row < 0 || row >= screen_Rows - || col < 0 || col >= screen_Columns) + || col < 0 || col >= screen_Columns) { c = -1; - else { + } else { off = LineOffset[row] + col; if (enc_utf8 && ScreenLinesUC[off] != 0) c = ScreenLinesUC[off]; @@ -14759,19 +14056,21 @@ static void f_searchdecl(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int locally = 1; int thisblock = 0; - int error = FALSE; + bool error = false; rettv->vval.v_number = 1; /* default: FAIL */ - char_u *name = get_tv_string_chk(&argvars[0]); + const char *const name = tv_get_string_chk(&argvars[0]); if (argvars[1].v_type != VAR_UNKNOWN) { - locally = get_tv_number_chk(&argvars[1], &error) == 0; - if (!error && argvars[2].v_type != VAR_UNKNOWN) - thisblock = get_tv_number_chk(&argvars[2], &error) != 0; + locally = tv_get_number_chk(&argvars[1], &error) == 0; + if (!error && argvars[2].v_type != VAR_UNKNOWN) { + thisblock = tv_get_number_chk(&argvars[2], &error) != 0; + } } - if (!error && name != NULL) - rettv->vval.v_number = find_decl(name, STRLEN(name), locally, + if (!error && name != NULL) { + rettv->vval.v_number = find_decl((char_u *)name, strlen(name), locally, thisblock, SEARCH_KEEP) == FAIL; + } } /* @@ -14779,65 +14078,70 @@ static void f_searchdecl(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) { - char_u *spat, *mpat, *epat; - char_u *skip; bool save_p_ws = p_ws; int dir; int flags = 0; - char_u nbuf1[NUMBUFLEN]; - char_u nbuf2[NUMBUFLEN]; - char_u nbuf3[NUMBUFLEN]; - int retval = 0; /* default: FAIL */ + int retval = 0; // default: FAIL long lnum_stop = 0; long time_limit = 0; - /* Get the three pattern arguments: start, middle, end. */ - spat = get_tv_string_chk(&argvars[0]); - mpat = get_tv_string_buf_chk(&argvars[1], nbuf1); - epat = get_tv_string_buf_chk(&argvars[2], nbuf2); - if (spat == NULL || mpat == NULL || epat == NULL) - goto theend; /* type error */ + // Get the three pattern arguments: start, middle, end. + char nbuf1[NUMBUFLEN]; + char nbuf2[NUMBUFLEN]; + char nbuf3[NUMBUFLEN]; + const char *spat = tv_get_string_chk(&argvars[0]); + const char *mpat = tv_get_string_buf_chk(&argvars[1], nbuf1); + const char *epat = tv_get_string_buf_chk(&argvars[2], nbuf2); + if (spat == NULL || mpat == NULL || epat == NULL) { + goto theend; // Type error. + } - /* Handle the optional fourth argument: flags */ - dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */ - if (dir == 0) + // Handle the optional fourth argument: flags. + dir = get_search_arg(&argvars[3], &flags); // may set p_ws. + if (dir == 0) { goto theend; + } - /* Don't accept SP_END or SP_SUBPAT. - * Only one of the SP_NOMOVE or SP_SETPCMARK flags can be set. - */ + // Don't accept SP_END or SP_SUBPAT. + // Only one of the SP_NOMOVE or SP_SETPCMARK flags can be set. if ((flags & (SP_END | SP_SUBPAT)) != 0 || ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK))) { - EMSG2(_(e_invarg2), get_tv_string(&argvars[3])); + EMSG2(_(e_invarg2), tv_get_string(&argvars[3])); goto theend; } - /* Using 'r' implies 'W', otherwise it doesn't work. */ - if (flags & SP_REPEAT) + // Using 'r' implies 'W', otherwise it doesn't work. + if (flags & SP_REPEAT) { p_ws = false; + } - /* Optional fifth argument: skip expression */ + // Optional fifth argument: skip expression. + const char *skip; if (argvars[3].v_type == VAR_UNKNOWN - || argvars[4].v_type == VAR_UNKNOWN) - skip = (char_u *)""; - else { - skip = get_tv_string_buf_chk(&argvars[4], nbuf3); + || argvars[4].v_type == VAR_UNKNOWN) { + skip = ""; + } else { + skip = tv_get_string_buf_chk(&argvars[4], nbuf3); + if (skip == NULL) { + goto theend; // Type error. + } if (argvars[5].v_type != VAR_UNKNOWN) { - lnum_stop = get_tv_number_chk(&argvars[5], NULL); - if (lnum_stop < 0) + lnum_stop = tv_get_number_chk(&argvars[5], NULL); + if (lnum_stop < 0) { goto theend; + } if (argvars[6].v_type != VAR_UNKNOWN) { - time_limit = get_tv_number_chk(&argvars[6], NULL); - if (time_limit < 0) + time_limit = tv_get_number_chk(&argvars[6], NULL); + if (time_limit < 0) { goto theend; + } } } } - if (skip == NULL) - goto theend; /* type error */ - retval = do_searchpair(spat, mpat, epat, dir, skip, flags, - match_pos, lnum_stop, time_limit); + retval = do_searchpair( + (char_u *)spat, (char_u *)mpat, (char_u *)epat, dir, (char_u *)skip, + flags, match_pos, lnum_stop, time_limit); theend: p_ws = save_p_ws; @@ -14862,15 +14166,15 @@ static void f_searchpairpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) int lnum = 0; int col = 0; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (searchpair_cmn(argvars, &match_pos) > 0) { lnum = match_pos.lnum; col = match_pos.col; } - list_append_number(rettv->vval.v_list, (varnumber_T)lnum); - list_append_number(rettv->vval.v_list, (varnumber_T)col); + tv_list_append_number(rettv->vval.v_list, (varnumber_T)lnum); + tv_list_append_number(rettv->vval.v_list, (varnumber_T)col); } /* @@ -14902,9 +14206,10 @@ do_searchpair ( int n; int r; int nest = 1; - int err; int options = SEARCH_KEEP; proftime_T tm; + size_t pat2_len; + size_t pat3_len; /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ save_cpo = p_cpo; @@ -14913,18 +14218,22 @@ do_searchpair ( /* Set the time limit, if there is one. */ tm = profile_setlimit(time_limit); - /* Make two search patterns: start/end (pat2, for in nested pairs) and - * start/middle/end (pat3, for the top pair). */ - pat2 = xmalloc(STRLEN(spat) + STRLEN(epat) + 15); - pat3 = xmalloc(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23); - sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat); - if (*mpat == NUL) + // Make two search patterns: start/end (pat2, for in nested pairs) and + // start/middle/end (pat3, for the top pair). + pat2_len = STRLEN(spat) + STRLEN(epat) + 17; + pat2 = xmalloc(pat2_len); + pat3_len = STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 25; + pat3 = xmalloc(pat3_len); + snprintf((char *)pat2, pat2_len, "\\m\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat); + if (*mpat == NUL) { STRCPY(pat3, pat2); - else - sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)", - spat, epat, mpat); - if (flags & SP_START) + } else { + snprintf((char *)pat3, pat3_len, + "\\m\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat, mpat); + } + if (flags & SP_START) { options |= SEARCH_START; + } save_cursor = curwin->w_cursor; pos = curwin->w_cursor; @@ -14958,7 +14267,8 @@ do_searchpair ( if (*skip != NUL) { save_pos = curwin->w_cursor; curwin->w_cursor = pos; - r = eval_to_bool(skip, &err, NULL, FALSE); + bool err; + r = eval_to_bool(skip, &err, NULL, false); curwin->w_cursor = save_pos; if (err) { /* Evaluating {skip} caused an error, break here. */ @@ -15029,7 +14339,7 @@ static void f_searchpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) int n; int flags = 0; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); n = search_cmn(argvars, &match_pos, &flags); if (n > 0) { @@ -15037,10 +14347,11 @@ static void f_searchpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) col = match_pos.col; } - list_append_number(rettv->vval.v_list, (varnumber_T)lnum); - list_append_number(rettv->vval.v_list, (varnumber_T)col); - if (flags & SP_SUBPAT) - list_append_number(rettv->vval.v_list, (varnumber_T)n); + tv_list_append_number(rettv->vval.v_list, (varnumber_T)lnum); + tv_list_append_number(rettv->vval.v_list, (varnumber_T)col); + if (flags & SP_SUBPAT) { + tv_list_append_number(rettv->vval.v_list, (varnumber_T)n); + } } /// "serverlist()" function @@ -15050,13 +14361,13 @@ static void f_serverlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) char **addrs = server_address_list(&n); // Copy addrs into a linked list. - list_T *l = rettv_list_alloc(rettv); + list_T *l = tv_list_alloc_ret(rettv); for (size_t i = 0; i < n; i++) { - listitem_T *li = listitem_alloc(); + listitem_T *li = tv_list_item_alloc(); li->li_tv.v_type = VAR_STRING; li->li_tv.v_lock = 0; - li->li_tv.vval.v_string = (char_u *) addrs[i]; - list_append(l, li); + li->li_tv.vval.v_string = (char_u *)addrs[i]; + tv_list_append(l, li); } xfree(addrs); } @@ -15071,22 +14382,39 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } + char *address; // If the user supplied an address, use it, otherwise use a temp. if (argvars[0].v_type != VAR_UNKNOWN) { if (argvars[0].v_type != VAR_STRING) { EMSG(_(e_invarg)); return; } else { - rettv->vval.v_string = vim_strsave(get_tv_string(argvars)); + address = xstrdup(tv_get_string(argvars)); } } else { - rettv->vval.v_string = (char_u *)server_address_new(); + address = server_address_new(); } - int result = server_start((char *) rettv->vval.v_string); + int result = server_start(address); + xfree(address); + if (result != 0) { - EMSG2("Failed to start server: %s", uv_strerror(result)); + EMSG2("Failed to start server: %s", + result > 0 ? "Unknown system error" : uv_strerror(result)); + return; + } + + // Since it's possible server_start adjusted the given {address} (e.g., + // "localhost:" will now have a port), return the final value to the user. + size_t n; + char **addrs = server_address_list(&n); + rettv->vval.v_string = (char_u *)addrs[n - 1]; + + n--; + for (size_t i = 0; i < n; i++) { + xfree(addrs[i]); } + xfree(addrs); } /// "serverstop()" function @@ -15096,7 +14424,7 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - if (argvars[0].v_type == VAR_UNKNOWN || argvars[0].v_type != VAR_STRING) { + if (argvars[0].v_type != VAR_STRING) { EMSG(_(e_invarg)); return; } @@ -15111,44 +14439,43 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - buf_T *buf; - char_u *varname, *bufvarname; - typval_T *varp; - char_u nbuf[NUMBUFLEN]; - - if (check_restricted() || check_secure()) + if (check_restricted() + || check_secure() + || !tv_check_str_or_nr(&argvars[0])) { return; - (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ - varname = get_tv_string_chk(&argvars[1]); - buf = get_buf_tv(&argvars[0], FALSE); - varp = &argvars[2]; + } + const char *varname = tv_get_string_chk(&argvars[1]); + buf_T *const buf = get_buf_tv(&argvars[0], false); + typval_T *varp = &argvars[2]; - if (buf != NULL && varname != NULL && varp != NULL) { + if (buf != NULL && varname != NULL) { if (*varname == '&') { long numval; - char_u *strval; - int error = false; - aco_save_T aco; + bool error = false; + aco_save_T aco; // set curbuf to be our buf, temporarily aucmd_prepbuf(&aco, buf); - ++varname; - numval = get_tv_number_chk(varp, &error); - strval = get_tv_string_buf_chk(varp, nbuf); - if (!error && strval != NULL) + varname++; + numval = tv_get_number_chk(varp, &error); + char nbuf[NUMBUFLEN]; + const char *const strval = tv_get_string_buf_chk(varp, nbuf); + if (!error && strval != NULL) { set_option_value(varname, numval, strval, OPT_LOCAL); + } // reset notion of buffer aucmd_restbuf(&aco); } else { buf_T *save_curbuf = curbuf; - bufvarname = xmalloc(STRLEN(varname) + 3); + const size_t varname_len = STRLEN(varname); + char *const bufvarname = xmalloc(varname_len + 3); curbuf = buf; - STRCPY(bufvarname, "b:"); - STRCPY(bufvarname + 2, varname); - set_var(bufvarname, varp, TRUE); + memcpy(bufvarname, "b:", 2); + memcpy(bufvarname + 2, varname, varname_len + 1); + set_var(bufvarname, varname_len + 2, varp, true); xfree(bufvarname); curbuf = save_curbuf; } @@ -15159,7 +14486,6 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_T *d; dictitem_T *di; - char_u *csearch; if (argvars[0].v_type != VAR_DICT) { EMSG(_(e_dictreq)); @@ -15167,7 +14493,7 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if ((d = argvars[0].vval.v_dict) != NULL) { - csearch = get_dict_string(d, "char", false); + char_u *const csearch = (char_u *)tv_dict_get_string(d, "char", false); if (csearch != NULL) { if (enc_utf8) { int pcc[MAX_MCO]; @@ -15179,13 +14505,15 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) csearch, MB_PTR2LEN(csearch)); } - di = dict_find(d, (char_u *)"forward", -1); - if (di != NULL) - set_csearch_direction(get_tv_number(&di->di_tv) ? FORWARD : BACKWARD); + di = tv_dict_find(d, S_LEN("forward")); + if (di != NULL) { + set_csearch_direction(tv_get_number(&di->di_tv) ? FORWARD : BACKWARD); + } - di = dict_find(d, (char_u *)"until", -1); - if (di != NULL) - set_csearch_until(!!get_tv_number(&di->di_tv)); + di = tv_dict_find(d, S_LEN("until")); + if (di != NULL) { + set_csearch_until(!!tv_get_number(&di->di_tv)); + } } } @@ -15194,10 +14522,11 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_setcmdpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int pos = (int)get_tv_number(&argvars[0]) - 1; + const int pos = (int)tv_get_number(&argvars[0]) - 1; - if (pos >= 0) + if (pos >= 0) { rettv->vval.v_number = set_cmdline_pos(pos); + } } @@ -15206,17 +14535,17 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = 0; - char_u *fname = get_tv_string_chk(&argvars[0]); + const char *const fname = tv_get_string_chk(&argvars[0]); if (fname == NULL) { return; } - char_u modebuf[NUMBUFLEN]; - char_u *mode_str = get_tv_string_buf_chk(&argvars[1], modebuf); + char modebuf[NUMBUFLEN]; + const char *const mode_str = tv_get_string_buf_chk(&argvars[1], modebuf); if (mode_str == NULL) { return; } - if (STRLEN(mode_str) != 9) { + if (strlen(mode_str) != 9) { EMSG2(_(e_invarg2), mode_str); return; } @@ -15237,27 +14566,28 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; - char_u *line = NULL; list_T *l = NULL; listitem_T *li = NULL; long added = 0; linenr_T lcount = curbuf->b_ml.ml_line_count; - lnum = get_tv_lnum(&argvars[0]); + linenr_T lnum = tv_get_lnum(&argvars[0]); + const char *line = NULL; if (argvars[1].v_type == VAR_LIST) { l = argvars[1].vval.v_list; li = l->lv_first; - } else - line = get_tv_string_chk(&argvars[1]); + } else { + line = tv_get_string_chk(&argvars[1]); + } /* default result is zero == OK */ for (;; ) { if (l != NULL) { - /* list argument, get next string */ - if (li == NULL) + // List argument, get next string. + if (li == NULL) { break; - line = get_tv_string_chk(&li->li_tv); + } + line = tv_get_string_chk(&li->li_tv); li = li->li_next; } @@ -15273,18 +14603,20 @@ static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (lnum <= curbuf->b_ml.ml_line_count) { - /* existing line, replace it */ - if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK) { + // Existing line, replace it. + if (u_savesub(lnum) == OK + && ml_replace(lnum, (char_u *)line, true) == OK) { changed_bytes(lnum, 0); if (lnum == curwin->w_cursor.lnum) check_cursor_col(); rettv->vval.v_number = 0; /* OK */ } } else if (added > 0 || u_save(lnum - 1, lnum) == OK) { - /* lnum is one past the last line, append the line */ - ++added; - if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK) - rettv->vval.v_number = 0; /* OK */ + // lnum is one past the last line, append the line. + added++; + if (ml_append(lnum - 1, (char_u *)line, 0, false) == OK) { + rettv->vval.v_number = 0; // OK + } } if (l == NULL) /* only one string argument */ @@ -15299,7 +14631,7 @@ static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// Create quickfix/location list from VimL values /// /// Used by `setqflist()` and `setloclist()` functions. Accepts invalid -/// list_arg, action_arg and title_arg arguments in which case errors out, +/// list_arg, action_arg and what_arg arguments in which case errors out, /// including VAR_UNKNOWN parameters. /// /// @param[in,out] wp Window to create location list for. May be NULL in @@ -15313,9 +14645,10 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) FUNC_ATTR_NONNULL_ARG(2, 3) { static char *e_invact = N_("E927: Invalid action: '%s'"); - char_u *title = NULL; + const char *title = NULL; int action = ' '; rettv->vval.v_number = -1; + dict_T *d = NULL; typval_T *list_arg = &args[0]; if (list_arg->v_type != VAR_LIST) { @@ -15331,7 +14664,7 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) EMSG(_(e_stringreq)); return; } - char_u *act = get_tv_string_chk(action_arg); + const char *const act = tv_get_string_chk(action_arg); if ((*act == 'a' || *act == 'r' || *act == ' ') && act[1] == NUL) { action = *act; } else { @@ -15343,20 +14676,26 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) if (title_arg->v_type == VAR_UNKNOWN) { // Option argument was not given. goto skip_args; - } - title = get_tv_string_chk(title_arg); - if (!title) { - // Type error. Error already printed by get_tv_string_chk(). + } else if (title_arg->v_type == VAR_STRING) { + title = tv_get_string_chk(title_arg); + if (!title) { + // Type error. Error already printed by tv_get_string_chk(). + return; + } + } else if (title_arg->v_type == VAR_DICT) { + d = title_arg->vval.v_dict; + } else { + emsgf(_(e_dictreq)); return; } skip_args: if (!title) { - title = (char_u*)(wp ? "setloclist()" : "setqflist()"); + title = (wp ? "setloclist()" : "setqflist()"); } list_T *l = list_arg->vval.v_list; - if (l && set_errorlist(wp, l, action, title) == OK) { + if (l && set_errorlist(wp, l, action, (char_u *)title, d) == OK) { rettv->vval.v_number = 0; } } @@ -15402,11 +14741,11 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) EMSG(_(e_invarg)); return; } - if (!(dict_find(d, (char_u *)"group", -1) != NULL - && (dict_find(d, (char_u *)"pattern", -1) != NULL - || dict_find(d, (char_u *)"pos1", -1) != NULL) - && dict_find(d, (char_u *)"priority", -1) != NULL - && dict_find(d, (char_u *)"id", -1) != NULL)) { + if (!(tv_dict_find(d, S_LEN("group")) != NULL + && (tv_dict_find(d, S_LEN("pattern")) != NULL + || tv_dict_find(d, S_LEN("pos1")) != NULL) + && tv_dict_find(d, S_LEN("priority")) != NULL + && tv_dict_find(d, S_LEN("id")) != NULL)) { EMSG(_(e_invarg)); return; } @@ -15415,29 +14754,31 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) clear_matches(curwin); li = l->lv_first; + bool match_add_failed = false; while (li != NULL) { int i = 0; - char_u buf[5]; - dictitem_T *di; d = li->li_tv.vval.v_dict; - if (dict_find(d, (char_u *)"pattern", -1) == NULL) { + dictitem_T *const di = tv_dict_find(d, S_LEN("pattern")); + if (di == NULL) { if (s == NULL) { - s = list_alloc(); + s = tv_list_alloc(); if (s == NULL) { return; } } // match from matchaddpos() - for (i = 1; i < 9; ++i) { - snprintf((char *)buf, sizeof(buf), (char *)"pos%d", i); - if ((di = dict_find(d, (char_u *)buf, -1)) != NULL) { - if (di->di_tv.v_type != VAR_LIST) { + for (i = 1; i < 9; i++) { + char buf[5]; + snprintf(buf, sizeof(buf), "pos%d", i); + dictitem_T *const pos_di = tv_dict_find(d, buf, -1); + if (pos_di != NULL) { + if (pos_di->di_tv.v_type != VAR_LIST) { return; } - list_append_tv(s, &di->di_tv); + tv_list_append_tv(s, &pos_di->di_tv); s->lv_refcount++; } else { break; @@ -15445,25 +14786,39 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } - char_u *group = get_dict_string(d, "group", false); - int priority = get_dict_number(d, "priority"); - int id = get_dict_number(d, "id"); - char_u *conceal = dict_find(d, (char_u *)"conceal", -1) != NULL - ? get_dict_string(d, "conceal", - false) - : NULL; + // Note: there are three number buffers involved: + // - group_buf below. + // - numbuf in tv_dict_get_string(). + // - mybuf in tv_get_string(). + // + // If you change this code make sure that buffers will not get + // accidentally reused. + char group_buf[NUMBUFLEN]; + const char *const group = tv_dict_get_string_buf(d, "group", group_buf); + const int priority = (int)tv_dict_get_number(d, "priority"); + const int id = (int)tv_dict_get_number(d, "id"); + dictitem_T *const conceal_di = tv_dict_find(d, S_LEN("conceal")); + const char *const conceal = (conceal_di != NULL + ? tv_get_string(&conceal_di->di_tv) + : NULL); if (i == 0) { - match_add(curwin, group, - get_dict_string(d, "pattern", false), - priority, id, NULL, conceal); + if (match_add(curwin, group, + tv_dict_get_string(d, "pattern", false), + priority, id, NULL, conceal) != id) { + match_add_failed = true; + } } else { - match_add(curwin, group, NULL, priority, id, s, conceal); - list_unref(s); + if (match_add(curwin, group, NULL, priority, id, s, conceal) != id) { + match_add_failed = true; + } + tv_list_unref(s); s = NULL; } li = li->li_next; } - rettv->vval.v_number = 0; + if (!match_add_failed) { + rettv->vval.v_number = 0; + } } } @@ -15474,11 +14829,10 @@ static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { pos_T pos; int fnum; - char_u *name; colnr_T curswant = -1; rettv->vval.v_number = -1; - name = get_tv_string_chk(argvars); + const char *const name = tv_get_string_chk(argvars); if (name != NULL) { if (list2fpos(&argvars[1], &pos, &fnum, &curswant) == OK) { if (--pos.col < 0) { @@ -15499,7 +14853,7 @@ static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL) { // set mark - if (setmark_pos(name[1], &pos, fnum) == OK) { + if (setmark_pos((uint8_t)name[1], &pos, fnum) == OK) { rettv->vval.v_number = 0; } } else { @@ -15523,8 +14877,6 @@ static void f_setqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int regname; - char_u *strregname; - char_u *stropt; bool append = false; MotionType yank_type; long block_len; @@ -15532,39 +14884,52 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) block_len = -1; yank_type = kMTUnknown; - strregname = get_tv_string_chk(argvars); - rettv->vval.v_number = 1; /* FAIL is default */ + rettv->vval.v_number = 1; // FAIL is default. - if (strregname == NULL) - return; /* type error; errmsg already given */ - regname = *strregname; - if (regname == 0 || regname == '@') + const char *const strregname = tv_get_string_chk(argvars); + if (strregname == NULL) { + return; // Type error; errmsg already given. + } + regname = (uint8_t)(*strregname); + if (regname == 0 || regname == '@') { regname = '"'; + } + bool set_unnamed = false; if (argvars[2].v_type != VAR_UNKNOWN) { - stropt = get_tv_string_chk(&argvars[2]); - if (stropt == NULL) - return; /* type error */ - for (; *stropt != NUL; ++stropt) + const char *stropt = tv_get_string_chk(&argvars[2]); + if (stropt == NULL) { + return; // Type error. + } + for (; *stropt != NUL; stropt++) { switch (*stropt) { - case 'a': case 'A': // append - append = true; - break; - case 'v': case 'c': // character-wise selection - yank_type = kMTCharWise; - break; - case 'V': case 'l': // line-wise selection - yank_type = kMTLineWise; - break; - case 'b': case Ctrl_V: // block-wise selection - yank_type = kMTBlockWise; - if (ascii_isdigit(stropt[1])) { - ++stropt; - block_len = getdigits_long(&stropt) - 1; - --stropt; + case 'a': case 'A': { // append + append = true; + break; + } + case 'v': case 'c': { // character-wise selection + yank_type = kMTCharWise; + break; + } + case 'V': case 'l': { // line-wise selection + yank_type = kMTLineWise; + break; + } + case 'b': case Ctrl_V: { // block-wise selection + yank_type = kMTBlockWise; + if (ascii_isdigit(stropt[1])) { + stropt++; + block_len = getdigits_long((char_u **)&stropt) - 1; + stropt--; + } + break; + } + case 'u': case '"': { // unnamed register + set_unnamed = true; + break; } - break; } + } } if (argvars[1].v_type == VAR_LIST) { @@ -15574,45 +14939,52 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) // First half: use for pointers to result lines; second half: use for // pointers to allocated copies. - char_u **lstval = xmalloc(sizeof(char_u *) * ((len + 1) * 2)); - char_u **curval = lstval; - char_u **allocval = lstval + len + 2; - char_u **curallocval = allocval; + char **lstval = xmalloc(sizeof(char *) * ((len + 1) * 2)); + const char **curval = (const char **)lstval; + char **allocval = lstval + len + 2; + char **curallocval = allocval; - char_u buf[NUMBUFLEN]; for (listitem_T *li = ll == NULL ? NULL : ll->lv_first; li != NULL; li = li->li_next) { - char_u *strval = get_tv_string_buf_chk(&li->li_tv, buf); - if (strval == NULL) { + char buf[NUMBUFLEN]; + *curval = tv_get_string_buf_chk(&li->li_tv, buf); + if (*curval == NULL) { goto free_lstval; } - if (strval == buf) { + if (*curval == buf) { // Need to make a copy, - // next get_tv_string_buf_chk() will overwrite the string. - strval = vim_strsave(buf); - *curallocval++ = strval; + // next tv_get_string_buf_chk() will overwrite the string. + *curallocval = xstrdup(*curval); + *curval = *curallocval; + curallocval++; } - *curval++ = strval; + curval++; } *curval++ = NULL; - write_reg_contents_lst(regname, lstval, STRLEN(lstval), - append, yank_type, block_len); + write_reg_contents_lst(regname, (char_u **)lstval, append, yank_type, + block_len); free_lstval: - while (curallocval > allocval) - xfree(*--curallocval); + while (curallocval > allocval) { + xfree(*--curallocval); + } xfree(lstval); } else { - char_u *strval = get_tv_string_chk(&argvars[1]); + const char *strval = tv_get_string_chk(&argvars[1]); if (strval == NULL) { return; } - write_reg_contents_ex(regname, strval, STRLEN(strval), + write_reg_contents_ex(regname, (const char_u *)strval, STRLEN(strval), append, yank_type, block_len); } rettv->vval.v_number = 0; + + if (set_unnamed) { + // Discard the result. We already handle the error case. + if (op_register_set_previous(regname)) { } + } } /* @@ -15620,35 +14992,31 @@ free_lstval: */ static void f_settabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - tabpage_T *save_curtab; - tabpage_T *tp; - char_u *varname, *tabvarname; - typval_T *varp; - rettv->vval.v_number = 0; - if (check_restricted() || check_secure()) + if (check_restricted() || check_secure()) { return; + } - tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL)); - varname = get_tv_string_chk(&argvars[1]); - varp = &argvars[2]; + tabpage_T *const tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); + const char *const varname = tv_get_string_chk(&argvars[1]); + typval_T *const varp = &argvars[2]; - if (varname != NULL && varp != NULL - && tp != NULL - ) { - save_curtab = curtab; - goto_tabpage_tp(tp, FALSE, FALSE); + if (varname != NULL && tp != NULL) { + tabpage_T *const save_curtab = curtab; + goto_tabpage_tp(tp, false, false); - tabvarname = xmalloc(STRLEN(varname) + 3); - STRCPY(tabvarname, "t:"); - STRCPY(tabvarname + 2, varname); - set_var(tabvarname, varp, TRUE); + const size_t varname_len = strlen(varname); + char *const tabvarname = xmalloc(varname_len + 3); + memcpy(tabvarname, "t:", 2); + memcpy(tabvarname + 2, varname, varname_len + 1); + set_var(tabvarname, varname_len + 2, varp, true); xfree(tabvarname); - /* Restore current tabpage */ - if (valid_tabpage(save_curtab)) - goto_tabpage_tp(save_curtab, FALSE, FALSE); + // Restore current tabpage. + if (valid_tabpage(save_curtab)) { + goto_tabpage_tp(save_curtab, false, false); + } } } @@ -15674,45 +15042,43 @@ static void f_setwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void setwinvar(typval_T *argvars, typval_T *rettv, int off) { - win_T *win; - win_T *save_curwin; - tabpage_T *save_curtab; - char_u *varname, *winvarname; - typval_T *varp; - char_u nbuf[NUMBUFLEN]; - tabpage_T *tp = NULL; - - if (check_restricted() || check_secure()) + if (check_restricted() || check_secure()) { return; + } - if (off == 1) - tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL)); - else + tabpage_T *tp = NULL; + if (off == 1) { + tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); + } else { tp = curtab; - win = find_win_by_nr(&argvars[off], tp); - varname = get_tv_string_chk(&argvars[off + 1]); - varp = &argvars[off + 2]; + } + win_T *const win = find_win_by_nr(&argvars[off], tp); + const char *varname = tv_get_string_chk(&argvars[off + 1]); + typval_T *varp = &argvars[off + 2]; if (win != NULL && varname != NULL && varp != NULL) { + win_T *save_curwin; + tabpage_T *save_curtab; bool need_switch_win = tp != curtab || win != curwin; if (!need_switch_win || switch_win(&save_curwin, &save_curtab, win, tp, true) == OK) { if (*varname == '&') { long numval; - char_u *strval; - int error = false; + bool error = false; - ++varname; - numval = get_tv_number_chk(varp, &error); - strval = get_tv_string_buf_chk(varp, nbuf); + varname++; + numval = tv_get_number_chk(varp, &error); + char nbuf[NUMBUFLEN]; + const char *const strval = tv_get_string_buf_chk(varp, nbuf); if (!error && strval != NULL) { set_option_value(varname, numval, strval, OPT_LOCAL); } } else { - winvarname = xmalloc(STRLEN(varname) + 3); - STRCPY(winvarname, "w:"); - STRCPY(winvarname + 2, varname); - set_var(winvarname, varp, true); + const size_t varname_len = strlen(varname); + char *const winvarname = xmalloc(varname_len + 3); + memcpy(winvarname, "w:", 2); + memcpy(winvarname + 2, varname, varname_len + 1); + set_var(winvarname, varname_len + 2, varp, true); xfree(winvarname); } } @@ -15725,11 +15091,11 @@ static void setwinvar(typval_T *argvars, typval_T *rettv, int off) /// f_sha256 - sha256({string}) function static void f_sha256(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p = get_tv_string(&argvars[0]); - const char_u *hash = sha256_bytes(p, (int) STRLEN(p) , NULL, 0); + const char *p = tv_get_string(&argvars[0]); + const char *hash = sha256_bytes((const uint8_t *)p, strlen(p) , NULL, 0); // make a copy of the hash (sha256_bytes returns a static buffer) - rettv->vval.v_string = (char_u *) xstrdup((char *) hash); + rettv->vval.v_string = (char_u *)xstrdup(hash); rettv->v_type = VAR_STRING; } @@ -15739,7 +15105,8 @@ static void f_sha256(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_shellescape(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_string = vim_strsave_shellescape( - get_tv_string(&argvars[0]), non_zero_arg(&argvars[1]), true); + (const char_u *)tv_get_string(&argvars[0]), non_zero_arg(&argvars[1]), + true); rettv->v_type = VAR_STRING; } @@ -15756,14 +15123,61 @@ static void f_shiftwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_simplify(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p; - - p = get_tv_string(&argvars[0]); - rettv->vval.v_string = vim_strsave(p); - simplify_filename(rettv->vval.v_string); /* simplify in place */ + const char *const p = tv_get_string(&argvars[0]); + rettv->vval.v_string = (char_u *)xstrdup(p); + simplify_filename(rettv->vval.v_string); // Simplify in place. rettv->v_type = VAR_STRING; } +/// "sockconnect()" function +static void f_sockconnect(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + if (argvars[0].v_type != VAR_STRING || argvars[1].v_type != VAR_STRING) { + EMSG(_(e_invarg)); + return; + } + if (argvars[2].v_type != VAR_DICT && argvars[2].v_type != VAR_UNKNOWN) { + // Wrong argument types + EMSG2(_(e_invarg2), "expected dictionary"); + return; + } + + const char *mode = tv_get_string(&argvars[0]); + const char *address = tv_get_string(&argvars[1]); + + bool tcp; + if (strcmp(mode, "tcp") == 0) { + tcp = true; + } else if (strcmp(mode, "pipe") == 0) { + tcp = false; + } else { + EMSG2(_(e_invarg2), "invalid mode"); + return; + } + + bool rpc = false; + if (argvars[2].v_type == VAR_DICT) { + dict_T *opts = argvars[2].vval.v_dict; + rpc = tv_dict_get_number(opts, "rpc") != 0; + } + + if (!rpc) { + EMSG2(_(e_invarg2), "rpc option must be true"); + return; + } + + const char *error = NULL; + eval_format_source_name_line((char *)IObuff, sizeof(IObuff)); + uint64_t id = channel_connect(tcp, address, 50, (char *)IObuff, &error); + + if (error) { + EMSG2(_("connection failed: %s"), error); + } + + rettv->vval.v_number = (varnumber_T)id; + rettv->v_type = VAR_NUMBER; +} + /// struct used in the array that's given to qsort() typedef struct { listitem_T *item; @@ -15776,10 +15190,10 @@ typedef struct { bool item_compare_numeric; bool item_compare_numbers; bool item_compare_float; - char_u *item_compare_func; + const char *item_compare_func; partial_T *item_compare_partial; dict_T *item_compare_selfdict; - int item_compare_func_err; + bool item_compare_func_err; } sortinfo_T; static sortinfo_T *sortinfo = NULL; @@ -15790,58 +15204,61 @@ static sortinfo_T *sortinfo = NULL; */ static int item_compare(const void *s1, const void *s2, bool keep_zero) { - sortItem_T *si1, *si2; - char_u *p1; - char_u *p2; - char_u *tofree1 = NULL; - char_u *tofree2 = NULL; - int res; + sortItem_T *const si1 = (sortItem_T *)s1; + sortItem_T *const si2 = (sortItem_T *)s2; - si1 = (sortItem_T *)s1; - si2 = (sortItem_T *)s2; - typval_T *tv1 = &si1->item->li_tv; - typval_T *tv2 = &si2->item->li_tv; + typval_T *const tv1 = &si1->item->li_tv; + typval_T *const tv2 = &si2->item->li_tv; + + int res; if (sortinfo->item_compare_numbers) { - long v1 = get_tv_number(tv1); - long v2 = get_tv_number(tv2); + const varnumber_T v1 = tv_get_number(tv1); + const varnumber_T v2 = tv_get_number(tv2); - return v1 == v2 ? 0 : v1 > v2 ? 1 : -1; + res = v1 == v2 ? 0 : v1 > v2 ? 1 : -1; + goto item_compare_end; } if (sortinfo->item_compare_float) { - float_T v1 = get_tv_float(tv1); - float_T v2 = get_tv_float(tv2); + const float_T v1 = tv_get_float(tv1); + const float_T v2 = tv_get_float(tv2); - return v1 == v2 ? 0 : v1 > v2 ? 1 : -1; + res = v1 == v2 ? 0 : v1 > v2 ? 1 : -1; + goto item_compare_end; } + char *tofree1 = NULL; + char *tofree2 = NULL; + char *p1; + char *p2; + // encode_tv2string() puts quotes around a string and allocates memory. Don't // do that for string variables. Use a single quote when comparing with // a non-string to do what the docs promise. if (tv1->v_type == VAR_STRING) { if (tv2->v_type != VAR_STRING || sortinfo->item_compare_numeric) { - p1 = (char_u *)"'"; + p1 = "'"; } else { - p1 = tv1->vval.v_string; + p1 = (char *)tv1->vval.v_string; } } else { - tofree1 = p1 = (char_u *) encode_tv2string(tv1, NULL); + tofree1 = p1 = encode_tv2string(tv1, NULL); } if (tv2->v_type == VAR_STRING) { if (tv1->v_type != VAR_STRING || sortinfo->item_compare_numeric) { - p2 = (char_u *)"'"; + p2 = "'"; } else { - p2 = tv2->vval.v_string; + p2 = (char *)tv2->vval.v_string; } } else { - tofree2 = p2 = (char_u *) encode_tv2string(tv2, NULL); + tofree2 = p2 = encode_tv2string(tv2, NULL); } if (p1 == NULL) { - p1 = (char_u *)""; + p1 = ""; } if (p2 == NULL) { - p2 = (char_u *)""; + p2 = ""; } if (!sortinfo->item_compare_numeric) { if (sortinfo->item_compare_ic) { @@ -15851,19 +15268,20 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero) } } else { double n1, n2; - n1 = strtod((char *)p1, (char **)&p1); - n2 = strtod((char *)p2, (char **)&p2); + n1 = strtod(p1, &p1); + n2 = strtod(p2, &p2); res = n1 == n2 ? 0 : n1 > n2 ? 1 : -1; } + xfree(tofree1); + xfree(tofree2); + +item_compare_end: // When the result would be zero, compare the item indexes. Makes the // sort stable. if (res == 0 && !keep_zero) { res = si1->idx > si2->idx ? 1 : -1; } - - xfree(tofree1); - xfree(tofree2); return res; } @@ -15884,7 +15302,7 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero) typval_T rettv; typval_T argv[3]; int dummy; - char_u *func_name; + const char *func_name; partial_T *partial = sortinfo->item_compare_partial; // shortcut after failure in previous call; compare all items equal @@ -15898,30 +15316,31 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero) if (partial == NULL) { func_name = sortinfo->item_compare_func; } else { - func_name = partial->pt_name; + func_name = (const char *)partial_name(partial); } + // Copy the values. This is needed to be able to set v_lock to VAR_FIXED // in the copy without changing the original list items. - copy_tv(&si1->item->li_tv, &argv[0]); - copy_tv(&si2->item->li_tv, &argv[1]); + tv_copy(&si1->item->li_tv, &argv[0]); + tv_copy(&si2->item->li_tv, &argv[1]); - rettv.v_type = VAR_UNKNOWN; // clear_tv() uses this - res = call_func(func_name, + rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this + res = call_func((const char_u *)func_name, (int)STRLEN(func_name), - &rettv, 2, argv, 0L, 0L, &dummy, true, + &rettv, 2, argv, NULL, 0L, 0L, &dummy, true, partial, sortinfo->item_compare_selfdict); - clear_tv(&argv[0]); - clear_tv(&argv[1]); + tv_clear(&argv[0]); + tv_clear(&argv[1]); if (res == FAIL) { res = ITEM_COMPARE_FAIL; } else { - res = get_tv_number_chk(&rettv, &sortinfo->item_compare_func_err); + res = tv_get_number_chk(&rettv, &sortinfo->item_compare_func_err); } if (sortinfo->item_compare_func_err) { res = ITEM_COMPARE_FAIL; // return value has wrong type } - clear_tv(&rettv); + tv_clear(&rettv); // When the result would be zero, compare the pointers themselves. Makes // the sort stable. @@ -15959,23 +15378,22 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) sortinfo_T *old_sortinfo = sortinfo; sortinfo = &info; + const char *const arg_errmsg = (sort + ? N_("sort() argument") + : N_("uniq() argument")); + if (argvars[0].v_type != VAR_LIST) { EMSG2(_(e_listarg), sort ? "sort()" : "uniq()"); } else { l = argvars[0].vval.v_list; - if (l == NULL - || tv_check_lock(l->lv_lock, - (char_u *)(sort - ? N_("sort() argument") - : N_("uniq() argument")), - true)) { + if (l == NULL || tv_check_lock(l->lv_lock, arg_errmsg, TV_TRANSLATE)) { goto theend; } rettv->vval.v_list = l; rettv->v_type = VAR_LIST; ++l->lv_refcount; - len = list_len(l); + len = tv_list_len(l); if (len <= 1) { goto theend; // short list sorts pretty quickly } @@ -15991,20 +15409,20 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) if (argvars[1].v_type != VAR_UNKNOWN) { /* optional second argument: {func} */ if (argvars[1].v_type == VAR_FUNC) { - info.item_compare_func = argvars[1].vval.v_string; + info.item_compare_func = (const char *)argvars[1].vval.v_string; } else if (argvars[1].v_type == VAR_PARTIAL) { info.item_compare_partial = argvars[1].vval.v_partial; } else { - int error = FALSE; + bool error = false; - i = get_tv_number_chk(&argvars[1], &error); + i = tv_get_number_chk(&argvars[1], &error); if (error) { goto theend; // type error; errmsg already given } if (i == 1) { info.item_compare_ic = true; } else if (argvars[1].v_type != VAR_NUMBER) { - info.item_compare_func = get_tv_string(&argvars[1]); + info.item_compare_func = tv_get_string(&argvars[1]); } else if (i != 0) { EMSG(_(e_invarg)); goto theend; @@ -16013,16 +15431,16 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) if (*info.item_compare_func == NUL) { // empty string means default sort info.item_compare_func = NULL; - } else if (STRCMP(info.item_compare_func, "n") == 0) { + } else if (strcmp(info.item_compare_func, "n") == 0) { info.item_compare_func = NULL; info.item_compare_numeric = true; - } else if (STRCMP(info.item_compare_func, "N") == 0) { + } else if (strcmp(info.item_compare_func, "N") == 0) { info.item_compare_func = NULL; info.item_compare_numbers = true; - } else if (STRCMP(info.item_compare_func, "f") == 0) { + } else if (strcmp(info.item_compare_func, "f") == 0) { info.item_compare_func = NULL; info.item_compare_float = true; - } else if (STRCMP(info.item_compare_func, "i") == 0) { + } else if (strcmp(info.item_compare_func, "i") == 0) { info.item_compare_func = NULL; info.item_compare_ic = true; } @@ -16074,7 +15492,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) l->lv_len = 0; for (i = 0; i < len; i++) { - list_append(l, ptrs[i].item); + tv_list_append(l, ptrs[i].item); } } } @@ -16110,8 +15528,8 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) } else { l->lv_last = ptrs[i].item; } - list_fix_watch(l, li); - listitem_free(li); + tv_list_watch_fix(l, li); + tv_list_item_free(li); l->lv_len--; } } @@ -16156,11 +15574,9 @@ static void f_reltimefloat(typval_T *argvars , typval_T *rettv, FunPtr fptr) */ static void f_soundfold(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *s; - rettv->v_type = VAR_STRING; - s = get_tv_string(&argvars[0]); - rettv->vval.v_string = eval_soundfold(s); + const char *const s = tv_get_string(&argvars[0]); + rettv->vval.v_string = (char_u *)eval_soundfold(s); } /* @@ -16168,25 +15584,26 @@ static void f_soundfold(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *word = (char_u *)""; + const char *word = ""; hlf_T attr = HLF_COUNT; size_t len = 0; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (argvars[0].v_type == VAR_UNKNOWN) { - /* Find the start and length of the badly spelled word. */ - len = spell_move_to(curwin, FORWARD, TRUE, TRUE, &attr); - if (len != 0) - word = get_cursor_pos_ptr(); + // Find the start and length of the badly spelled word. + len = spell_move_to(curwin, FORWARD, true, true, &attr); + if (len != 0) { + word = (char *)get_cursor_pos_ptr(); + } } else if (curwin->w_p_spell && *curbuf->b_s.b_p_spl != NUL) { - char_u *str = get_tv_string_chk(&argvars[0]); + const char *str = tv_get_string_chk(&argvars[0]); int capcol = -1; if (str != NULL) { - /* Check the argument for spelling. */ + // Check the argument for spelling. while (*str != NUL) { - len = spell_check(curwin, str, &attr, &capcol, false); + len = spell_check(curwin, (char_u *)str, &attr, &capcol, false); if (attr != HLF_COUNT) { word = str; break; @@ -16197,14 +15614,13 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr) } assert(len <= INT_MAX); - list_append_string(rettv->vval.v_list, word, (int)len); - list_append_string(rettv->vval.v_list, - (char_u *)(attr == HLF_SPB ? "bad" : - attr == HLF_SPR ? "rare" : - attr == HLF_SPL ? "local" : - attr == HLF_SPC ? "caps" : - ""), - -1); + tv_list_append_string(rettv->vval.v_list, word, len); + tv_list_append_string(rettv->vval.v_list, + (attr == HLF_SPB ? "bad" + : attr == HLF_SPR ? "rare" + : attr == HLF_SPL ? "local" + : attr == HLF_SPC ? "caps" + : NULL), -1); } /* @@ -16212,39 +15628,40 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_spellsuggest(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *str; - int typeerr = FALSE; + bool typeerr = false; int maxcount; garray_T ga; listitem_T *li; bool need_capital = false; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) { - str = get_tv_string(&argvars[0]); + const char *const str = tv_get_string(&argvars[0]); if (argvars[1].v_type != VAR_UNKNOWN) { - maxcount = get_tv_number_chk(&argvars[1], &typeerr); - if (maxcount <= 0) + maxcount = tv_get_number_chk(&argvars[1], &typeerr); + if (maxcount <= 0) { return; + } if (argvars[2].v_type != VAR_UNKNOWN) { - need_capital = get_tv_number_chk(&argvars[2], &typeerr); - if (typeerr) + need_capital = tv_get_number_chk(&argvars[2], &typeerr); + if (typeerr) { return; + } } } else maxcount = 25; - spell_suggest_list(&ga, str, maxcount, need_capital, false); + spell_suggest_list(&ga, (char_u *)str, maxcount, need_capital, false); - for (int i = 0; i < ga.ga_len; ++i) { - str = ((char_u **)ga.ga_data)[i]; + for (int i = 0; i < ga.ga_len; i++) { + char *p = ((char **)ga.ga_data)[i]; - li = listitem_alloc(); + li = tv_list_item_alloc(); li->li_tv.v_type = VAR_STRING; li->li_tv.v_lock = 0; - li->li_tv.vval.v_string = str; - list_append(rettv->vval.v_list, li); + li->li_tv.vval.v_string = (char_u *)p; + tv_list_append(rettv->vval.v_list, li); } ga_clear(&ga); } @@ -16252,64 +15669,69 @@ static void f_spellsuggest(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *str; - char_u *end; - char_u *pat = NULL; regmatch_T regmatch; - char_u patbuf[NUMBUFLEN]; char_u *save_cpo; int match; colnr_T col = 0; - int keepempty = FALSE; - int typeerr = FALSE; + bool keepempty = false; + bool typeerr = false; /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ save_cpo = p_cpo; p_cpo = (char_u *)""; - str = get_tv_string(&argvars[0]); + const char *str = tv_get_string(&argvars[0]); + const char *pat = NULL; + char patbuf[NUMBUFLEN]; if (argvars[1].v_type != VAR_UNKNOWN) { - pat = get_tv_string_buf_chk(&argvars[1], patbuf); - if (pat == NULL) - typeerr = TRUE; - if (argvars[2].v_type != VAR_UNKNOWN) - keepempty = get_tv_number_chk(&argvars[2], &typeerr); + pat = tv_get_string_buf_chk(&argvars[1], patbuf); + if (pat == NULL) { + typeerr = true; + } + if (argvars[2].v_type != VAR_UNKNOWN) { + keepempty = (bool)tv_get_number_chk(&argvars[2], &typeerr); + } + } + if (pat == NULL || *pat == NUL) { + pat = "[\\x01- ]\\+"; } - if (pat == NULL || *pat == NUL) - pat = (char_u *)"[\\x01- ]\\+"; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (typeerr) return; - regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); + regmatch.regprog = vim_regcomp((char_u *)pat, RE_MAGIC + RE_STRING); if (regmatch.regprog != NULL) { regmatch.rm_ic = FALSE; while (*str != NUL || keepempty) { - if (*str == NUL) - match = FALSE; /* empty item at the end */ - else - match = vim_regexec_nl(®match, str, col); - if (match) - end = regmatch.startp[0]; - else - end = str + STRLEN(str); + if (*str == NUL) { + match = false; // Empty item at the end. + } else { + match = vim_regexec_nl(®match, (char_u *)str, col); + } + const char *end; + if (match) { + end = (const char *)regmatch.startp[0]; + } else { + end = str + strlen(str); + } if (keepempty || end > str || (rettv->vval.v_list->lv_len > 0 - && *str != NUL && match && end < - regmatch.endp[0])) { - list_append_string(rettv->vval.v_list, str, (int)(end - str)); + && *str != NUL + && match + && end < (const char *)regmatch.endp[0])) { + tv_list_append_string(rettv->vval.v_list, str, end - str); } if (!match) break; - /* Advance to just after the match. */ - if (regmatch.endp[0] > str) + // Advance to just after the match. + if (regmatch.endp[0] > (char_u *)str) { col = 0; - else { - /* Don't get stuck at the same match. */ + } else { + // Don't get stuck at the same match. col = (*mb_ptr2len)(regmatch.endp[0]); } - str = regmatch.endp[0]; + str = (const char *)regmatch.endp[0]; } vim_regfree(regmatch.regprog); @@ -16323,11 +15745,16 @@ static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_str2float(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p = skipwhite(get_tv_string(&argvars[0])); + char_u *p = skipwhite((const char_u *)tv_get_string(&argvars[0])); + bool isneg = (*p == '-'); - if (*p == '+') + if (*p == '+' || *p == '-') { p = skipwhite(p + 1); - (void) string2float((char *) p, &rettv->vval.v_float); + } + (void)string2float((char *)p, &rettv->vval.v_float); + if (isneg) { + rettv->vval.v_float *= -1; + } rettv->v_type = VAR_FLOAT; } @@ -16335,37 +15762,45 @@ static void f_str2float(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int base = 10; - char_u *p; - long n; + varnumber_T n; int what; if (argvars[1].v_type != VAR_UNKNOWN) { - base = get_tv_number(&argvars[1]); + base = tv_get_number(&argvars[1]); if (base != 2 && base != 8 && base != 10 && base != 16) { EMSG(_(e_invarg)); return; } } - p = skipwhite(get_tv_string(&argvars[0])); - if (*p == '+') { + char_u *p = skipwhite((const char_u *)tv_get_string(&argvars[0])); + bool isneg = (*p == '-'); + if (*p == '+' || *p == '-') { p = skipwhite(p + 1); } switch (base) { - case 2: - what = STR2NR_BIN + STR2NR_FORCE; + case 2: { + what = STR2NR_BIN | STR2NR_FORCE; break; - case 8: - what = STR2NR_OCT + STR2NR_FORCE; + } + case 8: { + what = STR2NR_OCT | STR2NR_FORCE; break; - case 16: - what = STR2NR_HEX + STR2NR_FORCE; + } + case 16: { + what = STR2NR_HEX | STR2NR_FORCE; break; - default: + } + default: { what = 0; + } } vim_str2nr(p, NULL, NULL, what, &n, NULL, 0); - rettv->vval.v_number = n; + if (isneg) { + rettv->vval.v_number = -n; + } else { + rettv->vval.v_number = n; + } } /* @@ -16373,17 +15808,16 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u result_buf[256]; time_t seconds; - char_u *p; rettv->v_type = VAR_STRING; - p = get_tv_string(&argvars[0]); - if (argvars[1].v_type == VAR_UNKNOWN) + char *p = (char *)tv_get_string(&argvars[0]); + if (argvars[1].v_type == VAR_UNKNOWN) { seconds = time(NULL); - else - seconds = (time_t)get_tv_number(&argvars[1]); + } else { + seconds = (time_t)tv_get_number(&argvars[1]); + } struct tm curtime; struct tm *curtime_ptr = os_localtime_r(&seconds, &curtime); @@ -16397,23 +15831,27 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) conv.vc_type = CONV_NONE; enc = enc_locale(); convert_setup(&conv, p_enc, enc); - if (conv.vc_type != CONV_NONE) - p = string_convert(&conv, p, NULL); - if (p != NULL) - (void)strftime((char *)result_buf, sizeof(result_buf), - (char *)p, curtime_ptr); - else + if (conv.vc_type != CONV_NONE) { + p = (char *)string_convert(&conv, (char_u *)p, NULL); + } + char result_buf[256]; + if (p != NULL) { + (void)strftime(result_buf, sizeof(result_buf), p, curtime_ptr); + } else { result_buf[0] = NUL; + } - if (conv.vc_type != CONV_NONE) + 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 = vim_strsave(result_buf); + if (conv.vc_type != CONV_NONE) { + rettv->vval.v_string = string_convert(&conv, (char_u *)result_buf, NULL); + } else { + rettv->vval.v_string = (char_u *)xstrdup(result_buf); + } - /* Release conversion descriptors */ + // Release conversion descriptors. convert_setup(&conv, NULL, NULL); xfree(enc); } @@ -16422,33 +15860,28 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) // "strgetchar()" function static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *str; - int len; - int error = false; - int charidx; - rettv->vval.v_number = -1; - str = get_tv_string_chk(&argvars[0]); + + const char *const str = tv_get_string_chk(&argvars[0]); if (str == NULL) { return; } - len = (int)STRLEN(str); - charidx = get_tv_number_chk(&argvars[1], &error); + bool error = false; + varnumber_T charidx = tv_get_number_chk(&argvars[1], &error); if (error) { return; } - { - int byteidx = 0; + const size_t len = STRLEN(str); + size_t byteidx = 0; - while (charidx >= 0 && byteidx < len) { - if (charidx == 0) { - rettv->vval.v_number = mb_ptr2char(str + byteidx); - break; - } - charidx--; - byteidx += mb_cptr2len(str + byteidx); + while (charidx >= 0 && byteidx < len) { + if (charidx == 0) { + rettv->vval.v_number = mb_ptr2char((const char_u *)str + byteidx); + break; } + charidx--; + byteidx += MB_CPTR2LEN((const char_u *)str + byteidx); } } @@ -16457,32 +15890,33 @@ static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_stridx(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u buf[NUMBUFLEN]; - char_u *needle; - char_u *haystack; - char_u *save_haystack; - char_u *pos; - int start_idx; - - needle = get_tv_string_chk(&argvars[1]); - save_haystack = haystack = get_tv_string_buf_chk(&argvars[0], buf); rettv->vval.v_number = -1; - if (needle == NULL || haystack == NULL) - return; /* type error; errmsg already given */ + + char buf[NUMBUFLEN]; + const char *const needle = tv_get_string_chk(&argvars[1]); + const char *haystack = tv_get_string_buf_chk(&argvars[0], buf); + const char *const haystack_start = haystack; + if (needle == NULL || haystack == NULL) { + return; // Type error; errmsg already given. + } if (argvars[2].v_type != VAR_UNKNOWN) { - int error = FALSE; + bool error = false; - start_idx = get_tv_number_chk(&argvars[2], &error); - if (error || start_idx >= (int)STRLEN(haystack)) + const ptrdiff_t start_idx = (ptrdiff_t)tv_get_number_chk(&argvars[2], + &error); + if (error || start_idx >= (ptrdiff_t)strlen(haystack)) { return; - if (start_idx >= 0) + } + if (start_idx >= 0) { haystack += start_idx; + } } - pos = (char_u *)strstr((char *)haystack, (char *)needle); - if (pos != NULL) - rettv->vval.v_number = (varnumber_T)(pos - save_haystack); + const char *pos = strstr(haystack, needle); + if (pos != NULL) { + rettv->vval.v_number = (varnumber_T)(pos - haystack_start); + } } /* @@ -16499,8 +15933,7 @@ static void f_string(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_strlen(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = (varnumber_T)(STRLEN( - get_tv_string(&argvars[0]))); + rettv->vval.v_number = (varnumber_T)strlen(tv_get_string(&argvars[0])); } /* @@ -16508,21 +15941,21 @@ static void f_strlen(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_strchars(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *s = get_tv_string(&argvars[0]); + const char *s = tv_get_string(&argvars[0]); int skipcc = 0; varnumber_T len = 0; - int (*func_mb_ptr2char_adv)(char_u **pp); + int (*func_mb_ptr2char_adv)(const char_u **pp); if (argvars[1].v_type != VAR_UNKNOWN) { - skipcc = get_tv_number_chk(&argvars[1], NULL); + skipcc = tv_get_number_chk(&argvars[1], NULL); } if (skipcc < 0 || skipcc > 1) { EMSG(_(e_invarg)); } else { func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv; while (*s != NUL) { - func_mb_ptr2char_adv(&s); - ++len; + func_mb_ptr2char_adv((const char_u **)&s); + len++; } rettv->vval.v_number = len; } @@ -16533,13 +15966,14 @@ static void f_strchars(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *s = get_tv_string(&argvars[0]); + const char *const s = tv_get_string(&argvars[0]); int col = 0; - if (argvars[1].v_type != VAR_UNKNOWN) - col = get_tv_number(&argvars[1]); + if (argvars[1].v_type != VAR_UNKNOWN) { + col = tv_get_number(&argvars[1]); + } - rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, s) - col); + rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, (char_u *)s) - col); } /* @@ -16547,44 +15981,40 @@ static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_strwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *s = get_tv_string(&argvars[0]); + const char *const s = tv_get_string(&argvars[0]); - rettv->vval.v_number = (varnumber_T) mb_string2cells(s); + rettv->vval.v_number = (varnumber_T)mb_string2cells((const char_u *)s); } // "strcharpart()" function -static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p; - int nchar; - int nbyte = 0; - int charlen; - int len = 0; - int slen; - int error = false; - - p = get_tv_string(&argvars[0]); - slen = (int)STRLEN(p); +static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + const char *const p = tv_get_string(&argvars[0]); + const size_t slen = STRLEN(p); - nchar = get_tv_number_chk(&argvars[1], &error); + int nbyte = 0; + bool error = false; + varnumber_T nchar = tv_get_number_chk(&argvars[1], &error); if (!error) { if (nchar > 0) { - while (nchar > 0 && nbyte < slen) { - nbyte += mb_cptr2len(p + nbyte); + while (nchar > 0 && (size_t)nbyte < slen) { + nbyte += MB_CPTR2LEN((const char_u *)p + nbyte); nchar--; } } else { nbyte = nchar; } } + int len = 0; if (argvars[2].v_type != VAR_UNKNOWN) { - charlen = get_tv_number(&argvars[2]); - while (charlen > 0 && nbyte + len < slen) { + int charlen = tv_get_number(&argvars[2]); + while (charlen > 0 && nbyte + len < (int)slen) { int off = nbyte + len; if (off < 0) { len += 1; } else { - len += mb_cptr2len(p + off); + len += (size_t)MB_CPTR2LEN((const char_u *)p + off); } charlen--; } @@ -16597,17 +16027,17 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (nbyte < 0) { len += nbyte; nbyte = 0; - } else if (nbyte > slen) { + } else if ((size_t)nbyte > slen) { nbyte = slen; } if (len < 0) { len = 0; - } else if (nbyte + len > slen) { + } else if (nbyte + len > (int)slen) { len = slen - nbyte; } rettv->v_type = VAR_STRING; - rettv->vval.v_string = vim_strnsave(p + nbyte, len); + rettv->vval.v_string = (char_u *)xstrndup(p + nbyte, (size_t)len); } /* @@ -16615,39 +16045,37 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { */ static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p; - int n; - int len; - int slen; - int error = FALSE; + bool error = false; - p = get_tv_string(&argvars[0]); - slen = (int)STRLEN(p); + const char *const p = tv_get_string(&argvars[0]); + const size_t slen = strlen(p); - n = get_tv_number_chk(&argvars[1], &error); - if (error) + varnumber_T n = tv_get_number_chk(&argvars[1], &error); + varnumber_T len; + if (error) { len = 0; - else if (argvars[2].v_type != VAR_UNKNOWN) - len = get_tv_number(&argvars[2]); - else - len = slen - n; /* default len: all bytes that are available. */ + } else if (argvars[2].v_type != VAR_UNKNOWN) { + len = tv_get_number(&argvars[2]); + } else { + len = slen - n; // Default len: all bytes that are available. + } - /* - * Only return the overlap between the specified part and the actual - * string. - */ + // Only return the overlap between the specified part and the actual + // string. if (n < 0) { len += n; n = 0; - } else if (n > slen) + } else if (n > (varnumber_T)slen) { n = slen; - if (len < 0) + } + if (len < 0) { len = 0; - else if (n + len > slen) + } else if (n + len > (varnumber_T)slen) { len = slen - n; + } rettv->v_type = VAR_STRING; - rettv->vval.v_string = vim_strnsave(p + n, len); + rettv->vval.v_string = (char_u *)xmemdupz(p + n, (size_t)len); } /* @@ -16655,45 +16083,46 @@ static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_strridx(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u buf[NUMBUFLEN]; - char_u *needle; - char_u *haystack; - char_u *rest; - char_u *lastmatch = NULL; - int haystack_len, end_idx; - - needle = get_tv_string_chk(&argvars[1]); - haystack = get_tv_string_buf_chk(&argvars[0], buf); + char buf[NUMBUFLEN]; + const char *const needle = tv_get_string_chk(&argvars[1]); + const char *const haystack = tv_get_string_buf_chk(&argvars[0], buf); rettv->vval.v_number = -1; - if (needle == NULL || haystack == NULL) - return; /* type error; errmsg already given */ + if (needle == NULL || haystack == NULL) { + return; // Type error; errmsg already given. + } - haystack_len = (int)STRLEN(haystack); + const size_t haystack_len = STRLEN(haystack); + ptrdiff_t end_idx; if (argvars[2].v_type != VAR_UNKNOWN) { - /* Third argument: upper limit for index */ - end_idx = get_tv_number_chk(&argvars[2], NULL); - if (end_idx < 0) - return; /* can never find a match */ - } else - end_idx = haystack_len; + // Third argument: upper limit for index. + end_idx = (ptrdiff_t)tv_get_number_chk(&argvars[2], NULL); + if (end_idx < 0) { + return; // Can never find a match. + } + } else { + end_idx = (ptrdiff_t)haystack_len; + } + const char *lastmatch = NULL; if (*needle == NUL) { - /* Empty string matches past the end. */ + // Empty string matches past the end. lastmatch = haystack + end_idx; } else { - for (rest = haystack; *rest != NUL; ++rest) { - rest = (char_u *)strstr((char *)rest, (char *)needle); - if (rest == NULL || rest > haystack + end_idx) + for (const char *rest = haystack; *rest != NUL; rest++) { + rest = strstr(rest, needle); + if (rest == NULL || rest > haystack + end_idx) { break; + } lastmatch = rest; } } - if (lastmatch == NULL) + if (lastmatch == NULL) { rettv->vval.v_number = -1; - else + } else { rettv->vval.v_number = (varnumber_T)(lastmatch - haystack); + } } /* @@ -16702,7 +16131,7 @@ static void f_strridx(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_strtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = transstr(get_tv_string(&argvars[0])); + rettv->vval.v_string = transstr((char_u *)tv_get_string(&argvars[0])); } /* @@ -16710,18 +16139,22 @@ static void f_strtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_submatch(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int error = FALSE; - int no = (int)get_tv_number_chk(&argvars[0], &error); + bool error = false; + int no = (int)tv_get_number_chk(&argvars[0], &error); if (error) { return; } + if (no < 0 || no >= NSUBEXP) { + EMSGN(_("E935: invalid submatch number: %d"), no); + return; + } int retList = 0; if (argvars[1].v_type != VAR_UNKNOWN) { - retList = get_tv_number_chk(&argvars[1], &error); + retList = tv_get_number_chk(&argvars[1], &error); if (error) { - return; + return; } } @@ -16739,40 +16172,47 @@ static void f_submatch(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_substitute(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u patbuf[NUMBUFLEN]; - char_u subbuf[NUMBUFLEN]; - char_u flagsbuf[NUMBUFLEN]; + char patbuf[NUMBUFLEN]; + char subbuf[NUMBUFLEN]; + char flagsbuf[NUMBUFLEN]; + + const char *const str = tv_get_string_chk(&argvars[0]); + const char *const pat = tv_get_string_buf_chk(&argvars[1], patbuf); + const char *sub = NULL; + const char *const flg = tv_get_string_buf_chk(&argvars[3], flagsbuf); - char_u *str = get_tv_string_chk(&argvars[0]); - char_u *pat = get_tv_string_buf_chk(&argvars[1], patbuf); - char_u *sub = get_tv_string_buf_chk(&argvars[2], subbuf); - char_u *flg = get_tv_string_buf_chk(&argvars[3], flagsbuf); + typval_T *expr = NULL; + if (tv_is_func(argvars[2])) { + expr = &argvars[2]; + } else { + sub = tv_get_string_buf_chk(&argvars[2], subbuf); + } rettv->v_type = VAR_STRING; - if (str == NULL || pat == NULL || sub == NULL || flg == NULL) + if (str == NULL || pat == NULL || (sub == NULL && expr == NULL) + || flg == NULL) { rettv->vval.v_string = NULL; - else - rettv->vval.v_string = do_string_sub(str, pat, sub, flg); + } else { + rettv->vval.v_string = do_string_sub((char_u *)str, (char_u *)pat, + (char_u *)sub, expr, (char_u *)flg); + } } -/* - * "synID(lnum, col, trans)" function - */ +/// "synID(lnum, col, trans)" function static void f_synID(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int id = 0; - long lnum; - long col; - int trans; - int transerr = FALSE; + // -1 on type error (both) + const linenr_T lnum = tv_get_lnum(argvars); + const colnr_T col = (colnr_T)tv_get_number(&argvars[1]) - 1; - lnum = get_tv_lnum(argvars); /* -1 on type error */ - col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */ - trans = get_tv_number_chk(&argvars[2], &transerr); + bool transerr = false; + const int trans = tv_get_number_chk(&argvars[2], &transerr); + int id = 0; if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count - && col >= 0 && col < (long)STRLEN(ml_get(lnum))) - id = syn_get_id(curwin, lnum, (colnr_T)col, trans, NULL, FALSE); + && col >= 0 && (size_t)col < STRLEN(ml_get(lnum))) { + id = syn_get_id(curwin, lnum, col, trans, NULL, false); + } rettv->vval.v_number = id; } @@ -16782,20 +16222,16 @@ static void f_synID(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p = NULL; - int id; - char_u *what; - char_u *mode; - char_u modebuf[NUMBUFLEN]; + const int id = (int)tv_get_number(&argvars[0]); + const char *const what = tv_get_string(&argvars[1]); int modec; - - id = get_tv_number(&argvars[0]); - what = get_tv_string(&argvars[1]); if (argvars[2].v_type != VAR_UNKNOWN) { - mode = get_tv_string_buf(&argvars[2], modebuf); + char modebuf[NUMBUFLEN]; + const char *const mode = tv_get_string_buf(&argvars[2], modebuf); modec = TOLOWER_ASC(mode[0]); - if (modec != 'c' && modec != 'g') - modec = 0; /* replace invalid with current */ + if (modec != 'c' && modec != 'g') { + modec = 0; // Replace invalid with current. + } } else if (ui_rgb_attached()) { modec = 'g'; } else { @@ -16803,54 +16239,56 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) } + const char *p = NULL; switch (TOLOWER_ASC(what[0])) { - case 'b': - if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */ + case 'b': { + if (TOLOWER_ASC(what[1]) == 'g') { // bg[#] + p = highlight_color(id, what, modec); + } else { // bold + p = highlight_has_attr(id, HL_BOLD, modec); + } + break; + } + case 'f': { // fg[#] or font p = highlight_color(id, what, modec); - else /* bold */ - p = highlight_has_attr(id, HL_BOLD, modec); - break; - - case 'f': /* fg[#] or font */ - p = highlight_color(id, what, modec); - break; - - case 'i': - if (TOLOWER_ASC(what[1]) == 'n') /* inverse */ + break; + } + case 'i': { + if (TOLOWER_ASC(what[1]) == 'n') { // inverse + p = highlight_has_attr(id, HL_INVERSE, modec); + } else { // italic + p = highlight_has_attr(id, HL_ITALIC, modec); + } + break; + } + case 'n': { // name + p = get_highlight_name(NULL, id - 1); + break; + } + case 'r': { // reverse p = highlight_has_attr(id, HL_INVERSE, modec); - else /* italic */ - p = highlight_has_attr(id, HL_ITALIC, modec); - break; - - case 'n': /* name */ - p = get_highlight_name(NULL, id - 1); - break; - - case 'r': /* reverse */ - p = highlight_has_attr(id, HL_INVERSE, modec); - break; - - case 's': - if (TOLOWER_ASC(what[1]) == 'p') /* sp[#] */ - p = highlight_color(id, what, modec); - else /* standout */ - p = highlight_has_attr(id, HL_STANDOUT, modec); - break; - - case 'u': - if (STRLEN(what) <= 5 || TOLOWER_ASC(what[5]) != 'c') - /* underline */ - p = highlight_has_attr(id, HL_UNDERLINE, modec); - else - /* undercurl */ - p = highlight_has_attr(id, HL_UNDERCURL, modec); - break; + break; + } + case 's': { + if (TOLOWER_ASC(what[1]) == 'p') { // sp[#] + p = highlight_color(id, what, modec); + } else { // standout + p = highlight_has_attr(id, HL_STANDOUT, modec); + } + break; + } + case 'u': { + if (STRLEN(what) <= 5 || TOLOWER_ASC(what[5]) != 'c') { // underline + p = highlight_has_attr(id, HL_UNDERLINE, modec); + } else { // undercurl + p = highlight_has_attr(id, HL_UNDERCURL, modec); + } + break; + } } - if (p != NULL) - p = vim_strsave(p); rettv->v_type = VAR_STRING; - rettv->vval.v_string = p; + rettv->vval.v_string = (char_u *)(p == NULL ? p : xstrdup(p)); } /* @@ -16858,14 +16296,13 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_synIDtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int id; + int id = tv_get_number(&argvars[0]); - id = get_tv_number(&argvars[0]); - - if (id > 0) + if (id > 0) { id = syn_get_final_id(id); - else + } else { id = 0; + } rettv->vval.v_number = id; } @@ -16875,8 +16312,6 @@ static void f_synIDtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - long lnum; - long col; int syntax_flags = 0; int cchar; int matchid = 0; @@ -16885,15 +16320,16 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_LIST; rettv->vval.v_list = NULL; - lnum = get_tv_lnum(argvars); /* -1 on type error */ - col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */ + // -1 on type error (both) + const linenr_T lnum = tv_get_lnum(argvars); + const colnr_T col = (colnr_T)tv_get_number(&argvars[1]) - 1; memset(str, NUL, sizeof(str)); - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count && col >= 0 - && col <= (long)STRLEN(ml_get(lnum)) && curwin->w_p_cole > 0) { - (void)syn_get_id(curwin, lnum, col, FALSE, NULL, FALSE); + && (size_t)col <= STRLEN(ml_get(lnum)) && curwin->w_p_cole > 0) { + (void)syn_get_id(curwin, lnum, col, false, NULL, false); syntax_flags = get_syntax_info(&matchid); // get the conceal character @@ -16911,10 +16347,10 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } - list_append_number(rettv->vval.v_list, (syntax_flags & HL_CONCEAL) != 0); + tv_list_append_number(rettv->vval.v_list, (syntax_flags & HL_CONCEAL) != 0); // -1 to auto-determine strlen - list_append_string(rettv->vval.v_list, str, -1); - list_append_number(rettv->vval.v_list, matchid); + tv_list_append_string(rettv->vval.v_list, (const char *)str, -1); + tv_list_append_number(rettv->vval.v_list, matchid); } /* @@ -16922,56 +16358,35 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_synstack(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - long lnum; - long col; - rettv->v_type = VAR_LIST; rettv->vval.v_list = NULL; - lnum = get_tv_lnum(argvars); /* -1 on type error */ - col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */ + // -1 on type error (both) + const linenr_T lnum = tv_get_lnum(argvars); + const colnr_T col = (colnr_T)tv_get_number(&argvars[1]) - 1; if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count && col >= 0 - && col <= (long)STRLEN(ml_get(lnum))) { - rettv_list_alloc(rettv); - (void)syn_get_id(curwin, lnum, (colnr_T)col, FALSE, NULL, TRUE); + && (size_t)col <= STRLEN(ml_get(lnum))) { + tv_list_alloc_ret(rettv); + (void)syn_get_id(curwin, lnum, col, false, NULL, true); int id; int i = 0; while ((id = syn_get_stack_item(i++)) >= 0) { - list_append_number(rettv->vval.v_list, id); + tv_list_append_number(rettv->vval.v_list, id); } } } -static list_T* string_to_list(char_u *str, size_t len, bool keepempty) +static list_T *string_to_list(const char *str, size_t len, const bool keepempty) { - list_T *list = list_alloc(); - - // Copy each line to a list element using NL as the delimiter. - for (size_t i = 0; i < len; i++) { - char_u *start = str + i; - size_t line_len = (char_u *) xmemscan(start, NL, len - i) - start; - i += line_len; - - // Don't use a str function to copy res as it may contains NULs. - char_u *s = xmemdupz(start, line_len); - memchrsub(s, NUL, NL, line_len); // Replace NUL with NL to avoid truncation - - listitem_T *li = listitem_alloc(); - li->li_tv.v_type = VAR_STRING; - li->li_tv.v_lock = 0; - li->li_tv.vval.v_string = s; - list_append(list, li); - } - - // Optionally retain final newline, if present - if (keepempty && str[len-1] == NL) { - list_append_string(list, (char_u*)"", 0); + if (!keepempty && str[len - 1] == NL) { + len--; } - + list_T *const list = tv_list_alloc(); + encode_list_write(list, str, len); return list; } @@ -16986,16 +16401,20 @@ static void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv, } // get input to the shell command (if any), and its length - ssize_t input_len; - char *input = (char *) save_tv_as_string(&argvars[1], &input_len, false); + ptrdiff_t input_len; + char *input = save_tv_as_string(&argvars[1], &input_len, false); if (input_len < 0) { assert(input == NULL); return; } // get shell command to execute - char **argv = tv_to_argv(&argvars[0], NULL, NULL); + bool executable = true; + char **argv = tv_to_argv(&argvars[0], NULL, &executable); if (!argv) { + if (!executable) { + set_vim_var_nr(VV_SHELL_ERROR, (long)-1); + } xfree(input); return; // Already did emsg. } @@ -17012,7 +16431,7 @@ static void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv, if (res == NULL) { if (retlist) { // return an empty list when there's no output - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); } else { rettv->vval.v_string = (char_u *) xstrdup(""); } @@ -17022,9 +16441,9 @@ static void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv, if (retlist) { int keepempty = 0; if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) { - keepempty = get_tv_number(&argvars[2]); + keepempty = tv_get_number(&argvars[2]); } - rettv->vval.v_list = string_to_list((char_u *) res, nread, keepempty != 0); + rettv->vval.v_list = string_to_list(res, nread, (bool)keepempty); rettv->vval.v_list->lv_refcount++; rettv->v_type = VAR_LIST; @@ -17067,20 +16486,20 @@ static void f_systemlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - tabpage_T *tp; win_T *wp = NULL; - if (argvars[0].v_type == VAR_UNKNOWN) + if (argvars[0].v_type == VAR_UNKNOWN) { wp = firstwin; - else { - tp = find_tabpage((int)get_tv_number(&argvars[0])); - if (tp != NULL) + } else { + tabpage_T *const tp = find_tabpage((int)tv_get_number(&argvars[0])); + if (tp != NULL) { wp = (tp == curtab) ? firstwin : tp->tp_firstwin; + } } if (wp != NULL) { - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); while (wp != NULL) { - list_append_number(rettv->vval.v_list, wp->w_buffer->b_fnum); + tv_list_append_number(rettv->vval.v_list, wp->w_buffer->b_fnum); wp = wp->w_next; } } @@ -17093,19 +16512,20 @@ static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_tabpagenr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int nr = 1; - char_u *arg; if (argvars[0].v_type != VAR_UNKNOWN) { - arg = get_tv_string_chk(&argvars[0]); + const char *const arg = tv_get_string_chk(&argvars[0]); nr = 0; if (arg != NULL) { - if (STRCMP(arg, "$") == 0) + if (strcmp(arg, "$") == 0) { nr = tabpage_index(NULL) - 1; - else + } else { EMSG2(_(e_invexpr2), arg); + } } - } else + } else { nr = tabpage_index(curtab); + } rettv->vval.v_number = nr; } @@ -17119,19 +16539,19 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar) win_T *twin; int nr = 1; win_T *wp; - char_u *arg; twin = (tp == curtab) ? curwin : tp->tp_curwin; if (argvar->v_type != VAR_UNKNOWN) { - arg = get_tv_string_chk(argvar); - if (arg == NULL) - nr = 0; /* type error; errmsg already given */ - else if (STRCMP(arg, "$") == 0) + const char *const arg = tv_get_string_chk(argvar); + if (arg == NULL) { + nr = 0; // Type error; errmsg already given. + } else if (strcmp(arg, "$") == 0) { twin = (tp == curtab) ? lastwin : tp->tp_lastwin; - else if (STRCMP(arg, "#") == 0) { + } else if (strcmp(arg, "#") == 0) { twin = (tp == curtab) ? prevwin : tp->tp_prevwin; - if (twin == NULL) + if (twin == NULL) { nr = 0; + } } else { EMSG2(_(e_invexpr2), arg); nr = 0; @@ -17157,13 +16577,12 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar) static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int nr = 1; - tabpage_T *tp; - - tp = find_tabpage((int)get_tv_number(&argvars[0])); - if (tp == NULL) + tabpage_T *const tp = find_tabpage((int)tv_get_number(&argvars[0])); + if (tp == NULL) { nr = 0; - else + } else { nr = get_winnr(tp, &argvars[1]); + } rettv->vval.v_number = nr; } @@ -17173,16 +16592,16 @@ static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_tagfiles(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *fname; + char *fname; tagname_T tn; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); fname = xmalloc(MAXPATHL); - int first = TRUE; - while (get_tagfname(&tn, first, fname) == OK) { - list_append_string(rettv->vval.v_list, fname, -1); - first = FALSE; + bool first = true; + while (get_tagfname(&tn, first, (char_u *)fname) == OK) { + tv_list_append_string(rettv->vval.v_list, fname, -1); + first = false; } tagname_free(&tn); @@ -17194,15 +16613,19 @@ static void f_tagfiles(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_taglist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *tag_pattern; - - tag_pattern = get_tv_string(&argvars[0]); + const char *const tag_pattern = tv_get_string(&argvars[0]); - rettv->vval.v_number = FALSE; - if (*tag_pattern == NUL) + rettv->vval.v_number = false; + if (*tag_pattern == NUL) { return; + } - (void)get_tags(rettv_list_alloc(rettv), tag_pattern); + const char *fname = NULL; + if (argvars[1].v_type != VAR_UNKNOWN) { + fname = tv_get_string(&argvars[1]); + } + (void)get_tags(tv_list_alloc_ret(rettv), (char_u *)tag_pattern, + (char_u *)fname); } /* @@ -17226,7 +16649,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - char *cmd; + const char *cmd; bool executable = true; char **argv = tv_to_argv(&argvars[0], &cmd, &executable); if (!argv) { @@ -17244,15 +16667,15 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) Callback on_stdout = CALLBACK_NONE, on_stderr = CALLBACK_NONE, on_exit = CALLBACK_NONE; dict_T *job_opts = NULL; - char *cwd = "."; + const char *cwd = "."; if (argvars[1].v_type == VAR_DICT) { job_opts = argvars[1].vval.v_dict; - char *new_cwd = (char *)get_dict_string(job_opts, "cwd", false); - if (new_cwd && strlen(new_cwd) > 0) { + const char *const new_cwd = tv_dict_get_string(job_opts, "cwd", false); + if (new_cwd && *new_cwd != NUL) { cwd = new_cwd; // The new cwd must be a directory. - if (!os_isdir((char_u *)cwd)) { + if (!os_isdir((const char_u *)cwd)) { EMSG2(_(e_invarg2), "expected valid directory"); shell_free_argv(argv); return; @@ -17289,13 +16712,15 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) // at this point the buffer has no terminal instance associated yet, so unset // the 'swapfile' option to ensure no swap file will be created curbuf->b_p_swf = false; - (void)setfname(curbuf, (uint8_t *)buf, NULL, true); + (void)setfname(curbuf, (char_u *)buf, NULL, true); // Save the job id and pid in b:terminal_job_{id,pid} - Error err; - dict_set_value(curbuf->b_vars, cstr_as_string("terminal_job_id"), - INTEGER_OBJ(rettv->vval.v_number), false, false, &err); - dict_set_value(curbuf->b_vars, cstr_as_string("terminal_job_pid"), - INTEGER_OBJ(pid), false, false, &err); + Error err = ERROR_INIT; + dict_set_var(curbuf->b_vars, cstr_as_string("terminal_job_id"), + INTEGER_OBJ(rettv->vval.v_number), false, false, &err); + api_clear_error(&err); + dict_set_var(curbuf->b_vars, cstr_as_string("terminal_job_pid"), + INTEGER_OBJ(pid), false, false, &err); + api_clear_error(&err); Terminal *term = terminal_open(topts); data->term = term; @@ -17304,7 +16729,17 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } -static bool callback_from_typval(Callback *callback, typval_T *arg) +// "test_garbagecollect_now()" function +static void f_test_garbagecollect_now(typval_T *argvars, + typval_T *rettv, FunPtr fptr) +{ + // This is dangerous, any Lists and Dicts used internally may be freed + // while still in use. + garbage_collect(true); +} + +bool callback_from_typval(Callback *const callback, typval_T *const arg) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { if (arg->v_type == VAR_PARTIAL && arg->vval.v_partial != NULL) { callback->data.partial = arg->vval.v_partial; @@ -17324,53 +16759,33 @@ static bool callback_from_typval(Callback *callback, typval_T *arg) return true; } - /// Unref/free callback -static void callback_free(Callback *callback) +void callback_free(Callback *const callback) + FUNC_ATTR_NONNULL_ALL { switch (callback->type) { - case kCallbackFuncref: + case kCallbackFuncref: { func_unref(callback->data.funcref); xfree(callback->data.funcref); break; - - case kCallbackPartial: + } + case kCallbackPartial: { partial_unref(callback->data.partial); break; - - case kCallbackNone: + } + case kCallbackNone: { break; - - default: + } + default: { abort(); + } } callback->type = kCallbackNone; } -static bool callback_equal(Callback *cb1, Callback *cb2) -{ - if (cb1->type != cb2->type) { - return false; - } - switch (cb1->type) { - case kCallbackFuncref: - return STRCMP(cb1->data.funcref, cb2->data.funcref) == 0; - - case kCallbackPartial: - // FIXME: this is inconsistent with tv_equal but is needed for precision - // maybe change dictwatcheradd to return a watcher id instead? - return cb1->data.partial == cb2->data.partial; - - case kCallbackNone: - return true; - - default: - abort(); - } -} - -static bool callback_call(Callback *callback, int argcount_in, - typval_T *argvars_in, typval_T *rettv) +bool callback_call(Callback *const callback, const int argcount_in, + typval_T *const argvars_in, typval_T *const rettv) + FUNC_ATTR_NONNULL_ALL { partial_T *partial; char_u *name; @@ -17382,7 +16797,7 @@ static bool callback_call(Callback *callback, int argcount_in, case kCallbackPartial: partial = callback->data.partial; - name = partial->pt_name; + name = partial_name(partial); break; case kCallbackNone: @@ -17395,7 +16810,7 @@ static bool callback_call(Callback *callback, int argcount_in, int dummy; return call_func(name, (int)STRLEN(name), rettv, argcount_in, argvars_in, - curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy, + NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy, true, partial, NULL); } @@ -17422,11 +16837,82 @@ static bool set_ref_in_callback(Callback *callback, int copyID, return false; } +static void add_timer_info(typval_T *rettv, timer_T *timer) +{ + list_T *list = rettv->vval.v_list; + dict_T *dict = tv_dict_alloc(); + + tv_list_append_dict(list, dict); + tv_dict_add_nr(dict, S_LEN("id"), timer->timer_id); + tv_dict_add_nr(dict, S_LEN("time"), timer->timeout); + tv_dict_add_nr(dict, S_LEN("paused"), timer->paused); + + tv_dict_add_nr(dict, S_LEN("repeat"), + (timer->repeat_count < 0 ? -1 : timer->repeat_count)); + + dictitem_T *di = tv_dict_item_alloc("callback"); + if (tv_dict_add(dict, di) == FAIL) { + xfree(di); + return; + } + + if (timer->callback.type == kCallbackPartial) { + di->di_tv.v_type = VAR_PARTIAL; + di->di_tv.vval.v_partial = timer->callback.data.partial; + timer->callback.data.partial->pt_refcount++; + } else if (timer->callback.type == kCallbackFuncref) { + di->di_tv.v_type = VAR_FUNC; + di->di_tv.vval.v_string = vim_strsave(timer->callback.data.funcref); + } + di->di_tv.v_lock = 0; +} + +static void add_timer_info_all(typval_T *rettv) +{ + timer_T *timer; + map_foreach_value(timers, timer, { + if (!timer->stopped) { + add_timer_info(rettv, timer); + } + }) +} + +/// "timer_info([timer])" function +static void f_timer_info(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + tv_list_alloc_ret(rettv); + if (argvars[0].v_type != VAR_UNKNOWN) { + if (argvars[0].v_type != VAR_NUMBER) { + EMSG(_(e_number_exp)); + return; + } + timer_T *timer = pmap_get(uint64_t)(timers, tv_get_number(&argvars[0])); + if (timer != NULL && !timer->stopped) { + add_timer_info(rettv, timer); + } + } else { + add_timer_info_all(rettv); + } +} + +/// "timer_pause(timer, paused)" function +static void f_timer_pause(typval_T *argvars, typval_T *unused, FunPtr fptr) +{ + if (argvars[0].v_type != VAR_NUMBER) { + EMSG(_(e_number_exp)); + return; + } + int paused = (bool)tv_get_number(&argvars[1]); + timer_T *timer = pmap_get(uint64_t)(timers, tv_get_number(&argvars[0])); + if (timer != NULL) { + timer->paused = paused; + } +} /// "timer_start(timeout, callback, opts)" function static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - long timeout = get_tv_number(&argvars[0]); + const long timeout = tv_get_number(&argvars[0]); timer_T *timer; int repeat = 1; dict_T *dict; @@ -17436,11 +16922,12 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[2].v_type != VAR_UNKNOWN) { if (argvars[2].v_type != VAR_DICT || (dict = argvars[2].vval.v_dict) == NULL) { - EMSG2(_(e_invarg2), get_tv_string(&argvars[2])); + EMSG2(_(e_invarg2), tv_get_string(&argvars[2])); return; } - if (dict_find(dict, (char_u *)"repeat", -1) != NULL) { - repeat = get_dict_number(dict, "repeat"); + dictitem_T *const di = tv_dict_find(dict, S_LEN("repeat")); + if (di != NULL) { + repeat = tv_get_number(&di->di_tv); if (repeat == 0) { repeat = 1; } @@ -17455,6 +16942,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr) timer = xmalloc(sizeof *timer); timer->refcount = 1; timer->stopped = false; + timer->paused = false; timer->repeat_count = repeat; timer->timeout = timeout; timer->timer_id = last_timer_id++; @@ -17464,8 +16952,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr) timer->tw.events = multiqueue_new_child(main_loop.events); // if main loop is blocked, don't queue up multiple events timer->tw.blockable = true; - time_watcher_start(&timer->tw, timer_due_cb, timeout, - timeout * (repeat != 1)); + time_watcher_start(&timer->tw, timer_due_cb, timeout, timeout); pmap_put(uint64_t)(timers, timer->timer_id, timer); rettv->vval.v_number = timer->timer_id; @@ -17480,7 +16967,7 @@ static void f_timer_stop(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - timer_T *timer = pmap_get(uint64_t)(timers, get_tv_number(&argvars[0])); + timer_T *timer = pmap_get(uint64_t)(timers, tv_get_number(&argvars[0])); if (timer == NULL) { return; @@ -17489,28 +16976,32 @@ static void f_timer_stop(typval_T *argvars, typval_T *rettv, FunPtr fptr) timer_stop(timer); } +static void f_timer_stopall(typval_T *argvars, typval_T *unused, FunPtr fptr) +{ + timer_stop_all(); +} + // invoked on the main loop static void timer_due_cb(TimeWatcher *tw, void *data) { timer_T *timer = (timer_T *)data; - if (timer->stopped) { + if (timer->stopped || timer->paused) { return; } + timer->refcount++; // if repeat was negative repeat forever if (timer->repeat_count >= 0 && --timer->repeat_count == 0) { timer_stop(timer); } - typval_T argv[2]; - init_tv(argv); + typval_T argv[2] = { TV_INITIAL_VALUE, TV_INITIAL_VALUE }; argv[0].v_type = VAR_NUMBER; argv[0].vval.v_number = timer->timer_id; - typval_T rettv; + typval_T rettv = TV_INITIAL_VALUE; - init_tv(&rettv); callback_call(&timer->callback, 1, argv, &rettv); - clear_tv(&rettv); + tv_clear(&rettv); if (!timer->stopped && timer->timeout == 0) { // special case: timeout=0 means the callback will be @@ -17550,7 +17041,7 @@ static void timer_decref(timer_T *timer) } } -void timer_teardown(void) +static void timer_stop_all(void) { timer_T *timer; map_foreach_value(timers, timer, { @@ -17558,35 +17049,19 @@ void timer_teardown(void) }) } +void timer_teardown(void) +{ + timer_stop_all(); +} + /* * "tolower(string)" function */ static void f_tolower(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p = vim_strsave(get_tv_string(&argvars[0])); rettv->v_type = VAR_STRING; - rettv->vval.v_string = p; - - while (*p != NUL) { - int l; - - if (enc_utf8) { - int c, lc; - - c = utf_ptr2char(p); - lc = utf_tolower(c); - l = utf_ptr2len(p); - /* TODO: reallocate string when byte count changes. */ - if (utf_char2len(lc) == l) - utf_char2bytes(lc, p); - p += l; - } else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) - p += l; /* skip multi-byte character */ - else { - *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */ - ++p; - } - } + rettv->vval.v_string = (char_u *)strcase_save(tv_get_string(&argvars[0]), + false); } /* @@ -17595,7 +17070,8 @@ static void f_tolower(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_toupper(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = strup_save(get_tv_string(&argvars[0])); + rettv->vval.v_string = (char_u *)strcase_save(tv_get_string(&argvars[0]), + true); } /* @@ -17603,77 +17079,71 @@ static void f_toupper(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_tr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *in_str; - char_u *fromstr; - char_u *tostr; - char_u *p; - int inlen; - int fromlen; - int tolen; - int idx; - char_u *cpstr; - int cplen; - int first = TRUE; - char_u buf[NUMBUFLEN]; - char_u buf2[NUMBUFLEN]; - garray_T ga; + char buf[NUMBUFLEN]; + char buf2[NUMBUFLEN]; - in_str = get_tv_string(&argvars[0]); - fromstr = get_tv_string_buf_chk(&argvars[1], buf); - tostr = get_tv_string_buf_chk(&argvars[2], buf2); + const char *in_str = tv_get_string(&argvars[0]); + const char *fromstr = tv_get_string_buf_chk(&argvars[1], buf); + const char *tostr = tv_get_string_buf_chk(&argvars[2], buf2); - /* Default return value: empty string. */ + // Default return value: empty string. rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - if (fromstr == NULL || tostr == NULL) - return; /* type error; errmsg already given */ + if (fromstr == NULL || tostr == NULL) { + return; // Type error; errmsg already given. + } + garray_T ga; ga_init(&ga, (int)sizeof(char), 80); - if (!has_mbyte) - /* not multi-byte: fromstr and tostr must be the same length */ - if (STRLEN(fromstr) != STRLEN(tostr)) { -error: - EMSG2(_(e_invarg2), fromstr); - ga_clear(&ga); - return; + if (!has_mbyte) { + // Not multi-byte: fromstr and tostr must be the same length. + if (strlen(fromstr) != strlen(tostr)) { + goto error; } + } - /* fromstr and tostr have to contain the same number of chars */ + // fromstr and tostr have to contain the same number of chars. + bool first = true; while (*in_str != NUL) { if (has_mbyte) { - inlen = (*mb_ptr2len)(in_str); - cpstr = in_str; - cplen = inlen; - idx = 0; - for (p = fromstr; *p != NUL; p += fromlen) { - fromlen = (*mb_ptr2len)(p); + const char *cpstr = in_str; + const int inlen = (*mb_ptr2len)((const char_u *)in_str); + int cplen = inlen; + int idx = 0; + int fromlen; + for (const char *p = fromstr; *p != NUL; p += fromlen) { + fromlen = (*mb_ptr2len)((const char_u *)p); if (fromlen == inlen && STRNCMP(in_str, p, inlen) == 0) { + int tolen; for (p = tostr; *p != NUL; p += tolen) { - tolen = (*mb_ptr2len)(p); + tolen = (*mb_ptr2len)((const char_u *)p); if (idx-- == 0) { cplen = tolen; - cpstr = p; + cpstr = (char *)p; break; } } - if (*p == NUL) /* tostr is shorter than fromstr */ + if (*p == NUL) { // tostr is shorter than fromstr. goto error; + } break; } - ++idx; + idx++; } if (first && cpstr == in_str) { - /* Check that fromstr and tostr have the same number of - * (multi-byte) characters. Done only once when a character - * of in_str doesn't appear in fromstr. */ - first = FALSE; - for (p = tostr; *p != NUL; p += tolen) { - tolen = (*mb_ptr2len)(p); - --idx; + // Check that fromstr and tostr have the same number of + // (multi-byte) characters. Done only once when a character + // of in_str doesn't appear in fromstr. + first = false; + int tolen; + for (const char *p = tostr; *p != NUL; p += tolen) { + tolen = (*mb_ptr2len)((const char_u *)p); + idx--; } - if (idx != 0) + if (idx != 0) { goto error; + } } ga_grow(&ga, cplen); @@ -17682,13 +17152,14 @@ error: in_str += inlen; } else { - /* When not using multi-byte chars we can do it faster. */ - p = vim_strchr(fromstr, *in_str); - if (p != NULL) + // When not using multi-byte chars we can do it faster. + const char *const p = strchr(fromstr, *in_str); + if (p != NULL) { ga_append(&ga, tostr[p - fromstr]); - else + } else { ga_append(&ga, *in_str); - ++in_str; + } + in_str++; } } @@ -17696,6 +17167,11 @@ error: ga_append(&ga, NUL); rettv->vval.v_string = ga.ga_data; + return; +error: + EMSG2(_(e_invarg2), fromstr); + ga_clear(&ga); + return; } /* @@ -17741,20 +17217,18 @@ static void f_type(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_undofile(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - { - char_u *fname = get_tv_string(&argvars[0]); + const char *const fname = tv_get_string(&argvars[0]); - if (*fname == NUL) { - /* If there is no file name there will be no undo file. */ - rettv->vval.v_string = NULL; - } else { - char *ffname = FullName_save((char *)fname, false); + if (*fname == NUL) { + // If there is no file name there will be no undo file. + rettv->vval.v_string = NULL; + } else { + char *ffname = FullName_save(fname, false); - if (ffname != NULL) { - rettv->vval.v_string = (char_u *)u_get_undo_file_name(ffname, false); - } - xfree(ffname); + if (ffname != NULL) { + rettv->vval.v_string = (char_u *)u_get_undo_file_name(ffname, false); } + xfree(ffname); } } @@ -17763,22 +17237,22 @@ static void f_undofile(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_undotree(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv_dict_alloc(rettv); + tv_dict_alloc_ret(rettv); dict_T *dict = rettv->vval.v_dict; list_T *list; - dict_add_nr_str(dict, "synced", (long)curbuf->b_u_synced, NULL); - dict_add_nr_str(dict, "seq_last", curbuf->b_u_seq_last, NULL); - dict_add_nr_str(dict, "save_last", - (long)curbuf->b_u_save_nr_last, NULL); - dict_add_nr_str(dict, "seq_cur", curbuf->b_u_seq_cur, NULL); - dict_add_nr_str(dict, "time_cur", (long)curbuf->b_u_time_cur, NULL); - dict_add_nr_str(dict, "save_cur", (long)curbuf->b_u_save_nr_cur, NULL); + tv_dict_add_nr(dict, S_LEN("synced"), (varnumber_T)curbuf->b_u_synced); + tv_dict_add_nr(dict, S_LEN("seq_last"), (varnumber_T)curbuf->b_u_seq_last); + tv_dict_add_nr(dict, S_LEN("save_last"), + (varnumber_T)curbuf->b_u_save_nr_last); + tv_dict_add_nr(dict, S_LEN("seq_cur"), (varnumber_T)curbuf->b_u_seq_cur); + tv_dict_add_nr(dict, S_LEN("time_cur"), (varnumber_T)curbuf->b_u_time_cur); + tv_dict_add_nr(dict, S_LEN("save_cur"), (varnumber_T)curbuf->b_u_save_nr_cur); - list = list_alloc(); + list = tv_list_alloc(); u_eval_tree(curbuf->b_u_oldhead, list); - dict_add_list(dict, "entries", list); + tv_dict_add_list(dict, S_LEN("entries"), list); } /* @@ -17837,7 +17311,7 @@ static void f_wildmenumode(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "win_findbuf()" function static void f_win_findbuf(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); win_findbuf(argvars, rettv->vval.v_list); } @@ -17856,7 +17330,7 @@ static void f_win_gotoid(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "win_id2tabwin()" function static void f_win_id2tabwin(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); win_id2tabwin(argvars, rettv->vval.v_list); } @@ -17951,36 +17425,37 @@ static void f_winrestcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_winrestview(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - dict_T *dict; + dict_T *dict; if (argvars[0].v_type != VAR_DICT - || (dict = argvars[0].vval.v_dict) == NULL) - EMSG(_(e_invarg)); - else { - if (dict_find(dict, (char_u *)"lnum", -1) != NULL) { - curwin->w_cursor.lnum = get_dict_number(dict, "lnum"); + || (dict = argvars[0].vval.v_dict) == NULL) { + emsgf(_(e_invarg)); + } else { + dictitem_T *di; + if ((di = tv_dict_find(dict, S_LEN("lnum"))) != NULL) { + curwin->w_cursor.lnum = tv_get_number(&di->di_tv); } - if (dict_find(dict, (char_u *)"col", -1) != NULL) { - curwin->w_cursor.col = get_dict_number(dict, "col"); + if ((di = tv_dict_find(dict, S_LEN("col"))) != NULL) { + curwin->w_cursor.col = tv_get_number(&di->di_tv); } - if (dict_find(dict, (char_u *)"coladd", -1) != NULL) { - curwin->w_cursor.coladd = get_dict_number(dict, "coladd"); + if ((di = tv_dict_find(dict, S_LEN("coladd"))) != NULL) { + curwin->w_cursor.coladd = tv_get_number(&di->di_tv); } - if (dict_find(dict, (char_u *)"curswant", -1) != NULL) { - curwin->w_curswant = get_dict_number(dict, "curswant"); + if ((di = tv_dict_find(dict, S_LEN("curswant"))) != NULL) { + curwin->w_curswant = tv_get_number(&di->di_tv); curwin->w_set_curswant = false; } - if (dict_find(dict, (char_u *)"topline", -1) != NULL) { - set_topline(curwin, get_dict_number(dict, "topline")); + if ((di = tv_dict_find(dict, S_LEN("topline"))) != NULL) { + set_topline(curwin, tv_get_number(&di->di_tv)); } - if (dict_find(dict, (char_u *)"topfill", -1) != NULL) { - curwin->w_topfill = get_dict_number(dict, "topfill"); + if ((di = tv_dict_find(dict, S_LEN("topfill"))) != NULL) { + curwin->w_topfill = tv_get_number(&di->di_tv); } - if (dict_find(dict, (char_u *)"leftcol", -1) != NULL) { - curwin->w_leftcol = get_dict_number(dict, "leftcol"); + if ((di = tv_dict_find(dict, S_LEN("leftcol"))) != NULL) { + curwin->w_leftcol = tv_get_number(&di->di_tv); } - if (dict_find(dict, (char_u *)"skipcol", -1) != NULL) { - curwin->w_skipcol = get_dict_number(dict, "skipcol"); + if ((di = tv_dict_find(dict, S_LEN("skipcol"))) != NULL) { + curwin->w_skipcol = tv_get_number(&di->di_tv); } check_cursor(); @@ -18003,45 +17478,103 @@ static void f_winsaveview(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_T *dict; - rettv_dict_alloc(rettv); + tv_dict_alloc_ret(rettv); dict = rettv->vval.v_dict; - dict_add_nr_str(dict, "lnum", (long)curwin->w_cursor.lnum, NULL); - dict_add_nr_str(dict, "col", (long)curwin->w_cursor.col, NULL); - dict_add_nr_str(dict, "coladd", (long)curwin->w_cursor.coladd, NULL); + tv_dict_add_nr(dict, S_LEN("lnum"), (varnumber_T)curwin->w_cursor.lnum); + tv_dict_add_nr(dict, S_LEN("col"), (varnumber_T)curwin->w_cursor.col); + tv_dict_add_nr(dict, S_LEN("coladd"), (varnumber_T)curwin->w_cursor.coladd); update_curswant(); - dict_add_nr_str(dict, "curswant", (long)curwin->w_curswant, NULL); + tv_dict_add_nr(dict, S_LEN("curswant"), (varnumber_T)curwin->w_curswant); - dict_add_nr_str(dict, "topline", (long)curwin->w_topline, NULL); - dict_add_nr_str(dict, "topfill", (long)curwin->w_topfill, NULL); - dict_add_nr_str(dict, "leftcol", (long)curwin->w_leftcol, NULL); - dict_add_nr_str(dict, "skipcol", (long)curwin->w_skipcol, NULL); + tv_dict_add_nr(dict, S_LEN("topline"), (varnumber_T)curwin->w_topline); + tv_dict_add_nr(dict, S_LEN("topfill"), (varnumber_T)curwin->w_topfill); + tv_dict_add_nr(dict, S_LEN("leftcol"), (varnumber_T)curwin->w_leftcol); + tv_dict_add_nr(dict, S_LEN("skipcol"), (varnumber_T)curwin->w_skipcol); } /// Writes list of strings to file -static bool write_list(FILE *fd, list_T *list, bool binary) +/// +/// @param fp File to write to. +/// @param[in] list List to write. +/// @param[in] binary Whether to write in binary mode. +/// +/// @return true in case of success, false otherwise. +static bool write_list(FileDescriptor *const fp, const list_T *const list, + const bool binary) { - int ret = true; - - for (listitem_T *li = list->lv_first; li != NULL; li = li->li_next) { - for (char_u *s = get_tv_string(&li->li_tv); *s != NUL; ++s) { - if (putc(*s == '\n' ? NUL : *s, fd) == EOF) { - ret = false; - break; + int error = 0; + for (const listitem_T *li = list->lv_first; li != NULL; li = li->li_next) { + const char *const s = tv_get_string_chk(&li->li_tv); + if (s == NULL) { + return false; + } + const char *hunk_start = s; + for (const char *p = hunk_start;; p++) { + if (*p == NUL || *p == NL) { + if (p != hunk_start) { + const ptrdiff_t written = file_write(fp, hunk_start, + (size_t)(p - hunk_start)); + if (written < 0) { + error = (int)written; + goto write_list_error; + } + } + if (*p == NUL) { + break; + } else { + hunk_start = p + 1; + const ptrdiff_t written = file_write(fp, (char[]){ NUL }, 1); + if (written < 0) { + error = (int)written; + break; + } + } } } if (!binary || li->li_next != NULL) { - if (putc('\n', fd) == EOF) { - ret = false; - break; + const ptrdiff_t written = file_write(fp, "\n", 1); + if (written < 0) { + error = (int)written; + goto write_list_error; } } - if (ret == false) { - EMSG(_(e_write)); - break; + } + if ((error = file_flush(fp)) != 0) { + goto write_list_error; + } + return true; +write_list_error: + emsgf(_("E80: Error while writing: %s"), os_strerror(error)); + return false; +} + +/// Initializes a static list with 10 items. +void init_static_list(staticList10_T *sl) +{ + list_T *l = &sl->sl_list; + + memset(sl, 0, sizeof(staticList10_T)); + l->lv_first = &sl->sl_items[0]; + l->lv_last = &sl->sl_items[9]; + l->lv_refcount = DO_NOT_FREE_CNT; + l->lv_lock = VAR_FIXED; + sl->sl_list.lv_len = 10; + + for (int i = 0; i < 10; i++) { + listitem_T *li = &sl->sl_items[i]; + + if (i == 0) { + li->li_prev = NULL; + } else { + li->li_prev = li - 1; + } + if (i == 9) { + li->li_next = NULL; + } else { + li->li_next = li + 1; } } - return ret; } /// Saves a typval_T as a string. @@ -18053,7 +17586,7 @@ static bool write_list(FILE *fd, list_T *list, bool binary) /// @param[in] endnl If true, the output will end in a newline (if a list). /// @returns an allocated string if `tv` represents a VimL string, list, or /// number; NULL otherwise. -static char_u *save_tv_as_string(typval_T *tv, ssize_t *len, bool endnl) +static char *save_tv_as_string(typval_T *tv, ptrdiff_t *const len, bool endnl) FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { if (tv->v_type == VAR_UNKNOWN) { @@ -18061,34 +17594,33 @@ static char_u *save_tv_as_string(typval_T *tv, ssize_t *len, bool endnl) return NULL; } - // For types other than list, let get_tv_string_buf_chk() get the value or + // For types other than list, let tv_get_string_buf_chk() get the value or // print an error. if (tv->v_type != VAR_LIST) { - char_u *ret = get_tv_string_chk(tv); - if (ret && (*len = STRLEN(ret))) { - ret = vim_strsave(ret); + const char *ret = tv_get_string_chk(tv); + if (ret && (*len = strlen(ret))) { + return xmemdupz(ret, (size_t)(*len)); } else { - ret = NULL; *len = -1; + return NULL; } - return ret; } // Pre-calculate the resulting length. *len = 0; list_T *list = tv->vval.v_list; for (listitem_T *li = list->lv_first; li != NULL; li = li->li_next) { - *len += STRLEN(get_tv_string(&li->li_tv)) + 1; + *len += strlen(tv_get_string(&li->li_tv)) + 1; } if (*len == 0) { return NULL; } - char_u *ret = xmalloc(*len + endnl); - char_u *end = ret; + char *ret = xmalloc(*len + endnl); + char *end = ret; for (listitem_T *li = list->lv_first; li != NULL; li = li->li_next) { - for (char_u *s = get_tv_string(&li->li_tv); *s != NUL; s++) { + for (const char *s = tv_get_string(&li->li_tv); *s != NUL; s++) { *end++ = (*s == '\n') ? NUL : *s; } if (endnl || li->li_next != NULL) { @@ -18117,7 +17649,7 @@ static void f_winwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "wordcount()" function static void f_wordcount(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv_dict_alloc(rettv); + tv_dict_alloc_ret(rettv); cursor_pos_info(rettv->vval.v_dict); } @@ -18140,28 +17672,50 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr) bool binary = false; bool append = false; + bool do_fsync = !!p_fs; if (argvars[2].v_type != VAR_UNKNOWN) { - if (vim_strchr(get_tv_string(&argvars[2]), 'b')) { - binary = true; + const char *const flags = tv_get_string_chk(&argvars[2]); + if (flags == NULL) { + return; } - if (vim_strchr(get_tv_string(&argvars[2]), 'a')) { - append = true; + for (const char *p = flags; *p; p++) { + switch (*p) { + case 'b': { binary = true; break; } + case 'a': { append = true; break; } + case 's': { do_fsync = true; break; } + case 'S': { do_fsync = false; break; } + default: { + // Using %s, p and not %c, *p to preserve multibyte characters + emsgf(_("E5060: Unknown flag: %s"), p); + return; + } + } } } - // Always open the file in binary mode, library functions have a mind of - // their own about CR-LF conversion. - char_u *fname = get_tv_string(&argvars[1]); - FILE *fd; - if (*fname == NUL || (fd = mch_fopen((char *)fname, - append ? APPENDBIN : WRITEBIN)) == NULL) { - EMSG2(_(e_notcreate), *fname == NUL ? (char_u *)_("<empty>") : fname); - rettv->vval.v_number = -1; + char buf[NUMBUFLEN]; + const char *const fname = tv_get_string_buf_chk(&argvars[1], buf); + if (fname == NULL) { + return; + } + FileDescriptor fp; + int error; + rettv->vval.v_number = -1; + if (*fname == NUL) { + EMSG(_("E482: Can't open file with an empty name")); + } else if ((error = file_open(&fp, fname, + ((append ? kFileAppend : kFileTruncate) + | kFileCreate), 0666)) != 0) { + emsgf(_("E482: Can't open file %s for writing: %s"), + fname, os_strerror(error)); } else { - if (write_list(fd, argvars[0].vval.v_list, binary) == false) { - rettv->vval.v_number = -1; + if (write_list(&fp, argvars[0].vval.v_list, binary)) { + rettv->vval.v_number = 0; + } + if ((error = file_close(&fp, do_fsync)) != 0) { + emsgf(_("E80: Error when closing file %s: %s"), + fname, os_strerror(error)); } - fclose(fd); } } /* @@ -18169,82 +17723,96 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_xor(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL) - ^ get_tv_number_chk(&argvars[1], NULL); + rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL) + ^ tv_get_number_chk(&argvars[1], NULL); } -/* - * Translate a String variable into a position. - * Returns NULL when there is an error. - */ -static pos_T * -var2fpos ( - typval_T *varp, - int dollar_lnum, /* TRUE when $ is last line */ - int *fnum /* set to fnum for '0, 'A, etc. */ -) +/// Translate a VimL object into a position +/// +/// Accepts VAR_LIST and VAR_STRING objects. Does not give an error for invalid +/// type. +/// +/// @param[in] tv Object to translate. +/// @param[in] dollar_lnum True when "$" is last line. +/// @param[out] ret_fnum Set to fnum for marks. +/// +/// @return Pointer to position or NULL in case of error (e.g. invalid type). +pos_T *var2fpos(const typval_T *const tv, const int dollar_lnum, + int *const ret_fnum) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { - char_u *name; static pos_T pos; pos_T *pp; - /* Argument can be [lnum, col, coladd]. */ - if (varp->v_type == VAR_LIST) { + // Argument can be [lnum, col, coladd]. + if (tv->v_type == VAR_LIST) { list_T *l; int len; - int error = FALSE; - listitem_T *li; + bool error = false; + listitem_T *li; - l = varp->vval.v_list; - if (l == NULL) + l = tv->vval.v_list; + if (l == NULL) { return NULL; + } - /* Get the line number */ - pos.lnum = list_find_nr(l, 0L, &error); - if (error || pos.lnum <= 0 || pos.lnum > curbuf->b_ml.ml_line_count) - return NULL; /* invalid line number */ + // Get the line number. + pos.lnum = tv_list_find_nr(l, 0L, &error); + if (error || pos.lnum <= 0 || pos.lnum > curbuf->b_ml.ml_line_count) { + // Invalid line number. + return NULL; + } - /* Get the column number */ - pos.col = list_find_nr(l, 1L, &error); - if (error) + // Get the column number. + pos.col = tv_list_find_nr(l, 1L, &error); + if (error) { return NULL; + } len = (long)STRLEN(ml_get(pos.lnum)); - /* We accept "$" for the column number: last column. */ - li = list_find(l, 1L); + // We accept "$" for the column number: last column. + li = tv_list_find(l, 1L); if (li != NULL && li->li_tv.v_type == VAR_STRING && li->li_tv.vval.v_string != NULL - && STRCMP(li->li_tv.vval.v_string, "$") == 0) + && STRCMP(li->li_tv.vval.v_string, "$") == 0) { pos.col = len + 1; + } - /* Accept a position up to the NUL after the line. */ - if (pos.col == 0 || (int)pos.col > len + 1) - return NULL; /* invalid column number */ - --pos.col; + // Accept a position up to the NUL after the line. + if (pos.col == 0 || (int)pos.col > len + 1) { + // Invalid column number. + return NULL; + } + pos.col--; - /* Get the virtual offset. Defaults to zero. */ - pos.coladd = list_find_nr(l, 2L, &error); - if (error) + // Get the virtual offset. Defaults to zero. + pos.coladd = tv_list_find_nr(l, 2L, &error); + if (error) { pos.coladd = 0; + } return &pos; } - name = get_tv_string_chk(varp); - if (name == NULL) + const char *const name = tv_get_string_chk(tv); + if (name == NULL) { return NULL; - if (name[0] == '.') /* cursor */ + } + if (name[0] == '.') { // Cursor. return &curwin->w_cursor; - if (name[0] == 'v' && name[1] == NUL) { /* Visual start */ - if (VIsual_active) + } + if (name[0] == 'v' && name[1] == NUL) { // Visual start. + if (VIsual_active) { return &VIsual; + } return &curwin->w_cursor; } - if (name[0] == '\'') { /* mark */ - pp = getmark_buf_fnum(curbuf, name[1], FALSE, fnum); - if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0) + if (name[0] == '\'') { // Mark. + pp = getmark_buf_fnum(curbuf, (uint8_t)name[1], false, ret_fnum); + if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0) { return NULL; + } return pp; } @@ -18297,32 +17865,37 @@ static int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp) return FAIL; if (fnump != NULL) { - n = list_find_nr(l, i++, NULL); /* fnum */ - if (n < 0) + n = tv_list_find_nr(l, i++, NULL); // fnum + if (n < 0) { return FAIL; - if (n == 0) - n = curbuf->b_fnum; /* current buffer */ + } + if (n == 0) { + n = curbuf->b_fnum; // Current buffer. + } *fnump = n; } - n = list_find_nr(l, i++, NULL); /* lnum */ - if (n < 0) + n = tv_list_find_nr(l, i++, NULL); // lnum + if (n < 0) { return FAIL; + } posp->lnum = n; - n = list_find_nr(l, i++, NULL); /* col */ - if (n < 0) + n = tv_list_find_nr(l, i++, NULL); // col + if (n < 0) { return FAIL; + } posp->col = n; - n = list_find_nr(l, i, NULL); // off - if (n < 0) + n = tv_list_find_nr(l, i, NULL); // off + if (n < 0) { posp->coladd = 0; - else + } else { posp->coladd = n; + } if (curswantp != NULL) { - *curswantp = list_find_nr(l, i + 1, NULL); // curswant + *curswantp = tv_list_find_nr(l, i + 1, NULL); // curswant } return OK; @@ -18333,15 +17906,16 @@ static int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp) * Advance "arg" to the first character after the name. * Return 0 for error. */ -static int get_env_len(char_u **arg) +static int get_env_len(const char_u **arg) { - char_u *p; int len; - for (p = *arg; vim_isIDc(*p); ++p) - ; - if (p == *arg) /* no name found */ + const char_u *p; + for (p = *arg; vim_isIDc(*p); p++) { + } + if (p == *arg) { // No name found. return 0; + } len = (int)(p - *arg); *arg = p; @@ -18351,11 +17925,12 @@ static int get_env_len(char_u **arg) // Get the length of the name of a function or internal variable. // "arg" is advanced to the first non-white character after the name. // Return 0 if something is wrong. -static int get_id_len(char_u **arg) { - char_u *p; +static int get_id_len(const char **const arg) +{ int len; // Find the end of the name. + const char *p; for (p = *arg; eval_isnamec(*p); p++) { if (*p == ':') { // "s:" is start of "s:var", but "n:" is not and can be used in @@ -18372,7 +17947,7 @@ static int get_id_len(char_u **arg) { } len = (int)(p - *arg); - *arg = skipwhite(p); + *arg = (const char *)skipwhite((const char_u *)p); return len; } @@ -18386,18 +17961,18 @@ static int get_id_len(char_u **arg) { * If the name contains 'magic' {}'s, expand them and return the * expanded name in an allocated string via 'alias' - caller must free. */ -static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose) +static int get_name_len(const char **const arg, + char **alias, + int evaluate, + int verbose) { int len; - char_u *p; - char_u *expr_start; - char_u *expr_end; *alias = NULL; /* default to no alias */ - if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA - && (*arg)[2] == (int)KE_SNR) { - /* hard coded <SNR>, already translated */ + if ((*arg)[0] == (char)K_SPECIAL && (*arg)[1] == (char)KS_EXTRA + && (*arg)[2] == (char)KE_SNR) { + // Hard coded <SNR>, already translated. *arg += 3; return get_id_len(arg) + 3; } @@ -18407,17 +17982,17 @@ static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose) *arg += len; } - /* - * Find the end of the name; check for {} construction. - */ - p = find_name_end(*arg, &expr_start, &expr_end, - len > 0 ? 0 : FNE_CHECK_START); + // Find the end of the name; check for {} construction. + char_u *expr_start; + char_u *expr_end; + const char *p = (const char *)find_name_end((char_u *)(*arg), + (const char_u **)&expr_start, + (const char_u **)&expr_end, + len > 0 ? 0 : FNE_CHECK_START); if (expr_start != NULL) { - char_u *temp_string; - if (!evaluate) { len += (int)(p - *arg); - *arg = skipwhite(p); + *arg = (const char *)skipwhite((const char_u *)p); return len; } @@ -18425,11 +18000,13 @@ static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose) * Include any <SID> etc in the expanded string: * Thus the -len here. */ - temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p); - if (temp_string == NULL) + char_u *temp_string = make_expanded_name((char_u *)(*arg) - len, expr_start, + expr_end, (char_u *)p); + if (temp_string == NULL) { return -1; - *alias = temp_string; - *arg = skipwhite(p); + } + *alias = (char *)temp_string; + *arg = (const char *)skipwhite((const char_u *)p); return (int)STRLEN(temp_string); } @@ -18446,12 +18023,11 @@ static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose) // "flags" can have FNE_INCL_BR and FNE_CHECK_START. // Return a pointer to just after the name. Equal to "arg" if there is no // valid name. -static char_u *find_name_end(char_u *arg, char_u **expr_start, - char_u **expr_end, int flags) +static const char_u *find_name_end(const char_u *arg, const char_u **expr_start, + const char_u **expr_end, int flags) { int mb_nest = 0; int br_nest = 0; - char_u *p; int len; if (expr_start != NULL) { @@ -18464,6 +18040,7 @@ static char_u *find_name_end(char_u *arg, char_u **expr_start, return arg; } + const char_u *p; for (p = arg; *p != NUL && (eval_isnamec(*p) || *p == '{' @@ -18535,7 +18112,8 @@ static char_u *find_name_end(char_u *arg, char_u **expr_start, * Returns a new allocated string, which the caller must free. * Returns NULL for failure. */ -static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end) +static char_u *make_expanded_name(const char_u *in_start, char_u *expr_start, + char_u *expr_end, char_u *in_end) { char_u c1; char_u *retval = NULL; @@ -18564,7 +18142,9 @@ static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u * *expr_end = '}'; if (retval != NULL) { - temp_result = find_name_end(retval, &expr_start, &expr_end, 0); + temp_result = (char_u *)find_name_end(retval, + (const char_u **)&expr_start, + (const char_u **)&expr_end, 0); if (expr_start != NULL) { /* Further expansion! */ temp_result = make_expanded_name(retval, expr_start, @@ -18598,7 +18178,7 @@ static int eval_isnamec1(int c) /* * Get number v: variable value. */ -long get_vim_var_nr(int idx) FUNC_ATTR_PURE +varnumber_T get_vim_var_nr(int idx) FUNC_ATTR_PURE { return vimvars[idx].vv_nr; } @@ -18608,7 +18188,7 @@ long get_vim_var_nr(int idx) FUNC_ATTR_PURE */ char_u *get_vim_var_str(int idx) FUNC_ATTR_PURE FUNC_ATTR_NONNULL_RET { - return get_tv_string(&vimvars[idx].vv_tv); + return (char_u *)tv_get_string(&vimvars[idx].vv_tv); } /* @@ -18661,7 +18241,7 @@ void set_vcount(long count, long count1, int set_prevcount) /// @param[in] val Value to set to. void set_vim_var_nr(const VimVarIndex idx, const varnumber_T val) { - clear_tv(&vimvars[idx].vv_tv); + tv_clear(&vimvars[idx].vv_tv); vimvars[idx].vv_type = VAR_NUMBER; vimvars[idx].vv_nr = val; } @@ -18672,7 +18252,7 @@ void set_vim_var_nr(const VimVarIndex idx, const varnumber_T val) /// @param[in] val Value to set to. void set_vim_var_special(const VimVarIndex idx, const SpecialVarValue val) { - clear_tv(&vimvars[idx].vv_tv); + tv_clear(&vimvars[idx].vv_tv); vimvars[idx].vv_type = VAR_SPECIAL; vimvars[idx].vv_special = val; } @@ -18686,7 +18266,7 @@ void set_vim_var_special(const VimVarIndex idx, const SpecialVarValue val) void set_vim_var_string(const VimVarIndex idx, const char *const val, const ptrdiff_t len) { - clear_tv(&vimvars[idx].vv_di.di_tv); + tv_clear(&vimvars[idx].vv_di.di_tv); vimvars[idx].vv_type = VAR_STRING; if (val == NULL) { vimvars[idx].vv_str = NULL; @@ -18703,7 +18283,7 @@ void set_vim_var_string(const VimVarIndex idx, const char *const val, /// @param[in,out] val Value to set to. Reference count will be incremented. void set_vim_var_list(const VimVarIndex idx, list_T *const val) { - clear_tv(&vimvars[idx].vv_di.di_tv); + tv_clear(&vimvars[idx].vv_di.di_tv); vimvars[idx].vv_type = VAR_LIST; vimvars[idx].vv_list = val; if (val != NULL) { @@ -18718,14 +18298,14 @@ void set_vim_var_list(const VimVarIndex idx, list_T *const val) /// Also keys of the dictionary will be made read-only. void set_vim_var_dict(const VimVarIndex idx, dict_T *const val) { - clear_tv(&vimvars[idx].vv_di.di_tv); + tv_clear(&vimvars[idx].vv_di.di_tv); vimvars[idx].vv_type = VAR_DICT; vimvars[idx].vv_dict = val; if (val != NULL) { val->dv_refcount++; // Set readonly - dict_set_keys_readonly(val); + tv_dict_set_keys_readonly(val); } } @@ -18843,9 +18423,8 @@ char_u *set_cmdarg(exarg_T *eap, char_u *oldarg) * Get the value of internal variable "name". * Return OK or FAIL. */ -static int -get_var_tv ( - char_u *name, +static int get_var_tv( + const char *name, int len, // length of "name" typval_T *rettv, // NULL when only checking existence dictitem_T **dip, // non-NULL when typval's dict item is needed @@ -18855,55 +18434,52 @@ get_var_tv ( { int ret = OK; typval_T *tv = NULL; - typval_T atv; dictitem_T *v; - int cc; - - /* truncate the name, so that we can use strcmp() */ - cc = name[len]; - name[len] = NUL; - /* - * Check for "b:changedtick". - */ - if (STRCMP(name, "b:changedtick") == 0) { - atv.v_type = VAR_NUMBER; - atv.vval.v_number = curbuf->b_changedtick; - tv = &atv; - } - /* - * Check for user-defined variables. - */ - else { - v = find_var(name, NULL, no_autoload); - if (v != NULL) { - tv = &v->di_tv; - if (dip != NULL) { - *dip = v; - } + v = find_var(name, (size_t)len, NULL, no_autoload); + if (v != NULL) { + tv = &v->di_tv; + if (dip != NULL) { + *dip = v; } } if (tv == NULL) { - if (rettv != NULL && verbose) - EMSG2(_(e_undefvar), name); + if (rettv != NULL && verbose) { + emsgf(_("E121: Undefined variable: %.*s"), len, name); + } ret = FAIL; - } else if (rettv != NULL) - copy_tv(tv, rettv); - - name[len] = cc; + } else if (rettv != NULL) { + tv_copy(tv, rettv); + } return ret; } -/* - * Handle expr[expr], expr[expr:expr] subscript and .name lookup. - * Also handle function call with Funcref variable: func(expr) - * Can all be combined: dict.func(expr)[idx]['func'](expr) - */ -static int -handle_subscript ( - char_u **arg, +/// Check if variable "name[len]" is a local variable or an argument. +/// If so, "*eval_lavars_used" is set to TRUE. +static void check_vars(const char *name, size_t len) +{ + if (eval_lavars_used == NULL) { + return; + } + + const char *varname; + hashtab_T *ht = find_var_ht(name, len, &varname); + + if (ht == get_funccal_local_ht() || ht == get_funccal_args_ht()) { + if (find_var(name, len, NULL, true) != NULL) { + *eval_lavars_used = true; + } + } +} + +/// Handle expr[expr], expr[expr:expr] subscript and .name lookup. +/// Also handle function call with Funcref variable: func(expr) +/// Can all be combined: dict.func(expr)[idx]['func'](expr) +static int +handle_subscript( + const char **const arg, typval_T *rettv, int evaluate, /* do more than finding the end */ int verbose /* give error messages */ @@ -18918,8 +18494,7 @@ handle_subscript ( while (ret == OK && (**arg == '[' || (**arg == '.' && rettv->v_type == VAR_DICT) - || (**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC - || rettv->v_type == VAR_PARTIAL))) + || (**arg == '(' && (!evaluate || tv_is_func(*rettv)))) && !ascii_iswhite(*(*arg - 1))) { if (**arg == '(') { partial_T *pt = NULL; @@ -18931,59 +18506,59 @@ handle_subscript ( // Invoke the function. Recursive! if (functv.v_type == VAR_PARTIAL) { pt = functv.vval.v_partial; - s = pt->pt_name; + s = partial_name(pt); } else { s = functv.vval.v_string; } } else { s = (char_u *)""; } - ret = get_func_tv(s, (int)STRLEN(s), rettv, arg, + ret = get_func_tv(s, (int)STRLEN(s), rettv, (char_u **)arg, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &len, evaluate, pt, selfdict); - /* Clear the funcref afterwards, so that deleting it while - * evaluating the arguments is possible (see test55). */ - if (evaluate) - clear_tv(&functv); + // Clear the funcref afterwards, so that deleting it while + // evaluating the arguments is possible (see test55). + if (evaluate) { + tv_clear(&functv); + } /* Stop the expression evaluation when immediately aborting on * error, or when an interrupt occurred or an exception was thrown * but not caught. */ if (aborting()) { - if (ret == OK) - clear_tv(rettv); + if (ret == OK) { + tv_clear(rettv); + } ret = FAIL; } - dict_unref(selfdict); + tv_dict_unref(selfdict); selfdict = NULL; - } else { /* **arg == '[' || **arg == '.' */ - dict_unref(selfdict); + } else { // **arg == '[' || **arg == '.' + tv_dict_unref(selfdict); if (rettv->v_type == VAR_DICT) { selfdict = rettv->vval.v_dict; if (selfdict != NULL) ++selfdict->dv_refcount; } else selfdict = NULL; - if (eval_index(arg, rettv, evaluate, verbose) == FAIL) { - clear_tv(rettv); + if (eval_index((char_u **)arg, rettv, evaluate, verbose) == FAIL) { + tv_clear(rettv); ret = FAIL; } } } // Turn "dict.Func" into a partial for "Func" bound to "dict". - if (selfdict != NULL - && (rettv->v_type == VAR_FUNC - || rettv->v_type == VAR_PARTIAL)) { + if (selfdict != NULL && tv_is_func(*rettv)) { set_selfdict(rettv, selfdict); } - dict_unref(selfdict); + tv_dict_unref(selfdict); return ret; } -static void set_selfdict(typval_T *rettv, dict_T *selfdict) +void set_selfdict(typval_T *rettv, dict_T *selfdict) { // Don't do this when "dict.Func" is already a partial that was bound // explicitly (pt_auto is false). @@ -18991,19 +18566,23 @@ static void set_selfdict(typval_T *rettv, dict_T *selfdict) && rettv->vval.v_partial->pt_dict != NULL) { return; } - char_u *fname = rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING - ? rettv->vval.v_string - : rettv->vval.v_partial->pt_name; + char_u *fname; char_u *tofree = NULL; ufunc_T *fp; char_u fname_buf[FLEN_FIXED + 1]; int error; - // Translate "s:func" to the stored function name. - fname = fname_trans_sid(fname, fname_buf, &tofree, &error); - - fp = find_func(fname); - xfree(tofree); + if (rettv->v_type == VAR_PARTIAL && rettv->vval.v_partial->pt_func != NULL) { + fp = rettv->vval.v_partial->pt_func; + } else { + fname = rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING + ? rettv->vval.v_string + : 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(fname); + xfree(tofree); + } // Turn "dict.Func" into a partial for "Func" with "dict". if (fp != NULL && (fp->uf_flags & FC_DICT)) { @@ -19024,8 +18603,13 @@ static void set_selfdict(typval_T *rettv, dict_T *selfdict) // Partial: copy the function name, use selfdict and copy // args. Can't take over name or args, the partial might // be referenced elsewhere. - pt->pt_name = vim_strsave(ret_pt->pt_name); - func_ref(pt->pt_name); + if (ret_pt->pt_name != NULL) { + pt->pt_name = vim_strsave(ret_pt->pt_name); + func_ref(pt->pt_name); + } else { + pt->pt_func = ret_pt->pt_func; + func_ptr_ref(pt->pt_func); + } if (ret_pt->pt_argc > 0) { size_t arg_size = sizeof(typval_T) * ret_pt->pt_argc; pt->pt_argv = (typval_T *)xmalloc(arg_size); @@ -19035,7 +18619,7 @@ static void set_selfdict(typval_T *rettv, dict_T *selfdict) } else { pt->pt_argc = ret_pt->pt_argc; for (i = 0; i < pt->pt_argc; i++) { - copy_tv(&ret_pt->pt_argv[i], &pt->pt_argv[i]); + tv_copy(&ret_pt->pt_argv[i], &pt->pt_argv[i]); } } } @@ -19047,546 +18631,90 @@ static void set_selfdict(typval_T *rettv, dict_T *selfdict) } } -/* - * Free the memory for a variable type-value. - */ -void free_tv(typval_T *varp) +// Find variable "name" in the list of variables. +// Return a pointer to it if found, NULL if not found. +// Careful: "a:0" variables don't have a name. +// When "htp" is not NULL we are writing to the variable, set "htp" to the +// hashtab_T used. +static dictitem_T *find_var(const char *const name, const size_t name_len, + hashtab_T **htp, int no_autoload) { - if (varp != NULL) { - switch (varp->v_type) { - case VAR_FUNC: - func_unref(varp->vval.v_string); - // FALLTHROUGH - case VAR_STRING: - xfree(varp->vval.v_string); - break; - case VAR_PARTIAL: - partial_unref(varp->vval.v_partial); - break; - case VAR_LIST: - list_unref(varp->vval.v_list); - break; - case VAR_DICT: - dict_unref(varp->vval.v_dict); - break; - case VAR_SPECIAL: - case VAR_NUMBER: - case VAR_FLOAT: - case VAR_UNKNOWN: - break; - } - xfree(varp); + const char *varname; + hashtab_T *const ht = find_var_ht(name, name_len, &varname); + if (htp != NULL) { + *htp = ht; } -} - -#define TYPVAL_ENCODE_ALLOW_SPECIALS false - -#define TYPVAL_ENCODE_CONV_NIL(tv) \ - do { \ - tv->vval.v_special = kSpecialVarFalse; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) - -#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ - TYPVAL_ENCODE_CONV_NIL(tv) - -#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ - do { \ - (void)num; \ - tv->vval.v_number = 0; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) - -#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) - -#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ - do { \ - tv->vval.v_float = 0; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) - -#define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ - do { \ - xfree(buf); \ - tv->vval.v_string = NULL; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) - -#define TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len) - -#define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type) - -static inline int _nothing_conv_func_start(typval_T *const tv, - char_u *const fun) - FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ARG(1) -{ - tv->v_lock = VAR_UNLOCKED; - if (tv->v_type == VAR_PARTIAL) { - partial_T *const pt_ = tv->vval.v_partial; - if (pt_ != NULL && pt_->pt_refcount > 1) { - pt_->pt_refcount--; - tv->vval.v_partial = NULL; - return OK; - } - } else { - func_unref(fun); - if (fun != empty_string) { - xfree(fun); - } - tv->vval.v_string = NULL; + if (ht == NULL) { + return NULL; } - return NOTDONE; -} -#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ - do { \ - if (_nothing_conv_func_start(tv, fun) != NOTDONE) { \ - return OK; \ - } \ - } while (0) - -#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) -#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) - -static inline void _nothing_conv_func_end(typval_T *const tv, const int copyID) - FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL -{ - if (tv->v_type == VAR_PARTIAL) { - partial_T *const pt = tv->vval.v_partial; - if (pt == NULL) { - return; - } - // Dictionary should already be freed by the time. - // If it was not freed then it is a part of the reference cycle. - assert(pt->pt_dict == NULL || pt->pt_dict->dv_copyID == copyID); - pt->pt_dict = NULL; - // As well as all arguments. - pt->pt_argc = 0; - assert(pt->pt_refcount <= 1); - partial_unref(pt); - tv->vval.v_partial = NULL; - assert(tv->v_lock == VAR_UNLOCKED); - } -} -#define TYPVAL_ENCODE_CONV_FUNC_END(tv) _nothing_conv_func_end(tv, copyID) - -#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \ - do { \ - list_unref(tv->vval.v_list); \ - tv->vval.v_list = NULL; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) - -#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ - do { \ - assert((void *)&dict != (void *)&TYPVAL_ENCODE_NODICT_VAR); \ - dict_unref((dict_T *)dict); \ - *((dict_T **)&dict) = NULL; \ - if (tv != NULL) { \ - ((typval_T *)tv)->v_lock = VAR_UNLOCKED; \ - } \ - } while (0) - -static inline int _nothing_conv_real_list_after_start( - typval_T *const tv, MPConvStackVal *const mpsv) - FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT -{ - assert(tv != NULL); - tv->v_lock = VAR_UNLOCKED; - if (tv->vval.v_list->lv_refcount > 1) { - tv->vval.v_list->lv_refcount--; - tv->vval.v_list = NULL; - mpsv->data.l.li = NULL; - return OK; + dictitem_T *const ret = find_var_in_ht(ht, *name, + varname, + name_len - (size_t)(varname - name), + no_autoload || htp != NULL); + if (ret != NULL) { + return ret; } - return NOTDONE; -} -#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) - -#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) \ - do { \ - if (_nothing_conv_real_list_after_start(tv, &mpsv) != NOTDONE) { \ - goto typval_encode_stop_converting_one_item; \ - } \ - } while (0) -#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) - -static inline void _nothing_conv_list_end(typval_T *const tv) - FUNC_ATTR_ALWAYS_INLINE -{ - if (tv == NULL) { - return; - } - assert(tv->v_type == VAR_LIST); - list_T *const list = tv->vval.v_list; - list_unref(list); - tv->vval.v_list = NULL; + // Search in parent scope for lambda + return find_var_in_scoped_ht(name, name_len, no_autoload || htp != NULL); } -#define TYPVAL_ENCODE_CONV_LIST_END(tv) _nothing_conv_list_end(tv) -static inline int _nothing_conv_real_dict_after_start( - typval_T *const tv, dict_T **const dictp, const void *const nodictvar, - MPConvStackVal *const mpsv) - FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT -{ - if (tv != NULL) { - tv->v_lock = VAR_UNLOCKED; - } - if ((const void *)dictp != nodictvar && (*dictp)->dv_refcount > 1) { - (*dictp)->dv_refcount--; - *dictp = NULL; - mpsv->data.d.todo = 0; - return OK; - } - return NOTDONE; -} -#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) - -#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) \ - do { \ - if (_nothing_conv_real_dict_after_start( \ - tv, (dict_T **)&dict, (void *)&TYPVAL_ENCODE_NODICT_VAR, \ - &mpsv) != NOTDONE) { \ - goto typval_encode_stop_converting_one_item; \ - } \ - } while (0) - -#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(tv, dict) -#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) -#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) - -static inline void _nothing_conv_dict_end(typval_T *const tv, - dict_T **const dictp, - const void *const nodictvar) - FUNC_ATTR_ALWAYS_INLINE -{ - if ((const void *)dictp != nodictvar) { - dict_unref(*dictp); - *dictp = NULL; - } -} -#define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \ - _nothing_conv_dict_end(tv, (dict_T **)&dict, \ - (void *)&TYPVAL_ENCODE_NODICT_VAR) - -#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) - -#define TYPVAL_ENCODE_SCOPE static -#define TYPVAL_ENCODE_NAME nothing -#define TYPVAL_ENCODE_FIRST_ARG_TYPE const void *const -#define TYPVAL_ENCODE_FIRST_ARG_NAME ignored -#include "nvim/eval/typval_encode.c.h" -#undef TYPVAL_ENCODE_SCOPE -#undef TYPVAL_ENCODE_NAME -#undef TYPVAL_ENCODE_FIRST_ARG_TYPE -#undef TYPVAL_ENCODE_FIRST_ARG_NAME - -#undef TYPVAL_ENCODE_ALLOW_SPECIALS -#undef TYPVAL_ENCODE_CONV_NIL -#undef TYPVAL_ENCODE_CONV_BOOL -#undef TYPVAL_ENCODE_CONV_NUMBER -#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER -#undef TYPVAL_ENCODE_CONV_FLOAT -#undef TYPVAL_ENCODE_CONV_STRING -#undef TYPVAL_ENCODE_CONV_STR_STRING -#undef TYPVAL_ENCODE_CONV_EXT_STRING -#undef TYPVAL_ENCODE_CONV_FUNC_START -#undef TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS -#undef TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF -#undef TYPVAL_ENCODE_CONV_FUNC_END -#undef TYPVAL_ENCODE_CONV_EMPTY_LIST -#undef TYPVAL_ENCODE_CONV_EMPTY_DICT -#undef TYPVAL_ENCODE_CONV_LIST_START -#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START -#undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS -#undef TYPVAL_ENCODE_CONV_LIST_END -#undef TYPVAL_ENCODE_CONV_DICT_START -#undef TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START -#undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK -#undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY -#undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS -#undef TYPVAL_ENCODE_CONV_DICT_END -#undef TYPVAL_ENCODE_CONV_RECURSE - -/// Free memory for a variable value and set the value to NULL or 0 +/// Find variable in hashtab /// -/// @param[in,out] varp Value to free. -void clear_tv(typval_T *varp) -{ - if (varp != NULL && varp->v_type != VAR_UNKNOWN) { - const int evn_ret = encode_vim_to_nothing(varp, varp, "clear_tv argument"); - (void)evn_ret; - assert(evn_ret == OK); - } -} - -/* - * Set the value of a variable to NULL without freeing items. - */ -static void init_tv(typval_T *varp) -{ - if (varp != NULL) - memset(varp, 0, sizeof(typval_T)); -} - -/* - * Get the number value of a variable. - * If it is a String variable, uses vim_str2nr(). - * For incompatible types, return 0. - * get_tv_number_chk() is similar to get_tv_number(), but informs the - * caller of incompatible types: it sets *denote to TRUE if "denote" - * is not NULL or returns -1 otherwise. - */ -long get_tv_number(typval_T *varp) -{ - int error = FALSE; - - return get_tv_number_chk(varp, &error); /* return 0L on error */ -} - -long get_tv_number_chk(typval_T *varp, int *denote) -{ - long n = 0L; - - switch (varp->v_type) { - case VAR_NUMBER: - return (long)(varp->vval.v_number); - case VAR_FLOAT: - EMSG(_("E805: Using a Float as a Number")); - break; - case VAR_FUNC: - case VAR_PARTIAL: - EMSG(_("E703: Using a Funcref as a Number")); - break; - case VAR_STRING: - if (varp->vval.v_string != NULL) { - vim_str2nr(varp->vval.v_string, NULL, NULL, - STR2NR_ALL, &n, NULL, 0); - } - return n; - case VAR_LIST: - EMSG(_("E745: Using a List as a Number")); - break; - case VAR_DICT: - EMSG(_("E728: Using a Dictionary as a Number")); - break; - case VAR_SPECIAL: - switch (varp->vval.v_special) { - case kSpecialVarTrue: { - return 1; - } - case kSpecialVarFalse: - case kSpecialVarNull: { - return 0; - } - } - break; - case VAR_UNKNOWN: - EMSG2(_(e_intern2), "get_tv_number(UNKNOWN)"); - break; - } - if (denote == NULL) { - // useful for values that must be unsigned - n = -1; - } else { - *denote = true; - } - return n; -} - -static float_T get_tv_float(typval_T *varp) -{ - switch (varp->v_type) { - case VAR_NUMBER: - return (float_T)(varp->vval.v_number); - case VAR_FLOAT: - return varp->vval.v_float; - break; - case VAR_FUNC: - case VAR_PARTIAL: - EMSG(_("E891: Using a Funcref as a Float")); - break; - case VAR_STRING: - EMSG(_("E892: Using a String as a Float")); - break; - case VAR_LIST: - EMSG(_("E893: Using a List as a Float")); - break; - case VAR_DICT: - EMSG(_("E894: Using a Dictionary as a Float")); - break; - default: - EMSG2(_(e_intern2), "get_tv_float()"); - break; - } - return 0; -} - -/* - * Get the lnum from the first argument. - * Also accepts ".", "$", etc., but that only works for the current buffer. - * Returns -1 on error. - */ -static linenr_T get_tv_lnum(typval_T *argvars) -{ - typval_T rettv; - linenr_T lnum; - - lnum = get_tv_number_chk(&argvars[0], NULL); - if (lnum == 0) { /* no valid number, try using line() */ - rettv.v_type = VAR_NUMBER; - f_line(argvars, &rettv, NULL); - lnum = rettv.vval.v_number; - clear_tv(&rettv); - } - return lnum; -} - -/* - * Get the lnum from the first argument. - * Also accepts "$", then "buf" is used. - * Returns 0 on error. - */ -static linenr_T get_tv_lnum_buf(typval_T *argvars, buf_T *buf) -{ - if (argvars[0].v_type == VAR_STRING - && argvars[0].vval.v_string != NULL - && argvars[0].vval.v_string[0] == '$' - && buf != NULL) - return buf->b_ml.ml_line_count; - return get_tv_number_chk(&argvars[0], NULL); -} - -/* - * Get the string value of a variable. - * If it is a Number variable, the number is converted into a string. - * get_tv_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE! - * get_tv_string_buf() uses a given buffer. - * If the String variable has never been set, return an empty string. - * Never returns NULL; - * get_tv_string_chk() and get_tv_string_buf_chk() are similar, but return - * NULL on error. - */ -static char_u *get_tv_string(const typval_T *varp) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET -{ - static char_u mybuf[NUMBUFLEN]; - - return get_tv_string_buf(varp, mybuf); -} - -static char_u *get_tv_string_buf(const typval_T *varp, char_u *buf) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET -{ - char_u *res = get_tv_string_buf_chk(varp, buf); - - return res != NULL ? res : (char_u *)""; -} - -/// Careful: This uses a single, static buffer. YOU CAN ONLY USE IT ONCE! -char_u *get_tv_string_chk(const typval_T *varp) - FUNC_ATTR_NONNULL_ALL -{ - static char_u mybuf[NUMBUFLEN]; - - return get_tv_string_buf_chk(varp, mybuf); -} - -static char_u *get_tv_string_buf_chk(const typval_T *varp, char_u *buf) - FUNC_ATTR_NONNULL_ALL -{ - switch (varp->v_type) { - case VAR_NUMBER: - sprintf((char *)buf, "%" PRId64, (int64_t)varp->vval.v_number); - return buf; - case VAR_FUNC: - case VAR_PARTIAL: - EMSG(_("E729: using Funcref as a String")); - break; - case VAR_LIST: - EMSG(_("E730: using List as a String")); - break; - case VAR_DICT: - EMSG(_("E731: using Dictionary as a String")); - break; - case VAR_FLOAT: - EMSG(_(e_float_as_string)); - break; - case VAR_STRING: - if (varp->vval.v_string != NULL) - return varp->vval.v_string; - return (char_u *)""; - case VAR_SPECIAL: - STRCPY(buf, encode_special_var_names[varp->vval.v_special]); - return buf; - case VAR_UNKNOWN: - EMSG(_("E908: using an invalid value as a String")); - break; - } - return NULL; -} - -/* - * Find variable "name" in the list of variables. - * Return a pointer to it if found, NULL if not found. - * Careful: "a:0" variables don't have a name. - * When "htp" is not NULL we are writing to the variable, set "htp" to the - * hashtab_T used. - */ -static dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload) -{ - char_u *varname; - hashtab_T *ht; - - ht = find_var_ht(name, &varname); - if (htp != NULL) - *htp = ht; - if (ht == NULL) - return NULL; - return find_var_in_ht(ht, *name, varname, no_autoload || htp != NULL); -} - -/// Find variable "varname" in hashtab "ht" with name "htname". -/// Returns NULL if not found. -static dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, - char_u *varname, bool no_autoload) +/// @param[in] ht Hashtab to find variable in. +/// @param[in] htname Hashtab name (first character). +/// @param[in] varname Variable name. +/// @param[in] varname_len Variable name length. +/// @param[in] no_autoload If true then autoload scripts will not be sourced +/// if autoload variable was not found. +/// +/// @return pointer to the dictionary item with the found variable or NULL if it +/// was not found. +static dictitem_T *find_var_in_ht(hashtab_T *const ht, + int htname, + const char *const varname, + const size_t varname_len, + int no_autoload) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { hashitem_T *hi; - if (*varname == NUL) { - /* Must be something like "s:", otherwise "ht" would be NULL. */ + if (varname_len == 0) { + // Must be something like "s:", otherwise "ht" would be NULL. switch (htname) { - case 's': return &SCRIPT_SV(current_SID)->sv_var; - case 'g': return &globvars_var; - case 'v': return &vimvars_var; - case 'b': return &curbuf->b_bufvar; - case 'w': return &curwin->w_winvar; - case 't': return &curtab->tp_winvar; - case 'l': return current_funccal == NULL - ? NULL : ¤t_funccal->l_vars_var; - case 'a': return current_funccal == NULL - ? NULL : ¤t_funccal->l_avars_var; + case 's': return (dictitem_T *)&SCRIPT_SV(current_SID)->sv_var; + case 'g': return (dictitem_T *)&globvars_var; + case 'v': return (dictitem_T *)&vimvars_var; + case 'b': return (dictitem_T *)&curbuf->b_bufvar; + case 'w': return (dictitem_T *)&curwin->w_winvar; + case 't': return (dictitem_T *)&curtab->tp_winvar; + case 'l': return (current_funccal == NULL + ? NULL : (dictitem_T *)¤t_funccal->l_vars_var); + case 'a': return (current_funccal == NULL + ? NULL : (dictitem_T *)¤t_funccal->l_avars_var); } return NULL; } - hi = hash_find(ht, varname); + hi = hash_find_len(ht, varname, varname_len); if (HASHITEM_EMPTY(hi)) { - /* For global variables we may try auto-loading the script. If it - * worked find the variable again. Don't auto-load a script if it was - * loaded already, otherwise it would be loaded every time when - * checking if a function name is a Funcref variable. */ + // For global variables we may try auto-loading the script. If it + // worked find the variable again. Don't auto-load a script if it was + // loaded already, otherwise it would be loaded every time when + // checking if a function name is a Funcref variable. if (ht == &globvarht && !no_autoload) { - /* Note: script_autoload() may make "hi" invalid. It must either - * be obtained again or not used. */ - if (!script_autoload(varname, FALSE) || aborting()) + // Note: script_autoload() may make "hi" invalid. It must either + // be obtained again or not used. + if (!script_autoload(varname, varname_len, false) || aborting()) { return NULL; - hi = hash_find(ht, varname); + } + hi = hash_find_len(ht, varname, varname_len); } - if (HASHITEM_EMPTY(hi)) + if (HASHITEM_EMPTY(hi)) { return NULL; + } } - return HI2DI(hi); + return TV_DICT_HI2DI(hi); } // Get function call environment based on backtrace debug level @@ -19608,17 +18736,45 @@ static funccall_T *get_funccal(void) return funccal; } -// Find the dict and hashtable used for a variable name. Set "varname" to the -// start of name without ':'. -static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d) +/// Return the hashtable used for argument in the current funccal. +/// Return NULL if there is no current funccal. +static hashtab_T *get_funccal_args_ht(void) { - hashitem_T *hi; + if (current_funccal == NULL) { + return NULL; + } + return &get_funccal()->l_avars.dv_hashtab; +} + +/// Return the hashtable used for local variables in the current funccal. +/// Return NULL if there is no current funccal. +static hashtab_T *get_funccal_local_ht(void) +{ + if (current_funccal == NULL) { + return NULL; + } + return &get_funccal()->l_vars.dv_hashtab; +} + +/// Find the dict and hashtable used for a variable +/// +/// @param[in] name Variable name, possibly with scope prefix. +/// @param[in] name_len Variable name length. +/// @param[out] varname Will be set to the start of the name without scope +/// prefix. +/// @param[out] d Scope dictionary. +/// +/// @return Scope hashtab, NULL if name is not valid. +static hashtab_T *find_var_ht_dict(const char *name, const size_t name_len, + const char **varname, dict_T **d) +{ + hashitem_T *hi; *d = NULL; - if (name[0] == NUL) { + if (name_len == 0) { return NULL; } - if (name[1] != ':') { + if (name_len == 1 || (name_len >= 2 && name[1] != ':')) { // name has implicit scope if (name[0] == ':' || name[0] == AUTOLOAD_CHAR) { // The name must not start with a colon or #. @@ -19627,7 +18783,7 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d) *varname = name; // "version" is "v:version" in all scopes - hi = hash_find(&compat_hashtab, name); + hi = hash_find_len(&compat_hashtab, name, name_len); if (!HASHITEM_EMPTY(hi)) { return &compat_hashtab; } @@ -19643,26 +18799,27 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d) *varname = name + 2; if (*name == 'g') { // global variable *d = &globvardict; - } else if (vim_strchr(name + 2, ':') != NULL - || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL) { + } else if (name_len > 2 + && (memchr(name + 2, ':', name_len - 2) != NULL + || memchr(name + 2, AUTOLOAD_CHAR, name_len - 2) != NULL)) { // There must be no ':' or '#' in the rest of the name if g: was not used return NULL; } - if (*name == 'b') { // buffer variable + if (*name == 'b') { // buffer variable *d = curbuf->b_vars; - } else if (*name == 'w') { // window variable + } else if (*name == 'w') { // window variable *d = curwin->w_vars; - } else if (*name == 't') { // tab page variable + } else if (*name == 't') { // tab page variable *d = curtab->tp_vars; - } else if (*name == 'v') { // v: variable + } else if (*name == 'v') { // v: variable *d = &vimvardict; } else if (*name == 'a' && current_funccal != NULL) { // function argument *d = &get_funccal()->l_avars; } else if (*name == 'l' && current_funccal != NULL) { // local variable *d = &get_funccal()->l_vars; - } else if (*name == 's' // script variable - && current_SID > 0 && current_SID <= ga_scripts.ga_len) { + } else if (*name == 's' // script variable + && current_SID > 0 && current_SID <= ga_scripts.ga_len) { *d = &SCRIPT_SV(current_SID)->sv_dict; } @@ -19670,28 +18827,35 @@ end: return *d ? &(*d)->dv_hashtab : NULL; } -// Find the hashtab used for a variable name. -// Return NULL if the name is not valid. -// Set "varname" to the start of name without ':'. -static hashtab_T *find_var_ht(uint8_t *name, uint8_t **varname) +/// Find the hashtable used for a variable +/// +/// @param[in] name Variable name, possibly with scope prefix. +/// @param[in] name_len Variable name length. +/// @param[out] varname Will be set to the start of the name without scope +/// prefix. +/// +/// @return Scope hashtab, NULL if name is not valid. +static hashtab_T *find_var_ht(const char *name, const size_t name_len, + const char **varname) { dict_T *d; - return find_var_ht_dict(name, varname, &d); + return find_var_ht_dict(name, name_len, varname, &d); } /* * Get the string value of a (global/local) variable. - * Note: see get_tv_string() for how long the pointer remains valid. + * Note: see tv_get_string() for how long the pointer remains valid. * Returns NULL when it doesn't exist. */ -char_u *get_var_value(char_u *name) +char_u *get_var_value(const char *const name) { dictitem_T *v; - v = find_var(name, NULL, FALSE); - if (v == NULL) + v = find_var(name, strlen(name), NULL, false); + if (v == NULL) { return NULL; - return get_tv_string(&v->di_tv); + } + return (char_u *)tv_get_string(&v->di_tv); } /* @@ -19728,10 +18892,10 @@ void new_script_vars(scid_T id) * Initialize dictionary "dict" as a scope and set variable "dict_var" to * point to it. */ -void init_var_dict(dict_T *dict, dictitem_T *dict_var, int scope) +void init_var_dict(dict_T *dict, ScopeDictDictItem *dict_var, int scope) { hash_init(&dict->dv_hashtab); - dict->dv_lock = 0; + dict->dv_lock = VAR_UNLOCKED; dict->dv_scope = scope; dict->dv_refcount = DO_NOT_FREE_CNT; dict->dv_copyID = 0; @@ -19751,7 +18915,7 @@ void unref_var_dict(dict_T *dict) /* Now the dict needs to be freed if no one else is using it, go back to * normal reference counting. */ dict->dv_refcount -= DO_NOT_FREE_CNT - 1; - dict_unref(dict); + tv_dict_unref(dict); } /* @@ -19782,9 +18946,9 @@ static void vars_clear_ext(hashtab_T *ht, int free_val) // Free the variable. Don't remove it from the hashtab, // ht_array might change then. hash_clear() takes care of it // later. - v = HI2DI(hi); + v = TV_DICT_HI2DI(hi); if (free_val) { - clear_tv(&v->di_tv); + tv_clear(&v->di_tv); } if (v->di_flags & DI_FLAGS_ALLOC) { xfree(v); @@ -19801,38 +18965,37 @@ static void vars_clear_ext(hashtab_T *ht, int free_val) */ static void delete_var(hashtab_T *ht, hashitem_T *hi) { - dictitem_T *di = HI2DI(hi); + dictitem_T *di = TV_DICT_HI2DI(hi); hash_remove(ht, hi); - clear_tv(&di->di_tv); + tv_clear(&di->di_tv); xfree(di); } /* * List the value of one internal variable. */ -static void list_one_var(dictitem_T *v, char_u *prefix, int *first) +static void list_one_var(dictitem_T *v, const char *prefix, int *first) { - char_u *s = (char_u *) encode_tv2echo(&v->di_tv, NULL); - list_one_var_a(prefix, v->di_key, v->di_tv.v_type, - s == NULL ? (char_u *)"" : s, first); + char *const s = encode_tv2echo(&v->di_tv, NULL); + list_one_var_a(prefix, (const char *)v->di_key, STRLEN(v->di_key), + v->di_tv.v_type, (s == NULL ? "" : s), first); xfree(s); } -static void -list_one_var_a ( - char_u *prefix, - char_u *name, - int type, - char_u *string, - int *first /* when TRUE clear rest of screen and set to FALSE */ -) +/// @param[in] name_len Length of the name. May be -1, in this case strlen() +/// will be used. +/// @param[in,out] first When true clear rest of screen and set to false. +static void list_one_var_a(const char *prefix, const char *name, + const ptrdiff_t name_len, const int type, + const char *string, int *first) { - /* don't use msg() or msg_attr() to avoid overwriting "v:statusmsg" */ + // don't use msg() or msg_attr() to avoid overwriting "v:statusmsg" msg_start(); msg_puts(prefix); - if (name != NULL) /* "a:" vars don't have a name stored */ - msg_puts(name); + if (name != NULL) { // "a:" vars don't have a name stored + msg_puts_attr_len(name, name_len, 0); + } msg_putchar(' '); msg_advance(22); if (type == VAR_NUMBER) { @@ -19850,10 +19013,10 @@ list_one_var_a ( } else msg_putchar(' '); - msg_outtrans(string); + msg_outtrans((char_u *)string); if (type == VAR_FUNC || type == VAR_PARTIAL) { - msg_puts((char_u *)"()"); + msg_puts("()"); } if (*first) { msg_clr_eos(); @@ -19861,46 +19024,47 @@ list_one_var_a ( } } -/* - * Set variable "name" to value in "tv". - * If the variable already exists, the value is updated. - * Otherwise the variable is created. - */ -static void -set_var ( - char_u *name, - typval_T *tv, - int copy /* make copy of value in "tv" */ -) +/// Set variable to the given value +/// +/// If the variable already exists, the value is updated. Otherwise the variable +/// is created. +/// +/// @param[in] name Variable name to set. +/// @param[in] name_len Length of the variable name. +/// @param tv Variable value. +/// @param[in] copy True if value in tv is to be copied. +static void set_var(const char *name, const size_t name_len, typval_T *const tv, + const bool copy) + FUNC_ATTR_NONNULL_ALL { dictitem_T *v; - char_u *varname; hashtab_T *ht; - typval_T oldtv; dict_T *dict; - ht = find_var_ht_dict(name, &varname, &dict); - bool watched = is_watched(dict); - - if (watched) { - init_tv(&oldtv); - } + const char *varname; + ht = find_var_ht_dict(name, name_len, &varname, &dict); + const bool watched = tv_dict_is_watched(dict); if (ht == NULL || *varname == NUL) { EMSG2(_(e_illvar), name); return; } - v = find_var_in_ht(ht, 0, varname, TRUE); + v = find_var_in_ht(ht, 0, varname, name_len - (size_t)(varname - name), true); - if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) - && var_check_func_name(name, v == NULL)) { + // Search in parent scope which is possible to reference from lambda + if (v == NULL) { + v = find_var_in_scoped_ht((const char *)name, name_len, true); + } + + if (tv_is_func(*tv) && !var_check_func_name(name, v == NULL)) { return; } + typval_T oldtv = TV_INITIAL_VALUE; if (v != NULL) { // existing variable, need to clear the value - if (var_check_ro(v->di_flags, name, false) - || tv_check_lock(v->di_tv.v_lock, name, false)) { + if (var_check_ro(v->di_flags, name, name_len) + || tv_check_lock(v->di_tv.v_lock, name, name_len)) { return; } @@ -19909,19 +19073,19 @@ set_var ( if (ht == &vimvarht) { if (v->di_tv.v_type == VAR_STRING) { xfree(v->di_tv.vval.v_string); - if (copy || tv->v_type != VAR_STRING) - v->di_tv.vval.v_string = vim_strsave(get_tv_string(tv)); - else { + if (copy || tv->v_type != VAR_STRING) { + v->di_tv.vval.v_string = (char_u *)xstrdup(tv_get_string(tv)); + } else { // Take over the string to avoid an extra alloc/free. v->di_tv.vval.v_string = tv->vval.v_string; tv->vval.v_string = NULL; } return; } else if (v->di_tv.v_type == VAR_NUMBER) { - v->di_tv.vval.v_number = get_tv_number(tv); - if (STRCMP(varname, "searchforward") == 0) + v->di_tv.vval.v_number = tv_get_number(tv); + if (strcmp(varname, "searchforward") == 0) { set_search_direction(v->di_tv.vval.v_number ? '/' : '?'); - else if (STRCMP(varname, "hlsearch") == 0) { + } else if (strcmp(varname, "hlsearch") == 0) { no_hlsearch = !v->di_tv.vval.v_number; redraw_all_later(SOME_VALID); } @@ -19932,23 +19096,24 @@ set_var ( } if (watched) { - copy_tv(&v->di_tv, &oldtv); + tv_copy(&v->di_tv, &oldtv); } - clear_tv(&v->di_tv); - } else { /* add a new variable */ - /* Can't add "v:" variable. */ + tv_clear(&v->di_tv); + } else { // Add a new variable. + // Can't add "v:" variable. if (ht == &vimvarht) { - EMSG2(_(e_illvar), name); + emsgf(_(e_illvar), name); return; } - /* Make sure the variable name is valid. */ - if (!valid_varname(varname)) + // Make sure the variable name is valid. + if (!valid_varname(varname)) { return; + } - v = xmalloc(sizeof(dictitem_T) + STRLEN(varname)); + v = xmalloc(sizeof(dictitem_T) + strlen(varname)); STRCPY(v->di_key, varname); - if (hash_add(ht, DI2HIKEY(v)) == FAIL) { + if (tv_dict_add(dict, v) == FAIL) { xfree(v); return; } @@ -19956,167 +19121,153 @@ set_var ( } if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT) { - copy_tv(tv, &v->di_tv); + tv_copy(tv, &v->di_tv); } else { v->di_tv = *tv; v->di_tv.v_lock = 0; - init_tv(tv); + tv_init(tv); } if (watched) { if (oldtv.v_type == VAR_UNKNOWN) { - dictwatcher_notify(dict, (char *)v->di_key, &v->di_tv, NULL); + tv_dict_watcher_notify(dict, (char *)v->di_key, &v->di_tv, NULL); } else { - dictwatcher_notify(dict, (char *)v->di_key, &v->di_tv, &oldtv); - clear_tv(&oldtv); + tv_dict_watcher_notify(dict, (char *)v->di_key, &v->di_tv, &oldtv); + tv_clear(&oldtv); } } } -// Return true if di_flags "flags" indicates variable "name" is read-only. -// Also give an error message. -static bool var_check_ro(int flags, char_u *name, bool use_gettext) +/// Check whether variable is read-only (DI_FLAGS_RO, DI_FLAGS_RO_SBX) +/// +/// Also gives an error message. +/// +/// @param[in] flags di_flags attribute value. +/// @param[in] name Variable name, for use in error message. +/// @param[in] name_len Variable name length. Use #TV_TRANSLATE to translate +/// variable name and compute the length. Use #TV_CSTRING +/// to compute the length with strlen() without +/// translating. +/// +/// Both #TV_… values are used for optimization purposes: +/// variable name with its length is needed only in case +/// of error, when no error occurs computing them is +/// a waste of CPU resources. This especially applies to +/// gettext. +/// +/// @return True if variable is read-only: either always or in sandbox when +/// sandbox is enabled, false otherwise. +bool var_check_ro(const int flags, const char *name, + size_t name_len) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { + const char *error_message = NULL; if (flags & DI_FLAGS_RO) { - EMSG2(_(e_readonlyvar), use_gettext ? (char_u *)_(name) : name); - return true; + error_message = N_(e_readonlyvar); + } else if ((flags & DI_FLAGS_RO_SBX) && sandbox) { + error_message = N_("E794: Cannot set variable in the sandbox: \"%.*s\""); } - if ((flags & DI_FLAGS_RO_SBX) && sandbox) { - EMSG2(_(e_readonlysbx), use_gettext ? (char_u *)_(name) : name); - return true; + + if (error_message == NULL) { + return false; } - return false; + if (name_len == TV_TRANSLATE) { + name = _(name); + name_len = strlen(name); + } else if (name_len == TV_CSTRING) { + name_len = strlen(name); + } + + emsgf(_(error_message), (int)name_len, name); + + return true; } -// Return true if di_flags "flags" indicates variable "name" is fixed. -// Also give an error message. -static bool var_check_fixed(int flags, char_u *name, bool use_gettext) +/// Check whether variable is fixed (DI_FLAGS_FIX) +/// +/// Also gives an error message. +/// +/// @param[in] flags di_flags attribute value. +/// @param[in] name Variable name, for use in error message. +/// @param[in] name_len Variable name length. Use #TV_TRANSLATE to translate +/// variable name and compute the length. Use #TV_CSTRING +/// to compute the length with strlen() without +/// translating. +/// +/// Both #TV_… values are used for optimization purposes: +/// variable name with its length is needed only in case +/// of error, when no error occurs computing them is +/// a waste of CPU resources. This especially applies to +/// gettext. +/// +/// @return True if variable is fixed, false otherwise. +static bool var_check_fixed(const int flags, const char *name, + size_t name_len) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { if (flags & DI_FLAGS_FIX) { - EMSG2(_("E795: Cannot delete variable %s"), - use_gettext ? (char_u *)_(name) : name); + if (name_len == TV_TRANSLATE) { + name = _(name); + name_len = strlen(name); + } else if (name_len == TV_CSTRING) { + name_len = strlen(name); + } + emsgf(_("E795: Cannot delete variable %.*s"), (int)name_len, name); return true; } return false; } -/* - * Check if a funcref is assigned to a valid variable name. - * Return TRUE and give an error if not. - */ -static int -var_check_func_name ( - char_u *name, /* points to start of variable name */ - int new_var /* TRUE when creating the variable */ -) +// TODO(ZyX-I): move to eval/expressions + +/// Check if name is a valid name to assign funcref to +/// +/// @param[in] name Possible function/funcref name. +/// @param[in] new_var True if it is a name for a variable. +/// +/// @return false in case of error, true in case of success. Also gives an +/// error message if appropriate. +bool var_check_func_name(const char *const name, const bool new_var) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { // Allow for w: b: s: and t:. if (!(vim_strchr((char_u *)"wbst", name[0]) != NULL && name[1] == ':') && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':') ? name[2] : name[0])) { EMSG2(_("E704: Funcref variable name must start with a capital: %s"), name); - return TRUE; + return false; } - /* Don't allow hiding a function. When "v" is not NULL we might be - * assigning another function to the same var, the type is checked - * below. */ - if (new_var && function_exists(name)) { + // Don't allow hiding a function. When "v" is not NULL we might be + // assigning another function to the same var, the type is checked + // below. + if (new_var && function_exists((const char *)name, false)) { EMSG2(_("E705: Variable name conflicts with existing function: %s"), - name); - return TRUE; + name); + return false; } - return FALSE; + return true; } -/* - * Check if a variable name is valid. - * Return FALSE and give an error if not. - */ -static int valid_varname(char_u *varname) -{ - char_u *p; +// TODO(ZyX-I): move to eval/expressions - for (p = varname; *p != NUL; ++p) - if (!eval_isnamec1(*p) && (p == varname || !ascii_isdigit(*p)) +/// Check if a variable name is valid +/// +/// @param[in] varname Variable name to check. +/// +/// @return false when variable name is not valid, true when it is. Also gives +/// an error message if appropriate. +bool valid_varname(const char *varname) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + for (const char *p = varname; *p != NUL; p++) { + if (!eval_isnamec1((int)(uint8_t)(*p)) + && (p == varname || !ascii_isdigit(*p)) && *p != AUTOLOAD_CHAR) { - EMSG2(_(e_illvar), varname); - return FALSE; + emsgf(_(e_illvar), varname); + return false; } - return TRUE; -} - -// Return true if typeval "tv" is set to be locked (immutable). -// Also give an error message, using "name" or _("name") when use_gettext is -// true. -static bool tv_check_lock(int lock, char_u *name, bool use_gettext) -{ - if (lock & VAR_LOCKED) { - EMSG2(_("E741: Value is locked: %s"), - name == NULL - ? (char_u *)_("Unknown") - : use_gettext ? (char_u *)_(name) - : name); - return true; - } - if (lock & VAR_FIXED) { - EMSG2(_("E742: Cannot change value of %s"), - name == NULL - ? (char_u *)_("Unknown") - : use_gettext ? (char_u *)_(name) - : name); - return true; - } - return false; -} - -/* - * Copy the values from typval_T "from" to typval_T "to". - * When needed allocates string or increases reference count. - * Does not make a copy of a list or dict but copies the reference! - * It is OK for "from" and "to" to point to the same item. This is used to - * make a copy later. - */ -void copy_tv(typval_T *from, typval_T *to) -{ - to->v_type = from->v_type; - to->v_lock = 0; - memmove(&to->vval, &from->vval, sizeof(to->vval)); - switch (from->v_type) { - case VAR_NUMBER: - case VAR_FLOAT: - case VAR_SPECIAL: - break; - case VAR_STRING: - case VAR_FUNC: - if (from->vval.v_string != NULL) { - to->vval.v_string = vim_strsave(from->vval.v_string); - if (from->v_type == VAR_FUNC) { - func_ref(to->vval.v_string); - } - } - break; - case VAR_PARTIAL: - if (from->vval.v_partial == NULL) { - to->vval.v_partial = NULL; - } else { - to->vval.v_partial = from->vval.v_partial; - (to->vval.v_partial->pt_refcount)++; - } - break; - case VAR_LIST: - if (from->vval.v_list != NULL) { - to->vval.v_list->lv_refcount++; - } - break; - case VAR_DICT: - if (from->vval.v_dict != NULL) { - to->vval.v_dict->dv_refcount++; - } - break; - case VAR_UNKNOWN: - EMSG2(_(e_intern2), "copy_tv(UNKNOWN)"); - break; } + return true; } /// Make a copy of an item @@ -20134,7 +19285,7 @@ void copy_tv(typval_T *from, typval_T *to) /// list[1]`) var_item_copy with zero copyID will emit /// a copy with (`copy[0] isnot copy[1]`), with non-zero it /// will emit a copy with (`copy[0] is copy[1]`) like in the -/// original list. Not use when deep is false. +/// original list. Not used when deep is false. int var_item_copy(const vimconv_T *const conv, typval_T *const from, typval_T *const to, @@ -20157,11 +19308,12 @@ int var_item_copy(const vimconv_T *const conv, case VAR_FUNC: case VAR_PARTIAL: case VAR_SPECIAL: - copy_tv(from, to); + tv_copy(from, to); break; case VAR_STRING: - if (conv == NULL || conv->vc_type == CONV_NONE) { - copy_tv(from, to); + if (conv == NULL || conv->vc_type == CONV_NONE + || from->vval.v_string == NULL) { + tv_copy(from, to); } else { to->v_type = VAR_STRING; to->v_lock = 0; @@ -20183,10 +19335,11 @@ int var_item_copy(const vimconv_T *const conv, to->vval.v_list = from->vval.v_list->lv_copylist; ++to->vval.v_list->lv_refcount; } else { - to->vval.v_list = list_copy(conv, from->vval.v_list, deep, copyID); + to->vval.v_list = tv_list_copy(conv, from->vval.v_list, deep, copyID); } - if (to->vval.v_list == NULL) + if (to->vval.v_list == NULL && from->vval.v_list != NULL) { ret = FAIL; + } break; case VAR_DICT: to->v_type = VAR_DICT; @@ -20198,10 +19351,11 @@ int var_item_copy(const vimconv_T *const conv, to->vval.v_dict = from->vval.v_dict->dv_copydict; ++to->vval.v_dict->dv_refcount; } else { - to->vval.v_dict = dict_copy(conv, from->vval.v_dict, deep, copyID); + to->vval.v_dict = tv_dict_copy(conv, from->vval.v_dict, deep, copyID); } - if (to->vval.v_dict == NULL) + if (to->vval.v_dict == NULL && from->vval.v_dict != NULL) { ret = FAIL; + } break; case VAR_UNKNOWN: EMSG2(_(e_intern2), "var_item_copy(UNKNOWN)"); @@ -20220,7 +19374,6 @@ void ex_echo(exarg_T *eap) { char_u *arg = eap->arg; typval_T rettv; - char_u *p; bool needclr = true; bool atstart = true; @@ -20231,19 +19384,20 @@ void ex_echo(exarg_T *eap) * still need to be cleared. E.g., "echo 22,44". */ need_clr_eos = needclr; - p = arg; - if (eval1(&arg, &rettv, !eap->skip) == FAIL) { - /* - * Report the invalid expression unless the expression evaluation - * has been cancelled due to an aborting error, an interrupt, or an - * exception. - */ - if (!aborting()) - EMSG2(_(e_invexpr2), p); - need_clr_eos = FALSE; - break; + { + char_u *p = arg; + if (eval1(&arg, &rettv, !eap->skip) == FAIL) { + // Report the invalid expression unless the expression evaluation + // has been cancelled due to an aborting error, an interrupt, or an + // exception. + if (!aborting()) { + EMSG2(_(e_invexpr2), p); + } + need_clr_eos = false; + break; + } + need_clr_eos = false; } - need_clr_eos = FALSE; if (!eap->skip) { if (atstart) { @@ -20257,9 +19411,11 @@ void ex_echo(exarg_T *eap) msg_sb_eol(); msg_start(); } - } else if (eap->cmdidx == CMD_echo) - msg_puts_attr((char_u *)" ", echo_attr); - char_u *tofree = p = (char_u *) encode_tv2echo(&rettv, NULL); + } else if (eap->cmdidx == CMD_echo) { + msg_puts_attr(" ", echo_attr); + } + char *tofree = encode_tv2echo(&rettv, NULL); + const char *p = tofree; if (p != NULL) { for (; *p != NUL && !got_int; ++p) { if (*p == '\n' || *p == '\r' || *p == TAB) { @@ -20268,21 +19424,22 @@ void ex_echo(exarg_T *eap) msg_clr_eos(); needclr = false; } - msg_putchar_attr(*p, echo_attr); + msg_putchar_attr((uint8_t)(*p), echo_attr); } else { if (has_mbyte) { - int i = (*mb_ptr2len)(p); + int i = (*mb_ptr2len)((const char_u *)p); - (void)msg_outtrans_len_attr(p, i, echo_attr); + (void)msg_outtrans_len_attr((char_u *)p, i, echo_attr); p += i - 1; - } else - (void)msg_outtrans_len_attr(p, 1, echo_attr); + } else { + (void)msg_outtrans_len_attr((char_u *)p, 1, echo_attr); + } } } } xfree(tofree); } - clear_tv(&rettv); + tv_clear(&rettv); arg = skipwhite(arg); } eap->nextcmd = check_nextcmd(arg); @@ -20326,7 +19483,6 @@ void ex_execute(exarg_T *eap) int ret = OK; char_u *p; garray_T ga; - int len; int save_did_emsg; ga_init(&ga, 1, 80); @@ -20348,16 +19504,17 @@ void ex_execute(exarg_T *eap) } if (!eap->skip) { - p = get_tv_string(&rettv); - len = (int)STRLEN(p); + const char *const argstr = tv_get_string(&rettv); + const size_t len = strlen(argstr); ga_grow(&ga, len + 2); - if (!GA_EMPTY(&ga)) + if (!GA_EMPTY(&ga)) { ((char_u *)(ga.ga_data))[ga.ga_len++] = ' '; - STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p); + } + memcpy((char_u *)(ga.ga_data) + ga.ga_len, argstr, len + 1); ga.ga_len += len; } - clear_tv(&rettv); + tv_clear(&rettv); arg = skipwhite(arg); } @@ -20390,9 +19547,9 @@ void ex_execute(exarg_T *eap) * Returns NULL when no option name found. Otherwise pointer to the char * after the option name. */ -static char_u *find_option_end(char_u **arg, int *opt_flags) +static const char *find_option_end(const char **const arg, int *const opt_flags) { - char_u *p = *arg; + const char *p = *arg; ++p; if (*p == 'g' && p[1] == ':') { @@ -20401,18 +19558,22 @@ static char_u *find_option_end(char_u **arg, int *opt_flags) } else if (*p == 'l' && p[1] == ':') { *opt_flags = OPT_LOCAL; p += 2; - } else + } else { *opt_flags = 0; + } - if (!ASCII_ISALPHA(*p)) + if (!ASCII_ISALPHA(*p)) { return NULL; + } *arg = p; - if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL) - p += 4; /* termcap option */ - else - while (ASCII_ISALPHA(*p)) - ++p; + if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL) { + p += 4; // t_xx/termcap option + } else { + while (ASCII_ISALPHA(*p)) { + p++; + } + } return p; } @@ -20431,10 +19592,10 @@ void ex_function(exarg_T *eap) char_u *line_arg = NULL; garray_T newargs; garray_T newlines; - int varargs = FALSE; - int mustend = FALSE; + int varargs = false; int flags = 0; ufunc_T *fp; + bool overwrite = false; int indent; int nesting; char_u *skip_until = NULL; @@ -20457,8 +19618,9 @@ void ex_function(exarg_T *eap) if (!HASHITEM_EMPTY(hi)) { --todo; fp = HI2UF(hi); - if (!isdigit(*fp->uf_name)) - list_func_head(fp, FALSE); + if (!func_name_refcount(fp->uf_name)) { + list_func_head(fp, false); + } } } } @@ -20524,8 +19686,9 @@ void ex_function(exarg_T *eap) * interrupt, or an exception. */ if (!aborting()) { - if (!eap->skip && fudi.fd_newkey != NULL) + if (fudi.fd_newkey != NULL) { EMSG2(_(e_dictkey), fudi.fd_newkey); + } xfree(fudi.fd_newkey); return; } else @@ -20567,7 +19730,7 @@ void ex_function(exarg_T *eap) } if (!got_int) { msg_putchar('\n'); - msg_puts((char_u *)" endfunction"); + msg_puts(" endfunction"); } } else emsg_funcname(N_("E123: Undefined function: %s"), name); @@ -20600,9 +19763,7 @@ void ex_function(exarg_T *eap) arg = name; else arg = fudi.fd_newkey; - if (arg != NULL && (fudi.fd_di == NULL - || (fudi.fd_di->di_tv.v_type != VAR_FUNC - && fudi.fd_di->di_tv.v_type != VAR_PARTIAL))) { + if (arg != NULL && (fudi.fd_di == NULL || !tv_is_func(fudi.fd_di->di_tv))) { int j = (*arg == K_SPECIAL) ? 3 : 0; while (arg[j] != NUL && (j == 0 ? eval_isnamec1(arg[j]) : eval_isnamec(arg[j]))) @@ -20615,59 +19776,11 @@ void ex_function(exarg_T *eap) EMSG(_("E862: Cannot use g: here")); } - /* - * Isolate the arguments: "arg1, arg2, ...)" - */ - while (*p != ')') { - if (p[0] == '.' && p[1] == '.' && p[2] == '.') { - varargs = TRUE; - p += 3; - mustend = TRUE; - } else { - arg = p; - while (ASCII_ISALNUM(*p) || *p == '_') - ++p; - if (arg == p || isdigit(*arg) - || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0) - || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0)) { - if (!eap->skip) - EMSG2(_("E125: Illegal argument: %s"), arg); - break; - } - ga_grow(&newargs, 1); - c = *p; - *p = NUL; - arg = vim_strsave(arg); - - /* Check for duplicate argument name. */ - for (int i = 0; i < newargs.ga_len; ++i) - if (STRCMP(((char_u **)(newargs.ga_data))[i], arg) == 0) { - EMSG2(_("E853: Duplicate argument name: %s"), arg); - xfree(arg); - goto erret; - } - - ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg; - *p = c; - newargs.ga_len++; - if (*p == ',') - ++p; - else - mustend = TRUE; - } - p = skipwhite(p); - if (mustend && *p != ')') { - if (!eap->skip) - EMSG2(_(e_invarg2), eap->arg); - break; - } - } - if (*p != ')') { - goto erret; + if (get_function_args(&p, ')', &newargs, &varargs, eap->skip) == FAIL) { + goto errret_2; } - ++p; // skip the ')' - /* find extra arguments "range", "dict" and "abort" */ + // find extra arguments "range", "dict", "abort" and "closure" for (;; ) { p = skipwhite(p); if (STRNCMP(p, "range", 5) == 0) { @@ -20679,16 +19792,28 @@ void ex_function(exarg_T *eap) } else if (STRNCMP(p, "abort", 5) == 0) { flags |= FC_ABORT; p += 5; - } else + } else if (STRNCMP(p, "closure", 7) == 0) { + flags |= FC_CLOSURE; + p += 7; + if (current_funccal == NULL) { + emsg_funcname(N_ + ("E932: Closure function should not be at top level: %s"), + name == NULL ? (char_u *)"" : name); + goto erret; + } + } else { break; + } } /* When there is a line break use what follows for the function body. * Makes 'exe "func Test()\n...\nendfunc"' work. */ - if (*p == '\n') + const char *const end = (const char *)p + STRLEN(p); + if (*p == '\n') { line_arg = p + 1; - else if (*p != NUL && *p != '"' && !eap->skip && !did_emsg) - EMSG(_(e_trailing)); + } else if (*p != NUL && *p != '"' && !eap->skip && !did_emsg) { + emsgf(_(e_trailing)); + } /* * Read the body of the function, until ":endfunction" is found. @@ -20762,8 +19887,30 @@ void ex_function(exarg_T *eap) /* Check for "endfunction". */ if (checkforcmd(&p, "endfunction", 4) && nesting-- == 0) { - if (line_arg == NULL) + if (*p == '!') { + p++; + } + const char *const comment_start = strchr((const char *)p, '"'); + const char *const endfunc_end = (comment_start + ? strchr(comment_start, '\n') + : strpbrk((const char *)p, "\n|")); + p = (endfunc_end + ? (char_u *)endfunc_end + : p + STRLEN(p)); + if (*p == '|') { + emsgf(_(e_trailing2), p); + if (line_arg == NULL) { + xfree(theline); + } + goto erret; + } + if (line_arg == NULL) { xfree(theline); + } else { + if ((const char *)p < end) { + eap->nextcmd = p + 1; + } + } break; } @@ -20782,7 +19929,7 @@ void ex_function(exarg_T *eap) if (*p == '!') { p = skipwhite(p + 1); } - p += eval_fname_script(p); + p += eval_fname_script((const char *)p); xfree(trans_function_name(&p, true, 0, NULL, NULL)); if (*skipwhite(p) == '(') { nesting++; @@ -20790,9 +19937,15 @@ void ex_function(exarg_T *eap) } } - /* Check for ":append" or ":insert". */ + // Check for ":append", ":change", ":insert". p = skip_range(p, NULL); if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p')) + || (p[0] == 'c' + && (!ASCII_ISALPHA(p[1]) + || (p[1] == 'h' && (!ASCII_ISALPHA(p[2]) + || (p[2] == 'a' + && (STRNCMP(&p[3], "nge", 3) != 0 + || !ASCII_ISALPHA(p[6]))))))) || (p[0] == 'i' && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n' && (!ASCII_ISALPHA(p[2]) @@ -20857,7 +20010,7 @@ void ex_function(exarg_T *eap) * If there are no errors, add the function */ if (fudi.fd_dict == NULL) { - v = find_var(name, &ht, FALSE); + v = find_var((const char *)name, STRLEN(name), &ht, false); if (v != NULL && v->di_tv.v_type == VAR_FUNC) { emsg_funcname(N_("E707: Function name conflicts with variable: %s"), name); @@ -20870,16 +20023,25 @@ void ex_function(exarg_T *eap) emsg_funcname(e_funcexts, name); goto erret; } - if (fp->uf_refcount > 1 || fp->uf_calls > 0) { + if (fp->uf_calls > 0) { emsg_funcname(N_("E127: Cannot redefine function %s: It is in use"), name); goto erret; } - /* redefine existing function */ - ga_clear_strings(&(fp->uf_args)); - ga_clear_strings(&(fp->uf_lines)); - xfree(name); - name = NULL; + if (fp->uf_refcount > 1) { + // This function is referenced somewhere, don't redefine it but + // create a new one. + (fp->uf_refcount)--; + fp->uf_flags |= FC_REMOVED; + fp = NULL; + overwrite = true; + } else { + // redefine existing function + ga_clear_strings(&(fp->uf_args)); + ga_clear_strings(&(fp->uf_lines)); + xfree(name); + name = NULL; + } } } else { char numbuf[20]; @@ -20890,11 +20052,13 @@ void ex_function(exarg_T *eap) goto erret; } if (fudi.fd_di == NULL) { - if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg, false)) { + if (tv_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 (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg, false)) { + } else if (tv_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; } @@ -20914,7 +20078,7 @@ void ex_function(exarg_T *eap) /* Check that the autoload name matches the script name. */ int j = FAIL; if (sourcing_name != NULL) { - scriptname = autoload_name(name); + scriptname = (char_u *)autoload_name((const char *)name, STRLEN(name)); p = vim_strchr(scriptname, '/'); plen = (int)STRLEN(p); slen = (int)STRLEN(sourcing_name); @@ -20931,20 +20095,21 @@ void ex_function(exarg_T *eap) } } - fp = xmalloc(sizeof(ufunc_T) + STRLEN(name)); + fp = xcalloc(1, sizeof(ufunc_T) + STRLEN(name)); if (fudi.fd_dict != NULL) { if (fudi.fd_di == NULL) { - /* add new dict entry */ - fudi.fd_di = dictitem_alloc(fudi.fd_newkey); - if (dict_add(fudi.fd_dict, fudi.fd_di) == FAIL) { + // Add new dict entry + fudi.fd_di = tv_dict_item_alloc((const char *)fudi.fd_newkey); + if (tv_dict_add(fudi.fd_dict, fudi.fd_di) == FAIL) { xfree(fudi.fd_di); xfree(fp); goto erret; } - } else - /* overwrite existing dict entry */ - clear_tv(&fudi.fd_di->di_tv); + } else { + // Overwrite existing dict entry. + tv_clear(&fudi.fd_di->di_tv); + } fudi.fd_di->di_tv.v_type = VAR_FUNC; fudi.fd_di->di_tv.v_lock = 0; fudi.fd_di->di_tv.vval.v_string = vim_strsave(name); @@ -20955,14 +20120,22 @@ void ex_function(exarg_T *eap) /* insert the new function in the function list */ STRCPY(fp->uf_name, name); - if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL) { - xfree(fp); - goto erret; + if (overwrite) { + hi = hash_find(&func_hashtab, name); + hi->hi_key = UF2HIKEY(fp); + } else if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL) { + xfree(fp); + goto erret; } + fp->uf_refcount = 1; } - fp->uf_refcount = 1; fp->uf_args = newargs; fp->uf_lines = newlines; + if ((flags & FC_CLOSURE) != 0) { + register_closure(fp); + } else { + fp->uf_scoped = NULL; + } fp->uf_tml_count = NULL; fp->uf_tml_total = NULL; fp->uf_tml_self = NULL; @@ -20977,6 +20150,7 @@ void ex_function(exarg_T *eap) erret: ga_clear_strings(&newargs); +errret_2: ga_clear_strings(&newlines); ret_free: xfree(skip_until); @@ -20986,30 +20160,29 @@ ret_free: need_wait_return |= saved_wait_return; } -/* - * Get a function name, translating "<SID>" and "<SNR>". - * Also handles a Funcref in a List or Dictionary. - * Returns the function name in allocated memory, or NULL for failure. - * flags: - * TFN_INT: internal function name OK - * TFN_QUIET: be quiet - * TFN_NO_AUTOLOAD: do not use script autoloading - * Advances "pp" to just after the function name (if no error). - */ +/// Get a function name, translating "<SID>" and "<SNR>". +/// Also handles a Funcref in a List or Dictionary. +/// flags: +/// TFN_INT: internal function name OK +/// TFN_QUIET: be quiet +/// TFN_NO_AUTOLOAD: do not use script autoloading +/// TFN_NO_DEREF: do not dereference a Funcref +/// Advances "pp" to just after the function name (if no error). +/// +/// @return the function name in allocated memory, or NULL for failure. static char_u * -trans_function_name ( +trans_function_name( char_u **pp, - int skip, /* only find the end, don't evaluate */ + int skip, // only find the end, don't evaluate int flags, funcdict_T *fdp, // return: info about dictionary used partial_T **partial // return: partial of a FuncRef ) { char_u *name = NULL; - char_u *start; - char_u *end; + const char_u *start; + const char_u *end; int lead; - char_u sid_buf[20]; int len; lval_T lv; @@ -21022,19 +20195,20 @@ trans_function_name ( if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA && (*pp)[2] == (int)KE_SNR) { *pp += 3; - len = get_id_len(pp) + 3; - return vim_strnsave(start, len); + len = get_id_len((const char **)pp) + 3; + return (char_u *)xmemdupz(start, len); } /* A name starting with "<SID>" or "<SNR>" is local to a script. But * don't skip over "s:", get_lval() needs it for "s:dict.func". */ - lead = eval_fname_script(start); - if (lead > 2) + lead = eval_fname_script((const char *)start); + if (lead > 2) { start += lead; + } - /* Note that TFN_ flags use the same values as GLV_ flags. */ - end = get_lval(start, NULL, &lv, FALSE, skip, flags, - lead > 2 ? 0 : FNE_CHECK_START); + // Note that TFN_ flags use the same values as GLV_ flags. + end = get_lval((char_u *)start, NULL, &lv, false, skip, flags, + lead > 2 ? 0 : FNE_CHECK_START); if (end == start) { if (!skip) EMSG(_("E129: Function name required")); @@ -21047,10 +20221,12 @@ trans_function_name ( * interrupt, or an exception. */ if (!aborting()) { - if (end != NULL) - EMSG2(_(e_invarg2), start); - } else - *pp = find_name_end(start, NULL, NULL, FNE_INCL_BR); + if (end != NULL) { + emsgf(_(e_invarg2), start); + } + } else { + *pp = (char_u *)find_name_end(start, NULL, NULL, FNE_INCL_BR); + } goto theend; } @@ -21063,11 +20239,11 @@ trans_function_name ( } if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL) { name = vim_strsave(lv.ll_tv->vval.v_string); - *pp = end; + *pp = (char_u *)end; } else if (lv.ll_tv->v_type == VAR_PARTIAL && lv.ll_tv->vval.v_partial != NULL) { - name = vim_strsave(lv.ll_tv->vval.v_partial->pt_name); - *pp = end; + name = vim_strsave(partial_name(lv.ll_tv->vval.v_partial)); + *pp = (char_u *)end; if (partial != NULL) { *partial = lv.ll_tv->vval.v_partial; } @@ -21077,7 +20253,7 @@ trans_function_name ( || fdp->fd_newkey == NULL)) { EMSG(_(e_funcref)); } else { - *pp = end; + *pp = (char_u *)end; } name = NULL; } @@ -21085,29 +20261,30 @@ trans_function_name ( } if (lv.ll_name == NULL) { - /* Error found, but continue after the function name. */ - *pp = end; + // Error found, but continue after the function name. + *pp = (char_u *)end; goto theend; } /* Check if the name is a Funcref. If so, use the value. */ if (lv.ll_exp_name != NULL) { - len = (int)STRLEN(lv.ll_exp_name); + len = (int)strlen(lv.ll_exp_name); name = deref_func_name(lv.ll_exp_name, &len, partial, flags & TFN_NO_AUTOLOAD); - if (name == lv.ll_exp_name) { + if ((const char *)name == lv.ll_exp_name) { name = NULL; } - } else { + } else if (!(flags & TFN_NO_DEREF)) { len = (int)(end - *pp); - name = deref_func_name(*pp, &len, partial, flags & TFN_NO_AUTOLOAD); + name = deref_func_name((const char *)(*pp), &len, partial, + flags & TFN_NO_AUTOLOAD); if (name == *pp) { name = NULL; } } if (name != NULL) { name = vim_strsave(name); - *pp = end; + *pp = (char_u *)end; if (strncmp((char *)name, "<SNR>", 5) == 0) { // Change "<SNR>" to the byte sequence. name[0] = K_SPECIAL; @@ -21119,12 +20296,13 @@ trans_function_name ( } if (lv.ll_exp_name != NULL) { - len = (int)STRLEN(lv.ll_exp_name); + len = (int)strlen(lv.ll_exp_name); if (lead <= 2 && lv.ll_name == lv.ll_exp_name - && STRNCMP(lv.ll_name, "s:", 2) == 0) { - /* When there was "s:" already or the name expanded to get a - * leading "s:" then remove it. */ + && lv.ll_name_len >= 2 && memcmp(lv.ll_name, "s:", 2) == 0) { + // When there was "s:" already or the name expanded to get a + // leading "s:" then remove it. lv.ll_name += 2; + lv.ll_name_len -= 2; len -= 2; lead = 2; } @@ -21132,37 +20310,41 @@ trans_function_name ( // Skip over "s:" and "g:". if (lead == 2 || (lv.ll_name[0] == 'g' && lv.ll_name[1] == ':')) { lv.ll_name += 2; + lv.ll_name_len -= 2; } - len = (int)(end - lv.ll_name); + len = (int)((const char *)end - lv.ll_name); } - /* - * Copy the function name to allocated memory. - * Accept <SID>name() inside a script, translate into <SNR>123_name(). - * Accept <SNR>123_name() outside a script. - */ - if (skip) - lead = 0; /* do nothing */ - else if (lead > 0) { + size_t sid_buf_len = 0; + char sid_buf[20]; + + // Copy the function name to allocated memory. + // Accept <SID>name() inside a script, translate into <SNR>123_name(). + // Accept <SNR>123_name() outside a script. + if (skip) { + lead = 0; // do nothing + } else if (lead > 0) { lead = 3; if ((lv.ll_exp_name != NULL && eval_fname_sid(lv.ll_exp_name)) - || eval_fname_sid(*pp)) { - /* It's "s:" or "<SID>" */ + || eval_fname_sid((const char *)(*pp))) { + // It's "s:" or "<SID>". if (current_SID <= 0) { EMSG(_(e_usingsid)); goto theend; } - sprintf((char *)sid_buf, "%" PRId64 "_", (int64_t)current_SID); - lead += (int)STRLEN(sid_buf); + sid_buf_len = snprintf(sid_buf, sizeof(sid_buf), + "%" PRIdSCID "_", current_SID); + lead += sid_buf_len; } - } else if (!(flags & TFN_INT) && builtin_function(lv.ll_name, len)) { + } else if (!(flags & TFN_INT) + && builtin_function(lv.ll_name, lv.ll_name_len)) { EMSG2(_("E128: Function name must start with a capital or \"s:\": %s"), start); goto theend; } - if (!skip && !(flags & TFN_QUIET)) { - char_u *cp = vim_strchr(lv.ll_name, ':'); + if (!skip && !(flags & TFN_QUIET) && !(flags & TFN_NO_DEREF)) { + char_u *cp = xmemrchr(lv.ll_name, ':', lv.ll_name_len); if (cp != NULL && cp < end) { EMSG2(_("E884: Function name cannot contain a colon: %s"), start); @@ -21175,12 +20357,13 @@ trans_function_name ( name[0] = K_SPECIAL; name[1] = KS_EXTRA; name[2] = (int)KE_SNR; - if (lead > 3) /* If it's "<SID>" */ - STRCPY(name + 3, sid_buf); + if (sid_buf_len > 0) { // If it's "<SID>" + memcpy(name + 3, sid_buf, sid_buf_len); + } } - memmove(name + lead, lv.ll_name, (size_t)len); + memmove(name + lead, lv.ll_name, len); name[lead + len] = NUL; - *pp = end; + *pp = (char_u *)end; theend: clear_lval(&lv); @@ -21192,12 +20375,13 @@ theend: * Return 2 if "p" starts with "s:". * Return 0 otherwise. */ -static int eval_fname_script(char_u *p) +static int eval_fname_script(const char *const p) { - // Use mb_stricmp() because in Turkish comparing the "I" may not work with + // Use mb_strnicmp() because in Turkish comparing the "I" may not work with // the standard library function. - if (p[0] == '<' && (mb_strnicmp(p + 1, (char_u *)"SID>", 4) == 0 - || mb_strnicmp(p + 1, (char_u *)"SNR>", 4) == 0)) { + if (p[0] == '<' + && (mb_strnicmp((char_u *)p + 1, (char_u *)"SID>", 4) == 0 + || mb_strnicmp((char_u *)p + 1, (char_u *)"SNR>", 4) == 0)) { return 5; } if (p[0] == 's' && p[1] == ':') { @@ -21206,13 +20390,19 @@ static int eval_fname_script(char_u *p) return 0; } -/* - * Return TRUE if "p" starts with "<SID>" or "s:". - * Only works if eval_fname_script() returned non-zero for "p"! - */ -static int eval_fname_sid(char_u *p) +/// Check whether function name starts with <SID> or s: +/// +/// @warning Only works for names previously checked by eval_fname_script(), if +/// it returned non-zero. +/// +/// @param[in] name Name to check. +/// +/// @return true if it starts with <SID> or s:, false otherwise. +static inline bool eval_fname_sid(const char *const name) + FUNC_ATTR_PURE FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT + FUNC_ATTR_NONNULL_ALL { - return *p == 's' || TOUPPER_ASC(p[2]) == 'I'; + return *name == 's' || TOUPPER_ASC(name[2]) == 'I'; } /* @@ -21226,38 +20416,45 @@ static void list_func_head(ufunc_T *fp, int indent) MSG_PUTS("function "); if (fp->uf_name[0] == K_SPECIAL) { MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8)); - msg_puts(fp->uf_name + 3); - } else - msg_puts(fp->uf_name); + msg_puts((const char *)fp->uf_name + 3); + } else { + msg_puts((const char *)fp->uf_name); + } msg_putchar('('); int j; - for (j = 0; j < fp->uf_args.ga_len; ++j) { - if (j) - MSG_PUTS(", "); - msg_puts(FUNCARG(fp, j)); + for (j = 0; j < fp->uf_args.ga_len; j++) { + if (j) { + msg_puts(", "); + } + msg_puts((const char *)FUNCARG(fp, j)); } if (fp->uf_varargs) { - if (j) - MSG_PUTS(", "); - MSG_PUTS("..."); + if (j) { + msg_puts(", "); + } + msg_puts("..."); } msg_putchar(')'); - if (fp->uf_flags & FC_ABORT) - MSG_PUTS(" abort"); - if (fp->uf_flags & FC_RANGE) - MSG_PUTS(" range"); - if (fp->uf_flags & FC_DICT) - MSG_PUTS(" dict"); + if (fp->uf_flags & FC_ABORT) { + msg_puts(" abort"); + } + if (fp->uf_flags & FC_RANGE) { + msg_puts(" range"); + } + if (fp->uf_flags & FC_DICT) { + msg_puts(" dict"); + } + if (fp->uf_flags & FC_CLOSURE) { + msg_puts(" closure"); + } msg_clr_eos(); if (p_verbose > 0) last_set_msg(fp->uf_script_ID); } -/* - * Find a function by name, return pointer to it in ufuncs. - * Return NULL for unknown function. - */ -static ufunc_T *find_func(char_u *name) +/// Find a function by name, return pointer to it in ufuncs. +/// @return NULL for unknown function. +static ufunc_T *find_func(const char_u *name) { hashitem_T *hi; @@ -21271,61 +20468,118 @@ static ufunc_T *find_func(char_u *name) void free_all_functions(void) { hashitem_T *hi; + ufunc_T *fp; + uint64_t skipped = 0; + uint64_t todo = 1; + uint64_t used; + + // First clear what the functions contain. Since this may lower the + // reference count of a function, it may also free a function and change + // the hash table. Restart if that happens. + while (todo > 0) { + todo = func_hashtab.ht_used; + for (hi = func_hashtab.ht_array; todo > 0; hi++) { + if (!HASHITEM_EMPTY(hi)) { + // Only free functions that are not refcounted, those are + // supposed to be freed when no longer referenced. + fp = HI2UF(hi); + if (func_name_refcount(fp->uf_name)) { + skipped++; + } else { + used = func_hashtab.ht_used; + func_clear(fp, true); + if (used != func_hashtab.ht_used) { + skipped = 0; + break; + } + } + todo--; + } + } + } - /* Need to start all over every time, because func_free() may change the - * hash table. */ - while (func_hashtab.ht_used > 0) - for (hi = func_hashtab.ht_array;; ++hi) + // Now actually free the functions. Need to start all over every time, + // because func_free() may change the hash table. + skipped = 0; + while (func_hashtab.ht_used > skipped) { + todo = func_hashtab.ht_used; + for (hi = func_hashtab.ht_array; todo > 0; hi++) { if (!HASHITEM_EMPTY(hi)) { - func_free(HI2UF(hi)); - break; + todo--; + // Only free functions that are not refcounted, those are + // supposed to be freed when no longer referenced. + fp = HI2UF(hi); + if (func_name_refcount(fp->uf_name)) { + skipped++; + } else { + func_free(fp); + skipped = 0; + break; + } } + } + } + if (skipped == 0) { + hash_clear(&func_hashtab); + } } #endif -int translated_function_exists(char_u *name) +bool translated_function_exists(const char *name) { if (builtin_function(name, -1)) { return find_internal_func((char *)name) != NULL; } - return find_func(name) != NULL; + return find_func((const char_u *)name) != NULL; } -/* - * Return TRUE if a function "name" exists. - */ -static int function_exists(char_u *name) +/// Check whether function with the given name exists +/// +/// @param[in] name Function name. +/// @param[in] no_deref Whether to dereference a Funcref. +/// +/// @return True if it exists, false otherwise. +static bool function_exists(const char *const name, bool no_deref) { - char_u *nm = name; - char_u *p; - int n = FALSE; + const char_u *nm = (const char_u *)name; + bool n = false; + int flag = TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD; - p = trans_function_name(&nm, false, TFN_INT|TFN_QUIET|TFN_NO_AUTOLOAD, - NULL, NULL); + if (no_deref) { + flag |= TFN_NO_DEREF; + } + char *const p = (char *)trans_function_name((char_u **)&nm, false, flag, NULL, + NULL); nm = skipwhite(nm); /* Only accept "funcname", "funcname ", "funcname (..." and * "funcname(...", not "funcname!...". */ - if (p != NULL && (*nm == NUL || *nm == '(')) + if (p != NULL && (*nm == NUL || *nm == '(')) { n = translated_function_exists(p); + } xfree(p); return n; } -/// Return TRUE if "name" looks like a builtin function name: starts with a +/// Checks if a builtin function with the given name exists. +/// +/// @param[in] name name of the builtin function to check. +/// @param[in] len length of "name", or -1 for NUL terminated. +/// +/// @return true if "name" looks like a builtin function name: starts with a /// lower case letter and doesn't contain AUTOLOAD_CHAR. -/// "len" is the length of "name", or -1 for NUL terminated. -static bool builtin_function(char_u *name, int len) +static bool builtin_function(const char *name, int len) { if (!ASCII_ISLOWER(name[0])) { - return FALSE; + return false; } - char_u *p = vim_strchr(name, AUTOLOAD_CHAR); + const char *p = (len == -1 + ? strchr(name, AUTOLOAD_CHAR) + : memchr(name, AUTOLOAD_CHAR, (size_t)len)); - return p == NULL - || (len > 0 && p > name + len); + return p == NULL; } /* @@ -21491,44 +20745,45 @@ static int prof_self_cmp(const void *s1, const void *s2) } -/* - * If "name" has a package name try autoloading the script for it. - * Return TRUE if a package was loaded. - */ -static int -script_autoload ( - char_u *name, - int reload /* load script again when already loaded */ -) +/// If name has a package name try autoloading the script for it +/// +/// @param[in] name Variable/function name. +/// @param[in] name_len Name length. +/// @param[in] reload If true, load script again when already loaded. +/// +/// @return true if a package was loaded. +static bool script_autoload(const char *const name, const size_t name_len, + const bool reload) { - char_u *p; - char_u *scriptname, *tofree; - int ret = FALSE; - int i; - - /* If there is no '#' after name[0] there is no package name. */ - p = vim_strchr(name, AUTOLOAD_CHAR); - if (p == NULL || p == name) - return FALSE; + // If there is no '#' after name[0] there is no package name. + const char *p = memchr(name, AUTOLOAD_CHAR, name_len); + if (p == NULL || p == name) { + return false; + } - tofree = scriptname = autoload_name(name); + bool ret = false; + char *tofree = autoload_name(name, name_len); + char *scriptname = tofree; - /* Find the name in the list of previously loaded package names. Skip - * "autoload/", it's always the same. */ - for (i = 0; i < ga_loaded.ga_len; ++i) - if (STRCMP(((char_u **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0) + // Find the name in the list of previously loaded package names. Skip + // "autoload/", it's always the same. + int i = 0; + for (; i < ga_loaded.ga_len; i++) { + if (STRCMP(((char **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0) { break; - if (!reload && i < ga_loaded.ga_len) - ret = FALSE; /* was loaded already */ - else { - /* Remember the name if it wasn't loaded already. */ + } + } + if (!reload && i < ga_loaded.ga_len) { + ret = false; // Was loaded already. + } else { + // Remember the name if it wasn't loaded already. if (i == ga_loaded.ga_len) { - GA_APPEND(char_u *, &ga_loaded, scriptname); + GA_APPEND(char *, &ga_loaded, scriptname); tofree = NULL; } // Try loading the package from $VIMRUNTIME/autoload/<name>.vim - if (source_runtime(scriptname, 0) == OK) { + if (source_runtime((char_u *)scriptname, 0) == OK) { ret = true; } } @@ -21537,21 +20792,29 @@ script_autoload ( return ret; } -/* - * Return the autoload script name for a function or variable name. - */ -static char_u *autoload_name(char_u *name) +/// Return the autoload script name for a function or variable name +/// +/// @param[in] name Variable/function name. +/// @param[in] name_len Name length. +/// +/// @return [allocated] autoload script name. +static char *autoload_name(const char *const name, const size_t name_len) + FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT { - /* Get the script file name: replace '#' with '/', append ".vim". */ - char_u *scriptname = xmalloc(STRLEN(name) + 14); - STRCPY(scriptname, "autoload/"); - STRCAT(scriptname, name); - *vim_strrchr(scriptname, AUTOLOAD_CHAR) = NUL; - STRCAT(scriptname, ".vim"); - - char_u *p; - while ((p = vim_strchr(scriptname, AUTOLOAD_CHAR)) != NULL) - *p = '/'; + // Get the script file name: replace '#' with '/', append ".vim". + char *const scriptname = xmalloc(name_len + sizeof("autoload/.vim")); + memcpy(scriptname, "autoload/", sizeof("autoload/") - 1); + memcpy(scriptname + sizeof("autoload/") - 1, name, name_len); + size_t auchar_idx = 0; + for (size_t i = sizeof("autoload/") - 1; + i - sizeof("autoload/") + 1 < name_len; + i++) { + if (scriptname[i] == AUTOLOAD_CHAR) { + scriptname[i] = '/'; + auchar_idx = i; + } + } + memcpy(scriptname + auchar_idx, ".vim", sizeof(".vim")); return scriptname; } @@ -21579,8 +20842,10 @@ char_u *get_user_func_name(expand_T *xp, int idx) ++hi; fp = HI2UF(hi); - if (fp->uf_flags & FC_DICT) - return (char_u *)""; /* don't show dict functions */ + if ((fp->uf_flags & FC_DICT) + || STRNCMP(fp->uf_name, "<lambda>", 8) == 0) { + return (char_u *)""; // don't show dict and lambda functions + } if (STRLEN(fp->uf_name) + 4 >= IOSIZE) return fp->uf_name; /* prevents overflow */ @@ -21611,9 +20876,18 @@ static void cat_func_name(char_u *buf, ufunc_T *fp) STRCPY(buf, fp->uf_name); } -/* - * ":delfunction {name}" - */ +/// There are two kinds of function names: +/// 1. ordinary names, function defined with :function +/// 2. numbered functions and lambdas +/// 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(char_u *name) +{ + return isdigit(*name) || *name == '<'; +} + +/// ":delfunction {name}" void ex_delfunction(exarg_T *eap) { ufunc_T *fp = NULL; @@ -21660,102 +20934,172 @@ void ex_delfunction(exarg_T *eap) } if (fudi.fd_dict != NULL) { - /* Delete the dict item that refers to the function, it will - * invoke func_unref() and possibly delete the function. */ - dictitem_remove(fudi.fd_dict, fudi.fd_di); - } else - func_free(fp); + // Delete the dict item that refers to the function, it will + // invoke func_unref() and possibly delete the function. + tv_dict_item_remove(fudi.fd_dict, fudi.fd_di); + } else { + // A normal function (not a numbered function or lambda) has a + // refcount of 1 for the entry in the hashtable. When deleting + // 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(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)) { + fp->uf_refcount--; + } + fp->uf_flags |= FC_DELETED; + } else { + func_clear_free(fp, false); + } + } } } -/* - * Free a function and remove it from the list of functions. - */ -static void func_free(ufunc_T *fp) +/// Remove the function from the function hashtable. If the function was +/// deleted while it still has references this was already done. +/// +/// @return true if the entry was deleted, false if it wasn't found. +static bool func_remove(ufunc_T *fp) { - hashitem_T *hi; + hashitem_T *hi = hash_find(&func_hashtab, UF2HIKEY(fp)); + + if (!HASHITEM_EMPTY(hi)) { + hash_remove(&func_hashtab, hi); + return true; + } + + return false; +} - /* clear this function */ +/// Free all things that a function contains. Does not free the function +/// itself, use func_free() for that. +/// +/// param[in] force When true, we are exiting. +static void func_clear(ufunc_T *fp, bool force) +{ + if (fp->uf_cleared) { + return; + } + fp->uf_cleared = true; + + // clear this function ga_clear_strings(&(fp->uf_args)); ga_clear_strings(&(fp->uf_lines)); xfree(fp->uf_tml_count); xfree(fp->uf_tml_total); xfree(fp->uf_tml_self); + funccal_unref(fp->uf_scoped, fp, force); +} - /* remove the function from the function hashtable */ - hi = hash_find(&func_hashtab, UF2HIKEY(fp)); - if (HASHITEM_EMPTY(hi)) - EMSG2(_(e_intern2), "func_free()"); - else - hash_remove(&func_hashtab, hi); - +/// Free a function and remove it from the list of functions. Does not free +/// what a function contains, call func_clear() first. +/// +/// param[in] fp The function to free. +static void func_free(ufunc_T *fp) +{ + // only remove it when not done already, otherwise we would remove a newer + // version of the function + if ((fp->uf_flags & (FC_DELETED | FC_REMOVED)) == 0) { + func_remove(fp); + } xfree(fp); } +/// Free all things that a function contains and free the function itself. +/// +/// param[in] force When true, we are exiting. +static void func_clear_free(ufunc_T *fp, bool force) +{ + func_clear(fp, force); + func_free(fp); +} + /* * Unreference a Function: decrement the reference count and free it when it - * becomes zero. Only for numbered functions. + * becomes zero. */ void func_unref(char_u *name) { - ufunc_T *fp; + ufunc_T *fp = NULL; - if (name != NULL && isdigit(*name)) { - fp = find_func(name); - if (fp == NULL) { + if (name == NULL || !func_name_refcount(name)) { + return; + } + + fp = find_func(name); + if (fp == NULL && isdigit(*name)) { #ifdef EXITFREE - if (!entered_free_all_mem) { - EMSG2(_(e_intern2), "func_unref()"); - } + if (!entered_free_all_mem) { + EMSG2(_(e_intern2), "func_unref()"); + abort(); + } #else EMSG2(_(e_intern2), "func_unref()"); + abort(); #endif - } else { - user_func_unref(fp); - } } + func_ptr_unref(fp); } -static void user_func_unref(ufunc_T *fp) +/// Unreference a Function: decrement the reference count and free it when it +/// becomes zero. +/// Unreference user function, freeing it if needed +/// +/// Decrements the reference count and frees when it becomes zero. +/// +/// @param fp Function to unreference. +void func_ptr_unref(ufunc_T *fp) { - if (--fp->uf_refcount <= 0) { - // Only delete it when it's not being used. Otherwise it's done + if (fp != NULL && --fp->uf_refcount <= 0) { + // Only delete it when it's not being used. Otherwise it's done // when "uf_calls" becomes zero. if (fp->uf_calls == 0) { - func_free(fp); + func_clear_free(fp, false); } } } -/* - * Count a reference to a Function. - */ +/// Count a reference to a Function. void func_ref(char_u *name) { ufunc_T *fp; - if (name != NULL && isdigit(*name)) { - fp = find_func(name); - if (fp == NULL) - EMSG2(_(e_intern2), "func_ref()"); - else - ++fp->uf_refcount; + if (name == NULL || !func_name_refcount(name)) { + return; + } + fp = find_func(name); + if (fp != NULL) { + (fp->uf_refcount)++; + } else if (isdigit(*name)) { + // Only give an error for a numbered function. + // Fail silently, when named or lambda function isn't found. + EMSG2(_(e_intern2), "func_ref()"); } } -/* - * Call a user function. - */ -static void -call_user_func ( - ufunc_T *fp, /* pointer to function */ - int argcount, /* nr of args */ - typval_T *argvars, /* arguments */ - typval_T *rettv, /* return value */ - linenr_T firstline, /* first line of range */ - linenr_T lastline, /* last line of range */ - dict_T *selfdict /* Dictionary for "self" */ -) +/// Count a reference to a Function. +void func_ptr_ref(ufunc_T *fp) +{ + if (fp != NULL) { + (fp->uf_refcount)++; + } +} + +/// Call a user function +/// +/// @param fp Function to call. +/// @param[in] argcount Number of arguments. +/// @param argvars Arguments. +/// @param[out] rettv Return value. +/// @param[in] firstline First line of range. +/// @param[in] lastline Last line of range. +/// @param selfdict Dictionary for "self" for dictionary functions. +void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, + typval_T *rettv, linenr_T firstline, linenr_T lastline, + dict_T *selfdict) + FUNC_ATTR_NONNULL_ARG(1, 3, 4) { char_u *save_sourcing_name; linenr_T save_sourcing_lnum; @@ -21766,6 +21110,7 @@ call_user_func ( dictitem_T *v; int fixvar_idx = 0; /* index in fixvar[] */ int ai; + bool islambda = false; char_u numbuf[NUMBUFLEN]; char_u *name; proftime_T wait_start; @@ -21803,25 +21148,32 @@ call_user_func ( fc->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0); fc->dbg_tick = debug_tick; - /* - * Note about using fc->fixvar[]: This is an array of FIXVAR_CNT variables - * with names up to VAR_SHORT_LEN long. This avoids having to alloc/free - * each argument variable and saves a lot of time. - */ - /* - * Init l: variables. - */ + // Set up fields for closure. + fc->fc_refcount = 0; + fc->fc_copyID = 0; + ga_init(&fc->fc_funcs, sizeof(ufunc_T *), 1); + func_ptr_ref(fp); + + if (STRNCMP(fp->uf_name, "<lambda>", 8) == 0) { + islambda = true; + } + + // Note about using fc->fixvar[]: This is an array of FIXVAR_CNT variables + // with names up to VAR_SHORT_LEN long. This avoids having to alloc/free + // each argument variable and saves a lot of time. + // + // Init l: variables. init_var_dict(&fc->l_vars, &fc->l_vars_var, VAR_DEF_SCOPE); if (selfdict != NULL) { - /* Set l:self to "selfdict". Use "name" to avoid a warning from - * some compiler that checks the destination size. */ - v = &fc->fixvar[fixvar_idx++].var; + // Set l:self to "selfdict". Use "name" to avoid a warning from + // some compiler that checks the destination size. + v = (dictitem_T *)&fc->fixvar[fixvar_idx++]; #ifndef __clang_analyzer__ name = v->di_key; STRCPY(name, "self"); #endif v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX; - hash_add(&fc->l_vars.dv_hashtab, DI2HIKEY(v)); + tv_dict_add(&fc->l_vars, v); v->di_tv.v_type = VAR_DICT; v->di_tv.v_lock = 0; v->di_tv.vval.v_dict = selfdict; @@ -21834,17 +21186,17 @@ call_user_func ( * Set a:000 to a list with room for the "..." arguments. */ init_var_dict(&fc->l_avars, &fc->l_avars_var, VAR_SCOPE); - add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0", - (varnumber_T)(argcount - fp->uf_args.ga_len)); - /* Use "name" to avoid a warning from some compiler that checks the - * destination size. */ - v = &fc->fixvar[fixvar_idx++].var; + add_nr_var(&fc->l_avars, (dictitem_T *)&fc->fixvar[fixvar_idx++], "0", + (varnumber_T)(argcount - fp->uf_args.ga_len)); + // Use "name" to avoid a warning from some compiler that checks the + // destination size. + v = (dictitem_T *)&fc->fixvar[fixvar_idx++]; #ifndef __clang_analyzer__ name = v->di_key; STRCPY(name, "000"); #endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; - hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v)); + tv_dict_add(&fc->l_avars, v); v->di_tv.v_type = VAR_LIST; v->di_tv.v_lock = VAR_FIXED; v->di_tv.vval.v_list = &fc->l_varlist; @@ -21852,42 +21204,53 @@ call_user_func ( fc->l_varlist.lv_refcount = DO_NOT_FREE_CNT; fc->l_varlist.lv_lock = VAR_FIXED; - /* - * Set a:firstline to "firstline" and a:lastline to "lastline". - * Set a:name to named arguments. - * Set a:N to the "..." arguments. - */ - add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "firstline", - (varnumber_T)firstline); - add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline", - (varnumber_T)lastline); - for (int i = 0; i < argcount; ++i) { + // Set a:firstline to "firstline" and a:lastline to "lastline". + // Set a:name to named arguments. + // Set a:N to the "..." arguments. + add_nr_var(&fc->l_avars, (dictitem_T *)&fc->fixvar[fixvar_idx++], + "firstline", (varnumber_T)firstline); + add_nr_var(&fc->l_avars, (dictitem_T *)&fc->fixvar[fixvar_idx++], + "lastline", (varnumber_T)lastline); + for (int i = 0; i < argcount; i++) { + bool addlocal = false; + ai = i - fp->uf_args.ga_len; - if (ai < 0) - /* named argument a:name */ + if (ai < 0) { + // named argument a:name name = FUNCARG(fp, i); - else { - /* "..." argument a:1, a:2, etc. */ - sprintf((char *)numbuf, "%d", ai + 1); + if (islambda) { + addlocal = true; + } + } else { + // "..." argument a:1, a:2, etc. + snprintf((char *)numbuf, sizeof(numbuf), "%d", ai + 1); name = numbuf; } if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN) { - v = &fc->fixvar[fixvar_idx++].var; + v = (dictitem_T *)&fc->fixvar[fixvar_idx++]; v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; } else { v = xmalloc(sizeof(dictitem_T) + STRLEN(name)); v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX | DI_FLAGS_ALLOC; } STRCPY(v->di_key, name); - hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v)); - /* Note: the values are copied directly to avoid alloc/free. - * "argvars" must have VAR_FIXED for v_lock. */ + // Note: the values are copied directly to avoid alloc/free. + // "argvars" must have VAR_FIXED for v_lock. v->di_tv = argvars[i]; v->di_tv.v_lock = VAR_FIXED; + if (addlocal) { + // Named arguments can be accessed without the "a:" prefix in lambda + // expressions. Add to the l: dict. + tv_copy(&v->di_tv, &v->di_tv); + tv_dict_add(&fc->l_vars, v); + } else { + tv_dict_add(&fc->l_avars, v); + } + if (ai >= 0 && ai < MAX_FUNC_ARGS) { - list_append(&fc->l_varlist, &fc->l_listitems[ai]); + tv_list_append(&fc->l_varlist, &fc->l_listitems[ai]); fc->l_listitems[ai].li_tv = argvars[i]; fc->l_listitems[ai].li_tv.v_lock = VAR_FIXED; } @@ -21925,24 +21288,24 @@ call_user_func ( smsg(_("calling %s"), sourcing_name); if (p_verbose >= 14) { - char_u buf[MSG_BUF_LEN]; - - msg_puts((char_u *)"("); - for (int i = 0; i < argcount; ++i) { + msg_puts("("); + for (int i = 0; i < argcount; i++) { if (i > 0) { - msg_puts((char_u *)", "); + msg_puts(", "); } if (argvars[i].v_type == VAR_NUMBER) { msg_outnum((long)argvars[i].vval.v_number); } else { // Do not want errors such as E724 here. emsg_off++; - char_u *s = (char_u *) encode_tv2string(&argvars[i], NULL); - char_u *tofree = s; + char *tofree = encode_tv2string(&argvars[i], NULL); emsg_off--; - if (s != NULL) { - if (vim_strsize(s) > MSG_BUF_CLEN) { - trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN); + if (tofree != NULL) { + char *s = tofree; + char buf[MSG_BUF_LEN]; + if (vim_strsize((char_u *)s) > MSG_BUF_CLEN) { + trunc_string((char_u *)s, (char_u *)buf, MSG_BUF_CLEN, + sizeof(buf)); s = buf; } msg_puts(s); @@ -21950,9 +21313,9 @@ call_user_func ( } } } - msg_puts((char_u *)")"); + msg_puts(")"); } - msg_puts((char_u *)"\n"); /* don't overwrite this either */ + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); --no_wait_return; @@ -21995,14 +21358,14 @@ call_user_func ( // when the function was aborted because of an error, return -1 if ((did_emsg && (fp->uf_flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN) { - clear_tv(rettv); + tv_clear(rettv); rettv->v_type = VAR_NUMBER; rettv->vval.v_number = -1; } if (func_or_func_caller_profiling) { call_start = profile_end(call_start); - call_start = profile_sub_wait(wait_start, call_start); + call_start = profile_sub_wait(wait_start, call_start); // -V614 fp->uf_tm_total = profile_add(fp->uf_tm_total, call_start); fp->uf_tm_self = profile_self(fp->uf_tm_self, call_start, fp->uf_tm_children); @@ -22043,7 +21406,7 @@ call_user_func ( xfree(tofree); } } - msg_puts((char_u *)"\n"); /* don't overwrite this either */ + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); --no_wait_return; @@ -22061,7 +21424,7 @@ call_user_func ( verbose_enter_scroll(); smsg(_("continuing in %s"), sourcing_name); - msg_puts((char_u *)"\n"); /* don't overwrite this either */ + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); --no_wait_return; @@ -22071,41 +21434,35 @@ call_user_func ( current_funccal = fc->caller; --depth; - /* If the a:000 list and the l: and a: dicts are not referenced we can - * free the funccall_T and what's in it. */ + // If the a:000 list and the l: and a: dicts are not referenced and there + // is no closure using it, we can free the funccall_T and what's in it. if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT - && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT) { - free_funccal(fc, FALSE); + && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT + && fc->fc_refcount <= 0) { + free_funccal(fc, false); } else { - hashitem_T *hi; - listitem_T *li; - int todo; - - /* "fc" is still in use. This can happen when returning "a:000" or - * assigning "l:" to a global variable. - * Link "fc" in the list for garbage collection later. */ + // "fc" is still in use. This can happen when returning "a:000", + // assigning "l:" to a global variable or defining a closure. + // Link "fc" in the list for garbage collection later. fc->caller = previous_funccal; previous_funccal = fc; - /* Make a copy of the a: variables, since we didn't do that above. */ - todo = (int)fc->l_avars.dv_hashtab.ht_used; - for (hi = fc->l_avars.dv_hashtab.ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - v = HI2DI(hi); - copy_tv(&v->di_tv, &v->di_tv); - } - } + // Make a copy of the a: variables, since we didn't do that above. + TV_DICT_ITER(&fc->l_avars, di, { + tv_copy(&di->di_tv, &di->di_tv); + }); - /* Make a copy of the a:000 items, since we didn't do that above. */ - for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next) - copy_tv(&li->li_tv, &li->li_tv); + // Make a copy of the a:000 items, since we didn't do that above. + for (listitem_T *li = fc->l_varlist.lv_first; li != NULL; + li = li->li_next) { + tv_copy(&li->li_tv, &li->li_tv); + } } - if (--fp->uf_calls <= 0 && isdigit(*fp->uf_name) && fp->uf_refcount <= 0) { + if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0) { // Function was unreferenced while being used, free it now. - func_free(fp); + func_clear_free(fp, false); } // restore search patterns and redo buffer if (did_save_redo) { @@ -22114,15 +21471,46 @@ call_user_func ( restore_search_patterns(); } -/* - * Return TRUE if items in "fc" do not have "copyID". That means they are not - * referenced from anywhere that is in use. - */ +/// Unreference "fc": decrement the reference count and free it when it +/// becomes zero. "fp" is detached from "fc". +/// +/// @param[in] force When true, we are exiting. +static void funccal_unref(funccall_T *fc, ufunc_T *fp, bool force) +{ + funccall_T **pfc; + int i; + + if (fc == NULL) { + return; + } + + if (--fc->fc_refcount <= 0 && (force || ( + fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT + && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT + && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT))) { + for (pfc = &previous_funccal; *pfc != NULL; pfc = &(*pfc)->caller) { + if (fc == *pfc) { + *pfc = fc->caller; + free_funccal(fc, true); + return; + } + } + } + for (i = 0; i < fc->fc_funcs.ga_len; i++) { + if (((ufunc_T **)(fc->fc_funcs.ga_data))[i] == fp) { + ((ufunc_T **)(fc->fc_funcs.ga_data))[i] = NULL; + } + } +} + +/// @return true if items in "fc" do not have "copyID". That means they are not +/// referenced from anywhere that is in use. static int can_free_funccal(funccall_T *fc, int copyID) { return fc->l_varlist.lv_copyID != copyID && fc->l_vars.dv_copyID != copyID - && fc->l_avars.dv_copyID != copyID; + && fc->l_avars.dv_copyID != copyID + && fc->fc_copyID != copyID; } /* @@ -22136,18 +21524,34 @@ free_funccal ( { listitem_T *li; - /* The a: variables typevals may not have been allocated, only free the - * allocated variables. */ + for (int i = 0; i < fc->fc_funcs.ga_len; i++) { + ufunc_T *fp = ((ufunc_T **)(fc->fc_funcs.ga_data))[i]; + + // When garbage collecting a funccall_T may be freed before the + // function that references it, clear its uf_scoped field. + // The function may have been redefined and point to another + // funccal_T, don't clear it then. + if (fp != NULL && fp->uf_scoped == fc) { + fp->uf_scoped = NULL; + } + } + ga_clear(&fc->fc_funcs); + + // The a: variables typevals may not have been allocated, only free the + // allocated variables. vars_clear_ext(&fc->l_avars.dv_hashtab, free_val); /* free all l: variables */ vars_clear(&fc->l_vars.dv_hashtab); - /* Free the a:000 variables if they were allocated. */ - if (free_val) - for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next) - clear_tv(&li->li_tv); + // Free the a:000 variables if they were allocated. + if (free_val) { + for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next) { + tv_clear(&li->li_tv); + } + } + func_ptr_unref(fc->func); xfree(fc); } @@ -22160,7 +21564,7 @@ static void add_nr_var(dict_T *dp, dictitem_T *v, char *name, varnumber_T nr) STRCPY(v->di_key, name); #endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; - hash_add(&dp->dv_hashtab, DI2HIKEY(v)); + tv_dict_add(dp, v); v->di_tv.v_type = VAR_NUMBER; v->di_tv.v_lock = VAR_FIXED; v->di_tv.vval.v_number = nr; @@ -22186,10 +21590,11 @@ void ex_return(exarg_T *eap) eap->nextcmd = NULL; if ((*arg != NUL && *arg != '|' && *arg != '\n') && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL) { - if (!eap->skip) - returning = do_return(eap, FALSE, TRUE, &rettv); - else - clear_tv(&rettv); + if (!eap->skip) { + returning = do_return(eap, false, true, &rettv); + } else { + tv_clear(&rettv); + } } /* It's safer to return also on error. */ else if (!eap->skip) { @@ -22276,7 +21681,7 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv) * a return immediately after reanimation, the value is already * there. */ if (!reanimate && rettv != NULL) { - clear_tv(current_funccal->rettv); + tv_clear(current_funccal->rettv); *current_funccal->rettv = *(typval_T *)rettv; if (!is_cmd) xfree(rettv); @@ -22287,14 +21692,6 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv) } /* - * Free the variable with a pending return value. - */ -void discard_pending_return(void *rettv) -{ - free_tv((typval_T *)rettv); -} - -/* * Generate a return command for producing the value of "rettv". The result * is an allocated string. Used by report_pending() for verbose messages. */ @@ -22311,7 +21708,7 @@ char_u *get_return_cmd(void *rettv) } STRCPY(IObuff, ":return "); - STRNCPY(IObuff + 8, s, IOSIZE - 8); + STRLCPY(IObuff + 8, s, IOSIZE - 8); if (STRLEN(s) + 8 >= IOSIZE) STRCPY(IObuff + IOSIZE - 4, "..."); xfree(tofree); @@ -22466,6 +21863,72 @@ static var_flavour_T var_flavour(char_u *varname) } } +/// Search hashitem in parent scope. +hashitem_T *find_hi_in_scoped_ht(const char *name, hashtab_T **pht) +{ + if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) { + return NULL; + } + + funccall_T *old_current_funccal = current_funccal; + hashitem_T *hi = NULL; + const size_t namelen = strlen(name); + const char *varname; + + // Search in parent scope which is possible to reference from lambda + current_funccal = current_funccal->func->uf_scoped; + while (current_funccal != NULL) { + hashtab_T *ht = find_var_ht(name, namelen, &varname); + if (ht != NULL && *varname != NUL) { + hi = hash_find_len(ht, varname, namelen - (varname - name)); + if (!HASHITEM_EMPTY(hi)) { + *pht = ht; + break; + } + } + if (current_funccal == current_funccal->func->uf_scoped) { + break; + } + current_funccal = current_funccal->func->uf_scoped; + } + current_funccal = old_current_funccal; + + return hi; +} + +/// Search variable in parent scope. +dictitem_T *find_var_in_scoped_ht(const char *name, const size_t namelen, + int no_autoload) +{ + if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) { + return NULL; + } + + dictitem_T *v = NULL; + funccall_T *old_current_funccal = current_funccal; + const char *varname; + + // Search in parent scope which is possible to reference from lambda + current_funccal = current_funccal->func->uf_scoped; + while (current_funccal) { + hashtab_T *ht = find_var_ht(name, namelen, &varname); + if (ht != NULL && *varname != NUL) { + v = find_var_in_ht(ht, *name, varname, + namelen - (size_t)(varname - name), no_autoload); + if (v != NULL) { + break; + } + } + if (current_funccal == current_funccal->func->uf_scoped) { + break; + } + current_funccal = current_funccal->func->uf_scoped; + } + current_funccal = old_current_funccal; + + return v; +} + /// Iterate over global variables /// /// @warning No modifications to global variable dictionary must be performed @@ -22489,7 +21952,7 @@ const void *var_shada_iter(const void *const iter, const char **const name, hi = globvarht.ht_array; while ((size_t) (hi - hifirst) < hinum && (HASHITEM_EMPTY(hi) - || var_flavour(HI2DI(hi)->di_key) != VAR_FLAVOUR_SHADA)) { + || var_flavour(hi->hi_key) != VAR_FLAVOUR_SHADA)) { hi++; } if ((size_t) (hi - hifirst) == hinum) { @@ -22498,11 +21961,10 @@ const void *var_shada_iter(const void *const iter, const char **const name, } else { hi = (const hashitem_T *) iter; } - *name = (char *) HI2DI(hi)->di_key; - copy_tv(&(HI2DI(hi)->di_tv), rettv); - while ((size_t) (++hi - hifirst) < hinum) { - if (!HASHITEM_EMPTY(hi) - && var_flavour(HI2DI(hi)->di_key) == VAR_FLAVOUR_SHADA) { + *name = (char *)TV_DICT_HI2DI(hi)->di_key; + tv_copy(&TV_DICT_HI2DI(hi)->di_tv, rettv); + while ((size_t)(++hi - hifirst) < hinum) { + if (!HASHITEM_EMPTY(hi) && var_flavour(hi->hi_key) == VAR_FLAVOUR_SHADA) { return hi; } } @@ -22513,62 +21975,55 @@ void var_set_global(const char *const name, typval_T vartv) { funccall_T *const saved_current_funccal = current_funccal; current_funccal = NULL; - set_var((char_u *) name, &vartv, false); + set_var(name, strlen(name), &vartv, false); current_funccal = saved_current_funccal; } int store_session_globals(FILE *fd) { - hashitem_T *hi; - dictitem_T *this_var; - int todo; - char_u *p, *t; - - todo = (int)globvarht.ht_used; - for (hi = globvarht.ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - this_var = HI2DI(hi); - if ((this_var->di_tv.v_type == VAR_NUMBER - || this_var->di_tv.v_type == VAR_STRING) - && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION) { - /* Escape special characters with a backslash. Turn a LF and - * CR into \n and \r. */ - p = vim_strsave_escaped(get_tv_string(&this_var->di_tv), - (char_u *)"\\\"\n\r"); - for (t = p; *t != NUL; ++t) - if (*t == '\n') - *t = 'n'; - else if (*t == '\r') - *t = 'r'; - if ((fprintf(fd, "let %s = %c%s%c", - this_var->di_key, - (this_var->di_tv.v_type == VAR_STRING) ? '"' - : ' ', - p, - (this_var->di_tv.v_type == VAR_STRING) ? '"' - : ' ') < 0) - || put_eol(fd) == FAIL) { - xfree(p); - return FAIL; + TV_DICT_ITER(&globvardict, this_var, { + if ((this_var->di_tv.v_type == VAR_NUMBER + || this_var->di_tv.v_type == VAR_STRING) + && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION) { + // Escape special characters with a backslash. Turn a LF and + // CR into \n and \r. + char_u *const p = vim_strsave_escaped( + (const char_u *)tv_get_string(&this_var->di_tv), + (const char_u *)"\\\"\n\r"); + for (char_u *t = p; *t != NUL; t++) { + if (*t == '\n') { + *t = 'n'; + } else if (*t == '\r') { + *t = 'r'; } + } + if ((fprintf(fd, "let %s = %c%s%c", + this_var->di_key, + ((this_var->di_tv.v_type == VAR_STRING) ? '"' + : ' '), + p, + ((this_var->di_tv.v_type == VAR_STRING) ? '"' + : ' ')) < 0) + || put_eol(fd) == FAIL) { xfree(p); - } else if (this_var->di_tv.v_type == VAR_FLOAT - && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION) { - float_T f = this_var->di_tv.vval.v_float; - int sign = ' '; - - if (f < 0) { - f = -f; - sign = '-'; - } - if ((fprintf(fd, "let %s = %c%f", - this_var->di_key, sign, f) < 0) - || put_eol(fd) == FAIL) - return FAIL; + return FAIL; + } + xfree(p); + } else if (this_var->di_tv.v_type == VAR_FLOAT + && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION) { + float_T f = this_var->di_tv.vval.v_float; + int sign = ' '; + + if (f < 0) { + f = -f; + sign = '-'; + } + if ((fprintf(fd, "let %s = %c%f", this_var->di_key, sign, f) < 0) + || put_eol(fd) == FAIL) { + return FAIL; } } - } + }); return OK; } @@ -22588,51 +22043,6 @@ void last_set_msg(scid_T scriptID) } } -/* - * List v:oldfiles in a nice way. - */ -void ex_oldfiles(exarg_T *eap) -{ - list_T *l = get_vim_var_list(VV_OLDFILES); - listitem_T *li; - long nr = 0; - - if (l == NULL) - msg((char_u *)_("No old files")); - else { - msg_start(); - msg_scroll = TRUE; - for (li = l->lv_first; li != NULL && !got_int; li = li->li_next) { - msg_outnum(++nr); - MSG_PUTS(": "); - msg_outtrans(get_tv_string(&li->li_tv)); - msg_putchar('\n'); - ui_flush(); /* output one line at a time */ - os_breakcheck(); - } - /* Assume "got_int" was set to truncate the listing. */ - got_int = FALSE; - - // File selection prompt on ":browse oldfiles" - if (cmdmod.browse) { - quit_more = false; - nr = prompt_for_number(false); - msg_starthere(); - if (nr > 0 && nr <= l->lv_len) { - char_u *p = list_find_str(l, nr); - if (p == NULL) { - return; - } - p = expand_env_save(p); - eap->arg = p; - eap->cmdidx = CMD_edit; - do_exedit(eap, NULL); - xfree(p); - } - } - } -} - // reset v:option_new, v:option_old and v:option_type void reset_v_option_vars(void) { @@ -22865,7 +22275,7 @@ repeat: sub = vim_strnsave(s, (int)(p - s)); str = vim_strnsave(*fnamep, *fnamelen); *usedlen = (size_t)(p + 1 - src); - s = do_string_sub(str, pat, sub, flags); + s = do_string_sub(str, pat, sub, NULL, flags); *fnamep = s; *fnamelen = STRLEN(s); xfree(*bufp); @@ -22901,12 +22311,12 @@ repeat: return valid; } -/* - * Perform a substitution on "str" with pattern "pat" and substitute "sub". - * "flags" can be "g" to do a global substitute. - * Returns an allocated string, NULL for error. - */ -char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, char_u *flags) +/// Perform a substitution on "str" with pattern "pat" and substitute "sub". +/// When "sub" is NULL "expr" is used, must be a VAR_FUNC or VAR_PARTIAL. +/// "flags" can be "g" to do a global substitute. +/// Returns an allocated string, NULL for error. +char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, + typval_T *expr, char_u *flags) { int sublen; regmatch_T regmatch; @@ -22944,23 +22354,21 @@ char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, char_u *flags) zero_width = regmatch.startp[0]; } - /* - * Get some space for a temporary buffer to do the substitution - * into. It will contain: - * - The text up to where the match is. - * - The substituted text. - * - The text after the match. - */ - sublen = vim_regsub(®match, sub, tail, FALSE, TRUE, FALSE); + // Get some space for a temporary buffer to do the substitution + // into. It will contain: + // - The text up to where the match is. + // - The substituted text. + // - The text after the match. + sublen = vim_regsub(®match, sub, expr, tail, false, true, false); ga_grow(&ga, (int)((end - tail) + sublen - (regmatch.endp[0] - regmatch.startp[0]))); /* copy the text up to where the match is */ 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(®match, sub, (char_u *)ga.ga_data - + ga.ga_len + i, TRUE, TRUE, FALSE); + // add the substituted text + (void)vim_regsub(®match, sub, expr, (char_u *)ga.ga_data + + ga.ga_len + i, true, true, false); ga.ga_len += i + sublen - 1; tail = regmatch.endp[0]; if (*tail == NUL) @@ -22977,11 +22385,12 @@ char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, char_u *flags) char_u *ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data); ga_clear(&ga); - if (p_cpo == empty_option) + if (p_cpo == empty_option) { p_cpo = save_cpo; - else - /* Darn, evaluating {sub} expression changed the value. */ + } else { + // Darn, evaluating {sub} expression or {expr} changed the value. free_string_option(save_cpo); + } return ret; } @@ -22993,7 +22402,7 @@ static inline TerminalJobData *common_job_init(char **argv, bool pty, bool rpc, bool detach, - char *cwd) + const char *cwd) { TerminalJobData *data = xcalloc(1, sizeof(TerminalJobData)); data->stopped = false; @@ -23027,9 +22436,9 @@ static inline TerminalJobData *common_job_init(char **argv, static inline bool common_job_callbacks(dict_T *vopts, Callback *on_stdout, Callback *on_stderr, Callback *on_exit) { - if (get_dict_callback(vopts, "on_stdout", on_stdout) - && get_dict_callback(vopts, "on_stderr", on_stderr) - && get_dict_callback(vopts, "on_exit", on_exit)) { + if (tv_dict_get_callback(vopts, S_LEN("on_stdout"), on_stdout) + &&tv_dict_get_callback(vopts, S_LEN("on_stderr"), on_stderr) + && tv_dict_get_callback(vopts, S_LEN("on_exit"), on_exit)) { vopts->dv_refcount++; return true; } @@ -23056,8 +22465,9 @@ static inline bool common_job_start(TerminalJobData *data, typval_T *rettv) data->refcount++; char *cmd = xstrdup(proc->argv[0]); - if (!process_spawn(proc)) { - EMSG2(_(e_jobspawn), cmd); + int status = process_spawn(proc); + if (status) { + EMSG3(_(e_jobspawn), os_strerror(status), cmd); xfree(cmd); if (proc->type == kProcessTypePty) { xfree(data->proc.pty.term_name); @@ -23070,8 +22480,9 @@ static inline bool common_job_start(TerminalJobData *data, typval_T *rettv) if (data->rpc) { - // the rpc channel takes over the in and out streams - channel_from_process(proc, data->id); + eval_format_source_name_line((char *)IObuff, sizeof(IObuff)); + // RPC channel takes over the in/out streams. + channel_from_process(proc, data->id, (char *)IObuff); } else { wstream_init(proc->in, 0); if (proc->out) { @@ -23115,7 +22526,7 @@ static inline void process_job_event(TerminalJobData *data, Callback *callback, JobEvent event_data; event_data.received = NULL; if (buf) { - event_data.received = list_alloc(); + event_data.received = tv_list_alloc(); char *ptr = buf; size_t remaining = count; size_t off = 0; @@ -23123,7 +22534,7 @@ static inline void process_job_event(TerminalJobData *data, Callback *callback, while (off < remaining) { // append the line if (ptr[off] == NL) { - list_append_string(event_data.received, (uint8_t *)ptr, off); + tv_list_append_string(event_data.received, ptr, off); size_t skip = off + 1; ptr += skip; remaining -= skip; @@ -23136,7 +22547,7 @@ static inline void process_job_event(TerminalJobData *data, Callback *callback, } off++; } - list_append_string(event_data.received, (uint8_t *)ptr, off); + tv_list_append_string(event_data.received, ptr, off); } else { event_data.status = status; } @@ -23179,11 +22590,10 @@ static void on_job_output(Stream *stream, TerminalJobData *data, RBuffer *buf, terminal_receive(data->term, ptr, count); } + rbuffer_consumed(buf, count); if (callback->type != kCallbackNone) { process_job_event(data, callback, type, ptr, count, 0); } - - rbuffer_consumed(buf, count); } static void eval_job_process_exit_cb(Process *proc, int status, void *d) @@ -23283,10 +22693,9 @@ static void on_job_event(JobEvent *ev) argv[2].v_lock = 0; argv[2].vval.v_string = (uint8_t *)ev->type; - typval_T rettv; - init_tv(&rettv); + typval_T rettv = TV_INITIAL_VALUE; callback_call(ev->callback, 3, argv, &rettv); - clear_tv(&rettv); + tv_clear(&rettv); } static TerminalJobData *find_job(uint64_t id) @@ -23309,8 +22718,8 @@ static void script_host_eval(char *name, typval_T *argvars, typval_T *rettv) return; } - list_T *args = list_alloc(); - list_append_string(args, argvars[0].vval.v_string, -1); + list_T *args = tv_list_alloc(); + tv_list_append_string(args, (const char *)argvars[0].vval.v_string, -1); *rettv = eval_call_provider(name, "eval", args); } @@ -23342,11 +22751,12 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments) arguments->lv_refcount++; int dummy; - (void)call_func((uint8_t *)func, + (void)call_func((const char_u *)func, name_len, &rettv, 2, argvars, + NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy, @@ -23354,7 +22764,7 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments) NULL, NULL); - list_unref(arguments); + tv_list_unref(arguments); // Restore caller scope information restore_funccal(provider_caller_scope.funccalp); provider_caller_scope = saved_provider_caller_scope; @@ -23363,14 +22773,16 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments) return rettv; } -bool eval_has_provider(char *name) +bool eval_has_provider(const char *name) { -#define check_provider(name) \ +#define CHECK_PROVIDER(name) \ if (has_##name == -1) { \ - has_##name = !!find_func((uint8_t *)"provider#" #name "#Call"); \ + has_##name = !!find_func((char_u *)"provider#" #name "#Call"); \ if (!has_##name) { \ - script_autoload((uint8_t *)"provider#" #name "#Call", false); \ - has_##name = !!find_func((uint8_t *)"provider#" #name "#Call"); \ + script_autoload("provider#" #name "#Call", \ + sizeof("provider#" #name "#Call") - 1, \ + false); \ + has_##name = !!find_func((char_u *)"provider#" #name "#Call"); \ } \ } @@ -23379,107 +22791,27 @@ bool eval_has_provider(char *name) static int has_python3 = -1; static int has_ruby = -1; - if (!strcmp(name, "clipboard")) { - check_provider(clipboard); + if (strequal(name, "clipboard")) { + CHECK_PROVIDER(clipboard); return has_clipboard; - } else if (!strcmp(name, "python3")) { - check_provider(python3); + } else if (strequal(name, "python3")) { + CHECK_PROVIDER(python3); return has_python3; - } else if (!strcmp(name, "python")) { - check_provider(python); + } else if (strequal(name, "python")) { + CHECK_PROVIDER(python); return has_python; - } else if (!strcmp(name, "ruby")) { - check_provider(ruby); + } else if (strequal(name, "ruby")) { + CHECK_PROVIDER(ruby); return has_ruby; } return false; } -// Compute the `DictWatcher` address from a QUEUE node. This only exists for -// .asan-blacklist (ASAN doesn't handle QUEUE_DATA pointer arithmetic). -static DictWatcher *dictwatcher_node_data(QUEUE *q) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET -{ - return QUEUE_DATA(q, DictWatcher, node); -} - -// Send a change notification to all `dict` watchers that match `key`. -static void dictwatcher_notify(dict_T *dict, const char *key, typval_T *newtv, - typval_T *oldtv) - FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_NONNULL_ARG(2) -{ - typval_T argv[4]; - for (size_t i = 0; i < ARRAY_SIZE(argv); i++) { - init_tv(argv + i); - } - - argv[0].v_type = VAR_DICT; - argv[0].vval.v_dict = dict; - argv[1].v_type = VAR_STRING; - argv[1].vval.v_string = (char_u *)xstrdup(key); - argv[2].v_type = VAR_DICT; - argv[2].vval.v_dict = dict_alloc(); - argv[2].vval.v_dict->dv_refcount++; - - if (newtv) { - dictitem_T *v = dictitem_alloc((char_u *)"new"); - copy_tv(newtv, &v->di_tv); - dict_add(argv[2].vval.v_dict, v); - } - - if (oldtv) { - dictitem_T *v = dictitem_alloc((char_u *)"old"); - copy_tv(oldtv, &v->di_tv); - dict_add(argv[2].vval.v_dict, v); - } - - typval_T rettv; - - QUEUE *w; - QUEUE_FOREACH(w, &dict->watchers) { - DictWatcher *watcher = dictwatcher_node_data(w); - if (!watcher->busy && dictwatcher_matches(watcher, key)) { - init_tv(&rettv); - watcher->busy = true; - callback_call(&watcher->callback, 3, argv, &rettv); - watcher->busy = false; - clear_tv(&rettv); - } - } - - for (size_t i = 1; i < ARRAY_SIZE(argv); i++) { - clear_tv(argv + i); - } -} - -// Test if `key` matches with with `watcher->key_pattern` -static bool dictwatcher_matches(DictWatcher *watcher, const char *key) - FUNC_ATTR_NONNULL_ALL -{ - // For now only allow very simple globbing in key patterns: a '*' at the end - // of the string means it should match everything up to the '*' instead of the - // whole string. - char *nul = strchr(watcher->key_pattern, NUL); - size_t len = nul - watcher->key_pattern; - if (*(nul - 1) == '*') { - return !strncmp(key, watcher->key_pattern, len - 1); - } else { - return !strcmp(key, watcher->key_pattern); - } -} - -// Perform all necessary cleanup for a `DictWatcher` instance. -static void dictwatcher_free(DictWatcher *watcher) - FUNC_ATTR_NONNULL_ALL -{ - callback_free(&watcher->callback); - xfree(watcher->key_pattern); - xfree(watcher); -} - -// Check if `d` has at least one watcher. -static bool is_watched(dict_T *d) +/// Writes "<sourcing_name>:<sourcing_lnum>" to `buf[bufsize]`. +void eval_format_source_name_line(char *buf, size_t bufsize) { - return d && !QUEUE_EMPTY(&d->watchers); + snprintf(buf, bufsize, "%s:%" PRIdLINENR, + (sourcing_name ? sourcing_name : (char_u *)"?"), + (sourcing_name ? sourcing_lnum : 0)); } diff --git a/src/nvim/eval.h b/src/nvim/eval.h index 630e309442..070bc35bd5 100644 --- a/src/nvim/eval.h +++ b/src/nvim/eval.h @@ -1,11 +1,12 @@ #ifndef NVIM_EVAL_H #define NVIM_EVAL_H -#include "nvim/profile.h" #include "nvim/hashtab.h" // For hashtab_T -#include "nvim/garray.h" // For garray_T -#include "nvim/buffer_defs.h" // For scid_T +#include "nvim/buffer_defs.h" #include "nvim/ex_cmds_defs.h" // For exarg_T +#include "nvim/eval/typval.h" +#include "nvim/profile.h" +#include "nvim/garray.h" #define COPYID_INC 2 #define COPYID_MASK (~0x1) @@ -13,42 +14,10 @@ // All user-defined functions are found in this hashtable. extern hashtab_T func_hashtab; -// Structure to hold info for a user function. -typedef struct ufunc ufunc_T; - -struct ufunc { - int uf_varargs; ///< variable nr of arguments - int uf_flags; - int uf_calls; ///< nr of active calls - garray_T uf_args; ///< arguments - garray_T uf_lines; ///< function lines - int uf_profiling; ///< true when func is being profiled - // Profiling the function as a whole. - int uf_tm_count; ///< nr of calls - proftime_T uf_tm_total; ///< time spent in function + children - proftime_T uf_tm_self; ///< time spent in function itself - proftime_T uf_tm_children; ///< time spent in children this call - // Profiling the function per line. - int *uf_tml_count; ///< nr of times line was executed - proftime_T *uf_tml_total; ///< time spent in a line + children - proftime_T *uf_tml_self; ///< time spent in a line itself - proftime_T uf_tml_start; ///< start time for current line - proftime_T uf_tml_children; ///< time spent in children for this line - proftime_T uf_tml_wait; ///< start wait time for current line - int uf_tml_idx; ///< index of line being timed; -1 if none - int uf_tml_execed; ///< line being timed was executed - scid_T uf_script_ID; ///< ID of script where function was defined, - // used for s: variables - int uf_refcount; ///< for numbered function: reference count - char_u uf_name[1]; ///< name of function (actually longer); can - // start with <SNR>123_ (<SNR> is K_SPECIAL - // KS_EXTRA KE_SNR) -}; - // From user function to hashitem and back. EXTERN ufunc_T dumuf; #define UF2HIKEY(fp) ((fp)->uf_name) -#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf))) +#define HIKEY2UF(p) ((ufunc_T *)(p - offsetof(ufunc_T, uf_name))) #define HI2UF(hi) HIKEY2UF((hi)->hi_key) /// Defines for Vim variables @@ -127,6 +96,7 @@ typedef enum { VV__NULL_LIST, // List with NULL value. For test purposes only. VV__NULL_DICT, // Dictionary with NULL value. For test purposes only. VV_VIM_DID_ENTER, + VV_TESTING, VV_TYPE_NUMBER, VV_TYPE_STRING, VV_TYPE_FUNC, @@ -156,8 +126,8 @@ extern const list_T *eval_msgpack_type_lists[LAST_MSGPACK_TYPE + 1]; #undef LAST_MSGPACK_TYPE -/// Maximum number of function arguments -#define MAX_FUNC_ARGS 20 +typedef int (*ArgvFunc)(int current_argcount, typval_T *argv, + int called_func_argcount); #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval.h.generated.h" diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index e0b72feb19..0e359fb61c 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -2,10 +2,10 @@ -- -- Keys: -- --- args Number of arguments, list with maximum and minimum number of arguments --- or list with a minimum number of arguments only. Defaults to zero +-- args Number of arguments, list with maximum and minimum number of arguments +-- or list with a minimum number of arguments only. Defaults to zero -- arguments. --- func Name of the C function which implements the VimL function. Defaults to +-- func Name of the C function which implements the VimL function. Defaults to -- `f_{funcname}`. local varargs = function(nr) @@ -29,9 +29,11 @@ return { assert_exception={args={1, 2}}, assert_fails={args={1, 2}}, assert_false={args={1, 2}}, + assert_inrange={args={3, 4}}, assert_match={args={2, 3}}, assert_notequal={args={2, 3}}, assert_notmatch={args={2, 3}}, + assert_report={args=1}, assert_true={args={1, 2}}, atan={args=1, func="float_op_wrapper", data="&atan"}, atan2={args=2}, @@ -103,6 +105,7 @@ return { foldtext={}, foldtextresult={args=1}, foreground={}, + funcref={args={1, 3}}, ['function']={args={1, 3}}, garbagecollect={args={0, 1}}, get={args={2, 3}}, @@ -125,11 +128,11 @@ return { getftime={args=1}, getftype={args=1}, getline={args={1, 2}}, - getloclist={args=1, func='f_getqflist'}, + getloclist={args={1, 2}}, getmatches={}, getpid={}, getpos={args=1}, - getqflist={}, + getqflist={args={0, 1}}, getreg={args={0, 3}}, getregtype={args={0, 1}}, gettabinfo={args={0, 1}}, @@ -168,6 +171,7 @@ return { invert={args=1}, isdirectory={args=1}, islocked={args=1}, + id={args=1}, items={args=1}, jobclose={args={1, 2}}, jobpid={args=1}, @@ -190,6 +194,7 @@ return { localtime={}, log={args=1, func="float_op_wrapper", data="&log"}, log10={args=1, func="float_op_wrapper", data="&log10"}, + luaeval={args={1, 2}}, map={args=2}, maparg={args={1, 4}}, mapcheck={args={1, 3}}, @@ -203,6 +208,7 @@ return { matchstr={args={2, 4}}, matchstrpos={args={2,4}}, max={args=1}, + menu_get={args={1, 2}}, min={args=1}, mkdir={args={1, 3}}, mode={args={0, 1}}, @@ -264,6 +270,7 @@ return { simplify={args=1}, sin={args=1, func="float_op_wrapper", data="&sin"}, sinh={args=1, func="float_op_wrapper", data="&sinh"}, + sockconnect={args={2,3}}, sort={args={1, 3}}, soundfold={args=1}, spellbadword={args={0, 1}}, @@ -297,13 +304,17 @@ return { tabpagenr={args={0, 1}}, tabpagewinnr={args={1, 2}}, tagfiles={}, - taglist={args=1}, + taglist={args={1, 2}}, tan={args=1, func="float_op_wrapper", data="&tan"}, tanh={args=1, func="float_op_wrapper", data="&tanh"}, tempname={}, termopen={args={1, 2}}, + test_garbagecollect_now={}, + timer_info={args={0,1}}, + timer_pause={args=2}, timer_start={args={2,3}}, timer_stop={args=1}, + timer_stopall={args=0}, tolower={args=1}, toupper={args=1}, tr={args=3}, diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index 43e9f76c0f..9c9c2c2dc8 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -1,12 +1,17 @@ +// 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 <stddef.h> #include <msgpack.h> -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" #include "nvim/eval.h" #include "nvim/eval/encode.h" #include "nvim/ascii.h" +#include "nvim/macros.h" #include "nvim/message.h" +#include "nvim/globals.h" #include "nvim/charset.h" // vim_str2nr #include "nvim/lib/kvec.h" #include "nvim/vim.h" // OK, FAIL @@ -51,16 +56,16 @@ static inline void create_special_dict(typval_T *const rettv, typval_T val) FUNC_ATTR_NONNULL_ALL { - dict_T *const dict = dict_alloc(); - dictitem_T *const type_di = dictitem_alloc((char_u *) "_TYPE"); + dict_T *const dict = tv_dict_alloc(); + dictitem_T *const type_di = tv_dict_item_alloc_len(S_LEN("_TYPE")); type_di->di_tv.v_type = VAR_LIST; type_di->di_tv.v_lock = VAR_UNLOCKED; type_di->di_tv.vval.v_list = (list_T *) eval_msgpack_type_lists[type]; type_di->di_tv.vval.v_list->lv_refcount++; - dict_add(dict, type_di); - dictitem_T *const val_di = dictitem_alloc((char_u *) "_VAL"); + tv_dict_add(dict, type_di); + dictitem_T *const val_di = tv_dict_item_alloc_len(S_LEN("_VAL")); val_di->di_tv = val; - dict_add(dict, val_di); + tv_dict_add(dict, val_di); dict->dv_refcount++; *rettv = (typval_T) { .v_type = VAR_DICT, @@ -118,18 +123,18 @@ static inline int json_decoder_pop(ValuesStackItem obj, if (last_container.container.vval.v_list->lv_len != 0 && !obj.didcomma) { EMSG2(_("E474: Expected comma before list item: %s"), val_location); - clear_tv(&obj.val); + tv_clear(&obj.val); return FAIL; } assert(last_container.special_val == NULL); - listitem_T *obj_li = listitem_alloc(); + listitem_T *obj_li = tv_list_item_alloc(); obj_li->li_tv = obj.val; - list_append(last_container.container.vval.v_list, obj_li); + tv_list_append(last_container.container.vval.v_list, obj_li); } else if (last_container.stack_index == kv_size(*stack) - 2) { if (!obj.didcolon) { EMSG2(_("E474: Expected colon before dictionary value: %s"), val_location); - clear_tv(&obj.val); + tv_clear(&obj.val); return FAIL; } ValuesStackItem key = kv_pop(*stack); @@ -138,34 +143,35 @@ static inline int json_decoder_pop(ValuesStackItem obj, assert(!(key.is_special_string || key.val.vval.v_string == NULL || *key.val.vval.v_string == NUL)); - dictitem_T *obj_di = dictitem_alloc(key.val.vval.v_string); - clear_tv(&key.val); - if (dict_add(last_container.container.vval.v_dict, obj_di) + dictitem_T *const obj_di = tv_dict_item_alloc( + (const char *)key.val.vval.v_string); + tv_clear(&key.val); + if (tv_dict_add(last_container.container.vval.v_dict, obj_di) == FAIL) { assert(false); } obj_di->di_tv = obj.val; } else { - list_T *const kv_pair = list_alloc(); - list_append_list(last_container.special_val, kv_pair); - listitem_T *const key_li = listitem_alloc(); + list_T *const kv_pair = tv_list_alloc(); + tv_list_append_list(last_container.special_val, kv_pair); + listitem_T *const key_li = tv_list_item_alloc(); key_li->li_tv = key.val; - list_append(kv_pair, key_li); - listitem_T *const val_li = listitem_alloc(); + tv_list_append(kv_pair, key_li); + listitem_T *const val_li = tv_list_item_alloc(); val_li->li_tv = obj.val; - list_append(kv_pair, val_li); + tv_list_append(kv_pair, val_li); } } else { // Object with key only if (!obj.is_special_string && obj.val.v_type != VAR_STRING) { EMSG2(_("E474: Expected string key: %s"), *pp); - clear_tv(&obj.val); + tv_clear(&obj.val); return FAIL; } else if (!obj.didcomma && (last_container.special_val == NULL && (DICT_LEN(last_container.container.vval.v_dict) != 0))) { EMSG2(_("E474: Expected comma before dictionary key: %s"), val_location); - clear_tv(&obj.val); + tv_clear(&obj.val); return FAIL; } // Handle empty key and key represented as special dictionary @@ -173,16 +179,16 @@ static inline int json_decoder_pop(ValuesStackItem obj, && (obj.is_special_string || obj.val.vval.v_string == NULL || *obj.val.vval.v_string == NUL - || dict_find(last_container.container.vval.v_dict, - obj.val.vval.v_string, -1))) { - clear_tv(&obj.val); + || tv_dict_find(last_container.container.vval.v_dict, + (const char *)obj.val.vval.v_string, -1))) { + tv_clear(&obj.val); // Restart (void) kv_pop(*container_stack); ValuesStackItem last_container_val = kv_A(*stack, last_container.stack_index); while (kv_size(*stack) > last_container.stack_index) { - clear_tv(&(kv_pop(*stack).val)); + tv_clear(&(kv_pop(*stack).val)); } *pp = last_container.s; *didcomma = last_container_val.didcomma; @@ -218,10 +224,80 @@ static inline int json_decoder_pop(ValuesStackItem obj, } \ } while (0) +/// Create a new special dictionary that ought to represent a MAP +/// +/// @param[out] ret_tv Address where new special dictionary is saved. +/// +/// @return [allocated] list which should contain key-value pairs. Return value +/// may be safely ignored. +list_T *decode_create_map_special_dict(typval_T *const ret_tv) + FUNC_ATTR_NONNULL_ALL +{ + list_T *const list = tv_list_alloc(); + list->lv_refcount++; + create_special_dict(ret_tv, kMPMap, ((typval_T) { + .v_type = VAR_LIST, + .v_lock = VAR_UNLOCKED, + .vval = { .v_list = list }, + })); + return list; +} + +/// Convert char* string to typval_T +/// +/// Depending on whether string has (no) NUL bytes, it may use a special +/// dictionary or decode string to VAR_STRING. +/// +/// @param[in] s String to decode. +/// @param[in] len String length. +/// @param[in] hasnul Whether string has NUL byte, not or it was not yet +/// determined. +/// @param[in] binary If true, save special string type as kMPBinary, +/// otherwise kMPString. +/// @param[in] s_allocated If true, then `s` was allocated and can be saved in +/// a returned structure. If it is not saved there, it +/// will be freed. +/// +/// @return Decoded string. +typval_T decode_string(const char *const s, const size_t len, + const TriState hasnul, const bool binary, + const bool s_allocated) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + assert(s != NULL || len == 0); + const bool really_hasnul = (hasnul == kNone + ? memchr(s, NUL, len) != NULL + : (bool)hasnul); + if (really_hasnul) { + list_T *const list = tv_list_alloc(); + list->lv_refcount++; + typval_T tv; + create_special_dict(&tv, binary ? kMPBinary : kMPString, ((typval_T) { + .v_type = VAR_LIST, + .v_lock = VAR_UNLOCKED, + .vval = { .v_list = list }, + })); + const int elw_ret = encode_list_write((void *)list, s, len); + if (s_allocated) { + xfree((void *)s); + } + if (elw_ret == -1) { + tv_clear(&tv); + return (typval_T) { .v_type = VAR_UNKNOWN, .v_lock = VAR_UNLOCKED }; + } + return tv; + } else { + return (typval_T) { + .v_type = VAR_STRING, + .v_lock = VAR_UNLOCKED, + .vval = { .v_string = (char_u *)( + s_allocated ? (char *)s : xmemdupz(s, len)) }, + }; + } +} + /// Parse JSON double-quoted string /// -/// @param[in] conv Defines conversion necessary to convert UTF-8 string to -/// &encoding. /// @param[in] buf Buffer being converted. /// @param[in] buf_len Length of the buffer. /// @param[in,out] pp Pointer to the start of the string. Must point to '"'. @@ -238,8 +314,7 @@ static inline int json_decoder_pop(ValuesStackItem obj, /// value when decoder is restarted, otherwise unused. /// /// @return OK in case of success, FAIL in case of error. -static inline int parse_json_string(vimconv_T *const conv, - const char *const buf, const size_t buf_len, +static inline int parse_json_string(const char *const buf, const size_t buf_len, const char **const pp, ValuesStack *const stack, ContainerStack *const container_stack, @@ -360,8 +435,8 @@ static inline int parse_json_string(vimconv_T *const conv, case 'u': { const char ubuf[] = { t[1], t[2], t[3], t[4] }; t += 4; - unsigned long ch; - vim_str2nr((char_u *) ubuf, NULL, NULL, + uvarnumber_T ch; + vim_str2nr((char_u *)ubuf, NULL, NULL, STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4); if (ch == 0) { hasnul = true; @@ -414,43 +489,13 @@ static inline int parse_json_string(vimconv_T *const conv, } PUT_FST_IN_PAIR(fst_in_pair, str_end); #undef PUT_FST_IN_PAIR - if (conv->vc_type != CONV_NONE) { - size_t str_len = (size_t) (str_end - str); - char *const new_str = (char *) string_convert(conv, (char_u *) str, - &str_len); - if (new_str == NULL) { - emsgf(_("E474: Failed to convert string \"%.*s\" from UTF-8"), - (int) str_len, str); - xfree(str); - goto parse_json_string_fail; - } - xfree(str); - str = new_str; - str_end = new_str + str_len; - } - if (hasnul) { - typval_T obj; - list_T *const list = list_alloc(); - list->lv_refcount++; - create_special_dict(&obj, kMPString, ((typval_T) { - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = list }, - })); - if (encode_list_write((void *) list, str, (size_t) (str_end - str)) - == -1) { - clear_tv(&obj); - goto parse_json_string_fail; - } - xfree(str); - POP(obj, true); - } else { - *str_end = NUL; - POP(((typval_T) { - .v_type = VAR_STRING, - .vval = { .v_string = (char_u *) str }, - }), false); + *str_end = NUL; + typval_T obj = decode_string( + str, (size_t)(str_end - str), hasnul ? kTrue : kFalse, false, true); + if (obj.v_type == VAR_UNKNOWN) { + goto parse_json_string_fail; } + POP(obj, obj.v_type != VAR_STRING); goto parse_json_string_ret; parse_json_string_fail: ret = FAIL; @@ -564,7 +609,7 @@ parse_json_number_check: tv.v_type = VAR_FLOAT; } else { // Convert integer - long nr; + varnumber_T nr; int num_len; vim_str2nr((char_u *) s, NULL, &num_len, 0, &nr, NULL, (int) (p - s)); if ((int) exp_num_len != num_len) { @@ -572,7 +617,7 @@ parse_json_number_check: "to integer vim_str2nr consumed %i bytes in place of %zu"), (int) exp_num_len, s, num_len, exp_num_len); } - tv.vval.v_number = (varnumber_T) nr; + tv.vval.v_number = nr; } if (json_decoder_pop(OBJ(tv, false, *didcomma, *didcolon), stack, container_stack, @@ -624,9 +669,6 @@ int json_decode_string(const char *const buf, const size_t buf_len, EMSG(_("E474: Attempt to decode a blank string")); return FAIL; } - vimconv_T conv = { .vc_type = CONV_NONE }; - convert_setup(&conv, (char_u *) "utf-8", p_enc); - conv.vc_fail = true; int ret = OK; ValuesStack stack = KV_INITIAL_VALUE; ContainerStack container_stack = KV_INITIAL_VALUE; @@ -772,7 +814,7 @@ json_decode_string_cycle_start: break; } case '"': { - if (parse_json_string(&conv, buf, buf_len, &p, &stack, &container_stack, + if (parse_json_string(buf, buf_len, &p, &stack, &container_stack, &next_map_special, &didcomma, &didcolon) == FAIL) { // Error message was already given @@ -806,7 +848,7 @@ json_decode_string_cycle_start: break; } case '[': { - list_T *list = list_alloc(); + list_T *list = tv_list_alloc(); list->lv_refcount++; typval_T tv = { .v_type = VAR_LIST, @@ -827,15 +869,9 @@ json_decode_string_cycle_start: list_T *val_list = NULL; if (next_map_special) { next_map_special = false; - val_list = list_alloc(); - val_list->lv_refcount++; - create_special_dict(&tv, kMPMap, ((typval_T) { - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = val_list }, - })); + val_list = decode_create_map_special_dict(&tv); } else { - dict_T *dict = dict_alloc(); + dict_T *dict = tv_dict_alloc(); dict->dv_refcount++; tv = (typval_T) { .v_type = VAR_DICT, @@ -887,7 +923,7 @@ json_decode_string_after_cycle: json_decode_string_fail: ret = FAIL; while (kv_size(stack)) { - clear_tv(&(kv_pop(stack).val)); + tv_clear(&(kv_pop(stack).val)); } json_decode_string_ret: kv_destroy(stack); @@ -933,7 +969,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) .vval = { .v_number = (varnumber_T) mobj.via.u64 }, }; } else { - list_T *const list = list_alloc(); + list_T *const list = tv_list_alloc(); list->lv_refcount++; create_special_dict(rettv, kMPInteger, ((typval_T) { .v_type = VAR_LIST, @@ -941,10 +977,10 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) .vval = { .v_list = list }, })); uint64_t n = mobj.via.u64; - list_append_number(list, 1); - list_append_number(list, (varnumber_T) ((n >> 62) & 0x3)); - list_append_number(list, (varnumber_T) ((n >> 31) & 0x7FFFFFFF)); - list_append_number(list, (varnumber_T) (n & 0x7FFFFFFF)); + tv_list_append_number(list, 1); + tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3)); + tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF)); + tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF)); } break; } @@ -956,22 +992,28 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) .vval = { .v_number = (varnumber_T) mobj.via.i64 }, }; } else { - list_T *const list = list_alloc(); + list_T *const list = tv_list_alloc(); list->lv_refcount++; create_special_dict(rettv, kMPInteger, ((typval_T) { .v_type = VAR_LIST, .v_lock = VAR_UNLOCKED, .vval = { .v_list = list }, })); - uint64_t n = -((uint64_t) mobj.via.i64); - list_append_number(list, -1); - list_append_number(list, (varnumber_T) ((n >> 62) & 0x3)); - list_append_number(list, (varnumber_T) ((n >> 31) & 0x7FFFFFFF)); - list_append_number(list, (varnumber_T) (n & 0x7FFFFFFF)); + uint64_t n = -((uint64_t)mobj.via.i64); + tv_list_append_number(list, -1); + tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3)); + tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF)); + tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF)); } break; } - case MSGPACK_OBJECT_FLOAT: { +#ifdef NVIM_MSGPACK_HAS_FLOAT32 + case MSGPACK_OBJECT_FLOAT32: + case MSGPACK_OBJECT_FLOAT64: +#else + case MSGPACK_OBJECT_FLOAT: +#endif + { *rettv = (typval_T) { .v_type = VAR_FLOAT, .v_lock = VAR_UNLOCKED, @@ -980,43 +1022,23 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) break; } case MSGPACK_OBJECT_STR: { - list_T *const list = list_alloc(); - list->lv_refcount++; - create_special_dict(rettv, kMPString, ((typval_T) { - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = list }, - })); - if (encode_list_write((void *) list, mobj.via.str.ptr, mobj.via.str.size) - == -1) { + *rettv = decode_string(mobj.via.bin.ptr, mobj.via.bin.size, kTrue, false, + false); + if (rettv->v_type == VAR_UNKNOWN) { return FAIL; } break; } case MSGPACK_OBJECT_BIN: { - if (memchr(mobj.via.bin.ptr, NUL, mobj.via.bin.size) == NULL) { - *rettv = (typval_T) { - .v_type = VAR_STRING, - .v_lock = VAR_UNLOCKED, - .vval = { .v_string = xmemdupz(mobj.via.bin.ptr, mobj.via.bin.size) }, - }; - break; - } - list_T *const list = list_alloc(); - list->lv_refcount++; - create_special_dict(rettv, kMPBinary, ((typval_T) { - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = list }, - })); - if (encode_list_write((void *) list, mobj.via.bin.ptr, mobj.via.bin.size) - == -1) { + *rettv = decode_string(mobj.via.bin.ptr, mobj.via.bin.size, kNone, true, + false); + if (rettv->v_type == VAR_UNKNOWN) { return FAIL; } break; } case MSGPACK_OBJECT_ARRAY: { - list_T *const list = list_alloc(); + list_T *const list = tv_list_alloc(); list->lv_refcount++; *rettv = (typval_T) { .v_type = VAR_LIST, @@ -1024,9 +1046,9 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) .vval = { .v_list = list }, }; for (size_t i = 0; i < mobj.via.array.size; i++) { - listitem_T *const li = listitem_alloc(); + listitem_T *const li = tv_list_item_alloc(); li->li_tv.v_type = VAR_UNKNOWN; - list_append(list, li); + tv_list_append(list, li); if (msgpack_to_vim(mobj.via.array.ptr[i], &li->li_tv) == FAIL) { return FAIL; } @@ -1042,7 +1064,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) goto msgpack_to_vim_generic_map; } } - dict_T *const dict = dict_alloc(); + dict_T *const dict = tv_dict_alloc(); dict->dv_refcount++; *rettv = (typval_T) { .v_type = VAR_DICT, @@ -1055,9 +1077,9 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) memcpy(&di->di_key[0], mobj.via.map.ptr[i].key.via.str.ptr, mobj.via.map.ptr[i].key.via.str.size); di->di_tv.v_type = VAR_UNKNOWN; - if (dict_add(dict, di) == FAIL) { + if (tv_dict_add(dict, di) == FAIL) { // Duplicate key: fallback to generic map - clear_tv(rettv); + tv_clear(rettv); xfree(di); goto msgpack_to_vim_generic_map; } @@ -1067,22 +1089,16 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) } break; msgpack_to_vim_generic_map: {} - list_T *const list = list_alloc(); - list->lv_refcount++; - create_special_dict(rettv, kMPMap, ((typval_T) { - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = list }, - })); + list_T *const list = decode_create_map_special_dict(rettv); for (size_t i = 0; i < mobj.via.map.size; i++) { - list_T *const kv_pair = list_alloc(); - list_append_list(list, kv_pair); - listitem_T *const key_li = listitem_alloc(); + list_T *const kv_pair = tv_list_alloc(); + tv_list_append_list(list, kv_pair); + listitem_T *const key_li = tv_list_item_alloc(); key_li->li_tv.v_type = VAR_UNKNOWN; - list_append(kv_pair, key_li); - listitem_T *const val_li = listitem_alloc(); + tv_list_append(kv_pair, key_li); + listitem_T *const val_li = tv_list_item_alloc(); val_li->li_tv.v_type = VAR_UNKNOWN; - list_append(kv_pair, val_li); + tv_list_append(kv_pair, val_li); if (msgpack_to_vim(mobj.via.map.ptr[i].key, &key_li->li_tv) == FAIL) { return FAIL; } @@ -1093,11 +1109,11 @@ msgpack_to_vim_generic_map: {} break; } case MSGPACK_OBJECT_EXT: { - list_T *const list = list_alloc(); + list_T *const list = tv_list_alloc(); list->lv_refcount++; - list_append_number(list, mobj.via.ext.type); - list_T *const ext_val_list = list_alloc(); - list_append_list(list, ext_val_list); + tv_list_append_number(list, mobj.via.ext.type); + list_T *const ext_val_list = tv_list_alloc(); + tv_list_append_list(list, ext_val_list); create_special_dict(rettv, kMPExt, ((typval_T) { .v_type = VAR_LIST, .v_lock = VAR_UNLOCKED, diff --git a/src/nvim/eval/decode.h b/src/nvim/eval/decode.h index 5c25a64f7a..77fc4c78c2 100644 --- a/src/nvim/eval/decode.h +++ b/src/nvim/eval/decode.h @@ -5,7 +5,8 @@ #include <msgpack.h> -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" +#include "nvim/globals.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/decode.h.generated.h" diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index ee66b7cf09..ef647b3ee4 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -1,3 +1,6 @@ +// 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 + /// @file encode.c /// /// File containing functions for encoding and decoding VimL values. @@ -11,9 +14,9 @@ #include <math.h> #include "nvim/eval/encode.h" -#include "nvim/buffer_defs.h" // vimconv_T +#include "nvim/buffer_defs.h" #include "nvim/eval.h" -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" #include "nvim/garray.h" #include "nvim/mbyte.h" #include "nvim/message.h" @@ -29,10 +32,6 @@ #define utf_ptr2char(b) utf_ptr2char((char_u *)b) #define utf_ptr2len(b) ((size_t)utf_ptr2len((char_u *)b)) #define utf_char2len(b) ((size_t)utf_char2len(b)) -#define string_convert(a, b, c) \ - ((char *)string_convert((vimconv_T *)a, (char_u *)b, c)) -#define convert_setup(vcp, from, to) \ - (convert_setup(vcp, (char_u *)from, (char_u *)to)) const char *const encode_special_var_names[] = { [kSpecialVarNull] = "null", @@ -45,7 +44,8 @@ const char *const encode_special_var_names[] = { #endif /// Msgpack callback for writing to readfile()-style list -int encode_list_write(void *data, const char *buf, size_t len) +int encode_list_write(void *const data, const char *const buf, const size_t len) + FUNC_ATTR_NONNULL_ARG(1) { if (len == 0) { return 0; @@ -80,11 +80,11 @@ int encode_list_write(void *data, const char *buf, size_t len) str = xmemdupz(line_start, line_length); memchrsub(str, NUL, NL, line_length); } - list_append_allocated_string(list, str); + tv_list_append_allocated_string(list, str); line_end++; } if (line_end == end) { - list_append_allocated_string(list, NULL); + tv_list_append_allocated_string(list, NULL); } return 0; } @@ -182,9 +182,9 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack, } } } - EMSG3(msg, objname, (kv_size(*mpstack) == 0 - ? _("itself") - : (char *) msg_ga.ga_data)); + emsgf(msg, _(objname), (kv_size(*mpstack) == 0 + ? _("itself") + : (char *)msg_ga.ga_data)); ga_clear(&msg_ga); return FAIL; } @@ -253,9 +253,11 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, char *const buf_end = buf + nbuf; char *p = buf; while (p < buf_end) { + assert(state->li_length == 0 || state->li->li_tv.vval.v_string != NULL); for (size_t i = state->offset; i < state->li_length && p < buf_end; i++) { - const char ch = (char) state->li->li_tv.vval.v_string[state->offset++]; - *p++ = (char) ((char) ch == (char) NL ? (char) NUL : (char) ch); + assert(state->li->li_tv.vval.v_string != NULL); + const char ch = (char)state->li->li_tv.vval.v_string[state->offset++]; + *p++ = (char)((char)ch == (char)NL ? (char)NUL : (char)ch); } if (p < buf_end) { state->li = state->li->li_next; @@ -536,17 +538,6 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, } \ } while (0) -/// Last used p_enc value -/// -/// Generic pointer: it is not used as a string, only pointer comparisons are -/// performed. Must not be freed. -static const void *last_p_enc = NULL; - -/// Conversion setup for converting from last_p_enc to UTF-8 -static vimconv_T p_enc_conv = { - .vc_type = CONV_NONE, -}; - /// Escape sequences used in JSON static const char escapes[][3] = { [BS] = "\\b", @@ -578,33 +569,15 @@ static inline int convert_to_json_string(garray_T *const gap, } else { size_t utf_len = len; char *tofree = NULL; - if (last_p_enc != (const void *) p_enc) { - p_enc_conv.vc_type = CONV_NONE; - convert_setup(&p_enc_conv, p_enc, "utf-8"); - p_enc_conv.vc_fail = true; - last_p_enc = p_enc; - } - if (p_enc_conv.vc_type != CONV_NONE) { - tofree = string_convert(&p_enc_conv, buf, &utf_len); - if (tofree == NULL) { - emsgf(_("E474: Failed to convert string \"%.*s\" to UTF-8"), - utf_len, utf_buf); - return FAIL; - } - utf_buf = tofree; - } size_t str_len = 0; - // Encode character as \u0000 if - // 1. It is an ASCII control character (0x0 .. 0x1F, 0x7F). - // 2. &encoding is not UTF-8 and code point is above 0x7F. - // 3. &encoding is UTF-8 and code point is not printable according to - // utf_printable(). - // This is done to make it possible to :echo values when &encoding is not - // UTF-8. -#define ENCODE_RAW(p_enc_conv, ch) \ - (ch >= 0x20 && (p_enc_conv.vc_type == CONV_NONE \ - ? utf_printable(ch) \ - : ch < 0x7F)) + // Encode character as \uNNNN if + // 1. It is an ASCII control character (0x0 .. 0x1F; 0x7F not + // utf_printable and thus not checked specially). + // 2. Code point is not printable according to utf_printable(). + // This is done to make resulting values displayable on screen also not from + // Neovim. +#define ENCODE_RAW(ch) \ + (ch >= 0x20 && utf_printable(ch)) for (size_t i = 0; i < utf_len;) { const int ch = utf_ptr2char(utf_buf + i); const size_t shift = (ch == 0? 1: utf_ptr2len(utf_buf + i)); @@ -635,7 +608,7 @@ static inline int convert_to_json_string(garray_T *const gap, utf_len - (i - shift), utf_buf + i - shift); xfree(tofree); return FAIL; - } else if (ENCODE_RAW(p_enc_conv, ch)) { + } else if (ENCODE_RAW(ch)) { str_len += shift; } else { str_len += ((sizeof("\\u1234") - 1) @@ -665,7 +638,7 @@ static inline int convert_to_json_string(garray_T *const gap, break; } default: { - if (ENCODE_RAW(p_enc_conv, ch)) { + if (ENCODE_RAW(ch)) { ga_concat_len(gap, utf_buf + i, shift); } else if (ch < SURROGATE_FIRST_CHAR) { ga_concat_len(gap, ((const char[]) { @@ -743,11 +716,11 @@ bool encode_check_json_key(const typval_T *const tv) } const dictitem_T *type_di; const dictitem_T *val_di; - if ((type_di = dict_find((dict_T *) spdict, (char_u *) "_TYPE", -1)) == NULL + if ((type_di = tv_dict_find(spdict, S_LEN("_TYPE"))) == NULL || type_di->di_tv.v_type != VAR_LIST || (type_di->di_tv.vval.v_list != eval_msgpack_type_lists[kMPString] && type_di->di_tv.vval.v_list != eval_msgpack_type_lists[kMPBinary]) - || (val_di = dict_find((dict_T *) spdict, (char_u *) "_VAL", -1)) == NULL + || (val_di = tv_dict_find(spdict, S_LEN("_VAL"))) == NULL || val_di->di_tv.v_type != VAR_LIST) { return false; } @@ -822,7 +795,7 @@ char *encode_tv2string(typval_T *tv, size_t *len) garray_T ga; ga_init(&ga, (int)sizeof(char), 80); const int evs_ret = encode_vim_to_string(&ga, tv, - "encode_tv2string() argument"); + N_("encode_tv2string() argument")); (void)evs_ret; assert(evs_ret == OK); did_echo_string_emsg = false; @@ -850,7 +823,7 @@ char *encode_tv2echo(typval_T *tv, size_t *len) ga_concat(&ga, tv->vval.v_string); } } else { - const int eve_ret = encode_vim_to_echo(&ga, tv, ":echo argument"); + const int eve_ret = encode_vim_to_echo(&ga, tv, N_(":echo argument")); (void)eve_ret; assert(eve_ret == OK); } @@ -873,7 +846,8 @@ char *encode_tv2json(typval_T *tv, size_t *len) { garray_T ga; ga_init(&ga, (int)sizeof(char), 80); - const int evj_ret = encode_vim_to_json(&ga, tv, "encode_tv2json() argument"); + const int evj_ret = encode_vim_to_json(&ga, tv, + N_("encode_tv2json() argument")); if (!evj_ret) { ga_clear(&ga); } diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c new file mode 100644 index 0000000000..99298cbbcf --- /dev/null +++ b/src/nvim/eval/executor.c @@ -0,0 +1,118 @@ +// 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 "nvim/eval/typval.h" +#include "nvim/eval/executor.h" +#include "nvim/eval.h" +#include "nvim/message.h" +#include "nvim/vim.h" +#include "nvim/globals.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/executor.c.generated.h" +#endif + +static char *e_letwrong = N_("E734: Wrong variable type for %s="); + +char *e_listidx = N_("E684: list index out of range: %" PRId64); + +/// Hanle tv1 += tv2, -=, .= +/// +/// @param[in,out] tv1 First operand, modified typval. +/// @param[in] tv2 Second operand. +/// @param[in] op Used operator. +/// +/// @return OK or FAIL. +int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, + const char *const op) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NO_SANITIZE_UNDEFINED +{ + // Can't do anything with a Funcref, a Dict or special value on the right. + if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT) { + switch (tv1->v_type) { + case VAR_DICT: + case VAR_FUNC: + case VAR_PARTIAL: + case VAR_SPECIAL: { + break; + } + case VAR_LIST: { + if (*op != '+' || tv2->v_type != VAR_LIST) { + break; + } + // List += List + if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL) { + tv_list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL); + } + return OK; + } + case VAR_NUMBER: + case VAR_STRING: { + if (tv2->v_type == VAR_LIST) { + break; + } + if (*op == '+' || *op == '-') { + // nr += nr or nr -= nr + varnumber_T n = tv_get_number(tv1); + if (tv2->v_type == VAR_FLOAT) { + float_T f = (float_T)n; + + if (*op == '+') { + f += tv2->vval.v_float; + } else { + f -= tv2->vval.v_float; + } + tv_clear(tv1); + tv1->v_type = VAR_FLOAT; + tv1->vval.v_float = f; + } else { + if (*op == '+') { + n += tv_get_number(tv2); + } else { + n -= tv_get_number(tv2); + } + tv_clear(tv1); + tv1->v_type = VAR_NUMBER; + tv1->vval.v_number = n; + } + } else { + // str .= str + if (tv2->v_type == VAR_FLOAT) { + break; + } + const char *tvs = tv_get_string(tv1); + char numbuf[NUMBUFLEN]; + char *const s = (char *)concat_str( + (const char_u *)tvs, (const char_u *)tv_get_string_buf(tv2, + numbuf)); + tv_clear(tv1); + tv1->v_type = VAR_STRING; + tv1->vval.v_string = (char_u *)s; + } + return OK; + } + case VAR_FLOAT: { + if (*op == '.' || (tv2->v_type != VAR_FLOAT + && tv2->v_type != VAR_NUMBER + && tv2->v_type != VAR_STRING)) { + break; + } + const float_T f = (tv2->v_type == VAR_FLOAT + ? tv2->vval.v_float + : (float_T)tv_get_number(tv2)); + if (*op == '+') { + tv1->vval.v_float += f; + } else { + tv1->vval.v_float -= f; + } + return OK; + } + case VAR_UNKNOWN: { + assert(false); + } + } + } + + EMSG2(_(e_letwrong), op); + return FAIL; +} diff --git a/src/nvim/eval/executor.h b/src/nvim/eval/executor.h new file mode 100644 index 0000000000..3d789f76a5 --- /dev/null +++ b/src/nvim/eval/executor.h @@ -0,0 +1,11 @@ +#ifndef NVIM_EVAL_EXECUTOR_H +#define NVIM_EVAL_EXECUTOR_H + +#include "nvim/eval/typval.h" + +extern char *e_listidx; + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/executor.h.generated.h" +#endif +#endif // NVIM_EVAL_EXECUTOR_H diff --git a/src/nvim/eval/gc.c b/src/nvim/eval/gc.c new file mode 100644 index 0000000000..2bbf78d827 --- /dev/null +++ b/src/nvim/eval/gc.c @@ -0,0 +1,14 @@ +// 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 "nvim/eval/typval.h" +#include "nvim/eval/gc.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/gc.c.generated.h" +#endif + +/// Head of list of all dictionaries +dict_T *gc_first_dict = NULL; +/// Head of list of all lists +list_T *gc_first_list = NULL; diff --git a/src/nvim/eval/gc.h b/src/nvim/eval/gc.h new file mode 100644 index 0000000000..c2e862e469 --- /dev/null +++ b/src/nvim/eval/gc.h @@ -0,0 +1,12 @@ +#ifndef NVIM_EVAL_GC_H +#define NVIM_EVAL_GC_H + +#include "nvim/eval/typval.h" + +extern dict_T *gc_first_dict; +extern list_T *gc_first_list; + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/gc.h.generated.h" +#endif +#endif // NVIM_EVAL_GC_H diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c new file mode 100644 index 0000000000..c339a5cdd2 --- /dev/null +++ b/src/nvim/eval/typval.c @@ -0,0 +1,2627 @@ +// 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 <stdio.h> +#include <stddef.h> +#include <string.h> +#include <assert.h> +#include <stdbool.h> + +#include "nvim/lib/queue.h" +#include "nvim/eval/typval.h" +#include "nvim/eval/gc.h" +#include "nvim/eval/executor.h" +#include "nvim/eval/encode.h" +#include "nvim/eval/typval_encode.h" +#include "nvim/eval.h" +#include "nvim/types.h" +#include "nvim/assert.h" +#include "nvim/memory.h" +#include "nvim/globals.h" +#include "nvim/hashtab.h" +#include "nvim/vim.h" +#include "nvim/ascii.h" +#include "nvim/pos.h" +#include "nvim/charset.h" +#include "nvim/garray.h" +#include "nvim/gettext.h" +#include "nvim/macros.h" +#include "nvim/mbyte.h" +#include "nvim/message.h" +// TODO(ZyX-I): Move line_breakcheck out of misc1 +#include "nvim/misc1.h" // For line_breakcheck + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/typval.c.generated.h" +#endif + +bool tv_in_free_unref_items = false; + +// TODO(ZyX-I): Remove DICT_MAXNEST, make users be non-recursive instead + +#define DICT_MAXNEST 100 + +const char *const tv_empty_string = ""; + +//{{{1 Lists +//{{{2 List item + +/// Allocate a list item +/// +/// @warning Allocated item is not initialized, do not forget to initialize it +/// and specifically set lv_lock. +/// +/// @return [allocated] new list item. +listitem_T *tv_list_item_alloc(void) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC +{ + return xmalloc(sizeof(listitem_T)); +} + +/// Free a list item +/// +/// Also clears the value. Does not touch watchers. +/// +/// @param[out] item Item to free. +void tv_list_item_free(listitem_T *const item) + FUNC_ATTR_NONNULL_ALL +{ + tv_clear(&item->li_tv); + xfree(item); +} + +/// Remove a list item from a List and free it +/// +/// Also clears the value. +/// +/// @param[out] l List to remove item from. +/// @param[in,out] item Item to remove. +void tv_list_item_remove(list_T *const l, listitem_T *const item) + FUNC_ATTR_NONNULL_ALL +{ + tv_list_remove_items(l, item, item); + tv_list_item_free(item); +} + +//{{{2 List watchers + +/// Add a watcher to a list +/// +/// @param[out] l List to add watcher to. +/// @param[in] lw Watcher to add. +void tv_list_watch_add(list_T *const l, listwatch_T *const lw) + FUNC_ATTR_NONNULL_ALL +{ + lw->lw_next = l->lv_watch; + l->lv_watch = lw; +} + +/// Remove a watcher from a list +/// +/// Does not give a warning if watcher was not found. +/// +/// @param[out] l List to remove watcher from. +/// @param[in] lwrem Watcher to remove. +void tv_list_watch_remove(list_T *const l, listwatch_T *const lwrem) + FUNC_ATTR_NONNULL_ALL +{ + listwatch_T **lwp = &l->lv_watch; + for (listwatch_T *lw = l->lv_watch; lw != NULL; lw = lw->lw_next) { + if (lw == lwrem) { + *lwp = lw->lw_next; + break; + } + lwp = &lw->lw_next; + } +} + +/// Advance watchers to the next item +/// +/// Used just before removing an item from a list. +/// +/// @param[out] l List from which item is removed. +/// @param[in] item List item being removed. +void tv_list_watch_fix(list_T *const l, const listitem_T *const item) + FUNC_ATTR_NONNULL_ALL +{ + for (listwatch_T *lw = l->lv_watch; lw != NULL; lw = lw->lw_next) { + if (lw->lw_item == item) { + lw->lw_item = item->li_next; + } + } +} + +//{{{2 Alloc/free + +/// Allocate an empty list +/// +/// Caller should take care of the reference count. +/// +/// @return [allocated] new list. +list_T *tv_list_alloc(void) + FUNC_ATTR_NONNULL_RET +{ + list_T *const list = xcalloc(1, sizeof(list_T)); + + // Prepend the list to the list of lists for garbage collection. + if (gc_first_list != NULL) { + gc_first_list->lv_used_prev = list; + } + list->lv_used_prev = NULL; + list->lv_used_next = gc_first_list; + gc_first_list = list; + return list; +} + +/// Free items contained in a list +/// +/// @param[in,out] l List to clear. +void tv_list_free_contents(list_T *const l) + FUNC_ATTR_NONNULL_ALL +{ + for (listitem_T *item = l->lv_first; item != NULL; item = l->lv_first) { + // Remove the item before deleting it. + l->lv_first = item->li_next; + tv_clear(&item->li_tv); + xfree(item); + } + l->lv_len = 0; + l->lv_idx_item = NULL; + l->lv_last = NULL; + assert(l->lv_watch == NULL); +} + +/// Free a list itself, ignoring items it contains +/// +/// Ignores the reference count. +/// +/// @param[in,out] l List to free. +void tv_list_free_list(list_T *const l) + FUNC_ATTR_NONNULL_ALL +{ + // Remove the list from the list of lists for garbage collection. + if (l->lv_used_prev == NULL) { + gc_first_list = l->lv_used_next; + } else { + l->lv_used_prev->lv_used_next = l->lv_used_next; + } + if (l->lv_used_next != NULL) { + l->lv_used_next->lv_used_prev = l->lv_used_prev; + } + + xfree(l); +} + +/// Free a list, including all items it points to +/// +/// Ignores the reference count. Does not do anything if +/// tv_in_free_unref_items is true. +/// +/// @param[in,out] l List to free. +void tv_list_free(list_T *const l) + FUNC_ATTR_NONNULL_ALL +{ + if (!tv_in_free_unref_items) { + tv_list_free_contents(l); + tv_list_free_list(l); + } +} + +/// Unreference a list +/// +/// Decrements the reference count and frees when it becomes zero or less. +/// +/// @param[in,out] l List to unreference. +void tv_list_unref(list_T *const l) +{ + if (l != NULL && --l->lv_refcount <= 0) { + tv_list_free(l); + } +} + +//{{{2 Add/remove + +/// Remove items "item" to "item2" from list "l". +/// +/// @warning Does not free the listitem or the value! +/// +/// @param[out] l List to remove from. +/// @param[in] item First item to remove. +/// @param[in] item2 Last item to remove. +void tv_list_remove_items(list_T *const l, listitem_T *const item, + listitem_T *const item2) + FUNC_ATTR_NONNULL_ALL +{ + // Notify watchers. + for (listitem_T *ip = item; ip != item2->li_next; ip = ip->li_next) { + l->lv_len--; + tv_list_watch_fix(l, ip); + } + + if (item2->li_next == NULL) { + l->lv_last = item->li_prev; + } else { + item2->li_next->li_prev = item->li_prev; + } + if (item->li_prev == NULL) { + l->lv_first = item2->li_next; + } else { + item->li_prev->li_next = item2->li_next; + } + l->lv_idx_item = NULL; +} + +/// Insert list item +/// +/// @param[out] l List to insert to. +/// @param[in,out] ni Item to insert. +/// @param[in] item Item to insert before. If NULL, inserts at the end of the +/// list. +void tv_list_insert(list_T *const l, listitem_T *const ni, + listitem_T *const item) + FUNC_ATTR_NONNULL_ARG(1, 2) +{ + if (item == NULL) { + // Append new item at end of list. + tv_list_append(l, ni); + } else { + // Insert new item before existing item. + ni->li_prev = item->li_prev; + ni->li_next = item; + if (item->li_prev == NULL) { + l->lv_first = ni; + l->lv_idx++; + } else { + item->li_prev->li_next = ni; + l->lv_idx_item = NULL; + } + item->li_prev = ni; + l->lv_len++; + } +} + +/// Insert VimL value into a list +/// +/// @param[out] l List to insert to. +/// @param[in,out] tv Value to insert. Is copied (@see tv_copy()) to an +/// allocated listitem_T and inserted. +/// @param[in] item Item to insert before. If NULL, inserts at the end of the +/// list. +void tv_list_insert_tv(list_T *const l, typval_T *const tv, + listitem_T *const item) +{ + listitem_T *const ni = tv_list_item_alloc(); + + tv_copy(tv, &ni->li_tv); + tv_list_insert(l, ni, item); +} + +/// Append item to the end of list +/// +/// @param[out] l List to append to. +/// @param[in,out] item Item to append. +void tv_list_append(list_T *const l, listitem_T *const item) + FUNC_ATTR_NONNULL_ALL +{ + if (l->lv_last == NULL) { + // empty list + l->lv_first = item; + l->lv_last = item; + item->li_prev = NULL; + } else { + l->lv_last->li_next = item; + item->li_prev = l->lv_last; + l->lv_last = item; + } + l->lv_len++; + item->li_next = NULL; +} + +/// Append VimL value to the end of list +/// +/// @param[out] l List to append to. +/// @param[in,out] tv Value to append. Is copied (@see tv_copy()) to an +/// allocated listitem_T. +void tv_list_append_tv(list_T *const l, typval_T *const tv) + FUNC_ATTR_NONNULL_ALL +{ + listitem_T *const li = tv_list_item_alloc(); + tv_copy(tv, &li->li_tv); + tv_list_append(l, li); +} + +/// Append a list to a list as one item +/// +/// @param[out] l List to append to. +/// @param[in,out] itemlist List to append. Reference count is increased. +void tv_list_append_list(list_T *const list, list_T *const itemlist) + FUNC_ATTR_NONNULL_ARG(1) +{ + listitem_T *const li = tv_list_item_alloc(); + + li->li_tv.v_type = VAR_LIST; + li->li_tv.v_lock = VAR_UNLOCKED; + li->li_tv.vval.v_list = itemlist; + tv_list_append(list, li); + if (itemlist != NULL) { + itemlist->lv_refcount++; + } +} + +/// Append a dictionary to a list +/// +/// @param[out] l List to append to. +/// @param[in,out] dict Dictionary to append. Reference count is increased. +void tv_list_append_dict(list_T *const list, dict_T *const dict) + FUNC_ATTR_NONNULL_ARG(1) +{ + listitem_T *const li = tv_list_item_alloc(); + + li->li_tv.v_type = VAR_DICT; + li->li_tv.v_lock = VAR_UNLOCKED; + li->li_tv.vval.v_dict = dict; + tv_list_append(list, li); + if (dict != NULL) { + dict->dv_refcount++; + } +} + +/// Make a copy of "str" and append it as an item to list "l" +/// +/// @param[out] l List to append to. +/// @param[in] str String to append. +/// @param[in] len Length of the appended string. May be -1, in this +/// case string is considered to be usual zero-terminated +/// string or NULL “empty†string. +void tv_list_append_string(list_T *const l, const char *const str, + const ptrdiff_t len) + FUNC_ATTR_NONNULL_ARG(1) +{ + if (str == NULL) { + assert(len == 0 || len == -1); + tv_list_append_allocated_string(l, NULL); + } else { + tv_list_append_allocated_string(l, (len >= 0 + ? xmemdupz(str, (size_t)len) + : xstrdup(str))); + } +} + +/// Append given string to the list +/// +/// Unlike list_append_string this function does not copy the string. +/// +/// @param[out] l List to append to. +/// @param[in] str String to append. +void tv_list_append_allocated_string(list_T *const l, char *const str) + FUNC_ATTR_NONNULL_ARG(1) +{ + listitem_T *const li = tv_list_item_alloc(); + + tv_list_append(l, li); + li->li_tv.v_type = VAR_STRING; + li->li_tv.v_lock = VAR_UNLOCKED; + li->li_tv.vval.v_string = (char_u *)str; +} + +/// Append number to the list +/// +/// @param[out] l List to append to. +/// @param[in] n Number to append. Will be recorded in the allocated +/// listitem_T. +void tv_list_append_number(list_T *const l, const varnumber_T n) +{ + listitem_T *const li = tv_list_item_alloc(); + li->li_tv.v_type = VAR_NUMBER; + li->li_tv.v_lock = VAR_UNLOCKED; + li->li_tv.vval.v_number = n; + tv_list_append(l, li); +} + +//{{{2 Operations on the whole list + +/// Make a copy of list +/// +/// @param[in] conv If non-NULL, then all internal strings will be converted. +/// Only used when `deep` is true. +/// @param[in] orig Original list to copy. +/// @param[in] deep If false, then shallow copy will be done. +/// @param[in] copyID See var_item_copy(). +/// +/// @return Copied list. May be NULL in case original list is NULL or some +/// failure happens. The refcount of the new list is set to 1. +list_T *tv_list_copy(const vimconv_T *const conv, list_T *const orig, + const bool deep, const int copyID) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (orig == NULL) { + return NULL; + } + + list_T *copy = tv_list_alloc(); + if (copyID != 0) { + // Do this before adding the items, because one of the items may + // refer back to this list. + orig->lv_copyID = copyID; + orig->lv_copylist = copy; + } + listitem_T *item; + for (item = orig->lv_first; item != NULL && !got_int; + item = item->li_next) { + listitem_T *const ni = tv_list_item_alloc(); + if (deep) { + if (var_item_copy(conv, &item->li_tv, &ni->li_tv, deep, copyID) == FAIL) { + xfree(ni); + break; + } + } else { + tv_copy(&item->li_tv, &ni->li_tv); + } + tv_list_append(copy, ni); + } + copy->lv_refcount++; + if (item != NULL) { + tv_list_unref(copy); + copy = NULL; + } + + return copy; +} + +/// Extend first list with the second +/// +/// @param[out] l1 List to extend. +/// @param[in] l2 List to extend with. +/// @param[in] bef If not NULL, extends before this item. +void tv_list_extend(list_T *const l1, list_T *const l2, + listitem_T *const bef) + FUNC_ATTR_NONNULL_ARG(1, 2) +{ + int todo = l2->lv_len; + listitem_T *const befbef = (bef == NULL ? NULL : bef->li_prev); + listitem_T *const saved_next = (befbef == NULL ? NULL : befbef->li_next); + // We also quit the loop when we have inserted the original item count of + // the list, avoid a hang when we extend a list with itself. + for (listitem_T *item = l2->lv_first + ; item != NULL && --todo >= 0 + ; item = (item == befbef ? saved_next : item->li_next)) { + tv_list_insert_tv(l1, &item->li_tv, bef); + } +} + +/// Concatenate lists into a new list +/// +/// @param[in] l1 First list. +/// @param[in] l2 Second list. +/// @param[out] ret_tv Location where new list is saved. +/// +/// @return OK or FAIL. +int tv_list_concat(list_T *const l1, list_T *const l2, typval_T *const tv) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + list_T *l; + + tv->v_type = VAR_LIST; + + if (l1 == NULL && l2 == NULL) { + l = NULL; + } else if (l1 == NULL) { + l = tv_list_copy(NULL, l2, false, 0); + } else { + l = tv_list_copy(NULL, l1, false, 0); + if (l != NULL && l2 != NULL) { + tv_list_extend(l, l2, NULL); + } + } + if (l == NULL && !(l1 == NULL && l2 == NULL)) { + return FAIL; + } + + tv->vval.v_list = l; + return OK; +} + +typedef struct { + char_u *s; + char_u *tofree; +} Join; + +/// Join list into a string, helper function +/// +/// @param[out] gap Garray where result will be saved. +/// @param[in] l List to join. +/// @param[in] sep Used separator. +/// @param[in] join_gap Garray to keep each list item string. +/// +/// @return OK in case of success, FAIL otherwise. +static int list_join_inner(garray_T *const gap, list_T *const l, + const char *const sep, garray_T *const join_gap) + FUNC_ATTR_NONNULL_ALL +{ + size_t sumlen = 0; + bool first = true; + listitem_T *item; + + // Stringify each item in the list. + for (item = l->lv_first; item != NULL && !got_int; item = item->li_next) { + char *s; + size_t len; + s = encode_tv2echo(&item->li_tv, &len); + if (s == NULL) { + return FAIL; + } + + sumlen += len; + + Join *const p = GA_APPEND_VIA_PTR(Join, join_gap); + p->tofree = p->s = (char_u *)s; + + line_breakcheck(); + } + + // Allocate result buffer with its total size, avoid re-allocation and + // multiple copy operations. Add 2 for a tailing ']' and NUL. + if (join_gap->ga_len >= 2) { + sumlen += strlen(sep) * (size_t)(join_gap->ga_len - 1); + } + ga_grow(gap, (int)sumlen + 2); + + for (int i = 0; i < join_gap->ga_len && !got_int; i++) { + if (first) { + first = false; + } else { + ga_concat(gap, (const char_u *)sep); + } + const Join *const p = ((const Join *)join_gap->ga_data) + i; + + if (p->s != NULL) { + ga_concat(gap, p->s); + } + line_breakcheck(); + } + + return OK; +} + +/// Join list into a string using given separator +/// +/// @param[out] gap Garray where result will be saved. +/// @param[in] l Joined list. +/// @param[in] sep Separator. +/// +/// @return OK in case of success, FAIL otherwise. +int tv_list_join(garray_T *const gap, list_T *const l, const char *const sep) + FUNC_ATTR_NONNULL_ALL +{ + if (l->lv_len < 1) { + return OK; + } + + garray_T join_ga; + int retval; + + ga_init(&join_ga, (int)sizeof(Join), l->lv_len); + retval = list_join_inner(gap, l, sep, &join_ga); + +#define FREE_JOIN_TOFREE(join) xfree((join)->tofree) + GA_DEEP_CLEAR(&join_ga, Join, FREE_JOIN_TOFREE); +#undef FREE_JOIN_TOFREE + + return retval; +} + +/// Chech whether two lists are equal +/// +/// @param[in] l1 First list to compare. +/// @param[in] l2 Second list to compare. +/// @param[in] ic True if case is to be ignored. +/// @param[in] recursive True when used recursively. +/// +/// @return True if lists are equal, false otherwise. +bool tv_list_equal(list_T *const l1, list_T *const l2, const bool ic, + const bool recursive) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (l1 == l2) { + return true; + } + if (l1 == NULL || l2 == NULL) { + return false; + } + if (tv_list_len(l1) != tv_list_len(l2)) { + return false; + } + + listitem_T *item1 = l1->lv_first; + listitem_T *item2 = l2->lv_first; + for (; item1 != NULL && item2 != NULL + ; item1 = item1->li_next, item2 = item2->li_next) { + if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive)) { + return false; + } + } + assert(item1 == NULL && item2 == NULL); + return true; +} + +//{{{2 Indexing/searching + +/// Locate item with a given index in a list and return it +/// +/// @param[in] l List to index. +/// @param[in] n Index. Negative index is counted from the end, -1 is the last +/// item. +/// +/// @return Item at the given index or NULL if `n` is out of range. +listitem_T *tv_list_find(list_T *const l, int n) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + STATIC_ASSERT(sizeof(n) == sizeof(l->lv_idx), + "n and lv_idx sizes do not match"); + if (l == NULL) { + return NULL; + } + + // Negative index is relative to the end. + if (n < 0) { + n = l->lv_len + n; + } + + // Check for index out of range. + if (n < 0 || n >= l->lv_len) { + return NULL; + } + + int idx; + listitem_T *item; + + // When there is a cached index may start search from there. + if (l->lv_idx_item != NULL) { + if (n < l->lv_idx / 2) { + // Closest to the start of the list. + item = l->lv_first; + idx = 0; + } else if (n > (l->lv_idx + l->lv_len) / 2) { + // Closest to the end of the list. + item = l->lv_last; + idx = l->lv_len - 1; + } else { + // Closest to the cached index. + item = l->lv_idx_item; + idx = l->lv_idx; + } + } else { + if (n < l->lv_len / 2) { + // Closest to the start of the list. + item = l->lv_first; + idx = 0; + } else { + // Closest to the end of the list. + item = l->lv_last; + idx = l->lv_len - 1; + } + } + + while (n > idx) { + // Search forward. + item = item->li_next; + idx++; + } + while (n < idx) { + // Search backward. + item = item->li_prev; + idx--; + } + + assert(idx == n); + // Cache the used index. + l->lv_idx = idx; + l->lv_idx_item = item; + + return item; +} + +/// Get list item l[n] as a number +/// +/// @param[in] l List to index. +/// @param[in] n Index in a list. +/// @param[out] ret_error Location where 1 will be saved if index was not +/// found. May be NULL. If everything is OK, +/// `*ret_error` is not touched. +/// +/// @return Integer value at the given index or -1. +varnumber_T tv_list_find_nr(list_T *const l, const int n, bool *const ret_error) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + const listitem_T *const li = tv_list_find(l, n); + if (li == NULL) { + if (ret_error != NULL) { + *ret_error = true; + } + return -1; + } + return tv_get_number_chk(&li->li_tv, ret_error); +} + +/// Get list item l[n] as a string +/// +/// @param[in] l List to index. +/// @param[in] n Index in a list. +/// +/// @return List item string value or NULL in case of error. +const char *tv_list_find_str(list_T *const l, const int n) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + const listitem_T *const li = tv_list_find(l, n); + if (li == NULL) { + emsgf(_(e_listidx), (int64_t)n); + return NULL; + } + return tv_get_string(&li->li_tv); +} + +/// Locate item in a list and return its index +/// +/// @param[in] l List to search. +/// @param[in] item Item to search for. +/// +/// @return Index of an item or -1 if item is not in the list. +long tv_list_idx_of_item(const list_T *const l, const listitem_T *const item) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (l == NULL) { + return -1; + } + long idx = 0; + const listitem_T *li; + for (li = l->lv_first; li != NULL && li != item; li = li->li_next) { + idx++; + } + if (li == NULL) { + return -1; + } + return idx; +} + +//{{{1 Dictionaries +//{{{2 Dictionary watchers + +/// Perform all necessary cleanup for a `DictWatcher` instance +/// +/// @param watcher Watcher to free. +static void tv_dict_watcher_free(DictWatcher *watcher) + FUNC_ATTR_NONNULL_ALL +{ + callback_free(&watcher->callback); + xfree(watcher->key_pattern); + xfree(watcher); +} + +/// Add watcher to a dictionary +/// +/// @param[in] dict Dictionary to add watcher to. +/// @param[in] key_pattern Pattern to watch for. +/// @param[in] key_pattern_len Key pattern length. +/// @param callback Function to be called on events. +void tv_dict_watcher_add(dict_T *const dict, const char *const key_pattern, + const size_t key_pattern_len, Callback callback) + FUNC_ATTR_NONNULL_ARG(2) +{ + if (dict == NULL) { + return; + } + DictWatcher *const watcher = xmalloc(sizeof(DictWatcher)); + watcher->key_pattern = xmemdupz(key_pattern, key_pattern_len); + watcher->key_pattern_len = key_pattern_len; + watcher->callback = callback; + watcher->busy = false; + QUEUE_INSERT_TAIL(&dict->watchers, &watcher->node); +} + +/// Check whether two callbacks are equal +/// +/// @param[in] cb1 First callback to check. +/// @param[in] cb2 Second callback to check. +/// +/// @return True if they are equal, false otherwise. +bool tv_callback_equal(const Callback *const cb1, const Callback *const cb2) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (cb1->type != cb2->type) { + return false; + } + switch (cb1->type) { + case kCallbackFuncref: { + return STRCMP(cb1->data.funcref, cb2->data.funcref) == 0; + } + case kCallbackPartial: { + // FIXME: this is inconsistent with tv_equal but is needed for precision + // maybe change dictwatcheradd to return a watcher id instead? + return cb1->data.partial == cb2->data.partial; + } + case kCallbackNone: { + return true; + } + } + assert(false); + return false; +} + +/// Remove watcher from a dictionary +/// +/// @param dict Dictionary to remove watcher from. +/// @param[in] key_pattern Pattern to remove watcher for. +/// @param[in] key_pattern_len Pattern length. +/// @param callback Callback to remove watcher for. +/// +/// @return True on success, false if relevant watcher was not found. +bool tv_dict_watcher_remove(dict_T *const dict, const char *const key_pattern, + const size_t key_pattern_len, + Callback callback) + FUNC_ATTR_NONNULL_ARG(2) +{ + if (dict == NULL) { + return false; + } + + QUEUE *w = NULL; + DictWatcher *watcher = NULL; + bool matched = false; + QUEUE_FOREACH(w, &dict->watchers) { + watcher = tv_dict_watcher_node_data(w); + if (tv_callback_equal(&watcher->callback, &callback) + && watcher->key_pattern_len == key_pattern_len + && memcmp(watcher->key_pattern, key_pattern, key_pattern_len) == 0) { + matched = true; + break; + } + } + + if (!matched) { + return false; + } + + QUEUE_REMOVE(w); + tv_dict_watcher_free(watcher); + return true; +} + +/// Test if `key` matches with with `watcher->key_pattern` +/// +/// @param[in] watcher Watcher to check key pattern from. +/// @param[in] key Key to check. +/// +/// @return true if key matches, false otherwise. +static bool tv_dict_watcher_matches(DictWatcher *watcher, const char *const key) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + // For now only allow very simple globbing in key patterns: a '*' at the end + // of the string means it should match everything up to the '*' instead of the + // whole string. + const size_t len = watcher->key_pattern_len; + if (len && watcher->key_pattern[len - 1] == '*') { + return strncmp(key, watcher->key_pattern, len - 1) == 0; + } else { + return strcmp(key, watcher->key_pattern) == 0; + } +} + +/// Send a change notification to all dictionary watchers that match given key +/// +/// @param[in] dict Dictionary which was modified. +/// @param[in] key Key which was modified. +/// @param[in] newtv New key value. +/// @param[in] oldtv Old key value. +void tv_dict_watcher_notify(dict_T *const dict, const char *const key, + typval_T *const newtv, typval_T *const oldtv) + FUNC_ATTR_NONNULL_ARG(1, 2) +{ + typval_T argv[3]; + + argv[0].v_type = VAR_DICT; + argv[0].v_lock = VAR_UNLOCKED; + argv[0].vval.v_dict = dict; + argv[1].v_type = VAR_STRING; + argv[1].v_lock = VAR_UNLOCKED; + argv[1].vval.v_string = (char_u *)xstrdup(key); + argv[2].v_type = VAR_DICT; + argv[2].v_lock = VAR_UNLOCKED; + argv[2].vval.v_dict = tv_dict_alloc(); + argv[2].vval.v_dict->dv_refcount++; + + if (newtv) { + dictitem_T *const v = tv_dict_item_alloc_len(S_LEN("new")); + tv_copy(newtv, &v->di_tv); + tv_dict_add(argv[2].vval.v_dict, v); + } + + if (oldtv) { + dictitem_T *const v = tv_dict_item_alloc_len(S_LEN("old")); + tv_copy(oldtv, &v->di_tv); + tv_dict_add(argv[2].vval.v_dict, v); + } + + typval_T rettv; + + QUEUE *w; + QUEUE_FOREACH(w, &dict->watchers) { + DictWatcher *watcher = tv_dict_watcher_node_data(w); + if (!watcher->busy && tv_dict_watcher_matches(watcher, key)) { + rettv = TV_INITIAL_VALUE; + watcher->busy = true; + callback_call(&watcher->callback, 3, argv, &rettv); + watcher->busy = false; + tv_clear(&rettv); + } + } + + for (size_t i = 1; i < ARRAY_SIZE(argv); i++) { + tv_clear(argv + i); + } +} + +//{{{2 Dictionary item + +/// Allocate a dictionary item +/// +/// @note that the value of the item (->di_tv) still needs to be initialized. +/// +/// @param[in] key Key, is copied to the new item. +/// @param[in] key_len Key length. +/// +/// @return [allocated] new dictionary item. +dictitem_T *tv_dict_item_alloc_len(const char *const key, const size_t key_len) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT + FUNC_ATTR_MALLOC +{ + dictitem_T *const di = xmalloc(offsetof(dictitem_T, di_key) + key_len + 1); + memcpy(di->di_key, key, key_len); + di->di_key[key_len] = NUL; + di->di_flags = DI_FLAGS_ALLOC; + return di; +} + +/// Allocate a dictionary item +/// +/// @note that the value of the item (->di_tv) still needs to be initialized. +/// +/// @param[in] key Key, is copied to the new item. +/// +/// @return [allocated] new dictionary item. +dictitem_T *tv_dict_item_alloc(const char *const key) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT + FUNC_ATTR_MALLOC +{ + return tv_dict_item_alloc_len(key, strlen(key)); +} + +/// Free a dictionary item, also clearing the value +/// +/// @param item Item to free. +void tv_dict_item_free(dictitem_T *const item) + FUNC_ATTR_NONNULL_ALL +{ + tv_clear(&item->di_tv); + if (item->di_flags & DI_FLAGS_ALLOC) { + xfree(item); + } +} + +/// Make a copy of a dictionary item +/// +/// @param[in] di Item to copy. +/// +/// @return [allocated] new dictionary item. +static dictitem_T *tv_dict_item_copy(dictitem_T *const di) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + dictitem_T *const new_di = tv_dict_item_alloc((const char *)di->di_key); + tv_copy(&di->di_tv, &new_di->di_tv); + return new_di; +} + +/// Remove item from dictionary and free it +/// +/// @param dict Dictionary to remove item from. +/// @param item Item to remove. +void tv_dict_item_remove(dict_T *const dict, dictitem_T *const item) + FUNC_ATTR_NONNULL_ALL +{ + hashitem_T *const hi = hash_find(&dict->dv_hashtab, item->di_key); + if (HASHITEM_EMPTY(hi)) { + emsgf(_(e_intern2), "tv_dict_item_remove()"); + } else { + hash_remove(&dict->dv_hashtab, hi); + } + tv_dict_item_free(item); +} + +//{{{2 Alloc/free + +/// Allocate an empty dictionary +/// +/// @return [allocated] new dictionary. +dict_T *tv_dict_alloc(void) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT +{ + dict_T *const d = xmalloc(sizeof(dict_T)); + + // Add the dict to the list of dicts for garbage collection. + if (gc_first_dict != NULL) { + gc_first_dict->dv_used_prev = d; + } + d->dv_used_next = gc_first_dict; + d->dv_used_prev = NULL; + gc_first_dict = d; + + hash_init(&d->dv_hashtab); + d->dv_lock = VAR_UNLOCKED; + d->dv_scope = VAR_NO_SCOPE; + d->dv_refcount = 0; + d->dv_copyID = 0; + QUEUE_INIT(&d->watchers); + + return d; +} + +/// Free items contained in a dictionary +/// +/// @param[in,out] d Dictionary to clear. +void tv_dict_free_contents(dict_T *const d) + FUNC_ATTR_NONNULL_ALL +{ + // Lock the hashtab, we don't want it to resize while freeing items. + hash_lock(&d->dv_hashtab); + assert(d->dv_hashtab.ht_locked > 0); + HASHTAB_ITER(&d->dv_hashtab, hi, { + // Remove the item before deleting it, just in case there is + // something recursive causing trouble. + dictitem_T *const di = TV_DICT_HI2DI(hi); + hash_remove(&d->dv_hashtab, hi); + tv_dict_item_free(di); + }); + + while (!QUEUE_EMPTY(&d->watchers)) { + QUEUE *w = QUEUE_HEAD(&d->watchers); + QUEUE_REMOVE(w); + DictWatcher *watcher = tv_dict_watcher_node_data(w); + tv_dict_watcher_free(watcher); + } + + hash_clear(&d->dv_hashtab); + d->dv_hashtab.ht_locked--; + hash_init(&d->dv_hashtab); +} + +/// Free a dictionary itself, ignoring items it contains +/// +/// Ignores the reference count. +/// +/// @param[in,out] d Dictionary to free. +void tv_dict_free_dict(dict_T *const d) + FUNC_ATTR_NONNULL_ALL +{ + // Remove the dict from the list of dicts for garbage collection. + if (d->dv_used_prev == NULL) { + gc_first_dict = d->dv_used_next; + } else { + d->dv_used_prev->dv_used_next = d->dv_used_next; + } + if (d->dv_used_next != NULL) { + d->dv_used_next->dv_used_prev = d->dv_used_prev; + } + + xfree(d); +} + +/// Free a dictionary, including all items it contains +/// +/// Ignores the reference count. +/// +/// @param d Dictionary to free. +void tv_dict_free(dict_T *const d) + FUNC_ATTR_NONNULL_ALL +{ + if (!tv_in_free_unref_items) { + tv_dict_free_contents(d); + tv_dict_free_dict(d); + } +} + + +/// Unreference a dictionary +/// +/// Decrements the reference count and frees dictionary when it becomes zero. +/// +/// @param[in] d Dictionary to operate on. +void tv_dict_unref(dict_T *const d) +{ + if (d != NULL && --d->dv_refcount <= 0) { + tv_dict_free(d); + } +} + +//{{{2 Indexing/searching + +/// Find item in dictionary +/// +/// @param[in] d Dictionary to check. +/// @param[in] key Dictionary key. +/// @param[in] len Key length. If negative, then strlen(key) is used. +/// +/// @return found item or NULL if nothing was found. +dictitem_T *tv_dict_find(const dict_T *const d, const char *const key, + const ptrdiff_t len) + FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (d == NULL) { + return NULL; + } + hashitem_T *const hi = (len < 0 + ? hash_find(&d->dv_hashtab, (const char_u *)key) + : hash_find_len(&d->dv_hashtab, key, (size_t)len)); + if (HASHITEM_EMPTY(hi)) { + return NULL; + } + return TV_DICT_HI2DI(hi); +} + +/// Get a number item from a dictionary +/// +/// Returns 0 if the entry does not exist. +/// +/// @param[in] d Dictionary to get item from. +/// @param[in] key Key to find in dictionary. +/// +/// @return Dictionary item. +varnumber_T tv_dict_get_number(const dict_T *const d, const char *const key) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + dictitem_T *const di = tv_dict_find(d, key, -1); + if (di == NULL) { + return 0; + } + return tv_get_number(&di->di_tv); +} + +/// Get a string item from a dictionary +/// +/// @param[in] d Dictionary to get item from. +/// @param[in] key Dictionary key. +/// @param[in] save If true, returned string will be placed in the allocated +/// memory. +/// +/// @return NULL if key does not exist, empty string in case of type error, +/// string item value otherwise. If returned value is not NULL, it may +/// be allocated depending on `save` argument. +char *tv_dict_get_string(const dict_T *const d, const char *const key, + const bool save) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + static char numbuf[NUMBUFLEN]; + const char *const s = tv_dict_get_string_buf(d, key, numbuf); + if (save && s != NULL) { + return xstrdup(s); + } + return (char *)s; +} + +/// Get a string item from a dictionary +/// +/// @param[in] d Dictionary to get item from. +/// @param[in] key Dictionary key. +/// @param[in] numbuf Buffer for non-string items converted to strings, at +/// least of #NUMBUFLEN length. +/// +/// @return NULL if key does not exist, empty string in case of type error, +/// string item value otherwise. +const char *tv_dict_get_string_buf(const dict_T *const d, const char *const key, + char *const numbuf) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + const dictitem_T *const di = tv_dict_find(d, key, -1); + if (di == NULL) { + return NULL; + } + return tv_get_string_buf(&di->di_tv, numbuf); +} + +/// Get a string item from a dictionary +/// +/// @param[in] d Dictionary to get item from. +/// @param[in] key Dictionary key. +/// @param[in] key_len Key length. +/// @param[in] numbuf Buffer for non-string items converted to strings, at +/// least of #NUMBUFLEN length. +/// @param[in] def Default return when key does not exist. +/// +/// @return `def` when key does not exist, +/// NULL in case of type error, +/// string item value in case of success. +const char *tv_dict_get_string_buf_chk(const dict_T *const d, + const char *const key, + const ptrdiff_t key_len, + char *const numbuf, + const char *const def) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + const dictitem_T *const di = tv_dict_find(d, key, key_len); + if (di == NULL) { + return def; + } + return tv_get_string_buf_chk(&di->di_tv, numbuf); +} + +/// Get a function from a dictionary +/// +/// @param[in] d Dictionary to get callback from. +/// @param[in] key Dictionary key. +/// @param[in] key_len Key length, may be -1 to use strlen(). +/// @param[out] result The address where a pointer to the wanted callback +/// will be left. +/// +/// @return true/false on success/failure. +bool tv_dict_get_callback(dict_T *const d, + const char *const key, const ptrdiff_t key_len, + Callback *const result) + FUNC_ATTR_NONNULL_ARG(2, 4) FUNC_ATTR_WARN_UNUSED_RESULT +{ + result->type = kCallbackNone; + + dictitem_T *const di = tv_dict_find(d, key, key_len); + + if (di == NULL) { + return true; + } + + if (!tv_is_func(di->di_tv) && di->di_tv.v_type != VAR_STRING) { + emsgf(_("E6000: Argument is not a function or function name")); + return false; + } + + typval_T tv; + tv_copy(&di->di_tv, &tv); + set_selfdict(&tv, d); + const bool res = callback_from_typval(result, &tv); + tv_clear(&tv); + return res; +} + +//{{{2 dict_add* + +/// Add item to dictionary +/// +/// @param[out] d Dictionary to add to. +/// @param[in] item Item to add. +/// +/// @return FAIL if key already exists. +int tv_dict_add(dict_T *const d, dictitem_T *const item) + FUNC_ATTR_NONNULL_ALL +{ + return hash_add(&d->dv_hashtab, item->di_key); +} + +/// Add a list entry to dictionary +/// +/// @param[out] d Dictionary to add entry to. +/// @param[in] key Key to add. +/// @param[in] key_len Key length. +/// @param list List to add. Will have reference count incremented. +/// +/// @return OK in case of success, FAIL when key already exists. +int tv_dict_add_list(dict_T *const d, const char *const key, + const size_t key_len, list_T *const list) + FUNC_ATTR_NONNULL_ALL +{ + dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); + + item->di_tv.v_lock = VAR_UNLOCKED; + item->di_tv.v_type = VAR_LIST; + item->di_tv.vval.v_list = list; + list->lv_refcount++; + if (tv_dict_add(d, item) == FAIL) { + tv_dict_item_free(item); + return FAIL; + } + return OK; +} + +/// Add a dictionary entry to dictionary +/// +/// @param[out] d Dictionary to add entry to. +/// @param[in] key Key to add. +/// @param[in] key_len Key length. +/// @param dict Dictionary to add. Will have reference count incremented. +/// +/// @return OK in case of success, FAIL when key already exists. +int tv_dict_add_dict(dict_T *const d, const char *const key, + const size_t key_len, dict_T *const dict) + FUNC_ATTR_NONNULL_ALL +{ + dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); + + item->di_tv.v_lock = VAR_UNLOCKED; + item->di_tv.v_type = VAR_DICT; + item->di_tv.vval.v_dict = dict; + dict->dv_refcount++; + if (tv_dict_add(d, item) == FAIL) { + tv_dict_item_free(item); + return FAIL; + } + return OK; +} + +/// Add a number entry to dictionary +/// +/// @param[out] d Dictionary to add entry to. +/// @param[in] key Key to add. +/// @param[in] key_len Key length. +/// @param[in] nr Number to add. +/// +/// @return OK in case of success, FAIL when key already exists. +int tv_dict_add_nr(dict_T *const d, const char *const key, + const size_t key_len, const varnumber_T nr) +{ + dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); + + item->di_tv.v_lock = VAR_UNLOCKED; + item->di_tv.v_type = VAR_NUMBER; + item->di_tv.vval.v_number = nr; + if (tv_dict_add(d, item) == FAIL) { + tv_dict_item_free(item); + return FAIL; + } + return OK; +} + +/// Add a string entry to dictionary +/// +/// @param[out] d Dictionary to add entry to. +/// @param[in] key Key to add. +/// @param[in] key_len Key length. +/// @param[in] val String to add. +/// +/// @return OK in case of success, FAIL when key already exists. +int tv_dict_add_str(dict_T *const d, + const char *const key, const size_t key_len, + const char *const val) + FUNC_ATTR_NONNULL_ALL +{ + return tv_dict_add_allocated_str(d, key, key_len, xstrdup(val)); +} + +/// Add a string entry to dictionary +/// +/// Unlike tv_dict_add_str() saves val to the new dictionary item in place of +/// creating a new copy. +/// +/// @warning String will be freed even in case addition fails. +/// +/// @param[out] d Dictionary to add entry to. +/// @param[in] key Key to add. +/// @param[in] key_len Key length. +/// @param[in] val String to add. +/// +/// @return OK in case of success, FAIL when key already exists. +int tv_dict_add_allocated_str(dict_T *const d, + const char *const key, const size_t key_len, + char *const val) + FUNC_ATTR_NONNULL_ALL +{ + dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); + + item->di_tv.v_lock = VAR_UNLOCKED; + item->di_tv.v_type = VAR_STRING; + item->di_tv.vval.v_string = (char_u *)val; + if (tv_dict_add(d, item) == FAIL) { + tv_dict_item_free(item); + return FAIL; + } + return OK; +} + +//{{{2 Operations on the whole dict + +/// Clear all the keys of a Dictionary. "d" remains a valid empty Dictionary. +/// +/// @param d The Dictionary to clear +void tv_dict_clear(dict_T *const d) + FUNC_ATTR_NONNULL_ALL +{ + hash_lock(&d->dv_hashtab); + assert(d->dv_hashtab.ht_locked > 0); + + HASHTAB_ITER(&d->dv_hashtab, hi, { + tv_dict_item_free(TV_DICT_HI2DI(hi)); + hash_remove(&d->dv_hashtab, hi); + }); + + hash_unlock(&d->dv_hashtab); +} + +/// Extend dictionary with items from another dictionary +/// +/// @param d1 Dictionary to extend. +/// @param[in] d2 Dictionary to extend with. +/// @param[in] action "error", "force", "keep": +/// +/// e*, including "error": duplicate key gives an error. +/// f*, including "force": duplicate d2 keys override d1. +/// other, including "keep": duplicate d2 keys ignored. +void tv_dict_extend(dict_T *const d1, dict_T *const d2, + const char *const action) + FUNC_ATTR_NONNULL_ALL +{ + const bool watched = tv_dict_is_watched(d1); + const char *const arg_errmsg = _("extend() argument"); + const size_t arg_errmsg_len = strlen(arg_errmsg); + + TV_DICT_ITER(d2, di2, { + dictitem_T *const di1 = tv_dict_find(d1, (const char *)di2->di_key, -1); + if (d1->dv_scope != VAR_NO_SCOPE) { + // Disallow replacing a builtin function in l: and g:. + // Check the key to be valid when adding to any scope. + if (d1->dv_scope == VAR_DEF_SCOPE + && tv_is_func(di2->di_tv) + && !var_check_func_name((const char *)di2->di_key, di1 == NULL)) { + break; + } + if (!valid_varname((const char *)di2->di_key)) { + break; + } + } + if (di1 == NULL) { + dictitem_T *const new_di = tv_dict_item_copy(di2); + if (tv_dict_add(d1, new_di) == FAIL) { + tv_dict_item_free(new_di); + } else if (watched) { + tv_dict_watcher_notify(d1, (const char *)new_di->di_key, &new_di->di_tv, + NULL); + } + } else if (*action == 'e') { + emsgf(_("E737: Key already exists: %s"), di2->di_key); + break; + } else if (*action == 'f' && di2 != di1) { + typval_T oldtv; + + if (tv_check_lock(di1->di_tv.v_lock, arg_errmsg, arg_errmsg_len) + || var_check_ro(di1->di_flags, arg_errmsg, arg_errmsg_len)) { + break; + } + + if (watched) { + tv_copy(&di1->di_tv, &oldtv); + } + + tv_clear(&di1->di_tv); + tv_copy(&di2->di_tv, &di1->di_tv); + + if (watched) { + tv_dict_watcher_notify(d1, (const char *)di1->di_key, &di1->di_tv, + &oldtv); + tv_clear(&oldtv); + } + } + }); +} + +/// Compare two dictionaries +/// +/// @param[in] d1 First dictionary. +/// @param[in] d2 Second dictionary. +/// @param[in] ic True if case is to be ignored. +/// @param[in] recursive True when used recursively. +bool tv_dict_equal(dict_T *const d1, dict_T *const d2, + const bool ic, const bool recursive) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (d1 == d2) { + return true; + } + if (d1 == NULL || d2 == NULL) { + return false; + } + if (tv_dict_len(d1) != tv_dict_len(d2)) { + return false; + } + + TV_DICT_ITER(d1, di1, { + dictitem_T *const di2 = tv_dict_find(d2, (const char *)di1->di_key, -1); + if (di2 == NULL) { + return false; + } + if (!tv_equal(&di1->di_tv, &di2->di_tv, ic, recursive)) { + return false; + } + }); + return true; +} + +/// Make a copy of dictionary +/// +/// @param[in] conv If non-NULL, then all internal strings will be converted. +/// @param[in] orig Original dictionary to copy. +/// @param[in] deep If false, then shallow copy will be done. +/// @param[in] copyID See var_item_copy(). +/// +/// @return Copied dictionary. May be NULL in case original dictionary is NULL +/// or some failure happens. The refcount of the new dictionary is set +/// to 1. +dict_T *tv_dict_copy(const vimconv_T *const conv, + dict_T *const orig, + const bool deep, + const int copyID) +{ + if (orig == NULL) { + return NULL; + } + + dict_T *copy = tv_dict_alloc(); + if (copyID != 0) { + orig->dv_copyID = copyID; + orig->dv_copydict = copy; + } + TV_DICT_ITER(orig, di, { + if (got_int) { + break; + } + dictitem_T *new_di; + if (conv == NULL || conv->vc_type == CONV_NONE) { + new_di = tv_dict_item_alloc((const char *)di->di_key); + } else { + size_t len = STRLEN(di->di_key); + char *const key = (char *)string_convert(conv, di->di_key, &len); + if (key == NULL) { + new_di = tv_dict_item_alloc_len((const char *)di->di_key, len); + } else { + new_di = tv_dict_item_alloc_len(key, len); + xfree(key); + } + } + if (deep) { + if (var_item_copy(conv, &di->di_tv, &new_di->di_tv, deep, + copyID) == FAIL) { + xfree(new_di); + break; + } + } else { + tv_copy(&di->di_tv, &new_di->di_tv); + } + if (tv_dict_add(copy, new_di) == FAIL) { + tv_dict_item_free(new_di); + break; + } + }); + + copy->dv_refcount++; + if (got_int) { + tv_dict_unref(copy); + copy = NULL; + } + + return copy; +} + +/// Set all existing keys in "dict" as read-only. +/// +/// This does not protect against adding new keys to the Dictionary. +/// +/// @param dict The dict whose keys should be frozen. +void tv_dict_set_keys_readonly(dict_T *const dict) + FUNC_ATTR_NONNULL_ALL +{ + TV_DICT_ITER(dict, di, { + di->di_flags |= DI_FLAGS_RO | DI_FLAGS_FIX; + }); +} + +//{{{1 Generic typval operations +//{{{2 Init/alloc/clear +//{{{3 Alloc + +/// Allocate an empty list for a return value +/// +/// Also sets reference count. +/// +/// @param[out] ret_tv Structure where list is saved. +/// +/// @return [allocated] pointer to the created list. +list_T *tv_list_alloc_ret(typval_T *const ret_tv) + FUNC_ATTR_NONNULL_ALL +{ + list_T *const l = tv_list_alloc(); + ret_tv->vval.v_list = l; + ret_tv->v_type = VAR_LIST; + ret_tv->v_lock = VAR_UNLOCKED; + l->lv_refcount++; + return l; +} + +/// Allocate an empty dictionary for a return value +/// +/// Also sets reference count. +/// +/// @param[out] ret_tv Structure where dictionary is saved. +void tv_dict_alloc_ret(typval_T *const ret_tv) + FUNC_ATTR_NONNULL_ALL +{ + dict_T *const d = tv_dict_alloc(); + ret_tv->vval.v_dict = d; + ret_tv->v_type = VAR_DICT; + ret_tv->v_lock = VAR_UNLOCKED; + d->dv_refcount++; +} + +//{{{3 Clear +#define TYPVAL_ENCODE_ALLOW_SPECIALS false + +#define TYPVAL_ENCODE_CONV_NIL(tv) \ + do { \ + tv->vval.v_special = kSpecialVarFalse; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) + +#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ + TYPVAL_ENCODE_CONV_NIL(tv) + +#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ + do { \ + (void)num; \ + tv->vval.v_number = 0; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) + +#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) + +#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ + do { \ + tv->vval.v_float = 0; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) + +#define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ + do { \ + xfree(buf); \ + tv->vval.v_string = NULL; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) + +#define TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len) + +#define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type) + +static inline int _nothing_conv_func_start(typval_T *const tv, + char_u *const fun) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ARG(1) +{ + tv->v_lock = VAR_UNLOCKED; + if (tv->v_type == VAR_PARTIAL) { + partial_T *const pt_ = tv->vval.v_partial; + if (pt_ != NULL && pt_->pt_refcount > 1) { + pt_->pt_refcount--; + tv->vval.v_partial = NULL; + return OK; + } + } else { + func_unref(fun); + if ((const char *)fun != tv_empty_string) { + xfree(fun); + } + tv->vval.v_string = NULL; + } + return NOTDONE; +} +#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ + do { \ + if (_nothing_conv_func_start(tv, fun) != NOTDONE) { \ + return OK; \ + } \ + } while (0) + +#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) +#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) + +static inline void _nothing_conv_func_end(typval_T *const tv, const int copyID) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL +{ + if (tv->v_type == VAR_PARTIAL) { + partial_T *const pt = tv->vval.v_partial; + if (pt == NULL) { + return; + } + // Dictionary should already be freed by the time. + // If it was not freed then it is a part of the reference cycle. + assert(pt->pt_dict == NULL || pt->pt_dict->dv_copyID == copyID); + pt->pt_dict = NULL; + // As well as all arguments. + pt->pt_argc = 0; + assert(pt->pt_refcount <= 1); + partial_unref(pt); + tv->vval.v_partial = NULL; + assert(tv->v_lock == VAR_UNLOCKED); + } +} +#define TYPVAL_ENCODE_CONV_FUNC_END(tv) _nothing_conv_func_end(tv, copyID) + +#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \ + do { \ + tv_list_unref(tv->vval.v_list); \ + tv->vval.v_list = NULL; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) + +#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ + do { \ + assert((void *)&dict != (void *)&TYPVAL_ENCODE_NODICT_VAR); \ + tv_dict_unref((dict_T *)dict); \ + *((dict_T **)&dict) = NULL; \ + if (tv != NULL) { \ + ((typval_T *)tv)->v_lock = VAR_UNLOCKED; \ + } \ + } while (0) + +static inline int _nothing_conv_real_list_after_start( + typval_T *const tv, MPConvStackVal *const mpsv) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT +{ + assert(tv != NULL); + tv->v_lock = VAR_UNLOCKED; + if (tv->vval.v_list->lv_refcount > 1) { + tv->vval.v_list->lv_refcount--; + tv->vval.v_list = NULL; + mpsv->data.l.li = NULL; + return OK; + } + return NOTDONE; +} +#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) + +#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) \ + do { \ + if (_nothing_conv_real_list_after_start(tv, &mpsv) != NOTDONE) { \ + goto typval_encode_stop_converting_one_item; \ + } \ + } while (0) + +#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) + +static inline void _nothing_conv_list_end(typval_T *const tv) + FUNC_ATTR_ALWAYS_INLINE +{ + if (tv == NULL) { + return; + } + assert(tv->v_type == VAR_LIST); + list_T *const list = tv->vval.v_list; + tv_list_unref(list); + tv->vval.v_list = NULL; +} +#define TYPVAL_ENCODE_CONV_LIST_END(tv) _nothing_conv_list_end(tv) + +static inline int _nothing_conv_real_dict_after_start( + typval_T *const tv, dict_T **const dictp, const void *const nodictvar, + MPConvStackVal *const mpsv) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (tv != NULL) { + tv->v_lock = VAR_UNLOCKED; + } + if ((const void *)dictp != nodictvar && (*dictp)->dv_refcount > 1) { + (*dictp)->dv_refcount--; + *dictp = NULL; + mpsv->data.d.todo = 0; + return OK; + } + return NOTDONE; +} +#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) + +#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) \ + do { \ + if (_nothing_conv_real_dict_after_start( \ + tv, (dict_T **)&dict, (void *)&TYPVAL_ENCODE_NODICT_VAR, \ + &mpsv) != NOTDONE) { \ + goto typval_encode_stop_converting_one_item; \ + } \ + } while (0) + +#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(tv, dict) +#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) +#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) + +static inline void _nothing_conv_dict_end(typval_T *const tv, + dict_T **const dictp, + const void *const nodictvar) + FUNC_ATTR_ALWAYS_INLINE +{ + if ((const void *)dictp != nodictvar) { + tv_dict_unref(*dictp); + *dictp = NULL; + } +} +#define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \ + _nothing_conv_dict_end(tv, (dict_T **)&dict, \ + (void *)&TYPVAL_ENCODE_NODICT_VAR) + +#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) + +#define TYPVAL_ENCODE_SCOPE static +#define TYPVAL_ENCODE_NAME nothing +#define TYPVAL_ENCODE_FIRST_ARG_TYPE const void *const +#define TYPVAL_ENCODE_FIRST_ARG_NAME ignored +#define TYPVAL_ENCODE_TRANSLATE_OBJECT_NAME +#include "nvim/eval/typval_encode.c.h" +#undef TYPVAL_ENCODE_SCOPE +#undef TYPVAL_ENCODE_NAME +#undef TYPVAL_ENCODE_FIRST_ARG_TYPE +#undef TYPVAL_ENCODE_FIRST_ARG_NAME +#undef TYPVAL_ENCODE_TRANSLATE_OBJECT_NAME + +#undef TYPVAL_ENCODE_ALLOW_SPECIALS +#undef TYPVAL_ENCODE_CONV_NIL +#undef TYPVAL_ENCODE_CONV_BOOL +#undef TYPVAL_ENCODE_CONV_NUMBER +#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER +#undef TYPVAL_ENCODE_CONV_FLOAT +#undef TYPVAL_ENCODE_CONV_STRING +#undef TYPVAL_ENCODE_CONV_STR_STRING +#undef TYPVAL_ENCODE_CONV_EXT_STRING +#undef TYPVAL_ENCODE_CONV_FUNC_START +#undef TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS +#undef TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF +#undef TYPVAL_ENCODE_CONV_FUNC_END +#undef TYPVAL_ENCODE_CONV_EMPTY_LIST +#undef TYPVAL_ENCODE_CONV_EMPTY_DICT +#undef TYPVAL_ENCODE_CONV_LIST_START +#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START +#undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS +#undef TYPVAL_ENCODE_CONV_LIST_END +#undef TYPVAL_ENCODE_CONV_DICT_START +#undef TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START +#undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK +#undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY +#undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS +#undef TYPVAL_ENCODE_CONV_DICT_END +#undef TYPVAL_ENCODE_CONV_RECURSE + +/// Free memory for a variable value and set the value to NULL or 0 +/// +/// @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); + } +} + +//{{{3 Free + +/// Free allocated VimL object and value stored inside +/// +/// @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(tv->vval.v_string); + FALLTHROUGH; + } + case VAR_STRING: { + xfree(tv->vval.v_string); + 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_SPECIAL: + case VAR_NUMBER: + case VAR_FLOAT: + case VAR_UNKNOWN: { + break; + } + } + xfree(tv); + } +} + +//{{{3 Copy + +/// Copy typval from one location to another +/// +/// When needed allocates string or increases reference count. Does not make +/// a copy of a container, but copies its reference! +/// +/// It is OK for `from` and `to` to point to the same location; this is used to +/// make a copy later. +/// +/// @param[in] from Location to copy from. +/// @param[out] to Location to copy to. +void tv_copy(typval_T *const from, typval_T *const to) +{ + to->v_type = from->v_type; + to->v_lock = VAR_UNLOCKED; + memmove(&to->vval, &from->vval, sizeof(to->vval)); + switch (from->v_type) { + case VAR_NUMBER: + case VAR_FLOAT: + case VAR_SPECIAL: { + break; + } + case VAR_STRING: + case VAR_FUNC: { + if (from->vval.v_string != NULL) { + to->vval.v_string = vim_strsave(from->vval.v_string); + if (from->v_type == VAR_FUNC) { + func_ref(to->vval.v_string); + } + } + break; + } + case VAR_PARTIAL: { + if (to->vval.v_partial != NULL) { + to->vval.v_partial->pt_refcount++; + } + break; + } + case VAR_LIST: { + if (from->vval.v_list != NULL) { + to->vval.v_list->lv_refcount++; + } + break; + } + case VAR_DICT: { + if (from->vval.v_dict != NULL) { + to->vval.v_dict->dv_refcount++; + } + break; + } + case VAR_UNKNOWN: { + emsgf(_(e_intern2), "tv_copy(UNKNOWN)"); + break; + } + } +} + +//{{{2 Locks + +/// Lock or unlock an item +/// +/// @param[out] tv Item to (un)lock. +/// @param[in] deep Levels to (un)lock, -1 to (un)lock everything. +/// @param[in] lock True if it is needed to lock an item, false to unlock. +void tv_item_lock(typval_T *const tv, const int deep, const bool lock) + FUNC_ATTR_NONNULL_ALL +{ + // TODO(ZyX-I): Make this not recursive + static int recurse = 0; + + if (recurse >= DICT_MAXNEST) { + emsgf(_("E743: variable nested too deep for (un)lock")); + return; + } + if (deep == 0) { + return; + } + recurse++; + + // lock/unlock the item itself +#define CHANGE_LOCK(lock, var) \ + do { \ + var = ((VarLockStatus[]) { \ + [VAR_UNLOCKED] = (lock ? VAR_LOCKED : VAR_UNLOCKED), \ + [VAR_LOCKED] = (lock ? VAR_LOCKED : VAR_UNLOCKED), \ + [VAR_FIXED] = VAR_FIXED, \ + })[var]; \ + } while (0) + CHANGE_LOCK(lock, tv->v_lock); + + switch (tv->v_type) { + case VAR_LIST: { + list_T *const l = tv->vval.v_list; + if (l != NULL) { + CHANGE_LOCK(lock, l->lv_lock); + if (deep < 0 || deep > 1) { + // Recursive: lock/unlock the items the List contains. + for (listitem_T *li = l->lv_first; li != NULL; li = li->li_next) { + tv_item_lock(&li->li_tv, deep - 1, lock); + } + } + } + break; + } + case VAR_DICT: { + dict_T *const d = tv->vval.v_dict; + if (d != NULL) { + CHANGE_LOCK(lock, d->dv_lock); + if (deep < 0 || deep > 1) { + // recursive: lock/unlock the items the List contains + TV_DICT_ITER(d, di, { + tv_item_lock(&di->di_tv, deep - 1, lock); + }); + } + } + break; + } + case VAR_NUMBER: + case VAR_FLOAT: + case VAR_STRING: + case VAR_FUNC: + case VAR_PARTIAL: + case VAR_SPECIAL: { + break; + } + case VAR_UNKNOWN: { + assert(false); + } + } +#undef CHANGE_LOCK + recurse--; +} + +/// Check whether VimL value is locked itself or refers to a locked container +/// +/// @param[in] tv Value to check. +/// +/// @return True if value is locked, false otherwise. +bool tv_islocked(const typval_T *const tv) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL +{ + return ((tv->v_lock == VAR_LOCKED) + || (tv->v_type == VAR_LIST + && tv->vval.v_list != NULL + && (tv->vval.v_list->lv_lock == VAR_LOCKED)) + || (tv->v_type == VAR_DICT + && tv->vval.v_dict != NULL + && (tv->vval.v_dict->dv_lock == VAR_LOCKED))); +} + +/// Return true if typval is locked +/// +/// Also gives an error message when typval is locked. +/// +/// @param[in] lock Lock status. +/// @param[in] name Variable name, used in the error message. +/// @param[in] name_len Variable name length. Use #TV_TRANSLATE to translate +/// variable name and compute the length. Use #TV_CSTRING +/// to compute the length with strlen() without +/// translating. +/// +/// Both #TV_… values are used for optimization purposes: +/// variable name with its length is needed only in case +/// of error, when no error occurs computing them is +/// a waste of CPU resources. This especially applies to +/// gettext. +/// +/// @return true if variable is locked, false otherwise. +bool tv_check_lock(const VarLockStatus lock, const char *name, + size_t name_len) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + const char *error_message = NULL; + switch (lock) { + case VAR_UNLOCKED: { + return false; + } + case VAR_LOCKED: { + error_message = N_("E741: Value is locked: %.*s"); + break; + } + case VAR_FIXED: { + error_message = N_("E742: Cannot change value of %.*s"); + break; + } + } + assert(error_message != NULL); + + if (name == NULL) { + name = _("Unknown"); + name_len = strlen(name); + } else if (name_len == TV_TRANSLATE) { + name = _(name); + name_len = strlen(name); + } else if (name_len == TV_CSTRING) { + name_len = strlen(name); + } + + emsgf(_(error_message), (int)name_len, name); + + return true; +} + +//{{{2 Comparison + +static int tv_equal_recurse_limit; + +/// Compare two VimL values +/// +/// Like "==", but strings and numbers are different, as well as floats and +/// numbers. +/// +/// @warning Too nested structures may be considered equal even if they are not. +/// +/// @param[in] tv1 First value to compare. +/// @param[in] tv2 Second value to compare. +/// @param[in] ic True if case is to be ignored. +/// @param[in] recursive True when used recursively. +/// +/// @return true if values are equal. +bool tv_equal(typval_T *const tv1, typval_T *const tv2, const bool ic, + const bool recursive) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL +{ + // TODO(ZyX-I): Make this not recursive + static int recursive_cnt = 0; // Catch recursive loops. + + if (!(tv_is_func(*tv1) && tv_is_func(*tv2)) && tv1->v_type != tv2->v_type) { + return false; + } + + // Catch lists and dicts that have an endless loop by limiting + // recursiveness to a limit. We guess they are equal then. + // A fixed limit has the problem of still taking an awful long time. + // Reduce the limit every time running into it. That should work fine for + // deeply linked structures that are not recursively linked and catch + // recursiveness quickly. + if (!recursive) { + tv_equal_recurse_limit = 1000; + } + if (recursive_cnt >= tv_equal_recurse_limit) { + tv_equal_recurse_limit--; + return true; + } + + switch (tv1->v_type) { + case VAR_LIST: { + recursive_cnt++; + const bool r = tv_list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, + true); + recursive_cnt--; + return r; + } + case VAR_DICT: { + recursive_cnt++; + const bool r = tv_dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, + true); + recursive_cnt--; + return r; + } + case VAR_PARTIAL: + case VAR_FUNC: { + if ((tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial == NULL) + || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial == NULL)) { + return false; + } + recursive_cnt++; + const bool r = func_equal(tv1, tv2, ic); + recursive_cnt--; + return r; + } + case VAR_NUMBER: { + return tv1->vval.v_number == tv2->vval.v_number; + } + case VAR_FLOAT: { + return tv1->vval.v_float == tv2->vval.v_float; + } + case VAR_STRING: { + char buf1[NUMBUFLEN]; + char buf2[NUMBUFLEN]; + const char *s1 = tv_get_string_buf(tv1, buf1); + const char *s2 = tv_get_string_buf(tv2, buf2); + return mb_strcmp_ic((bool)ic, s1, s2) == 0; + } + case VAR_SPECIAL: { + return tv1->vval.v_special == tv2->vval.v_special; + } + case VAR_UNKNOWN: { + // VAR_UNKNOWN can be the result of an invalid expression, let’s say it + // does not equal anything, not even self. + return false; + } + } + + assert(false); + return false; +} + +//{{{2 Type checks + +/// Check that given value is a number or string +/// +/// Error messages are compatible with tv_get_number() previously used for the +/// same purpose in buf*() functions. Special values are not accepted (previous +/// behaviour: silently fail to find buffer). +/// +/// @param[in] tv Value to check. +/// +/// @return true if everything is OK, false otherwise. +bool tv_check_str_or_nr(const typval_T *const tv) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL +{ + switch (tv->v_type) { + case VAR_NUMBER: + case VAR_STRING: { + return true; + } + case VAR_FLOAT: { + emsgf(_("E805: Expected a Number or a String, Float found")); + return false; + } + case VAR_PARTIAL: + case VAR_FUNC: { + emsgf(_("E703: Expected a Number or a String, Funcref found")); + return false; + } + case VAR_LIST: { + emsgf(_("E745: Expected a Number or a String, List found")); + return false; + } + case VAR_DICT: { + emsgf(_("E728: Expected a Number or a String, Dictionary found")); + return false; + } + case VAR_SPECIAL: { + emsgf(_("E5300: Expected a Number or a String")); + return false; + } + case VAR_UNKNOWN: { + emsgf(_(e_intern2), "tv_check_str_or_nr(UNKNOWN)"); + return false; + } + } + assert(false); + return false; +} + +#define FUNC_ERROR "E703: Using a Funcref as a Number" + +static const char *const num_errors[] = { + [VAR_PARTIAL]=N_(FUNC_ERROR), + [VAR_FUNC]=N_(FUNC_ERROR), + [VAR_LIST]=N_("E745: Using a List as a Number"), + [VAR_DICT]=N_("E728: Using a Dictionary as a Number"), + [VAR_FLOAT]=N_("E805: Using a Float as a Number"), + [VAR_UNKNOWN]=N_("E685: using an invalid value as a Number"), +}; + +#undef FUNC_ERROR + +/// Check that given value is a number or can be converted to it +/// +/// Error messages are compatible with tv_get_number_chk() previously used for +/// the same purpose. +/// +/// @param[in] tv Value to check. +/// +/// @return true if everything is OK, false otherwise. +bool tv_check_num(const typval_T *const tv) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + switch (tv->v_type) { + case VAR_NUMBER: + case VAR_SPECIAL: + case VAR_STRING: { + return true; + } + case VAR_FUNC: + case VAR_PARTIAL: + case VAR_LIST: + case VAR_DICT: + case VAR_FLOAT: + case VAR_UNKNOWN: { + emsgf(_(num_errors[tv->v_type])); + return false; + } + } + assert(false); + return false; +} + +#define FUNC_ERROR "E729: using Funcref as a String" + +static const char *const str_errors[] = { + [VAR_PARTIAL]=N_(FUNC_ERROR), + [VAR_FUNC]=N_(FUNC_ERROR), + [VAR_LIST]=N_("E730: using List as a String"), + [VAR_DICT]=N_("E731: using Dictionary as a String"), + [VAR_FLOAT]=((const char *)e_float_as_string), + [VAR_UNKNOWN]=N_("E908: using an invalid value as a String"), +}; + +#undef FUNC_ERROR + +/// Check that given value is a string or can be converted to it +/// +/// Error messages are compatible with tv_get_string_chk() previously used for +/// the same purpose. +/// +/// @param[in] tv Value to check. +/// +/// @return true if everything is OK, false otherwise. +bool tv_check_str(const typval_T *const tv) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + switch (tv->v_type) { + case VAR_NUMBER: + case VAR_SPECIAL: + case VAR_STRING: { + return true; + } + case VAR_PARTIAL: + case VAR_FUNC: + case VAR_LIST: + case VAR_DICT: + case VAR_FLOAT: + case VAR_UNKNOWN: { + emsgf(_(str_errors[tv->v_type])); + return false; + } + } + assert(false); + return false; +} + +//{{{2 Get + +/// Get the number value of a VimL object +/// +/// @note Use tv_get_number_chk() if you need to determine whether there was an +/// error. +/// +/// @param[in] tv Object to get value from. +/// +/// @return Number value: vim_str2nr() output for VAR_STRING objects, value +/// for VAR_NUMBER objects, -1 for other types. +varnumber_T tv_get_number(const typval_T *const tv) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + bool error = false; + return tv_get_number_chk(tv, &error); +} + +/// Get the number value of a VimL object +/// +/// @param[in] tv Object to get value from. +/// @param[out] ret_error If type error occurred then `true` will be written +/// to this location. Otherwise it is not touched. +/// +/// @note Needs to be initialized to `false` to be +/// useful. +/// +/// @return Number value: vim_str2nr() output for VAR_STRING objects, value +/// for VAR_NUMBER objects, -1 (ret_error == NULL) or 0 (otherwise) for +/// other types. +varnumber_T tv_get_number_chk(const typval_T *const tv, bool *const ret_error) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1) +{ + switch (tv->v_type) { + case VAR_FUNC: + case VAR_PARTIAL: + case VAR_LIST: + case VAR_DICT: + case VAR_FLOAT: { + emsgf(_(num_errors[tv->v_type])); + break; + } + case VAR_NUMBER: { + return tv->vval.v_number; + } + case VAR_STRING: { + varnumber_T n = 0; + if (tv->vval.v_string != NULL) { + vim_str2nr(tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0); + } + return n; + } + case VAR_SPECIAL: { + switch (tv->vval.v_special) { + case kSpecialVarTrue: { + return 1; + } + case kSpecialVarFalse: + case kSpecialVarNull: { + return 0; + } + } + break; + } + case VAR_UNKNOWN: { + emsgf(_(e_intern2), "tv_get_number(UNKNOWN)"); + break; + } + } + if (ret_error != NULL) { + *ret_error = true; + } + return (ret_error == NULL ? -1 : 0); +} + +/// Get the line number from VimL object +/// +/// @param[in] tv Object to get value from. Is expected to be a number or +/// a special string like ".", "$", … (works with current buffer +/// only). +/// +/// @return Line number or -1 or 0. +linenr_T tv_get_lnum(const typval_T *const tv) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + linenr_T lnum = (linenr_T)tv_get_number_chk(tv, NULL); + if (lnum == 0) { // No valid number, try using same function as line() does. + int fnum; + pos_T *const fp = var2fpos(tv, true, &fnum); + if (fp != NULL) { + lnum = fp->lnum; + } + } + return lnum; +} + +/// Get the floating-point value of a VimL object +/// +/// Raises an error if object is not number or floating-point. +/// +/// @param[in] tv Object to get value of. +/// +/// @return Floating-point value of the variable or zero. +float_T tv_get_float(const typval_T *const tv) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + switch (tv->v_type) { + case VAR_NUMBER: { + return (float_T)(tv->vval.v_number); + } + case VAR_FLOAT: { + return tv->vval.v_float; + } + case VAR_PARTIAL: + case VAR_FUNC: { + emsgf(_("E891: Using a Funcref as a Float")); + break; + } + case VAR_STRING: { + emsgf(_("E892: Using a String as a Float")); + break; + } + case VAR_LIST: { + emsgf(_("E893: Using a List as a Float")); + break; + } + case VAR_DICT: { + emsgf(_("E894: Using a Dictionary as a Float")); + break; + } + case VAR_SPECIAL: { + emsgf(_("E907: Using a special value as a Float")); + break; + } + case VAR_UNKNOWN: { + emsgf(_(e_intern2), "tv_get_float(UNKNOWN)"); + break; + } + } + return 0; +} + +/// Get the string value of a VimL object +/// +/// @param[in] tv Object to get value of. +/// @param buf Buffer used to hold numbers and special variables converted to +/// string. When function encounters one of these stringified value +/// will be written to buf and buf will be returned. +/// +/// Buffer must have NUMBUFLEN size. +/// +/// @return Object value if it is VAR_STRING object, number converted to +/// a string for VAR_NUMBER, v: variable name for VAR_SPECIAL or NULL. +const char *tv_get_string_buf_chk(const typval_T *const tv, char *const buf) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + switch (tv->v_type) { + case VAR_NUMBER: { + snprintf(buf, NUMBUFLEN, "%" PRIdVARNUMBER, tv->vval.v_number); + return buf; + } + case VAR_STRING: { + if (tv->vval.v_string != NULL) { + return (const char *)tv->vval.v_string; + } + return ""; + } + case VAR_SPECIAL: { + STRCPY(buf, encode_special_var_names[tv->vval.v_special]); + return buf; + } + case VAR_PARTIAL: + case VAR_FUNC: + case VAR_LIST: + case VAR_DICT: + case VAR_FLOAT: + case VAR_UNKNOWN: { + emsgf(_(str_errors[tv->v_type])); + return false; + } + } + return NULL; +} + +/// Get the string value of a VimL object +/// +/// @warning For number and special values it uses a single, static buffer. It +/// may be used only once, next call to get_tv_string may reuse it. Use +/// tv_get_string_buf() if you need to use tv_get_string() output after +/// calling it again. +/// +/// @param[in] tv Object to get value of. +/// +/// @return Object value if it is VAR_STRING object, number converted to +/// a string for VAR_NUMBER, v: variable name for VAR_SPECIAL or NULL. +const char *tv_get_string_chk(const typval_T *const tv) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + static char mybuf[NUMBUFLEN]; + + return tv_get_string_buf_chk(tv, mybuf); +} + +/// Get the string value of a VimL object +/// +/// @warning For number and special values it uses a single, static buffer. It +/// may be used only once, next call to get_tv_string may reuse it. Use +/// tv_get_string_buf() if you need to use tv_get_string() output after +/// calling it again. +/// +/// @note tv_get_string_chk() and tv_get_string_buf_chk() are similar, but +/// return NULL on error. +/// +/// @param[in] tv Object to get value of. +/// +/// @return Object value if it is VAR_STRING object, number converted to +/// a string for VAR_NUMBER, v: variable name for VAR_SPECIAL or empty +/// string. +const char *tv_get_string(const typval_T *const tv) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT +{ + static char mybuf[NUMBUFLEN]; + return tv_get_string_buf((typval_T *)tv, mybuf); +} + +/// Get the string value of a VimL object +/// +/// @note tv_get_string_chk() and tv_get_string_buf_chk() are similar, but +/// return NULL on error. +/// +/// @param[in] tv Object to get value of. +/// @param buf Buffer used to hold numbers and special variables converted to +/// string. When function encounters one of these stringified value +/// will be written to buf and buf will be returned. +/// +/// Buffer must have NUMBUFLEN size. +/// +/// @return Object value if it is VAR_STRING object, number converted to +/// a string for VAR_NUMBER, v: variable name for VAR_SPECIAL or empty +/// string. +const char *tv_get_string_buf(const typval_T *const tv, char *const buf) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT +{ + const char *const res = (const char *)tv_get_string_buf_chk(tv, buf); + + return res != NULL ? res : ""; +} diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h new file mode 100644 index 0000000000..c44b85644d --- /dev/null +++ b/src/nvim/eval/typval.h @@ -0,0 +1,448 @@ +#ifndef NVIM_EVAL_TYPVAL_H +#define NVIM_EVAL_TYPVAL_H + +#include <inttypes.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <stdbool.h> + +#include "nvim/types.h" +#include "nvim/hashtab.h" +#include "nvim/garray.h" +#include "nvim/mbyte.h" +#include "nvim/func_attr.h" +#include "nvim/lib/queue.h" +#include "nvim/profile.h" // for proftime_T +#include "nvim/pos.h" // for linenr_T +#include "nvim/gettext.h" +#include "nvim/message.h" +#include "nvim/macros.h" + +/// Type used for VimL VAR_NUMBER values +typedef int64_t varnumber_T; +typedef uint64_t uvarnumber_T; + +/// Type used for VimL VAR_FLOAT values +typedef double float_T; + +/// Maximal possible value of varnumber_T variable +#define VARNUMBER_MAX INT64_MAX +#define UVARNUMBER_MAX UINT64_MAX + +/// Mimimal possible value of varnumber_T variable +#define VARNUMBER_MIN INT64_MIN + +/// %d printf format specifier for varnumber_T +#define PRIdVARNUMBER PRId64 + +typedef struct listvar_S list_T; +typedef struct dictvar_S dict_T; +typedef struct partial_S partial_T; + +typedef struct ufunc ufunc_T; + +typedef enum { + kCallbackNone = 0, + kCallbackFuncref, + kCallbackPartial, +} CallbackType; + +typedef struct { + union { + char_u *funcref; + partial_T *partial; + } data; + CallbackType type; +} Callback; +#define CALLBACK_NONE ((Callback){ .type = kCallbackNone }) + +/// Structure holding dictionary watcher +typedef struct dict_watcher { + Callback callback; + char *key_pattern; + size_t key_pattern_len; + QUEUE node; + bool busy; // prevent recursion if the dict is changed in the callback +} DictWatcher; + +/// Special variable values +typedef enum { + kSpecialVarFalse, ///< v:false + kSpecialVarTrue, ///< v:true + kSpecialVarNull, ///< v:null +} SpecialVarValue; + +/// Variable lock status for typval_T.v_lock +typedef enum { + VAR_UNLOCKED = 0, ///< Not locked. + VAR_LOCKED = 1, ///< User lock, can be unlocked. + VAR_FIXED = 2, ///< Locked forever. +} VarLockStatus; + +/// VimL variable types, for use in typval_T.v_type +typedef enum { + VAR_UNKNOWN = 0, ///< Unknown (unspecified) value. + VAR_NUMBER, ///< Number, .v_number is used. + VAR_STRING, ///< String, .v_string is used. + VAR_FUNC, ///< Function reference, .v_string is used as function name. + VAR_LIST, ///< List, .v_list is used. + VAR_DICT, ///< Dictionary, .v_dict is used. + VAR_FLOAT, ///< Floating-point value, .v_float is used. + VAR_SPECIAL, ///< Special value (true, false, null), .v_special + ///< is used. + VAR_PARTIAL, ///< Partial, .v_partial is used. +} VarType; + +/// Structure that holds an internal variable value +typedef struct { + VarType v_type; ///< Variable type. + VarLockStatus v_lock; ///< Variable lock status. + union typval_vval_union { + varnumber_T v_number; ///< Number, for VAR_NUMBER. + SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL. + float_T v_float; ///< Floating-point number, for VAR_FLOAT. + char_u *v_string; ///< String, for VAR_STRING and VAR_FUNC, can be NULL. + list_T *v_list; ///< List for VAR_LIST, can be NULL. + dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL. + partial_T *v_partial; ///< Closure: function with args. + } vval; ///< Actual value. +} typval_T; + +/// Values for (struct dictvar_S).dv_scope +typedef enum { + VAR_NO_SCOPE = 0, ///< Not a scope dictionary. + VAR_SCOPE = 1, ///< Scope dictionary which requires prefix (a:, v:, …). + VAR_DEF_SCOPE = 2, ///< Scope dictionary which may be accessed without prefix + ///< (l:, g:). +} ScopeType; + +/// Structure to hold an item of a list +typedef struct listitem_S listitem_T; + +struct listitem_S { + listitem_T *li_next; ///< Next item in list. + listitem_T *li_prev; ///< Previous item in list. + typval_T li_tv; ///< Item value. +}; + +/// Structure used by those that are using an item in a list +typedef struct listwatch_S listwatch_T; + +struct listwatch_S { + listitem_T *lw_item; ///< Item being watched. + listwatch_T *lw_next; ///< Next watcher. +}; + +/// Structure to hold info about a list +struct listvar_S { + listitem_T *lv_first; ///< First item, NULL if none. + listitem_T *lv_last; ///< Last item, NULL if none. + int lv_refcount; ///< Reference count. + int lv_len; ///< Number of items. + listwatch_T *lv_watch; ///< First watcher, NULL if none. + int lv_idx; ///< Index of a cached item, used for optimising repeated l[idx]. + listitem_T *lv_idx_item; ///< When not NULL item at index "lv_idx". + int lv_copyID; ///< ID used by deepcopy(). + list_T *lv_copylist; ///< Copied list used by deepcopy(). + VarLockStatus lv_lock; ///< Zero, VAR_LOCKED, VAR_FIXED. + list_T *lv_used_next; ///< next list in used lists list. + list_T *lv_used_prev; ///< Previous list in used lists list. +}; + +// Static list with 10 items. Use init_static_list() to initialize. +typedef struct { + list_T sl_list; // must be first + listitem_T sl_items[10]; +} staticList10_T; + +// Structure to hold an item of a Dictionary. +// Also used for a variable. +// The key is copied into "di_key" to avoid an extra alloc/free for it. +struct dictitem_S { + typval_T di_tv; ///< type and value of the variable + char_u di_flags; ///< flags (only used for variable) + char_u di_key[1]; ///< key (actually longer!) +}; + +#define TV_DICTITEM_STRUCT(KEY_LEN) \ + struct { \ + typval_T di_tv; /* Structure that holds scope dictionary itself. */ \ + uint8_t di_flags; /* Flags. */ \ + char_u di_key[KEY_LEN]; /* Key value. */ \ + } + +/// Structure to hold a scope dictionary +/// +/// @warning Must be compatible with dictitem_T. +/// +/// For use in find_var_in_ht to pretend that it found dictionary item when it +/// finds scope dictionary. +typedef TV_DICTITEM_STRUCT(1) ScopeDictDictItem; + +/// Structure to hold an item of a Dictionary +/// +/// @warning Must be compatible with ScopeDictDictItem. +/// +/// Also used for a variable. +typedef TV_DICTITEM_STRUCT() dictitem_T; + +/// Flags for dictitem_T.di_flags +typedef enum { + DI_FLAGS_RO = 1, ///< Read-only value + DI_FLAGS_RO_SBX = 2, ///< Value, read-only in the sandbox + DI_FLAGS_FIX = 4, ///< Fixed value: cannot be :unlet or remove()d. + DI_FLAGS_LOCK = 8, ///< Locked value. + DI_FLAGS_ALLOC = 16, ///< Separately allocated. +} DictItemFlags; + +/// Structure representing a Dictionary +struct dictvar_S { + VarLockStatus dv_lock; ///< Whole dictionary lock status. + ScopeType dv_scope; ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if + ///< dictionary represents a scope (i.e. g:, l: …). + int dv_refcount; ///< Reference count. + int dv_copyID; ///< ID used when recursivery traversing a value. + hashtab_T dv_hashtab; ///< Hashtab containing all items. + dict_T *dv_copydict; ///< Copied dict used by deepcopy(). + dict_T *dv_used_next; ///< Next dictionary in used dictionaries list. + dict_T *dv_used_prev; ///< Previous dictionary in used dictionaries list. + QUEUE watchers; ///< Dictionary key watchers set by user code. +}; + +/// Type used for script ID +typedef int scid_T; +/// Format argument for scid_T +#define PRIdSCID "d" + +// Structure to hold info for a function that is currently being executed. +typedef struct funccall_S funccall_T; + +/// Structure to hold info for a user function. +struct ufunc { + int uf_varargs; ///< variable nr of arguments + int uf_flags; + int uf_calls; ///< nr of active calls + bool uf_cleared; ///< func_clear() was already called + garray_T uf_args; ///< arguments + garray_T uf_lines; ///< function lines + int uf_profiling; ///< true when func is being profiled + // Profiling the function as a whole. + int uf_tm_count; ///< nr of calls + proftime_T uf_tm_total; ///< time spent in function + children + proftime_T uf_tm_self; ///< time spent in function itself + proftime_T uf_tm_children; ///< time spent in children this call + // Profiling the function per line. + int *uf_tml_count; ///< nr of times line was executed + proftime_T *uf_tml_total; ///< time spent in a line + children + proftime_T *uf_tml_self; ///< time spent in a line itself + proftime_T uf_tml_start; ///< start time for current line + proftime_T uf_tml_children; ///< time spent in children for this line + proftime_T uf_tml_wait; ///< start wait time for current line + int uf_tml_idx; ///< index of line being timed; -1 if none + int uf_tml_execed; ///< line being timed was executed + scid_T uf_script_ID; ///< ID of script where function was defined, + ///< 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[1]; ///< name of function (actually longer); can + ///< start with <SNR>123_ (<SNR> is K_SPECIAL + ///< KS_EXTRA KE_SNR) +}; + +/// Maximum number of function arguments +#define MAX_FUNC_ARGS 20 + +struct partial_S { + int pt_refcount; ///< Reference count. + char_u *pt_name; ///< Function name; when NULL use pt_func->name. + ufunc_T *pt_func; ///< Function pointer; when NULL lookup function with + ///< pt_name. + bool pt_auto; ///< When true the partial was created by using dict.member + ///< in handle_subscript(). + int pt_argc; ///< Number of arguments. + typval_T *pt_argv; ///< Arguments in allocated array. + dict_T *pt_dict; ///< Dict for "self". +}; + +/// Structure used for explicit stack while garbage collecting hash tables +typedef struct ht_stack_S { + hashtab_T *ht; + struct ht_stack_S *prev; +} ht_stack_T; + +/// Structure used for explicit stack while garbage collecting lists +typedef struct list_stack_S { + list_T *list; + struct list_stack_S *prev; +} list_stack_T; + +// In a hashtab item "hi_key" points to "di_key" in a dictitem. +// This avoids adding a pointer to the hashtab item. + +/// Convert a hashitem pointer to a dictitem pointer +#define TV_DICT_HI2DI(hi) \ + ((dictitem_T *)((hi)->hi_key - offsetof(dictitem_T, di_key))) + +static inline long tv_list_len(const list_T *const l) + REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; + +/// Get the number of items in a list +/// +/// @param[in] l List to check. +static inline long tv_list_len(const list_T *const l) +{ + if (l == NULL) { + return 0; + } + return l->lv_len; +} + +static inline long tv_dict_len(const dict_T *const d) + REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; + +/// Get the number of items in a Dictionary +/// +/// @param[in] d Dictionary to check. +static inline long tv_dict_len(const dict_T *const d) +{ + if (d == NULL) { + return 0L; + } + return (long)d->dv_hashtab.ht_used; +} + +static inline bool tv_dict_is_watched(const dict_T *const d) + REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; + +/// Check if dictionary is watched +/// +/// @param[in] d Dictionary to check. +/// +/// @return true if there is at least one watcher. +static inline bool tv_dict_is_watched(const dict_T *const d) +{ + return d && !QUEUE_EMPTY(&d->watchers); +} + +/// Initialize VimL object +/// +/// Initializes to unlocked VAR_UNKNOWN object. +/// +/// @param[out] tv Object to initialize. +static inline void tv_init(typval_T *const tv) +{ + if (tv != NULL) { + memset(tv, 0, sizeof(*tv)); + } +} + +#define TV_INITIAL_VALUE \ + ((typval_T) { \ + .v_type = VAR_UNKNOWN, \ + .v_lock = VAR_UNLOCKED, \ + }) + +/// Empty string +/// +/// Needed for hack which allows not allocating empty string and still not +/// crashing when freeing it. +extern const char *const tv_empty_string; + +/// Specifies that free_unref_items() function has (not) been entered +extern bool tv_in_free_unref_items; + +/// Iterate over a dictionary +/// +/// @param[in] d Dictionary to iterate over. +/// @param di Name of the variable with current dictitem_T entry. +/// @param code Cycle body. +#define TV_DICT_ITER(d, di, code) \ + HASHTAB_ITER(&(d)->dv_hashtab, di##hi_, { \ + { \ + dictitem_T *const di = TV_DICT_HI2DI(di##hi_); \ + { \ + code \ + } \ + } \ + }) + +static inline bool tv_get_float_chk(const typval_T *const tv, + float_T *const ret_f) + REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT; + +// FIXME circular dependency, cannot import message.h. +bool emsgf(const char *const fmt, ...); + +/// Get the float value +/// +/// Raises an error if object is not number or floating-point. +/// +/// @param[in] tv VimL object to get value from. +/// @param[out] ret_f Location where resulting float is stored. +/// +/// @return true in case of success, false if tv is not a number or float. +static inline bool tv_get_float_chk(const typval_T *const tv, + float_T *const ret_f) +{ + if (tv->v_type == VAR_FLOAT) { + *ret_f = tv->vval.v_float; + return true; + } + if (tv->v_type == VAR_NUMBER) { + *ret_f = (float_T)tv->vval.v_number; + return true; + } + emsgf(_("E808: Number or Float required")); + return false; +} + +static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q) + REAL_FATTR_NONNULL_ALL REAL_FATTR_NONNULL_RET REAL_FATTR_PURE + REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE; + +/// Compute the `DictWatcher` address from a QUEUE node. +/// +/// This only exists for .asan-blacklist (ASAN doesn't handle QUEUE_DATA pointer +/// arithmetic). +static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q) +{ + return QUEUE_DATA(q, DictWatcher, node); +} + +static inline bool tv_is_func(const typval_T tv) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_CONST; + +/// Check whether given typval_T contains a function +/// +/// That is, whether it contains VAR_FUNC or VAR_PARTIAL. +/// +/// @param[in] tv Typval to check. +/// +/// @return True if it is a function or a partial, false otherwise. +static inline bool tv_is_func(const typval_T tv) +{ + return tv.v_type == VAR_FUNC || tv.v_type == VAR_PARTIAL; +} + +/// Specify that argument needs to be translated +/// +/// Used for size_t length arguments to avoid calling gettext() and strlen() +/// unless needed. +#define TV_TRANSLATE (SIZE_MAX) + +/// Specify that argument is a NUL-terminated C string +/// +/// Used for size_t length arguments to avoid calling strlen() unless needed. +#define TV_CSTRING (SIZE_MAX - 1) + +#ifdef UNIT_TESTING +// Do not use enum constants, see commit message. +EXTERN const size_t kTVCstring INIT(= TV_CSTRING); +EXTERN const size_t kTVTranslate INIT(= TV_TRANSLATE); +#endif + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/typval.h.generated.h" +#endif +#endif // NVIM_EVAL_TYPVAL_H diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h index 365eb2dd77..a93ad2dbba 100644 --- a/src/nvim/eval/typval_encode.c.h +++ b/src/nvim/eval/typval_encode.c.h @@ -233,16 +233,12 @@ /// /// This name will only be used by one of the above macros which are defined by /// the caller. Functions defined here do not use first argument directly. -#ifndef NVIM_EVAL_TYPVAL_ENCODE_C_H -#define NVIM_EVAL_TYPVAL_ENCODE_C_H -#undef NVIM_EVAL_TYPVAL_ENCODE_C_H - #include <stddef.h> #include <inttypes.h> #include <assert.h> #include "nvim/lib/kvec.h" -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" #include "nvim/eval/encode.h" #include "nvim/func_attr.h" #include "nvim/eval/typval_encode.h" @@ -344,10 +340,11 @@ 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 : pt->pt_name)); + TYPVAL_ENCODE_CONV_FUNC_START(tv, (pt == NULL ? NULL : partial_name(pt))); _mp_push(*mpstack, ((MPConvStackVal) { .type = kMPConvPartial, .tv = tv, + .saved_copyID = copyID - 1, .data = { .p = { .stage = kMPConvPartialArgs, @@ -362,12 +359,15 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( TYPVAL_ENCODE_CONV_EMPTY_LIST(tv); break; } + const int saved_copyID = tv->vval.v_list->lv_copyID; _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(tv->vval.v_list, lv_copyID, copyID, kMPConvList); TYPVAL_ENCODE_CONV_LIST_START(tv, tv->vval.v_list->lv_len); + assert(saved_copyID != copyID && saved_copyID != copyID - 1); _mp_push(*mpstack, ((MPConvStackVal) { .type = kMPConvList, .tv = tv, + .saved_copyID = saved_copyID, .data = { .l = { .list = tv->vval.v_list, @@ -402,11 +402,11 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( const dictitem_T *val_di; if (TYPVAL_ENCODE_ALLOW_SPECIALS && tv->vval.v_dict->dv_hashtab.ht_used == 2 - && (type_di = dict_find((dict_T *)tv->vval.v_dict, - (char_u *)"_TYPE", -1)) != NULL + && (type_di = tv_dict_find((dict_T *)tv->vval.v_dict, + S_LEN("_TYPE"))) != NULL && type_di->di_tv.v_type == VAR_LIST - && (val_di = dict_find((dict_T *)tv->vval.v_dict, - (char_u *)"_VAL", -1)) != NULL) { + && (val_di = tv_dict_find((dict_T *)tv->vval.v_dict, + S_LEN("_VAL"))) != NULL) { size_t i; for (i = 0; i < ARRAY_SIZE(eval_msgpack_type_lists); i++) { if (type_di->di_tv.vval.v_list == eval_msgpack_type_lists[i]) { @@ -485,7 +485,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( } if (is_string) { TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len); - } else { + } else { // -V523 TYPVAL_ENCODE_CONV_STRING(tv, buf, len); } xfree(buf); @@ -495,14 +495,17 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( if (val_di->di_tv.v_type != VAR_LIST) { goto _convert_one_value_regular_dict; } + const int saved_copyID = val_di->di_tv.vval.v_list->lv_copyID; _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val_di->di_tv.vval.v_list, lv_copyID, copyID, kMPConvList); TYPVAL_ENCODE_CONV_LIST_START(tv, val_di->di_tv.vval.v_list->lv_len); + assert(saved_copyID != copyID && saved_copyID != copyID - 1); _mp_push(*mpstack, ((MPConvStackVal) { .tv = tv, .type = kMPConvList, + .saved_copyID = saved_copyID, .data = { .l = { .list = val_di->di_tv.vval.v_list, @@ -528,13 +531,16 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( goto _convert_one_value_regular_dict; } } + const int saved_copyID = val_di->di_tv.vval.v_list->lv_copyID; _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val_list, lv_copyID, copyID, kMPConvPairs); TYPVAL_ENCODE_CONV_DICT_START(tv, TYPVAL_ENCODE_NODICT_VAR, val_list->lv_len); + assert(saved_copyID != copyID && saved_copyID != copyID - 1); _mp_push(*mpstack, ((MPConvStackVal) { .tv = tv, .type = kMPConvPairs, + .saved_copyID = saved_copyID, .data = { .l = { .list = val_list, @@ -569,14 +575,17 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( } break; } -_convert_one_value_regular_dict: +_convert_one_value_regular_dict: {} + const int saved_copyID = tv->vval.v_dict->dv_copyID; _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(tv->vval.v_dict, dv_copyID, copyID, kMPConvDict); TYPVAL_ENCODE_CONV_DICT_START(tv, tv->vval.v_dict, tv->vval.v_dict->dv_hashtab.ht_used); + assert(saved_copyID != copyID && saved_copyID != copyID - 1); _mp_push(*mpstack, ((MPConvStackVal) { .tv = tv, .type = kMPConvDict, + .saved_copyID = saved_copyID, .data = { .d = { .dict = tv->vval.v_dict, @@ -598,7 +607,7 @@ _convert_one_value_regular_dict: typval_encode_stop_converting_one_item: return OK; // Prevent “unused label†warnings. - goto typval_encode_stop_converting_one_item; + goto typval_encode_stop_converting_one_item; // -V779 } TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE( @@ -638,7 +647,7 @@ typval_encode_stop_converting_one_item: case kMPConvDict: { if (!cur_mpsv->data.d.todo) { (void)_mp_pop(mpstack); - cur_mpsv->data.d.dict->dv_copyID = copyID - 1; + cur_mpsv->data.d.dict->dv_copyID = cur_mpsv->saved_copyID; TYPVAL_ENCODE_CONV_DICT_END(cur_mpsv->tv, *cur_mpsv->data.d.dictp); continue; } else if (cur_mpsv->data.d.todo @@ -649,7 +658,7 @@ typval_encode_stop_converting_one_item: while (HASHITEM_EMPTY(cur_mpsv->data.d.hi)) { cur_mpsv->data.d.hi++; } - dictitem_T *const di = HI2DI(cur_mpsv->data.d.hi); + dictitem_T *const di = TV_DICT_HI2DI(cur_mpsv->data.d.hi); cur_mpsv->data.d.todo--; cur_mpsv->data.d.hi++; TYPVAL_ENCODE_CONV_STR_STRING(NULL, &di->di_key[0], @@ -662,7 +671,7 @@ typval_encode_stop_converting_one_item: case kMPConvList: { if (cur_mpsv->data.l.li == NULL) { (void)_mp_pop(mpstack); - cur_mpsv->data.l.list->lv_copyID = copyID - 1; + cur_mpsv->data.l.list->lv_copyID = cur_mpsv->saved_copyID; TYPVAL_ENCODE_CONV_LIST_END(cur_mpsv->tv); continue; } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { @@ -675,7 +684,7 @@ typval_encode_stop_converting_one_item: case kMPConvPairs: { if (cur_mpsv->data.l.li == NULL) { (void)_mp_pop(mpstack); - cur_mpsv->data.l.list->lv_copyID = copyID - 1; + cur_mpsv->data.l.list->lv_copyID = cur_mpsv->saved_copyID; TYPVAL_ENCODE_CONV_DICT_END(cur_mpsv->tv, TYPVAL_ENCODE_NODICT_VAR); continue; } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { @@ -711,6 +720,7 @@ typval_encode_stop_converting_one_item: _mp_push(mpstack, ((MPConvStackVal) { .type = kMPConvPartialList, .tv = NULL, + .saved_copyID = copyID - 1, .data = { .a = { .arg = pt->pt_argv, @@ -731,6 +741,7 @@ typval_encode_stop_converting_one_item: TYPVAL_ENCODE_CONV_EMPTY_DICT(NULL, pt->pt_dict); continue; } + const int saved_copyID = dict->dv_copyID; const int te_csr_ret = _TYPVAL_ENCODE_CHECK_SELF_REFERENCE( TYPVAL_ENCODE_FIRST_ARG_NAME, dict, &dict->dv_copyID, &mpstack, copyID, kMPConvDict, @@ -744,9 +755,11 @@ typval_encode_stop_converting_one_item: } TYPVAL_ENCODE_CONV_DICT_START(NULL, pt->pt_dict, dict->dv_hashtab.ht_used); + assert(saved_copyID != copyID && saved_copyID != copyID - 1); _mp_push(mpstack, ((MPConvStackVal) { .type = kMPConvDict, .tv = NULL, + .saved_copyID = saved_copyID, .data = { .d = { .dict = dict, @@ -797,6 +810,5 @@ encode_vim_to__error_ret: _mp_destroy(mpstack); return FAIL; // Prevent “unused label†warnings. - goto typval_encode_stop_converting_one_item; + goto typval_encode_stop_converting_one_item; // -V779 } -#endif // NVIM_EVAL_TYPVAL_ENCODE_C_H diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h index ba325b8f55..3475f6d8b3 100644 --- a/src/nvim/eval/typval_encode.h +++ b/src/nvim/eval/typval_encode.h @@ -11,7 +11,7 @@ #include <assert.h> #include "nvim/lib/kvec.h" -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" #include "nvim/func_attr.h" /// Type of the stack entry @@ -34,6 +34,7 @@ typedef enum { typedef struct { MPConvStackValType type; ///< Type of the stack entry. typval_T *tv; ///< Currently converted typval_T. + int saved_copyID; ///< copyID item used to have. union { struct { dict_T *dict; ///< Currently converted dictionary. diff --git a/src/nvim/eval_defs.h b/src/nvim/eval_defs.h deleted file mode 100644 index f478d19ca1..0000000000 --- a/src/nvim/eval_defs.h +++ /dev/null @@ -1,198 +0,0 @@ -#ifndef NVIM_EVAL_DEFS_H -#define NVIM_EVAL_DEFS_H - -#include <limits.h> -#include <stddef.h> - -#include "nvim/hashtab.h" -#include "nvim/lib/queue.h" - -typedef int varnumber_T; -typedef double float_T; - -#define VARNUMBER_MAX INT_MAX -#define VARNUMBER_MIN INT_MIN - -typedef struct listvar_S list_T; -typedef struct dictvar_S dict_T; -typedef struct partial_S partial_T; - -/// Special variable values -typedef enum { - kSpecialVarFalse, ///< v:false - kSpecialVarTrue, ///< v:true - kSpecialVarNull, ///< v:null -} SpecialVarValue; - -/// Variable lock status for typval_T.v_lock -typedef enum { - VAR_UNLOCKED = 0, ///< Not locked. - VAR_LOCKED, ///< User lock, can be unlocked. - VAR_FIXED, ///< Locked forever. -} VarLockStatus; - -/// VimL variable types, for use in typval_T.v_type -typedef enum { - VAR_UNKNOWN = 0, ///< Unknown (unspecified) value. - VAR_NUMBER, ///< Number, .v_number is used. - VAR_STRING, ///< String, .v_string is used. - VAR_FUNC, ///< Function reference, .v_string is used as function name. - VAR_LIST, ///< List, .v_list is used. - VAR_DICT, ///< Dictionary, .v_dict is used. - VAR_FLOAT, ///< Floating-point value, .v_float is used. - VAR_SPECIAL, ///< Special value (true, false, null), .v_special - ///< is used. - VAR_PARTIAL, ///< Partial, .v_partial is used. -} VarType; - -/// Structure that holds an internal variable value -typedef struct { - VarType v_type; ///< Variable type. - VarLockStatus v_lock; ///< Variable lock status. - union { - varnumber_T v_number; ///< Number, for VAR_NUMBER. - SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL. - float_T v_float; ///< Floating-point number, for VAR_FLOAT. - char_u *v_string; ///< String, for VAR_STRING and VAR_FUNC, can be NULL. - list_T *v_list; ///< List for VAR_LIST, can be NULL. - dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL. - partial_T *v_partial; ///< Closure: function with args. - } vval; ///< Actual value. -} typval_T; - -/* Values for "dv_scope". */ -#define VAR_SCOPE 1 /* a:, v:, s:, etc. scope dictionaries */ -#define VAR_DEF_SCOPE 2 /* l:, g: scope dictionaries: here funcrefs are not - allowed to mask existing functions */ - -/* - * Structure to hold an item of a list: an internal variable without a name. - */ -typedef struct listitem_S listitem_T; - -struct listitem_S { - listitem_T *li_next; /* next item in list */ - listitem_T *li_prev; /* previous item in list */ - typval_T li_tv; /* type and value of the variable */ -}; - -/* - * Struct used by those that are using an item in a list. - */ -typedef struct listwatch_S listwatch_T; - -struct listwatch_S { - listitem_T *lw_item; /* item being watched */ - listwatch_T *lw_next; /* next watcher */ -}; - -/* - * Structure to hold info about a list. - */ -struct listvar_S { - listitem_T *lv_first; /* first item, NULL if none */ - listitem_T *lv_last; /* last item, NULL if none */ - int lv_refcount; /* reference count */ - int lv_len; /* number of items */ - listwatch_T *lv_watch; /* first watcher, NULL if none */ - int lv_idx; /* cached index of an item */ - listitem_T *lv_idx_item; /* when not NULL item at index "lv_idx" */ - int lv_copyID; /* ID used by deepcopy() */ - list_T *lv_copylist; /* copied list used by deepcopy() */ - char lv_lock; /* zero, VAR_LOCKED, VAR_FIXED */ - list_T *lv_used_next; /* next list in used lists list */ - list_T *lv_used_prev; /* previous list in used lists list */ -}; - -/* - * Structure to hold an item of a Dictionary. - * Also used for a variable. - * The key is copied into "di_key" to avoid an extra alloc/free for it. - */ -struct dictitem_S { - typval_T di_tv; /* type and value of the variable */ - char_u di_flags; /* flags (only used for variable) */ - char_u di_key[1]; /* key (actually longer!) */ -}; - -typedef struct dictitem_S dictitem_T; - -/// A dictitem with a 16 character key (plus NUL) -struct dictitem16_S { - typval_T di_tv; ///< type and value of the variable - char_u di_flags; ///< flags (only used for variable) - char_u di_key[17]; ///< key -}; - -typedef struct dictitem16_S dictitem16_T; - - -#define DI_FLAGS_RO 1 // "di_flags" value: read-only variable -#define DI_FLAGS_RO_SBX 2 // "di_flags" value: read-only in the sandbox -#define DI_FLAGS_FIX 4 // "di_flags" value: fixed: no :unlet or remove() -#define DI_FLAGS_LOCK 8 // "di_flags" value: locked variable -#define DI_FLAGS_ALLOC 16 // "di_flags" value: separately allocated - -/// Structure representing a Dictionary -struct dictvar_S { - VarLockStatus dv_lock; ///< Whole dictionary lock status. - char dv_scope; ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if - ///< dictionary represents a scope (i.e. g:, l: …). - int dv_refcount; ///< Reference count. - int dv_copyID; ///< ID used when recursivery traversing a value. - hashtab_T dv_hashtab; ///< Hashtab containing all items. - dict_T *dv_copydict; ///< Copied dict used by deepcopy(). - dict_T *dv_used_next; ///< Next dictionary in used dictionaries list. - dict_T *dv_used_prev; ///< Previous dictionary in used dictionaries list. - QUEUE watchers; ///< Dictionary key watchers set by user code. -}; - -struct partial_S { - int pt_refcount; ///< Reference count. - char_u *pt_name; ///< Function name. - bool pt_auto; ///< when true the partial was created for using - ///< dict.member in handle_subscript(). - int pt_argc; ///< Number of arguments. - typval_T *pt_argv; ///< Arguments in allocated array. - dict_T *pt_dict; ///< Dict for "self". -}; - -// structure used for explicit stack while garbage collecting hash tables -typedef struct ht_stack_S { - hashtab_T *ht; - struct ht_stack_S *prev; -} ht_stack_T; - -// structure used for explicit stack while garbage collecting lists -typedef struct list_stack_S { - list_T *list; - struct list_stack_S *prev; -} list_stack_T; - -// In a hashtab item "hi_key" points to "di_key" in a dictitem. -// This avoids adding a pointer to the hashtab item. - -/// Convert a dictitem pointer to a hashitem key pointer -#define DI2HIKEY(di) ((di)->di_key) - -/// Convert a hashitem key pointer to a dictitem pointer -#define HIKEY2DI(p) ((dictitem_T *)(p - offsetof(dictitem_T, di_key))) - -/// Convert a hashitem value pointer to a dictitem pointer -#define HIVAL2DI(p) \ - ((dictitem_T *)(((char *)p) - offsetof(dictitem_T, di_tv))) - -/// Convert a hashitem pointer to a dictitem pointer -#define HI2DI(hi) HIKEY2DI((hi)->hi_key) - -/// Type of assert_* check being performed -typedef enum -{ - ASSERT_EQUAL, - ASSERT_NOTEQUAL, - ASSERT_MATCH, - ASSERT_NOTMATCH, - ASSERT_OTHER, -} assert_type_T; - -#endif // NVIM_EVAL_DEFS_H diff --git a/src/nvim/event/defs.h b/src/nvim/event/defs.h index e5335d9f25..cc875d74b9 100644 --- a/src/nvim/event/defs.h +++ b/src/nvim/event/defs.h @@ -8,16 +8,14 @@ typedef void (*argv_callback)(void **argv); typedef struct message { - int priority; argv_callback handler; void *argv[EVENT_HANDLER_MAX_ARGC]; } Event; typedef void(*event_scheduler)(Event event, void *data); -#define VA_EVENT_INIT(event, p, h, a) \ +#define VA_EVENT_INIT(event, h, a) \ do { \ assert(a <= EVENT_HANDLER_MAX_ARGC); \ - (event)->priority = p; \ (event)->handler = h; \ if (a) { \ va_list args; \ @@ -29,11 +27,11 @@ typedef void(*event_scheduler)(Event event, void *data); } \ } while (0) -static inline Event event_create(int priority, argv_callback cb, int argc, ...) +static inline Event event_create(argv_callback cb, int argc, ...) { assert(argc <= EVENT_HANDLER_MAX_ARGC); Event event; - VA_EVENT_INIT(&event, priority, cb, argc); + VA_EVENT_INIT(&event, cb, argc); return event; } diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c index a68badcc8f..f6a567a520 100644 --- a/src/nvim/event/libuv_process.c +++ b/src/nvim/event/libuv_process.c @@ -1,3 +1,6 @@ +// 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 <uv.h> @@ -8,22 +11,31 @@ #include "nvim/event/process.h" #include "nvim/event/libuv_process.h" #include "nvim/log.h" +#include "nvim/macros.h" +#include "nvim/os/os.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "event/libuv_process.c.generated.h" #endif -bool libuv_process_spawn(LibuvProcess *uvproc) +/// @returns zero on success, or negative error code +int libuv_process_spawn(LibuvProcess *uvproc) FUNC_ATTR_NONNULL_ALL { Process *proc = (Process *)uvproc; uvproc->uvopts.file = proc->argv[0]; uvproc->uvopts.args = proc->argv; - uvproc->uvopts.flags = UV_PROCESS_WINDOWS_HIDE - | UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS; + uvproc->uvopts.flags = UV_PROCESS_WINDOWS_HIDE; if (proc->detach) { uvproc->uvopts.flags |= UV_PROCESS_DETACHED; } +#ifdef WIN32 + // libuv collapses the argv to a CommandLineToArgvW()-style string. cmd.exe + // expects a different syntax (must be prepared by the caller before now). + if (os_shell_is_cmdexe(proc->argv[0])) { + uvproc->uvopts.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS; + } +#endif uvproc->uvopts.exit_cb = exit_cb; uvproc->uvopts.cwd = proc->cwd; uvproc->uvopts.env = NULL; @@ -36,27 +48,30 @@ bool libuv_process_spawn(LibuvProcess *uvproc) if (proc->in) { uvproc->uvstdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; - uvproc->uvstdio[0].data.stream = (uv_stream_t *)&proc->in->uv.pipe; + uvproc->uvstdio[0].data.stream = STRUCT_CAST(uv_stream_t, + &proc->in->uv.pipe); } if (proc->out) { uvproc->uvstdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; - uvproc->uvstdio[1].data.stream = (uv_stream_t *)&proc->out->uv.pipe; + uvproc->uvstdio[1].data.stream = STRUCT_CAST(uv_stream_t, + &proc->out->uv.pipe); } if (proc->err) { uvproc->uvstdio[2].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; - uvproc->uvstdio[2].data.stream = (uv_stream_t *)&proc->err->uv.pipe; + uvproc->uvstdio[2].data.stream = STRUCT_CAST(uv_stream_t, + &proc->err->uv.pipe); } int status; if ((status = uv_spawn(&proc->loop->uv, &uvproc->uv, &uvproc->uvopts))) { ELOG("uv_spawn failed: %s", uv_strerror(status)); - return false; + return status; } proc->pid = uvproc->uv.pid; - return true; + return status; } void libuv_process_close(LibuvProcess *uvproc) diff --git a/src/nvim/event/libuv_process.h b/src/nvim/event/libuv_process.h index aaaa896e10..1132ce79ca 100644 --- a/src/nvim/event/libuv_process.h +++ b/src/nvim/event/libuv_process.h @@ -14,8 +14,9 @@ typedef struct libuv_process { static inline LibuvProcess libuv_process_init(Loop *loop, void *data) { - LibuvProcess rv; - rv.process = process_init(loop, kProcessTypeUv, data); + LibuvProcess rv = { + .process = process_init(loop, kProcessTypeUv, data) + }; return rv; } diff --git a/src/nvim/event/loop.c b/src/nvim/event/loop.c index 0e1775d01b..25701a1621 100644 --- a/src/nvim/event/loop.c +++ b/src/nvim/event/loop.c @@ -1,3 +1,6 @@ +// 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 <stdarg.h> #include <stdint.h> @@ -5,6 +8,7 @@ #include "nvim/event/loop.h" #include "nvim/event/process.h" +#include "nvim/log.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "event/loop.c.generated.h" @@ -41,8 +45,7 @@ void loop_poll_events(Loop *loop, int ms) // we do not block indefinitely for I/O. uv_timer_start(&loop->poll_timer, timer_cb, (uint64_t)ms, (uint64_t)ms); } else if (ms == 0) { - // For ms == 0, we need to do a non-blocking event poll by - // setting the run mode to UV_RUN_NOWAIT. + // For ms == 0, do a non-blocking event poll. mode = UV_RUN_NOWAIT; } @@ -76,20 +79,34 @@ void loop_on_put(MultiQueue *queue, void *data) uv_stop(&loop->uv); } -void loop_close(Loop *loop, bool wait) +/// @returns false if the loop could not be closed gracefully +bool loop_close(Loop *loop, bool wait) { + bool rv = true; uv_mutex_destroy(&loop->mutex); uv_close((uv_handle_t *)&loop->children_watcher, NULL); uv_close((uv_handle_t *)&loop->children_kill_timer, NULL); uv_close((uv_handle_t *)&loop->poll_timer, NULL); uv_close((uv_handle_t *)&loop->async, NULL); - do { + uint64_t start = wait ? os_hrtime() : 0; + while (true) { uv_run(&loop->uv, wait ? UV_RUN_DEFAULT : UV_RUN_NOWAIT); - } while (uv_loop_close(&loop->uv) && wait); + if (!uv_loop_close(&loop->uv) || !wait) { + break; + } + if (os_hrtime() - start >= 2 * 1000000000) { + // Some libuv resource was not correctly deref'd. Log and bail. + rv = false; + ELOG("uv_loop_close() hang?"); + log_uv_handles(&loop->uv); + break; + } + } multiqueue_free(loop->fast_events); multiqueue_free(loop->thread_events); multiqueue_free(loop->events); kl_destroy(WatcherPtr, loop->children); + return rv; } void loop_purge(Loop *loop) diff --git a/src/nvim/event/multiqueue.c b/src/nvim/event/multiqueue.c index 79b4dd9458..ef9f3f1870 100644 --- a/src/nvim/event/multiqueue.c +++ b/src/nvim/event/multiqueue.c @@ -1,3 +1,6 @@ +// 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 + // Multi-level queue for selective async event processing. // Not threadsafe; access must be synchronized externally. // @@ -123,6 +126,7 @@ void multiqueue_free(MultiQueue *this) xfree(this); } +/// Removes the next item and returns its Event. Event multiqueue_get(MultiQueue *this) { return multiqueue_empty(this) ? NILEVENT : multiqueue_remove(this); @@ -141,7 +145,7 @@ void multiqueue_process_events(MultiQueue *this) { assert(this); while (!multiqueue_empty(this)) { - Event event = multiqueue_get(this); + Event event = multiqueue_remove(this); if (event.handler) { event.handler(event.argv); } @@ -175,36 +179,48 @@ size_t multiqueue_size(MultiQueue *this) return this->size; } -static Event multiqueue_remove(MultiQueue *this) +/// Gets an Event from an item. +/// +/// @param remove Remove the node from its queue, and free it. +static Event multiqueueitem_get_event(MultiQueueItem *item, bool remove) { - assert(!multiqueue_empty(this)); - QUEUE *h = QUEUE_HEAD(&this->headtail); - QUEUE_REMOVE(h); - MultiQueueItem *item = multiqueue_node_data(h); - Event rv; - + assert(item != NULL); + Event ev; if (item->link) { - assert(!this->parent); - // remove the next node in the linked queue + // get the next node in the linked queue MultiQueue *linked = item->data.queue; assert(!multiqueue_empty(linked)); MultiQueueItem *child = multiqueue_node_data(QUEUE_HEAD(&linked->headtail)); - QUEUE_REMOVE(&child->node); - rv = child->data.item.event; - xfree(child); + ev = child->data.item.event; + // remove the child node + if (remove) { + QUEUE_REMOVE(&child->node); + xfree(child); + } } else { - if (this->parent) { - // remove the corresponding link node in the parent queue + // remove the corresponding link node in the parent queue + if (remove && item->data.item.parent_item) { QUEUE_REMOVE(&item->data.item.parent_item->node); xfree(item->data.item.parent_item); + item->data.item.parent_item = NULL; } - rv = item->data.item.event; + ev = item->data.item.event; } + return ev; +} +static Event multiqueue_remove(MultiQueue *this) +{ + assert(!multiqueue_empty(this)); + QUEUE *h = QUEUE_HEAD(&this->headtail); + QUEUE_REMOVE(h); + MultiQueueItem *item = multiqueue_node_data(h); + assert(!item->link || !this->parent); // Only a parent queue has link-nodes + Event ev = multiqueueitem_get_event(item, true); this->size--; xfree(item); - return rv; + return ev; } static void multiqueue_push(MultiQueue *this, Event event) @@ -212,6 +228,7 @@ static void multiqueue_push(MultiQueue *this, Event event) MultiQueueItem *item = xmalloc(sizeof(MultiQueueItem)); item->link = false; item->data.item.event = event; + item->data.item.parent_item = NULL; QUEUE_INSERT_TAIL(&this->headtail, &item->node); if (this->parent) { // push link node to the parent queue diff --git a/src/nvim/event/multiqueue.h b/src/nvim/event/multiqueue.h index def6b95a10..a688107665 100644 --- a/src/nvim/event/multiqueue.h +++ b/src/nvim/event/multiqueue.h @@ -10,7 +10,7 @@ typedef struct multiqueue MultiQueue; typedef void (*put_callback)(MultiQueue *multiq, void *data); #define multiqueue_put(q, h, ...) \ - multiqueue_put_event(q, event_create(1, h, __VA_ARGS__)); + multiqueue_put_event(q, event_create(h, __VA_ARGS__)); #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index dc7886469b..8371d3cd48 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -1,3 +1,6 @@ +// 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 <stdlib.h> @@ -11,15 +14,16 @@ #include "nvim/event/libuv_process.h" #include "nvim/os/pty_process.h" #include "nvim/globals.h" +#include "nvim/macros.h" #include "nvim/log.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "event/process.c.generated.h" #endif -// Time (ns) for a process to exit cleanly before we send TERM/KILL. -#define TERM_TIMEOUT 1000000000 -#define KILL_TIMEOUT (TERM_TIMEOUT * 2) +// Time for a process to exit cleanly before we send KILL. +// For pty processes SIGTERM is sent first (in case SIGHUP was not enough). +#define KILL_TIMEOUT_MS 2000 #define CLOSE_PROC_STREAM(proc, stream) \ do { \ @@ -30,7 +34,8 @@ static bool process_is_tearing_down = false; -bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL +/// @returns zero on success, or negative error code +int process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL { if (proc->in) { uv_pipe_init(&proc->loop->uv, &proc->in->uv.pipe, 0); @@ -44,19 +49,19 @@ bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL uv_pipe_init(&proc->loop->uv, &proc->err->uv.pipe, 0); } - bool success; + int status; switch (proc->type) { case kProcessTypeUv: - success = libuv_process_spawn((LibuvProcess *)proc); + status = libuv_process_spawn((LibuvProcess *)proc); break; case kProcessTypePty: - success = pty_process_spawn((PtyProcess *)proc); + status = pty_process_spawn((PtyProcess *)proc); break; default: abort(); } - if (!success) { + if (status) { if (proc->in) { uv_close((uv_handle_t *)&proc->in->uv.pipe, NULL); } @@ -74,11 +79,12 @@ bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL } shell_free_argv(proc->argv); proc->status = -1; - return false; + return status; } if (proc->in) { - stream_init(NULL, proc->in, -1, (uv_stream_t *)&proc->in->uv.pipe); + stream_init(NULL, proc->in, -1, + STRUCT_CAST(uv_stream_t, &proc->in->uv.pipe)); proc->in->events = proc->events; proc->in->internal_data = proc; proc->in->internal_close_cb = on_process_stream_close; @@ -86,7 +92,8 @@ bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL } if (proc->out) { - stream_init(NULL, proc->out, -1, (uv_stream_t *)&proc->out->uv.pipe); + stream_init(NULL, proc->out, -1, + STRUCT_CAST(uv_stream_t, &proc->out->uv.pipe)); proc->out->events = proc->events; proc->out->internal_data = proc; proc->out->internal_close_cb = on_process_stream_close; @@ -94,7 +101,8 @@ bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL } if (proc->err) { - stream_init(NULL, proc->err, -1, (uv_stream_t *)&proc->err->uv.pipe); + stream_init(NULL, proc->err, -1, + STRUCT_CAST(uv_stream_t, &proc->err->uv.pipe)); proc->err->events = proc->events; proc->err->internal_data = proc; proc->err->internal_close_cb = on_process_stream_close; @@ -105,7 +113,7 @@ bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL proc->internal_close_cb = decref; proc->refcount++; kl_push(WatcherPtr, proc->loop->children, proc); - return true; + return 0; } void process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL @@ -117,8 +125,6 @@ void process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL // Close handles to process without killing it. CREATE_EVENT(loop->events, process_close_handles, 1, proc); } else { - uv_kill(proc->pid, SIGTERM); - proc->term_sent = true; process_stop(proc); } } @@ -155,19 +161,16 @@ void process_close_err(Process *proc) FUNC_ATTR_NONNULL_ALL /// Synchronously wait for a process to finish /// -/// @param process The Process instance -/// @param ms Number of milliseconds to wait, 0 for not waiting, -1 for -/// waiting until the process quits. -/// @return returns the status code of the exited process. -1 if the process is -/// still running and the `timeout` has expired. Note that this is -/// indistinguishable from the process returning -1 by itself. Which -/// is possible on some OS. Returns -2 if an user has interruped the -/// wait. +/// @param process Process instance +/// @param ms Time in milliseconds to wait for the process. +/// 0 for no wait. -1 to wait until the process quits. +/// @return Exit code of the process. +/// -1 if the timeout expired while the process is still running. +/// -2 if the user interruped the wait. int process_wait(Process *proc, int ms, MultiQueue *events) FUNC_ATTR_NONNULL_ARG(1) { - // The default status is -1, which represents a timeout - int status = -1; + int status = -1; // default bool interrupted = false; if (!proc->refcount) { status = proc->status; @@ -179,8 +182,8 @@ int process_wait(Process *proc, int ms, MultiQueue *events) events = proc->events; } - // Increase refcount to stop the exit callback from being called(and possibly - // being freed) before we have a chance to get the status. + // Increase refcount to stop the exit callback from being called (and possibly + // freed) before we have a chance to get the status. proc->refcount++; LOOP_PROCESS_EVENTS_UNTIL(proc->loop, events, ms, // Until... @@ -230,9 +233,10 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL switch (proc->type) { case kProcessTypeUv: // Close the process's stdin. If the process doesn't close its own - // stdout/stderr, they will be closed when it exits(possibly due to being - // terminated after a timeout) + // stdout/stderr, they will be closed when it exits (voluntarily or not). process_close_in(proc); + ILOG("Sending SIGTERM to pid %d", proc->pid); + uv_kill(proc->pid, SIGTERM); break; case kProcessTypePty: // close all streams for pty processes to send SIGHUP to the process @@ -246,9 +250,10 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL Loop *loop = proc->loop; if (!loop->children_stop_requests++) { // When there's at least one stop request pending, start a timer that - // will periodically check if a signal should be send to a to the job - DLOG("Starting job kill timer"); - uv_timer_start(&loop->children_kill_timer, children_kill_cb, 100, 100); + // will periodically check if a signal should be send to the job. + ILOG("Starting job kill timer"); + uv_timer_start(&loop->children_kill_timer, children_kill_cb, + KILL_TIMEOUT_MS, KILL_TIMEOUT_MS); } } @@ -264,15 +269,15 @@ static void children_kill_cb(uv_timer_t *handle) if (!proc->stopped_time) { continue; } - uint64_t elapsed = now - proc->stopped_time; - - if (!proc->term_sent && elapsed >= TERM_TIMEOUT) { - ILOG("Sending SIGTERM to pid %d", proc->pid); - uv_kill(proc->pid, SIGTERM); - proc->term_sent = true; - } else if (elapsed >= KILL_TIMEOUT) { - ILOG("Sending SIGKILL to pid %d", proc->pid); - uv_kill(proc->pid, SIGKILL); + uint64_t elapsed = (now - proc->stopped_time) / 1000000 + 1; + + if (elapsed >= KILL_TIMEOUT_MS) { + int sig = proc->type == kProcessTypePty && elapsed < KILL_TIMEOUT_MS * 2 + ? SIGTERM + : SIGKILL; + ILOG("Sending %s to pid %d", sig == SIGTERM ? "SIGTERM" : "SIGKILL", + proc->pid); + uv_kill(proc->pid, sig); } } } diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h index 5cbf7f9ce7..5c00e8e7ec 100644 --- a/src/nvim/event/process.h +++ b/src/nvim/event/process.h @@ -21,12 +21,12 @@ struct process { int pid, status, refcount; // set to the hrtime of when process_stop was called for the process. uint64_t stopped_time; - char *cwd; + const char *cwd; char **argv; Stream *in, *out, *err; process_exit_cb cb; internal_process_cb internal_exit_cb, internal_close_cb; - bool closed, term_sent, detach; + bool closed, detach; MultiQueue *events; }; @@ -48,7 +48,6 @@ static inline Process process_init(Loop *loop, ProcessType type, void *data) .err = NULL, .cb = NULL, .closed = false, - .term_sent = false, .internal_close_cb = NULL, .internal_exit_cb = NULL, .detach = false diff --git a/src/nvim/event/rstream.c b/src/nvim/event/rstream.c index 92efc9fa2e..2c4db08b30 100644 --- a/src/nvim/event/rstream.c +++ b/src/nvim/event/rstream.c @@ -1,3 +1,6 @@ +// 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 <stdbool.h> @@ -89,7 +92,10 @@ static void on_rbuffer_nonfull(RBuffer *buf, void *data) static void alloc_cb(uv_handle_t *handle, size_t suggested, uv_buf_t *buf) { Stream *stream = handle->data; - buf->base = rbuffer_write_ptr(stream->buffer, &buf->len); + // `uv_buf_t.len` happens to have different size on Windows. + size_t write_count; + buf->base = rbuffer_write_ptr(stream->buffer, &write_count); + buf->len = write_count; } // Callback invoked by libuv after it copies the data into the buffer provided @@ -112,7 +118,7 @@ static void read_cb(uv_stream_t *uvstream, ssize_t cnt, const uv_buf_t *buf) // to `alloc_cb` will return the same unused pointer(`rbuffer_produced` // won't be called) && cnt != 0) { - DLOG("Closing Stream (%p): %s (%s)", stream, + DLOG("closing Stream: %p: %s (%s)", stream, uv_err_name((int)cnt), os_strerror((int)cnt)); // Read error or EOF, either way stop the stream and invoke the callback // with eof == true @@ -136,7 +142,10 @@ static void fread_idle_cb(uv_idle_t *handle) uv_fs_t req; Stream *stream = handle->data; - stream->uvbuf.base = rbuffer_write_ptr(stream->buffer, &stream->uvbuf.len); + // `uv_buf_t.len` happens to have different size on Windows. + size_t write_count; + stream->uvbuf.base = rbuffer_write_ptr(stream->buffer, &write_count); + stream->uvbuf.len = write_count; // the offset argument to uv_fs_read is int64_t, could someone really try // to read more than 9 quintillion (9e18) bytes? diff --git a/src/nvim/event/signal.c b/src/nvim/event/signal.c index 11ce15a882..fec46da4ff 100644 --- a/src/nvim/event/signal.c +++ b/src/nvim/event/signal.c @@ -1,3 +1,6 @@ +// 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 <uv.h> #include "nvim/event/loop.h" diff --git a/src/nvim/event/socket.c b/src/nvim/event/socket.c index 8f9327f3d4..6f45b09fce 100644 --- a/src/nvim/event/socket.c +++ b/src/nvim/event/socket.c @@ -1,3 +1,6 @@ +// 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> @@ -12,99 +15,123 @@ #include "nvim/vim.h" #include "nvim/strings.h" #include "nvim/path.h" +#include "nvim/main.h" #include "nvim/memory.h" +#include "nvim/macros.h" +#include "nvim/charset.h" +#include "nvim/log.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "event/socket.c.generated.h" #endif -#define NVIM_DEFAULT_TCP_PORT 7450 - -void socket_watcher_init(Loop *loop, SocketWatcher *watcher, - const char *endpoint, void *data) - FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_NONNULL_ARG(3) +int socket_watcher_init(Loop *loop, SocketWatcher *watcher, + const char *endpoint) + FUNC_ATTR_NONNULL_ALL { - // Trim to `ADDRESS_MAX_SIZE` - if (xstrlcpy(watcher->addr, endpoint, sizeof(watcher->addr)) - >= sizeof(watcher->addr)) { - // TODO(aktau): since this is not what the user wanted, perhaps we - // should return an error here - WLOG("Address was too long, truncated to %s", watcher->addr); - } - - bool tcp = true; - char ip[16], *ip_end = xstrchrnul(watcher->addr, ':'); + xstrlcpy(watcher->addr, endpoint, sizeof(watcher->addr)); + char *addr = watcher->addr; + char *host_end = strrchr(addr, ':'); - // (ip_end - addr) is always > 0, so convert to size_t - size_t addr_len = (size_t)(ip_end - watcher->addr); + if (host_end && addr != host_end) { + // Split user specified address into two strings, addr(hostname) and port. + // The port part in watcher->addr will be updated later. + *host_end = '\0'; + char *port = host_end + 1; + intmax_t iport; - if (addr_len > sizeof(ip) - 1) { - // Maximum length of an IPv4 address buffer is 15 (eg: 255.255.255.255) - addr_len = sizeof(ip) - 1; - } + int ret = getdigits_safe(&(char_u *){ (char_u *)port }, &iport); + if (ret == FAIL || iport < 0 || iport > UINT16_MAX) { + ELOG("Invalid port: %s", port); + return UV_EINVAL; + } - // Extract the address part - xstrlcpy(ip, watcher->addr, addr_len + 1); - int port = NVIM_DEFAULT_TCP_PORT; - - if (*ip_end == ':') { - // Extract the port - long lport = strtol(ip_end + 1, NULL, 10); // NOLINT - if (lport <= 0 || lport > 0xffff) { - // Invalid port, treat as named pipe or unix socket - tcp = false; - } else { - port = (int) lport; + if (*port == NUL) { + // When no port is given, (uv_)getaddrinfo expects NULL otherwise the + // implementation may attempt to lookup the service by name (and fail) + port = NULL; } - } - if (tcp) { - // Try to parse ip address - if (uv_ip4_addr(ip, port, &watcher->uv.tcp.addr)) { - // Invalid address, treat as named pipe or unix socket - tcp = false; + uv_getaddrinfo_t request; + + int retval = uv_getaddrinfo(&loop->uv, &request, NULL, addr, port, + &(struct addrinfo){ + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }); + if (retval != 0) { + ELOG("Host lookup failed: %s", endpoint); + return retval; } - } + watcher->uv.tcp.addrinfo = request.addrinfo; - if (tcp) { uv_tcp_init(&loop->uv, &watcher->uv.tcp.handle); - watcher->stream = (uv_stream_t *)&watcher->uv.tcp.handle; + uv_tcp_nodelay(&watcher->uv.tcp.handle, true); + watcher->stream = STRUCT_CAST(uv_stream_t, &watcher->uv.tcp.handle); } else { uv_pipe_init(&loop->uv, &watcher->uv.pipe.handle, 0); - watcher->stream = (uv_stream_t *)&watcher->uv.pipe.handle; + watcher->stream = STRUCT_CAST(uv_stream_t, &watcher->uv.pipe.handle); } watcher->stream->data = watcher; watcher->cb = NULL; watcher->close_cb = NULL; watcher->events = NULL; + watcher->data = NULL; + + return 0; } int socket_watcher_start(SocketWatcher *watcher, int backlog, socket_cb cb) FUNC_ATTR_NONNULL_ALL { watcher->cb = cb; - int result; + int result = UV_EINVAL; if (watcher->stream->type == UV_TCP) { - result = uv_tcp_bind(&watcher->uv.tcp.handle, - (const struct sockaddr *)&watcher->uv.tcp.addr, 0); + struct addrinfo *ai = watcher->uv.tcp.addrinfo; + + for (; ai; ai = ai->ai_next) { + result = uv_tcp_bind(&watcher->uv.tcp.handle, ai->ai_addr, 0); + if (result != 0) { + continue; + } + result = uv_listen(watcher->stream, backlog, connection_cb); + if (result == 0) { + struct sockaddr_storage sas; + + // When the endpoint in socket_watcher_init() didn't specify a port + // number, a free random port number will be assigned. sin_port will + // contain 0 in this case, unless uv_tcp_getsockname() is used first. + uv_tcp_getsockname(&watcher->uv.tcp.handle, (struct sockaddr *)&sas, + &(int){ sizeof(sas) }); + uint16_t port = (uint16_t)( + (sas.ss_family == AF_INET) + ? (STRUCT_CAST(struct sockaddr_in, &sas))->sin_port + : (STRUCT_CAST(struct sockaddr_in6, &sas))->sin6_port); + // v:servername uses the string from watcher->addr + size_t len = strlen(watcher->addr); + snprintf(watcher->addr+len, sizeof(watcher->addr)-len, ":%" PRIu16, + ntohs(port)); + break; + } + } + uv_freeaddrinfo(watcher->uv.tcp.addrinfo); } else { result = uv_pipe_bind(&watcher->uv.pipe.handle, watcher->addr); - } - - if (result == 0) { - result = uv_listen(watcher->stream, backlog, connection_cb); + if (result == 0) { + result = uv_listen(watcher->stream, backlog, connection_cb); + } } assert(result <= 0); // libuv should return negative error code or zero. if (result < 0) { - if (result == -EACCES) { + if (result == UV_EACCES) { // Libuv converts ENOENT to EACCES for Windows compatibility, but if // the parent directory does not exist, ENOENT would be more accurate. *path_tail((char_u *)watcher->addr) = NUL; if (!os_path_exists((char_u *)watcher->addr)) { - result = -ENOENT; + result = UV_ENOENT; } } return result; @@ -119,10 +146,11 @@ int socket_watcher_accept(SocketWatcher *watcher, Stream *stream) uv_stream_t *client; if (watcher->stream->type == UV_TCP) { - client = (uv_stream_t *)&stream->uv.tcp; + client = STRUCT_CAST(uv_stream_t, &stream->uv.tcp); uv_tcp_init(watcher->uv.tcp.handle.loop, (uv_tcp_t *)client); + uv_tcp_nodelay((uv_tcp_t *)client, true); } else { - client = (uv_stream_t *)&stream->uv.pipe; + client = STRUCT_CAST(uv_stream_t, &stream->uv.pipe); uv_pipe_init(watcher->uv.pipe.handle.loop, (uv_pipe_t *)client, 0); } @@ -165,3 +193,77 @@ static void close_cb(uv_handle_t *handle) watcher->close_cb(watcher, watcher->data); } } + +static void connect_cb(uv_connect_t *req, int status) +{ + int *ret_status = req->data; + *ret_status = status; + if (status != 0) { + uv_close((uv_handle_t *)req->handle, NULL); + } +} + +bool socket_connect(Loop *loop, Stream *stream, + bool is_tcp, const char *address, + int timeout, const char **error) +{ + bool success = false; + int status; + uv_connect_t req; + req.data = &status; + uv_stream_t *uv_stream; + + uv_tcp_t *tcp = &stream->uv.tcp; + uv_getaddrinfo_t addr_req; + addr_req.addrinfo = NULL; + const struct addrinfo *addrinfo = NULL; + char *addr = NULL; + if (is_tcp) { + addr = xstrdup(address); + char *host_end = strrchr(addr, ':'); + if (!host_end) { + *error = _("tcp address must be host:port"); + goto cleanup; + } + *host_end = NUL; + + const struct addrinfo hints = { .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + .ai_flags = AI_NUMERICSERV }; + int retval = uv_getaddrinfo(&loop->uv, &addr_req, NULL, + addr, host_end+1, &hints); + if (retval != 0) { + *error = _("failed to lookup host or port"); + goto cleanup; + } + addrinfo = addr_req.addrinfo; + +tcp_retry: + uv_tcp_init(&loop->uv, tcp); + uv_tcp_nodelay(tcp, true); + uv_tcp_connect(&req, tcp, addrinfo->ai_addr, connect_cb); + uv_stream = (uv_stream_t *)tcp; + + } else { + uv_pipe_t *pipe = &stream->uv.pipe; + uv_pipe_init(&loop->uv, pipe, 0); + uv_pipe_connect(&req, pipe, address, connect_cb); + uv_stream = STRUCT_CAST(uv_stream_t, pipe); + } + status = 1; + LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, timeout, status != 1); + if (status == 0) { + stream_init(NULL, stream, -1, uv_stream); + success = true; + } else if (is_tcp && addrinfo->ai_next) { + addrinfo = addrinfo->ai_next; + goto tcp_retry; + } else { + *error = _("connection refused"); + } + +cleanup: + xfree(addr); + uv_freeaddrinfo(addr_req.addrinfo); + return success; +} diff --git a/src/nvim/event/socket.h b/src/nvim/event/socket.h index eb0823c76d..d30ae45502 100644 --- a/src/nvim/event/socket.h +++ b/src/nvim/event/socket.h @@ -20,7 +20,7 @@ struct socket_watcher { union { struct { uv_tcp_t handle; - struct sockaddr_in addr; + struct addrinfo *addrinfo; } tcp; struct { uv_pipe_t handle; diff --git a/src/nvim/event/stream.c b/src/nvim/event/stream.c index 26083c20f4..7c865bfe1e 100644 --- a/src/nvim/event/stream.c +++ b/src/nvim/event/stream.c @@ -1,10 +1,15 @@ +// 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 <stdio.h> #include <stdbool.h> #include <uv.h> +#include "nvim/log.h" #include "nvim/rbuffer.h" +#include "nvim/macros.h" #include "nvim/event/stream.h" #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -23,8 +28,9 @@ int stream_set_blocking(int fd, bool blocking) uv_loop_init(&loop); uv_pipe_init(&loop, &stream, 0); uv_pipe_open(&stream, fd); - int retval = uv_stream_set_blocking((uv_stream_t *)&stream, blocking); - uv_close((uv_handle_t *)&stream, NULL); + int retval = uv_stream_set_blocking(STRUCT_CAST(uv_stream_t, &stream), + blocking); + uv_close(STRUCT_CAST(uv_handle_t, &stream), NULL); uv_run(&loop, UV_RUN_NOWAIT); // not necessary, but couldn't hurt. uv_loop_close(&loop); return retval; @@ -49,7 +55,7 @@ void stream_init(Loop *loop, Stream *stream, int fd, uv_stream_t *uvstream) assert(type == UV_NAMED_PIPE || type == UV_TTY); uv_pipe_init(&loop->uv, &stream->uv.pipe, 0); uv_pipe_open(&stream->uv.pipe, fd); - stream->uvstream = (uv_stream_t *)&stream->uv.pipe; + stream->uvstream = STRUCT_CAST(uv_stream_t, &stream->uv.pipe); } } @@ -76,6 +82,7 @@ void stream_close(Stream *stream, stream_close_cb on_stream_close, void *data) FUNC_ATTR_NONNULL_ARG(1) { assert(!stream->closed); + DLOG("closing Stream: %p", stream); stream->closed = true; stream->close_cb = on_stream_close; stream->close_cb_data = data; diff --git a/src/nvim/event/time.c b/src/nvim/event/time.c index 77260546db..80289c27d1 100644 --- a/src/nvim/event/time.c +++ b/src/nvim/event/time.c @@ -1,3 +1,6 @@ +// 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 <stdint.h> #include <uv.h> diff --git a/src/nvim/event/wstream.c b/src/nvim/event/wstream.c index fc7aad8eb9..320006890d 100644 --- a/src/nvim/event/wstream.c +++ b/src/nvim/event/wstream.c @@ -1,3 +1,6 @@ +// 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 <stdbool.h> @@ -5,6 +8,7 @@ #include <uv.h> +#include "nvim/log.h" #include "nvim/event/loop.h" #include "nvim/event/wstream.h" #include "nvim/vim.h" diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index b1a17e8c44..32dbf4cc69 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * ex_cmds.c: some functions for command line commands */ @@ -315,14 +318,12 @@ static int sort_abort; ///< flag to indicate if sorting has been interrupted /// Struct to store info to be sorted. typedef struct { linenr_T lnum; ///< line number - long start_col_nr; ///< starting column number or number - long end_col_nr; ///< ending column number union { struct { - long start_col_nr; ///< starting column number - long end_col_nr; ///< ending column number + varnumber_T start_col_nr; ///< starting column number + varnumber_T end_col_nr; ///< ending column number } line; - long value; ///< value if sorting by integer + varnumber_T value; ///< value if sorting by integer float_T value_flt; ///< value if sorting by float } st_u; } sorti_T; @@ -357,12 +358,12 @@ static int sort_compare(const void *s1, const void *s2) // We need to copy one line into "sortbuf1", because there is no // guarantee that the first pointer becomes invalid when obtaining the // second one. - STRNCPY(sortbuf1, ml_get(l1.lnum) + l1.st_u.line.start_col_nr, - l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr + 1); - sortbuf1[l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr] = 0; - STRNCPY(sortbuf2, ml_get(l2.lnum) + l2.st_u.line.start_col_nr, - l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr + 1); - sortbuf2[l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr] = 0; + memcpy(sortbuf1, ml_get(l1.lnum) + l1.st_u.line.start_col_nr, + l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr + 1); + sortbuf1[l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr] = NUL; + memcpy(sortbuf2, ml_get(l2.lnum) + l2.st_u.line.start_col_nr, + l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr + 1); + sortbuf2[l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr] = NUL; result = sort_ic ? STRICMP(sortbuf1, sortbuf2) : STRCMP(sortbuf1, sortbuf2); @@ -596,9 +597,10 @@ void ex_sort(exarg_T *eap) // Adjust marks for deleted (or added) lines and prepare for displaying. deleted = (long)(count - (lnum - eap->line2)); if (deleted > 0) { - mark_adjust(eap->line2 - deleted, eap->line2, (long)MAXLNUM, -deleted); + mark_adjust(eap->line2 - deleted, eap->line2, (long)MAXLNUM, -deleted, + false); } else if (deleted < 0) { - mark_adjust(eap->line2, MAXLNUM, -deleted, 0L); + mark_adjust(eap->line2, MAXLNUM, -deleted, 0L, false); } changed_lines(eap->line1, 0, eap->line2 + 1, -deleted); @@ -756,14 +758,6 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest) linenr_T num_lines; // Num lines moved linenr_T last_line; // Last line in file after adding new text - // Moving lines seems to corrupt the folds, delete folding info now - // and recreate it when finished. Don't do this for manual folding, it - // would delete all folds. - bool isFolded = hasAnyFolding(curwin) && !foldmethodIsManual(curwin); - if (isFolded) { - deleteFoldRecurse(&curwin->w_folds); - } - if (dest >= line1 && dest < line2) { EMSG(_("E134: Move lines into themselves")); return FAIL; @@ -801,21 +795,29 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest) * their final destination at the new text position -- webb */ last_line = curbuf->b_ml.ml_line_count; - mark_adjust(line1, line2, last_line - line2, 0L); - changed_lines(last_line - num_lines + 1, 0, last_line + 1, num_lines); + mark_adjust_nofold(line1, line2, last_line - line2, 0L, true); if (dest >= line2) { - mark_adjust(line2 + 1, dest, -num_lines, 0L); + mark_adjust_nofold(line2 + 1, dest, -num_lines, 0L, false); + FOR_ALL_TAB_WINDOWS(tab, win) { + if (win->w_buffer == curbuf) { + foldMoveRange(&win->w_folds, line1, line2, dest); + } + } curbuf->b_op_start.lnum = dest - num_lines + 1; curbuf->b_op_end.lnum = dest; } else { - mark_adjust(dest + 1, line1 - 1, num_lines, 0L); + mark_adjust_nofold(dest + 1, line1 - 1, num_lines, 0L, false); + FOR_ALL_TAB_WINDOWS(tab, win) { + if (win->w_buffer == curbuf) { + foldMoveRange(&win->w_folds, dest + 1, line1 - 1, line2); + } + } curbuf->b_op_start.lnum = dest + 1; curbuf->b_op_end.lnum = dest + num_lines; } curbuf->b_op_start.col = curbuf->b_op_end.col = 0; - mark_adjust(last_line - num_lines + 1, last_line, - -(last_line - dest - extra), 0L); - changed_lines(last_line - num_lines + 1, 0, last_line + 1, -extra); + mark_adjust_nofold(last_line - num_lines + 1, last_line, + -(last_line - dest - extra), 0L, true); /* * Now we delete the original text -- webb @@ -851,11 +853,6 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest) changed_lines(dest + 1, 0, line1 + num_lines, 0L); } - // recreate folds - if (isFolded) { - foldUpdateAll(curwin); - } - return OK; } @@ -1013,8 +1010,8 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out) AppendToRedobuffLit(cmd, -1); xfree(cmd); - AppendToRedobuff((char_u *)"\n"); - bangredo = FALSE; + AppendToRedobuff("\n"); + bangredo = false; } /* * Add quotes around the command, for shells that need them. @@ -1131,11 +1128,12 @@ static void do_filter( */ ++no_wait_return; /* don't call wait_return() while busy */ if (itmp != NULL && buf_write(curbuf, itmp, NULL, line1, line2, eap, - FALSE, FALSE, FALSE, TRUE) == FAIL) { - msg_putchar('\n'); /* keep message from buf_write() */ - --no_wait_return; - if (!aborting()) - (void)EMSG2(_(e_notcreate), itmp); /* will call wait_return */ + false, false, false, true) == FAIL) { + msg_putchar('\n'); // Keep message from buf_write(). + no_wait_return--; + if (!aborting()) { + EMSG2(_("E482: Can't create file %s"), itmp); // Will call wait_return. + } goto filterend; } if (curbuf != old_curbuf) @@ -1193,8 +1191,8 @@ static void do_filter( if (do_out) { if (otmp != NULL) { - if (readfile(otmp, NULL, line2, (linenr_T)0, (linenr_T)MAXLNUM, - eap, READ_FILTER) == FAIL) { + if (readfile(otmp, NULL, line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, + READ_FILTER) != OK) { if (!aborting()) { msg_putchar('\n'); EMSG2(_(e_notread), otmp); @@ -1215,15 +1213,14 @@ static void do_filter( if (do_in) { if (cmdmod.keepmarks || vim_strchr(p_cpo, CPO_REMMARK) == NULL) { - if (read_linecount >= linecount) - /* move all marks from old lines to new lines */ - mark_adjust(line1, line2, linecount, 0L); - else { - /* move marks from old lines to new lines, delete marks - * that are in deleted lines */ - mark_adjust(line1, line1 + read_linecount - 1, - linecount, 0L); - mark_adjust(line1 + read_linecount, line2, MAXLNUM, 0L); + if (read_linecount >= linecount) { + // move all marks from old lines to new lines + mark_adjust(line1, line2, linecount, 0L, false); + } else { + // move marks from old lines to new lines, delete marks + // that are in deleted lines + mark_adjust(line1, line1 + read_linecount - 1, linecount, 0L, false); + mark_adjust(line1 + read_linecount, line2, MAXLNUM, 0L, false); } } @@ -1404,36 +1401,34 @@ char_u *make_filter_cmd(char_u *cmd, char_u *itmp, char_u *otmp) : "(%s)"; vim_snprintf(buf, len, fmt, (char *)cmd); } else { - strncpy(buf, (char *) cmd, len); + xstrlcpy(buf, (char *)cmd, len); } if (itmp != NULL) { - strncat(buf, " < ", len); - strncat(buf, (char *) itmp, len); + xstrlcat(buf, " < ", len - 1); + xstrlcat(buf, (const char *)itmp, len - 1); } #else // For shells that don't understand braces around commands, at least allow // the use of commands in a pipe. - strncpy(buf, cmd, len); + xstrlcpy(buf, cmd, len); if (itmp != NULL) { - char_u *p; - // 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 // redirection would be inside the quotes. if (*p_shq == NUL) { - p = strchr(buf, '|'); + char *const p = strchr(buf, '|'); if (p != NULL) { *p = NUL; } } - strncat(buf, " < ", len); - strncat(buf, (char *) itmp, len); + xstrlcat(buf, " < ", len); + xstrlcat(buf, (const char *)itmp, len); if (*p_shq == NUL) { - p = strchr(cmd, '|'); + const char *const p = strchr((const char *)cmd, '|'); if (p != NULL) { - strncat(buf, " ", len); // Insert a space before the '|' for DOS - strncat(buf, p, len); + xstrlcat(buf, " ", len - 1); // Insert a space before the '|' for DOS + xstrlcat(buf, p, len - 1); } } } @@ -1476,12 +1471,12 @@ void append_redir(char *const buf, const size_t buflen, void print_line_no_prefix(linenr_T lnum, int use_number, int list) { - char_u numbuf[30]; + char numbuf[30]; if (curwin->w_p_nu || use_number) { - vim_snprintf((char *)numbuf, sizeof(numbuf), - "%*ld ", number_width(curwin), (long)lnum); - msg_puts_attr(numbuf, hl_attr(HLF_N)); /* Highlight line nrs */ + vim_snprintf(numbuf, sizeof(numbuf), "%*" PRIdLINENR " ", + number_width(curwin), lnum); + msg_puts_attr(numbuf, hl_attr(HLF_N)); // Highlight line nrs. } msg_prt_line(ml_get(lnum), list); } @@ -1493,6 +1488,11 @@ void print_line(linenr_T lnum, int use_number, int list) { int save_silent = silent_mode; + // apply :filter /pat/ + if (message_filtered(ml_get(lnum))) { + return; + } + msg_start(); silent_mode = FALSE; info_message = TRUE; /* use mch_msg(), not mch_errmsg() */ @@ -1906,11 +1906,15 @@ void do_wqall(exarg_T *eap) FALSE) == FAIL) { ++error; } else { - if (buf_write_all(buf, eap->forceit) == FAIL) - ++error; - /* an autocommand may have deleted the buffer */ - if (!buf_valid(buf)) + bufref_T bufref; + set_bufref(&bufref, buf); + if (buf_write_all(buf, eap->forceit) == FAIL) { + error++; + } + // An autocommand may have deleted the buffer. + if (!bufref_valid(&bufref)) { buf = firstbuf; + } } eap->forceit = save_forceit; /* check_overwrite() may set it */ } @@ -2083,7 +2087,8 @@ int do_ecmd( char_u *new_name = NULL; int did_set_swapcommand = FALSE; buf_T *buf; - buf_T *old_curbuf = curbuf; + bufref_T bufref; + bufref_T old_curbuf; char_u *free_fname = NULL; int retval = FAIL; long n; @@ -2100,6 +2105,8 @@ int do_ecmd( if (eap != NULL) command = eap->do_ecmd_cmd; + set_bufref(&old_curbuf, curbuf); + if (fnum != 0) { if (fnum == curbuf->b_fnum) /* file is already being edited */ return OK; /* nothing to do */ @@ -2211,23 +2218,27 @@ int do_ecmd( if (oldwin != NULL) { oldwin = curwin; } - old_curbuf = curbuf; + set_bufref(&old_curbuf, curbuf); } if (buf == NULL) goto theend; - if (buf->b_ml.ml_mfp == NULL) { /* no memfile yet */ - oldbuf = FALSE; - } else { /* existing memfile */ - oldbuf = TRUE; - (void)buf_check_timestamp(buf, FALSE); - /* Check if autocommands made buffer invalid or changed the current - * buffer. */ - if (!buf_valid(buf) - || curbuf != old_curbuf - ) + if (buf->b_ml.ml_mfp == NULL) { + // No memfile yet. + oldbuf = false; + } else { + // Existing memfile. + oldbuf = true; + set_bufref(&bufref, buf); + (void)buf_check_timestamp(buf, false); + // Check if autocommands made buffer invalid or changed the current + // buffer. + if (!bufref_valid(&bufref) || curbuf != old_curbuf.br_buf) { goto theend; - if (aborting()) /* autocmds may abort script processing */ + } + if (aborting()) { + // Autocmds may abort script processing. goto theend; + } } /* May jump to last used line number for a loaded buffer or when asked @@ -2255,12 +2266,14 @@ int do_ecmd( * - If we ended up in the new buffer already, need to skip a few * things, set auto_buf. */ - if (buf->b_fname != NULL) + if (buf->b_fname != NULL) { new_name = vim_strsave(buf->b_fname); - au_new_curbuf = buf; - apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf); - if (!buf_valid(buf)) { /* new buffer has been deleted */ - delbuf_msg(new_name); /* frees new_name */ + } + set_bufref(&au_new_curbuf, buf); + apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf); + if (!bufref_valid(&au_new_curbuf)) { + // New buffer has been deleted. + delbuf_msg(new_name); // Frees new_name. goto theend; } if (aborting()) { /* autocmds may abort script processing */ @@ -2272,29 +2285,34 @@ int do_ecmd( } else { win_T *the_curwin = curwin; - // Set the w_closing flag to avoid that autocommands close the window. + // Set w_closing to avoid that autocommands close the window. + // Set b_locked for the same reason. the_curwin->w_closing = true; - if (curbuf == old_curbuf) { + buf->b_locked++; + + if (curbuf == old_curbuf.br_buf) { buf_copy_options(buf, BCO_ENTER); } // Close the link to the current buffer. This will set - // curwin->w_buffer to NULL. + // oldwin->w_buffer to NULL. u_sync(false); close_buffer(oldwin, curbuf, (flags & ECMD_HIDE) || curbuf->terminal ? 0 : DOBUF_UNLOAD, false); the_curwin->w_closing = false; + buf->b_locked--; // autocmds may abort script processing if (aborting() && curwin->w_buffer != NULL) { xfree(new_name); goto theend; } - /* Be careful again, like above. */ - if (!buf_valid(buf)) { /* new buffer has been deleted */ - delbuf_msg(new_name); /* frees new_name */ + // Be careful again, like above. + if (!bufref_valid(&au_new_curbuf)) { + // New buffer has been deleted. + delbuf_msg(new_name); // Frees new_name. goto theend; } if (buf == curbuf) { // already in new buffer @@ -2327,7 +2345,8 @@ int do_ecmd( } xfree(new_name); - au_new_curbuf = NULL; + au_new_curbuf.br_buf = NULL; + au_new_curbuf.br_buf_free_count = 0; } curwin->w_pcmark.lnum = 1; @@ -2380,10 +2399,12 @@ int do_ecmd( solcol = curwin->w_cursor.col; } buf = curbuf; - if (buf->b_fname != NULL) + if (buf->b_fname != NULL) { new_name = vim_strsave(buf->b_fname); - else + } else { new_name = NULL; + } + set_bufref(&bufref, buf); if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur) { /* Save all the text, so that the reload can be undone. * Sync first so that this is a separate undo-able action. */ @@ -2396,14 +2417,15 @@ int do_ecmd( u_unchanged(curbuf); buf_freeall(curbuf, BFA_KEEP_UNDO); - /* tell readfile() not to clear or reload undo info */ + // Tell readfile() not to clear or reload undo info. readfile_flags = READ_KEEP_UNDO; - } else - buf_freeall(curbuf, 0); /* free all things for buffer */ - /* If autocommands deleted the buffer we were going to re-edit, give - * up and jump to the end. */ - if (!buf_valid(buf)) { - delbuf_msg(new_name); /* frees new_name */ + } else { + buf_freeall(curbuf, 0); // Free all things for buffer. + } + // If autocommands deleted the buffer we were going to re-edit, give + // up and jump to the end. + if (!bufref_valid(&bufref)) { + delbuf_msg(new_name); // Frees new_name. goto theend; } xfree(new_name); @@ -2428,11 +2450,6 @@ int do_ecmd( retval = OK; /* - * Reset cursor position, could be used by autocommands. - */ - check_cursor(); - - /* * Check if we are editing the w_arg_idx file in the argument list. */ check_arg_idx(curwin); @@ -2474,7 +2491,7 @@ int do_ecmd( if (swap_exists_action == SEA_QUIT) retval = FAIL; - handle_swap_exists(old_curbuf); + handle_swap_exists(&old_curbuf); } else { /* Read the modelines, but only to set window-local options. Any * buffer-local options have already been set and may have been @@ -2609,7 +2626,8 @@ static void delbuf_msg(char_u *name) EMSG2(_("E143: Autocommands unexpectedly deleted new buffer %s"), name == NULL ? (char_u *)"" : name); xfree(name); - au_new_curbuf = NULL; + au_new_curbuf.br_buf = NULL; + au_new_curbuf.br_buf_free_count = 0; } static int append_indent = 0; /* autoindent for first line */ @@ -2784,16 +2802,18 @@ void ex_z(exarg_T *eap) int j; linenr_T lnum = eap->line2; - /* Vi compatible: ":z!" uses display height, without a count uses - * 'scroll' */ - if (eap->forceit) + // Vi compatible: ":z!" uses display height, without a count uses + // 'scroll' + if (eap->forceit) { bigness = curwin->w_height; - else if (firstwin == lastwin) + } else if (ONE_WINDOW) { bigness = curwin->w_p_scr * 2; - else + } else { bigness = curwin->w_height - 3; - if (bigness < 1) + } + if (bigness < 1) { bigness = 1; + } x = eap->arg; kind = x; @@ -2862,8 +2882,11 @@ void ex_z(exarg_T *eap) if (end > curbuf->b_ml.ml_line_count) end = curbuf->b_ml.ml_line_count; - if (curs > curbuf->b_ml.ml_line_count) + if (curs > curbuf->b_ml.ml_line_count) { curs = curbuf->b_ml.ml_line_count; + } else if (curs < 1) { + curs = 1; + } for (i = start; i <= end; i++) { if (minus && i == lnum) { @@ -2883,8 +2906,11 @@ void ex_z(exarg_T *eap) } } - curwin->w_cursor.lnum = curs; - ex_no_reprint = TRUE; + if (curwin->w_cursor.lnum != curs) { + curwin->w_cursor.lnum = curs; + curwin->w_cursor.col = 0; + } + ex_no_reprint = true; } /* @@ -2946,7 +2972,7 @@ void sub_set_replacement(SubReplacementString sub) { xfree(old_sub.sub); if (sub.additional_elements != old_sub.additional_elements) { - list_unref(old_sub.additional_elements); + tv_list_unref(old_sub.additional_elements); } old_sub = sub; } @@ -3308,7 +3334,8 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout) // Check for a match on each line. linenr_T line2 = eap->line2; for (linenr_T lnum = eap->line1; - lnum <= line2 && !(got_quit || aborting()); + lnum <= line2 && !(got_quit || aborting()) + && (!preview || matched_lines.size <= (size_t)p_cwh); lnum++) { long nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum, (colnr_T)0, NULL); @@ -3473,6 +3500,10 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout) setmouse(); /* disable mouse in xterm */ curwin->w_cursor.col = regmatch.startpos[0].col; + if (curwin->w_p_crb) { + do_check_cursorbind(); + } + /* When 'cpoptions' contains "u" don't sync undo when * asking for confirmation. */ if (vim_strchr(p_cpo, CPO_UNDO) != NULL) @@ -3565,11 +3596,9 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout) ui_cursor_goto(msg_row, msg_col); RedrawingDisabled = temp; - ++no_mapping; /* don't map this key */ - ++allow_keys; /* allow special keys */ + no_mapping++; // don't map this key typed = plain_vgetc(); - --allow_keys; - --no_mapping; + no_mapping--; /* clear the question */ msg_didout = FALSE; /* don't scroll up */ @@ -3736,7 +3765,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout) *p1 = NUL; // truncate up to the CR ml_append(lnum - 1, new_start, (colnr_T)(p1 - new_start + 1), false); - mark_adjust(lnum + 1, (linenr_T)MAXLNUM, 1L, 0L); + mark_adjust(lnum + 1, (linenr_T)MAXLNUM, 1L, 0L, false); if (subflags.do_ask) { appended_lines(lnum - 1, 1L); } else { @@ -3825,7 +3854,7 @@ skip: for (i = 0; i < nmatch_tl; ++i) ml_delete(lnum, (int)FALSE); mark_adjust(lnum, lnum + nmatch_tl - 1, - (long)MAXLNUM, -nmatch_tl); + (long)MAXLNUM, -nmatch_tl, false); if (subflags.do_ask) { deleted_lines(lnum, nmatch_tl); } @@ -4345,19 +4374,22 @@ void ex_help(exarg_T *eap) if (!curwin->w_buffer->b_help || cmdmod.tab != 0 ) { - if (cmdmod.tab != 0) + if (cmdmod.tab != 0) { wp = NULL; - else - for (wp = firstwin; wp != NULL; wp = wp->w_next) - if (wp->w_buffer != NULL && wp->w_buffer->b_help) + } else { + wp = NULL; + FOR_ALL_WINDOWS_IN_TAB(wp2, curtab) { + if (wp2->w_buffer != NULL && wp2->w_buffer->b_help) { + wp = wp2; break; - if (wp != NULL && wp->w_buffer->b_nwindows > 0) + } + } + } + if (wp != NULL && wp->w_buffer->b_nwindows > 0) { win_enter(wp, true); - else { - /* - * There is no help window yet. - * Try to open the file specified by the "helpfile" option. - */ + } else { + // There is no help window yet. + // Try to open the file specified by the "helpfile" option. if ((helpfd = mch_fopen((char *)p_hf, READBIN)) == NULL) { smsg(_("Sorry, help file \"%s\" not found"), p_hf); goto erret; @@ -4751,8 +4783,8 @@ void fix_help_buffer(void) char_u *p; char_u *rt; - /* set filetype to "help". */ - set_option_value((char_u *)"ft", 0L, (char_u *)"help", OPT_LOCAL); + // Set filetype to "help". + set_option_value("ft", 0L, "help", OPT_LOCAL); if (!syntax_present(curwin)) { for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) { @@ -4814,9 +4846,13 @@ void fix_help_buffer(void) vimconv_T vc; char_u *cp; - /* Find all "doc/ *.txt" files in this directory. */ - add_pathsep((char *)NameBuff); - STRCAT(NameBuff, "doc/*.??[tx]"); + // Find all "doc/ *.txt" files in this directory. + if (!add_pathsep((char *)NameBuff) + || STRLCAT(NameBuff, "doc/*.??[tx]", + sizeof(NameBuff)) >= MAXPATHL) { + EMSG(_(e_fnametoolong)); + continue; + } // Note: We cannot just do `&NameBuff` because it is a statically sized array // so `NameBuff == &NameBuff` according to C semantics. @@ -4847,8 +4883,9 @@ void fix_help_buffer(void) continue; e1 = vim_strrchr(t1, '.'); e2 = vim_strrchr(path_tail(f2), '.'); - if (e1 == NUL || e2 == NUL) + if (e1 == NULL || e2 == NULL) { continue; + } if (fnamecmp(e1, ".txt") != 0 && fnamecmp(e1, fname + 4) != 0) { /* Not .txt and not .abx, remove it. */ @@ -4979,8 +5016,12 @@ static void helptags_one(char_u *dir, char_u *ext, char_u *tagfname, // Find all *.txt files. size_t dirlen = STRLCPY(NameBuff, dir, sizeof(NameBuff)); - STRCAT(NameBuff, "/**/*"); // NOLINT - STRCAT(NameBuff, ext); + if (dirlen >= MAXPATHL + || STRLCAT(NameBuff, "/**/*", sizeof(NameBuff)) >= MAXPATHL // NOLINT + || STRLCAT(NameBuff, ext, sizeof(NameBuff)) >= MAXPATHL) { + EMSG(_(e_fnametoolong)); + return; + } // Note: We cannot just do `&NameBuff` because it is a statically sized array // so `NameBuff == &NameBuff` according to C semantics. @@ -4988,18 +5029,22 @@ static void helptags_one(char_u *dir, char_u *ext, char_u *tagfname, if (gen_expand_wildcards(1, buff_list, &filecount, &files, EW_FILE|EW_SILENT) == FAIL || filecount == 0) { - if (!got_int) - EMSG2("E151: No match: %s", NameBuff); + if (!got_int) { + EMSG2(_("E151: No match: %s"), NameBuff); + } return; } - /* - * Open the tags file for writing. - * Do this before scanning through all the files. - */ - STRLCPY(NameBuff, dir, sizeof(NameBuff)); - add_pathsep((char *)NameBuff); - STRNCAT(NameBuff, tagfname, sizeof(NameBuff) - dirlen - 2); + // + // Open the tags file for writing. + // Do this before scanning through all the files. + // + memcpy(NameBuff, dir, dirlen + 1); + if (!add_pathsep((char *)NameBuff) + || STRLCAT(NameBuff, tagfname, sizeof(NameBuff)) >= MAXPATHL) { + EMSG(_(e_fnametoolong)); + return; + } fd_tags = mch_fopen((char *)NameBuff, "w"); if (fd_tags == NULL) { EMSG2(_("E152: Cannot open %s for writing"), NameBuff); @@ -5063,14 +5108,13 @@ static void helptags_one(char_u *dir, char_u *ext, char_u *tagfname, } p1 = vim_strchr(IObuff, '*'); /* find first '*' */ while (p1 != NULL) { - /* Use vim_strbyte() instead of vim_strchr() so that when - * 'encoding' is dbcs it still works, don't find '*' in the - * second byte. */ - p2 = vim_strbyte(p1 + 1, '*'); /* find second '*' */ - if (p2 != NULL && p2 > p1 + 1) { /* skip "*" and "**" */ - for (s = p1 + 1; s < p2; ++s) - if (*s == ' ' || *s == '\t' || *s == '|') + p2 = (char_u *)strchr((const char *)p1 + 1, '*'); // Find second '*'. + if (p2 != NULL && p2 > p1 + 1) { // Skip "*" and "**". + for (s = p1 + 1; s < p2; s++) { + if (*s == ' ' || *s == '\t' || *s == '|') { break; + } + } /* * Only accept a *tag* when it consists of valid @@ -5173,8 +5217,12 @@ static void do_helptags(char_u *dirname, bool add_help_tags) // Get a list of all files in the help directory and in subdirectories. STRLCPY(NameBuff, dirname, sizeof(NameBuff)); - add_pathsep((char *)NameBuff); - STRCAT(NameBuff, "**"); + if (!add_pathsep((char *)NameBuff) + || STRLCAT(NameBuff, "**", sizeof(NameBuff)) >= MAXPATHL) { + EMSG(_(e_fnametoolong)); + xfree(dirname); + return; + } // Note: We cannot just do `&NameBuff` because it is a statically sized array // so `NameBuff == &NameBuff` according to C semantics. @@ -5182,7 +5230,7 @@ static void do_helptags(char_u *dirname, bool add_help_tags) if (gen_expand_wildcards(1, buff_list, &filecount, &files, EW_FILE|EW_SILENT) == FAIL || filecount == 0) { - EMSG2("E151: No match: %s", NameBuff); + EMSG2(_("E151: No match: %s"), NameBuff); xfree(dirname); return; } @@ -5688,33 +5736,33 @@ void ex_sign(exarg_T *eap) */ static void sign_list_defined(sign_T *sp) { - char_u *p; - smsg("sign %s", sp->sn_name); if (sp->sn_icon != NULL) { - MSG_PUTS(" icon="); + msg_puts(" icon="); msg_outtrans(sp->sn_icon); - MSG_PUTS(_(" (not supported)")); + msg_puts(_(" (not supported)")); } if (sp->sn_text != NULL) { - MSG_PUTS(" text="); + msg_puts(" text="); msg_outtrans(sp->sn_text); } if (sp->sn_line_hl > 0) { - MSG_PUTS(" linehl="); - p = get_highlight_name(NULL, sp->sn_line_hl - 1); - if (p == NULL) - MSG_PUTS("NONE"); - else + msg_puts(" linehl="); + const char *const p = get_highlight_name(NULL, sp->sn_line_hl - 1); + if (p == NULL) { + msg_puts("NONE"); + } else { msg_puts(p); + } } if (sp->sn_text_hl > 0) { - MSG_PUTS(" texthl="); - p = get_highlight_name(NULL, sp->sn_text_hl - 1); - if (p == NULL) - MSG_PUTS("NONE"); - else + msg_puts(" texthl="); + const char *const p = get_highlight_name(NULL, sp->sn_text_hl - 1); + if (p == NULL) { + msg_puts("NONE"); + } else { msg_puts(p); + } } } @@ -5908,9 +5956,8 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg) // :sign define {name} {args}... {last}= // | | // last p - if (p == NUL) - { - /* Expand last argument name (before equal sign). */ + if (p == NULL) { + // Expand last argument name (before equal sign). xp->xp_pattern = last; switch (cmd_idx) { @@ -6093,7 +6140,6 @@ void ex_substitute(exarg_T *eap) int save_w_p_cul = curwin->w_p_cul; int save_w_p_cuc = curwin->w_p_cuc; - emsg_off++; // No error messages during command preview. curbuf->b_p_ul = LONG_MAX; // make sure we can undo all changes curwin->w_p_cul = false; // Disable 'cursorline' curwin->w_p_cuc = false; // Disable 'cursorcolumn' @@ -6107,7 +6153,7 @@ void ex_substitute(exarg_T *eap) // restore it so that undotree() is identical before/after the preview. curbuf->b_u_newhead = save_b_u_newhead; curbuf->b_u_time_cur = save_b_u_time_cur; - curbuf->b_changedtick = save_changedtick; + buf_set_changedtick(curbuf, save_changedtick); } if (buf_valid(preview_buf)) { // XXX: Must do this *after* u_undo_and_forget(), why? @@ -6120,6 +6166,105 @@ void ex_substitute(exarg_T *eap) restore_search_patterns(); win_size_restore(&save_view); ga_clear(&save_view); - emsg_off--; unblock_autocmds(); } + +/// Skip over the pattern argument of ":vimgrep /pat/[g][j]". +/// Put the start of the pattern in "*s", unless "s" is NULL. +/// If "flags" is not NULL put the flags in it: VGR_GLOBAL, VGR_NOJUMP. +/// If "s" is not NULL terminate the pattern with a NUL. +/// Return a pointer to the char just past the pattern plus flags. +char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags) +{ + int c; + + if (vim_isIDc(*p)) { + // ":vimgrep pattern fname" + if (s != NULL) { + *s = p; + } + p = skiptowhite(p); + if (s != NULL && *p != NUL) { + *p++ = NUL; + } + } else { + // ":vimgrep /pattern/[g][j] fname" + if (s != NULL) { + *s = p + 1; + } + c = *p; + p = skip_regexp(p + 1, c, true, NULL); + if (*p != c) { + return NULL; + } + + // Truncate the pattern. + if (s != NULL) { + *p = NUL; + } + p++; + + // Find the flags + while (*p == 'g' || *p == 'j') { + if (flags != NULL) { + if (*p == 'g') { + *flags |= VGR_GLOBAL; + } else { + *flags |= VGR_NOJUMP; + } + } + p++; + } + } + return p; +} + +/// List v:oldfiles in a nice way. +void ex_oldfiles(exarg_T *eap) +{ + list_T *l = get_vim_var_list(VV_OLDFILES); + listitem_T *li; + long nr = 0; + + if (l == NULL) { + msg((char_u *)_("No old files")); + } else { + msg_start(); + msg_scroll = true; + for (li = l->lv_first; li != NULL && !got_int; li = li->li_next) { + nr++; + const char *fname = tv_get_string(&li->li_tv); + if (!message_filtered((char_u *)fname)) { + msg_outnum(nr); + MSG_PUTS(": "); + msg_outtrans((char_u *)tv_get_string(&li->li_tv)); + msg_clr_eos(); + msg_putchar('\n'); + ui_flush(); // output one line at a time + os_breakcheck(); + } + } + + // Assume "got_int" was set to truncate the listing. + got_int = false; + + // File selection prompt on ":browse oldfiles" + if (cmdmod.browse) { + quit_more = false; + nr = prompt_for_number(false); + msg_starthere(); + if (nr > 0 && nr <= l->lv_len) { + const char *const p = tv_list_find_str(l, nr - 1); + if (p == NULL) { + return; + } + char *const s = (char *)expand_env_save((char_u *)p); + eap->arg = (char_u *)s; + eap->cmdidx = CMD_edit; + cmdmod.browse = false; + do_exedit(eap, NULL); + xfree(s); + } + } + } +} diff --git a/src/nvim/ex_cmds.h b/src/nvim/ex_cmds.h index 243b11255e..b564cde56c 100644 --- a/src/nvim/ex_cmds.h +++ b/src/nvim/ex_cmds.h @@ -4,8 +4,10 @@ #include <stdbool.h> #include "nvim/os/time.h" -#include "nvim/eval_defs.h" #include "nvim/pos.h" +#include "nvim/eval/typval.h" +#include "nvim/buffer_defs.h" +#include "nvim/ex_cmds_defs.h" // flags for do_ecmd() #define ECMD_HIDE 0x01 // don't free the current buffer diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index 88095602ba..5a578cd088 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -1,4 +1,4 @@ -bit = require 'bit' +local bit = require 'bit' -- Description of the values below is contained in ex_cmds_defs.h file. local RANGE = 0x001 @@ -34,7 +34,8 @@ local ADDR_ARGUMENTS = 2 local ADDR_LOADED_BUFFERS = 3 local ADDR_BUFFERS = 4 local ADDR_TABS = 5 -local ADDR_QUICKFIX = 6 +local ADDR_TABS_RELATIVE = 6 +local ADDR_QUICKFIX = 7 local ADDR_OTHER = 99 -- The following table is described in ex_cmds_defs.h file. @@ -462,6 +463,12 @@ return { func='ex_checktime', }, { + command='chistory', + flags=bit.bor(TRLBAR), + addr_type=ADDR_LINES, + func='qf_history', + }, + { command='clist', flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN), addr_type=ADDR_LINES, @@ -621,13 +628,13 @@ return { command='cscope', flags=bit.bor(EXTRA, NOTRLCOM, XFILE), addr_type=ADDR_LINES, - func='do_cscope', + func='ex_cscope', }, { command='cstag', flags=bit.bor(BANG, TRLBAR, WORD1), addr_type=ADDR_LINES, - func='do_cstag', + func='ex_cstag', }, { command='cunmap', @@ -924,6 +931,12 @@ return { func='ex_filetype', }, { + command='filter', + flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM), + addr_type=ADDR_LINES, + func='ex_wrongmodifier', + }, + { command='find', flags=bit.bor(RANGE, NOTADR, BANG, FILE1, EDITCMD, ARGOPT, TRLBAR), addr_type=ADDR_LINES, @@ -1063,7 +1076,7 @@ return { }, { command='hide', - flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EXTRA, NOTRLCOM), + flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EXTRA, TRLBAR), addr_type=ADDR_WINDOWS, func='ex_hide', }, @@ -1311,7 +1324,7 @@ return { command='lcscope', flags=bit.bor(EXTRA, NOTRLCOM, XFILE), addr_type=ADDR_LINES, - func='do_cscope', + func='ex_cscope', }, { command='ldo', @@ -1400,6 +1413,12 @@ return { func='ex_helpgrep', }, { + command='lhistory', + flags=bit.bor(TRLBAR), + addr_type=ADDR_LINES, + func='qf_history', + }, + { command='ll', flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG), addr_type=ADDR_LINES, @@ -1529,19 +1548,19 @@ return { command='lua', flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN), addr_type=ADDR_LINES, - func='ex_script_ni', + func='ex_lua', }, { command='luado', flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN), addr_type=ADDR_LINES, - func='ex_ni', + func='ex_luado', }, { command='luafile', flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN), addr_type=ADDR_LINES, - func='ex_ni', + func='ex_luafile', }, { command='lvimgrep', @@ -2315,7 +2334,7 @@ return { command='scscope', flags=bit.bor(EXTRA, NOTRLCOM), addr_type=ADDR_LINES, - func='do_scscope', + func='ex_scscope', }, { command='set', @@ -2638,12 +2657,12 @@ return { { command='tab', flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM), - addr_type=ADDR_LINES, + addr_type=ADDR_TABS, func='ex_wrongmodifier', }, { command='tabclose', - flags=bit.bor(RANGE, NOTADR, COUNT, BANG, TRLBAR, CMDWIN), + flags=bit.bor(BANG, RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN), addr_type=ADDR_TABS, func='ex_tabclose', }, @@ -2668,7 +2687,7 @@ return { { command='tabfirst', flags=bit.bor(TRLBAR), - addr_type=ADDR_LINES, + addr_type=ADDR_TABS, func='ex_tabnext', }, { @@ -2680,13 +2699,13 @@ return { { command='tablast', flags=bit.bor(TRLBAR), - addr_type=ADDR_LINES, + addr_type=ADDR_TABS, func='ex_tabnext', }, { command='tabnext', - flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR), - addr_type=ADDR_LINES, + flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR), + addr_type=ADDR_TABS, func='ex_tabnext', }, { @@ -2697,32 +2716,32 @@ return { }, { command='tabonly', - flags=bit.bor(BANG, RANGE, NOTADR, TRLBAR, CMDWIN), + flags=bit.bor(BANG, RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN), addr_type=ADDR_TABS, func='ex_tabonly', }, { command='tabprevious', - flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR), - addr_type=ADDR_LINES, + flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR), + addr_type=ADDR_TABS_RELATIVE, func='ex_tabnext', }, { command='tabNext', - flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR), - addr_type=ADDR_LINES, + flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR), + addr_type=ADDR_TABS_RELATIVE, func='ex_tabnext', }, { command='tabrewind', flags=bit.bor(TRLBAR), - addr_type=ADDR_LINES, + addr_type=ADDR_TABS, func='ex_tabnext', }, { command='tabs', flags=bit.bor(TRLBAR, CMDWIN), - addr_type=ADDR_LINES, + addr_type=ADDR_TABS, func='ex_tabs', }, { diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 3b92b3734a..371f7b3bce 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -1,3 +1,6 @@ +// 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 + /// @file ex_cmds2.c /// /// Some more functions for command line commands @@ -186,7 +189,8 @@ void do_debug(char_u *cmd) } xfree(cmdline); - cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL); + cmdline = (char_u *)getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL, + CALLBACK_NONE); if (typeahead_saved) { restore_typeahead(&typeaheadbuf); @@ -957,23 +961,21 @@ char_u *get_profile_name(expand_T *xp, int idx) } /// Handle command line completion for :profile command. -void set_context_in_profile_cmd(expand_T *xp, char_u *arg) +void set_context_in_profile_cmd(expand_T *xp, const char *arg) { - char_u *end_subcmd; - // Default: expand subcommands. xp->xp_context = EXPAND_PROFILE; pexpand_what = PEXP_SUBCMD; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; - end_subcmd = skiptowhite(arg); + char_u *const end_subcmd = skiptowhite((const char_u *)arg); if (*end_subcmd == NUL) { return; } - if (end_subcmd - arg == 5 && STRNCMP(arg, "start", 5) == 0) { + if ((const char *)end_subcmd - arg == 5 && strncmp(arg, "start", 5) == 0) { xp->xp_context = EXPAND_FILES; - xp->xp_pattern = skipwhite(end_subcmd); + xp->xp_pattern = skipwhite((const char_u *)end_subcmd); return; } @@ -1181,6 +1183,7 @@ bool prof_def_func(void) int autowrite(buf_T *buf, int forceit) { int r; + bufref_T bufref; if (!(p_aw || p_awa) || !p_write // never autowrite a "nofile" or "nowrite" buffer @@ -1188,11 +1191,12 @@ int autowrite(buf_T *buf, int forceit) || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL) { return FAIL; } + set_bufref(&bufref, buf); r = buf_write_all(buf, forceit); // Writing may succeed but the buffer still changed, e.g., when there is a // conversion error. We do want to return FAIL then. - if (buf_valid(buf) && bufIsChanged(buf)) { + if (bufref_valid(&bufref) && bufIsChanged(buf)) { r = FAIL; } return r; @@ -1207,9 +1211,11 @@ void autowrite_all(void) FOR_ALL_BUFFERS(buf) { if (bufIsChanged(buf) && !buf->b_p_ro) { + bufref_T bufref; + set_bufref(&bufref, buf); (void)buf_write_all(buf, false); // an autocommand may have deleted the buffer - if (!buf_valid(buf)) { + if (!bufref_valid(&bufref)) { buf = firstbuf; } } @@ -1221,6 +1227,8 @@ void autowrite_all(void) bool check_changed(buf_T *buf, int flags) { int forceit = (flags & CCGD_FORCEIT); + bufref_T bufref; + set_bufref(&bufref, buf); if (!forceit && bufIsChanged(buf) @@ -1236,12 +1244,12 @@ bool check_changed(buf_T *buf, int flags) } } } - if (!buf_valid(buf)) { + if (!bufref_valid(&bufref)) { // Autocommand deleted buffer, oops! It's not changed now. return false; } dialog_changed(buf, count > 1); - if (!buf_valid(buf)) { + if (!bufref_valid(&bufref)) { // Autocommand deleted buffer, oops! It's not changed now. return false; } @@ -1300,9 +1308,10 @@ void dialog_changed(buf_T *buf, int checkall) // Skip readonly buffers, these need to be confirmed // individually. FOR_ALL_BUFFERS(buf2) { - if (bufIsChanged(buf2) - && (buf2->b_ffname != NULL) - && !buf2->b_p_ro) { + if (bufIsChanged(buf2) && (buf2->b_ffname != NULL) && !buf2->b_p_ro) { + bufref_T bufref; + set_bufref(&bufref, buf2); + if (buf2->b_fname != NULL && check_overwrite(&ea, buf2, buf2->b_fname, buf2->b_ffname, false) == OK) { @@ -1310,7 +1319,7 @@ void dialog_changed(buf_T *buf, int checkall) (void)buf_write_all(buf2, false); } // an autocommand may have deleted the buffer - if (!buf_valid(buf2)) { + if (!bufref_valid(&bufref)) { buf2 = firstbuf; } } @@ -1407,11 +1416,14 @@ bool check_changed_any(bool hidden, bool unload) continue; } if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf)) { + bufref_T bufref; + set_bufref(&bufref, buf); + // Try auto-writing the buffer. If this fails but the buffer no // longer exists it's not changed, that's OK. if (check_changed(buf, (p_awa ? CCGD_AW : 0) | CCGD_MULTWIN - | CCGD_ALLBUF) && buf_valid(buf)) { + | CCGD_ALLBUF) && bufref_valid(&bufref)) { break; // didn't save - still changes } } @@ -1447,9 +1459,11 @@ bool check_changed_any(bool hidden, bool unload) if (buf != curbuf) { FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->w_buffer == buf) { + bufref_T bufref; + set_bufref(&bufref, buf); goto_tabpage_win(tp, wp); // Paranoia: did autocmds wipe out the buffer with changes? - if (!buf_valid(buf)) { + if (!bufref_valid(&bufref)) { goto theend; } goto buf_found; @@ -2061,9 +2075,9 @@ void ex_listdo(exarg_T *eap) // Clear 'shm' to avoid that the file message overwrites // any output from the command. p_shm_save = vim_strsave(p_shm); - set_option_value((char_u *)"shm", 0L, (char_u *)"", 0); + set_option_value("shm", 0L, "", 0); do_argfile(eap, i); - set_option_value((char_u *)"shm", 0L, p_shm_save, 0); + set_option_value("shm", 0L, (char *)p_shm_save, 0); xfree(p_shm_save); } if (curwin->w_arg_idx != i) { @@ -2126,9 +2140,9 @@ void ex_listdo(exarg_T *eap) // Go to the next buffer. Clear 'shm' to avoid that the file // message overwrites any output from the command. p_shm_save = vim_strsave(p_shm); - set_option_value((char_u *)"shm", 0L, (char_u *)"", 0); + set_option_value("shm", 0L, "", 0); goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum); - set_option_value((char_u *)"shm", 0L, p_shm_save, 0); + set_option_value("shm", 0L, (char *)p_shm_save, 0); xfree(p_shm_save); // If autocommands took us elsewhere, quit here. @@ -2238,14 +2252,14 @@ void ex_compiler(exarg_T *eap) // plugin will then skip the settings. Afterwards set // "b:current_compiler" and restore "current_compiler". // Explicitly prepend "g:" to make it work in a function. - old_cur_comp = get_var_value((char_u *)"g:current_compiler"); + old_cur_comp = get_var_value("g:current_compiler"); if (old_cur_comp != NULL) { old_cur_comp = vim_strsave(old_cur_comp); } do_cmdline_cmd("command -nargs=* CompilerSet setlocal <args>"); } - do_unlet((char_u *)"g:current_compiler", true); - do_unlet((char_u *)"b:current_compiler", true); + do_unlet(S_LEN("g:current_compiler"), true); + do_unlet(S_LEN("b:current_compiler"), true); snprintf((char *)buf, bufsize, "compiler/%s.vim", eap->arg); if (source_runtime(buf, DIP_ALL) == FAIL) { @@ -2256,7 +2270,7 @@ void ex_compiler(exarg_T *eap) do_cmdline_cmd(":delcommand CompilerSet"); // Set "b:current_compiler" from "current_compiler". - p = get_var_value((char_u *)"g:current_compiler"); + p = get_var_value("g:current_compiler"); if (p != NULL) { set_internal_string_var((char_u *)"b:current_compiler", p); } @@ -2268,7 +2282,7 @@ void ex_compiler(exarg_T *eap) old_cur_comp); xfree(old_cur_comp); } else { - do_unlet((char_u *)"g:current_compiler", true); + do_unlet(S_LEN("g:current_compiler"), true); } } } @@ -2305,16 +2319,6 @@ static void source_callback(char_u *fname, void *cookie) (void)do_source(fname, false, DOSO_NONE); } -/// Source the file "name" from all directories in 'runtimepath'. -/// "name" can contain wildcards. -/// When "flags" has DIP_ALL: source all files, otherwise only the first one. -/// -/// return FAIL when no file could be sourced, OK otherwise. -int source_runtime(char_u *name, int flags) -{ - return do_in_runtimepath(name, flags, source_callback, NULL); -} - /// Find the file "name" in all directories in "path" and invoke /// "callback(fname, cookie)". /// "name" can contain wildcards. @@ -2349,12 +2353,25 @@ int do_in_path(char_u *path, char_u *name, int flags, while (*rtp != NUL && ((flags & DIP_ALL) || !did_one)) { // Copy the path from 'runtimepath' to buf[]. copy_option_part(&rtp, buf, MAXPATHL, ","); + size_t buflen = STRLEN(buf); + + // Skip after or non-after directories. + if (flags & (DIP_NOAFTER | DIP_AFTER)) { + bool is_after = buflen >= 5 + && STRCMP(buf + buflen - 5, "after") == 0; + + if ((is_after && (flags & DIP_NOAFTER)) + || (!is_after && (flags & DIP_AFTER))) { + continue; + } + } + if (name == NULL) { (*callback)(buf, (void *)&cookie); if (!did_one) { did_one = (cookie == NULL); } - } else if (STRLEN(buf) + STRLEN(name) + 2 < MAXPATHL) { + } else if (buflen + STRLEN(name) + 2 < MAXPATHL) { add_pathsep((char *)buf); tail = buf + STRLEN(buf); @@ -2407,21 +2424,21 @@ int do_in_path(char_u *path, char_u *name, int flags, return did_one ? OK : FAIL; } -/// Find "name" in 'runtimepath'. When found, invoke the callback function for +/// Find "name" in "path". When found, invoke the callback function for /// it: callback(fname, "cookie") /// When "flags" has DIP_ALL repeat for all matches, otherwise only the first /// one is used. /// Returns OK when at least one match found, FAIL otherwise. -/// If "name" is NULL calls callback for each entry in runtimepath. Cookie is +/// If "name" is NULL calls callback for each entry in "path". Cookie is /// passed by reference in this case, setting it to NULL indicates that callback /// has done its job. -int do_in_runtimepath(char_u *name, int flags, DoInRuntimepathCB callback, - void *cookie) +int do_in_path_and_pp(char_u *path, char_u *name, int flags, + DoInRuntimepathCB callback, void *cookie) { int done = FAIL; if ((flags & DIP_NORTP) == 0) { - done = do_in_path(p_rtp, name, flags, callback, cookie); + done = do_in_path(path, name, flags, callback, cookie); } if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_START)) { @@ -2449,6 +2466,29 @@ int do_in_runtimepath(char_u *name, int flags, DoInRuntimepathCB callback, return done; } +/// Just like do_in_path_and_pp(), using 'runtimepath' for "path". +int do_in_runtimepath(char_u *name, int flags, DoInRuntimepathCB callback, + void *cookie) +{ + return do_in_path_and_pp(p_rtp, name, flags, callback, cookie); +} + +/// Source the file "name" from all directories in 'runtimepath'. +/// "name" can contain wildcards. +/// When "flags" has DIP_ALL: source all files, otherwise only the first one. +/// +/// return FAIL when no file could be sourced, OK otherwise. +int source_runtime(char_u *name, int flags) +{ + return source_in_path(p_rtp, name, flags); +} + +/// Just like source_runtime(), but use "path" instead of 'runtimepath'. +int source_in_path(char_u *path, char_u *name, int flags) +{ + return do_in_path_and_pp(path, name, flags, source_callback, NULL); +} + // Expand wildcards in "pat" and invoke do_source() for each match. static void source_all_matches(char_u *pat) { @@ -2471,16 +2511,17 @@ static int APP_BOTH; static void add_pack_plugin(char_u *fname, void *cookie) { char_u *p4, *p3, *p2, *p1, *p; - char_u *new_rtp; - char_u *ffname = (char_u *)fix_fname((char *)fname); + char_u *buf = NULL; + + char *const ffname = fix_fname((char *)fname); if (ffname == NULL) { return; } - if (cookie != &APP_LOAD && strstr((char *)p_rtp, (char *)ffname) == NULL) { + if (cookie != &APP_LOAD && strstr((char *)p_rtp, ffname) == NULL) { // directory is not yet in 'runtimepath', add it - p4 = p3 = p2 = p1 = get_past_head(ffname); + p4 = p3 = p2 = p1 = get_past_head((char_u *)ffname); for (p = p1; *p; mb_ptr_adv(p)) { if (vim_ispathsep_nocolon(*p)) { p4 = p3; p3 = p2; p2 = p1; p1 = p; @@ -2496,57 +2537,70 @@ static void add_pack_plugin(char_u *fname, void *cookie) *p4 = NUL; // Find "ffname" in "p_rtp", ignoring '/' vs '\' differences - size_t fname_len = STRLEN(ffname); - char_u *insp = p_rtp; - for (;;) { - if (vim_fnamencmp(insp, ffname, fname_len) == 0) { - break; + size_t fname_len = strlen(ffname); + const char *insp = (const char *)p_rtp; + buf = try_malloc(MAXPATHL); + if (buf == NULL) { + goto theend; + } + while (*insp != NUL) { + copy_option_part((char_u **)&insp, buf, MAXPATHL, ","); + add_pathsep((char *)buf); + char *const rtp_ffname = fix_fname((char *)buf); + if (rtp_ffname == NULL) { + goto theend; } - insp = vim_strchr(insp, ','); - if (insp == NULL) { + bool match = path_fnamencmp(rtp_ffname, ffname, fname_len) == 0; + xfree(rtp_ffname); + if (match) { break; } - insp++; } - if (insp == NULL) { + if (*insp == NUL) { // not found, append at the end - insp = p_rtp + STRLEN(p_rtp); + insp = (const char *)p_rtp + STRLEN(p_rtp); } else { // append after the matching directory. - insp += STRLEN(ffname); - while (*insp != NUL && *insp != ',') { - insp++; - } + insp--; } *p4 = c; // check if rtp/pack/name/start/name/after exists - char *afterdir = concat_fnames((char *)ffname, "after", true); + char *afterdir = concat_fnames(ffname, "after", true); size_t afterlen = 0; if (os_isdir((char_u *)afterdir)) { - afterlen = STRLEN(afterdir) + 1; // add one for comma + afterlen = strlen(afterdir) + 1; // add one for comma } - size_t oldlen = STRLEN(p_rtp); - size_t addlen = STRLEN(ffname) + 1; // add one for comma - new_rtp = try_malloc(oldlen + addlen + afterlen + 1); // add one for NUL + const size_t oldlen = STRLEN(p_rtp); + const size_t addlen = strlen(ffname) + 1; // add one for comma + const size_t new_rtp_len = oldlen + addlen + afterlen + 1; + // add one for NUL -------------------------------------^ + char *const new_rtp = try_malloc(new_rtp_len); if (new_rtp == NULL) { goto theend; } - uintptr_t keep = (uintptr_t)(insp - p_rtp); + const size_t keep = (size_t)(insp - (const char *)p_rtp); + size_t new_rtp_fill = 0; memmove(new_rtp, p_rtp, keep); - new_rtp[keep] = ','; - memmove(new_rtp + keep + 1, ffname, addlen); + new_rtp_fill += keep; + new_rtp[new_rtp_fill++] = ','; + memmove(new_rtp + new_rtp_fill, ffname, addlen); + new_rtp_fill += addlen - 1; + assert(new_rtp[new_rtp_fill] == NUL || new_rtp[new_rtp_fill] == ','); if (p_rtp[keep] != NUL) { - memmove(new_rtp + keep + addlen, p_rtp + keep, - oldlen - keep + 1); + memmove(new_rtp + new_rtp_fill, p_rtp + keep, oldlen - keep + 1); + new_rtp_fill += oldlen - keep; } if (afterlen > 0) { - STRCAT(new_rtp, ","); - STRCAT(new_rtp, afterdir); + assert(new_rtp[new_rtp_fill] == NUL); + new_rtp[new_rtp_fill++] = ','; + memmove(new_rtp + new_rtp_fill, afterdir, afterlen - 1); + new_rtp_fill += afterlen - 1; } - set_option_value((char_u *)"rtp", 0L, new_rtp, 0); + new_rtp[new_rtp_fill] = NUL; + set_option_value("rtp", 0L, new_rtp, 0); xfree(new_rtp); xfree(afterdir); } @@ -2555,7 +2609,7 @@ static void add_pack_plugin(char_u *fname, void *cookie) static const char *plugpat = "%s/plugin/**/*.vim"; // NOLINT static const char *ftpat = "%s/ftdetect/*.vim"; // NOLINT - size_t len = STRLEN(ffname) + STRLEN(ftpat); + size_t len = strlen(ffname) + STRLEN(ftpat); char_u *pat = try_malloc(len + 1); if (pat == NULL) { goto theend; @@ -2578,25 +2632,35 @@ static void add_pack_plugin(char_u *fname, void *cookie) } theend: + xfree(buf); xfree(ffname); } -static bool did_source_packages = false; +/// Add all packages in the "start" directory to 'runtimepath'. +void add_pack_start_dirs(void) +{ + do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, // NOLINT + add_pack_plugin, &APP_ADD_DIR); +} + +/// Load plugins from all packages in the "start" directory. +void load_start_packages(void) +{ + did_source_packages = true; + do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, // NOLINT + add_pack_plugin, &APP_LOAD); +} // ":packloadall" // Find plugins in the package directories and source them. void ex_packloadall(exarg_T *eap) { - if (!did_source_packages || (eap != NULL && eap->forceit)) { - did_source_packages = true; - + if (!did_source_packages || eap->forceit) { // First do a round to add all directories to 'runtimepath', then load // the plugins. This allows for plugins to use an autoload directory // of another plugin. - do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, // NOLINT - add_pack_plugin, &APP_ADD_DIR); - do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, // NOLINT - add_pack_plugin, &APP_LOAD); + add_pack_start_dirs(); + load_start_packages(); } } @@ -2680,14 +2744,7 @@ static FILE *fopen_noinh_readbin(char *filename) return NULL; } -#ifdef HAVE_FD_CLOEXEC - { - int fdflags = fcntl(fd_tmp, F_GETFD); - if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) { - (void)fcntl(fd_tmp, F_SETFD, fdflags | FD_CLOEXEC); - } - } -#endif + (void)os_set_cloexec(fd_tmp); return fdopen(fd_tmp, READBIN); } @@ -3581,18 +3638,11 @@ void ex_language(exarg_T *eap) static char_u **locales = NULL; // Array of all available locales -static bool did_init_locales = false; -/// Lazy initialization of all available locales. -static void init_locales(void) -{ - if (!did_init_locales) { - did_init_locales = true; - locales = find_locales(); - } -} +#ifndef WIN32 +static bool did_init_locales = false; -// Return an array of strings for all available locales + NULL for the +/// Return an array of strings for all available locales + NULL for the /// last element. Return NULL in case of error. static char_u **find_locales(void) { @@ -3624,6 +3674,18 @@ static char_u **find_locales(void) ((char_u **)locales_ga.ga_data)[locales_ga.ga_len] = NULL; return (char_u **)locales_ga.ga_data; } +#endif + +/// Lazy initialization of all available locales. +static void init_locales(void) +{ +#ifndef WIN32 + if (!did_init_locales) { + did_init_locales = true; + locales = find_locales(); + } +#endif +} # if defined(EXITFREE) void free_locales(void) @@ -3676,19 +3738,18 @@ char_u *get_locales(expand_T *xp, int idx) static void script_host_execute(char *name, exarg_T *eap) { - uint8_t *script = script_get(eap, eap->arg); + size_t len; + char *const script = script_get(eap, &len); - if (!eap->skip) { - list_T *args = list_alloc(); + if (script != NULL) { + list_T *const args = tv_list_alloc(); // script - list_append_string(args, script ? script : eap->arg, -1); + tv_list_append_allocated_string(args, script); // current range - list_append_number(args, (int)eap->line1); - list_append_number(args, (int)eap->line2); + tv_list_append_number(args, (int)eap->line1); + tv_list_append_number(args, (int)eap->line2); (void)eval_call_provider(name, "execute", args); } - - xfree(script); } static void script_host_execute_file(char *name, exarg_T *eap) @@ -3696,21 +3757,21 @@ static void script_host_execute_file(char *name, exarg_T *eap) uint8_t buffer[MAXPATHL]; vim_FullName((char *)eap->arg, (char *)buffer, sizeof(buffer), false); - list_T *args = list_alloc(); + list_T *args = tv_list_alloc(); // filename - list_append_string(args, buffer, -1); + tv_list_append_string(args, (const char *)buffer, -1); // current range - list_append_number(args, (int)eap->line1); - list_append_number(args, (int)eap->line2); + tv_list_append_number(args, (int)eap->line1); + tv_list_append_number(args, (int)eap->line2); (void)eval_call_provider(name, "execute_file", args); } static void script_host_do_range(char *name, exarg_T *eap) { - list_T *args = list_alloc(); - list_append_number(args, (int)eap->line1); - list_append_number(args, (int)eap->line2); - list_append_string(args, eap->arg, -1); + list_T *args = tv_list_alloc(); + tv_list_append_number(args, (int)eap->line1); + tv_list_append_number(args, (int)eap->line2); + tv_list_append_string(args, (const char *)eap->arg, -1); (void)eval_call_provider(name, "do_range", args); } diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h index c6389a0c8b..d72b83404e 100644 --- a/src/nvim/ex_cmds_defs.h +++ b/src/nvim/ex_cmds_defs.h @@ -6,6 +6,7 @@ #include "nvim/pos.h" // for linenr_T #include "nvim/normal.h" +#include "nvim/regexp_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ex_cmds_enum.generated.h" @@ -72,7 +73,8 @@ #define ADDR_LOADED_BUFFERS 3 #define ADDR_BUFFERS 4 #define ADDR_TABS 5 -#define ADDR_QUICKFIX 6 +#define ADDR_TABS_RELATIVE 6 // Tab page that only relative +#define ADDR_QUICKFIX 7 #define ADDR_OTHER 99 typedef struct exarg exarg_T; @@ -162,18 +164,20 @@ struct expand { /// flag. This needs to be saved for recursive commands, put them in a /// structure for easy manipulation. typedef struct { - int split; ///< flags for win_split() - int tab; ///< > 0 when ":tab" was used - bool browse; ///< true to invoke file dialog - bool confirm; ///< true to invoke yes/no dialog - bool hide; ///< true when ":hide" was used - bool keepalt; ///< true when ":keepalt" was used - bool keepjumps; ///< true when ":keepjumps" was used - bool keepmarks; ///< true when ":keepmarks" was used - bool keeppatterns; ///< true when ":keeppatterns" was used - bool lockmarks; ///< true when ":lockmarks" was used - bool noswapfile; ///< true when ":noswapfile" was used - char_u *save_ei; ///< saved value of 'eventignore' + int split; ///< flags for win_split() + int tab; ///< > 0 when ":tab" was used + bool browse; ///< true to invoke file dialog + bool confirm; ///< true to invoke yes/no dialog + bool hide; ///< true when ":hide" was used + bool keepalt; ///< true when ":keepalt" was used + bool keepjumps; ///< true when ":keepjumps" was used + bool keepmarks; ///< true when ":keepmarks" was used + bool keeppatterns; ///< true when ":keeppatterns" was used + bool lockmarks; ///< true when ":lockmarks" was used + bool noswapfile; ///< true when ":noswapfile" was used + char_u *save_ei; ///< saved value of 'eventignore' + regmatch_T filter_regmatch; ///< set by :filter /pat/ + bool filter_force; ///< set for :filter! } cmdmod_T; #endif // NVIM_EX_CMDS_DEFS_H diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index eccece7ac7..d1405978b3 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * ex_docmd.c: functions for executing an Ex command line. */ @@ -50,6 +53,7 @@ #include "nvim/screen.h" #include "nvim/search.h" #include "nvim/spell.h" +#include "nvim/spellfile.h" #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tag.h" @@ -66,6 +70,8 @@ #include "nvim/event/rstream.h" #include "nvim/event/wstream.h" #include "nvim/shada.h" +#include "nvim/lua/executor.h" +#include "nvim/globals.h" static int quitmore = 0; static int ex_pressedreturn = FALSE; @@ -268,7 +274,7 @@ do_exmode ( /* * Execute a simple command line. Used for translated commands like "*". */ -int do_cmdline_cmd(char *cmd) +int do_cmdline_cmd(const char *cmd) { return do_cmdline((char_u *)cmd, NULL, NULL, DOCMD_NOWAIT|DOCMD_KEYTYPED); @@ -334,12 +340,13 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, msg_list = &private_msg_list; private_msg_list = NULL; - /* It's possible to create an endless loop with ":execute", catch that - * here. The value of 200 allows nested function calls, ":source", etc. */ - if (call_depth == 200) { + // It's possible to create an endless loop with ":execute", catch that + // here. The value of 200 allows nested function calls, ":source", etc. + // Allow 200 or 'maxfuncdepth', whatever is larger. + if (call_depth >= 200 && call_depth >= p_mfd) { EMSG(_("E169: Command too recursive")); - /* When converting to an exception, we do not include the command name - * since this is not an error of the specific command. */ + // When converting to an exception, we do not include the command name + // since this is not an error of the specific command. do_errthrow((struct condstack *)NULL, (char_u *)NULL); msg_list = saved_msg_list; return FAIL; @@ -583,10 +590,10 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, ++no_wait_return; verbose_enter_scroll(); - smsg(_("line %" PRId64 ": %s"), - (int64_t)sourcing_lnum, cmdline_copy); - if (msg_silent == 0) - msg_puts((char_u *)"\n"); /* don't overwrite this */ + smsg(_("line %" PRIdLINENR ": %s"), sourcing_lnum, cmdline_copy); + if (msg_silent == 0) { + msg_puts("\n"); // don't overwrite this either + } verbose_leave_scroll(); --no_wait_return; @@ -838,8 +845,6 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, break; case ET_INTERRUPT: break; - default: - p = vim_strsave((char_u *)_(e_internal)); } saved_sourcing_name = sourcing_name; @@ -1244,6 +1249,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, cmdmod_T save_cmdmod; int ni; /* set when Not Implemented */ char_u *cmd; + int address_count = 1; memset(&ea, 0, sizeof(ea)); ea.line1 = 1; @@ -1301,7 +1307,6 @@ static char_u * do_one_cmd(char_u **cmdlinep, /* * 2. Handle command modifiers. */ - p = ea.cmd; p = skip_range(ea.cmd, NULL); switch (*p) { /* When adding an entry, also modify cmd_exists(). */ @@ -1345,6 +1350,31 @@ static char_u * do_one_cmd(char_u **cmdlinep, cmdmod.keepjumps = true; continue; + case 'f': { // only accept ":filter {pat} cmd" + char_u *reg_pat; + + if (!checkforcmd(&p, "filter", 4) || *p == NUL || ends_excmd(*p)) { + break; + } + if (*p == '!') { + cmdmod.filter_force = true; + p = skipwhite(p + 1); + if (*p == NUL || ends_excmd(*p)) { + break; + } + } + p = skip_vimgrep_pat(p, ®_pat, NULL); + if (p == NULL || *p == NUL) { + break; + } + cmdmod.filter_regmatch.regprog = vim_regcomp(reg_pat, RE_MAGIC); + if (cmdmod.filter_regmatch.regprog == NULL) { + break; + } + ea.cmd = p; + continue; + } + /* ":hide" and ":hide | cmd" are not modifiers */ case 'h': if (p != ea.cmd || !checkforcmd(&p, "hide", 3) || *p == NUL || ends_excmd(*p)) @@ -1405,7 +1435,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, continue; case 't': if (checkforcmd(&p, "tab", 3)) { - long tabnr = get_address(&ea, &ea.cmd, ADDR_TABS, ea.skip, false); + long tabnr = get_address(&ea, &ea.cmd, ADDR_TABS, ea.skip, false, 1); if (tabnr == MAXLNUM) { cmdmod.tab = tabpage_index(curtab) + 1; } else { @@ -1447,6 +1477,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, } break; } + char_u *after_modifier = ea.cmd; ea.skip = did_emsg || got_int || did_throw || (cstack->cs_idx >= 0 && !(cstack->cs_flags[cstack-> @@ -1520,8 +1551,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, ea.line2 = curwin->w_cursor.lnum; break; case ADDR_WINDOWS: - lnum = CURRENT_WIN_NR; - ea.line2 = lnum; + ea.line2 = CURRENT_WIN_NR; break; case ADDR_ARGUMENTS: ea.line2 = curwin->w_arg_idx + 1; @@ -1534,8 +1564,10 @@ static char_u * do_one_cmd(char_u **cmdlinep, ea.line2 = curbuf->b_fnum; break; case ADDR_TABS: - lnum = CURRENT_TAB_NR; - ea.line2 = lnum; + ea.line2 = CURRENT_TAB_NR; + break; + case ADDR_TABS_RELATIVE: + ea.line2 = 1; break; case ADDR_QUICKFIX: ea.line2 = qf_get_cur_valid_idx(&ea); @@ -1543,7 +1575,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, } ea.cmd = skipwhite(ea.cmd); lnum = get_address(&ea, &ea.cmd, ea.addr_type, ea.skip, - ea.addr_count == 0); + ea.addr_count == 0, address_count++); if (ea.cmd == NULL) { // error detected goto doend; } @@ -1585,6 +1617,10 @@ static char_u * do_one_cmd(char_u **cmdlinep, goto doend; } break; + case ADDR_TABS_RELATIVE: + errormsg = (char_u *)_(e_invrange); + goto doend; + break; case ADDR_ARGUMENTS: if (ARGCOUNT == 0) { ea.line1 = ea.line2 = 0; @@ -1630,11 +1666,15 @@ static char_u * do_one_cmd(char_u **cmdlinep, ea.addr_count++; if (*ea.cmd == ';') { - if (!ea.skip) + if (!ea.skip) { curwin->w_cursor.lnum = ea.line2; - } else if (*ea.cmd != ',') + // Don't leave the cursor on an illegal line (caused by ';') + check_cursor_lnum(); + } + } else if (*ea.cmd != ',') { break; - ++ea.cmd; + } + ea.cmd++; } /* One address given: set start and end lines */ @@ -1645,9 +1685,6 @@ static char_u * do_one_cmd(char_u **cmdlinep, ea.addr_count = 0; } - /* Don't leave the cursor on an illegal line (caused by ';') */ - check_cursor_lnum(); - /* * 5. Parse the command. */ @@ -1719,16 +1756,18 @@ static char_u * do_one_cmd(char_u **cmdlinep, errormsg = (char_u *)_("E464: Ambiguous use of user-defined command"); goto doend; } - /* Check for wrong commands. */ - if (*p == '!' && ea.cmd[1] == 0151 && ea.cmd[0] == 78) { - errormsg = uc_fun_cmd(); - goto doend; - } + // Check for wrong commands. if (ea.cmdidx == CMD_SIZE) { if (!ea.skip) { STRCPY(IObuff, _("E492: Not an editor command")); if (!(flags & DOCMD_VERBOSE)) { - append_command(*cmdlinep); + // If the modifier was parsed OK the error must be in the following + // command + if (after_modifier != NULL) { + append_command(after_modifier); + } else { + append_command(*cmdlinep); + } } errormsg = IObuff; did_emsg_syntax = TRUE; @@ -1815,9 +1854,9 @@ static char_u * do_one_cmd(char_u **cmdlinep, errormsg = (char_u *)_("E493: Backwards range given"); goto doend; } - if (ask_yesno((char_u *) - _("Backwards range given, OK to swap"), FALSE) != 'y') + if (ask_yesno(_("Backwards range given, OK to swap"), false) != 'y') { goto doend; + } } lnum = ea.line1; ea.line1 = ea.line2; @@ -1971,6 +2010,9 @@ static char_u * do_one_cmd(char_u **cmdlinep, case ADDR_TABS: ea.line2 = LAST_TAB_NR; break; + case ADDR_TABS_RELATIVE: + ea.line2 = 1; + break; case ADDR_ARGUMENTS: if (ARGCOUNT == 0) { ea.line1 = ea.line2 = 0; @@ -2026,11 +2068,11 @@ static char_u * do_one_cmd(char_u **cmdlinep, ea.line1 = ea.line2; ea.line2 += n - 1; ++ea.addr_count; - /* - * Be vi compatible: no error message for out of range. - */ - if (ea.line2 > curbuf->b_ml.ml_line_count) + // Be vi compatible: no error message for out of range. + if (ea.addr_type == ADDR_LINES + && ea.line2 > curbuf->b_ml.ml_line_count) { ea.line2 = curbuf->b_ml.ml_line_count; + } } } @@ -2095,6 +2137,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, case CMD_echomsg: case CMD_echon: case CMD_execute: + case CMD_filter: case CMD_help: case CMD_hide: case CMD_ijump: @@ -2246,6 +2289,10 @@ doend: free_string_option(cmdmod.save_ei); } + if (cmdmod.filter_regmatch.regprog != NULL) { + vim_regfree(cmdmod.filter_regmatch.regprog); + } + cmdmod = save_cmdmod; if (save_msg_silent != -1) { @@ -2531,28 +2578,29 @@ static struct cmdmod { int minlen; int has_count; /* :123verbose :3tab */ } cmdmods[] = { - {"aboveleft", 3, FALSE}, - {"belowright", 3, FALSE}, - {"botright", 2, FALSE}, - {"browse", 3, FALSE}, - {"confirm", 4, FALSE}, - {"hide", 3, FALSE}, - {"keepalt", 5, FALSE}, - {"keepjumps", 5, FALSE}, - {"keepmarks", 3, FALSE}, - {"keeppatterns", 5, FALSE}, - {"leftabove", 5, FALSE}, - {"lockmarks", 3, FALSE}, - {"noautocmd", 3, FALSE}, - {"noswapfile", 3, FALSE}, - {"rightbelow", 6, FALSE}, - {"sandbox", 3, FALSE}, - {"silent", 3, FALSE}, - {"tab", 3, TRUE}, - {"topleft", 2, FALSE}, - {"unsilent", 3, FALSE}, - {"verbose", 4, TRUE}, - {"vertical", 4, FALSE}, + { "aboveleft", 3, false }, + { "belowright", 3, false }, + { "botright", 2, false }, + { "browse", 3, false }, + { "confirm", 4, false }, + { "filter", 4, false }, + { "hide", 3, false }, + { "keepalt", 5, false }, + { "keepjumps", 5, false }, + { "keepmarks", 3, false }, + { "keeppatterns", 5, false }, + { "leftabove", 5, false }, + { "lockmarks", 3, false }, + { "noautocmd", 3, false }, + { "noswapfile", 3, false }, + { "rightbelow", 6, false }, + { "sandbox", 3, false }, + { "silent", 3, false }, + { "tab", 3, true }, + { "topleft", 2, false }, + { "unsilent", 3, false }, + { "verbose", 4, true }, + { "vertical", 4, false }, }; /* @@ -2582,27 +2630,29 @@ int modifier_len(char_u *cmd) * Return 2 if there is an exact match. * Return 3 if there is an ambiguous match. */ -int cmd_exists(char_u *name) +int cmd_exists(const char *const name) { exarg_T ea; - int full = FALSE; - int i; - int j; char_u *p; - /* Check command modifiers. */ - for (i = 0; i < (int)ARRAY_SIZE(cmdmods); ++i) { - for (j = 0; name[j] != NUL; ++j) - if (name[j] != cmdmods[i].name[j]) + // Check command modifiers. + for (int i = 0; i < (int)ARRAY_SIZE(cmdmods); i++) { + int j; + for (j = 0; name[j] != NUL; j++) { + if (name[j] != (char)cmdmods[i].name[j]) { break; - if (name[j] == NUL && j >= cmdmods[i].minlen) + } + } + if (name[j] == NUL && j >= cmdmods[i].minlen) { return cmdmods[i].name[j] == NUL ? 2 : 1; + } } /* Check built-in commands and user defined commands. * For ":2match" and ":3match" we need to skip the number. */ - ea.cmd = (*name == '2' || *name == '3') ? name + 1 : name; + ea.cmd = (char_u *)((*name == '2' || *name == '3') ? name + 1 : name); ea.cmdidx = (cmdidx_T)0; + int full = false; p = find_command(&ea, &full); if (p == NULL) return 3; @@ -2620,32 +2670,27 @@ int cmd_exists(char_u *name) * perfectly compatible with each other, but then the command line syntax * probably won't change that much -- webb. */ -char_u * -set_one_cmd_context ( +const char * set_one_cmd_context( expand_T *xp, - char_u *buff /* buffer for command string */ + const char *buff // buffer for command string ) { - char_u *p; - char_u *cmd, *arg; - int len = 0; + size_t len = 0; exarg_T ea; - int compl = EXPAND_NOTHING; - int delim; - int forceit = FALSE; - int usefilter = FALSE; /* filter instead of file name */ + int context = EXPAND_NOTHING; + int forceit = false; + int usefilter = false; // Filter instead of file name. ExpandInit(xp); - xp->xp_pattern = buff; - xp->xp_context = EXPAND_COMMANDS; /* Default until we get past command */ + xp->xp_pattern = (char_u *)buff; + xp->xp_context = EXPAND_COMMANDS; // Default until we get past command ea.argt = 0; - /* - * 2. skip comment lines and leading space, colons or bars - */ - for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++) - ; - xp->xp_pattern = cmd; + // 2. skip comment lines and leading space, colons or bars + const char *cmd; + for (cmd = buff; vim_strchr((const char_u *)" \t:|", *cmd) != NULL; cmd++) { + } + xp->xp_pattern = (char_u *)cmd; if (*cmd == NUL) return NULL; @@ -2657,14 +2702,15 @@ set_one_cmd_context ( /* * 3. parse a range specifier of the form: addr [,addr] [;addr] .. */ - cmd = skip_range(cmd, &xp->xp_context); + cmd = (const char *)skip_range((const char_u *)cmd, &xp->xp_context); /* * 4. parse command */ - xp->xp_pattern = cmd; - if (*cmd == NUL) + xp->xp_pattern = (char_u *)cmd; + if (*cmd == NUL) { return NULL; + } if (*cmd == '"') { xp->xp_context = EXPAND_NOTHING; return NULL; @@ -2680,6 +2726,7 @@ set_one_cmd_context ( * do accept "keepmarks", "keepalt" and "keepjumps". * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r' */ + const char *p; if (*cmd == 'k' && cmd[1] != 'e') { ea.cmdidx = CMD_k; p = cmd + 1; @@ -2702,20 +2749,21 @@ set_one_cmd_context ( } } // check for non-alpha command - if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL) { + if (p == cmd && vim_strchr((const char_u *)"@*!=><&~#", *p) != NULL) { p++; } - len = (int)(p - cmd); + len = (size_t)(p - cmd); if (len == 0) { xp->xp_context = EXPAND_UNSUCCESSFUL; return NULL; } for (ea.cmdidx = (cmdidx_T)0; (int)ea.cmdidx < (int)CMD_SIZE; - ea.cmdidx = (cmdidx_T)((int)ea.cmdidx + 1)) - if (STRNCMP(cmdnames[(int)ea.cmdidx].cmd_name, cmd, - (size_t)len) == 0) + ea.cmdidx = (cmdidx_T)((int)ea.cmdidx + 1)) { + if (STRNCMP(cmdnames[(int)ea.cmdidx].cmd_name, cmd, len) == 0) { break; + } + } if (cmd[0] >= 'A' && cmd[0] <= 'Z') { while (ASCII_ISALNUM(*p) || *p == '*') { // Allow * wild card @@ -2732,16 +2780,15 @@ set_one_cmd_context ( return NULL; if (ea.cmdidx == CMD_SIZE) { - if (*cmd == 's' && vim_strchr((char_u *)"cgriI", cmd[1]) != NULL) { + if (*cmd == 's' && vim_strchr((const char_u *)"cgriI", cmd[1]) != NULL) { ea.cmdidx = CMD_substitute; p = cmd + 1; } else if (cmd[0] >= 'A' && cmd[0] <= 'Z') { - ea.cmd = cmd; - p = find_ucmd(&ea, p, NULL, xp, - &compl - ); - if (p == NULL) - ea.cmdidx = CMD_SIZE; /* ambiguous user command */ + ea.cmd = (char_u *)cmd; + p = (const char *)find_ucmd(&ea, (char_u *)p, NULL, xp, &context); + if (p == NULL) { + ea.cmdidx = CMD_SIZE; // Ambiguous user command. + } } } if (ea.cmdidx == CMD_SIZE) { @@ -2764,16 +2811,17 @@ set_one_cmd_context ( ea.argt = cmdnames[(int)ea.cmdidx].cmd_argt; } - arg = skipwhite(p); + const char *arg = (const char *)skipwhite((const char_u *)p); if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) { - if (*arg == '>') { /* append */ - if (*++arg == '>') - ++arg; - arg = skipwhite(arg); - } else if (*arg == '!' && ea.cmdidx == CMD_write) { /* :w !filter */ - ++arg; - usefilter = TRUE; + if (*arg == '>') { // Append. + if (*++arg == '>') { + arg++; + } + arg = (const char *)skipwhite((const char_u *)arg); + } else if (*arg == '!' && ea.cmdidx == CMD_write) { // :w !filter + arg++; + usefilter = true; } } @@ -2786,23 +2834,24 @@ set_one_cmd_context ( } if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) { - while (*arg == *cmd) /* allow any number of '>' or '<' */ - ++arg; - arg = skipwhite(arg); + while (*arg == *cmd) { // allow any number of '>' or '<' + arg++; + } + arg = (const char *)skipwhite((const char_u *)arg); } /* Does command allow "+command"? */ if ((ea.argt & EDITCMD) && !usefilter && *arg == '+') { /* Check if we're in the +command */ p = arg + 1; - arg = skip_cmd_arg(arg, FALSE); + arg = (const char *)skip_cmd_arg((char_u *)arg, false); /* Still touching the command after '+'? */ if (*arg == NUL) return p; - /* Skip space(s) after +command to get to the real argument */ - arg = skipwhite(arg); + // Skip space(s) after +command to get to the real argument. + arg = (const char *)skipwhite((const char_u *)arg); } /* @@ -2831,19 +2880,18 @@ set_one_cmd_context ( } // no arguments allowed - if (!(ea.argt & EXTRA) && *arg != NUL - && vim_strchr((char_u *)"|\"", *arg) == NULL) { + if (!(ea.argt & EXTRA) && *arg != NUL && strchr("|\"", *arg) == NULL) { return NULL; } /* Find start of last argument (argument just before cursor): */ p = buff; - xp->xp_pattern = p; - len = (int)STRLEN(buff); + xp->xp_pattern = (char_u *)p; + len = strlen(buff); while (*p && p < buff + len) { if (*p == ' ' || *p == TAB) { - /* argument starts after a space */ - xp->xp_pattern = ++p; + // Argument starts after a space. + xp->xp_pattern = (char_u *)++p; } else { if (*p == '\\' && *(p + 1) != NUL) ++p; /* skip over escaped character */ @@ -2853,25 +2901,26 @@ set_one_cmd_context ( if (ea.argt & XFILE) { int c; - int in_quote = FALSE; - char_u *bow = NULL; /* Beginning of word */ + int in_quote = false; + const char *bow = NULL; // Beginning of word. /* * Allow spaces within back-quotes to count as part of the argument * being expanded. */ - xp->xp_pattern = skipwhite(arg); - p = xp->xp_pattern; + xp->xp_pattern = skipwhite((const char_u *)arg); + p = (const char *)xp->xp_pattern; while (*p != NUL) { - if (has_mbyte) - c = mb_ptr2char(p); - else - c = *p; - if (c == '\\' && p[1] != NUL) - ++p; - else if (c == '`') { + if (has_mbyte) { + c = mb_ptr2char((const char_u *)p); + } else { + c = (uint8_t)(*p); + } + if (c == '\\' && p[1] != NUL) { + p++; + } else if (c == '`') { if (!in_quote) { - xp->xp_pattern = p; + xp->xp_pattern = (char_u *)p; bow = p + 1; } in_quote = !in_quote; @@ -2884,22 +2933,26 @@ set_one_cmd_context ( || ascii_iswhite(c)) { len = 0; /* avoid getting stuck when space is in 'isfname' */ while (*p != NUL) { - if (has_mbyte) - c = mb_ptr2char(p); - else + if (has_mbyte) { + c = mb_ptr2char((const char_u *)p); + } else { c = *p; - if (c == '`' || vim_isfilec_or_wc(c)) + } + if (c == '`' || vim_isfilec_or_wc(c)) { break; - if (has_mbyte) - len = (*mb_ptr2len)(p); - else + } + if (has_mbyte) { + len = (size_t)(*mb_ptr2len)((const char_u *)p); + } else { len = 1; + } mb_ptr_adv(p); } - if (in_quote) + if (in_quote) { bow = p; - else - xp->xp_pattern = p; + } else { + xp->xp_pattern = (char_u *)p; + } p -= len; } mb_ptr_adv(p); @@ -2909,8 +2962,9 @@ set_one_cmd_context ( * If we are still inside the quotes, and we passed a space, just * expand from there. */ - if (bow != NULL && in_quote) - xp->xp_pattern = bow; + if (bow != NULL && in_quote) { + xp->xp_pattern = (char_u *)bow; + } xp->xp_context = EXPAND_FILES; /* For a shell command more chars need to be escaped. */ @@ -2918,33 +2972,36 @@ set_one_cmd_context ( #ifndef BACKSLASH_IN_FILENAME xp->xp_shell = TRUE; #endif - /* When still after the command name expand executables. */ - if (xp->xp_pattern == skipwhite(arg)) + // When still after the command name expand executables. + if (xp->xp_pattern == skipwhite((const char_u *)arg)) { xp->xp_context = EXPAND_SHELLCMD; + } } - /* Check for environment variable */ - if (*xp->xp_pattern == '$' - ) { - for (p = xp->xp_pattern + 1; *p != NUL; ++p) - if (!vim_isIDc(*p)) + // Check for environment variable. + if (*xp->xp_pattern == '$') { + for (p = (const char *)xp->xp_pattern + 1; *p != NUL; p++) { + if (!vim_isIDc((uint8_t)(*p))) { break; + } + } if (*p == NUL) { xp->xp_context = EXPAND_ENV_VARS; - ++xp->xp_pattern; - /* Avoid that the assignment uses EXPAND_FILES again. */ - if (compl != EXPAND_USER_DEFINED && compl != EXPAND_USER_LIST) - compl = EXPAND_ENV_VARS; + xp->xp_pattern++; + // Avoid that the assignment uses EXPAND_FILES again. + if (context != EXPAND_USER_DEFINED && context != EXPAND_USER_LIST) { + context = EXPAND_ENV_VARS; + } } } /* Check for user names */ if (*xp->xp_pattern == '~') { - for (p = xp->xp_pattern + 1; *p != NUL && *p != '/'; ++p) - ; - /* Complete ~user only if it partially matches a user name. - * A full match ~user<Tab> will be replaced by user's home - * directory i.e. something like ~user<Tab> -> /home/user/ */ - if (*p == NUL && p > xp->xp_pattern + 1 + for (p = (const char *)xp->xp_pattern + 1; *p != NUL && *p != '/'; p++) { + } + // Complete ~user only if it partially matches a user name. + // A full match ~user<Tab> will be replaced by user's home + // directory i.e. something like ~user<Tab> -> /home/user/ + if (*p == NUL && p > (const char *)xp->xp_pattern + 1 && match_user(xp->xp_pattern + 1) == 1) { xp->xp_context = EXPAND_USER; ++xp->xp_pattern; @@ -2974,7 +3031,7 @@ set_one_cmd_context ( break; case CMD_help: xp->xp_context = EXPAND_HELP; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; /* Command modifiers: return the argument. @@ -3013,17 +3070,28 @@ set_one_cmd_context ( case CMD_windo: return arg; + case CMD_filter: + if (*arg != NUL) { + arg = (const char *)skip_vimgrep_pat((char_u *)arg, NULL, NULL); + } + if (arg == NULL || *arg == NUL) { + xp->xp_context = EXPAND_NOTHING; + return NULL; + } + return (const char *)skipwhite((const char_u *)arg); + case CMD_match: if (*arg == NUL || !ends_excmd(*arg)) { /* also complete "None" */ set_context_in_echohl_cmd(xp, arg); - arg = skipwhite(skiptowhite(arg)); + arg = (const char *)skipwhite(skiptowhite((const char_u *)arg)); if (*arg != NUL) { xp->xp_context = EXPAND_NOTHING; - arg = skip_regexp(arg + 1, *arg, p_magic, NULL); + arg = (const char *)skip_regexp((char_u *)arg + 1, (uint8_t)(*arg), + p_magic, NULL); } } - return find_nextcmd(arg); + return (const char *)find_nextcmd((char_u *)arg); /* * All completion for the +cmdline_compl feature goes here. @@ -3032,15 +3100,15 @@ set_one_cmd_context ( case CMD_command: /* Check for attributes */ while (*arg == '-') { - arg++; /* Skip "-" */ - p = skiptowhite(arg); + arg++; // Skip "-". + p = (const char *)skiptowhite((const char_u *)arg); if (*p == NUL) { - /* Cursor is still in the attribute */ - p = vim_strchr(arg, '='); + // Cursor is still in the attribute. + p = strchr(arg, '='); if (p == NULL) { - /* No "=", so complete attribute names */ + // No "=", so complete attribute names. xp->xp_context = EXPAND_USER_CMD_FLAGS; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; return NULL; } @@ -3048,73 +3116,81 @@ set_one_cmd_context ( // their arguments as well. if (STRNICMP(arg, "complete", p - arg) == 0) { xp->xp_context = EXPAND_USER_COMPLETE; - xp->xp_pattern = p + 1; + xp->xp_pattern = (char_u *)p + 1; return NULL; } else if (STRNICMP(arg, "nargs", p - arg) == 0) { xp->xp_context = EXPAND_USER_NARGS; - xp->xp_pattern = p + 1; + xp->xp_pattern = (char_u *)p + 1; return NULL; } else if (STRNICMP(arg, "addr", p - arg) == 0) { xp->xp_context = EXPAND_USER_ADDR_TYPE; - xp->xp_pattern = p + 1; + xp->xp_pattern = (char_u *)p + 1; return NULL; } return NULL; } - arg = skipwhite(p); + arg = (const char *)skipwhite((char_u *)p); } - /* After the attributes comes the new command name */ - p = skiptowhite(arg); + // After the attributes comes the new command name. + p = (const char *)skiptowhite((const char_u *)arg); if (*p == NUL) { xp->xp_context = EXPAND_USER_COMMANDS; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; } - /* And finally comes a normal command */ - return skipwhite(p); + // And finally comes a normal command. + return (const char *)skipwhite((const char_u *)p); case CMD_delcommand: xp->xp_context = EXPAND_USER_COMMANDS; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_global: - case CMD_vglobal: - delim = *arg; /* get the delimiter */ - if (delim) - ++arg; /* skip delimiter if there is one */ + case CMD_vglobal: { + const int delim = (uint8_t)(*arg); // Get the delimiter. + if (delim) { + arg++; // Skip delimiter if there is one. + } - while (arg[0] != NUL && arg[0] != delim) { - if (arg[0] == '\\' && arg[1] != NUL) - ++arg; - ++arg; + while (arg[0] != NUL && (uint8_t)arg[0] != delim) { + if (arg[0] == '\\' && arg[1] != NUL) { + arg++; + } + arg++; } if (arg[0] != NUL) return arg + 1; break; + } case CMD_and: - case CMD_substitute: - delim = *arg; + case CMD_substitute: { + const int delim = (uint8_t)(*arg); if (delim) { - /* skip "from" part */ - ++arg; - arg = skip_regexp(arg, delim, p_magic, NULL); + // Skip "from" part. + arg++; + arg = (const char *)skip_regexp((char_u *)arg, delim, p_magic, NULL); } - /* skip "to" part */ - while (arg[0] != NUL && arg[0] != delim) { - if (arg[0] == '\\' && arg[1] != NUL) - ++arg; - ++arg; + // Skip "to" part. + while (arg[0] != NUL && (uint8_t)arg[0] != delim) { + if (arg[0] == '\\' && arg[1] != NUL) { + arg++; + } + arg++; } - if (arg[0] != NUL) /* skip delimiter */ - ++arg; - while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL) - ++arg; - if (arg[0] != NUL) + if (arg[0] != NUL) { // Skip delimiter. + arg++; + } + while (arg[0] && strchr("|\"#", arg[0]) == NULL) { + arg++; + } + if (arg[0] != NUL) { return arg; + } break; + } case CMD_isearch: case CMD_dsearch: case CMD_ilist: @@ -3124,36 +3200,40 @@ set_one_cmd_context ( case CMD_djump: case CMD_isplit: case CMD_dsplit: - arg = skipwhite(skipdigits(arg)); /* skip count */ - if (*arg == '/') { /* Match regexp, not just whole words */ - for (++arg; *arg && *arg != '/'; arg++) - if (*arg == '\\' && arg[1] != NUL) + // Skip count. + arg = (const char *)skipwhite(skipdigits((const char_u *)arg)); + if (*arg == '/') { // Match regexp, not just whole words. + for (++arg; *arg && *arg != '/'; arg++) { + if (*arg == '\\' && arg[1] != NUL) { arg++; + } + } if (*arg) { - arg = skipwhite(arg + 1); + arg = (const char *)skipwhite((const char_u *)arg + 1); - /* Check for trailing illegal characters */ - if (*arg && vim_strchr((char_u *)"|\"\n", *arg) == NULL) + // Check for trailing illegal characters. + if (*arg && strchr("|\"\n", *arg) == NULL) { xp->xp_context = EXPAND_NOTHING; - else + } else { return arg; + } } } break; case CMD_autocmd: - return set_context_in_autocmd(xp, arg, FALSE); + return (const char *)set_context_in_autocmd(xp, (char_u *)arg, false); case CMD_doautocmd: case CMD_doautoall: - return set_context_in_autocmd(xp, arg, TRUE); + return (const char *)set_context_in_autocmd(xp, (char_u *)arg, true); case CMD_set: - set_context_in_set_cmd(xp, arg, 0); + set_context_in_set_cmd(xp, (char_u *)arg, 0); break; case CMD_setglobal: - set_context_in_set_cmd(xp, arg, OPT_GLOBAL); + set_context_in_set_cmd(xp, (char_u *)arg, OPT_GLOBAL); break; case CMD_setlocal: - set_context_in_set_cmd(xp, arg, OPT_LOCAL); + set_context_in_set_cmd(xp, (char_u *)arg, OPT_LOCAL); break; case CMD_tag: case CMD_stag: @@ -3165,15 +3245,16 @@ set_one_cmd_context ( case CMD_tjump: case CMD_stjump: case CMD_ptjump: - if (*p_wop != NUL) + if (*p_wop != NUL) { xp->xp_context = EXPAND_TAGS_LISTFILES; - else + } else { xp->xp_context = EXPAND_TAGS; - xp->xp_pattern = arg; + } + xp->xp_pattern = (char_u *)arg; break; case CMD_augroup: xp->xp_context = EXPAND_AUGROUP; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_syntax: set_context_in_syntax_cmd(xp, arg); @@ -3190,20 +3271,21 @@ set_one_cmd_context ( case CMD_echoerr: case CMD_call: case CMD_return: - set_context_for_expression(xp, arg, ea.cmdidx); + set_context_for_expression(xp, (char_u *)arg, ea.cmdidx); break; case CMD_unlet: - while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) - arg = xp->xp_pattern + 1; + while ((xp->xp_pattern = (char_u *)strchr(arg, ' ')) != NULL) { + arg = (const char *)xp->xp_pattern + 1; + } xp->xp_context = EXPAND_USER_VARS; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_function: case CMD_delfunction: xp->xp_context = EXPAND_USER_FUNC; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_echohl: @@ -3218,33 +3300,37 @@ set_one_cmd_context ( set_context_in_cscope_cmd(xp, arg, ea.cmdidx); break; case CMD_sign: - set_context_in_sign_cmd(xp, arg); + set_context_in_sign_cmd(xp, (char_u *)arg); break; case CMD_bdelete: case CMD_bwipeout: case CMD_bunload: - while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) - arg = xp->xp_pattern + 1; - /*FALLTHROUGH*/ + while ((xp->xp_pattern = (char_u *)strchr(arg, ' ')) != NULL) { + arg = (const char *)xp->xp_pattern + 1; + } + // FALLTHROUGH case CMD_buffer: case CMD_sbuffer: case CMD_checktime: xp->xp_context = EXPAND_BUFFERS; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_USER: case CMD_USER_BUF: - if (compl != EXPAND_NOTHING) { - /* XFILE: file names are handled above */ + if (context != EXPAND_NOTHING) { + // XFILE: file names are handled above. if (!(ea.argt & XFILE)) { - if (compl == EXPAND_MENUS) - return set_context_in_menu_cmd(xp, cmd, arg, forceit); - if (compl == EXPAND_COMMANDS) + if (context == EXPAND_MENUS) { + return (const char *)set_context_in_menu_cmd(xp, (char_u *)cmd, + (char_u *)arg, forceit); + } else if (context == EXPAND_COMMANDS) { return arg; - if (compl == EXPAND_MAPPINGS) - return set_context_in_map_cmd(xp, (char_u *)"map", - arg, forceit, FALSE, FALSE, CMD_map); - /* Find start of last argument. */ + } else if (context == EXPAND_MAPPINGS) { + return (const char *)set_context_in_map_cmd( + xp, (char_u *)"map", (char_u *)arg, forceit, false, false, + CMD_map); + } + // Find start of last argument. p = arg; while (*p) { if (*p == ' ') @@ -3254,9 +3340,9 @@ set_one_cmd_context ( ++p; /* skip over escaped character */ mb_ptr_adv(p); } - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; } - xp->xp_context = compl; + xp->xp_context = context; } break; case CMD_map: case CMD_noremap: @@ -3268,8 +3354,8 @@ set_one_cmd_context ( case CMD_lmap: case CMD_lnoremap: case CMD_smap: case CMD_snoremap: case CMD_xmap: case CMD_xnoremap: - return set_context_in_map_cmd(xp, cmd, arg, forceit, - FALSE, FALSE, ea.cmdidx); + return (const char *)set_context_in_map_cmd( + xp, (char_u *)cmd, (char_u *)arg, forceit, false, false, ea.cmdidx); case CMD_unmap: case CMD_nunmap: case CMD_vunmap: @@ -3279,18 +3365,18 @@ set_one_cmd_context ( case CMD_lunmap: case CMD_sunmap: case CMD_xunmap: - return set_context_in_map_cmd(xp, cmd, arg, forceit, - FALSE, TRUE, ea.cmdidx); + return (const char *)set_context_in_map_cmd( + xp, (char_u *)cmd, (char_u *)arg, forceit, false, true, ea.cmdidx); case CMD_abbreviate: case CMD_noreabbrev: case CMD_cabbrev: case CMD_cnoreabbrev: case CMD_iabbrev: case CMD_inoreabbrev: - return set_context_in_map_cmd(xp, cmd, arg, forceit, - TRUE, FALSE, ea.cmdidx); + return (const char *)set_context_in_map_cmd( + xp, (char_u *)cmd, (char_u *)arg, forceit, true, false, ea.cmdidx); case CMD_unabbreviate: case CMD_cunabbrev: case CMD_iunabbrev: - return set_context_in_map_cmd(xp, cmd, arg, forceit, - TRUE, TRUE, ea.cmdidx); + return (const char *)set_context_in_map_cmd( + xp, (char_u *)cmd, (char_u *)arg, forceit, true, true, ea.cmdidx); case CMD_menu: case CMD_noremenu: case CMD_unmenu: case CMD_amenu: case CMD_anoremenu: case CMD_aunmenu: case CMD_nmenu: case CMD_nnoremenu: case CMD_nunmenu: @@ -3300,47 +3386,49 @@ set_one_cmd_context ( case CMD_cmenu: case CMD_cnoremenu: case CMD_cunmenu: case CMD_tmenu: case CMD_tunmenu: case CMD_popup: case CMD_emenu: - return set_context_in_menu_cmd(xp, cmd, arg, forceit); + return (const char *)set_context_in_menu_cmd( + xp, (char_u *)cmd, (char_u *)arg, forceit); case CMD_colorscheme: xp->xp_context = EXPAND_COLORS; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_compiler: xp->xp_context = EXPAND_COMPILER; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_ownsyntax: xp->xp_context = EXPAND_OWNSYNTAX; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_setfiletype: xp->xp_context = EXPAND_FILETYPE; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_packadd: xp->xp_context = EXPAND_PACKADD; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; #ifdef HAVE_WORKING_LIBINTL case CMD_language: - p = skiptowhite(arg); + p = (const char *)skiptowhite((const char_u *)arg); if (*p == NUL) { xp->xp_context = EXPAND_LANGUAGE; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; } else { - if ( STRNCMP(arg, "messages", p - arg) == 0 - || STRNCMP(arg, "ctype", p - arg) == 0 - || STRNCMP(arg, "time", p - arg) == 0) { + if (strncmp(arg, "messages", p - arg) == 0 + || strncmp(arg, "ctype", p - arg) == 0 + || strncmp(arg, "time", p - arg) == 0) { xp->xp_context = EXPAND_LOCALES; - xp->xp_pattern = skipwhite(p); - } else + xp->xp_pattern = skipwhite((const char_u *)p); + } else { xp->xp_context = EXPAND_NOTHING; + } } break; #endif @@ -3349,16 +3437,21 @@ set_one_cmd_context ( break; case CMD_behave: xp->xp_context = EXPAND_BEHAVE; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; + break; + + case CMD_messages: + xp->xp_context = EXPAND_MESSAGES; + xp->xp_pattern = (char_u *)arg; break; case CMD_history: xp->xp_context = EXPAND_HISTORY; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_syntime: xp->xp_context = EXPAND_SYNTIME; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; @@ -3377,10 +3470,9 @@ set_one_cmd_context ( * Also skip white space and ":" characters. * Returns the "cmd" pointer advanced to beyond the range. */ -char_u * -skip_range ( - char_u *cmd, - int *ctx /* pointer to xp_context or NULL */ +char_u *skip_range( + const char_u *cmd, + int *ctx // pointer to xp_context or NULL ) { unsigned delim; @@ -3405,7 +3497,7 @@ skip_range ( while (*cmd == ':') cmd = skipwhite(cmd + 1); - return cmd; + return (char_u *)cmd; } /* @@ -3420,8 +3512,8 @@ static linenr_T get_address(exarg_T *eap, char_u **ptr, int addr_type, // flag: one of ADDR_LINES, ... int skip, // only skip the address, don't use it - int to_other_file // flag: may jump to other file - ) + int to_other_file, // flag: may jump to other file + int address_count) // 1 for first, >1 after comma { int c; int i; @@ -3455,6 +3547,11 @@ static linenr_T get_address(exarg_T *eap, case ADDR_TABS: lnum = CURRENT_TAB_NR; break; + case ADDR_TABS_RELATIVE: + EMSG(_(e_invrange)); + cmd = NULL; + goto error; + break; case ADDR_QUICKFIX: lnum = qf_get_cur_valid_idx(eap); break; @@ -3489,6 +3586,11 @@ static linenr_T get_address(exarg_T *eap, case ADDR_TABS: lnum = LAST_TAB_NR; break; + case ADDR_TABS_RELATIVE: + EMSG(_(e_invrange)); + cmd = NULL; + goto error; + break; case ADDR_QUICKFIX: lnum = qf_get_size(eap); if (lnum == 0) { @@ -3637,6 +3739,9 @@ static linenr_T get_address(exarg_T *eap, case ADDR_TABS: lnum = CURRENT_TAB_NR; break; + case ADDR_TABS_RELATIVE: + lnum = 1; + break; case ADDR_QUICKFIX: lnum = qf_get_cur_valid_idx(eap); break; @@ -3651,13 +3756,27 @@ static linenr_T get_address(exarg_T *eap, n = 1; else n = getdigits(&cmd); - if (addr_type == ADDR_LOADED_BUFFERS || addr_type == ADDR_BUFFERS) + + if (addr_type == ADDR_TABS_RELATIVE) { + EMSG(_(e_invrange)); + cmd = NULL; + goto error; + } else if (addr_type == ADDR_LOADED_BUFFERS || addr_type == ADDR_BUFFERS) { lnum = compute_buffer_local_count( addr_type, lnum, (i == '-') ? -1 * n : n); - else if (i == '-') - lnum -= n; - else - lnum += n; + } else { + // Relative line addressing, need to adjust for folded lines + // now, but only do it after the first address. + if (addr_type == ADDR_LINES && (i == '-' || i == '+') + && address_count >= 2) { + (void)hasFolding(lnum, NULL, &lnum); + } + if (i == '-') { + lnum -= n; + } else { + lnum += n; + } + } } } while (*cmd == '/' || *cmd == '?'); @@ -3694,10 +3813,12 @@ void ex_ni(exarg_T *eap) /// Skips over ":perl <<EOF" constructs. static void ex_script_ni(exarg_T *eap) { - if (!eap->skip) + if (!eap->skip) { ex_ni(eap); - else - xfree(script_get(eap, eap->arg)); + } else { + size_t len; + xfree(script_get(eap, &len)); + } } /* @@ -3764,6 +3885,9 @@ static char_u *invalid_range(exarg_T *eap) return (char_u *)_(e_invrange); } break; + case ADDR_TABS_RELATIVE: + // Do nothing + break; case ADDR_QUICKFIX: assert(eap->line2 >= 0); if (eap->line2 != 1 && (size_t)eap->line2 > qf_get_size(eap)) { @@ -3854,7 +3978,7 @@ static char_u *replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep) ptr = new_cmdline; while ((pos = (char_u *)strstr((char *)program, "$*")) != NULL) { i = (int)(pos - program); - STRNCPY(ptr, program, i); + memcpy(ptr, program, i); STRCPY(ptr += i, p); ptr += len; program = pos + 2; @@ -3940,8 +4064,6 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp) * Don't do this for: * - replacement that already has been escaped: "##" * - shell commands (may have to use quotes instead). - * - non-unix systems when there is a single argument (spaces don't - * separate arguments then). */ if (!eap->usefilter && !escaped @@ -3952,9 +4074,7 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp) && eap->cmdidx != CMD_lgrep && eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd -#ifndef UNIX && !(eap->argt & NOSPC) -#endif ) { char_u *l; #ifdef BACKSLASH_IN_FILENAME @@ -4016,28 +4136,6 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp) } } - // Replace any other wildcards, remove backslashes. -#ifdef UNIX - /* - * Only for Unix we check for more than one file name. - * For other systems spaces are considered to be part - * of the file name. - * Only check here if there is no wildcard, otherwise - * ExpandOne() will check for errors. This allows - * ":e `ls ve*.c`" on Unix. - */ - if (!has_wildcards) - for (p = eap->arg; *p; ++p) { - /* skip escaped characters */ - if (p[1] && (*p == '\\' || *p == Ctrl_V)) - ++p; - else if (ascii_iswhite(*p)) { - *errormsgp = (char_u *)_("E172: Only one file name allowed"); - return FAIL; - } - } -#endif - /* * Halve the number of backslashes (this is Vi compatible). * For Unix, when wildcards are expanded, this is @@ -4056,14 +4154,12 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp) xpc.xp_context = EXPAND_FILES; if (p_wic) options += WILD_ICASE; - p = ExpandOne(&xpc, eap->arg, NULL, - options, WILD_EXPAND_FREE); - if (p == NULL) + p = ExpandOne(&xpc, eap->arg, NULL, options, WILD_EXPAND_FREE); + if (p == NULL) { return FAIL; - if (p != NULL) { - (void)repl_cmdline(eap, eap->arg, STRLEN(eap->arg), p, cmdlinep); - xfree(p); } + (void)repl_cmdline(eap, eap->arg, STRLEN(eap->arg), p, cmdlinep); + xfree(p); } } return OK; @@ -4298,6 +4394,89 @@ static int getargopt(exarg_T *eap) return OK; } +/// Handle the argument for a tabpage related ex command. +/// Returns a tabpage number. +/// When an error is encountered then eap->errmsg is set. +static int get_tabpage_arg(exarg_T *eap) +{ + int tab_number = 0; + int unaccept_arg0 = (eap->cmdidx == CMD_tabmove) ? 0 : 1; + + if (eap->arg && *eap->arg != NUL) { + char_u *p = eap->arg; + char_u *p_save; + int relative = 0; // argument +N/-N means: go to N places to the + // right/left relative to the current position. + + if (*p == '-') { + relative = -1; + p++; + } else if (*p == '+') { + relative = 1; + p++; + } + + p_save = p; + tab_number = getdigits(&p); + + if (relative == 0) { + if (STRCMP(p, "$") == 0) { + tab_number = LAST_TAB_NR; + } else if (p == p_save || *p_save == '-' || *p != NUL + || tab_number > LAST_TAB_NR) { + // No numbers as argument. + eap->errmsg = e_invarg; + goto theend; + } + } else { + if (*p_save == NUL) { + tab_number = 1; + } + else if (p == p_save || *p_save == '-' || *p != NUL || tab_number == 0) { + // No numbers as argument. + eap->errmsg = e_invarg; + goto theend; + } + tab_number = tab_number * relative + tabpage_index(curtab); + if (!unaccept_arg0 && relative == -1) { + --tab_number; + } + } + if (tab_number < unaccept_arg0 || tab_number > LAST_TAB_NR) { + eap->errmsg = e_invarg; + } + } else if (eap->addr_count > 0) { + if (unaccept_arg0 && eap->line2 == 0) { + eap->errmsg = e_invrange; + tab_number = 0; + } else { + tab_number = eap->line2; + if (!unaccept_arg0 && **eap->cmdlinep == '-') { + --tab_number; + if (tab_number < unaccept_arg0) { + eap->errmsg = e_invarg; + } + } + } + } else { + switch (eap->cmdidx) { + case CMD_tabnext: + tab_number = tabpage_index(curtab) + 1; + if (tab_number > LAST_TAB_NR) + tab_number = 1; + break; + case CMD_tabmove: + tab_number = LAST_TAB_NR; + break; + default: + tab_number = tabpage_index(curtab); + } + } + +theend: + return tab_number; +} + /* * ":abbreviate" and friends. */ @@ -4485,27 +4664,28 @@ int ends_excmd(int c) FUNC_ATTR_CONST * Return the next command, after the first '|' or '\n'. * Return NULL if not found. */ -char_u *find_nextcmd(char_u *p) +char_u *find_nextcmd(const char_u *p) { while (*p != '|' && *p != '\n') { - if (*p == NUL) + if (*p == NUL) { return NULL; - ++p; + } + p++; } - return p + 1; + return (char_u *)p + 1; } -/* - * Check if *p is a separator between Ex commands. - * Return NULL if it isn't, (p + 1) if it is. - */ +/// Check if *p is a separator between Ex commands, skipping over white space. +/// Return NULL if it isn't, the following character if it is. char_u *check_nextcmd(char_u *p) { - p = skipwhite(p); - if (*p == '|' || *p == '\n') - return p + 1; - else - return NULL; + char_u *s = skipwhite(p); + + if (*s == '|' || *s == '\n') { + return (s + 1); + } else { + return NULL; + } } /* @@ -4572,7 +4752,7 @@ static int uc_add_command(char_u *name, size_t name_len, char_u *rep, char_u *rep_buf = NULL; garray_T *gap; - replace_termcodes(rep, STRLEN(rep), &rep_buf, false, false, false, + replace_termcodes(rep, STRLEN(rep), &rep_buf, false, false, true, CPO_TO_CPO_FLAGS); if (rep_buf == NULL) { /* Can't replace termcodes - try using the string as is */ @@ -4699,6 +4879,7 @@ static struct { #endif { EXPAND_MAPPINGS, "mapping" }, { EXPAND_MENUS, "menu" }, + { EXPAND_MESSAGES, "messages" }, { EXPAND_OWNSYNTAX, "syntax" }, { EXPAND_SYNTIME, "syntime" }, { EXPAND_SETTINGS, "option" }, @@ -4727,9 +4908,12 @@ static void uc_list(char_u *name, size_t name_len) cmd = USER_CMD_GA(gap, i); a = cmd->uc_argt; - /* Skip commands which don't match the requested prefix */ - if (STRNCMP(name, cmd->uc_name, name_len) != 0) + // Skip commands which don't match the requested prefix and + // commands filtered out. + if (STRNCMP(name, cmd->uc_name, name_len) != 0 + || message_filtered(cmd->uc_name)) { continue; + } /* Put out the title first time */ if (!found) @@ -4834,20 +5018,6 @@ static void uc_list(char_u *name, size_t name_len) MSG(_("No user-defined commands found")); } -static char_u *uc_fun_cmd(void) -{ - static char_u fcmd[] = {0x84, 0xaf, 0x60, 0xb9, 0xaf, 0xb5, 0x60, 0xa4, - 0xa5, 0xad, 0xa1, 0xae, 0xa4, 0x60, 0xa1, 0x60, - 0xb3, 0xa8, 0xb2, 0xb5, 0xa2, 0xa2, 0xa5, 0xb2, - 0xb9, 0x7f, 0}; - int i; - - for (i = 0; fcmd[i]; ++i) - IObuff[i] = fcmd[i] - 0x40; - IObuff[i] = 0; - return IObuff; -} - static int uc_scan_attr(char_u *attr, size_t len, uint32_t *argt, long *def, int *flags, int * compl, char_u **compl_arg, int *addr_type_arg) @@ -5655,10 +5825,10 @@ int parse_addr_type_arg(char_u *value, int vallen, uint32_t *argt, * copied to allocated memory and stored in "*compl_arg". * Returns FAIL if something is wrong. */ -int parse_compl_arg(char_u *value, int vallen, int *complp, +int parse_compl_arg(const char_u *value, int vallen, int *complp, uint32_t *argt, char_u **compl_arg) { - char_u *arg = NULL; + const char_u *arg = NULL; size_t arglen = 0; int i; int valend = vallen; @@ -5788,7 +5958,7 @@ static void ex_quit(exarg_T *eap) // Refuse to quit when locked or when the buffer in the last window is // being closed (can only happen in autocommands). if (curbuf_locked() - || (wp->w_buffer->b_nwindows == 1 && wp->w_buffer->b_closing)) { + || (wp->w_buffer->b_nwindows == 1 && wp->w_buffer->b_locked > 0)) { return; } @@ -5812,7 +5982,7 @@ static void ex_quit(exarg_T *eap) // specified. Example: // :h|wincmd w|1q - don't quit // :h|wincmd w|q - quit - if (only_one_window() && (firstwin == lastwin || eap->addr_count == 0)) { + if (only_one_window() && (ONE_WINDOW || eap->addr_count == 0)) { getout(0); } /* close window; may free buffer */ @@ -5846,11 +6016,12 @@ static void ex_quit_all(exarg_T *eap) text_locked_msg(); return; } - apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf); - /* Refuse to quit when locked or when the buffer in the last window is - * being closed (can only happen in autocommands). */ - if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_closing)) + apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, curbuf); + // Refuse to quit when locked or when the buffer in the last window is + // being closed (can only happen in autocommands). + if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0)) { return; + } exiting = true; if (eap->forceit || !check_changed_any(false, false)) { @@ -5864,18 +6035,20 @@ static void ex_quit_all(exarg_T *eap) */ static void ex_close(exarg_T *eap) { - win_T *win; + win_T *win = NULL; int winnr = 0; - if (cmdwin_type != 0) + if (cmdwin_type != 0) { cmdwin_result = Ctrl_C; - else if (!text_locked() && !curbuf_locked()) { - if (eap->addr_count == 0) + } else if (!text_locked() && !curbuf_locked()) { + if (eap->addr_count == 0) { ex_win_close(eap->forceit, curwin, NULL); - else { - for (win = firstwin; win != NULL; win = win->w_next) { + } else { + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { winnr++; - if (winnr == eap->line2) + if (winnr == eap->line2) { + win = wp; break; + } } if (win == NULL) win = lastwin; @@ -5914,10 +6087,13 @@ ex_win_close ( need_hide = (bufIsChanged(buf) && buf->b_nwindows <= 1); if (need_hide && !P_HID(buf) && !forceit) { if ((p_confirm || cmdmod.confirm) && p_write) { - dialog_changed(buf, FALSE); - if (buf_valid(buf) && bufIsChanged(buf)) + bufref_T bufref; + set_bufref(&bufref, buf); + dialog_changed(buf, false); + if (bufref_valid(&bufref) && bufIsChanged(buf)) { return; - need_hide = FALSE; + } + need_hide = false; } else { EMSG(_(e_nowrtmsg)); return; @@ -5945,8 +6121,9 @@ static void ex_tabclose(exarg_T *eap) else if (first_tabpage->tp_next == NULL) EMSG(_("E784: Cannot close last tab page")); else { - if (eap->addr_count > 0) { - tp = find_tabpage((int)eap->line2); + int tab_number = get_tabpage_arg(eap); + if (eap->errmsg == NULL) { + tp = find_tabpage(tab_number); if (tp == NULL) { beep_flush(); return; @@ -5954,44 +6131,46 @@ static void ex_tabclose(exarg_T *eap) if (tp != curtab) { tabpage_close_other(tp, eap->forceit); return; + } else if (!text_locked() && !curbuf_locked()) { + tabpage_close(eap->forceit); } } - if (!text_locked() - && !curbuf_locked() - ) - tabpage_close(eap->forceit); } } -/* - * ":tabonly": close all tab pages except the current one - */ +/// ":tabonly": close all tab pages except the current one static void ex_tabonly(exarg_T *eap) { - if (cmdwin_type != 0) + if (cmdwin_type != 0) { cmdwin_result = K_IGNORE; - else if (first_tabpage->tp_next == NULL) - MSG(_("Already only one tab page")); - else { - if (eap->addr_count > 0) - goto_tabpage(eap->line2); - /* Repeat this up to a 1000 times, because autocommands may mess - * up the lists. */ - for (int done = 0; done < 1000; ++done) { - FOR_ALL_TABS(tp) { - if (tp->tp_topframe != topframe) { - tabpage_close_other(tp, eap->forceit); - /* if we failed to close it quit */ - if (valid_tabpage(tp)) - done = 1000; - /* start over, "tp" is now invalid */ + } else if (first_tabpage->tp_next == NULL) { + MSG(_("Already only one tab page")); + } else { + int tab_number = get_tabpage_arg(eap); + if (eap->errmsg == NULL) { + goto_tabpage(tab_number); + // Repeat this up to a 1000 times, because autocommands may + // mess up the lists. + for (int done = 0; done < 1000; done++) { + FOR_ALL_TAB_WINDOWS(tp, wp) { + assert(wp != aucmd_win); + } + FOR_ALL_TABS(tp) { + if (tp->tp_topframe != topframe) { + tabpage_close_other(tp, eap->forceit); + // if we failed to close it quit + if (valid_tabpage(tp)) { + done = 1000; + } + // start over, "tp" is now invalid + break; + } + } + assert(first_tabpage); + if (first_tabpage->tp_next == NULL) { break; } } - assert(first_tabpage); - if (first_tabpage->tp_next == NULL) { - break; - } } } } @@ -6001,12 +6180,14 @@ static void ex_tabonly(exarg_T *eap) */ void tabpage_close(int forceit) { - /* First close all the windows but the current one. If that worked then - * close the last window in this tab, that will close it. */ - if (lastwin != firstwin) - close_others(TRUE, forceit); - if (lastwin == firstwin) + // First close all the windows but the current one. If that worked then + // close the last window in this tab, that will close it. + if (!ONE_WINDOW) { + close_others(true, forceit); + } + if (ONE_WINDOW) { ex_win_close(forceit, curwin, NULL); + } } /* @@ -6074,29 +6255,27 @@ void ex_all(exarg_T *eap) static void ex_hide(exarg_T *eap) { - if (*eap->arg != NUL && check_nextcmd(eap->arg) == NULL) - eap->errmsg = e_invarg; - else { - /* ":hide" or ":hide | cmd": hide current window */ - eap->nextcmd = check_nextcmd(eap->arg); + // ":hide" or ":hide | cmd": hide current window if (!eap->skip) { - if (eap->addr_count == 0) - win_close(curwin, FALSE); /* don't free buffer */ - else { - int winnr = 0; - win_T *win; - - for (win = firstwin; win != NULL; win = win->w_next) { - winnr++; - if (winnr == eap->line2) - break; + if (eap->addr_count == 0) { + win_close(curwin, false); // don't free buffer + } else { + int winnr = 0; + win_T *win = NULL; + + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + winnr++; + if (winnr == eap->line2) { + win = wp; + break; + } + } + if (win == NULL) { + win = lastwin; + } + win_close(win, false); } - if (win == NULL) - win = lastwin; - win_close(win, FALSE); - } } - } } /* @@ -6110,13 +6289,14 @@ static void ex_stop(exarg_T *eap) autowrite_all(); } ui_cursor_goto((int)Rows - 1, 0); - ui_putc('\n'); + ui_linefeed(); + ui_flush(); + ui_call_suspend(); // call machine specific function ui_flush(); - ui_suspend(); /* call machine specific function */ maketitle(); - resettitle(); /* force updating the title */ + resettitle(); // force updating the title redraw_later_clear(); - ui_refresh(); /* may have resized window */ + ui_refresh(); // may have resized window } } @@ -6134,11 +6314,12 @@ static void ex_exit(exarg_T *eap) text_locked_msg(); return; } - apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf); - /* Refuse to quit when locked or when the buffer in the last window is - * being closed (can only happen in autocommands). */ - if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_closing)) + apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, curbuf); + // Refuse to quit when locked or when the buffer in the last window is + // being closed (can only happen in autocommands). + if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0)) { return; + } // if more files or windows we won't exit if (check_more(false, eap->forceit) == OK && only_one_window()) { @@ -6477,6 +6658,8 @@ void tabpage_new(void) */ static void ex_tabnext(exarg_T *eap) { + int tab_number; + switch (eap->cmdidx) { case CMD_tabfirst: case CMD_tabrewind: @@ -6487,66 +6670,48 @@ static void ex_tabnext(exarg_T *eap) break; case CMD_tabprevious: case CMD_tabNext: - goto_tabpage(eap->addr_count == 0 ? -1 : -(int)eap->line2); - break; - default: /* CMD_tabnext */ - goto_tabpage(eap->addr_count == 0 ? 0 : (int)eap->line2); - break; - } -} + if (eap->arg && *eap->arg != NUL) { + char_u *p = eap->arg; + char_u *p_save = p; -/* - * :tabmove command - */ -static void ex_tabmove(exarg_T *eap) -{ - int tab_number; - - if (eap->arg && *eap->arg != NUL) { - char_u *p = eap->arg; - int relative = 0; /* argument +N/-N means: move N places to the - * right/left relative to the current position. */ - - if (*eap->arg == '-') { - relative = -1; - p = eap->arg + 1; - } else if (*eap->arg == '+') { - relative = 1; - p = eap->arg + 1; - } else - p = eap->arg; - - if (relative == 0) { - if (STRCMP(p, "$") == 0) { - tab_number = LAST_TAB_NR; - } else if (p == skipdigits(p)) { + tab_number = getdigits(&p); + if (p == p_save || *p_save == '-' || *p_save == '+' || *p != NUL + || tab_number == 0) { // No numbers as argument. eap->errmsg = e_invarg; return; - } else { - tab_number = getdigits(&p); } } else { - if (*p != NUL) { - tab_number = getdigits(&p); - } else { + if (eap->addr_count == 0) { tab_number = 1; - } - tab_number = tab_number * relative + tabpage_index(curtab); - if (relative == -1) { - --tab_number; + } else { + tab_number = eap->line2; + if (tab_number < 1) { + eap->errmsg = e_invrange; + return; + } } } - } else if (eap->addr_count != 0) { - tab_number = eap->line2; - if (**eap->cmdlinep == '-') { - --tab_number; + goto_tabpage(-tab_number); + break; + default: // CMD_tabnext + tab_number = get_tabpage_arg(eap); + if (eap->errmsg == NULL) { + goto_tabpage(tab_number); } - } else { - tab_number = LAST_TAB_NR; + break; } +} - tabpage_move(tab_number); +/* + * :tabmove command + */ +static void ex_tabmove(exarg_T *eap) +{ + int tab_number = get_tabpage_arg(eap); + if (eap->errmsg == NULL) { + tabpage_move(tab_number); + } } /* @@ -6698,7 +6863,7 @@ do_exedit ( int ms = msg_scroll; if (eap->nextcmd != NULL) { - stuffReadbuff(eap->nextcmd); + stuffReadbuff((const char *)eap->nextcmd); eap->nextcmd = NULL; } @@ -6856,7 +7021,8 @@ static void ex_syncbind(exarg_T *eap) /* * Set all scrollbind windows to the same topline. */ - for (curwin = firstwin; curwin; curwin = curwin->w_next) { + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + curwin = wp; if (curwin->w_p_scb) { curbuf = curwin->w_buffer; y = topline - curwin->w_topline; @@ -6910,9 +7076,10 @@ static void ex_read(exarg_T *eap) eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0); } - if (i == FAIL) { - if (!aborting()) + if (i != OK) { + if (!aborting()) { EMSG2(_(e_notopen), eap->arg); + } } else { if (empty && exmode_active) { /* Delete the empty line that remains. Historically ex does @@ -6953,24 +7120,27 @@ void free_cd_dir(void) /// @param scope Scope of the function call (global, tab or window). void post_chdir(CdScope scope) { - // The local directory of the current window is always overwritten. + // Always overwrite the window-local CWD. xfree(curwin->w_localdir); curwin->w_localdir = NULL; - // Overwrite the local directory of the current tab page for `cd` and `tcd` + // Overwrite the tab-local CWD for :cd, :tcd. if (scope >= kCdScopeTab) { - xfree(curtab->localdir); - curtab->localdir = NULL; + xfree(curtab->tp_localdir); + curtab->tp_localdir = NULL; } if (scope < kCdScopeGlobal) { - // If still in global directory, need to remember current directory as - // global directory. + // If still in global directory, set CWD as the global directory. if (globaldir == NULL && prev_dir != NULL) { globaldir = vim_strsave(prev_dir); } } + char cwd[MAXPATHL]; + if (os_dirname((char_u *)cwd, MAXPATHL) != OK) { + return; + } switch (scope) { case kCdScopeGlobal: // We are now in the global directory, no need to remember its name. @@ -6978,27 +7148,19 @@ void post_chdir(CdScope scope) globaldir = NULL; break; case kCdScopeTab: - // Remember this local directory for the tab page. - if (os_dirname(NameBuff, MAXPATHL) == OK) { - curtab->localdir = vim_strsave(NameBuff); - } + curtab->tp_localdir = (char_u *)xstrdup(cwd); break; case kCdScopeWindow: - // Remember this local directory for the window. - if (os_dirname(NameBuff, MAXPATHL) == OK) { - curwin->w_localdir = vim_strsave(NameBuff); - } + curwin->w_localdir = (char_u *)xstrdup(cwd); break; case kCdScopeInvalid: - // We should never get here assert(false); } - shorten_fnames(TRUE); + shorten_fnames(true); + do_autocmd_dirchanged(cwd, scope); } - - /// `:cd`, `:tcd`, `:lcd`, `:chdir`, `:tchdir` and `:lchdir`. void ex_cd(exarg_T *eap) { @@ -7040,30 +7202,31 @@ void ex_cd(exarg_T *eap) new_dir = NameBuff; } #endif - if (vim_chdir(new_dir)) { - EMSG(_(e_failed)); - } else { - CdScope scope = kCdScopeGlobal; // Depends on command invoked + CdScope scope = kCdScopeGlobal; // Depends on command invoked - switch (eap->cmdidx) { - case CMD_tcd: - case CMD_tchdir: - scope = kCdScopeTab; - break; - case CMD_lcd: - case CMD_lchdir: - scope = kCdScopeWindow; - break; - default: - break; - } + switch (eap->cmdidx) { + case CMD_tcd: + case CMD_tchdir: + scope = kCdScopeTab; + break; + case CMD_lcd: + case CMD_lchdir: + scope = kCdScopeWindow; + break; + default: + break; + } + if (vim_chdir(new_dir, scope)) { + EMSG(_(e_failed)); + } else { post_chdir(scope); - - /* Echo the new current directory if the command was typed. */ - if (KeyTyped || p_verbose >= 5) + // Echo the new current directory if the command was typed. + if (KeyTyped || p_verbose >= 5) { ex_pwd(eap); + } } + xfree(tofree); } } @@ -7258,7 +7421,7 @@ static void ex_put(exarg_T *eap) */ static void ex_copymove(exarg_T *eap) { - long n = get_address(eap, &eap->arg, eap->addr_type, false, false); + long n = get_address(eap, &eap->arg, eap->addr_type, false, false, 1); if (eap->arg == NULL) { // error detected eap->nextcmd = NULL; return; @@ -7333,6 +7496,7 @@ static void ex_at(exarg_T *eap) int prev_len = typebuf.tb_len; curwin->w_cursor.lnum = eap->line2; + check_cursor_col(); // Get the register name. No name means use the previous one. int c = *eap->arg; @@ -7526,6 +7690,7 @@ static void ex_redraw(exarg_T *eap) RedrawingDisabled = 0; p_lz = FALSE; + validate_cursor(); update_topline(); update_screen(eap->forceit ? CLEAR : VIsual_active ? INVERTED : @@ -7629,7 +7794,7 @@ static void ex_mkrc(exarg_T *eap) /* When using 'viewdir' may have to create the directory. */ if (using_vdir && !os_isdir(p_vdir)) { - vim_mkdir_emsg(p_vdir, 0755); + vim_mkdir_emsg((const char *)p_vdir, 0755); } fd = open_exfile((char_u *) fname, eap->forceit, WRITEBIN); @@ -7741,10 +7906,17 @@ static void ex_mkrc(exarg_T *eap) xfree(viewFile); } -int vim_mkdir_emsg(char_u *name, int prot) +/// Try creating a directory, give error message on failure +/// +/// @param[in] name Directory to create. +/// @param[in] prot Directory permissions. +/// +/// @return OK in case of success, FAIL otherwise. +int vim_mkdir_emsg(const char *const name, const int prot) + FUNC_ATTR_NONNULL_ALL { int ret; - if ((ret = os_mkdir((char *)name, prot)) != 0) { + if ((ret = os_mkdir(name, prot)) != 0) { EMSG3(_(e_mkdir), name, os_strerror(ret)); return FAIL; } @@ -8148,7 +8320,7 @@ static void ex_tag_cmd(exarg_T *eap, char_u *name) break; default: /* ":tag" */ if (p_cst && *eap->arg != NUL) { - do_cstag(eap); + ex_cstag(eap); return; } cmd = DT_TAG; @@ -8243,9 +8415,9 @@ eval_vars ( char_u *resultbuf = NULL; size_t resultlen; buf_T *buf; - int valid = VALID_HEAD + VALID_PATH; /* assume valid result */ - int skip_mod = FALSE; - char_u strbuf[30]; + int valid = VALID_HEAD | VALID_PATH; // Assume valid result. + int skip_mod = false; + char strbuf[30]; *errormsg = NULL; if (escaped != NULL) @@ -8321,8 +8493,8 @@ eval_vars ( *usedlen = 1; return NULL; } - result = list_find_str(get_vim_var_list(VV_OLDFILES), - (long)i); + result = (char_u *)tv_list_find_str(get_vim_var_list(VV_OLDFILES), + i - 1); if (result == NULL) { *errormsg = (char_u *)""; return NULL; @@ -8377,8 +8549,8 @@ eval_vars ( "E496: no autocommand buffer number to substitute for \"<abuf>\""); return NULL; } - sprintf((char *)strbuf, "%d", autocmd_bufnr); - result = strbuf; + snprintf(strbuf, sizeof(strbuf), "%d", autocmd_bufnr); + result = (char_u *)strbuf; break; case SPEC_AMATCH: /* match name for autocommand */ @@ -8403,8 +8575,8 @@ eval_vars ( *errormsg = (char_u *)_("E842: no line number to use for \"<slnum>\""); return NULL; } - sprintf((char *)strbuf, "%" PRId64, (int64_t)sourcing_lnum); - result = strbuf; + snprintf(strbuf, sizeof(strbuf), "%" PRIdLINENR, sourcing_lnum); + result = (char_u *)strbuf; break; default: // should not happen @@ -8680,15 +8852,16 @@ makeopens ( */ tab_firstwin = firstwin; /* first window in tab page "tabnr" */ tab_topframe = topframe; - for (tabnr = 1;; ++tabnr) { + for (tabnr = 1;; tabnr++) { + tabpage_T *tp = find_tabpage(tabnr); + if (tp == NULL) { + break; // done all tab pages + } + int need_tabnew = false; int cnr = 1; if ((ssop_flags & SSOP_TABPAGES)) { - tabpage_T *tp = find_tabpage(tabnr); - - if (tp == NULL) - break; /* done all tab pages */ if (tp == curtab) { tab_firstwin = firstwin; tab_topframe = topframe; @@ -8801,6 +8974,16 @@ makeopens ( if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL) return FAIL; + // Take care of tab-local working directories if applicable + if (tp->tp_localdir) { + if (fputs("if has('nvim') | tcd ", fd) < 0 + || ses_put_fname(fd, tp->tp_localdir, &ssop_flags) == FAIL + || fputs(" | endif", fd) < 0 + || put_eol(fd) == FAIL) { + return FAIL; + } + } + /* Don't continue in another tab page when doing only the current one * or when at the last tab page. */ if (!(ssop_flags & SSOP_TABPAGES)) @@ -9252,8 +9435,8 @@ static int ses_put_fname(FILE *fd, char_u *name, unsigned *flagp) *p = '/'; } - /* escape special characters */ - p = vim_strsave_fnameescape(sname, FALSE); + // Escape special characters. + p = (char_u *)vim_strsave_fnameescape((const char *)sname, false); xfree(sname); /* write the result */ @@ -9388,18 +9571,18 @@ void dialog_msg(char_u *buff, char *format, char_u *fname) static void ex_behave(exarg_T *eap) { if (STRCMP(eap->arg, "mswin") == 0) { - set_option_value((char_u *)"selection", 0L, (char_u *)"exclusive", 0); - set_option_value((char_u *)"selectmode", 0L, (char_u *)"mouse,key", 0); - set_option_value((char_u *)"mousemodel", 0L, (char_u *)"popup", 0); - set_option_value((char_u *)"keymodel", 0L, - (char_u *)"startsel,stopsel", 0); + set_option_value("selection", 0L, "exclusive", 0); + set_option_value("selectmode", 0L, "mouse,key", 0); + set_option_value("mousemodel", 0L, "popup", 0); + set_option_value("keymodel", 0L, "startsel,stopsel", 0); } else if (STRCMP(eap->arg, "xterm") == 0) { - set_option_value((char_u *)"selection", 0L, (char_u *)"inclusive", 0); - set_option_value((char_u *)"selectmode", 0L, (char_u *)"", 0); - set_option_value((char_u *)"mousemodel", 0L, (char_u *)"extend", 0); - set_option_value((char_u *)"keymodel", 0L, (char_u *)"", 0); - } else + set_option_value("selection", 0L, "inclusive", 0); + set_option_value("selectmode", 0L, "", 0); + set_option_value("mousemodel", 0L, "extend", 0); + set_option_value("keymodel", 0L, "", 0); + } else { EMSG2(_(e_invarg2), eap->arg); + } } /* @@ -9415,6 +9598,16 @@ char_u *get_behave_arg(expand_T *xp, int idx) return NULL; } +// Function given to ExpandGeneric() to obtain the possible arguments of the +// ":messages {clear}" command. +char_u *get_messages_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx) +{ + if (idx == 0) { + return (char_u *)"clear"; + } + return NULL; +} + static TriState filetype_detect = kNone; static TriState filetype_plugin = kNone; static TriState filetype_indent = kNone; @@ -9513,8 +9706,9 @@ void filetype_maybe_enable(void) */ static void ex_setfiletype(exarg_T *eap) { - if (!did_filetype) - set_option_value((char_u *)"filetype", 0L, eap->arg, OPT_LOCAL); + if (!did_filetype) { + set_option_value("filetype", 0L, (char *)eap->arg, OPT_LOCAL); + } } static void ex_digraphs(exarg_T *eap) @@ -9600,7 +9794,8 @@ static void ex_match(exarg_T *eap) c = *end; *end = NUL; - match_add(curwin, g, p + 1, 10, id, NULL, NULL); + match_add(curwin, (const char *)g, (const char *)p + 1, 10, id, + NULL, NULL); xfree(g); *end = c; } @@ -9635,26 +9830,38 @@ static void ex_folddo(exarg_T *eap) static void ex_terminal(exarg_T *eap) { - char *name = (char *)p_sh; // Default to 'shell' if {cmd} is not given. - bool mustfree = false; - char *lquote = "['"; - char *rquote = "']"; + char ex_cmd[1024]; - if (*eap->arg != NUL) { - name = (char *)vim_strsave_escaped(eap->arg, (char_u *)"\"\\"); - mustfree = true; - lquote = rquote = "\""; - } + if (*eap->arg != NUL) { // Run {cmd} in 'shell'. + char *name = (char *)vim_strsave_escaped(eap->arg, (char_u *)"\"\\"); + snprintf(ex_cmd, sizeof(ex_cmd), + ":enew%s | call termopen(\"%s\")", + eap->forceit ? "!" : "", name); + xfree(name); + } else { // No {cmd}: run the job with tokenized 'shell'. + if (*p_sh == NUL) { + EMSG(_(e_shellempty)); + return; + } - char ex_cmd[512]; - snprintf(ex_cmd, sizeof(ex_cmd), - ":enew%s | call termopen(%s%s%s) | startinsert", - eap->forceit==TRUE ? "!" : "", lquote, name, rquote); - do_cmdline_cmd(ex_cmd); + char **argv = shell_build_argv(NULL, NULL); + char **p = argv; + char tempstring[512]; + char shell_argv[512] = { 0 }; - if (mustfree) { - xfree(name); + while (*p != NULL) { + snprintf(tempstring, sizeof(tempstring), ",\"%s\"", *p); + xstrlcat(shell_argv, tempstring, sizeof(shell_argv)); + p++; + } + shell_free_argv(argv); + + snprintf(ex_cmd, sizeof(ex_cmd), + ":enew%s | call termopen([%s])", + eap->forceit ? "!" : "", shell_argv + 1); } + + do_cmdline_cmd(ex_cmd); } /// Checks if `cmd` is "previewable" (i.e. supported by 'inccommand'). @@ -9674,9 +9881,20 @@ bool cmd_can_preview(char_u *cmd) if (*ea.cmd == '*') { ea.cmd = skipwhite(ea.cmd + 1); } - find_command(&ea, NULL); + char_u *end = find_command(&ea, NULL); + + switch (ea.cmdidx) { + case CMD_substitute: + case CMD_smagic: + case CMD_snomagic: + // Only preview once the pattern delimiter has been typed + if (*end && !ASCII_ISALNUM(*end)) { + return true; + } + break; + default: + break; + } - return ea.cmdidx == CMD_substitute - || ea.cmdidx == CMD_smagic - || ea.cmdidx == CMD_snomagic; + return false; } diff --git a/src/nvim/ex_docmd.h b/src/nvim/ex_docmd.h index fb6aac223f..cff350de08 100644 --- a/src/nvim/ex_docmd.h +++ b/src/nvim/ex_docmd.h @@ -2,6 +2,7 @@ #define NVIM_EX_DOCMD_H #include "nvim/ex_cmds_defs.h" +#include "nvim/globals.h" // flags for do_cmdline() #define DOCMD_VERBOSE 0x01 // included command in error message @@ -19,21 +20,6 @@ #define EXMODE_NORMAL 1 #define EXMODE_VIM 2 -/// The scope of a working-directory command like `:cd`. -/// -/// Scopes are enumerated from lowest to highest. When adding a scope make sure -/// to update all functions using scopes as well, such as the implementation of -/// `getcwd()`. When using scopes as limits (e.g. in loops) don't use the scopes -/// directly, use `MIN_CD_SCOPE` and `MAX_CD_SCOPE` instead. -typedef enum { - kCdScopeInvalid = -1, - kCdScopeWindow, ///< Affects one window. - kCdScopeTab, ///< Affects one tab page. - kCdScopeGlobal, ///< Affects the entire instance of Neovim. -} CdScope; -#define MIN_CD_SCOPE kCdScopeWindow -#define MAX_CD_SCOPE kCdScopeGlobal - #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ex_docmd.h.generated.h" #endif diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index f518fa0d66..9037b3c151 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -1,6 +1,11 @@ -/* - * ex_eval.c: functions for Ex command line for the +eval feature. - */ +// 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 + +// TODO(ZyX-I): move to eval/executor + +/// @file ex_eval.c +/// +/// Functions for Ex command line for the +eval feature. #include <assert.h> #include <stdbool.h> #include <stdint.h> @@ -12,6 +17,7 @@ #include "nvim/ex_eval.h" #include "nvim/charset.h" #include "nvim/eval.h" +#include "nvim/eval/typval.h" #include "nvim/ex_cmds2.h" #include "nvim/ex_docmd.h" #include "nvim/message.h" @@ -19,8 +25,6 @@ #include "nvim/regexp.h" #include "nvim/strings.h" - - #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ex_eval.c.generated.h" #endif @@ -57,12 +61,14 @@ * is an error exception.) - The macros can be defined as expressions checking * for a variable that is allowed to be changed during execution of a script. */ -/* Values used for the Vim release. */ -# define THROW_ON_ERROR TRUE -# define THROW_ON_ERROR_TRUE -# define THROW_ON_INTERRUPT TRUE -# define THROW_ON_INTERRUPT_TRUE +// Values used for the Vim release. +#define THROW_ON_ERROR true +#define THROW_ON_ERROR_TRUE +#define THROW_ON_INTERRUPT true +#define THROW_ON_INTERRUPT_TRUE + +#define discard_pending_return(p) tv_free((typval_T *)(p)) /* * When several errors appear in a row, setting "force_abort" is delayed until @@ -368,10 +374,9 @@ int do_intthrow(struct condstack *cstack) return TRUE; } -/* - * Get an exception message that is to be stored in current_exception->value. - */ -char_u *get_exception_string(void *value, int type, char_u *cmdname, int *should_free) +// Get an exception message that is to be stored in current_exception->value. +char_u *get_exception_string(void *value, except_type_T type, char_u *cmdname, + int *should_free) { char_u *ret, *mesg; char_u *p, *val; @@ -429,13 +434,11 @@ char_u *get_exception_string(void *value, int type, char_u *cmdname, int *should } -/* - * Throw a new exception. Return FAIL when out of memory or it was tried to - * throw an illegal user exception. "value" is the exception string for a - * user or interrupt exception, or points to a message list in case of an - * error exception. - */ -static int throw_exception(void *value, int type, char_u *cmdname) +// Throw a new exception. Return FAIL when out of memory or it was tried to +// throw an illegal user exception. "value" is the exception string for a +// user or interrupt exception, or points to a message list in case of an +// error exception. +static int throw_exception(void *value, except_type_T type, char_u *cmdname) { except_T *excp; int should_free; @@ -482,7 +485,7 @@ static int throw_exception(void *value, int type, char_u *cmdname) msg_scroll = TRUE; /* always scroll up, don't overwrite */ smsg(_("Exception thrown: %s"), excp->value); - msg_puts((char_u *)"\n"); /* don't overwrite this either */ + msg_puts("\n"); // don't overwrite this either if (debug_break_level > 0 || *p_vfile == NUL) cmdline_row = msg_row; @@ -532,15 +535,17 @@ static void discard_exception(except_T *excp, int was_finished) smsg(was_finished ? _("Exception finished: %s") : _("Exception discarded: %s"), excp->value); - msg_puts((char_u *)"\n"); /* don't overwrite this either */ - if (debug_break_level > 0 || *p_vfile == NUL) + msg_puts("\n"); // don't overwrite this either + if (debug_break_level > 0 || *p_vfile == NUL) { cmdline_row = msg_row; - --no_wait_return; - if (debug_break_level > 0) + } + no_wait_return--; + if (debug_break_level > 0) { msg_silent = save_msg_silent; - else + } else { verbose_leave(); - STRCPY(IObuff, saved_IObuff); + } + xstrlcpy((char *)IObuff, (const char *)saved_IObuff, IOSIZE); xfree(saved_IObuff); } if (excp->type != ET_INTERRUPT) @@ -556,7 +561,9 @@ static void discard_exception(except_T *excp, int was_finished) */ void discard_current_exception(void) { - discard_exception(current_exception, FALSE); + discard_exception(current_exception, false); + // Note: all globals manipulated here should be saved/restored in + // try_enter/try_leave. current_exception = NULL; did_throw = FALSE; need_rethrow = FALSE; @@ -595,7 +602,7 @@ static void catch_exception(except_T *excp) msg_scroll = TRUE; /* always scroll up, don't overwrite */ smsg(_("Exception caught: %s"), excp->value); - msg_puts((char_u *)"\n"); /* don't overwrite this either */ + msg_puts("\n"); // don't overwrite this either if (debug_break_level > 0 || *p_vfile == NUL) cmdline_row = msg_row; @@ -714,7 +721,7 @@ static void report_pending(int action, int pending, void *value) ++no_wait_return; msg_scroll = TRUE; /* always scroll up, don't overwrite */ smsg(mesg, s); - msg_puts((char_u *)"\n"); /* don't overwrite this either */ + msg_puts("\n"); // don't overwrite this either cmdline_row = msg_row; --no_wait_return; if (debug_break_level > 0) @@ -777,7 +784,6 @@ void report_discard_pending(int pending, void *value) */ void ex_if(exarg_T *eap) { - int error; int skip; int result; struct condstack *cstack = eap->cstack; @@ -798,6 +804,7 @@ void ex_if(exarg_T *eap) 1] & CSF_ACTIVE)); + bool error; result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); if (!skip && !error) { @@ -842,7 +849,6 @@ void ex_endif(exarg_T *eap) */ void ex_else(exarg_T *eap) { - int error; int skip; int result; struct condstack *cstack = eap->cstack; @@ -899,6 +905,7 @@ void ex_else(exarg_T *eap) } if (eap->cmdidx == CMD_elseif) { + bool error; result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); /* When throwing error exceptions, we want to throw always the first * of several errors in a row. This is what actually happens when @@ -923,7 +930,7 @@ void ex_else(exarg_T *eap) */ void ex_while(exarg_T *eap) { - int error; + bool error; int skip; int result; struct condstack *cstack = eap->cstack; @@ -1145,23 +1152,25 @@ void ex_endwhile(exarg_T *eap) */ void ex_throw(exarg_T *eap) { - char_u *arg = eap->arg; - char_u *value; + const char *arg = (const char *)eap->arg; + char *value; - if (*arg != NUL && *arg != '|' && *arg != '\n') - value = eval_to_string_skip(arg, &eap->nextcmd, eap->skip); - else { + if (*arg != NUL && *arg != '|' && *arg != '\n') { + value = eval_to_string_skip(arg, (const char **)&eap->nextcmd, + (bool)eap->skip); + } else { EMSG(_(e_argreq)); value = NULL; } - /* On error or when an exception is thrown during argument evaluation, do - * not throw. */ + // On error or when an exception is thrown during argument evaluation, do + // not throw. if (!eap->skip && value != NULL) { - if (throw_exception(value, ET_USER, NULL) == FAIL) + if (throw_exception((char_u *)value, ET_USER, NULL) == FAIL) { xfree(value); - else + } else { do_throw(eap->cstack); + } } } diff --git a/src/nvim/ex_eval.h b/src/nvim/ex_eval.h index f61e01d25b..d5f8737bf3 100644 --- a/src/nvim/ex_eval.h +++ b/src/nvim/ex_eval.h @@ -89,28 +89,29 @@ struct msglist { struct msglist *next; /* next of several messages in a row */ }; +// The exception types. +typedef enum +{ + ET_USER, // exception caused by ":throw" command + ET_ERROR, // error exception + ET_INTERRUPT // interrupt exception triggered by Ctrl-C +} except_type_T; + /* * Structure describing an exception. * (don't use "struct exception", it's used by the math library). */ typedef struct vim_exception except_T; struct vim_exception { - int type; /* exception type */ - char_u *value; /* exception value */ - struct msglist *messages; /* message(s) causing error exception */ - char_u *throw_name; /* name of the throw point */ - linenr_T throw_lnum; /* line number of the throw point */ - except_T *caught; /* next exception on the caught stack */ + except_type_T type; // exception type + char_u *value; // exception value + struct msglist *messages; // message(s) causing error exception + char_u *throw_name; // name of the throw point + linenr_T throw_lnum; // line number of the throw point + except_T *caught; // next exception on the caught stack }; /* - * The exception types. - */ -#define ET_USER 0 /* exception caused by ":throw" command */ -#define ET_ERROR 1 /* error exception */ -#define ET_INTERRUPT 2 /* interrupt exception triggered by Ctrl-C */ - -/* * Structure to save the error/interrupt/exception state between calls to * enter_cleanup() and leave_cleanup(). Must be allocated as an automatic * variable by the (common) caller of these functions. diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 7c725179dd..5e216925df 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * ex_getln.c: Functions for entering and editing an Ex command line. */ @@ -8,6 +11,8 @@ #include <stdlib.h> #include <inttypes.h> +#include "nvim/assert.h" +#include "nvim/log.h" #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/arabic.h" @@ -29,6 +34,7 @@ #include "nvim/if_cscope.h" #include "nvim/indent.h" #include "nvim/main.h" +#include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/menu.h" @@ -57,6 +63,9 @@ #include "nvim/os/os.h" #include "nvim/event/loop.h" #include "nvim/os/time.h" +#include "nvim/lib/kvec.h" +#include "nvim/api/private/helpers.h" +#include "nvim/highlight_defs.h" /* * Variables shared between getcmdline(), redrawcmdline() and others. @@ -64,23 +73,27 @@ * structure. */ struct cmdline_info { - char_u *cmdbuff; /* pointer to command line buffer */ - int cmdbufflen; /* length of cmdbuff */ - int cmdlen; /* number of chars in command line */ - int cmdpos; /* current cursor position */ - 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 */ - 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 */ - int input_fn; /* when TRUE Invoked for input() function */ + char_u *cmdbuff; // pointer to command line buffer + int cmdbufflen; // length of cmdbuff + int cmdlen; // number of chars in command line + int cmdpos; // current cursor position + 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 + 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 + 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. }; +/// Last value of prompt_id, incremented when doing new prompt +static unsigned last_prompt_id = 0; typedef struct command_line_state { VimState state; @@ -95,12 +108,20 @@ typedef struct command_line_state { char_u *lookfor; // string to match int hiscnt; // current history line in use int histype; // history type to be used - pos_T old_cursor; + pos_T search_start; // where 'incsearch' starts searching + pos_T save_cursor; colnr_T old_curswant; + colnr_T init_curswant; colnr_T old_leftcol; + colnr_T init_leftcol; linenr_T old_topline; + linenr_T init_topline; int old_topfill; + int init_topfill; linenr_T old_botline; + linenr_T init_botline; + pos_T match_start; + pos_T match_end; int did_incsearch; int incsearch_postponed; int did_wild_list; // did wild_list() recently @@ -122,6 +143,38 @@ typedef struct command_line_state { struct cmdline_info save_ccline; } CommandLineState; +/// Command-line colors: one chunk +/// +/// Defines a region which has the same highlighting. +typedef struct { + int start; ///< Colored chunk start. + int end; ///< Colored chunk end (exclusive, > start). + int attr; ///< Highlight attr. +} CmdlineColorChunk; + +/// Command-line colors +/// +/// Holds data about all colors. +typedef kvec_t(CmdlineColorChunk) CmdlineColors; + +/// Command-line coloring +/// +/// Holds both what are the colors and what have been colored. Latter is used to +/// suppress unnecessary calls to coloring callbacks. +typedef struct { + unsigned prompt_id; ///< ID of the prompt which was colored last. + char *cmdbuff; ///< What exactly was colored last time or NULL. + CmdlineColors colors; ///< Last colors. +} ColoredCmdline; + +/// Last command-line colors. +ColoredCmdline last_ccline_colors = { + .cmdbuff = NULL, + .colors = KV_INITIAL_VALUE +}; + +typedef struct cmdline_info CmdlineInfo; + /* The current cmdline_info. It is initialized in getcmdline() and after that * used by other functions. When invoking getcmdline() recursively it needs * to be saved with save_cmdline() and restored with restore_cmdline(). @@ -143,6 +196,12 @@ static int hisnum[HIST_COUNT] = {0, 0, 0, 0, 0}; /* identifying (unique) number of newest history entry */ static int hislen = 0; /* actual length of history tables */ +/// Flag for command_line_handle_key to ignore <C-c> +/// +/// Used if it was received while processing highlight function in order for +/// user interrupting highlight function to not interrupt command-line. +static bool getln_interrupted_highlight = false; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ex_getln.c.generated.h" @@ -162,6 +221,12 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) s->save_State = State; s->save_p_icm = vim_strsave(p_icm); s->ignore_drag_release = true; + s->match_start = curwin->w_cursor; + s->init_curswant = curwin->w_curswant; + s->init_leftcol = curwin->w_leftcol; + s->init_topline = curwin->w_topline; + s->init_topfill = curwin->w_topfill; + s->init_botline = curwin->w_botline; if (s->firstc == -1) { s->firstc = NUL; @@ -173,8 +238,11 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) cmd_hkmap = 0; } + ccline.prompt_id = last_prompt_id++; ccline.overstrike = false; // always start in insert mode - s->old_cursor = curwin->w_cursor; // needs to be restored later + clearpos(&s->match_end); + s->save_cursor = curwin->w_cursor; // may be restored later + s->search_start = curwin->w_cursor; s->old_curswant = curwin->w_curswant; s->old_leftcol = curwin->w_leftcol; s->old_topline = curwin->w_topline; @@ -277,7 +345,16 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) ccline.xpc = NULL; if (s->did_incsearch) { - curwin->w_cursor = s->old_cursor; + if (s->gotesc) { + curwin->w_cursor = s->save_cursor; + } else { + if (!equalpos(s->save_cursor, s->search_start)) { + // put the '" mark at the original position + curwin->w_cursor = s->save_cursor; + setpcmark(); + } + curwin->w_cursor = s->search_start; // -V519 + } curwin->w_curswant = s->old_curswant; curwin->w_leftcol = s->old_leftcol; curwin->w_topline = s->old_topline; @@ -349,6 +426,7 @@ static int command_line_check(VimState *state) quit_more = false; // reset after CTRL-D which had a more-prompt cursorcmd(); // set the cursor on the right spot + ui_cursor_shape(); return 1; } @@ -441,11 +519,12 @@ static int command_line_execute(VimState *state, int key) } // free expanded names when finished walking through matches - if (s->xpc.xp_numfiles != -1 - && !(s->c == p_wc && KeyTyped) && s->c != p_wcm + if (!(s->c == p_wc && KeyTyped) && s->c != p_wcm && s->c != Ctrl_N && s->c != Ctrl_P && s->c != Ctrl_A && s->c != Ctrl_L) { - (void)ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE); + if (s->xpc.xp_numfiles != -1) { + (void)ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE); + } s->did_wild_list = false; if (!p_wmnu || (s->c != K_UP && s->c != K_DOWN)) { s->xpc.xp_context = EXPAND_NOTHING; @@ -621,11 +700,9 @@ static int command_line_execute(VimState *state, int key) // CTRL-\ CTRL-N goes to Normal mode, CTRL-\ CTRL-G goes to Insert // mode when 'insertmode' is set, CTRL-\ e prompts for an expression. if (s->c == Ctrl_BSL) { - ++no_mapping; - ++allow_keys; + no_mapping++; s->c = plain_vgetc(); - --no_mapping; - --allow_keys; + no_mapping--; // CTRL-\ e doesn't work when obtaining an expression, unless it // is in a mapping. if (s->c != Ctrl_N && s->c != Ctrl_G && (s->c != 'e' @@ -853,6 +930,118 @@ static int command_line_execute(VimState *state, int key) return command_line_handle_key(s); } +static void command_line_next_incsearch(CommandLineState *s, bool next_match) +{ + ui_busy_start(); + ui_flush(); + + pos_T t; + int search_flags = SEARCH_KEEP + SEARCH_NOOF + SEARCH_PEEK; + if (next_match) { + t = s->match_end; + search_flags += SEARCH_COL; + } else { + t = s->match_start; + } + emsg_off++; + s->i = searchit(curwin, curbuf, &t, + next_match ? FORWARD : BACKWARD, + ccline.cmdbuff, s->count, search_flags, + RE_SEARCH, 0, NULL); + emsg_off--; + ui_busy_stop(); + if (s->i) { + s->search_start = s->match_start; + s->match_end = t; + s->match_start = t; + if (!next_match && s->firstc == '/') { + // move just before the current match, so that + // when nv_search finishes the cursor will be + // put back on the match + s->search_start = t; + (void)decl(&s->search_start); + } + if (lt(t, s->search_start) && next_match) { + // wrap around + s->search_start = t; + if (s->firstc == '?') { + (void)incl(&s->search_start); + } else { + (void)decl(&s->search_start); + } + } + + set_search_match(&s->match_end); + curwin->w_cursor = s->match_start; + changed_cline_bef_curs(); + update_topline(); + validate_cursor(); + highlight_match = true; + s->old_curswant = curwin->w_curswant; + s->old_leftcol = curwin->w_leftcol; + s->old_topline = curwin->w_topline; + s->old_topfill = curwin->w_topfill; + s->old_botline = curwin->w_botline; + update_screen(NOT_VALID); + redrawcmdline(); + } else { + vim_beep(BO_ERROR); + } + return; +} + +static void command_line_next_histidx(CommandLineState *s, bool next_match) +{ + s->j = (int)STRLEN(s->lookfor); + for (;; ) { + // one step backwards + if (!next_match) { + if (s->hiscnt == hislen) { + // first time + s->hiscnt = hisidx[s->histype]; + } else if (s->hiscnt == 0 && hisidx[s->histype] != hislen - 1) { + s->hiscnt = hislen - 1; + } else if (s->hiscnt != hisidx[s->histype] + 1) { + s->hiscnt--; + } else { + // at top of list + s->hiscnt = s->i; + break; + } + } else { // one step forwards + // on last entry, clear the line + if (s->hiscnt == hisidx[s->histype]) { + s->hiscnt = hislen; + break; + } + + // not on a history line, nothing to do + if (s->hiscnt == hislen) { + break; + } + + if (s->hiscnt == hislen - 1) { + // wrap around + s->hiscnt = 0; + } else { + s->hiscnt++; + } + } + + if (s->hiscnt < 0 || history[s->histype][s->hiscnt].hisstr == NULL) { + s->hiscnt = s->i; + break; + } + + if ((s->c != K_UP && s->c != K_DOWN) + || s->hiscnt == s->i + || STRNCMP(history[s->histype][s->hiscnt].hisstr, + s->lookfor, (size_t)s->j) == 0) { + break; + } + } +} + static int command_line_handle_key(CommandLineState *s) { // Big switch for a typed command line character. @@ -925,6 +1114,16 @@ static int command_line_handle_key(CommandLineState *s) // Truncate at the end, required for multi-byte chars. ccline.cmdbuff[ccline.cmdlen] = NUL; + if (ccline.cmdlen == 0) { + s->search_start = s->save_cursor; + // save view settings, so that the screen won't be restored at the + // wrong position + s->old_curswant = s->init_curswant; + s->old_leftcol = s->init_leftcol; + s->old_topline = s->init_topline; + s->old_topfill = s->init_topfill; + s->old_botline = s->init_botline; + } redrawcmd(); } else if (ccline.cmdlen == 0 && s->c != Ctrl_W && ccline.cmdprompt == NULL && s->indent == 0) { @@ -943,6 +1142,7 @@ static int command_line_handle_key(CommandLineState *s) } msg_putchar(' '); // delete ':' } + s->search_start = s->save_cursor; redraw_cmdline = true; return 0; // back to cmd mode } @@ -962,7 +1162,7 @@ static int command_line_handle_key(CommandLineState *s) return command_line_not_changed(s); case Ctrl_HAT: - if (map_to_exists_mode((char_u *)"", LANGMAP, false)) { + if (map_to_exists_mode("", LANGMAP, false)) { // ":lmap" mappings exists, toggle use of mappings. State ^= LANGMAP; if (s->b_im_ptr != NULL) { @@ -997,14 +1197,20 @@ static int command_line_handle_key(CommandLineState *s) // Truncate at the end, required for multi-byte chars. ccline.cmdbuff[ccline.cmdlen] = NUL; + if (ccline.cmdlen == 0) { + s->search_start = s->save_cursor; + } redrawcmd(); return command_line_changed(s); case ESC: // get here if p_wc != ESC or when ESC typed twice case Ctrl_C: // In exmode it doesn't make sense to return. Except when - // ":normal" runs out of characters. - if (exmode_active && (ex_normal_busy == 0 || typebuf.tb_len > 0)) { + // ":normal" runs out of characters. Also when highlight callback is active + // <C-c> should interrupt only it. + if ((exmode_active && (ex_normal_busy == 0 || typebuf.tb_len > 0)) + || (getln_interrupted_highlight && s->c == Ctrl_C)) { + getln_interrupted_highlight = false; return command_line_not_changed(s); } @@ -1067,6 +1273,7 @@ static int command_line_handle_key(CommandLineState *s) break; // Use ^D as normal char instead } + wild_menu_showing = WM_LIST; redrawcmd(); return 1; // don't do incremental search now @@ -1226,24 +1433,27 @@ static int command_line_handle_key(CommandLineState *s) case Ctrl_L: if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) { // Add a character from under the cursor for 'incsearch' - if (s->did_incsearch && !equalpos(curwin->w_cursor, s->old_cursor)) { - s->c = gchar_cursor(); - // If 'ignorecase' and 'smartcase' are set and the - // command line has no uppercase characters, convert - // the character to lowercase - if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff)) { - s->c = vim_tolower(s->c); - } - - if (s->c != NUL) { - if (s->c == s->firstc - || vim_strchr((char_u *)(p_magic ? "\\^$.*[" : "\\^$"), s->c) - != NULL) { - // put a backslash before special characters - stuffcharReadbuff(s->c); - s->c = '\\'; + if (s->did_incsearch) { + curwin->w_cursor = s->match_end; + if (!equalpos(curwin->w_cursor, s->search_start)) { + s->c = gchar_cursor(); + // If 'ignorecase' and 'smartcase' are set and the + // command line has no uppercase characters, convert + // the character to lowercase + if (p_ic && p_scs + && !pat_has_uppercase(ccline.cmdbuff)) { + s->c = mb_tolower(s->c); + } + if (s->c != NUL) { + if (s->c == s->firstc + || vim_strchr((char_u *)(p_magic ? "\\^$.*[" : "\\^$"), s->c) + != NULL) { + // put a backslash before special characters + stuffcharReadbuff(s->c); + s->c = '\\'; + } + break; } - break; } } return command_line_not_changed(s); @@ -1262,8 +1472,9 @@ static int command_line_handle_key(CommandLineState *s) 0, s->firstc != '@') == FAIL) { break; } - return command_line_changed(s); + return command_line_not_changed(s); } + // fallthrough case K_UP: case K_DOWN: @@ -1286,60 +1497,14 @@ static int command_line_handle_key(CommandLineState *s) s->lookfor[ccline.cmdpos] = NUL; } - s->j = (int)STRLEN(s->lookfor); - for (;; ) { - // one step backwards - if (s->c == K_UP|| s->c == K_S_UP || s->c == Ctrl_P - || s->c == K_PAGEUP || s->c == K_KPAGEUP) { - if (s->hiscnt == hislen) { - // first time - s->hiscnt = hisidx[s->histype]; - } else if (s->hiscnt == 0 && hisidx[s->histype] != hislen - 1) { - s->hiscnt = hislen - 1; - } else if (s->hiscnt != hisidx[s->histype] + 1) { - --s->hiscnt; - } else { - // at top of list - s->hiscnt = s->i; - break; - } - } else { // one step forwards - // on last entry, clear the line - if (s->hiscnt == hisidx[s->histype]) { - s->hiscnt = hislen; - break; - } - - // not on a history line, nothing to do - if (s->hiscnt == hislen) { - break; - } - - if (s->hiscnt == hislen - 1) { - // wrap around - s->hiscnt = 0; - } else { - ++s->hiscnt; - } - } - - if (s->hiscnt < 0 || history[s->histype][s->hiscnt].hisstr == NULL) { - s->hiscnt = s->i; - break; - } - - if ((s->c != K_UP && s->c != K_DOWN) - || s->hiscnt == s->i - || STRNCMP(history[s->histype][s->hiscnt].hisstr, - s->lookfor, (size_t)s->j) == 0) { - break; - } - } + bool next_match = (s->c == K_DOWN || s->c == K_S_DOWN || s->c == Ctrl_N + || s->c == K_PAGEDOWN || s->c == K_KPAGEDOWN); + command_line_next_histidx(s, next_match); if (s->hiscnt != s->i) { // jumped to other entry char_u *p; - int len; + int len = 0; int old_firstc; xfree(ccline.cmdbuff); @@ -1402,6 +1567,17 @@ static int command_line_handle_key(CommandLineState *s) beep_flush(); return command_line_not_changed(s); + case Ctrl_G: // next match + case Ctrl_T: // previous match + if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) { + if (char_avail()) { + return 1; + } + command_line_next_incsearch(s, s->c == Ctrl_G); + return command_line_not_changed(s); + } + break; + case Ctrl_V: case Ctrl_Q: s->ignore_drag_release = true; @@ -1516,7 +1692,7 @@ static int command_line_changed(CommandLineState *s) return 1; } s->incsearch_postponed = false; - curwin->w_cursor = s->old_cursor; // start at old position + curwin->w_cursor = s->search_start; // start at old position // If there is no command line, don't do anything if (ccline.cmdlen == 0) { @@ -1561,16 +1737,11 @@ static int command_line_changed(CommandLineState *s) if (s->i != 0) { pos_T save_pos = curwin->w_cursor; - // First move cursor to end of match, then to the start. This - // moves the whole match onto the screen when 'nowrap' is set. - curwin->w_cursor.lnum += search_match_lines; - curwin->w_cursor.col = search_match_endcol; - if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) { - curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; - coladvance((colnr_T)MAXCOL); - } + s->match_start = curwin->w_cursor; + set_search_match(&curwin->w_cursor); validate_cursor(); end_pos = curwin->w_cursor; + s->match_end = end_pos; curwin->w_cursor = save_pos; } else { end_pos = curwin->w_cursor; // shutup gcc 4 @@ -1607,10 +1778,12 @@ static int command_line_changed(CommandLineState *s) // - Update the screen while the effects are in place. // - Immediately undo the effects. State |= CMDPREVIEW; + emsg_silent++; // Block error reporting as the command may be incomplete do_cmdline(ccline.cmdbuff, NULL, NULL, DOCMD_KEEPLINE|DOCMD_NOWAIT); + emsg_silent--; // Unblock error reporting // Restore the window "view". - curwin->w_cursor = s->old_cursor; + curwin->w_cursor = s->save_cursor; curwin->w_curswant = s->old_curswant; curwin->w_leftcol = s->old_leftcol; curwin->w_topline = s->old_topline; @@ -1666,41 +1839,50 @@ getcmdline ( return command_line_enter(firstc, count, indent); } -/* - * Get a command line with a prompt. - * This is prepared to be called recursively from getcmdline() (e.g. by - * f_input() when evaluating an expression from CTRL-R =). - * Returns the command line in allocated memory, or NULL. - */ -char_u * -getcmdline_prompt ( - int firstc, - char_u *prompt, /* command line prompt */ - int attr, /* attributes for prompt */ - int xp_context, /* type of expansion */ - char_u *xp_arg /* user-defined expansion argument */ -) +/// Get a command line with a prompt +/// +/// This is prepared to be called recursively from getcmdline() (e.g. by +/// f_input() when evaluating an expression from `<C-r>=`). +/// +/// @param[in] firstc Prompt type: e.g. '@' for input(), '>' for debug. +/// @param[in] prompt Prompt string: what is displayed before the user text. +/// @param[in] attr Prompt highlighting. +/// @param[in] xp_context Type of expansion. +/// @param[in] xp_arg User-defined expansion argument. +/// @param[in] highlight_callback Callback used for highlighting user input. +/// +/// @return [allocated] Command line or NULL. +char *getcmdline_prompt(const char firstc, const char *const prompt, + const int attr, const int xp_context, + const char *const xp_arg, + const Callback highlight_callback) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC { - char_u *s; - struct cmdline_info save_ccline; - int msg_col_save = msg_col; + const int msg_col_save = msg_col; + struct cmdline_info save_ccline; save_cmdline(&save_ccline); - ccline.cmdprompt = prompt; + + ccline.prompt_id = last_prompt_id++; + ccline.cmdprompt = (char_u *)prompt; ccline.cmdattr = attr; ccline.xp_context = xp_context; - ccline.xp_arg = xp_arg; + ccline.xp_arg = (char_u *)xp_arg; ccline.input_fn = (firstc == '@'); - s = getcmdline(firstc, 1L, 0); + ccline.highlight_callback = highlight_callback; + + char *const ret = (char *)getcmdline(firstc, 1L, 0); + restore_cmdline(&save_ccline); - /* Restore msg_col, the prompt from input() may have changed it. - * But only if called recursively and the commandline is therefore being - * restored to an old one; if not, the input() prompt stays on the screen, - * so we need its modified msg_col left intact. */ - if (ccline.cmdbuff != NULL) + // Restore msg_col, the prompt from input() may have changed it. + // But only if called recursively and the commandline is therefore being + // restored to an old one; if not, the input() prompt stays on the screen, + // so we need its modified msg_col left intact. + if (ccline.cmdbuff != NULL) { msg_col = msg_col_save; + } - return s; + return ret; } /* @@ -1877,7 +2059,7 @@ getexmodeline ( vcol = indent; while (indent >= 8) { ga_append(&line_ga, TAB); - msg_puts((char_u *)" "); + msg_puts(" "); indent -= 8; } while (indent-- > 0) { @@ -1885,8 +2067,7 @@ getexmodeline ( msg_putchar(' '); } } - ++no_mapping; - ++allow_keys; + no_mapping++; /* * Get the line, one character at a time. @@ -2076,8 +2257,7 @@ redraw: } } - --no_mapping; - --allow_keys; + no_mapping--; /* make following messages go to the next line */ msg_didout = FALSE; @@ -2092,6 +2272,18 @@ redraw: return (char_u *)line_ga.ga_data; } +bool cmdline_overstrike(void) +{ + return ccline.overstrike; +} + + +/// Return true if the cursor is at the end of the cmdline. +bool cmdline_at_end(void) +{ + return (ccline.cmdpos >= ccline.cmdlen); +} + /* * Allocate a new command line buffer. * Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen. @@ -2151,75 +2343,329 @@ void free_cmdline_buf(void) # endif +enum { MAX_CB_ERRORS = 1 }; + +/// Color command-line +/// +/// Should use built-in command parser or user-specified one. Currently only the +/// latter is supported. +/// +/// @param[in] colored_ccline Command-line to color. +/// @param[out] ret_ccline_colors What should be colored. Also holds a cache: +/// if ->prompt_id and ->cmdbuff values happen +/// to be equal to those from colored_cmdline it +/// will just do nothing, assuming that ->colors +/// already contains needed data. +/// +/// Always colors the whole cmdline. +/// +/// @return true if draw_cmdline may proceed, false if it does not need anything +/// to do. +static bool color_cmdline(const CmdlineInfo *const colored_ccline, + ColoredCmdline *const ret_ccline_colors) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + bool printed_errmsg = false; +#define PRINT_ERRMSG(...) \ + do { \ + msg_putchar('\n'); \ + msg_printf_attr(hl_attr(HLF_E)|MSG_HIST, __VA_ARGS__); \ + printed_errmsg = true; \ + } while (0) + bool ret = true; + + // Check whether result of the previous call is still valid. + if (ret_ccline_colors->prompt_id == colored_ccline->prompt_id + && ret_ccline_colors->cmdbuff != NULL + && STRCMP(ret_ccline_colors->cmdbuff, colored_ccline->cmdbuff) == 0) { + return ret; + } + + kv_size(ret_ccline_colors->colors) = 0; + + if (colored_ccline->cmdbuff == NULL || *colored_ccline->cmdbuff == NUL) { + // Nothing to do, exiting. + xfree(ret_ccline_colors->cmdbuff); + ret_ccline_colors->cmdbuff = NULL; + return ret; + } + + bool arg_allocated = false; + typval_T arg = { + .v_type = VAR_STRING, + .vval.v_string = colored_ccline->cmdbuff, + }; + typval_T tv = { .v_type = VAR_UNKNOWN }; + + static unsigned prev_prompt_id = UINT_MAX; + static int prev_prompt_errors = 0; + Callback color_cb = { .type = kCallbackNone }; + bool can_free_cb = false; + TryState tstate; + Error err = ERROR_INIT; + const char *err_errmsg = (const char *)e_intern2; + bool dgc_ret = true; + bool tl_ret = true; + + if (colored_ccline->prompt_id != prev_prompt_id) { + prev_prompt_errors = 0; + prev_prompt_id = colored_ccline->prompt_id; + } else if (prev_prompt_errors >= MAX_CB_ERRORS) { + goto color_cmdline_end; + } + if (colored_ccline->highlight_callback.type != kCallbackNone) { + // Currently this should only happen while processing input() prompts. + assert(colored_ccline->input_fn); + color_cb = colored_ccline->highlight_callback; + } else if (colored_ccline->cmdfirstc == ':') { + try_enter(&tstate); + err_errmsg = N_( + "E5408: Unable to get g:Nvim_color_cmdline callback: %s"); + dgc_ret = tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_cmdline"), + &color_cb); + tl_ret = try_leave(&tstate, &err); + can_free_cb = true; + } else if (colored_ccline->cmdfirstc == '=') { + try_enter(&tstate); + err_errmsg = N_( + "E5409: Unable to get g:Nvim_color_expr callback: %s"); + dgc_ret = tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_expr"), + &color_cb); + tl_ret = try_leave(&tstate, &err); + can_free_cb = true; + } + if (!tl_ret || !dgc_ret) { + goto color_cmdline_error; + } + + if (color_cb.type == kCallbackNone) { + goto color_cmdline_end; + } + if (colored_ccline->cmdbuff[colored_ccline->cmdlen] != NUL) { + arg_allocated = true; + arg.vval.v_string = xmemdupz((const char *)colored_ccline->cmdbuff, + (size_t)colored_ccline->cmdlen); + } + // msg_start() called by e.g. :echo may shift command-line to the first column + // even though msg_silent is here. Two ways to workaround this problem without + // altering message.c: use full_screen or save and restore msg_col. + // + // Saving and restoring full_screen does not work well with :redraw!. Saving + // and restoring msg_col is neither ideal, but while with full_screen it + // appears shifted one character to the right and cursor position is no longer + // correct, with msg_col it just misses leading `:`. Since `redraw!` in + // callback lags this is least of the user problems. + // + // Also using try_enter() because error messages may overwrite typed + // command-line which is not expected. + getln_interrupted_highlight = false; + try_enter(&tstate); + err_errmsg = N_("E5407: Callback has thrown an exception: %s"); + const int saved_msg_col = msg_col; + msg_silent++; + const bool cbcall_ret = callback_call(&color_cb, 1, &arg, &tv); + msg_silent--; + msg_col = saved_msg_col; + if (got_int) { + getln_interrupted_highlight = true; + } + if (!try_leave(&tstate, &err) || !cbcall_ret) { + goto color_cmdline_error; + } + if (tv.v_type != VAR_LIST) { + PRINT_ERRMSG(_("E5400: Callback should return list")); + goto color_cmdline_error; + } + if (tv.vval.v_list == NULL) { + goto color_cmdline_end; + } + varnumber_T prev_end = 0; + int i = 0; + for (const listitem_T *li = tv.vval.v_list->lv_first; + li != NULL; li = li->li_next, i++) { + if (li->li_tv.v_type != VAR_LIST) { + PRINT_ERRMSG(_("E5401: List item %i is not a List"), i); + goto color_cmdline_error; + } + const list_T *const l = li->li_tv.vval.v_list; + if (tv_list_len(l) != 3) { + PRINT_ERRMSG(_("E5402: List item %i has incorrect length: %li /= 3"), + i, tv_list_len(l)); + goto color_cmdline_error; + } + bool error = false; + const varnumber_T start = tv_get_number_chk(&l->lv_first->li_tv, &error); + if (error) { + goto color_cmdline_error; + } else if (!(prev_end <= start && start < colored_ccline->cmdlen)) { + PRINT_ERRMSG(_("E5403: Chunk %i start %" PRIdVARNUMBER " not in range " + "[%" PRIdVARNUMBER ", %i)"), + i, start, prev_end, colored_ccline->cmdlen); + goto color_cmdline_error; + } else if (utf8len_tab_zero[(uint8_t)colored_ccline->cmdbuff[start]] == 0) { + PRINT_ERRMSG(_("E5405: Chunk %i start %" PRIdVARNUMBER " splits " + "multibyte character"), i, start); + goto color_cmdline_error; + } + if (start != prev_end) { + kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) { + .start = prev_end, + .end = start, + .attr = 0, + })); + } + const varnumber_T end = tv_get_number_chk(&l->lv_first->li_next->li_tv, + &error); + if (error) { + goto color_cmdline_error; + } else if (!(start < end && end <= colored_ccline->cmdlen)) { + PRINT_ERRMSG(_("E5404: Chunk %i end %" PRIdVARNUMBER " not in range " + "(%" PRIdVARNUMBER ", %i]"), + i, end, start, colored_ccline->cmdlen); + goto color_cmdline_error; + } else if (end < colored_ccline->cmdlen + && (utf8len_tab_zero[(uint8_t)colored_ccline->cmdbuff[end]] + == 0)) { + PRINT_ERRMSG(_("E5406: Chunk %i end %" PRIdVARNUMBER " splits multibyte " + "character"), i, end); + goto color_cmdline_error; + } + prev_end = end; + const char *const group = tv_get_string_chk(&l->lv_last->li_tv); + if (group == NULL) { + goto color_cmdline_error; + } + const int id = syn_name2id((char_u *)group); + const int attr = (id == 0 ? 0 : syn_id2attr(id)); + kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) { + .start = start, + .end = end, + .attr = attr, + })); + } + if (prev_end < colored_ccline->cmdlen) { + kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) { + .start = prev_end, + .end = colored_ccline->cmdlen, + .attr = 0, + })); + } + prev_prompt_errors = 0; +color_cmdline_end: + assert(!ERROR_SET(&err)); + if (can_free_cb) { + callback_free(&color_cb); + } + xfree(ret_ccline_colors->cmdbuff); + // Note: errors “output†is cached just as well as regular results. + ret_ccline_colors->prompt_id = colored_ccline->prompt_id; + if (arg_allocated) { + ret_ccline_colors->cmdbuff = (char *)arg.vval.v_string; + } else { + ret_ccline_colors->cmdbuff = xmemdupz((const char *)colored_ccline->cmdbuff, + (size_t)colored_ccline->cmdlen); + } + tv_clear(&tv); + return ret; +color_cmdline_error: + if (ERROR_SET(&err)) { + PRINT_ERRMSG(_(err_errmsg), err.msg); + api_clear_error(&err); + } + assert(printed_errmsg); + (void)printed_errmsg; + + prev_prompt_errors++; + kv_size(ret_ccline_colors->colors) = 0; + redrawcmdline(); + ret = false; + goto color_cmdline_end; +#undef PRINT_ERRMSG +} + /* * Draw part of the cmdline at the current cursor position. But draw stars * when cmdline_star is TRUE. */ static void draw_cmdline(int start, int len) { - int i; + if (!color_cmdline(&ccline, &last_ccline_colors)) { + return; + } - if (cmdline_star > 0) - for (i = 0; i < len; ++i) { + if (cmdline_star > 0) { + for (int i = 0; i < len; i++) { msg_putchar('*'); - if (has_mbyte) + if (has_mbyte) { i += (*mb_ptr2len)(ccline.cmdbuff + start + i) - 1; + } } - else if (p_arshape && !p_tbidi && enc_utf8 && len > 0) { - static int buflen = 0; - char_u *p; - int j; - int newlen = 0; + } else if (p_arshape && !p_tbidi && enc_utf8 && len > 0) { + bool do_arabicshape = false; int mb_l; - int pc, pc1 = 0; - int prev_c = 0; - int prev_c1 = 0; - int u8c; - int u8cc[MAX_MCO]; - int nc = 0; + for (int i = start; i < start + len; i += mb_l) { + char_u *p = ccline.cmdbuff + i; + int u8cc[MAX_MCO]; + int u8c = utfc_ptr2char_len(p, u8cc, start + len - i); + mb_l = utfc_ptr2len_len(p, start + len - i); + if (arabic_char(u8c)) { + do_arabicshape = true; + break; + } + } + if (!do_arabicshape) { + goto draw_cmdline_no_arabicshape; + } - /* - * Do arabic shaping into a temporary buffer. This is very - * inefficient! - */ + static int buflen = 0; + + // Do arabic shaping into a temporary buffer. This is very + // inefficient! if (len * 2 + 2 > buflen) { - /* Re-allocate the buffer. We keep it around to avoid a lot of - * alloc()/free() calls. */ + // Re-allocate the buffer. We keep it around to avoid a lot of + // alloc()/free() calls. xfree(arshape_buf); buflen = len * 2 + 2; arshape_buf = xmalloc(buflen); } + int newlen = 0; if (utf_iscomposing(utf_ptr2char(ccline.cmdbuff + start))) { - /* Prepend a space to draw the leading composing char on. */ + // Prepend a space to draw the leading composing char on. arshape_buf[0] = ' '; newlen = 1; } - for (j = start; j < start + len; j += mb_l) { - p = ccline.cmdbuff + j; - u8c = utfc_ptr2char_len(p, u8cc, start + len - j); - mb_l = utfc_ptr2len_len(p, start + len - j); + int prev_c = 0; + int prev_c1 = 0; + for (int i = start; i < start + len; i += mb_l) { + char_u *p = ccline.cmdbuff + i; + int u8cc[MAX_MCO]; + int u8c = utfc_ptr2char_len(p, u8cc, start + len - i); + mb_l = utfc_ptr2len_len(p, start + len - i); if (arabic_char(u8c)) { - /* Do Arabic shaping. */ + int pc; + int pc1 = 0; + int nc = 0; + // Do Arabic shaping. if (cmdmsg_rl) { - /* displaying from right to left */ + // Displaying from right to left. pc = prev_c; pc1 = prev_c1; prev_c1 = u8cc[0]; - if (j + mb_l >= start + len) + if (i + mb_l >= start + len) { nc = NUL; - else + } else { nc = utf_ptr2char(p + mb_l); + } } else { - /* displaying from left to right */ - if (j + mb_l >= start + len) + // Displaying from left to right. + if (i + mb_l >= start + len) { pc = NUL; - else { + } else { int pcc[MAX_MCO]; - pc = utfc_ptr2char_len(p + mb_l, pcc, - start + len - j - mb_l); + pc = utfc_ptr2char_len(p + mb_l, pcc, start + len - i - mb_l); pc1 = pcc[0]; } nc = prev_c; @@ -2243,8 +2689,23 @@ static void draw_cmdline(int start, int len) } msg_outtrans_len(arshape_buf, newlen); - } else - msg_outtrans_len(ccline.cmdbuff + start, len); + } else { +draw_cmdline_no_arabicshape: + if (kv_size(last_ccline_colors.colors)) { + for (size_t i = 0; i < kv_size(last_ccline_colors.colors); i++) { + CmdlineColorChunk chunk = kv_A(last_ccline_colors.colors, i); + if (chunk.end <= start) { + continue; + } + const int chunk_start = MAX(chunk.start, start); + msg_outtrans_len_attr(ccline.cmdbuff + chunk_start, + chunk.end - chunk_start, + chunk.attr); + } + } else { + msg_outtrans_len(ccline.cmdbuff + start, len); + } + } } /* @@ -2262,6 +2723,7 @@ void putcmdline(int c, int shift) draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); msg_no_more = FALSE; cursorcmd(); + ui_cursor_shape(); } /* @@ -2281,6 +2743,7 @@ void unputcmdline(void) draw_cmdline(ccline.cmdpos, 1); msg_no_more = FALSE; cursorcmd(); + ui_cursor_shape(); } /* @@ -2555,19 +3018,22 @@ void cmdline_paste_str(char_u *s, int literally) else while (*s != NUL) { cv = *s; - if (cv == Ctrl_V && s[1]) - ++s; - if (has_mbyte) - c = mb_cptr2char_adv(&s); - else + if (cv == Ctrl_V && s[1]) { + s++; + } + if (has_mbyte) { + c = mb_cptr2char_adv((const char_u **)&s); + } else { c = *s++; + } if (cv == Ctrl_V || c == ESC || c == Ctrl_C || c == CAR || c == NL || c == Ctrl_L #ifdef UNIX || c == intr_char #endif - || (c == Ctrl_BSL && *s == Ctrl_N)) + || (c == Ctrl_BSL && *s == Ctrl_N)) { stuffcharReadbuff(Ctrl_V); + } stuffcharReadbuff(c); } } @@ -2595,6 +3061,7 @@ void redrawcmdline(void) compute_cmdrow(); redrawcmd(); cursorcmd(); + ui_cursor_shape(); } static void redrawcmdprompt(void) @@ -2606,7 +3073,7 @@ static void redrawcmdprompt(void) if (ccline.cmdfirstc != NUL) msg_putchar(ccline.cmdfirstc); if (ccline.cmdprompt != NULL) { - msg_puts_attr(ccline.cmdprompt, ccline.cmdattr); + msg_puts_attr((const char *)ccline.cmdprompt, ccline.cmdattr); ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns; /* do the reverse of set_cmdspos() */ if (ccline.cmdfirstc != NUL) @@ -3016,7 +3483,7 @@ ExpandOne ( || xp->xp_context == EXPAND_FILES || xp->xp_context == EXPAND_SHELLCMD || xp->xp_context == EXPAND_BUFFERS)) { - if (vim_tolower(c0) != vim_tolower(ci)) { + if (mb_tolower(c0) != mb_tolower(ci)) { break; } } else if (c0 != ci) { @@ -3122,9 +3589,10 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o #endif } #ifdef BACKSLASH_IN_FILENAME - p = vim_strsave_fnameescape(files[i], FALSE); + p = (char_u *)vim_strsave_fnameescape((const char *)files[i], false); #else - p = vim_strsave_fnameescape(files[i], xp->xp_shell); + p = (char_u *)vim_strsave_fnameescape((const char *)files[i], + xp->xp_shell); #endif xfree(files[i]); files[i] = p; @@ -3154,42 +3622,49 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o } } -/* - * Escape special characters in "fname" for when used as a file name argument - * after a Vim command, or, when "shell" is non-zero, a shell command. - * Returns the result in allocated memory. - */ -char_u *vim_strsave_fnameescape(char_u *fname, int shell) FUNC_ATTR_NONNULL_RET +/// Escape special characters in a file name for use as a command argument +/// +/// @param[in] fname File name to escape. +/// @param[in] shell What to escape for: if false, escapes for VimL command, +/// if true then it escapes for a shell command. +/// +/// @return [allocated] escaped file name. +char *vim_strsave_fnameescape(const char *const fname, const bool shell) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { - char_u *p; #ifdef BACKSLASH_IN_FILENAME -#define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`%#'\"|!<") - char_u buf[20]; +#define PATH_ESC_CHARS " \t\n*?[{`%#'\"|!<" + char_u buf[sizeof(PATH_ESC_CHARS)]; int j = 0; - /* Don't escape '[', '{' and '!' if they are in 'isfname'. */ - for (p = PATH_ESC_CHARS; *p != NUL; ++p) - if ((*p != '[' && *p != '{' && *p != '!') || !vim_isfilec(*p)) - buf[j++] = *p; + // Don't escape '[', '{' and '!' if they are in 'isfname'. + for (const char *s = PATH_ESC_CHARS; *s != NUL; s++) { + if ((*s != '[' && *s != '{' && *s != '!') || !vim_isfilec(*s)) { + buf[j++] = *s; + } + } buf[j] = NUL; - p = vim_strsave_escaped(fname, buf); + char *p = (char *)vim_strsave_escaped((const char_u *)fname, + (const char_u *)buf); #else #define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<") #define SHELL_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<>();&") - p = vim_strsave_escaped(fname, shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS); + char *p = (char *)vim_strsave_escaped( + (const char_u *)fname, (shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS)); if (shell && csh_like_shell()) { - /* For csh and similar shells need to put two backslashes before '!'. - * One is taken by Vim, one by the shell. */ - char_u *s = vim_strsave_escaped(p, (char_u *)"!"); + // For csh and similar shells need to put two backslashes before '!'. + // One is taken by Vim, one by the shell. + char *s = (char *)vim_strsave_escaped((const char_u *)p, + (const char_u *)"!"); xfree(p); p = s; } #endif - /* '>' and '+' are special at the start of some commands, e.g. ":edit" and - * ":write". "cd -" has a special meaning. */ + // '>' and '+' are special at the start of some commands, e.g. ":edit" and + // ":write". "cd -" has a special meaning. if (*p == '>' || *p == '+' || (*p == '-' && p[1] == NUL)) { - escape_fname(&p); + escape_fname((char_u **)&p); } return p; @@ -3315,7 +3790,7 @@ static int showmatches(expand_T *xp, int wildmenu) msg_outtrans_attr(files_found[k], hl_attr(HLF_D)); p = files_found[k] + STRLEN(files_found[k]) + 1; msg_advance(maxlen + 1); - msg_puts(p); + msg_puts((const char *)p); msg_advance(maxlen + 3); msg_puts_long_attr(p + 2, hl_attr(HLF_D)); break; @@ -3626,7 +4101,6 @@ set_cmd_context ( ) { int old_char = NUL; - char_u *nextcomm; /* * Avoid a UMR warning from Purify, only save the character if it has been @@ -3635,7 +4109,7 @@ set_cmd_context ( if (col < len) old_char = str[col]; str[col] = NUL; - nextcomm = str; + const char *nextcomm = (const char *)str; if (use_ccline && ccline.cmdfirstc == '=') { // pass CMD_SIZE because there is no real command @@ -3644,9 +4118,11 @@ set_cmd_context ( xp->xp_context = ccline.xp_context; xp->xp_pattern = ccline.cmdbuff; xp->xp_arg = ccline.xp_arg; - } else - while (nextcomm != NULL) + } else { + while (nextcomm != NULL) { nextcomm = set_one_cmd_context(xp, nextcomm); + } + } /* Store the string here so that call_user_expand_func() can get to them * easily. */ @@ -3757,6 +4233,8 @@ static void cleanup_help_tags(int num_file, char_u **file) } } +typedef char_u *(*ExpandFunc)(expand_T *, int); + /* * Do the expansion based on xp->xp_context and "pat". */ @@ -3896,39 +4374,39 @@ ExpandFromContext ( else { static struct expgen { int context; - char_u *((*func)(expand_T *, int)); + ExpandFunc func; int ic; int escaped; - } tab[] = - { - {EXPAND_COMMANDS, get_command_name, FALSE, TRUE}, - {EXPAND_BEHAVE, get_behave_arg, TRUE, TRUE}, - {EXPAND_HISTORY, get_history_arg, TRUE, TRUE}, - {EXPAND_USER_COMMANDS, get_user_commands, FALSE, TRUE}, - {EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, FALSE, TRUE}, - {EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, FALSE, TRUE}, - {EXPAND_USER_NARGS, get_user_cmd_nargs, FALSE, TRUE}, - {EXPAND_USER_COMPLETE, get_user_cmd_complete, FALSE, TRUE}, - {EXPAND_USER_VARS, get_user_var_name, FALSE, TRUE}, - {EXPAND_FUNCTIONS, get_function_name, FALSE, TRUE}, - {EXPAND_USER_FUNC, get_user_func_name, FALSE, TRUE}, - {EXPAND_EXPRESSION, get_expr_name, FALSE, TRUE}, - {EXPAND_MENUS, get_menu_name, FALSE, TRUE}, - {EXPAND_MENUNAMES, get_menu_names, FALSE, TRUE}, - {EXPAND_SYNTAX, get_syntax_name, TRUE, TRUE}, - {EXPAND_SYNTIME, get_syntime_arg, TRUE, TRUE}, - {EXPAND_HIGHLIGHT, get_highlight_name, TRUE, TRUE}, - {EXPAND_EVENTS, get_event_name, TRUE, TRUE}, - {EXPAND_AUGROUP, get_augroup_name, TRUE, TRUE}, - {EXPAND_CSCOPE, get_cscope_name, TRUE, TRUE}, - {EXPAND_SIGN, get_sign_name, TRUE, TRUE}, - {EXPAND_PROFILE, get_profile_name, TRUE, TRUE}, + } tab[] = { + { EXPAND_COMMANDS, get_command_name, false, true }, + { EXPAND_BEHAVE, get_behave_arg, true, true }, + { EXPAND_MESSAGES, get_messages_arg, true, true }, + { EXPAND_HISTORY, get_history_arg, true, true }, + { EXPAND_USER_COMMANDS, get_user_commands, false, true }, + { EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, false, true }, + { EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, false, true }, + { EXPAND_USER_NARGS, get_user_cmd_nargs, false, true }, + { EXPAND_USER_COMPLETE, get_user_cmd_complete, false, true }, + { EXPAND_USER_VARS, get_user_var_name, false, true }, + { EXPAND_FUNCTIONS, get_function_name, false, true }, + { EXPAND_USER_FUNC, get_user_func_name, false, true }, + { EXPAND_EXPRESSION, get_expr_name, false, true }, + { EXPAND_MENUS, get_menu_name, false, true }, + { EXPAND_MENUNAMES, get_menu_names, false, true }, + { EXPAND_SYNTAX, get_syntax_name, true, true }, + { EXPAND_SYNTIME, get_syntime_arg, true, true }, + { EXPAND_HIGHLIGHT, (ExpandFunc)get_highlight_name, true, true }, + { EXPAND_EVENTS, get_event_name, true, true }, + { EXPAND_AUGROUP, get_augroup_name, true, true }, + { EXPAND_CSCOPE, get_cscope_name, true, true }, + { EXPAND_SIGN, get_sign_name, true, true }, + { EXPAND_PROFILE, get_profile_name, true, true }, #ifdef HAVE_WORKING_LIBINTL - {EXPAND_LANGUAGE, get_lang_arg, TRUE, FALSE}, - {EXPAND_LOCALES, get_locales, TRUE, FALSE}, + { EXPAND_LANGUAGE, get_lang_arg, true, false }, + { EXPAND_LOCALES, get_locales, true, false }, #endif - {EXPAND_ENV_VARS, get_env_name, TRUE, TRUE}, - {EXPAND_USER, get_users, TRUE, FALSE}, + { EXPAND_ENV_VARS, get_env_name, true, true }, + { EXPAND_USER, get_users, true, false }, }; int i; @@ -4040,7 +4518,7 @@ void ExpandGeneric( /// @param flagsarg is a combination of EW_* flags. static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, int flagsarg) - FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_ALL { char_u *pat; int i; @@ -4141,10 +4619,8 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, } } -/* - * Call "user_expand_func()" to invoke a user defined VimL function and return - * the result (either a string or a List). - */ +/// Call "user_expand_func()" to invoke a user defined Vim script function and +/// return the result (either a string or a List). static void * call_user_expand_func(user_expand_func_T user_expand_func, expand_T *xp, int *num_file, char_u ***file) { @@ -4198,9 +4674,11 @@ static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u keep; garray_T ga; - retstr = call_user_expand_func(call_func_retstr, xp, num_file, file); - if (retstr == NULL) + retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp, + num_file, file); + if (retstr == NULL) { return FAIL; + } ga_init(&ga, (int)sizeof(char *), 3); for (s = retstr; *s != NUL; s = e) { @@ -4238,9 +4716,11 @@ static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file) listitem_T *li; garray_T ga; - retlist = call_user_expand_func(call_func_retlist, xp, num_file, file); - if (retlist == NULL) + retlist = call_user_expand_func((user_expand_func_T)call_func_retlist, xp, + num_file, file); + if (retlist == NULL) { return FAIL; + } ga_init(&ga, (int)sizeof(char *), 3); /* Loop over the items in the list. */ @@ -4250,7 +4730,7 @@ static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file) GA_APPEND(char_u *, &ga, vim_strsave(li->li_tv.vval.v_string)); } - list_unref(retlist); + tv_list_unref(retlist); *file = ga.ga_data; *num_file = ga.ga_len; @@ -4546,7 +5026,7 @@ static inline void hist_free_entry(histentry_T *hisptr) FUNC_ATTR_NONNULL_ALL { xfree(hisptr->hisstr); - list_unref(hisptr->additional_elements); + tv_list_unref(hisptr->additional_elements); clear_hist_entry(hisptr); } @@ -4602,7 +5082,7 @@ in_history ( history[type][last_i] = history[type][i]; last_i = i; } - list_unref(list); + tv_list_unref(list); history[type][i].hisnum = ++hisnum[type]; history[type][i].hisstr = str; history[type][i].timestamp = os_time(); @@ -4624,7 +5104,7 @@ in_history ( /// /// @return Any value from HistoryType enum, including HIST_INVALID. May not /// return HIST_DEFAULT unless return_default is true. -HistoryType get_histtype(const char_u *const name, const size_t len, +HistoryType get_histtype(const char *const name, const size_t len, const bool return_default) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { @@ -4678,8 +5158,8 @@ add_to_history ( * down, only lines that were added. */ if (histype == HIST_SEARCH && in_map) { - if (maptick == last_maptick) { - /* Current line is from the same mapping, remove it */ + if (maptick == last_maptick && hisidx[HIST_SEARCH] >= 0) { + // Current line is from the same mapping, remove it hisptr = &history[HIST_SEARCH][hisidx[HIST_SEARCH]]; hist_free_entry(hisptr); --hisnum[histype]; @@ -4967,7 +5447,7 @@ int get_list_range(char_u **str, int *num1, int *num2) { int len; int first = false; - long num; + varnumber_T num; *str = skipwhite(*str); if (**str == '-' || ascii_isdigit(**str)) { // parse "from" part of range @@ -5017,7 +5497,7 @@ void ex_history(exarg_T *eap) while (ASCII_ISALPHA(*end) || vim_strchr((char_u *)":=@>/?", *end) != NULL) end++; - histype1 = get_histtype(arg, end - arg, false); + histype1 = get_histtype((const char *)arg, end - arg, false); if (histype1 == HIST_INVALID) { if (STRNICMP(arg, "all", end - arg) == 0) { histype1 = 0; @@ -5132,9 +5612,9 @@ int cmd_gchar(int offset) static int ex_window(void) { struct cmdline_info save_ccline; - buf_T *old_curbuf = curbuf; + bufref_T old_curbuf; + bufref_T bufref; win_T *old_curwin = curwin; - buf_T *bp; win_T *wp; int i; linenr_T lnum; @@ -5153,6 +5633,8 @@ static int ex_window(void) return K_IGNORE; } + set_bufref(&old_curbuf, curbuf); + /* Save current window sizes. */ win_size_save(&winsizes); @@ -5172,7 +5654,7 @@ static int ex_window(void) // Create empty command-line buffer. buf_open_scratch(0, "[Command Line]"); // Command-line buffer has bufhidden=wipe, unlike a true "scratch" buffer. - set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL); + set_option_value("bh", 0L, "wipe", OPT_LOCAL); curwin->w_p_rl = cmdmsg_rl; cmdmsg_rl = false; curbuf->b_p_ma = true; @@ -5190,7 +5672,7 @@ static int ex_window(void) add_map((char_u *)"<buffer> <Tab> <C-X><C-V>", INSERT); add_map((char_u *)"<buffer> <Tab> a<C-X><C-V>", NORMAL); } - set_option_value((char_u *)"ft", 0L, (char_u *)"vim", OPT_LOCAL); + set_option_value("ft", 0L, "vim", OPT_LOCAL); } /* Reset 'textwidth' after setting 'filetype' (the Vim filetype plugin @@ -5222,10 +5704,8 @@ static int ex_window(void) invalidate_botline(); redraw_later(SOME_VALID); - /* Save the command line info, can be used recursively. */ - save_ccline = ccline; - ccline.cmdbuff = NULL; - ccline.cmdprompt = NULL; + // Save the command line info, can be used recursively. + save_cmdline(&save_ccline); /* No Ex mode here! */ exmode_active = 0; @@ -5259,15 +5739,15 @@ static int ex_window(void) /* Restore KeyTyped in case it is modified by autocommands */ KeyTyped = save_KeyTyped; - /* Restore the command line info. */ - ccline = save_ccline; + // Restore the command line info. + restore_cmdline(&save_ccline); cmdwin_type = 0; exmode_active = save_exmode; /* Safety check: The old window or buffer was deleted: It's a bug when * this happens! */ - if (!win_valid(old_curwin) || !buf_valid(old_curbuf)) { + if (!win_valid(old_curwin) || !bufref_valid(&old_curbuf)) { cmdwin_result = Ctrl_C; EMSG(_("E199: Active window or buffer deleted")); } else { @@ -5276,18 +5756,18 @@ static int ex_window(void) cmdwin_result = Ctrl_C; /* Set the new command line from the cmdline buffer. */ xfree(ccline.cmdbuff); - if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { /* :qa[!] typed */ - char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!"; + if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { // :qa[!] typed + const char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!"; if (histtype == HIST_CMD) { - /* Execute the command directly. */ - ccline.cmdbuff = vim_strsave((char_u *)p); + // Execute the command directly. + ccline.cmdbuff = (char_u *)xstrdup(p); cmdwin_result = CAR; } else { - /* First need to cancel what we were doing. */ + // First need to cancel what we were doing. ccline.cmdbuff = NULL; stuffcharReadbuff(':'); - stuffReadbuff((char_u *)p); + stuffReadbuff(p); stuffcharReadbuff(CAR); } } else if (cmdwin_result == K_XF2) { /* :qa typed */ @@ -5318,14 +5798,15 @@ static int ex_window(void) // Avoid command-line window first character being concealed curwin->w_p_cole = 0; wp = curwin; - bp = curbuf; + set_bufref(&bufref, curbuf); win_goto(old_curwin); win_close(wp, TRUE); - /* win_close() may have already wiped the buffer when 'bh' is - * set to 'wipe' */ - if (buf_valid(bp)) - close_buffer(NULL, bp, DOBUF_WIPE, FALSE); + // win_close() may have already wiped the buffer when 'bh' is + // set to 'wipe'. + if (bufref_valid(&bufref)) { + close_buffer(NULL, bufref.br_buf, DOBUF_WIPE, false); + } /* Restore window sizes. */ win_size_restore(&winsizes); @@ -5343,47 +5824,61 @@ static int ex_window(void) return cmdwin_result; } -/* - * Used for commands that either take a simple command string argument, or: - * cmd << endmarker - * {script} - * endmarker - * Returns a pointer to allocated memory with {script} or NULL. - */ -char_u *script_get(exarg_T *eap, char_u *cmd) +/// Get script string +/// +/// Used for commands which accept either `:command script` or +/// +/// :command << endmarker +/// script +/// endmarker +/// +/// @param eap Command being run. +/// @param[out] lenp Location where length of resulting string is saved. Will +/// be set to zero when skipping. +/// +/// @return [allocated] NULL or script. Does not show any error messages. +/// NULL is returned when skipping and on error. +char *script_get(exarg_T *const eap, size_t *const lenp) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC { - char_u *theline; - char *end_pattern = NULL; - char dot[] = "."; - garray_T ga; - - if (cmd[0] != '<' || cmd[1] != '<' || eap->getline == NULL) - return NULL; + const char *const cmd = (const char *)eap->arg; - ga_init(&ga, 1, 0x400); + if (cmd[0] != '<' || cmd[1] != '<' || eap->getline == NULL) { + *lenp = STRLEN(eap->arg); + return eap->skip ? NULL : xmemdupz(eap->arg, *lenp); + } - if (cmd[2] != NUL) - end_pattern = (char *)skipwhite(cmd + 2); - else - end_pattern = dot; + garray_T ga = { .ga_data = NULL, .ga_len = 0 }; + if (!eap->skip) { + ga_init(&ga, 1, 0x400); + } - for (;; ) { - theline = eap->getline( + const char *const end_pattern = ( + cmd[2] != NUL + ? (const char *)skipwhite((const char_u *)cmd + 2) + : "."); + for (;;) { + char *const theline = (char *)eap->getline( eap->cstack->cs_looplevel > 0 ? -1 : NUL, eap->cookie, 0); - if (theline == NULL || STRCMP(end_pattern, theline) == 0) { + if (theline == NULL || strcmp(end_pattern, theline) == 0) { xfree(theline); break; } - ga_concat(&ga, theline); - ga_append(&ga, '\n'); + if (!eap->skip) { + ga_concat(&ga, (const char_u *)theline); + ga_append(&ga, '\n'); + } xfree(theline); } - ga_append(&ga, NUL); + *lenp = (size_t)ga.ga_len; // Set length without trailing NUL. + if (!eap->skip) { + ga_append(&ga, NUL); + } - return (char_u *)ga.ga_data; + return (char *)ga.ga_data; } /// Iterate over history items @@ -5469,3 +5964,15 @@ histentry_T *hist_get_array(const uint8_t history_type, int **const new_hisidx, *new_hisnum = &(hisnum[history_type]); return history[history_type]; } + +static void set_search_match(pos_T *t) +{ + // First move cursor to end of match, then to the start. This + // moves the whole match onto the screen when 'nowrap' is set. + t->lnum += search_match_lines; + t->col = search_match_endcol; + if (t->lnum > curbuf->b_ml.ml_line_count) { + t->lnum = curbuf->b_ml.ml_line_count; + coladvance((colnr_T)MAXCOL); + } +} diff --git a/src/nvim/ex_getln.h b/src/nvim/ex_getln.h index 24eebdc303..051564fbe1 100644 --- a/src/nvim/ex_getln.h +++ b/src/nvim/ex_getln.h @@ -1,8 +1,11 @@ #ifndef NVIM_EX_GETLN_H #define NVIM_EX_GETLN_H -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" #include "nvim/ex_cmds.h" +#include "nvim/ex_cmds_defs.h" +#include "nvim/os/time.h" +#include "nvim/regexp_defs.h" /* Values for nextwild() and ExpandOne(). See ExpandOne() for meaning. */ #define WILD_FREE 1 diff --git a/src/nvim/farsi.c b/src/nvim/farsi.c index eb22ad1428..1053cb3ac2 100644 --- a/src/nvim/farsi.c +++ b/src/nvim/farsi.c @@ -1,3 +1,6 @@ +// 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 + /// @file farsi.c /// /// Functions for Farsi language @@ -131,7 +134,7 @@ static char_u toF_Xor_X_(int c) /// @param c The character to convert. /// /// @return Character converted to the Farsi capital leter. -char_u toF_TyA(char_u c) +static char_u toF_TyA(char_u c) { char_u tempc; @@ -321,7 +324,7 @@ static void put_curr_and_l_to_X(char_u c) } if ((curwin->w_cursor.col < (colnr_T)STRLEN(get_cursor_line_ptr()))) { - if ((p_ri && curwin->w_cursor.col) || !p_ri) { + if (!p_ri || curwin->w_cursor.col) { if (p_ri) { dec_cursor(); } else { @@ -1557,7 +1560,7 @@ static char_u toF_ending(char_u c) } /// Convert the Farsi 3342 standard into Farsi VIM. -void conv_to_pvim(void) +static void conv_to_pvim(void) { char_u *ptr; int lnum, llen, i; @@ -1588,23 +1591,23 @@ void conv_to_pvim(void) } // Following lines contains Farsi encoded character. - do_cmdline_cmd("%s/\202\231/\232/g"); - do_cmdline_cmd("%s/\201\231/\370\334/g"); + do_cmdline_cmd("%s/\202\231/\232/ge"); + do_cmdline_cmd("%s/\201\231/\370\334/ge"); // Assume the screen has been messed up: clear it and redraw. redraw_later(CLEAR); - MSG_ATTR(farsi_text_1, hl_attr(HLF_S)); + MSG_ATTR((const char *)farsi_text_1, hl_attr(HLF_S)); } /// Convert the Farsi VIM into Farsi 3342 standard. -void conv_to_pstd(void) +static void conv_to_pstd(void) { char_u *ptr; int lnum, llen, i; // Following line contains Farsi encoded character. - do_cmdline_cmd("%s/\232/\202\231/g"); - for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) { + do_cmdline_cmd("%s/\232/\202\231/ge"); + for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; lnum++) { ptr = ml_get((linenr_T)lnum); llen = (int)STRLEN(ptr); for (i = 0; i < llen; i++) { @@ -1614,7 +1617,7 @@ void conv_to_pstd(void) // Assume the screen has been messed up: clear it and redraw. redraw_later(CLEAR); - MSG_ATTR(farsi_text_2, hl_attr(HLF_S)); + msg_attr((const char *)farsi_text_2, hl_attr(HLF_S)); } /// left-right swap the characters in buf[len]. @@ -2036,34 +2039,31 @@ bool F_ischar(int c) return c >= TEE_ && c <= YE_; } -void farsi_fkey(cmdarg_T *cap) +void farsi_f8(cmdarg_T *cap FUNC_ATTR_UNUSED) { - int c = cap->cmdchar; - - if (c == K_F8) { - if (p_altkeymap) { - if (curwin->w_farsi & W_R_L) { - p_fkmap = 0; - do_cmdline_cmd("set norl"); - MSG(""); - } else { - p_fkmap = 1; - do_cmdline_cmd("set rl"); - MSG(""); - } - - curwin->w_farsi = curwin->w_farsi ^ W_R_L; + if (p_altkeymap) { + if (curwin->w_farsi & W_R_L) { + p_fkmap = 0; + do_cmdline_cmd("set norl"); + MSG(""); + } else { + p_fkmap = 1; + do_cmdline_cmd("set rl"); + MSG(""); } + + curwin->w_farsi = curwin->w_farsi ^ W_R_L; } +} - if (c == K_F9) { - if (p_altkeymap && curwin->w_p_rl) { - curwin->w_farsi = curwin->w_farsi ^ W_CONV; - if (curwin->w_farsi & W_CONV) { - conv_to_pvim(); - } else { - conv_to_pstd(); - } +void farsi_f9(cmdarg_T *cap FUNC_ATTR_UNUSED) +{ + if (p_altkeymap && curwin->w_p_rl) { + curwin->w_farsi = curwin->w_farsi ^ W_CONV; + if (curwin->w_farsi & W_CONV) { + conv_to_pvim(); + } else { + conv_to_pstd(); } } } diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index 2ac8e27047..8094a1b266 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -1,3 +1,6 @@ +// 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 + // File searching functions for 'path', 'tags' and 'cdpath' options. // // External visible functions: @@ -48,6 +51,7 @@ #include <limits.h> #include "nvim/vim.h" +#include "nvim/eval.h" #include "nvim/ascii.h" #include "nvim/file_search.h" #include "nvim/charset.h" @@ -192,7 +196,6 @@ typedef struct ff_search_ctx_T { static char_u e_pathtoolong[] = N_("E854: path too long for completion"); - /* * Initialization routine for vim_findfile(). * @@ -322,8 +325,11 @@ vim_findfile_init ( drive[0] = path[0]; drive[1] = ':'; drive[2] = NUL; - if (vim_FullName(drive, ff_expand_buffer, MAXPATHL, TRUE) == FAIL) + if (vim_FullName((const char *)drive, (char *)ff_expand_buffer, MAXPATHL, + true) + == FAIL) { goto error_return; + } path += 2; } else #endif @@ -636,9 +642,8 @@ char_u *vim_findfile(void *search_ctx_arg) if (p_verbose >= 5) { verbose_enter_scroll(); smsg("Already Searched: %s (%s)", - stackp->ffs_fix_path, stackp->ffs_wc_path); - /* don't overwrite this either */ - msg_puts((char_u *)"\n"); + stackp->ffs_fix_path, stackp->ffs_wc_path); + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); } #endif @@ -650,8 +655,7 @@ char_u *vim_findfile(void *search_ctx_arg) verbose_enter_scroll(); smsg("Searching: %s (%s)", stackp->ffs_fix_path, stackp->ffs_wc_path); - /* don't overwrite this either */ - msg_puts((char_u *)"\n"); + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); } #endif @@ -809,10 +813,8 @@ char_u *vim_findfile(void *search_ctx_arg) ) == FAIL) { if (p_verbose >= 5) { verbose_enter_scroll(); - smsg("Already: %s", - file_path); - /* don't overwrite this either */ - msg_puts((char_u *)"\n"); + smsg("Already: %s", file_path); + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); } continue; @@ -837,8 +839,7 @@ char_u *vim_findfile(void *search_ctx_arg) if (p_verbose >= 5) { verbose_enter_scroll(); smsg("HIT: %s", file_path); - /* don't overwrite this either */ - msg_puts((char_u *)"\n"); + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); } #endif @@ -999,10 +1000,8 @@ static ff_visited_list_hdr_T *ff_get_visited_list(char_u *filename, ff_visited_l #ifdef FF_VERBOSE if (p_verbose >= 5) { verbose_enter_scroll(); - smsg("ff_get_visited_list: FOUND list for %s", - filename); - /* don't overwrite this either */ - msg_puts((char_u *)"\n"); + smsg("ff_get_visited_list: FOUND list for %s", filename); + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); } #endif @@ -1016,8 +1015,7 @@ static ff_visited_list_hdr_T *ff_get_visited_list(char_u *filename, ff_visited_l if (p_verbose >= 5) { verbose_enter_scroll(); smsg("ff_get_visited_list: new list for %s", filename); - /* don't overwrite this either */ - msg_puts((char_u *)"\n"); + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); } #endif @@ -1062,7 +1060,7 @@ static bool ff_wc_equal(char_u *s1, char_u *s2) c1 = PTR2CHAR(s1 + i); c2 = PTR2CHAR(s2 + j); - if ((p_fic ? vim_tolower(c1) != vim_tolower(c2) : c1 != c2) + if ((p_fic ? mb_tolower(c1) != mb_tolower(c2) : c1 != c2) && (prev1 != '*' || prev2 != '*')) { return false; } @@ -1370,6 +1368,11 @@ find_file_in_path_option ( char_u *buf = NULL; int rel_to_curdir; + if (rel_fname != NULL && path_with_url((const char *)rel_fname)) { + // Do not attempt to search "relative" to a URL. #6009 + rel_fname = NULL; + } + if (first == TRUE) { /* copy file name into NameBuff, expanding environment variables */ save_char = ptr[len]; @@ -1522,26 +1525,85 @@ theend: return file_name; } +void do_autocmd_dirchanged(char *new_dir, CdScope scope) +{ + static bool recursive = false; + + if (recursive || !has_event(EVENT_DIRCHANGED)) { + // No autocommand was defined or we changed + // the directory from this autocommand. + return; + } + + recursive = true; + + dict_T *dict = get_vim_var_dict(VV_EVENT); + char buf[8]; + + switch (scope) { + case kCdScopeGlobal: + snprintf(buf, sizeof(buf), "global"); + break; + case kCdScopeTab: + snprintf(buf, sizeof(buf), "tab"); + break; + case kCdScopeWindow: + snprintf(buf, sizeof(buf), "window"); + break; + case kCdScopeInvalid: + // Should never happen. + assert(false); + } + + tv_dict_add_str(dict, S_LEN("scope"), buf); + tv_dict_add_str(dict, S_LEN("cwd"), new_dir); + tv_dict_set_keys_readonly(dict); + + apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, (char_u *)new_dir, false, + NULL); + + tv_dict_clear(dict); + + recursive = false; +} + /// Change to a file's directory. /// Caller must call shorten_fnames()! /// @return OK or FAIL int vim_chdirfile(char_u *fname) { - char_u dir[MAXPATHL]; + char dir[MAXPATHL]; STRLCPY(dir, fname, MAXPATHL); - *path_tail_with_sep(dir) = NUL; - return os_chdir((char *)dir) == 0 ? OK : FAIL; + *path_tail_with_sep((char_u *)dir) = NUL; + + if (os_dirname(NameBuff, sizeof(NameBuff)) != OK) { + NameBuff[0] = NUL; + } + + if (os_chdir(dir) != 0) { + return FAIL; + } + +#ifdef BACKSLASH_IN_FILENAME + slash_adjust(dir); +#endif + if (!strequal(dir, (char *)NameBuff)) { + do_autocmd_dirchanged(dir, kCdScopeWindow); + } + + return OK; } /// Change directory to "new_dir". Search 'cdpath' for relative directory names. -int vim_chdir(char_u *new_dir) +int vim_chdir(char_u *new_dir, CdScope scope) { char_u *dir_name = find_directory_in_path(new_dir, STRLEN(new_dir), FNAME_MESS, curbuf->b_ffname); if (dir_name == NULL) { return -1; } + int r = os_chdir((char *)dir_name); xfree(dir_name); return r; diff --git a/src/nvim/file_search.h b/src/nvim/file_search.h index 833a1a05ff..b128029123 100644 --- a/src/nvim/file_search.h +++ b/src/nvim/file_search.h @@ -1,6 +1,11 @@ #ifndef NVIM_FILE_SEARCH_H #define NVIM_FILE_SEARCH_H +#include <stdlib.h> // for size_t + +#include "nvim/types.h" // for char_u +#include "nvim/globals.h" // for CdScope + /* Flags for find_file_*() functions. */ #define FINDFILE_FILE 0 /* only files */ #define FINDFILE_DIR 1 /* only directories */ diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 29114201d2..feb16f44d4 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -1,3 +1,6 @@ +// 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 + /* * fileio.c: read from and write to a file */ @@ -200,18 +203,14 @@ void filemess(buf_T *buf, char_u *name, char_u *s, int attr) { int msg_scroll_save; - if (msg_silent != 0) + if (msg_silent != 0) { return; - msg_add_fname(buf, name); /* put file name in IObuff with quotes */ - /* If it's extremely long, truncate it. */ - if (STRLEN(IObuff) > IOSIZE - 80) - IObuff[IOSIZE - 80] = NUL; - STRCAT(IObuff, s); - /* - * For the first message may have to start a new line. - * For further ones overwrite the previous one, reset msg_scroll before - * calling filemess(). - */ + } + add_quoted_fname((char *)IObuff, IOSIZE - 80, buf, (const char *)name); + xstrlcat((char *)IObuff, (const char *)s, IOSIZE); + // For the first message may have to start a new line. + // For further ones overwrite the previous one, reset msg_scroll before + // calling filemess(). msg_scroll_save = msg_scroll; if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0) msg_scroll = FALSE; @@ -248,8 +247,9 @@ void filemess(buf_T *buf, char_u *name, char_u *s, int attr) * stdin) * READ_DUMMY read into a dummy buffer (to check if file contents changed) * READ_KEEP_UNDO don't clear undo info or read it from a file + * READ_FIFO read from fifo/socket instead of a file * - * return FAIL for failure, OK otherwise + * return FAIL for failure, NOTDONE for directory (failure), or OK */ int readfile ( @@ -258,7 +258,7 @@ readfile ( linenr_T from, linenr_T lines_to_skip, linenr_T lines_to_read, - exarg_T *eap, /* can be NULL! */ + exarg_T *eap, // can be NULL! int flags ) { @@ -268,6 +268,7 @@ readfile ( int filtering = (flags & READ_FILTER); int read_stdin = (flags & READ_STDIN); int read_buffer = (flags & READ_BUFFER); + int read_fifo = (flags & READ_FIFO); int set_options = newfile || read_buffer || (eap != NULL && eap->read_edit); linenr_T read_buf_lnum = 1; /* next line to read from curbuf */ @@ -281,9 +282,9 @@ readfile ( int wasempty; /* buffer was empty before reading */ colnr_T len; long size = 0; - char_u *p; - off_t filesize = 0; - int skip_read = FALSE; + char_u *p = NULL; + off_T filesize = 0; + int skip_read = false; context_sha256_T sha_ctx; int read_undo_file = FALSE; int split = 0; /* number of split lines */ @@ -427,8 +428,8 @@ readfile ( } } - if (!read_buffer && !read_stdin) { - perm = os_getperm(fname); + if (!read_buffer && !read_stdin && !read_fifo) { + perm = os_getperm((const char *)fname); #ifdef UNIX // On Unix it is possible to read a directory, so we have to // check for it before os_open(). @@ -444,13 +445,14 @@ readfile ( // ... or a character special file named /dev/fd/<n> # endif ) { - if (S_ISDIR(perm)) + if (S_ISDIR(perm)) { filemess(curbuf, fname, (char_u *)_("is a directory"), 0); - else + } else { filemess(curbuf, fname, (char_u *)_("is not a file"), 0); + } msg_end(); msg_scroll = msg_save; - return FAIL; + return S_ISDIR(perm) ? NOTDONE : FAIL; } #endif } @@ -468,8 +470,8 @@ readfile ( if (check_readonly && !readonlymode) curbuf->b_p_ro = FALSE; - if (newfile && !read_stdin && !read_buffer) { - /* Remember time of file. */ + if (newfile && !read_stdin && !read_buffer && !read_fifo) { + // Remember time of file. FileInfo file_info; if (os_fileinfo((char *)fname, &file_info)) { buf_store_file_info(curbuf, &file_info); @@ -613,10 +615,12 @@ readfile ( return FAIL; } #ifdef UNIX - /* Set swap file protection bits after creating it. */ + // Set swap file protection bits after creating it. if (swap_mode > 0 && curbuf->b_ml.ml_mfp != NULL - && curbuf->b_ml.ml_mfp->mf_fname != NULL) - (void)os_setperm(curbuf->b_ml.ml_mfp->mf_fname, (long)swap_mode); + && curbuf->b_ml.ml_mfp->mf_fname != NULL) { + (void)os_setperm((const char *)curbuf->b_ml.ml_mfp->mf_fname, + (long)swap_mode); + } #endif } @@ -699,16 +703,9 @@ readfile ( wasempty = (curbuf->b_ml.ml_flags & ML_EMPTY); if (!recoverymode && !filtering && !(flags & READ_DUMMY)) { - /* - * Show the user that we are busy reading the input. Sometimes this - * may take a while. When reading from stdin another program may - * still be running, don't move the cursor to the last line, unless - * always using the GUI. - */ - if (read_stdin) { - mch_msg(_("Nvim: Reading from stdin...\n")); - } else if (!read_buffer) + if (!read_stdin && !read_buffer) { filemess(curbuf, sfname, (char_u *)"", 0); + } } msg_scroll = FALSE; /* overwrite the file message */ @@ -738,43 +735,16 @@ readfile ( fenc = (char_u *)""; /* binary: don't convert */ fenc_alloced = FALSE; } else if (curbuf->b_help) { - char_u firstline[80]; - int fc; - - /* Help files are either utf-8 or latin1. Try utf-8 first, if this - * fails it must be latin1. - * Always do this when 'encoding' is "utf-8". Otherwise only do - * this when needed to avoid [converted] remarks all the time. - * It is needed when the first line contains non-ASCII characters. - * That is only in *.??x files. */ - fenc = (char_u *)"latin1"; - c = enc_utf8; - if (!c && !read_stdin) { - fc = fname[STRLEN(fname) - 1]; - if (TOLOWER_ASC(fc) == 'x') { - /* Read the first line (and a bit more). Immediately rewind to - * the start of the file. If the read() fails "len" is -1. */ - len = read_eintr(fd, firstline, 80); - lseek(fd, (off_t)0L, SEEK_SET); - for (p = firstline; p < firstline + len; ++p) - if (*p >= 0x80) { - c = TRUE; - break; - } - } - } + // Help files are either utf-8 or latin1. Try utf-8 first, if this + // fails it must be latin1. + // It is needed when the first line contains non-ASCII characters. + // That is only in *.??x files. + fenc_next = (char_u *)"latin1"; + fenc = (char_u *)"utf-8"; - if (c) { - fenc_next = fenc; - fenc = (char_u *)"utf-8"; + fenc_alloced = false; - /* When the file is utf-8 but a character doesn't fit in - * 'encoding' don't retry. In help text editing utf-8 bytes - * doesn't make sense. */ - if (!enc_utf8) - keep_dest_enc = TRUE; - } - fenc_alloced = FALSE; + c = 1; } else if (*p_fencs == NUL) { fenc = curbuf->b_p_fenc; /* use format from buffer */ fenc_alloced = FALSE; @@ -809,9 +779,9 @@ retry: if (read_buffer) { read_buf_lnum = 1; read_buf_col = 0; - } else if (read_stdin || lseek(fd, (off_t)0L, SEEK_SET) != 0) { - /* Can't rewind the file, give up. */ - error = TRUE; + } else if (read_stdin || vim_lseek(fd, (off_T)0L, SEEK_SET) != 0) { + // Can't rewind the file, give up. + error = true; goto failed; } /* Delete the previously read lines. */ @@ -927,6 +897,7 @@ retry: * and we can't do it internally or with iconv(). */ if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL + && !read_fifo # ifdef USE_ICONV && iconv_fd == (iconv_t)-1 # endif @@ -967,7 +938,7 @@ retry: /* Set "can_retry" when it's possible to rewind the file and try with * another "fenc" value. It's FALSE when no other "fenc" to try, reading * stdin or fixed at a specific encoding. */ - can_retry = (*fenc != NUL && !read_stdin && !keep_dest_enc); + can_retry = (*fenc != NUL && !read_stdin && !keep_dest_enc && !read_fifo); if (!skip_read) { linerest = 0; @@ -979,6 +950,7 @@ retry: && curbuf->b_ffname != NULL && curbuf->b_p_udf && !filtering + && !read_fifo && !read_stdin && !read_buffer); if (read_undo_file) @@ -1646,19 +1618,16 @@ rewind_retry: if (fileformat == EOL_DOS) { if (ptr[-1] == CAR) { /* remove CR */ ptr[-1] = NUL; - --len; - } - /* - * Reading in Dos format, but no CR-LF found! - * When 'fileformats' includes "unix", delete all - * the lines read so far and start all over again. - * Otherwise give an error message later. - */ - else if (ff_error != EOL_DOS) { - if ( try_unix - && !read_stdin - && (read_buffer - || lseek(fd, (off_t)0L, SEEK_SET) == 0)) { + len--; + } else if (ff_error != EOL_DOS) { + // Reading in Dos format, but no CR-LF found! + // When 'fileformats' includes "unix", delete all + // the lines read so far and start all over again. + // Otherwise give an error message later. + if (try_unix + && !read_stdin + && (read_buffer + || vim_lseek(fd, (off_T)0L, SEEK_SET) == 0)) { fileformat = EOL_UNIX; if (set_options) set_fileformat(EOL_UNIX, OPT_LOCAL); @@ -1741,16 +1710,11 @@ failed: } # endif - if (!read_buffer && !read_stdin) - close(fd); /* errors are ignored */ -#ifdef HAVE_FD_CLOEXEC - else { - int fdflags = fcntl(fd, F_GETFD); - if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) { - (void)fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC); - } + if (!read_buffer && !read_stdin) { + close(fd); // errors are ignored + } else { + (void)os_set_cloexec(fd); } -#endif xfree(buffer); if (read_stdin) { @@ -1809,8 +1773,8 @@ failed: } if (!filtering && !(flags & READ_DUMMY)) { - msg_add_fname(curbuf, sfname); /* fname in IObuff with quotes */ - c = FALSE; + add_quoted_fname((char *)IObuff, IOSIZE, curbuf, (const char *)sfname); + c = false; #ifdef UNIX # ifdef S_ISFIFO @@ -1881,17 +1845,22 @@ failed: xfree(keep_msg); keep_msg = NULL; + p = NULL; msg_scrolled_ign = TRUE; - p = msg_trunc_attr(IObuff, FALSE, 0); + + if (!read_stdin && !read_buffer) { + p = msg_trunc_attr(IObuff, FALSE, 0); + } + if (read_stdin || read_buffer || restart_edit != 0 - || (msg_scrolled != 0 && !need_wait_return)) - /* Need to repeat the message after redrawing when: - * - When reading from stdin (the screen will be cleared next). - * - When restart_edit is set (otherwise there will be a delay - * before redrawing). - * - When the screen was scrolled but there is no wait-return - * prompt. */ + || (msg_scrolled != 0 && !need_wait_return)) { + // Need to repeat the message after redrawing when: + // - When reading from stdin (the screen will be cleared next). + // - When restart_edit is set (otherwise there will be a delay before + // redrawing). + // - When the screen was scrolled but there is no wait-return prompt. set_keep_msg(p, 0); + } msg_scrolled_ign = FALSE; } @@ -1954,7 +1923,7 @@ failed: u_read_undo(NULL, hash, fname); } - if (!read_stdin && !read_buffer) { + if (!read_stdin && !read_fifo && (!read_buffer || sfname != NULL)) { int m = msg_scroll; int n = msg_scrolled; @@ -1972,7 +1941,7 @@ failed: if (filtering) { apply_autocmds_exarg(EVENT_FILTERREADPOST, NULL, sfname, false, curbuf, eap); - } else if (newfile) { + } else if (newfile || (read_buffer && sfname != NULL)) { apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname, false, curbuf, eap); if (!au_did_filetype && *curbuf->b_p_ft != NUL) { @@ -2005,7 +1974,7 @@ failed: /// Do not accept "/dev/fd/[012]", opening these may hang Vim. /// /// @param fname file name to check -static bool is_dev_fd_file(char_u *fname) +bool is_dev_fd_file(char_u *fname) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { return STRNCMP(fname, "/dev/fd/", 8) == 0 @@ -2262,9 +2231,16 @@ buf_write ( int len; linenr_T lnum; long nchars; - char_u *errmsg = NULL; - int errmsg_allocated = FALSE; - char_u *errnum = NULL; +#define SET_ERRMSG_NUM(num, msg) \ + errnum = num, errmsg = msg, errmsgarg = 0 +#define SET_ERRMSG_ARG(msg, error) \ + errnum = NULL, errmsg = msg, errmsgarg = error +#define SET_ERRMSG(msg) \ + errnum = NULL, errmsg = msg, errmsgarg = 0 + const char *errnum = NULL; + char *errmsg = NULL; + int errmsgarg = 0; + bool errmsg_allocated = false; char_u *buffer; char_u smallbuf[SMBUFSIZE]; char_u *backup_ext; @@ -2286,7 +2262,6 @@ buf_write ( /* writing everything */ int whole = (start == 1 && end == buf->b_ml.ml_line_count); linenr_T old_line_count = buf->b_ml.ml_line_count; - int attr; int fileformat; int write_bin; struct bw_info write_info; /* info for buf_write_bytes() */ @@ -2396,6 +2371,7 @@ buf_write ( int did_cmd = FALSE; int nofile_err = FALSE; int empty_memline = (buf->b_ml.ml_mfp == NULL); + bufref_T bufref; /* * Apply PRE autocommands. @@ -2411,8 +2387,9 @@ buf_write ( if (fname == buf->b_sfname) buf_fname_s = TRUE; - /* set curwin/curbuf to buf and save a few things */ + // Set curwin/curbuf to buf and save a few things. aucmd_prepbuf(&aco, buf); + set_bufref(&bufref, buf); if (append) { if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEAPPENDCMD, @@ -2460,14 +2437,13 @@ buf_write ( /* restore curwin/curbuf and a few other things */ aucmd_restbuf(&aco); - /* - * In three situations we return here and don't write the file: - * 1. the autocommands deleted or unloaded the buffer. - * 2. The autocommands abort script processing. - * 3. If one of the "Cmd" autocommands was executed. - */ - if (!buf_valid(buf)) + // In three situations we return here and don't write the file: + // 1. the autocommands deleted or unloaded the buffer. + // 2. The autocommands abort script processing. + // 3. If one of the "Cmd" autocommands was executed. + if (!bufref_valid(&bufref)) { buf = NULL; + } if (buf == NULL || (buf->b_ml.ml_mfp == NULL && !empty_memline) || did_cmd || nofile_err || aborting() @@ -2580,13 +2556,11 @@ buf_write ( perm = file_info_old.stat.st_mode; if (!S_ISREG(file_info_old.stat.st_mode)) { /* not a file */ if (S_ISDIR(file_info_old.stat.st_mode)) { - errnum = (char_u *)"E502: "; - errmsg = (char_u *)_("is a directory"); + SET_ERRMSG_NUM("E502", _("is a directory")); goto fail; } if (os_nodetype((char *)fname) != NODE_WRITABLE) { - errnum = (char_u *)"E503: "; - errmsg = (char_u *)_("is not a file or writable device"); + SET_ERRMSG_NUM("E503", _("is not a file or writable device")); goto fail; } /* It's a device of some kind (or a fifo) which we can write to @@ -2596,14 +2570,11 @@ buf_write ( perm = -1; } } -#else /* win32 */ - /* - * Check for a writable device name. - */ - c = os_nodetype((char *)fname); +#else // win32 + // Check for a writable device name. + c = fname == NULL ? NODE_OTHER : os_nodetype((char *)fname); if (c == NODE_OTHER) { - errnum = (char_u *)"E503: "; - errmsg = (char_u *)_("is not a file or writable device"); + SET_ERRMSG_NUM("E503", _("is not a file or writable device")); goto fail; } if (c == NODE_WRITABLE) { @@ -2611,20 +2582,18 @@ buf_write ( newfile = TRUE; perm = -1; } else { - perm = os_getperm(fname); - if (perm < 0) - newfile = TRUE; - else if (os_isdir(fname)) { - errnum = (char_u *)"E502: "; - errmsg = (char_u *)_("is a directory"); + perm = os_getperm((const char *)fname); + if (perm < 0) { + newfile = true; + } else if (os_isdir(fname)) { + SET_ERRMSG_NUM("E502", _("is a directory")); goto fail; } if (overwriting) { os_fileinfo((char *)fname, &file_info_old); } - } -#endif /* !UNIX */ +#endif // !UNIX if (!device && !newfile) { /* @@ -2635,11 +2604,9 @@ buf_write ( if (!forceit && file_readonly) { if (vim_strchr(p_cpo, CPO_FWRITE) != NULL) { - errnum = (char_u *)"E504: "; - errmsg = (char_u *)_(err_readonly); + SET_ERRMSG_NUM("E504", _(err_readonly)); } else { - errnum = (char_u *)"E505: "; - errmsg = (char_u *)_("is read-only (add ! to override)"); + SET_ERRMSG_NUM("E505", _("is read-only (add ! to override)")); } goto fail; } @@ -2875,9 +2842,9 @@ buf_write ( xfree(backup); backup = NULL; } else { - /* set file protection same as original file, but - * strip s-bit */ - (void)os_setperm(backup, perm & 0777); + // set file protection same as original file, but + // strip s-bit. + (void)os_setperm((const char *)backup, perm & 0777); #ifdef UNIX /* @@ -2888,7 +2855,8 @@ buf_write ( */ if (file_info_new.stat.st_gid != file_info_old.stat.st_gid && os_fchown(bfd, -1, file_info_old.stat.st_gid) != 0) { - os_setperm(backup, (perm & 0707) | ((perm & 07) << 3)); + os_setperm((const char *)backup, + (perm & 0707) | ((perm & 07) << 3)); } # ifdef HAVE_SELINUX mch_copy_sec(fname, backup); @@ -2906,23 +2874,27 @@ buf_write ( while ((write_info.bw_len = read_eintr(fd, copybuf, BUFSIZE)) > 0) { if (buf_write_bytes(&write_info) == FAIL) { - errmsg = (char_u *)_( - "E506: Can't write to backup file (add ! to override)"); + SET_ERRMSG(_( + "E506: Can't write to backup file (add ! to override)")); break; } os_breakcheck(); if (got_int) { - errmsg = (char_u *)_(e_interr); + SET_ERRMSG(_(e_interr)); break; } } - if (close(bfd) < 0 && errmsg == NULL) - errmsg = (char_u *)_( - "E507: Close error for backup file (add ! to override)"); - if (write_info.bw_len < 0) - errmsg = (char_u *)_( - "E508: Can't read file for backup (add ! to override)"); + int error; + if ((error = os_close(bfd)) != 0 && errmsg == NULL) { + SET_ERRMSG_ARG(_("E507: Close error for backup file " + "(add ! to override): %s"), + error); + } + if (write_info.bw_len < 0) { + SET_ERRMSG(_( + "E508: Can't read file for backup (add ! to override)")); + } #ifdef UNIX set_file_time(backup, file_info_old.stat.st_atim.tv_sec, @@ -2939,18 +2911,19 @@ buf_write ( } } nobackup: - close(fd); /* ignore errors for closing read file */ + os_close(fd); // Ignore errors for closing read file. xfree(copybuf); - if (backup == NULL && errmsg == NULL) - errmsg = (char_u *)_( - "E509: Cannot create backup file (add ! to override)"); - /* ignore errors when forceit is TRUE */ + if (backup == NULL && errmsg == NULL) { + SET_ERRMSG(_( + "E509: Cannot create backup file (add ! to override)")); + } + // Ignore errors when forceit is TRUE. if ((some_error || errmsg != NULL) && !forceit) { retval = FAIL; goto fail; } - errmsg = NULL; + SET_ERRMSG(NULL); } else { char_u *dirp; char_u *p; @@ -2965,8 +2938,7 @@ nobackup: * anyway, thus we need an extra check here. */ if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL) { - errnum = (char_u *)"E504: "; - errmsg = (char_u *)_(err_readonly); + SET_ERRMSG_NUM("E504", _(err_readonly)); goto fail; } @@ -3030,7 +3002,7 @@ nobackup: } } if (backup == NULL && !forceit) { - errmsg = (char_u *)_("E510: Can't make backup file (add ! to override)"); + SET_ERRMSG(_("E510: Can't make backup file (add ! to override)")); goto fail; } } @@ -3042,8 +3014,8 @@ nobackup: && file_info_old.stat.st_uid == getuid() && vim_strchr(p_cpo, CPO_FWRITE) == NULL) { perm |= 0200; - (void)os_setperm(fname, perm); - made_writable = TRUE; + (void)os_setperm((const char *)fname, perm); + made_writable = true; } #endif @@ -3071,7 +3043,7 @@ nobackup: && !(exiting && backup != NULL)) { ml_preserve(buf, FALSE); if (got_int) { - errmsg = (char_u *)_(e_interr); + SET_ERRMSG(_(e_interr)); goto restore_backup; } } @@ -3142,8 +3114,8 @@ nobackup: */ if (*p_ccv != NUL) { wfname = vim_tempname(); - if (wfname == NULL) { /* Can't write without a tempfile! */ - errmsg = (char_u *)_("E214: Can't find temp file for writing"); + if (wfname == NULL) { // Can't write without a tempfile! + SET_ERRMSG(_("E214: Can't find temp file for writing")); goto restore_backup; } } @@ -3155,8 +3127,8 @@ nobackup: && wfname == fname ) { if (!forceit) { - errmsg = (char_u *)_( - "E213: Cannot convert (add ! to write without conversion)"); + SET_ERRMSG(_( + "E213: Cannot convert (add ! to write without conversion)")); goto restore_backup; } notconverted = TRUE; @@ -3187,15 +3159,14 @@ nobackup: #ifdef UNIX FileInfo file_info; - /* Don't delete the file when it's a hard or symbolic link. */ - if ((!newfile && os_fileinfo_hardlinks(&file_info) > 1) + // Don't delete the file when it's a hard or symbolic link. + if ((!newfile && os_fileinfo_hardlinks(&file_info_old) > 1) || (os_fileinfo_link((char *)fname, &file_info) && !os_fileinfo_id_equal(&file_info, &file_info_old))) { - errmsg = (char_u *)_("E166: Can't open linked file for writing"); - } else + SET_ERRMSG(_("E166: Can't open linked file for writing")); + } else { #endif - { - errmsg = (char_u *)_("E212: Can't open file for writing"); + SET_ERRMSG_ARG(_("E212: Can't open file for writing: %s"), fd); if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL && perm >= 0) { #ifdef UNIX @@ -3213,7 +3184,9 @@ nobackup: os_remove((char *)wfname); continue; } +#ifdef UNIX } +#endif } restore_backup: @@ -3255,7 +3228,7 @@ restore_backup: xfree(wfname); goto fail; } - errmsg = NULL; + SET_ERRMSG(NULL); write_info.bw_fd = fd; @@ -3375,7 +3348,6 @@ restore_backup: nchars += len; } -#if defined(UNIX) // On many journalling file systems there is a bug that causes both the // original and the backup file to be lost when halting the system right // after writing the file. That's because only the meta-data is @@ -3384,11 +3356,11 @@ restore_backup: // For a device do try the fsync() but don't complain if it does not work // (could be a pipe). // If the 'fsync' option is FALSE, don't fsync(). Useful for laptops. - if (p_fs && os_fsync(fd) != 0 && !device) { - errmsg = (char_u *)_("E667: Fsync failed"); + int error; + if (p_fs && (error = os_fsync(fd)) != 0 && !device) { + SET_ERRMSG_ARG(_("E667: Fsync failed: %s"), error); end = 0; } -#endif #ifdef HAVE_SELINUX /* Probably need to set the security context. */ @@ -3407,8 +3379,9 @@ restore_backup: || file_info.stat.st_uid != file_info_old.stat.st_uid || file_info.stat.st_gid != file_info_old.stat.st_gid) { os_fchown(fd, file_info_old.stat.st_uid, file_info_old.stat.st_gid); - if (perm >= 0) /* set permission again, may have changed */ - (void)os_setperm(wfname, perm); + if (perm >= 0) { // Set permission again, may have changed. + (void)os_setperm((const char *)wfname, perm); + } } buf_set_file_id(buf); } else if (!buf->file_id_valid) { @@ -3417,8 +3390,8 @@ restore_backup: } #endif - if (close(fd) != 0) { - errmsg = (char_u *)_("E512: Close failed"); + if ((error = os_close(fd)) != 0) { + SET_ERRMSG_ARG(_("E512: Close failed: %s"), error); end = 0; } @@ -3426,8 +3399,9 @@ restore_backup: if (made_writable) perm &= ~0200; /* reset 'w' bit for security reasons */ #endif - if (perm >= 0) /* set perm. of new file same as old file */ - (void)os_setperm(wfname, perm); + if (perm >= 0) { // Set perm. of new file same as old file. + (void)os_setperm((const char *)wfname, perm); + } #ifdef HAVE_ACL /* Probably need to set the ACL before changing the user (can't set the * ACL on a file the user doesn't own). */ @@ -3454,21 +3428,24 @@ restore_backup: if (end == 0) { if (errmsg == NULL) { if (write_info.bw_conv_error) { - if (write_info.bw_conv_error_lnum == 0) - errmsg = (char_u *)_( - "E513: write error, conversion failed (make 'fenc' empty to override)"); - else { - errmsg_allocated = TRUE; - errmsg = xmalloc(300); - vim_snprintf((char *)errmsg, 300, - _("E513: write error, conversion failed in line %" PRId64 + if (write_info.bw_conv_error_lnum == 0) { + SET_ERRMSG(_( + "E513: write error, conversion failed " + "(make 'fenc' empty to override)")); + } else { + errmsg_allocated = true; + SET_ERRMSG(xmalloc(300)); + vim_snprintf( + errmsg, 300, + _("E513: write error, conversion failed in line %" PRIdLINENR " (make 'fenc' empty to override)"), - (int64_t)write_info.bw_conv_error_lnum); + write_info.bw_conv_error_lnum); } - } else if (got_int) - errmsg = (char_u *)_(e_interr); - else - errmsg = (char_u *)_("E514: write error (file system full?)"); + } else if (got_int) { + SET_ERRMSG(_(e_interr)); + } else { + SET_ERRMSG(_("E514: write error (file system full?)")); + } } /* @@ -3523,8 +3500,8 @@ restore_backup: fname = sfname; /* use shortname now, for the messages */ #endif if (!filtering) { - msg_add_fname(buf, fname); /* put fname in IObuff with quotes */ - c = FALSE; + add_quoted_fname((char *)IObuff, IOSIZE, buf, (const char *)fname); + c = false; if (write_info.bw_conv_error) { STRCAT(IObuff, _(" CONVERSION ERROR")); c = TRUE; @@ -3633,7 +3610,7 @@ restore_backup: close(empty_fd); } if (org != NULL) { - os_setperm((char_u *)org, os_getperm(fname) & 0777); + os_setperm(org, os_getperm((const char *)fname) & 0777); xfree(org); } } @@ -3673,33 +3650,32 @@ nofail: #endif if (errmsg != NULL) { - int numlen = errnum != NULL ? (int)STRLEN(errnum) : 0; - - attr = hl_attr(HLF_E); /* set highlight for error messages */ - msg_add_fname(buf, + // - 100 to save some space for further error message #ifndef UNIX - sfname + add_quoted_fname((char *)IObuff, IOSIZE - 100, buf, (const char *)sfname); #else - fname + add_quoted_fname((char *)IObuff, IOSIZE - 100, buf, (const char *)fname); #endif - ); /* put file name in IObuff with quotes */ - if (STRLEN(IObuff) + STRLEN(errmsg) + numlen >= IOSIZE) - IObuff[IOSIZE - STRLEN(errmsg) - numlen - 1] = NUL; - /* If the error message has the form "is ...", put the error number in - * front of the file name. */ if (errnum != NULL) { - STRMOVE(IObuff + numlen, IObuff); - memmove(IObuff, errnum, (size_t)numlen); + if (errmsgarg != 0) { + emsgf("%s: %s%s: %s", errnum, IObuff, errmsg, os_strerror(errmsgarg)); + } else { + emsgf("%s: %s%s", errnum, IObuff, errmsg); + } + } else if (errmsgarg != 0) { + emsgf(errmsg, os_strerror(errmsgarg)); + } else { + emsgf(errmsg); } - STRCAT(IObuff, errmsg); - emsg(IObuff); - if (errmsg_allocated) + if (errmsg_allocated) { xfree(errmsg); + } retval = FAIL; if (end == 0) { + const int attr = hl_attr(HLF_E); // Set highlight for error messages. MSG_PUTS_ATTR(_("\nWARNING: Original file may be lost or damaged\n"), - attr | MSG_HIST); + attr | MSG_HIST); MSG_PUTS_ATTR(_( "don't quit the editor until the file is successfully written!"), attr | MSG_HIST); @@ -3759,6 +3735,9 @@ nofail: got_int |= prev_got_int; return retval; +#undef SET_ERRMSG +#undef SET_ERRMSG_ARG +#undef SET_ERRMSG_NUM } /* @@ -3802,16 +3781,25 @@ static int set_rw_fname(char_u *fname, char_u *sfname) return OK; } -/* - * Put file name into IObuff with quotes. - */ -void msg_add_fname(buf_T *buf, char_u *fname) +/// Put file name into the specified buffer with quotes +/// +/// Replaces home directory at the start with `~`. +/// +/// @param[out] ret_buf Buffer to save results to. +/// @param[in] buf_len ret_buf length. +/// @param[in] buf buf_T file name is coming from. +/// @param[in] fname File name to write. +static void add_quoted_fname(char *const ret_buf, const size_t buf_len, + const buf_T *const buf, const char *fname) + FUNC_ATTR_NONNULL_ARG(1) { - if (fname == NULL) - fname = (char_u *)"-stdin-"; - home_replace(buf, fname, IObuff + 1, IOSIZE - 4, TRUE); - IObuff[0] = '"'; - STRCAT(IObuff, "\" "); + if (fname == NULL) { + fname = "-stdin-"; + } + ret_buf[0] = '"'; + home_replace(buf, (const char_u *)fname, (char_u *)ret_buf + 1, + (int)buf_len - 4, true); + xstrlcat(ret_buf, "\" ", buf_len); } /// Append message for text mode to IObuff. @@ -3843,7 +3831,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) +void msg_add_lines(int insert_space, long lnum, off_T nchars) { char_u *p; @@ -3888,15 +3876,15 @@ static int check_mtime(buf_T *buf, FileInfo *file_info) if (buf->b_mtime_read != 0 && time_differs(file_info->stat.st_mtim.tv_sec, buf->b_mtime_read)) { - msg_scroll = TRUE; /* don't overwrite messages here */ - msg_silent = 0; /* must give this prompt */ - /* don't use emsg() here, don't want to flush the buffers */ - MSG_ATTR(_("WARNING: The file has been changed since reading it!!!"), - hl_attr(HLF_E)); - if (ask_yesno((char_u *)_("Do you really want to write to it"), - TRUE) == 'n') + msg_scroll = true; // Don't overwrite messages here. + msg_silent = 0; // Must give this prompt. + // Don't use emsg() here, don't want to flush the buffers. + msg_attr(_("WARNING: The file has been changed since reading it!!!"), + hl_attr(HLF_E)); + if (ask_yesno(_("Do you really want to write to it"), true) == 'n') { return FAIL; - msg_scroll = FALSE; /* always overwrite the file message now */ + } + msg_scroll = false; // Always overwrite the file message now. } return OK; } @@ -4553,9 +4541,10 @@ int put_time(FILE *fd, time_t time_) /// os_rename() only works if both files are on the same file system, this /// function will (attempts to?) copy the file across if rename fails -- webb -// +/// /// @return -1 for failure, 0 for success -int vim_rename(char_u *from, char_u *to) +int vim_rename(const char_u *from, const char_u *to) + FUNC_ATTR_NONNULL_ALL { int fd_in; int fd_out; @@ -4574,10 +4563,12 @@ int vim_rename(char_u *from, char_u *to) * the file name differs we need to go through a temp file. */ if (fnamecmp(from, to) == 0) { - if (p_fic && STRCMP(path_tail(from), path_tail(to)) != 0) + if (p_fic && (STRCMP(path_tail((char_u *)from), path_tail((char_u *)to)) + != 0)) { use_tmp_file = true; - else + } else { return 0; + } } // Fail if the "from" file doesn't exist. Avoids that "to" is deleted. @@ -4643,9 +4634,9 @@ int vim_rename(char_u *from, char_u *to) /* * Rename() failed, try copying the file. */ - perm = os_getperm(from); + perm = os_getperm((const char *)from); #ifdef HAVE_ACL - /* For systems that support ACL: get the ACL from the original file. */ + // For systems that support ACL: get the ACL from the original file. acl = mch_get_acl(from); #endif fd_in = os_open((char *)from, O_RDONLY, 0); @@ -4667,7 +4658,7 @@ int vim_rename(char_u *from, char_u *to) return -1; } - // Avoid xmalloc() here as vim_rename() is called by buf_write() when neovim + // Avoid xmalloc() here as vim_rename() is called by buf_write() when nvim // is `preserve_exit()`ing. buffer = try_malloc(BUFSIZE); if (buffer == NULL) { @@ -4693,8 +4684,8 @@ int vim_rename(char_u *from, char_u *to) errmsg = _("E210: Error reading \"%s\""); to = from; } -#ifndef UNIX /* for Unix os_open() already set the permission */ - os_setperm(to, perm); +#ifndef UNIX // For Unix os_open() already set the permission. + os_setperm((const char *)to, perm); #endif #ifdef HAVE_ACL mch_set_acl(to, acl); @@ -4726,7 +4717,6 @@ check_timestamps ( int focus /* called for GUI focus event */ ) { - buf_T *buf; int didit = 0; int n; @@ -4745,32 +4735,33 @@ check_timestamps ( if (!stuff_empty() || global_busy || !typebuf_typed() || autocmd_busy || curbuf_lock > 0 || allbuf_lock > 0 - ) - need_check_timestamps = TRUE; /* check later */ - else { - ++no_wait_return; - did_check_timestamps = TRUE; - already_warned = FALSE; - for (buf = firstbuf; buf != NULL; ) { - /* Only check buffers in a window. */ + ) { + need_check_timestamps = true; // check later + } else { + no_wait_return++; + did_check_timestamps = true; + already_warned = false; + FOR_ALL_BUFFERS(buf) { + // Only check buffers in a window. if (buf->b_nwindows > 0) { + bufref_T bufref; + set_bufref(&bufref, buf); n = buf_check_timestamp(buf, focus); - if (didit < n) + if (didit < n) { didit = n; - if (n > 0 && !buf_valid(buf)) { - /* Autocommands have removed the buffer, start at the - * first one again. */ + } + if (n > 0 && !bufref_valid(&bufref)) { + // Autocommands have removed the buffer, start at the first one again. buf = firstbuf; continue; } } - buf = buf->b_next; } --no_wait_return; need_check_timestamps = FALSE; if (need_wait_return && didit == 2) { - /* make sure msg isn't overwritten */ - msg_puts((char_u *)"\n"); + // make sure msg isn't overwritten + msg_puts("\n"); ui_flush(); } } @@ -4829,6 +4820,7 @@ buf_check_timestamp ( buf_T *buf, int focus /* called for GUI focus event */ ) + FUNC_ATTR_NONNULL_ALL { int retval = 0; char_u *path; @@ -4844,6 +4836,9 @@ buf_check_timestamp ( char_u *s; char *reason; + bufref_T bufref; + set_bufref(&bufref, buf); + // If its a terminal, there is no file name, the buffer is not loaded, // 'buftype' is set, we are in the middle of a save or being called // recursively: ignore this buffer. @@ -4913,8 +4908,9 @@ buf_check_timestamp ( allbuf_lock--; busy = false; if (n) { - if (!buf_valid(buf)) + if (!bufref_valid(&bufref)) { EMSG(_("E246: FileChangedShell autocommand deleted buffer")); + } s = get_vim_var_str(VV_FCS_CHOICE); if (STRCMP(s, "reload") == 0 && *reason != 'd') reload = TRUE; @@ -4976,8 +4972,8 @@ buf_check_timestamp ( set_vim_var_string(VV_WARNINGMSG, tbuf, -1); if (can_reload) { if (*mesg2 != NUL) { - strncat(tbuf, "\n", tbuf_len); - strncat(tbuf, mesg2, tbuf_len); + xstrlcat(tbuf, "\n", tbuf_len - 1); + xstrlcat(tbuf, mesg2, tbuf_len - 1); } if (do_dialog(VIM_WARNING, (char_u *) _("Warning"), (char_u *) tbuf, (char_u *) _("&OK\n&Load File"), 1, NULL, true) == 2) { @@ -4985,18 +4981,17 @@ buf_check_timestamp ( } } else if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned) { if (*mesg2 != NUL) { - strncat(tbuf, "; ", tbuf_len); - strncat(tbuf, mesg2, tbuf_len); + xstrlcat(tbuf, "; ", tbuf_len - 1); + xstrlcat(tbuf, mesg2, tbuf_len - 1); } EMSG(tbuf); retval = 2; } else { if (!autocmd_busy) { msg_start(); - msg_puts_attr((char_u *) tbuf, hl_attr(HLF_E) + MSG_HIST); + msg_puts_attr(tbuf, hl_attr(HLF_E) + MSG_HIST); if (*mesg2 != NUL) { - msg_puts_attr((char_u *)mesg2, - hl_attr(HLF_W) + MSG_HIST); + msg_puts_attr(mesg2, hl_attr(HLF_W) + MSG_HIST); } msg_clr_eos(); (void)msg_end(); @@ -5031,11 +5026,11 @@ buf_check_timestamp ( } } - /* Trigger FileChangedShell when the file was changed in any way. */ - if (buf_valid(buf) && retval != 0) - (void)apply_autocmds(EVENT_FILECHANGEDSHELLPOST, - buf->b_fname, buf->b_fname, FALSE, buf); - + // Trigger FileChangedShell when the file was changed in any way. + if (bufref_valid(&bufref) && retval != 0) { + (void)apply_autocmds(EVENT_FILECHANGEDSHELLPOST, buf->b_fname, buf->b_fname, + false, buf); + } return retval; } @@ -5052,6 +5047,7 @@ void buf_reload(buf_T *buf, int orig_mode) linenr_T old_topline; int old_ro = buf->b_p_ro; buf_T *savebuf; + bufref_T bufref; int saved = OK; aco_save_T aco; int flags = READ_NEW; @@ -5087,6 +5083,7 @@ void buf_reload(buf_T *buf, int orig_mode) } else { // Allocate a buffer without putting it in the buffer list. savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY); + set_bufref(&bufref, savebuf); if (savebuf != NULL && buf == curbuf) { /* Open the memline. */ curbuf = savebuf; @@ -5104,19 +5101,21 @@ void buf_reload(buf_T *buf, int orig_mode) } if (saved == OK) { - curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */ - keep_filetype = TRUE; /* don't detect 'filetype' */ - if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0, - (linenr_T)0, - (linenr_T)MAXLNUM, &ea, flags) == FAIL) { - if (!aborting()) + curbuf->b_flags |= BF_CHECK_RO; // check for RO again + keep_filetype = true; // don't detect 'filetype' + if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0, (linenr_T)0, + (linenr_T)MAXLNUM, &ea, flags) != OK) { + if (!aborting()) { EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname); - if (savebuf != NULL && buf_valid(savebuf) && buf == curbuf) { - /* Put the text back from the save buffer. First - * delete any lines that readfile() added. */ - while (!bufempty()) - if (ml_delete(buf->b_ml.ml_line_count, FALSE) == FAIL) + } + if (savebuf != NULL && bufref_valid(&bufref) && buf == curbuf) { + // Put the text back from the save buffer. First + // delete any lines that readfile() added. + while (!bufempty()) { + if (ml_delete(buf->b_ml.ml_line_count, false) == FAIL) { break; + } + } (void)move_lines(savebuf, buf); } } else if (buf == curbuf) { /* "buf" still valid */ @@ -5133,8 +5132,9 @@ void buf_reload(buf_T *buf, int orig_mode) } xfree(ea.cmd); - if (savebuf != NULL && buf_valid(savebuf)) - wipe_buffer(savebuf, FALSE); + if (savebuf != NULL && bufref_valid(&bufref)) { + wipe_buffer(savebuf, false); + } /* Invalidate diff info if necessary. */ diff_invalidate(curbuf); @@ -5197,7 +5197,7 @@ void forward_slash(char_u *fname) { char_u *p; - if (path_with_url(fname)) { + if (path_with_url((const char *)fname)) { return; } for (p = fname; *p != NUL; p++) { @@ -5258,7 +5258,7 @@ static void vim_maketempdir(void) /// Delete "name" and everything in it, recursively. /// @param name The path which should be deleted. /// @return 0 for success, -1 if some file was not deleted. -int delete_recursive(char_u *name) +int delete_recursive(const char *name) { int result = 0; @@ -5272,7 +5272,7 @@ int delete_recursive(char_u *name) EW_DIR | EW_FILE | EW_SILENT | EW_ALLLINKS | EW_DODOT | EW_EMPTYOK) == OK) { for (int i = 0; i < file_count; i++) { - if (delete_recursive(files[i]) != 0) { + if (delete_recursive((const char *)files[i]) != 0) { result = -1; } } @@ -5282,9 +5282,9 @@ int delete_recursive(char_u *name) } xfree(exp); - os_rmdir((char *)name); + os_rmdir(name); } else { - result = os_remove((char *)name) == 0 ? 0 : -1; + result = os_remove(name) == 0 ? 0 : -1; } return result; @@ -5296,7 +5296,7 @@ void vim_deltempdir(void) if (vim_tempdir != NULL) { // remove the trailing path separator path_tail(vim_tempdir)[-1] = NUL; - delete_recursive(vim_tempdir); + delete_recursive((const char *)vim_tempdir); xfree(vim_tempdir); vim_tempdir = NULL; } @@ -5367,11 +5367,9 @@ char_u *vim_tempname(void) static AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */ -/* - * augroups stores a list of autocmd group names. - */ -static garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL}; -#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i]) +/// List of autocmd group names +static garray_T augroups = { 0, 0, sizeof(char_u *), 10, NULL }; +#define AUGROUP_NAME(i) (((char **)augroups.ga_data)[i]) /* * The ID of the current group. Group 0 is the default one. @@ -5386,6 +5384,18 @@ static event_T last_event; static int last_group; static int autocmd_blocked = 0; /* block all autocmds */ +// use get_deleted_augroup() to get this +static const char *deleted_augroup = NULL; + +static inline const char *get_deleted_augroup(void) + FUNC_ATTR_ALWAYS_INLINE +{ + if (deleted_augroup == NULL) { + deleted_augroup = _("--Deleted--"); + } + return deleted_augroup; +} + /* * Show the autocommands for one AutoPat. */ @@ -5405,11 +5415,12 @@ static void show_autocmd(AutoPat *ap, event_T event) return; if (event != last_event || ap->group != last_group) { if (ap->group != AUGROUP_DEFAULT) { - if (AUGROUP_NAME(ap->group) == NULL) - msg_puts_attr((char_u *)_("--Deleted--"), hl_attr(HLF_E)); - else + if (AUGROUP_NAME(ap->group) == NULL) { + msg_puts_attr(get_deleted_augroup(), hl_attr(HLF_E)); + } else { msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T)); - msg_puts((char_u *)" "); + } + msg_puts(" "); } msg_puts_attr(event_nr2name(event), hl_attr(HLF_T)); last_event = event; @@ -5538,7 +5549,7 @@ void aubuflocal_remove(buf_T *buf) if (p_verbose >= 6) { verbose_enter(); smsg(_("auto-removing autocommand: %s <buffer=%d>"), - event_nr2name(event), buf->b_fnum); + event_nr2name(event), buf->b_fnum); verbose_leave(); } } @@ -5561,9 +5572,10 @@ static int au_new_group(char_u *name) ga_grow(&augroups, 1); } - AUGROUP_NAME(i) = vim_strsave(name); - if (i == augroups.ga_len) - ++augroups.ga_len; + AUGROUP_NAME(i) = xstrdup((char *)name); + if (i == augroups.ga_len) { + augroups.ga_len++; + } } return i; @@ -5574,11 +5586,33 @@ static void au_del_group(char_u *name) int i; i = au_find_group(name); - if (i == AUGROUP_ERROR) /* the group doesn't exist */ + if (i == AUGROUP_ERROR) { // the group doesn't exist EMSG2(_("E367: No such group: \"%s\""), name); - else { + } else if (i == current_augroup) { + EMSG(_("E936: Cannot delete the current group")); + } else { + event_T event; + AutoPat *ap; + int in_use = false; + + for (event = (event_T)0; (int)event < (int)NUM_EVENTS; + event = (event_T)((int)event + 1)) { + for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next) { + if (ap->group == i && ap->pat != NULL) { + give_warning((char_u *) + _("W19: Deleting augroup that is still in use"), true); + in_use = true; + event = NUM_EVENTS; + break; + } + } + } xfree(AUGROUP_NAME(i)); - AUGROUP_NAME(i) = NULL; + if (in_use) { + AUGROUP_NAME(i) = (char *)get_deleted_augroup(); + } else { + AUGROUP_NAME(i) = NULL; + } } } @@ -5590,8 +5624,9 @@ static void au_del_group(char_u *name) static int au_find_group(const char_u *name) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { - for (int i = 0; i < augroups.ga_len; ++i) { - if (AUGROUP_NAME(i) != NULL && STRCMP(AUGROUP_NAME(i), name) == 0) { + for (int i = 0; i < augroups.ga_len; i++) { + if (AUGROUP_NAME(i) != NULL && AUGROUP_NAME(i) != get_deleted_augroup() + && STRCMP(AUGROUP_NAME(i), name) == 0) { return i; } } @@ -5628,7 +5663,7 @@ void do_augroup(char_u *arg, int del_group) for (int i = 0; i < augroups.ga_len; ++i) { if (AUGROUP_NAME(i) != NULL) { msg_puts(AUGROUP_NAME(i)); - msg_puts((char_u *)" "); + msg_puts(" "); } } msg_clr_eos(); @@ -5640,11 +5675,18 @@ void do_augroup(char_u *arg, int del_group) void free_all_autocmds(void) { for (current_augroup = -1; current_augroup < augroups.ga_len; - ++current_augroup) - do_autocmd((char_u *)"", TRUE); - ga_clear_strings(&augroups); -} + current_augroup++) { + do_autocmd((char_u *)"", true); + } + for (int i = 0; i < augroups.ga_len; i++) { + char *const s = ((char **)(augroups.ga_data))[i]; + if ((const char *)s != get_deleted_augroup()) { + xfree(s); + } + } + ga_clear(&augroups); +} #endif /* @@ -5652,13 +5694,13 @@ void free_all_autocmds(void) * Return NUM_EVENTS if the event name was not found. * Return a pointer to the next event name in "end". */ -static event_T event_name2nr(char_u *start, char_u **end) +static event_T event_name2nr(const char_u *start, char_u **end) { - char_u *p; + const char_u *p; int i; int len; - // the event name ends with end of line, '|', a blank or a comma */ + // the event name ends with end of line, '|', a blank or a comma for (p = start; *p && !ascii_iswhite(*p) && *p != ',' && *p != '|'; p++) { } for (i = 0; event_names[i].name != NULL; i++) { @@ -5667,25 +5709,32 @@ static event_T event_name2nr(char_u *start, char_u **end) break; } } - if (*p == ',') - ++p; - *end = p; - if (event_names[i].name == NULL) + if (*p == ',') { + p++; + } + *end = (char_u *)p; + if (event_names[i].name == NULL) { return NUM_EVENTS; + } return event_names[i].event; } -/* - * Return the name for event "event". - */ -static char_u *event_nr2name(event_T event) +/// Return the name for event +/// +/// @param[in] event Event to return name for. +/// +/// @return Event name, static string. Returns "Unknown" for unknown events. +static const char *event_nr2name(event_T event) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_CONST { int i; - for (i = 0; event_names[i].name != NULL; ++i) - if (event_names[i].event == event) - return (char_u *)event_names[i].name; - return (char_u *)"Unknown"; + for (i = 0; event_names[i].name != NULL; i++) { + if (event_names[i].event == event) { + return event_names[i].name; + } + } + return "Unknown"; } /* @@ -6237,6 +6286,7 @@ void ex_doautoall(exarg_T *eap) aco_save_T aco; char_u *arg = eap->arg; int call_do_modelines = check_nomodeline(&arg); + bufref_T bufref; /* * This is a bit tricky: For some commands curwin->w_buffer needs to be @@ -6249,8 +6299,9 @@ void ex_doautoall(exarg_T *eap) if (buf->b_ml.ml_mfp == NULL) { continue; } - /* find a window for this buffer and save some values */ + // Find a window for this buffer and save some values. aucmd_prepbuf(&aco, buf); + set_bufref(&bufref, buf); bool did_aucmd; // execute the autocommands for this buffer @@ -6266,9 +6317,10 @@ void ex_doautoall(exarg_T *eap) /* restore the current window */ aucmd_restbuf(&aco); - /* stop if there is some error or buffer was deleted */ - if (retval == FAIL || !buf_valid(buf)) + // Stop if there is some error or buffer was deleted. + if (retval == FAIL || !bufref_valid(&bufref)) { break; + } } check_cursor(); /* just in case lines got deleted */ @@ -6375,7 +6427,7 @@ aucmd_prepbuf ( } curbuf = buf; aco->new_curwin = curwin; - aco->new_curbuf = curbuf; + set_bufref(&aco->new_curbuf, curbuf); } /// Cleanup after executing autocommands for a (hidden) buffer. @@ -6409,6 +6461,12 @@ win_found: win_remove(curwin, NULL); aucmd_win_used = false; last_status(false); // may need to remove last status line + + if (!valid_tabpage_win(curtab)) { + // no valid window in current tabpage + close_tabpage(curtab); + } + restore_snapshot(SNAP_AUCMD_IDX, false); (void)win_comp_pos(); // recompute window positions unblock_autocmds(); @@ -6438,14 +6496,14 @@ win_found: // Restore the buffer which was previously edited by curwin, if it was // changed, we are still the same window and the buffer is valid. if (curwin == aco->new_curwin - && curbuf != aco->new_curbuf - && buf_valid(aco->new_curbuf) - && aco->new_curbuf->b_ml.ml_mfp != NULL) { + && curbuf != aco->new_curbuf.br_buf + && bufref_valid(&aco->new_curbuf) + && aco->new_curbuf.br_buf->b_ml.ml_mfp != NULL) { if (curwin->w_s == &curbuf->b_s) { - curwin->w_s = &aco->new_curbuf->b_s; + curwin->w_s = &aco->new_curbuf.br_buf->b_s; } curbuf->b_nwindows--; - curbuf = aco->new_curbuf; + curbuf = aco->new_curbuf.br_buf; curwin->w_buffer = curbuf; curbuf->b_nwindows++; } @@ -6715,8 +6773,9 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, fname = vim_strsave(fname); /* make a copy, so we can change it */ } else { sfname = vim_strsave(fname); - // don't try expanding the following events + // Don't try expanding the following events. if (event == EVENT_COLORSCHEME + || event == EVENT_DIRCHANGED || event == EVENT_FILETYPE || event == EVENT_FUNCUNDEFINED || event == EVENT_OPTIONSET @@ -6725,10 +6784,11 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, || event == EVENT_REMOTEREPLY || event == EVENT_SPELLFILEMISSING || event == EVENT_SYNTAX - || event == EVENT_TABCLOSED) + || event == EVENT_TABCLOSED) { fname = vim_strsave(fname); - else - fname = (char_u *)FullName_save((char *)fname, FALSE); + } else { + fname = (char_u *)FullName_save((char *)fname, false); + } } if (fname == NULL) { /* out of memory */ xfree(sfname); @@ -6810,8 +6870,8 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, patcmd.next = active_apc_list; active_apc_list = &patcmd; - /* set v:cmdarg (only when there is a matching pattern) */ - save_cmdbang = get_vim_var_nr(VV_CMDBANG); + // set v:cmdarg (only when there is a matching pattern) + save_cmdbang = (long)get_vim_var_nr(VV_CMDBANG); if (eap != NULL) { save_cmdarg = set_cmdarg(eap, NULL); set_vim_var_nr(VV_CMDBANG, (long)eap->forceit); @@ -6945,7 +7005,6 @@ auto_next_pat ( { AutoPat *ap; AutoCmd *cp; - char_u *name; char *s; xfree(sourcing_name); @@ -6964,11 +7023,13 @@ auto_next_pat ( ? match_file_pat(NULL, &ap->reg_prog, apc->fname, apc->sfname, apc->tail, ap->allow_dirs) : ap->buflocal_nr == apc->arg_bufnr) { - name = event_nr2name(apc->event); + const char *const name = event_nr2name(apc->event); s = _("%s Auto commands for \"%s\""); - sourcing_name = xmalloc(STRLEN(s) + STRLEN(name) + ap->patlen + 1); - sprintf((char *)sourcing_name, s, - (char *)name, (char *)ap->pat); + const size_t sourcing_name_len = (STRLEN(s) + strlen(name) + ap->patlen + + 1); + sourcing_name = xmalloc(sourcing_name_len); + snprintf((char *)sourcing_name, sourcing_name_len, s, name, + (char *)ap->pat); if (p_verbose >= 8) { verbose_enter(); smsg(_("Executing %s"), sourcing_name); @@ -7034,7 +7095,7 @@ char_u *getnextac(int c, void *cookie, int indent) if (p_verbose >= 9) { verbose_enter_scroll(); smsg(_("autocommand %s"), ac->cmd); - msg_puts((char_u *)"\n"); /* don't overwrite this either */ + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); } retval = vim_strsave(ac->cmd); @@ -7100,13 +7161,17 @@ bool has_autocmd(event_T event, char_u *sfname, buf_T *buf) */ char_u *get_augroup_name(expand_T *xp, int idx) { - if (idx == augroups.ga_len) /* add "END" add the end */ + if (idx == augroups.ga_len) { // add "END" add the end return (char_u *)"END"; - if (idx >= augroups.ga_len) /* end of list */ + } + if (idx >= augroups.ga_len) { // end of list return NULL; - if (AUGROUP_NAME(idx) == NULL) /* skip deleted entries */ + } + if (AUGROUP_NAME(idx) == NULL || AUGROUP_NAME(idx) == get_deleted_augroup()) { + // skip deleted entries return (char_u *)""; - return AUGROUP_NAME(idx); /* return a name */ + } + return (char_u *)AUGROUP_NAME(idx); } static int include_groups = FALSE; @@ -7163,21 +7228,27 @@ set_context_in_autocmd ( */ char_u *get_event_name(expand_T *xp, int idx) { - if (idx < augroups.ga_len) { /* First list group names, if wanted */ - if (!include_groups || AUGROUP_NAME(idx) == NULL) - return (char_u *)""; /* skip deleted entries */ - return AUGROUP_NAME(idx); /* return a name */ + if (idx < augroups.ga_len) { // First list group names, if wanted + if (!include_groups || AUGROUP_NAME(idx) == NULL + || AUGROUP_NAME(idx) == get_deleted_augroup()) { + return (char_u *)""; // skip deleted entries + } + return (char_u *)AUGROUP_NAME(idx); } return (char_u *)event_names[idx - augroups.ga_len].name; } -/// Return true if autocmd "event" is supported. -bool autocmd_supported(char_u *event) +/// Check whether given autocommand is supported +/// +/// @param[in] event Event to check. +/// +/// @return True if it is, false otherwise. +bool autocmd_supported(const char *const event) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { char_u *p; - - return event_name2nr(event, &p) != NUM_EVENTS; + return event_name2nr((const char_u *)event, &p) != NUM_EVENTS; } /// Return true if an autocommand is defined for a group, event and @@ -7192,26 +7263,24 @@ bool autocmd_supported(char_u *event) /// exists("#Event#pat") /// /// @param arg autocommand string -bool au_exists(const char_u *arg) FUNC_ATTR_WARN_UNUSED_RESULT +bool au_exists(const char *const arg) FUNC_ATTR_WARN_UNUSED_RESULT { - char_u *arg_save; - char_u *pattern = NULL; - char_u *event_name; - char_u *p; event_T event; AutoPat *ap; buf_T *buflocal_buf = NULL; int group; bool retval = false; - /* Make a copy so that we can change the '#' chars to a NUL. */ - arg_save = vim_strsave(arg); - p = vim_strchr(arg_save, '#'); - if (p != NULL) + // Make a copy so that we can change the '#' chars to a NUL. + char *const arg_save = xstrdup(arg); + char *p = strchr(arg_save, '#'); + if (p != NULL) { *p++ = NUL; + } - /* First, look for an autocmd group name */ - group = au_find_group(arg_save); + // First, look for an autocmd group name. + group = au_find_group((char_u *)arg_save); + char *event_name; if (group == AUGROUP_ERROR) { /* Didn't match a group name, assume the first argument is an event. */ group = AUGROUP_ALL; @@ -7223,17 +7292,18 @@ bool au_exists(const char_u *arg) FUNC_ATTR_WARN_UNUSED_RESULT goto theend; } - /* Must be "Group#Event" or "Group#Event#pat". */ + // Must be "Group#Event" or "Group#Event#pat". event_name = p; - p = vim_strchr(event_name, '#'); - if (p != NULL) - *p++ = NUL; /* "Group#Event#pat" */ + p = strchr(event_name, '#'); + if (p != NULL) { + *p++ = NUL; // "Group#Event#pat" + } } - pattern = p; /* "pattern" is NULL when there is no pattern */ + char *pattern = p; // "pattern" is NULL when there is no pattern. - /* find the index (enum) for the event name */ - event = event_name2nr(event_name, &p); + // Find the index (enum) for the event name. + event = event_name2nr((char_u *)event_name, (char_u **)&p); /* return FALSE if the event name is not recognized */ if (event == NUM_EVENTS) @@ -7259,7 +7329,7 @@ bool au_exists(const char_u *arg) FUNC_ATTR_WARN_UNUSED_RESULT && (group == AUGROUP_ALL || ap->group == group) && (pattern == NULL || (buflocal_buf == NULL - ? fnamecmp(ap->pat, pattern) == 0 + ? fnamecmp(ap->pat, (char_u *)pattern) == 0 : ap->buflocal_nr == buflocal_buf->b_fnum))) { retval = true; break; diff --git a/src/nvim/fileio.h b/src/nvim/fileio.h index ceb101167d..8db4b89806 100644 --- a/src/nvim/fileio.h +++ b/src/nvim/fileio.h @@ -4,13 +4,14 @@ #include "nvim/buffer_defs.h" #include "nvim/os/os.h" -/* Values for readfile() flags */ -#define READ_NEW 0x01 /* read a file into a new buffer */ -#define READ_FILTER 0x02 /* read filter output */ -#define READ_STDIN 0x04 /* read from stdin */ -#define READ_BUFFER 0x08 /* read from curbuf (converting stdin) */ -#define READ_DUMMY 0x10 /* reading into a dummy buffer */ -#define READ_KEEP_UNDO 0x20 /* keep undo info*/ +// Values for readfile() flags +#define READ_NEW 0x01 // read a file into a new buffer +#define READ_FILTER 0x02 // read filter output +#define READ_STDIN 0x04 // read from stdin +#define READ_BUFFER 0x08 // read from curbuf (converting stdin) +#define READ_DUMMY 0x10 // reading into a dummy buffer +#define READ_KEEP_UNDO 0x20 // keep undo info +#define READ_FIFO 0x40 // read from fifo or socket #define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) @@ -19,12 +20,12 @@ * not the current buffer. */ typedef struct { - buf_T *save_curbuf; /* saved curbuf */ - int use_aucmd_win; /* using aucmd_win */ - win_T *save_curwin; /* saved curwin */ - win_T *new_curwin; /* new curwin */ - buf_T *new_curbuf; /* new curbuf */ - char_u *globaldir; /* saved value of globaldir */ + buf_T *save_curbuf; ///< saved curbuf + int use_aucmd_win; ///< using aucmd_win + win_T *save_curwin; ///< saved curwin + win_T *new_curwin; ///< new curwin + bufref_T new_curbuf; ///< new curbuf + char_u *globaldir; ///< saved value of globaldir } aco_save_T; #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/fold.c b/src/nvim/fold.c index dcd32acfb7..db88791967 100644 --- a/src/nvim/fold.c +++ b/src/nvim/fold.c @@ -1,3 +1,6 @@ +// 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 + // vim: set fdm=marker fdl=1 fdc=3 /* @@ -29,6 +32,7 @@ #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/undo.h" +#include "nvim/ops.h" /* local declarations. {{{1 */ /* typedef fold_T {{{2 */ @@ -1438,13 +1442,16 @@ static void foldMarkAdjustRecurse(garray_T *gap, linenr_T line1, linenr_T line2, } else { /* 5. fold is below line1 and contains line2; need to * correct nested folds too */ - foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top, - line2 - fp->fd_top, amount, - amount_after + (fp->fd_top - top)); if (amount == MAXLNUM) { + foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top, + line2 - fp->fd_top, amount, + amount_after + (fp->fd_top - top)); fp->fd_len -= line2 - fp->fd_top + 1; fp->fd_top = line1; } else { + foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top, + line2 - fp->fd_top, amount, + amount_after - amount); fp->fd_len += amount_after - amount; fp->fd_top += amount; } @@ -1590,29 +1597,32 @@ static void foldCreateMarkers(linenr_T start, linenr_T end) /* * Add "marker[markerlen]" in 'commentstring' to line "lnum". */ -static void foldAddMarker(linenr_T lnum, char_u *marker, size_t markerlen) +static void foldAddMarker(linenr_T lnum, const char_u *marker, size_t markerlen) { char_u *cms = curbuf->b_p_cms; char_u *line; char_u *newline; char_u *p = (char_u *)strstr((char *)curbuf->b_p_cms, "%s"); + bool line_is_comment = false; - /* Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end */ + // Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end line = ml_get(lnum); size_t line_len = STRLEN(line); if (u_save(lnum - 1, lnum + 1) == OK) { + // Check if the line ends with an unclosed comment + skip_comment(line, false, false, &line_is_comment); newline = xmalloc(line_len + markerlen + STRLEN(cms) + 1); STRCPY(newline, line); - if (p == NULL) + // Append the marker to the end of the line + if (p == NULL || line_is_comment) { STRLCPY(newline + line_len, marker, markerlen + 1); - else { + } else { STRCPY(newline + line_len, cms); - STRNCPY(newline + line_len + (p - cms), marker, markerlen); + memcpy(newline + line_len + (p - cms), marker, markerlen); STRCPY(newline + line_len + (p - cms) + markerlen, p + 2); } - - ml_replace(lnum, newline, FALSE); + ml_replace(lnum, newline, false); } } @@ -1673,7 +1683,8 @@ static void foldDelMarker(linenr_T lnum, char_u *marker, size_t markerlen) if (u_save(lnum - 1, lnum + 1) == OK) { /* Make new line: text-before-marker + text-after-marker */ newline = xmalloc(STRLEN(line) - len + 1); - STRNCPY(newline, line, p - line); + assert(p >= line); + memcpy(newline, line, (size_t)(p - line)); STRCPY(newline + (p - line), p + len); ml_replace(lnum, newline, FALSE); } @@ -1681,12 +1692,10 @@ static void foldDelMarker(linenr_T lnum, char_u *marker, size_t markerlen) } } -/* get_foldtext() {{{2 */ -/* - * Return the text for a closed fold at line "lnum", with last line "lnume". - * When 'foldtext' isn't set puts the result in "buf[51]". Otherwise the - * result is in allocated memory. - */ +// get_foldtext() {{{2 +/// Return the text for a closed fold at line "lnum", with last line "lnume". +/// When 'foldtext' isn't set puts the result in "buf[FOLD_TEXT_LEN]". +/// Otherwise the result is in allocated memory. char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T *foldinfo, char_u *buf) FUNC_ATTR_NONNULL_ARG(1) @@ -1773,8 +1782,12 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, } } if (text == NULL) { - sprintf((char *)buf, _("+--%3ld lines folded "), - (long)(lnume - lnum + 1)); + unsigned long count = (unsigned long)(lnume - lnum + 1); + + vim_snprintf((char *)buf, FOLD_TEXT_LEN, + ngettext("+--%3ld line folded", + "+--%3ld lines folded ", count), + count); text = buf; } return text; @@ -2224,32 +2237,51 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level, * before where we started looking, extend it. If it * starts at another line, update nested folds to keep * their position, compensating for the new fd_top. */ - if (fp->fd_top >= startlnum && fp->fd_top != firstlnum) { - if (fp->fd_top > firstlnum) - /* like lines are inserted */ + if (fp->fd_top == firstlnum) { + // We have found a fold beginning exactly where we want one. + } else if (fp->fd_top >= startlnum) { + if (fp->fd_top > firstlnum) { + // We will move the start of this fold up, hence we move all + // nested folds (with relative line numbers) down. foldMarkAdjustRecurse(&fp->fd_nested, - (linenr_T)0, (linenr_T)MAXLNUM, - (long)(fp->fd_top - firstlnum), 0L); - else - /* like lines are deleted */ + (linenr_T)0, (linenr_T)MAXLNUM, + (long)(fp->fd_top - firstlnum), 0L); + } else { + // Will move fold down, move nested folds relatively up. foldMarkAdjustRecurse(&fp->fd_nested, - (linenr_T)0, - (long)(firstlnum - fp->fd_top - 1), - (linenr_T)MAXLNUM, - (long)(fp->fd_top - firstlnum)); + (linenr_T)0, + (long)(firstlnum - fp->fd_top - 1), + (linenr_T)MAXLNUM, + (long)(fp->fd_top - firstlnum)); + } fp->fd_len += fp->fd_top - firstlnum; fp->fd_top = firstlnum; - fold_changed = TRUE; - } else if (flp->start != 0 && lvl == level - && fp->fd_top != firstlnum) { - /* Existing fold that includes startlnum must stop - * if we find the start of a new fold at the same - * level. Split it. Delete contained folds at - * this point to split them too. */ - foldRemove(&fp->fd_nested, flp->lnum - fp->fd_top, - flp->lnum - fp->fd_top); + fold_changed = true; + } else if ((flp->start != 0 && lvl == level) + || (firstlnum != startlnum)) { + // Before there was a fold spanning from above startlnum to below + // firstlnum. This fold is valid above startlnum (because we are + // not updating that range), but there is now a break in it. + // If the break is because we are now forced to start a new fold + // at the level "level" at line fline->lnum, then we need to + // split the fold at fline->lnum. + // If the break is because the range [startlnum, firstlnum) is + // now at a lower indent than "level", we need to split the fold + // in this range. + // Any splits have to be done recursively. + linenr_T breakstart; + linenr_T breakend; + if (firstlnum != startlnum) { + breakstart = startlnum; + breakend = firstlnum; + } else { + breakstart = flp->lnum; + breakend = flp->lnum; + } + foldRemove(&fp->fd_nested, breakstart - fp->fd_top, + breakend - fp->fd_top); i = (int)(fp - (fold_T *)gap->ga_data); - foldSplit(gap, i, flp->lnum, flp->lnum - 1); + foldSplit(gap, i, breakstart, breakend - 1); fp = (fold_T *)gap->ga_data + i + 1; /* If using the "marker" or "syntax" method, we * need to continue until the end of the fold is @@ -2259,6 +2291,16 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level, || getlevel == foldlevelSyntax) finish = TRUE; } + if (fp->fd_top == startlnum && concat) { + i = (int)(fp - (fold_T *)gap->ga_data); + if (i != 0) { + fp2 = fp - 1; + if (fp2->fd_top + fp2->fd_len == fp->fd_top) { + foldMerge(fp2, gap, fp); + fp = fp2; + } + } + } break; } if (fp->fd_top >= startlnum) { @@ -2499,6 +2541,8 @@ static void foldSplit(garray_T *gap, int i, linenr_T top, linenr_T bot) fp = (fold_T *)gap->ga_data + i; fp[1].fd_top = bot + 1; + // check for wrap around (MAXLNUM, and 32bit) + assert(fp[1].fd_top > bot); fp[1].fd_len = fp->fd_len - (fp[1].fd_top - fp->fd_top); fp[1].fd_flags = fp->fd_flags; fp[1].fd_small = MAYBE; @@ -2531,10 +2575,10 @@ static void foldSplit(garray_T *gap, int i, linenr_T top, linenr_T bot) * 1 2 3 * 1 2 3 * top 2 3 4 5 - * 2 3 4 5 - * bot 2 3 4 5 - * 3 5 6 - * 3 5 6 + * 2 3 4 5 + * bot 2 3 4 5 + * 3 5 6 + * 3 5 6 * * 1: not changed * 2: truncate to stop above "top" @@ -2547,34 +2591,35 @@ static void foldRemove(garray_T *gap, linenr_T top, linenr_T bot) { fold_T *fp = NULL; - if (bot < top) - return; /* nothing to do */ + if (bot < top) { + return; // nothing to do + } for (;; ) { - /* Find fold that includes top or a following one. */ + // Find fold that includes top or a following one. if (foldFind(gap, top, &fp) && fp->fd_top < top) { - /* 2: or 3: need to delete nested folds */ + // 2: or 3: need to delete nested folds foldRemove(&fp->fd_nested, top - fp->fd_top, bot - fp->fd_top); - if (fp->fd_top + fp->fd_len > bot + 1) { - /* 3: need to split it. */ + if (fp->fd_top + fp->fd_len - 1 > bot) { + // 3: need to split it. foldSplit(gap, (int)(fp - (fold_T *)gap->ga_data), top, bot); } else { - /* 2: truncate fold at "top". */ + // 2: truncate fold at "top". fp->fd_len = top - fp->fd_top; } - fold_changed = TRUE; + fold_changed = true; continue; } if (fp >= (fold_T *)(gap->ga_data) + gap->ga_len || fp->fd_top > bot) { - /* 6: Found a fold below bot, can stop looking. */ + // 6: Found a fold below bot, can stop looking. break; } if (fp->fd_top >= top) { - /* Found an entry below top. */ - fold_changed = TRUE; + // Found an entry below top. + fold_changed = true; if (fp->fd_top + fp->fd_len - 1 > bot) { - /* 5: Make fold that includes bot start below bot. */ + // 5: Make fold that includes bot start below bot. foldMarkAdjustRecurse(&fp->fd_nested, (linenr_T)0, (long)(bot - fp->fd_top), (linenr_T)MAXLNUM, (long)(fp->fd_top - bot - 1)); @@ -2583,11 +2628,162 @@ static void foldRemove(garray_T *gap, linenr_T top, linenr_T bot) break; } - /* 4: Delete completely contained fold. */ - deleteFoldEntry(gap, (int)(fp - (fold_T *)gap->ga_data), TRUE); + // 4: Delete completely contained fold. + deleteFoldEntry(gap, (int)(fp - (fold_T *)gap->ga_data), true); + } + } +} + +// foldMoveRange() {{{2 +static void reverse_fold_order(garray_T *gap, size_t start, size_t end) +{ + for (; start < end; start++, end--) { + fold_T *left = (fold_T *)gap->ga_data + start; + fold_T *right = (fold_T *)gap->ga_data + end; + fold_T tmp = *left; + *left = *right; + *right = tmp; + } +} + +// Move folds within the inclusive range "line1" to "line2" to after "dest" +// require "line1" <= "line2" <= "dest" +// +// There are the following situations for the first fold at or below line1 - 1. +// 1 2 3 4 +// 1 2 3 4 +// line1 2 3 4 +// 2 3 4 5 6 7 +// line2 3 4 5 6 7 +// 3 4 6 7 8 9 +// dest 4 7 8 9 +// 4 7 8 10 +// 4 7 8 10 +// +// In the following descriptions, "moved" means moving in the buffer, *and* in +// the fold array. +// Meanwhile, "shifted" just means moving in the buffer. +// 1. not changed +// 2. truncated above line1 +// 3. length reduced by line2 - line1, folds starting between the end of 3 and +// dest are truncated and shifted up +// 4. internal folds moved (from [line1, line2] to dest) +// 5. moved to dest. +// 6. truncated below line2 and moved. +// 7. length reduced by line2 - dest, folds starting between line2 and dest are +// removed, top is moved down by move_len. +// 8. truncated below dest and shifted up. +// 9. shifted up +// 10. not changed +static void truncate_fold(fold_T *fp, linenr_T end) +{ + // I want to stop *at here*, foldRemove() stops *above* top + end += 1; + foldRemove(&fp->fd_nested, end - fp->fd_top, MAXLNUM); + fp->fd_len = end - fp->fd_top; +} + +#define FOLD_END(fp) ((fp)->fd_top + (fp)->fd_len - 1) +#define VALID_FOLD(fp, gap) ((fp) < ((fold_T *)(gap)->ga_data + (gap)->ga_len)) +#define FOLD_INDEX(fp, gap) ((size_t)(fp - ((fold_T *)(gap)->ga_data))) +void foldMoveRange(garray_T *gap, const linenr_T line1, const linenr_T line2, + const linenr_T dest) +{ + fold_T *fp; + const linenr_T range_len = line2 - line1 + 1; + const linenr_T move_len = dest - line2; + const bool at_start = foldFind(gap, line1 - 1, &fp); + + if (at_start) { + if (FOLD_END(fp) > dest) { + // Case 4 -- don't have to change this fold, but have to move nested + // folds. + foldMoveRange(&fp->fd_nested, line1 - fp->fd_top, line2 - + fp->fd_top, dest - fp->fd_top); + return; + } else if (FOLD_END(fp) > line2) { + // Case 3 -- Remove nested folds between line1 and line2 & reduce the + // length of fold by "range_len". + // Folds after this one must be dealt with. + foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top, + line2 - fp->fd_top, MAXLNUM, -range_len); + fp->fd_len -= range_len; + } else { + // Case 2 -- truncate fold *above* line1. + // Folds after this one must be dealt with. + truncate_fold(fp, line1 - 1); + } + // Look at the next fold, and treat that one as if it were the first after + // "line1" (because now it is). + fp = fp + 1; + } + + if (!VALID_FOLD(fp, gap) || fp->fd_top > dest) { + // No folds after "line1" and before "dest" + // Case 10. + return; + } else if (fp->fd_top > line2) { + for (; VALID_FOLD(fp, gap) && FOLD_END(fp) <= dest; fp++) { + // Case 9. (for all case 9's) -- shift up. + fp->fd_top -= range_len; + } + if (VALID_FOLD(fp, gap) && fp->fd_top <= dest) { + // Case 8. -- ensure truncated at dest, shift up + truncate_fold(fp, dest); + fp->fd_top -= range_len; + } + return; + } else if (FOLD_END(fp) > dest) { + // Case 7 -- remove nested folds and shrink + foldMarkAdjustRecurse(&fp->fd_nested, line2 + 1 - fp->fd_top, + dest - fp->fd_top, MAXLNUM, -move_len); + fp->fd_len -= move_len; + fp->fd_top += move_len; + return; + } + + // Case 5 or 6: changes rely on whether there are folds between the end of + // this fold and "dest". + size_t move_start = FOLD_INDEX(fp, gap); + size_t move_end = 0, dest_index = 0; + for (; VALID_FOLD(fp, gap) && fp->fd_top <= dest; fp++) { + if (fp->fd_top <= line2) { + // 5, or 6 + if (FOLD_END(fp) > line2) { + // 6, truncate before moving + truncate_fold(fp, line2); + } + fp->fd_top += move_len; + continue; + } + + // Record index of the first fold after the moved range. + if (move_end == 0) { + move_end = FOLD_INDEX(fp, gap); + } + + if (FOLD_END(fp) > dest) { + truncate_fold(fp, dest); } + + fp->fd_top -= range_len; + } + dest_index = FOLD_INDEX(fp, gap); + + // All folds are now correct, but not necessarily in the correct order. + // We must swap folds in the range [move_end, dest_index) with those in the + // range [move_start, move_end). + if (move_end == 0) { + // There are no folds after those moved, so none were moved out of order. + return; } + reverse_fold_order(gap, move_start, dest_index - 1); + reverse_fold_order(gap, move_start, move_start + dest_index - move_end - 1); + reverse_fold_order(gap, move_start + dest_index - move_end, dest_index - 1); } +#undef FOLD_END +#undef VALID_FOLD +#undef FOLD_INDEX /* foldMerge() {{{2 */ /* @@ -2698,7 +2894,7 @@ static void foldlevelExpr(fline_T *flp) /* KeyTyped may be reset to 0 when calling a function which invokes * do_cmdline(). To make 'foldopen' work correctly restore KeyTyped. */ save_keytyped = KeyTyped; - n = eval_foldexpr(flp->wp->w_p_fde, &c); + n = (int)eval_foldexpr(flp->wp->w_p_fde, &c); KeyTyped = save_keytyped; switch (c) { diff --git a/src/nvim/fold.h b/src/nvim/fold.h index 2ff10c0e91..f35b328fb1 100644 --- a/src/nvim/fold.h +++ b/src/nvim/fold.h @@ -1,7 +1,12 @@ #ifndef NVIM_FOLD_H #define NVIM_FOLD_H +#include <stdio.h> + #include "nvim/pos.h" +#include "nvim/garray.h" +#include "nvim/types.h" +#include "nvim/buffer_defs.h" /* * Info used to pass info about a fold from the fold-detection code to the diff --git a/src/nvim/func_attr.h b/src/nvim/func_attr.h index d98fe5b22b..bd26205d6d 100644 --- a/src/nvim/func_attr.h +++ b/src/nvim/func_attr.h @@ -41,9 +41,7 @@ // $ gcc -E -dM - </dev/null // $ echo | clang -dM -E - -#ifndef NVIM_FUNC_ATTR_H -#define NVIM_FUNC_ATTR_H -#undef NVIM_FUNC_ATTR_H +#include "nvim/macros.h" #ifdef FUNC_ATTR_MALLOC # undef FUNC_ATTR_MALLOC @@ -93,11 +91,18 @@ # undef FUNC_ATTR_NONNULL_RET #endif +#ifdef FUNC_ATTR_NORETURN +# undef FUNC_ATTR_NORETURN +#endif + +#ifdef FUNC_ATTR_NO_SANITIZE_UNDEFINED +# undef FUNC_ATTR_NO_SANITIZE_UNDEFINED +#endif + #ifndef DID_REAL_ATTR # define DID_REAL_ATTR # ifdef __GNUC__ -// place defines for all gnulikes here, for now that's gcc, clang and -// intel. +// For all gnulikes: gcc, clang, intel. // place these after the argument list of the function declaration // (not definition), like so: @@ -111,27 +116,27 @@ # define REAL_FATTR_UNUSED __attribute__((unused)) # define REAL_FATTR_NONNULL_ALL __attribute__((nonnull)) # define REAL_FATTR_NONNULL_ARG(...) __attribute__((nonnull(__VA_ARGS__))) +# define REAL_FATTR_NORETURN __attribute__((noreturn)) + +# if NVIM_HAS_ATTRIBUTE(returns_nonnull) +# define REAL_FATTR_NONNULL_RET __attribute__((returns_nonnull)) +# endif -# ifdef __clang__ -// clang only -# elif defined(__INTEL_COMPILER) -// intel only -# else -# define GCC_VERSION \ - (__GNUC__ * 10000 + \ - __GNUC_MINOR__ * 100 + \ - __GNUC_PATCHLEVEL__) -// gcc only +# if NVIM_HAS_ATTRIBUTE(alloc_size) # define REAL_FATTR_ALLOC_SIZE(x) __attribute__((alloc_size(x))) # define REAL_FATTR_ALLOC_SIZE_PROD(x, y) __attribute__((alloc_size(x, y))) -# if GCC_VERSION >= 40900 -# define REAL_FATTR_NONNULL_RET __attribute__((returns_nonnull)) -# endif +# endif + +# if NVIM_HAS_ATTRIBUTE(no_sanitize_undefined) +# define REAL_FATTR_NO_SANITIZE_UNDEFINED \ + __attribute__((no_sanitize_undefined)) +# elif NVIM_HAS_ATTRIBUTE(no_sanitize) +# define REAL_FATTR_NO_SANITIZE_UNDEFINED \ + __attribute__((no_sanitize("undefined"))) # endif # endif -// define function attributes that haven't been defined for this specific -// compiler. +// Define attributes that are not defined for this compiler. # ifndef REAL_FATTR_MALLOC # define REAL_FATTR_MALLOC @@ -180,12 +185,22 @@ # ifndef REAL_FATTR_NONNULL_RET # define REAL_FATTR_NONNULL_RET # endif + +# ifndef REAL_FATTR_NORETURN +# define REAL_FATTR_NORETURN +# endif + +# ifndef REAL_FATTR_NO_SANITIZE_UNDEFINED +# define REAL_FATTR_NO_SANITIZE_UNDEFINED +# endif #endif #ifdef DEFINE_FUNC_ATTRIBUTES # define FUNC_API_ASYNC # define FUNC_API_NOEXPORT -# define FUNC_API_NOEVAL +# define FUNC_API_REMOTE_ONLY +# define FUNC_API_SINCE(X) +# define FUNC_API_DEPRECATED_SINCE(X) # define FUNC_ATTR_MALLOC REAL_FATTR_MALLOC # define FUNC_ATTR_ALLOC_SIZE(x) REAL_FATTR_ALLOC_SIZE(x) # define FUNC_ATTR_ALLOC_SIZE_PROD(x, y) REAL_FATTR_ALLOC_SIZE_PROD(x, y) @@ -198,6 +213,8 @@ # define FUNC_ATTR_NONNULL_ALL REAL_FATTR_NONNULL_ALL # define FUNC_ATTR_NONNULL_ARG(...) REAL_FATTR_NONNULL_ARG(__VA_ARGS__) # define FUNC_ATTR_NONNULL_RET REAL_FATTR_NONNULL_RET +# define FUNC_ATTR_NORETURN REAL_FATTR_NORETURN +# define FUNC_ATTR_NO_SANITIZE_UNDEFINED REAL_FATTR_NO_SANITIZE_UNDEFINED #elif !defined(DO_NOT_DEFINE_EMPTY_ATTRIBUTES) # define FUNC_ATTR_MALLOC # define FUNC_ATTR_ALLOC_SIZE(x) @@ -211,5 +228,6 @@ # define FUNC_ATTR_NONNULL_ALL # define FUNC_ATTR_NONNULL_ARG(...) # define FUNC_ATTR_NONNULL_RET +# define FUNC_ATTR_NORETURN +# define FUNC_ATTR_NO_SANITIZE_UNDEFINED #endif -#endif // NVIM_FUNC_ATTR_H diff --git a/src/nvim/garray.c b/src/nvim/garray.c index 9ed3b901ef..2d2af54c95 100644 --- a/src/nvim/garray.c +++ b/src/nvim/garray.c @@ -1,3 +1,6 @@ +// 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 + /// @file garray.c /// /// Functions for handling growing arrays. diff --git a/src/nvim/garray.h b/src/nvim/garray.h index 5d7806bbfa..94e1b61671 100644 --- a/src/nvim/garray.h +++ b/src/nvim/garray.h @@ -37,7 +37,7 @@ typedef struct growarray { static inline void *ga_append_via_ptr(garray_T *gap, size_t item_size) { if ((int)item_size != gap->ga_itemsize) { - ELOG("wrong item size in garray(%d), should be %d", item_size); + WLOG("wrong item size (%d), should be %d", item_size, gap->ga_itemsize); } ga_grow(gap, 1); return ((char *)gap->ga_data) + (item_size * (size_t)gap->ga_len++); diff --git a/src/nvim/generators/c_grammar.lua b/src/nvim/generators/c_grammar.lua new file mode 100644 index 0000000000..d3047e1a9c --- /dev/null +++ b/src/nvim/generators/c_grammar.lua @@ -0,0 +1,50 @@ +lpeg = require('lpeg') + +-- lpeg grammar for building api metadata from a set of header files. It +-- ignores comments and preprocessor commands and parses a very small subset +-- of C prototypes with a limited set of types +local P, R, S = lpeg.P, lpeg.R, lpeg.S +local C, Ct, Cc, Cg = lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg + +local any = P(1) -- (consume one character) +local letter = R('az', 'AZ') + S('_$') +local num = R('09') +local alpha = letter + num +local nl = P('\r\n') + P('\n') +local not_nl = any - nl +local ws = S(' \t') + nl +local fill = ws ^ 0 +local c_comment = P('//') * (not_nl ^ 0) +local c_preproc = P('#') * (not_nl ^ 0) +local typed_container = + (P('ArrayOf(') + P('DictionaryOf(')) * ((any - P(')')) ^ 1) * P(')') +local c_id = ( + typed_container + + (letter * (alpha ^ 0)) +) +local c_void = P('void') +local c_param_type = ( + ((P('Error') * fill * P('*') * fill) * Cc('error')) + + (C(c_id) * (ws ^ 1)) + ) +local c_type = (C(c_void) * (ws ^ 1)) + c_param_type +local c_param = Ct(c_param_type * C(c_id)) +local c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0) +local c_params = Ct(c_void + c_param_list) +local c_proto = Ct( + Cg(c_type, 'return_type') * Cg(c_id, 'name') * + fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * + Cg(Cc(false), 'async') * + (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1) * + (fill * Cg((P('FUNC_API_DEPRECATED_SINCE(') * C(num ^ 1)) * P(')'), + 'deprecated_since') ^ -1) * + (fill * Cg((P('FUNC_API_ASYNC') * Cc(true)), 'async') ^ -1) * + (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) * + (fill * Cg((P('FUNC_API_REMOTE_ONLY') * Cc(true)), 'remote_only') ^ -1) * + (fill * Cg((P('FUNC_API_REMOTE_IMPL') * Cc(true)), 'remote_impl') ^ -1) * + (fill * Cg((P('FUNC_API_BRIDGE_IMPL') * Cc(true)), 'bridge_impl') ^ -1) * + fill * P(';') + ) + +local grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) +return {grammar=grammar, typed_container=typed_container} diff --git a/src/nvim/generators/dump_bin_array.lua b/src/nvim/generators/dump_bin_array.lua new file mode 100644 index 0000000000..bee5aba73f --- /dev/null +++ b/src/nvim/generators/dump_bin_array.lua @@ -0,0 +1,17 @@ +local function dump_bin_array(output, name, data) + output:write([[ + static const uint8_t ]]..name..[[[] = { +]]) + + for i = 1, #data do + output:write(string.byte(data, i)..', ') + if i % 10 == 0 then + output:write('\n ') + end + end + output:write([[ +}; +]]) +end + +return dump_bin_array diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua new file mode 100644 index 0000000000..b01321e713 --- /dev/null +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -0,0 +1,458 @@ +mpack = require('mpack') + +-- we need at least 4 arguments since the last two are output files +if arg[1] == '--help' then + print('Usage: genmsgpack.lua args') + print('Args: 1: source directory') + print(' 2: dispatch output file (dispatch_wrappers.generated.h)') + print(' 3: functions metadata output file (funcs_metadata.generated.h)') + print(' 4: API metadata output file (api_metadata.mpack)') + print(' 5: lua C bindings output file (msgpack_lua_c_bindings.generated.c)') + print(' rest: C files where API functions are defined') +end +assert(#arg >= 4) +functions = {} + +local nvimdir = arg[1] +package.path = nvimdir .. '/?.lua;' .. package.path + +-- names of all headers relative to the source root (for inclusion in the +-- generated file) +headers = {} + +-- output h file with generated dispatch functions +dispatch_outputf = arg[2] +-- output h file with packed metadata +funcs_metadata_outputf = arg[3] +-- output metadata mpack file, for use by other build scripts +mpack_outputf = arg[4] +lua_c_bindings_outputf = arg[5] + +-- set of function names, used to detect duplicates +function_names = {} + +c_grammar = require('generators.c_grammar') + +-- read each input file, parse and append to the api metadata +for i = 6, #arg do + local full_path = arg[i] + local parts = {} + for part in string.gmatch(full_path, '[^/]+') do + parts[#parts + 1] = part + end + headers[#headers + 1] = parts[#parts - 1]..'/'..parts[#parts] + + local input = io.open(full_path, 'rb') + + local tmp = c_grammar.grammar:match(input:read('*all')) + for i = 1, #tmp do + local fn = tmp[i] + if not fn.noexport then + functions[#functions + 1] = tmp[i] + function_names[fn.name] = true + if #fn.parameters ~= 0 and fn.parameters[1][2] == 'channel_id' then + -- this function should receive the channel id + fn.receives_channel_id = true + -- remove the parameter since it won't be passed by the api client + table.remove(fn.parameters, 1) + end + if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'error' then + -- function can fail if the last parameter type is 'Error' + fn.can_fail = true + -- remove the error parameter, msgpack has it's own special field + -- for specifying errors + fn.parameters[#fn.parameters] = nil + end + end + end + input:close() +end + +local function shallowcopy(orig) + local copy = {} + for orig_key, orig_value in pairs(orig) do + copy[orig_key] = orig_value + end + return copy +end + +local function startswith(String,Start) + return string.sub(String,1,string.len(Start))==Start +end + +-- Export functions under older deprecated names. +-- These will be removed eventually. +local deprecated_aliases = require("api.dispatch_deprecated") +for i,f in ipairs(shallowcopy(functions)) do + local ismethod = false + if startswith(f.name, "nvim_") then + if startswith(f.name, "nvim__") then + f.since = -1 + elseif f.since == nil then + print("Function "..f.name.." lacks since field.\n") + os.exit(1) + end + f.since = tonumber(f.since) + if f.deprecated_since ~= nil then + f.deprecated_since = tonumber(f.deprecated_since) + end + + if startswith(f.name, "nvim_buf_") then + ismethod = true + elseif startswith(f.name, "nvim_win_") then + ismethod = true + elseif startswith(f.name, "nvim_tabpage_") then + ismethod = true + end + else + f.remote_only = true + f.since = 0 + f.deprecated_since = 1 + end + f.method = ismethod + local newname = deprecated_aliases[f.name] + if newname ~= nil then + if function_names[newname] then + -- duplicate + print("Function "..f.name.." has deprecated alias\n" + ..newname.." which has a separate implementation.\n".. + "Please remove it from src/nvim/api/dispatch_deprecated.lua") + os.exit(1) + end + local newf = shallowcopy(f) + newf.name = newname + if newname == "ui_try_resize" then + -- The return type was incorrectly set to Object in 0.1.5. + -- Keep it that way for clients that rely on this. + newf.return_type = "Object" + end + newf.impl_name = f.name + newf.remote_only = true + newf.since = 0 + newf.deprecated_since = 1 + functions[#functions+1] = newf + end +end + +-- don't expose internal attributes like "impl_name" in public metadata +exported_attributes = {'name', 'parameters', 'return_type', 'method', + 'since', 'deprecated_since'} +exported_functions = {} +for _,f in ipairs(functions) do + if not startswith(f.name, "nvim__") then + local f_exported = {} + for _,attr in ipairs(exported_attributes) do + f_exported[attr] = f[attr] + end + exported_functions[#exported_functions+1] = f_exported + end +end + + +-- serialize the API metadata using msgpack and embed into the resulting +-- binary for easy querying by clients +funcs_metadata_output = io.open(funcs_metadata_outputf, 'wb') +packed = mpack.pack(exported_functions) +dump_bin_array = require("generators.dump_bin_array") +dump_bin_array(funcs_metadata_output, 'funcs_metadata', packed) +funcs_metadata_output:close() + +-- start building the dispatch wrapper output +output = io.open(dispatch_outputf, 'wb') + +local function real_type(type) + local rv = type + if c_grammar.typed_container:match(rv) then + if rv:match('Array') then + rv = 'Array' + else + rv = 'Dictionary' + end + end + return rv +end + +local function attr_name(rt) + if rt == 'Float' then + return 'floating' + else + return rt:lower() + end +end + +-- start the handler functions. Visit each function metadata to build the +-- handler function with code generated for validating arguments and calling to +-- the real API. +for i = 1, #functions do + local fn = functions[i] + if fn.impl_name == nil then + local args = {} + + output:write('Object handle_'..fn.name..'(uint64_t channel_id, Array args, Error *error)') + output:write('\n{') + output:write('\n Object ret = NIL;') + -- Declare/initialize variables that will hold converted arguments + for j = 1, #fn.parameters do + local param = fn.parameters[j] + local converted = 'arg_'..j + output:write('\n '..param[1]..' '..converted..';') + end + output:write('\n') + output:write('\n if (args.size != '..#fn.parameters..') {') + output:write('\n api_set_error(error, kErrorTypeException, "Wrong number of arguments: expecting '..#fn.parameters..' but got %zu", args.size);') + output:write('\n goto cleanup;') + output:write('\n }\n') + + -- Validation/conversion for each argument + for j = 1, #fn.parameters do + local converted, convert_arg, param, arg + param = fn.parameters[j] + converted = 'arg_'..j + local rt = real_type(param[1]) + if rt ~= 'Object' then + if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') then + -- Buffer, Window, and Tabpage have a specific type, but are stored in integer + output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..' && args.items['..(j - 1)..'].data.integer >= 0) {') + output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') + else + output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..') {') + output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..attr_name(rt)..';') + end + if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') or rt:match('^Boolean$') then + -- accept nonnegative integers for Booleans, Buffers, Windows and Tabpages + output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeInteger && args.items['..(j - 1)..'].data.integer >= 0) {') + output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') + end + output:write('\n } else {') + output:write('\n api_set_error(error, kErrorTypeException, "Wrong type for argument '..j..', expecting '..param[1]..'");') + output:write('\n goto cleanup;') + output:write('\n }\n') + else + output:write('\n '..converted..' = args.items['..(j - 1)..'];\n') + end + + args[#args + 1] = converted + end + + -- function call + local call_args = table.concat(args, ', ') + output:write('\n ') + if fn.return_type ~= 'void' then + -- has a return value, prefix the call with a declaration + output:write(fn.return_type..' rv = ') + end + + -- write the function name and the opening parenthesis + output:write(fn.name..'(') + + if fn.receives_channel_id then + -- if the function receives the channel id, pass it as first argument + if #args > 0 or fn.can_fail then + output:write('channel_id, '..call_args) + else + output:write('channel_id') + end + else + output:write(call_args) + end + + if fn.can_fail then + -- if the function can fail, also pass a pointer to the local error object + if #args > 0 then + output:write(', error);\n') + else + output:write('error);\n') + end + -- and check for the error + output:write('\n if (ERROR_SET(error)) {') + output:write('\n goto cleanup;') + output:write('\n }\n') + else + output:write(');\n') + end + + if fn.return_type ~= 'void' then + output:write('\n ret = '..string.upper(real_type(fn.return_type))..'_OBJ(rv);') + end + output:write('\n\ncleanup:'); + + output:write('\n return ret;\n}\n\n'); + end +end + +-- Generate a function that initializes method names with handler functions +output:write([[ +void msgpack_rpc_init_method_table(void) +{ + methods = map_new(String, MsgpackRpcRequestHandler)(); + +]]) + +for i = 1, #functions do + local fn = functions[i] + output:write(' msgpack_rpc_add_method_handler('.. + '(String) {.data = "'..fn.name..'", '.. + '.size = sizeof("'..fn.name..'") - 1}, '.. + '(MsgpackRpcRequestHandler) {.fn = handle_'.. (fn.impl_name or fn.name).. + ', .async = '..tostring(fn.async)..'});\n') + +end + +output:write('\n}\n\n') +output:close() + +mpack_output = io.open(mpack_outputf, 'wb') +mpack_output:write(mpack.pack(functions)) +mpack_output:close() + +local function include_headers(output, headers) + for i = 1, #headers do + if headers[i]:sub(-12) ~= '.generated.h' then + output:write('\n#include "nvim/'..headers[i]..'"') + end + end +end + +local function write_shifted_output(output, str) + str = str:gsub('\n ', '\n') + str = str:gsub('^ ', '') + str = str:gsub(' +$', '') + output:write(str) +end + +-- start building lua output +output = io.open(lua_c_bindings_outputf, 'wb') + +output:write([[ +#include <lua.h> +#include <lualib.h> +#include <lauxlib.h> + +#include "nvim/func_attr.h" +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" +#include "nvim/lua/converter.h" +]]) +include_headers(output, headers) +output:write('\n') + +lua_c_functions = {} + +local function process_function(fn) + lua_c_function_name = ('nlua_msgpack_%s'):format(fn.name) + write_shifted_output(output, string.format([[ + + static int %s(lua_State *lstate) + { + Error err = ERROR_INIT; + if (lua_gettop(lstate) != %i) { + api_set_error(&err, kErrorTypeValidation, "Expected %i argument%s"); + goto exit_0; + } + ]], lua_c_function_name, #fn.parameters, #fn.parameters, + (#fn.parameters == 1) and '' or 's')) + lua_c_functions[#lua_c_functions + 1] = { + binding=lua_c_function_name, + api=fn.name + } + local cparams = '' + local free_code = {} + for j = #fn.parameters,1,-1 do + param = fn.parameters[j] + cparam = string.format('arg%u', j) + param_type = real_type(param[1]) + lc_param_type = param_type:lower() + write_shifted_output(output, string.format([[ + const %s %s = nlua_pop_%s(lstate, &err); + + if (ERROR_SET(&err)) { + goto exit_%u; + } + ]], param[1], cparam, param_type, #fn.parameters - j)) + free_code[#free_code + 1] = ('api_free_%s(%s);'):format( + lc_param_type, cparam) + cparams = cparam .. ', ' .. cparams + end + if fn.receives_channel_id then + cparams = 'LUA_INTERNAL_CALL, ' .. cparams + end + if fn.can_fail then + cparams = cparams .. '&err' + else + cparams = cparams:gsub(', $', '') + end + local free_at_exit_code = '' + for i = 1, #free_code do + local rev_i = #free_code - i + 1 + local code = free_code[rev_i] + if i == 1 then + free_at_exit_code = free_at_exit_code .. ('\n %s'):format(code) + else + free_at_exit_code = free_at_exit_code .. ('\n exit_%u:\n %s'):format( + rev_i, code) + end + end + local err_throw_code = [[ + + exit_0: + if (ERROR_SET(&err)) { + luaL_where(lstate, 1); + lua_pushstring(lstate, err.msg); + api_clear_error(&err); + lua_concat(lstate, 2); + return lua_error(lstate); + } + ]] + if fn.return_type ~= 'void' then + if fn.return_type:match('^ArrayOf') then + return_type = 'Array' + else + return_type = fn.return_type + end + write_shifted_output(output, string.format([[ + const %s ret = %s(%s); + nlua_push_%s(lstate, ret); + api_free_%s(ret); + %s + %s + return 1; + ]], fn.return_type, fn.name, cparams, return_type, return_type:lower(), + free_at_exit_code, err_throw_code)) + else + write_shifted_output(output, string.format([[ + %s(%s); + %s + %s + return 0; + ]], fn.name, cparams, free_at_exit_code, err_throw_code)) + end + write_shifted_output(output, [[ + } + ]]) +end + +for _, fn in ipairs(functions) do + if not fn.remote_only or fn.name:sub(1, 4) == '_vim' then + process_function(fn) + end +end + +output:write(string.format([[ +void nlua_add_api_functions(lua_State *lstate) + FUNC_ATTR_NONNULL_ALL +{ + lua_createtable(lstate, 0, %u); +]], #lua_c_functions)) +for _, func in ipairs(lua_c_functions) do + output:write(string.format([[ + + lua_pushcfunction(lstate, &%s); + lua_setfield(lstate, -2, "%s");]], func.binding, func.api)) +end +output:write([[ + + lua_setfield(lstate, -2, "api"); +} +]]) + +output:close() diff --git a/src/nvim/generators/gen_api_ui_events.lua b/src/nvim/generators/gen_api_ui_events.lua new file mode 100644 index 0000000000..d2b90db707 --- /dev/null +++ b/src/nvim/generators/gen_api_ui_events.lua @@ -0,0 +1,166 @@ +mpack = require('mpack') + +local nvimdir = arg[1] +package.path = nvimdir .. '/?.lua;' .. package.path + +assert(#arg == 7) +input = io.open(arg[2], 'rb') +proto_output = io.open(arg[3], 'wb') +call_output = io.open(arg[4], 'wb') +remote_output = io.open(arg[5], 'wb') +bridge_output = io.open(arg[6], 'wb') +metadata_output = io.open(arg[7], 'wb') + +c_grammar = require('generators.c_grammar') +local events = c_grammar.grammar:match(input:read('*all')) + +function write_signature(output, ev, prefix, notype) + output:write('('..prefix) + if prefix == "" and #ev.parameters == 0 then + output:write('void') + end + for j = 1, #ev.parameters do + if j > 1 or prefix ~= '' then + output:write(', ') + end + local param = ev.parameters[j] + if not notype then + output:write(param[1]..' ') + end + output:write(param[2]) + end + output:write(')') +end + +function write_arglist(output, ev, need_copy) + output:write(' Array args = ARRAY_DICT_INIT;\n') + for j = 1, #ev.parameters do + local param = ev.parameters[j] + local kind = string.upper(param[1]) + local do_copy = need_copy and (kind == "ARRAY" or kind == "DICTIONARY" or kind == "STRING") + output:write(' ADD(args, ') + if do_copy then + output:write('copy_object(') + end + output:write(kind..'_OBJ('..param[2]..')') + if do_copy then + output:write(')') + end + output:write(');\n') + end +end + +for i = 1, #events do + ev = events[i] + assert(ev.return_type == 'void') + + if ev.since == nil then + print("Ui event "..ev.name.." lacks since field.\n") + os.exit(1) + end + ev.since = tonumber(ev.since) + + if not ev.remote_only then + proto_output:write(' void (*'..ev.name..')') + write_signature(proto_output, ev, 'UI *ui') + proto_output:write(';\n') + + if not ev.remote_impl then + remote_output:write('static void remote_ui_'..ev.name) + write_signature(remote_output, ev, 'UI *ui') + remote_output:write('\n{\n') + write_arglist(remote_output, ev, true) + remote_output:write(' push_call(ui, "'..ev.name..'", args);\n') + remote_output:write('}\n\n') + end + + if not ev.bridge_impl then + + send, argv, recv, recv_argv, recv_cleanup = '', '', '', '', '' + argc = 1 + for j = 1, #ev.parameters do + local param = ev.parameters[j] + copy = 'copy_'..param[2] + if param[1] == 'String' then + send = send..' String copy_'..param[2]..' = copy_string('..param[2]..');\n' + argv = argv..', '..copy..'.data, INT2PTR('..copy..'.size)' + recv = (recv..' String '..param[2].. + ' = (String){.data = argv['..argc..'],'.. + '.size = (size_t)argv['..(argc+1)..']};\n') + recv_argv = recv_argv..', '..param[2] + recv_cleanup = recv_cleanup..' api_free_string('..param[2]..');\n' + argc = argc+2 + elseif param[1] == 'Array' then + send = send..' Array copy_'..param[2]..' = copy_array('..param[2]..');\n' + argv = argv..', '..copy..'.items, INT2PTR('..copy..'.size)' + recv = (recv..' Array '..param[2].. + ' = (Array){.items = argv['..argc..'],'.. + '.size = (size_t)argv['..(argc+1)..']};\n') + recv_argv = recv_argv..', '..param[2] + recv_cleanup = recv_cleanup..' api_free_array('..param[2]..');\n' + argc = argc+2 + elseif param[1] == 'Integer' or param[1] == 'Boolean' then + argv = argv..', INT2PTR('..param[2]..')' + recv_argv = recv_argv..', PTR2INT(argv['..argc..'])' + argc = argc+1 + else + assert(false) + end + end + bridge_output:write('static void ui_bridge_'..ev.name.. + '_event(void **argv)\n{\n') + bridge_output:write(' UI *ui = UI(argv[0]);\n') + bridge_output:write(recv) + bridge_output:write(' ui->'..ev.name..'(ui'..recv_argv..');\n') + bridge_output:write(recv_cleanup) + bridge_output:write('}\n\n') + + bridge_output:write('static void ui_bridge_'..ev.name) + write_signature(bridge_output, ev, 'UI *ui') + bridge_output:write('\n{\n') + bridge_output:write(send) + bridge_output:write(' UI_BRIDGE_CALL(ui, '..ev.name..', '..argc..', ui'..argv..');\n}\n') + end + end + + call_output:write('void ui_call_'..ev.name) + write_signature(call_output, ev, '') + call_output:write('\n{\n') + if ev.remote_only then + write_arglist(call_output, ev, false) + call_output:write(' UI_LOG('..ev.name..', 0);\n') + call_output:write(' ui_event("'..ev.name..'", args);\n') + else + call_output:write(' UI_CALL') + write_signature(call_output, ev, ev.name, true) + call_output:write(";\n") + end + call_output:write("}\n\n") + +end + +proto_output:close() +call_output:close() +remote_output:close() + +-- don't expose internal attributes like "impl_name" in public metadata +exported_attributes = {'name', 'parameters', + 'since', 'deprecated_since'} +exported_events = {} +for _,ev in ipairs(events) do + local ev_exported = {} + for _,attr in ipairs(exported_attributes) do + ev_exported[attr] = ev[attr] + end + for _,p in ipairs(ev_exported.parameters) do + if p[1] == 'HlAttrs' then + p[1] = 'Dictionary' + end + end + exported_events[#exported_events+1] = ev_exported +end + +packed = mpack.pack(exported_events) +dump_bin_array = require("generators.dump_bin_array") +dump_bin_array(metadata_output, 'ui_events_metadata', packed) +metadata_output:close() diff --git a/src/nvim/generators/gen_char_blob.lua b/src/nvim/generators/gen_char_blob.lua new file mode 100644 index 0000000000..d860375e26 --- /dev/null +++ b/src/nvim/generators/gen_char_blob.lua @@ -0,0 +1,48 @@ +if arg[1] == '--help' then + print('Usage:') + print(' gencharblob.lua source target varname') + print('') + print('Generates C file with big uint8_t blob.') + print('Blob will be stored in a static const array named varname.') + os.exit() +end + +assert(#arg == 3) + +local source_file = arg[1] +local target_file = arg[2] +local varname = arg[3] + +source = io.open(source_file, 'r') +target = io.open(target_file, 'w') + +target:write('#include <stdint.h>\n\n') +target:write(('static const uint8_t %s[] = {\n'):format(varname)) + +num_bytes = 0 +MAX_NUM_BYTES = 15 -- 78 / 5: maximum number of bytes on one line +target:write(' ') + +increase_num_bytes = function() + num_bytes = num_bytes + 1 + if num_bytes == MAX_NUM_BYTES then + num_bytes = 0 + target:write('\n ') + end +end + +for line in source:lines() do + for i = 1,string.len(line) do + byte = string.byte(line, i) + assert(byte ~= 0) + target:write(string.format(' %3u,', byte)) + increase_num_bytes() + end + target:write(string.format(' %3u,', string.byte('\n', 1))) + increase_num_bytes() +end + +target:write(' 0};\n') + +source:close() +target:close() diff --git a/src/nvim/generators/gen_declarations.lua b/src/nvim/generators/gen_declarations.lua new file mode 100755 index 0000000000..e999e53e4a --- /dev/null +++ b/src/nvim/generators/gen_declarations.lua @@ -0,0 +1,287 @@ +#!/usr/bin/lua + +local fname = arg[1] +local static_fname = arg[2] +local non_static_fname = arg[3] +local preproc_fname = arg[4] + + +local lpeg = require('lpeg') + +local fold = function (func, ...) + local result = nil + for i, v in ipairs({...}) do + if result == nil then + result = v + else + result = func(result, v) + end + end + return result +end + +local folder = function (func) + return function (...) + return fold(func, ...) + end +end + +local lit = lpeg.P +local set = function(...) + return lpeg.S(fold(function (a, b) return a .. b end, ...)) +end +local any_character = lpeg.P(1) +local rng = function(s, e) return lpeg.R(s .. e) end +local concat = folder(function (a, b) return a * b end) +local branch = folder(function (a, b) return a + b end) +local one_or_more = function(v) return v ^ 1 end +local two_or_more = function(v) return v ^ 2 end +local any_amount = function(v) return v ^ 0 end +local one_or_no = function(v) return v ^ -1 end +local look_behind = lpeg.B +local look_ahead = function(v) return #v end +local neg_look_ahead = function(v) return -v end +local neg_look_behind = function(v) return -look_behind(v) end + +local w = branch( + rng('a', 'z'), + rng('A', 'Z'), + lit('_') +) +local aw = branch( + w, + rng('0', '9') +) +local s = set(' ', '\n', '\t') +local raw_word = concat(w, any_amount(aw)) +local right_word = concat( + raw_word, + neg_look_ahead(aw) +) +local word = branch( + concat( + branch(lit('ArrayOf('), lit('DictionaryOf(')), -- typed container macro + one_or_more(any_character - lit(')')), + lit(')') + ), + concat( + neg_look_behind(aw), + right_word + ) +) +local inline_comment = concat( + lit('/*'), + any_amount(concat( + neg_look_ahead(lit('*/')), + any_character + )), + lit('*/') +) +local spaces = any_amount(branch( + s, + -- Comments are really handled by preprocessor, so the following is not needed + inline_comment, + concat( + lit('//'), + any_amount(concat( + neg_look_ahead(lit('\n')), + any_character + )), + lit('\n') + ), + -- Linemarker inserted by preprocessor + concat( + lit('# '), + any_amount(concat( + neg_look_ahead(lit('\n')), + any_character + )), + lit('\n') + ) +)) +local typ_part = concat( + word, + any_amount(concat( + spaces, + lit('*') + )), + spaces +) +local typ = one_or_more(typ_part) +local typ_id = two_or_more(typ_part) +local arg = typ_id -- argument name is swallowed by typ +local pattern = concat( + any_amount(branch(set(' ', '\t'), inline_comment)), + typ_id, -- return type with function name + spaces, + lit('('), + spaces, + one_or_no(branch( -- function arguments + concat( + arg, -- first argument, does not require comma + any_amount(concat( -- following arguments, start with a comma + spaces, + lit(','), + spaces, + arg, + any_amount(concat( + lit('['), + spaces, + any_amount(aw), + spaces, + lit(']') + )) + )), + one_or_no(concat( + spaces, + lit(','), + spaces, + lit('...') + )) + ), + lit('void') -- also accepts just void + )), + spaces, + lit(')'), + any_amount(concat( -- optional attributes + spaces, + lit('FUNC_'), + any_amount(aw), + one_or_no(concat( -- attribute argument + spaces, + lit('('), + any_amount(concat( + neg_look_ahead(lit(')')), + any_character + )), + lit(')') + )) + )), + look_ahead(concat( -- definition must be followed by "{" + spaces, + lit('{') + )) +) + +if fname == '--help' then + print'Usage:' + print() + print' gendeclarations.lua definitions.c static.h non-static.h preprocessor.i' + os.exit() +end + +local preproc_f = io.open(preproc_fname) +local text = preproc_f:read("*all") +preproc_f:close() + + +local header = [[ +#ifndef DEFINE_FUNC_ATTRIBUTES +# define DEFINE_FUNC_ATTRIBUTES +#endif +#include "nvim/func_attr.h" +#undef DEFINE_FUNC_ATTRIBUTES +]] + +local footer = [[ +#include "nvim/func_attr.h" +]] + +local non_static = header +local static = header + +local filepattern = '^#%a* (%d+) "([^"]-)/?([^"/]+)"' +local curfile + +local init = 0 +local curfile = nil +local neededfile = fname:match('[^/]+$') +local declline = 0 +local declendpos = 0 +local curdir = nil +local is_needed_file = false +while init ~= nil do + init = text:find('[\n;}]', init) + if init == nil then + break + end + local init_is_nl = text:sub(init, init) == '\n' + init = init + 1 + if init_is_nl and is_needed_file then + declline = declline + 1 + end + if init_is_nl and text:sub(init, init) == '#' then + local line, dir, file = text:match(filepattern, init) + if file ~= nil then + curfile = file + is_needed_file = (curfile == neededfile) + declline = tonumber(line) - 1 + local curdir_start = dir:find('src/nvim/') + if curdir_start ~= nil then + curdir = dir:sub(curdir_start + #('src/nvim/')) + else + curdir = dir + end + else + declline = declline - 1 + end + elseif init < declendpos then + -- Skipping over declaration + elseif is_needed_file then + s = init + e = pattern:match(text, init) + if e ~= nil then + local declaration = text:sub(s, e - 1) + -- Comments are really handled by preprocessor, so the following is not + -- needed + declaration = declaration:gsub('/%*.-%*/', '') + declaration = declaration:gsub('//.-\n', '\n') + + declaration = declaration:gsub('# .-\n', '') + + declaration = declaration:gsub('\n', ' ') + declaration = declaration:gsub('%s+', ' ') + declaration = declaration:gsub(' ?%( ?', '(') + -- declaration = declaration:gsub(' ?%) ?', ')') + declaration = declaration:gsub(' ?, ?', ', ') + declaration = declaration:gsub(' ?(%*+) ?', ' %1') + declaration = declaration:gsub(' ?(FUNC_ATTR_)', ' %1') + declaration = declaration:gsub(' $', '') + declaration = declaration:gsub('^ ', '') + declaration = declaration .. ';' + declaration = declaration .. (' // %s/%s:%u'):format( + curdir, curfile, declline) + declaration = declaration .. '\n' + if declaration:sub(1, 6) == 'static' then + static = static .. declaration + else + non_static = non_static .. declaration + end + declendpos = e + end + end +end + +non_static = non_static .. footer +static = static .. footer + +local F +F = io.open(static_fname, 'w') +F:write(static) +F:close() + +-- Before generating the non-static headers, check if the current file(if +-- exists) is different from the new one. If they are the same, we won't touch +-- the current version to avoid triggering an unnecessary rebuilds of modules +-- that depend on this one +F = io.open(non_static_fname, 'r') +if F ~= nil then + if F:read('*a') == non_static then + os.exit(0) + end + io.close(F) +end + +F = io.open(non_static_fname, 'w') +F:write(non_static) +F:close() diff --git a/src/nvim/generators/gen_eval.lua b/src/nvim/generators/gen_eval.lua new file mode 100644 index 0000000000..23435a1d0b --- /dev/null +++ b/src/nvim/generators/gen_eval.lua @@ -0,0 +1,67 @@ +mpack = require('mpack') + +local nvimsrcdir = arg[1] +local autodir = arg[2] +local metadata_file = arg[3] +local funcs_file = arg[4] + +if nvimsrcdir == '--help' then + print([[ +Usage: + lua geneval.lua src/nvim build/src/nvim/auto + +Will generate build/src/nvim/auto/funcs.generated.h with definition of functions +static const array. +]]) + os.exit(0) +end + +package.path = nvimsrcdir .. '/?.lua;' .. package.path + +local funcsfname = autodir .. '/funcs.generated.h' + +local gperfpipe = io.open(funcsfname .. '.gperf', 'wb') + +local funcs = require('eval').funcs +local metadata = mpack.unpack(io.open(arg[3], 'rb'):read("*all")) +for i,fun in ipairs(metadata) do + if not fun.remote_only then + funcs[fun.name] = { + args=#fun.parameters, + func='api_wrapper', + data='&handle_'..fun.name, + } + end +end + +local funcsdata = io.open(funcs_file, 'w') +funcsdata:write(mpack.pack(funcs)) +funcsdata:close() + +gperfpipe:write([[ +%language=ANSI-C +%global-table +%readonly-tables +%define initializer-suffix ,0,0,NULL,NULL +%define word-array-name functions +%define hash-function-name hash_internal_func_gperf +%define lookup-function-name find_internal_func_gperf +%omit-struct-type +%struct-type +VimLFuncDef; +%% +]]) + +for name, def in pairs(funcs) do + args = def.args or 0 + if type(args) == 'number' then + args = {args, args} + elseif #args == 1 then + args[2] = 'MAX_FUNC_ARGS' + end + func = def.func or ('f_' .. name) + data = def.data or "NULL" + gperfpipe:write(('%s, %s, %s, &%s, (FunPtr)%s\n') + :format(name, args[1], args[2], func, data)) +end +gperfpipe:close() diff --git a/src/nvim/generators/gen_events.lua b/src/nvim/generators/gen_events.lua new file mode 100644 index 0000000000..75e0b3da3a --- /dev/null +++ b/src/nvim/generators/gen_events.lua @@ -0,0 +1,65 @@ +if arg[1] == '--help' then + print('Usage: gen_events.lua src/nvim enum_file event_names_file') + os.exit(0) +end + +local nvimsrcdir = arg[1] +local fileio_enum_file = arg[2] +local names_file = arg[3] + +package.path = nvimsrcdir .. '/?.lua;' .. package.path + +local auevents = require('auevents') +local events = auevents.events +local aliases = auevents.aliases + +enum_tgt = io.open(fileio_enum_file, 'w') +names_tgt = io.open(names_file, 'w') + +enum_tgt:write('typedef enum auto_event {') +names_tgt:write([[ +static const struct event_name { + size_t len; + char *name; + event_T event; +} event_names[] = {]]) + +for i, event in ipairs(events) do + if i > 1 then + comma = ',\n' + else + comma = '\n' + end + enum_tgt:write(('%s EVENT_%s = %u'):format(comma, event:upper(), i - 1)) + names_tgt:write(('%s {%u, "%s", EVENT_%s}'):format(comma, #event, event, event:upper())) +end + +for alias, event in pairs(aliases) do + names_tgt:write((',\n {%u, "%s", EVENT_%s}'):format(#alias, alias, event:upper())) +end + +names_tgt:write(',\n {0, NULL, (event_T)0}') + +enum_tgt:write('\n} event_T;\n') +names_tgt:write('\n};\n') + +enum_tgt:write(('\n#define NUM_EVENTS %u\n'):format(#events)) +names_tgt:write('\nstatic AutoPat *first_autopat[NUM_EVENTS] = {\n ') +line_len = 1 +for i = 1,((#events) - 1) do + line_len = line_len + #(' NULL,') + if line_len > 80 then + names_tgt:write('\n ') + line_len = 1 + #(' NULL,') + end + names_tgt:write(' NULL,') +end +if line_len + #(' NULL') > 80 then + names_tgt:write('\n NULL') +else + names_tgt:write(' NULL') +end +names_tgt:write('\n};\n') + +enum_tgt:close() +names_tgt:close() diff --git a/src/nvim/generators/gen_ex_cmds.lua b/src/nvim/generators/gen_ex_cmds.lua new file mode 100644 index 0000000000..cb566d46ca --- /dev/null +++ b/src/nvim/generators/gen_ex_cmds.lua @@ -0,0 +1,88 @@ +local nvimsrcdir = arg[1] +local includedir = arg[2] +local autodir = arg[3] + +if nvimsrcdir == '--help' then + print ([[ +Usage: + lua genex_cmds.lua src/nvim build/include build/src/nvim/auto + +Will generate files build/include/ex_cmds_enum.generated.h with cmdidx_T +enum and build/src/nvim/auto/ex_cmds_defs.generated.h with main Ex commands +definitions. +]]) + os.exit(0) +end + +package.path = nvimsrcdir .. '/?.lua;' .. package.path + +local enumfname = includedir .. '/ex_cmds_enum.generated.h' +local defsfname = autodir .. '/ex_cmds_defs.generated.h' + +local enumfile = io.open(enumfname, 'w') +local defsfile = io.open(defsfname, 'w') + +local defs = require('ex_cmds') +local lastchar = nil + +local i +local cmd +local first = true +local prevfirstchar = nil + +local byte_a = string.byte('a') +local byte_z = string.byte('z') + +local cmdidxs = string.format([[ +static const cmdidx_T cmdidxs[%u] = { +]], byte_z - byte_a + 2) + +enumfile:write([[ +typedef enum CMD_index { +]]) +defsfile:write(string.format([[ +static CommandDefinition cmdnames[%u] = { +]], #defs)) +for i, cmd in ipairs(defs) do + local enumname = cmd.enum or ('CMD_' .. cmd.command) + firstchar = string.byte(cmd.command) + if firstchar ~= prevfirstchar then + if (not prevfirstchar + or (byte_a <= firstchar and firstchar <= byte_z) + or (byte_a <= prevfirstchar and prevfirstchar <= byte_z)) then + if not first then + cmdidxs = cmdidxs .. ',\n' + end + cmdidxs = cmdidxs .. ' ' .. enumname + end + prevfirstchar = firstchar + end + if first then + first = false + else + defsfile:write(',\n') + end + enumfile:write(' ' .. enumname .. ',\n') + defsfile:write(string.format([[ + [%s] = { + .cmd_name = (char_u *) "%s", + .cmd_func = (ex_func_T)&%s, + .cmd_argt = %uL, + .cmd_addr_type = %i + }]], enumname, cmd.command, cmd.func, cmd.flags, cmd.addr_type)) +end +defsfile:write([[ + +}; +]]) +enumfile:write([[ + CMD_SIZE, + CMD_USER = -1, + CMD_USER_BUF = -2 +} cmdidx_T; +]]) +cmdidxs = cmdidxs .. [[ + +}; +]] +defsfile:write(cmdidxs) diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua new file mode 100644 index 0000000000..ca0134043c --- /dev/null +++ b/src/nvim/generators/gen_options.lua @@ -0,0 +1,190 @@ +if arg[1] == '--help' then + print('Usage: genoptions.lua src/nvim options_file') + os.exit(0) +end + +local nvimsrcdir = arg[1] +local options_file = arg[2] + +package.path = nvimsrcdir .. '/?.lua;' .. package.path + +local opt_fd = io.open(options_file, 'w') + +local w = function(s) + if s:match('^ %.') then + opt_fd:write(s .. ',\n') + else + opt_fd:write(s .. '\n') + end +end + +local options = require('options') + +cstr = options.cstr + +local type_flags={ + bool='P_BOOL', + number='P_NUM', + string='P_STRING', +} + +local redraw_flags={ + statuslines='P_RSTAT', + current_window='P_RWIN', + current_window_only='P_RWINONLY', + current_buffer='P_RBUF', + all_windows='P_RALL', + everything='P_RCLR', + curswant='P_CURSWANT', +} + +local list_flags={ + comma='P_COMMA', + onecomma='P_ONECOMMA', + flags='P_FLAGLIST', + flagscomma='P_COMMA|P_FLAGLIST', +} + +local get_flags = function(o) + local ret = {type_flags[o.type]} + local add_flag = function(f) + ret[1] = ret[1] .. '|' .. f + end + if o.list then + add_flag(list_flags[o.list]) + end + if o.redraw then + for _, r_flag in ipairs(o.redraw) do + add_flag(redraw_flags[r_flag]) + end + end + if o.expand then + add_flag('P_EXPAND') + if o.expand == 'nodefault' then + add_flag('P_NO_DEF_EXP') + end + end + for _, flag_desc in ipairs({ + {'alloced'}, + {'nodefault'}, + {'no_mkrc'}, + {'vi_def'}, + {'vim'}, + {'secure'}, + {'gettext'}, + {'noglob'}, + {'normal_fname_chars', 'P_NFNAME'}, + {'pri_mkrc'}, + {'deny_in_modelines', 'P_NO_ML'}, + {'deny_duplicates', 'P_NODUP'}, + }) do + local key_name = flag_desc[1] + local def_name = flag_desc[2] or ('P_' .. key_name:upper()) + if o[key_name] then + add_flag(def_name) + end + end + return ret[1] +end + +local get_cond +get_cond = function(c, base_string) + local cond_string = base_string or '#if ' + if type(c) == 'table' then + cond_string = cond_string .. get_cond(c[1], '') + for i, subc in ipairs(c) do + if i > 1 then + cond_string = cond_string .. ' && ' .. get_cond(subc, '') + end + end + elseif c:sub(1, 1) == '!' then + cond_string = cond_string .. '!defined(' .. c:sub(2) .. ')' + else + cond_string = cond_string .. 'defined(' .. c .. ')' + end + return cond_string +end + +value_dumpers = { + ['function']=function(v) return v() end, + string=cstr, + boolean=function(v) return v and 'true' or 'false' end, + number=function(v) return ('%iL'):format(v) end, + ['nil']=function(v) return '0L' end, +} + +local get_value = function(v) + return '(char_u *) ' .. value_dumpers[type(v)](v) +end + +local get_defaults = function(d) + return ('{' .. get_value(d.vi) .. ', ' .. get_value(d.vim) .. '}') +end + +local defines = {} + +local dump_option = function(i, o) + w(' [' .. ('%u'):format(i - 1) .. ']={') + w(' .fullname=' .. cstr(o.full_name)) + if o.abbreviation then + w(' .shortname=' .. cstr(o.abbreviation)) + end + w(' .flags=' .. get_flags(o)) + if o.enable_if then + w(get_cond(o.enable_if)) + end + if o.varname then + w(' .var=(char_u *)&' .. o.varname) + elseif #o.scope == 1 and o.scope[1] == 'window' then + w(' .var=VAR_WIN') + end + if o.enable_if then + w('#endif') + end + if #o.scope == 1 and o.scope[1] == 'global' then + w(' .indir=PV_NONE') + else + assert (#o.scope == 1 or #o.scope == 2) + assert (#o.scope == 1 or o.scope[1] == 'global') + local min_scope = o.scope[#o.scope] + local varname = o.pv_name or o.varname or ( + 'p_' .. (o.abbreviation or o.full_name)) + local pv_name = ( + 'OPT_' .. min_scope:sub(1, 3):upper() .. '(' .. ( + min_scope:sub(1, 1):upper() .. 'V_' .. varname:sub(3):upper() + ) .. ')' + ) + if #o.scope == 2 then + pv_name = 'OPT_BOTH(' .. pv_name .. ')' + end + defines['PV_' .. varname:sub(3):upper()] = pv_name + w(' .indir=' .. pv_name) + end + if o.defaults then + if o.defaults.condition then + w(get_cond(o.defaults.condition)) + end + w(' .def_val=' .. get_defaults(o.defaults.if_true)) + if o.defaults.condition then + if o.defaults.if_false then + w('#else') + w(' .def_val=' .. get_defaults(o.defaults.if_false)) + end + w('#endif') + end + end + w(' },') +end + +w('static vimoption_T options[] = {') +for i, o in ipairs(options.options) do + dump_option(i, o) +end +w(' [' .. ('%u'):format(#options.options) .. ']={.fullname=NULL}') +w('};') +w('') + +for k, v in pairs(defines) do + w('#define ' .. k .. ' ' .. v) +end +opt_fd:close() diff --git a/src/nvim/generators/gen_unicode_tables.lua b/src/nvim/generators/gen_unicode_tables.lua new file mode 100644 index 0000000000..66430ba26e --- /dev/null +++ b/src/nvim/generators/gen_unicode_tables.lua @@ -0,0 +1,327 @@ +-- Script creates the following tables in unicode_tables.generated.h: +-- +-- 1. doublewidth and ambiguous tables: sorted list of non-overlapping closed +-- intervals. Codepoints in these intervals have double (W or F) or ambiguous +-- (A) east asian width respectively. +-- 2. combining table: same as the above, but characters inside are combining +-- characters (i.e. have general categories equal to Mn, Mc or Me). +-- 3. foldCase, toLower and toUpper tables used to convert characters to +-- folded/lower/upper variants. In these tables first two values are +-- character ranges: like in previous tables they are sorted and must be +-- non-overlapping. Third value means step inside the range: e.g. if it is +-- 2 then interval applies only to first, third, fifth, … character in range. +-- Fourth value is number that should be added to the codepoint to yield +-- folded/lower/upper codepoint. +-- 4. emoji_width and emoji_all tables: sorted lists of non-overlapping closed +-- intervals of Emoji characters. emoji_width contains all the characters +-- which don't have ambiguous or double width, and emoji_all has all Emojis. +if arg[1] == '--help' then + print('Usage:') + print(' genunicodetables.lua unicode/ unicode_tables.generated.h') + os.exit(0) +end + +local basedir = arg[1] +local pathsep = package.config:sub(1, 1) +local get_path = function(fname) + return basedir .. pathsep .. fname +end + +local unicodedata_fname = get_path('UnicodeData.txt') +local casefolding_fname = get_path('CaseFolding.txt') +local eastasianwidth_fname = get_path('EastAsianWidth.txt') +local emoji_fname = get_path('emoji-data.txt') + +local utf_tables_fname = arg[2] + +local split_on_semicolons = function(s) + local ret = {} + local idx = 1 + while idx <= #s + 1 do + item = s:match('^[^;]*', idx) + idx = idx + #item + 1 + if idx <= #s + 1 then + assert(s:sub(idx - 1, idx - 1) == ';') + end + item = item:gsub('^%s*', '') + item = item:gsub('%s*$', '') + table.insert(ret, item) + end + return ret +end + +local fp_lines_to_lists = function(fp, n, has_comments) + local ret = {} + local line + local i = 0 + while true do + i = i + 1 + line = fp:read('*l') + if not line then + break + end + if (not has_comments + or (line:sub(1, 1) ~= '#' and not line:match('^%s*$'))) then + local l = split_on_semicolons(line) + if #l ~= n then + io.stderr:write(('Found %s items in line %u, expected %u\n'):format( + #l, i, n)) + io.stderr:write('Line: ' .. line .. '\n') + return nil + end + table.insert(ret, l) + end + end + return ret +end + +local parse_data_to_props = function(ud_fp) + return fp_lines_to_lists(ud_fp, 15, false) +end + +local parse_fold_props = function(cf_fp) + return fp_lines_to_lists(cf_fp, 4, true) +end + +local parse_width_props = function(eaw_fp) + return fp_lines_to_lists(eaw_fp, 2, true) +end + +local parse_emoji_props = function(emoji_fp) + return fp_lines_to_lists(emoji_fp, 2, true) +end + +local make_range = function(start, end_, step, add) + if step and add then + return (' {0x%x, 0x%x, %d, %d},\n'):format( + start, end_, step == 0 and -1 or step, add) + else + return (' {0x%04x, 0x%04x},\n'):format(start, end_) + end +end + +local build_convert_table = function(ut_fp, props, cond_func, nl_index, + table_name) + ut_fp:write('static const convertStruct ' .. table_name .. '[] = {\n') + local start = -1 + local end_ = -1 + local step = 0 + local add = -1 + for _, p in ipairs(props) do + if cond_func(p) then + local n = tonumber(p[1], 16) + local nl = tonumber(p[nl_index], 16) + if start >= 0 and add == (nl - n) and (step == 0 or n - end_ == step) then + -- Continue with the same range. + step = n - end_ + end_ = n + else + if start >= 0 then + -- Produce previous range. + ut_fp:write(make_range(start, end_, step, add)) + end + start = n + end_ = n + step = 0 + add = nl - n + end + end + end + if start >= 0 then + ut_fp:write(make_range(start, end_, step, add)) + end + ut_fp:write('};\n') +end + +local build_case_table = function(ut_fp, dataprops, table_name, index) + local cond_func = function(p) + return p[index] ~= '' + end + return build_convert_table(ut_fp, dataprops, cond_func, index, + 'to' .. table_name) +end + +local build_fold_table = function(ut_fp, foldprops) + local cond_func = function(p) + return (p[2] == 'C' or p[2] == 'S') + end + return build_convert_table(ut_fp, foldprops, cond_func, 3, 'foldCase') +end + +local build_combining_table = function(ut_fp, dataprops) + ut_fp:write('static const struct interval combining[] = {\n') + local start = -1 + local end_ = -1 + for _, p in ipairs(dataprops) do + if (({Mn=true, Mc=true, Me=true})[p[3]]) then + local n = tonumber(p[1], 16) + if start >= 0 and end_ + 1 == n then + -- Continue with the same range. + end_ = n + else + if start >= 0 then + -- Produce previous range. + ut_fp:write(make_range(start, end_)) + end + start = n + end_ = n + end + end + end + if start >= 0 then + ut_fp:write(make_range(start, end_)) + end + ut_fp:write('};\n') +end + +local build_width_table = function(ut_fp, dataprops, widthprops, widths, + table_name) + ut_fp:write('static const struct interval ' .. table_name .. '[] = {\n') + local start = -1 + local end_ = -1 + local dataidx = 1 + local ret = {} + for _, p in ipairs(widthprops) do + if widths[p[2]:sub(1, 1)] then + local rng_start, rng_end = p[1]:find('%.%.') + local n, n_last + if rng_start then + -- It is a range. We don’t check for composing char then. + n = tonumber(p[1]:sub(1, rng_start - 1), 16) + n_last = tonumber(p[1]:sub(rng_end + 1), 16) + else + n = tonumber(p[1], 16) + n_last = n + end + local dn + while true do + dn = tonumber(dataprops[dataidx][1], 16) + if dn >= n then + break + end + dataidx = dataidx + 1 + end + if dn ~= n and n_last == n then + io.stderr:write('Cannot find character ' .. n .. ' in data table.\n') + end + -- Only use the char when it’s not a composing char. + -- But use all chars from a range. + local dp = dataprops[dataidx] + if (n_last > n) or (not (({Mn=true, Mc=true, Me=true})[dp[3]])) then + if start >= 0 and end_ + 1 == n then + -- Continue with the same range. + else + if start >= 0 then + ut_fp:write(make_range(start, end_)) + table.insert(ret, {start, end_}) + end + start = n + end + end_ = n_last + end + end + end + if start >= 0 then + ut_fp:write(make_range(start, end_)) + table.insert(ret, {start, end_}) + end + ut_fp:write('};\n') + return ret +end + +local build_emoji_table = function(ut_fp, emojiprops, doublewidth, ambiwidth) + local emojiwidth = {} + local emoji = {} + for _, p in ipairs(emojiprops) do + if p[2]:match('Emoji%s+#') then + local rng_start, rng_end = p[1]:find('%.%.') + if rng_start then + n = tonumber(p[1]:sub(1, rng_start - 1), 16) + n_last = tonumber(p[1]:sub(rng_end + 1), 16) + else + n = tonumber(p[1], 16) + n_last = n + end + if #emoji > 0 and n - 1 == emoji[#emoji][2] then + emoji[#emoji][2] = n_last + else + table.insert(emoji, { n, n_last }) + end + + -- Characters below 1F000 may be considered single width traditionally, + -- making them double width causes problems. + if n >= 0x1f000 then + -- exclude characters that are in the ambiguous/doublewidth table + for _, ambi in ipairs(ambiwidth) do + if n >= ambi[1] and n <= ambi[2] then + n = ambi[2] + 1 + end + if n_last >= ambi[1] and n_last <= ambi[2] then + n_last = ambi[1] - 1 + end + end + for _, double in ipairs(doublewidth) do + if n >= double[1] and n <= double[2] then + n = double[2] + 1 + end + if n_last >= double[1] and n_last <= double[2] then + n_last = double[1] - 1 + end + end + + if n <= n_last then + if #emojiwidth > 0 and n - 1 == emojiwidth[#emojiwidth][2] then + emojiwidth[#emojiwidth][2] = n_last + else + table.insert(emojiwidth, { n, n_last }) + end + end + end + end + end + + ut_fp:write('static const struct interval emoji_all[] = {\n') + for _, p in ipairs(emoji) do + ut_fp:write(make_range(p[1], p[2])) + end + ut_fp:write('};\n') + + ut_fp:write('static const struct interval emoji_width[] = {\n') + for _, p in ipairs(emojiwidth) do + ut_fp:write(make_range(p[1], p[2])) + end + ut_fp:write('};\n') +end + +local ud_fp = io.open(unicodedata_fname, 'r') +local dataprops = parse_data_to_props(ud_fp) +ud_fp:close() + +local ut_fp = io.open(utf_tables_fname, 'w') + +build_case_table(ut_fp, dataprops, 'Lower', 14) +build_case_table(ut_fp, dataprops, 'Upper', 13) +build_combining_table(ut_fp, dataprops) + +local cf_fp = io.open(casefolding_fname, 'r') +local foldprops = parse_fold_props(cf_fp) +cf_fp:close() + +build_fold_table(ut_fp, foldprops) + +local eaw_fp = io.open(eastasianwidth_fname, 'r') +local widthprops = parse_width_props(eaw_fp) +eaw_fp:close() + +local doublewidth = build_width_table(ut_fp, dataprops, widthprops, + {W=true, F=true}, 'doublewidth') +local ambiwidth = build_width_table(ut_fp, dataprops, widthprops, + {A=true}, 'ambiguous') + +local emoji_fp = io.open(emoji_fname, 'r') +local emojiprops = parse_emoji_props(emoji_fp) +emoji_fp:close() + +build_emoji_table(ut_fp, emojiprops, doublewidth, ambiwidth) + +ut_fp:close() diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index fccbd69dbf..a22b716bb6 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -1,3 +1,6 @@ +// 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 + /* * getchar.c * @@ -15,6 +18,7 @@ #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/getchar.h" +#include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/cursor.h" #include "nvim/edit.h" @@ -44,6 +48,7 @@ #include "nvim/event/loop.h" #include "nvim/os/input.h" #include "nvim/os/os.h" +#include "nvim/api/private/handle.h" /* * These buffers are used for storing: @@ -99,11 +104,10 @@ static int block_redo = FALSE; (NORMAL + VISUAL + SELECTMODE + \ OP_PENDING)) ? (c1) : ((c1) ^ 0x80)) -/* - * Each mapping is put in one of the 256 hash lists, to speed up finding it. - */ -static mapblock_T *(maphash[256]); -static int maphash_valid = FALSE; +// Each mapping is put in one of the MAX_MAPHASH hash lists, +// to speed up finding it. +static mapblock_T *(maphash[MAX_MAPHASH]); +static bool maphash_valid = false; /* * List used for abbreviations. @@ -235,19 +239,18 @@ char_u *get_inserted(void) return get_buffcont(&redobuff, FALSE); } -/* - * Add string "s" after the current block of buffer "buf". - * K_SPECIAL and CSI should have been escaped already. - */ -static void -add_buff ( - buffheader_T *buf, - char_u *s, - ssize_t slen // length of "s" or -1 -) +/// Add string after the current block of the given buffer +/// +/// K_SPECIAL and CSI should have been escaped already. +/// +/// @param[out] buf Buffer to add to. +/// @param[in] s String to add. +/// @param[in] slen String length or -1 for NUL-terminated string. +static void add_buff(buffheader_T *const buf, const char *const s, + ptrdiff_t slen) { if (slen < 0) { - slen = (ssize_t)STRLEN(s); + slen = (ptrdiff_t)strlen(s); } if (slen == 0) { // don't add empty strings return; @@ -292,9 +295,8 @@ add_buff ( */ static void add_num_buff(buffheader_T *buf, long n) { - char_u number[32]; - - sprintf((char *)number, "%" PRId64, (int64_t)n); + char number[32]; + snprintf(number, sizeof(number), "%ld", n); add_buff(buf, number, -1L); } @@ -304,27 +306,29 @@ static void add_num_buff(buffheader_T *buf, long n) */ static void add_char_buff(buffheader_T *buf, int c) { - char_u bytes[MB_MAXBYTES + 1]; - int len; - int i; - char_u temp[4]; + uint8_t bytes[MB_MAXBYTES + 1]; - if (IS_SPECIAL(c)) + int len; + if (IS_SPECIAL(c)) { len = 1; - else - len = (*mb_char2bytes)(c, bytes); - for (i = 0; i < len; ++i) { - if (!IS_SPECIAL(c)) + } else { + len = mb_char2bytes(c, bytes); + } + + for (int i = 0; i < len; i++) { + if (!IS_SPECIAL(c)) { c = bytes[i]; + } + char temp[4]; if (IS_SPECIAL(c) || c == K_SPECIAL || c == NUL) { - /* translate special key code into three byte sequence */ - temp[0] = K_SPECIAL; - temp[1] = (char_u)K_SECOND(c); - temp[2] = (char_u)K_THIRD(c); + // Translate special key code into three byte sequence. + temp[0] = (char)K_SPECIAL; + temp[1] = (char)K_SECOND(c); + temp[2] = (char)K_THIRD(c); temp[3] = NUL; } else { - temp[0] = (char_u)c; + temp[0] = (char)c; temp[1] = NUL; } add_buff(buf, temp, -1L); @@ -479,16 +483,14 @@ static int save_level = 0; void saveRedobuff(void) { - char_u *s; - if (save_level++ == 0) { save_redobuff = redobuff; redobuff.bh_first.b_next = NULL; save_old_redobuff = old_redobuff; old_redobuff.bh_first.b_next = NULL; - /* Make a copy, so that ":normal ." in a function works. */ - s = get_buffcont(&save_redobuff, FALSE); + // Make a copy, so that ":normal ." in a function works. + char *const s = (char *)get_buffcont(&save_redobuff, false); if (s != NULL) { add_buff(&redobuff, s, -1L); xfree(s); @@ -514,10 +516,11 @@ void restoreRedobuff(void) * Append "s" to the redo buffer. * K_SPECIAL and CSI should already have been escaped. */ -void AppendToRedobuff(char_u *s) +void AppendToRedobuff(const char *s) { - if (!block_redo) - add_buff(&redobuff, s, -1L); + if (!block_redo) { + add_buff(&redobuff, (const char *)s, -1L); + } } /* @@ -530,44 +533,47 @@ AppendToRedobuffLit ( int len /* length of "str" or -1 for up to the NUL */ ) { - char_u *s = str; - int c; - char_u *start; - - if (block_redo) + if (block_redo) { return; + } + + const char *s = (const char *)str; + while (len < 0 ? *s != NUL : s - (const char *)str < len) { + // Put a string of normal characters in the redo buffer (that's + // faster). + const char *start = s; + while (*s >= ' ' && *s < DEL && (len < 0 || s - (const char *)str < len)) { + s++; + } - while (len < 0 ? *s != NUL : s - str < len) { - /* Put a string of normal characters in the redo buffer (that's - * faster). */ - start = s; - while (*s >= ' ' && *s < DEL && (len < 0 || s - str < len)) - ++s; - - /* Don't put '0' or '^' as last character, just in case a CTRL-D is - * typed next. */ - if (*s == NUL && (s[-1] == '0' || s[-1] == '^')) - --s; - if (s > start) + // Don't put '0' or '^' as last character, just in case a CTRL-D is + // typed next. + if (*s == NUL && (s[-1] == '0' || s[-1] == '^')) { + s--; + } + if (s > start) { add_buff(&redobuff, start, (long)(s - start)); + } - if (*s == NUL || (len >= 0 && s - str >= len)) + if (*s == NUL || (len >= 0 && s - (const char *)str >= len)) { break; + } - /* Handle a special or multibyte character. */ - if (has_mbyte) - /* Handle composing chars separately. */ - c = mb_cptr2char_adv(&s); - else - c = *s++; - if (c < ' ' || c == DEL || (*s == NUL && (c == '0' || c == '^'))) + // Handle a special or multibyte character. + // Composing chars separately are handled separately. + const int c = (has_mbyte + ? mb_cptr2char_adv((const char_u **)&s) + : (uint8_t)(*s++)); + if (c < ' ' || c == DEL || (*s == NUL && (c == '0' || c == '^'))) { add_char_buff(&redobuff, Ctrl_V); + } - /* CTRL-V '0' must be inserted as CTRL-V 048 */ - if (*s == NUL && c == '0') - add_buff(&redobuff, (char_u *)"048", 3L); - else + // CTRL-V '0' must be inserted as CTRL-V 048. + if (*s == NUL && c == '0') { + add_buff(&redobuff, "048", 3L); + } else { add_char_buff(&redobuff, c); + } } } @@ -594,19 +600,19 @@ void AppendNumberToRedobuff(long n) * Append string "s" to the stuff buffer. * CSI and K_SPECIAL must already have been escaped. */ -void stuffReadbuff(char_u *s) +void stuffReadbuff(const char *s) { add_buff(&readbuf1, s, -1L); } /// Append string "s" to the redo stuff buffer. /// @remark CSI and K_SPECIAL must already have been escaped. -void stuffRedoReadbuff(char_u *s) +void stuffRedoReadbuff(const char *s) { add_buff(&readbuf2, s, -1L); } -void stuffReadbuffLen(char_u *s, long len) +void stuffReadbuffLen(const char *s, long len) { add_buff(&readbuf1, s, len); } @@ -616,19 +622,18 @@ void stuffReadbuffLen(char_u *s, long len) * escaping other K_SPECIAL and CSI bytes. * Change CR, LF and ESC into a space. */ -void stuffReadbuffSpec(char_u *s) +void stuffReadbuffSpec(const char *s) { - int c; - while (*s != NUL) { - if (*s == K_SPECIAL && s[1] != NUL && s[2] != NUL) { - /* Insert special key literally. */ - stuffReadbuffLen(s, 3L); + if ((uint8_t)(*s) == K_SPECIAL && s[1] != NUL && s[2] != NUL) { + // Insert special key literally. + stuffReadbuffLen(s, 3); s += 3; } else { - c = mb_ptr2char_adv(&s); - if (c == CAR || c == NL || c == ESC) + int c = mb_ptr2char_adv((const char_u **)&s); + if (c == CAR || c == NL || c == ESC) { c = ' '; + } stuffcharReadbuff(c); } } @@ -747,8 +752,8 @@ int start_redo(long count, int old_redo) /* copy the buffer name, if present */ if (c == '"') { - add_buff(&readbuf2, (char_u *)"\"", 1L); - c = read_redo(FALSE, old_redo); + add_buff(&readbuf2, "\"", 1L); + c = read_redo(false, old_redo); /* if a numbered buffer is used, increment the number */ if (c >= '1' && c < '9') @@ -1091,21 +1096,19 @@ static void gotchars(char_u *chars, size_t len) { char_u *s = chars; int c; - char_u buf[2]; // remember how many chars were last recorded if (Recording) { last_recorded_len += len; } - buf[1] = NUL; while (len--) { // Handle one byte at a time; no translation to be done. c = *s++; updatescript(c); if (Recording) { - buf[0] = (char_u)c; + char buf[2] = { (char)c, NUL }; add_buff(&recordbuff, buf, 1L); } } @@ -1327,8 +1330,9 @@ int using_script(void) void before_blocking(void) { updatescript(0); - if (may_garbage_collect) - garbage_collect(); + if (may_garbage_collect) { + garbage_collect(false); + } } /* @@ -1366,10 +1370,11 @@ int vgetc(void) char_u buf[MB_MAXBYTES + 1]; int i; - /* Do garbage collection when garbagecollect() was called previously and - * we are now at the toplevel. */ - if (may_garbage_collect && want_garbage_collect) - garbage_collect(); + // Do garbage collection when garbagecollect() was called previously and + // we are now at the toplevel. + if (may_garbage_collect && want_garbage_collect) { + garbage_collect(false); + } /* * If a character was put back with vungetc, it was already processed. @@ -1387,27 +1392,20 @@ int vgetc(void) for (;; ) { // this is done twice if there are modifiers bool did_inc = false; if (mod_mask) { // no mapping after modifier has been read - ++no_mapping; - ++allow_keys; + no_mapping++; did_inc = true; // mod_mask may change value } c = vgetorpeek(true); if (did_inc) { - --no_mapping; - --allow_keys; + no_mapping--; } - /* Get two extra bytes for special keys */ - if (c == K_SPECIAL - ) { - int save_allow_keys = allow_keys; - - ++no_mapping; - allow_keys = 0; /* make sure BS is not found */ - c2 = vgetorpeek(TRUE); /* no mapping for these chars */ - c = vgetorpeek(TRUE); - --no_mapping; - allow_keys = save_allow_keys; + // Get two extra bytes for special keys + if (c == K_SPECIAL) { + no_mapping++; + c2 = vgetorpeek(true); // no mapping for these chars + c = vgetorpeek(true); + no_mapping--; if (c2 == KS_MODIFIER) { mod_mask = c; continue; @@ -1485,7 +1483,7 @@ int vgetc(void) buf[i] = CSI; } } - --no_mapping; + no_mapping--; c = (*mb_ptr2char)(buf); } @@ -1568,7 +1566,7 @@ int char_avail(void) no_mapping++; retval = vpeekc(); - --no_mapping; + no_mapping--; return retval != NUL; } @@ -1595,7 +1593,7 @@ vungetc ( /* unget one character (can only be done once!) */ /// This may do a blocking wait if "advance" is TRUE. /// /// if "advance" is TRUE (vgetc()): -/// really get the character. +/// Really get the character. /// KeyTyped is set to TRUE in the case the user typed the key. /// KeyStuffed is TRUE if the character comes from the stuff buffer. /// if "advance" is FALSE (vpeekc()): @@ -1808,7 +1806,7 @@ static int vgetorpeek(int advance) * <M-a> and then changing 'encoding'. Beware * that 0x80 is escaped. */ char_u *p1 = mp->m_keys; - char_u *p2 = mb_unescape(&p1); + char_u *p2 = (char_u *)mb_unescape((const char **)&p1); if (has_mbyte && p2 != NULL && MB_BYTE2LEN(c1) > MB_PTR2LEN(p2)) mlen = 0; @@ -1855,11 +1853,12 @@ static int vgetorpeek(int advance) mp_match = mp; mp_match_len = keylen; } - } else - /* No match; may have to check for - * termcode at next character. */ - if (max_mlen < mlen) - max_mlen = mlen; + } else { + // No match; may have to check for termcode at next character. + if (max_mlen < mlen) { + max_mlen = mlen; + } + } } } @@ -1886,9 +1885,8 @@ static int vgetorpeek(int advance) (size_t)(mlen - typebuf.tb_maplen)); } - del_typebuf(mlen, 0); /* remove the chars */ - set_option_value((char_u *)"paste", - (long)!p_paste, NULL, 0); + del_typebuf(mlen, 0); // Remove the chars. + set_option_value("paste", !p_paste, NULL, 0); if (!(State & INSERT)) { msg_col = 0; msg_row = (int)Rows - 1; @@ -1911,63 +1909,30 @@ static int vgetorpeek(int advance) if ((mp == NULL || max_mlen >= mp_match_len) && keylen != KEYLEN_PART_MAP) { - /* - * When no matching mapping found or found a - * non-matching mapping that matches at least what the - * matching mapping matched: - * Check if we have a terminal code, when: - * mapping is allowed, - * keys have not been mapped, - * and not an ESC sequence, not in insert mode or - * p_ek is on, - * and when not timed out, - */ - if ((no_mapping == 0 || allow_keys != 0) - && (typebuf.tb_maplen == 0 - || (p_remap && typebuf.tb_noremap[ - typebuf.tb_off] == RM_YES)) - && !timedout) { - keylen = 0; - } else - keylen = 0; - if (keylen == 0) { /* no matching terminal code */ - /* When there was a matching mapping and no - * termcode could be replaced after another one, - * use that mapping (loop around). If there was - * no mapping use the character from the - * typeahead buffer right here. */ - if (mp == NULL) { - /* - * get a character: 2. from the typeahead buffer - */ - c = typebuf.tb_buf[typebuf.tb_off] & 255; - if (advance) { /* remove chars from tb_buf */ - cmd_silent = (typebuf.tb_silent > 0); - if (typebuf.tb_maplen > 0) - KeyTyped = FALSE; - else { - KeyTyped = TRUE; - /* write char to script file(s) */ - gotchars(typebuf.tb_buf - + typebuf.tb_off, 1); - } - KeyNoremap = typebuf.tb_noremap[ - typebuf.tb_off]; - del_typebuf(1, 0); + // No matching mapping found or found a non-matching mapping that + // matches at least what the matching mapping matched + keylen = 0; + // If there was no mapping, use the character from the typeahead + // buffer right here. Otherwise, use the mapping (loop around). + if (mp == NULL) { + // get a character: 2. from the typeahead buffer + c = typebuf.tb_buf[typebuf.tb_off] & 255; + if (advance) { // remove chars from tb_buf + cmd_silent = (typebuf.tb_silent > 0); + if (typebuf.tb_maplen > 0) { + KeyTyped = false; + } else { + KeyTyped = true; + // write char to script file(s) + gotchars(typebuf.tb_buf + typebuf.tb_off, 1); } - break; /* got character, break for loop */ + KeyNoremap = typebuf.tb_noremap[typebuf.tb_off]; + del_typebuf(1, 0); } - } - if (keylen > 0) { /* full matching terminal code */ - continue; /* try mapping again */ - } - - /* Partial match: get some more characters. When a - * matching mapping was found use that one. */ - if (mp == NULL || keylen < 0) - keylen = KEYLEN_PART_KEY; - else + break; // got character, break for loop + } else { keylen = mp_match_len; + } } /* complete match */ @@ -2462,7 +2427,7 @@ inchar ( if (typebuf_changed(tb_change_cnt)) return 0; - return fix_input_buffer(buf, len, script_char >= 0); + return fix_input_buffer(buf, len); } /* @@ -2470,12 +2435,7 @@ inchar ( * buf[] must have room to triple the number of bytes! * Returns the new length. */ -int -fix_input_buffer ( - char_u *buf, - int len, - int script /* TRUE when reading from a script */ -) +int fix_input_buffer(char_u *buf, int len) { if (!using_script()) { // Should not escape K_SPECIAL/CSI reading input from the user because vim @@ -2492,12 +2452,10 @@ fix_input_buffer ( // Replace NUL by K_SPECIAL KS_ZERO KE_FILLER // Replace K_SPECIAL by K_SPECIAL KS_SPECIAL KE_FILLER // Replace CSI by K_SPECIAL KS_EXTRA KE_CSI - // Don't replace K_SPECIAL when reading a script file. for (i = len; --i >= 0; ++p) { if (p[0] == NUL || (p[0] == K_SPECIAL - && !script - && (i < 2 || p[1] != KS_EXTRA))) { + && (i < 2 || p[1] != KS_EXTRA))) { memmove(p + 3, p + 1, (size_t)i); p[2] = (char_u)K_THIRD(p[0]); p[1] = (char_u)K_SECOND(p[0]); @@ -2579,7 +2537,6 @@ do_map ( bool unique = false; bool nowait = false; bool silent = false; - bool special = false; bool expr = false; int noremap; char_u *orig_rhs; @@ -2625,12 +2582,9 @@ do_map ( continue; } - /* - * Check for "<special>": accept special keys in <> - */ + // Ignore obsolete "<special>" modifier. if (STRNCMP(keys, "<special>", 9) == 0) { keys = skipwhite(keys + 9); - special = true; continue; } @@ -2699,7 +2653,7 @@ do_map ( // needs to be freed later (*keys_buf and *arg_buf). // replace_termcodes() also removes CTRL-Vs and sometimes backslashes. if (haskey) { - keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, special, + keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, true, CPO_TO_CPO_FLAGS); } orig_rhs = rhs; @@ -2707,7 +2661,7 @@ do_map ( if (STRICMP(rhs, "<nop>") == 0) { // "<Nop>" means nothing rhs = (char_u *)""; } else { - rhs = replace_termcodes(rhs, STRLEN(rhs), &arg_buf, false, true, special, + rhs = replace_termcodes(rhs, STRLEN(rhs), &arg_buf, false, true, true, CPO_TO_CPO_FLAGS); } } @@ -3163,11 +3117,11 @@ map_clear_int ( } } -/* - * Return characters to represent the map mode in an allocated string. - * Returns NULL when out of memory. - */ -char_u *map_mode_to_chars(int mode) +/// Return characters to represent the map mode in an allocated string +/// +/// @return [allocated] NUL-terminated string with characters. +char *map_mode_to_chars(int mode) + FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET { garray_T mapmode; @@ -3200,7 +3154,7 @@ char_u *map_mode_to_chars(int mode) } ga_append(&mapmode, NUL); - return (char_u *)mapmode.ga_data; + return (char *)mapmode.ga_data; } static void @@ -3209,8 +3163,11 @@ showmap ( int local /* TRUE for buffer-local map */ ) { - int len = 1; - char_u *mapchars; + size_t len = 1; + + if (message_filtered(mp->m_keys) && message_filtered(mp->m_str)) { + return; + } if (msg_didout || msg_silent != 0) { msg_putchar('\n'); @@ -3218,29 +3175,30 @@ showmap ( return; } - mapchars = map_mode_to_chars(mp->m_mode); - if (mapchars != NULL) { + { + char *const mapchars = map_mode_to_chars(mp->m_mode); msg_puts(mapchars); - len = (int)STRLEN(mapchars); + len = strlen(mapchars); xfree(mapchars); } while (++len <= 3) msg_putchar(' '); - /* Display the LHS. Get length of what we write. */ - len = msg_outtrans_special(mp->m_keys, TRUE); + // Display the LHS. Get length of what we write. + len = (size_t)msg_outtrans_special(mp->m_keys, true); do { msg_putchar(' '); /* padd with blanks */ ++len; } while (len < 12); - if (mp->m_noremap == REMAP_NONE) - msg_puts_attr((char_u *)"*", hl_attr(HLF_8)); - else if (mp->m_noremap == REMAP_SCRIPT) - msg_puts_attr((char_u *)"&", hl_attr(HLF_8)); - else + if (mp->m_noremap == REMAP_NONE) { + msg_puts_attr("*", hl_attr(HLF_8)); + } else if (mp->m_noremap == REMAP_SCRIPT) { + msg_puts_attr("&", hl_attr(HLF_8)); + } else { msg_putchar(' '); + } if (local) msg_putchar('@'); @@ -3249,11 +3207,11 @@ showmap ( /* Use FALSE below if we only want things like <Up> to show up as such on * the rhs, and not M-x etc, TRUE gets both -- webb */ - if (*mp->m_str == NUL) - msg_puts_attr((char_u *)"<Nop>", hl_attr(HLF_8)); - else { - /* Remove escaping of CSI, because "m_str" is in a format to be used - * as typeahead. */ + if (*mp->m_str == NUL) { + msg_puts_attr("<Nop>", hl_attr(HLF_8)); + } else { + // Remove escaping of CSI, because "m_str" is in a format to be used + // as typeahead. char_u *s = vim_strsave(mp->m_str); vim_unescape_csi(s); msg_outtrans_special(s, FALSE); @@ -3264,82 +3222,99 @@ showmap ( ui_flush(); /* show one line at a time */ } -/* - * Return TRUE if a map exists that has "str" in the rhs for mode "modechars". - * Recognize termcap codes in "str". - * Also checks mappings local to the current buffer. - */ -int map_to_exists(char_u *str, char_u *modechars, int abbr) +/// Check if a map exists that has given string in the rhs +/// +/// Also checks mappings local to the current buffer. +/// +/// @param[in] str String which mapping must have in the rhs. Termcap codes +/// are recognized in this argument. +/// @param[in] modechars Mode(s) in which mappings are checked. +/// @param[in] abbr true if checking abbreviations in place of mappings. +/// +/// @return true if there is at least one mapping with given parameters. +bool map_to_exists(const char *const str, const char *const modechars, + const bool abbr) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE { int mode = 0; - char_u *rhs; - char_u *buf; int retval; - rhs = replace_termcodes(str, STRLEN(str), &buf, false, true, false, - CPO_TO_CPO_FLAGS); - - if (vim_strchr(modechars, 'n') != NULL) - mode |= NORMAL; - if (vim_strchr(modechars, 'v') != NULL) - mode |= VISUAL + SELECTMODE; - if (vim_strchr(modechars, 'x') != NULL) - mode |= VISUAL; - if (vim_strchr(modechars, 's') != NULL) - mode |= SELECTMODE; - if (vim_strchr(modechars, 'o') != NULL) - mode |= OP_PENDING; - if (vim_strchr(modechars, 'i') != NULL) - mode |= INSERT; - if (vim_strchr(modechars, 'l') != NULL) - mode |= LANGMAP; - if (vim_strchr(modechars, 'c') != NULL) - mode |= CMDLINE; - - retval = map_to_exists_mode(rhs, mode, abbr); + char_u *buf; + char_u *const rhs = replace_termcodes((const char_u *)str, strlen(str), &buf, + false, true, true, + CPO_TO_CPO_FLAGS); + +#define MAPMODE(mode, modechars, chr, modeflags) \ + do { \ + if (strchr(modechars, chr) != NULL) { \ + mode |= modeflags; \ + } \ + } while (0) + MAPMODE(mode, modechars, 'n', NORMAL); + MAPMODE(mode, modechars, 'v', VISUAL|SELECTMODE); + MAPMODE(mode, modechars, 'x', VISUAL); + MAPMODE(mode, modechars, 's', SELECTMODE); + MAPMODE(mode, modechars, 'o', OP_PENDING); + MAPMODE(mode, modechars, 'i', INSERT); + MAPMODE(mode, modechars, 'l', LANGMAP); + MAPMODE(mode, modechars, 'c', CMDLINE); +#undef MAPMODE + + retval = map_to_exists_mode((const char *)rhs, mode, abbr); xfree(buf); return retval; } -/* - * Return TRUE if a map exists that has "str" in the rhs for mode "mode". - * Also checks mappings local to the current buffer. - */ -int map_to_exists_mode(char_u *rhs, int mode, int abbr) +/// Check if a map exists that has given string in the rhs +/// +/// Also checks mappings local to the current buffer. +/// +/// @param[in] rhs String which mapping must have in the rhs. Termcap codes +/// are recognized in this argument. +/// @param[in] mode Mode(s) in which mappings are checked. +/// @param[in] abbr true if checking abbreviations in place of mappings. +/// +/// @return true if there is at least one mapping with given parameters. +int map_to_exists_mode(const char *const rhs, const int mode, const bool abbr) { mapblock_T *mp; int hash; - int expand_buffer = FALSE; + bool expand_buffer = false; validate_maphash(); - /* Do it twice: once for global maps and once for local maps. */ - for (;; ) { - for (hash = 0; hash < 256; ++hash) { + // Do it twice: once for global maps and once for local maps. + for (;;) { + for (hash = 0; hash < 256; hash++) { if (abbr) { - if (hash > 0) /* there is only one abbr list */ + if (hash > 0) { // There is only one abbr list. break; - if (expand_buffer) + } + if (expand_buffer) { mp = curbuf->b_first_abbr; - else + } else { mp = first_abbr; - } else if (expand_buffer) + } + } else if (expand_buffer) { mp = curbuf->b_maphash[hash]; - else + } else { mp = maphash[hash]; + } for (; mp; mp = mp->m_next) { if ((mp->m_mode & mode) - && strstr((char *)mp->m_str, (char *)rhs) != NULL) - return TRUE; + && strstr((char *)mp->m_str, rhs) != NULL) { + return true; + } } } - if (expand_buffer) + if (expand_buffer) { break; - expand_buffer = TRUE; + } + expand_buffer = true; } - return FALSE; + return false; } /* @@ -3618,8 +3593,8 @@ int check_abbr(int c, char_u *ptr, int col, int mincol) char_u *q = mp->m_keys; int match; - if (vim_strbyte(mp->m_keys, K_SPECIAL) != NULL) { - /* might have CSI escaped mp->m_keys */ + if (strchr((const char *)mp->m_keys, K_SPECIAL) != NULL) { + // Might have CSI escaped mp->m_keys. q = vim_strsave(mp->m_keys); vim_unescape_csi(q); qlen = (int)STRLEN(q); @@ -3755,8 +3730,10 @@ eval_map_expr ( */ char_u *vim_strsave_escape_csi(char_u *p) { - /* Need a buffer to hold up to three times as much. */ - char_u *res = xmalloc(STRLEN(p) * 3 + 1); + // 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; for (char_u *s = p; *s != NUL; ) { if (s[0] == K_SPECIAL && s[1] != NUL && s[2] != NUL) { @@ -3765,17 +3742,10 @@ char_u *vim_strsave_escape_csi(char_u *p) *d++ = *s++; *d++ = *s++; } else { - int len = mb_char2len(PTR2CHAR(s)); - int len2 = mb_ptr2len(s); - /* Add character, possibly multi-byte to destination, escaping - * CSI and K_SPECIAL. */ + // Add character, possibly multi-byte to destination, escaping + // CSI and K_SPECIAL. Be careful, it can be an illegal byte! d = add_char2buf(PTR2CHAR(s), d); - while (len < len2) { - /* add following combining char */ - d = add_char2buf(PTR2CHAR(s + len), d); - len += mb_char2len(PTR2CHAR(s + len)); - } - mb_ptr_adv(s); + s += MB_CPTR2LEN(s); } } *d = NUL; @@ -3821,8 +3791,7 @@ makemap ( char *cmd; int abbr; int hash; - int did_cpo = FALSE; - int i; + bool did_cpo = false; validate_maphash(); @@ -3950,13 +3919,15 @@ makemap ( /* When outputting <> form, need to make sure that 'cpo' * is set to the Vim default. */ if (!did_cpo) { - if (*mp->m_str == NUL) /* will use <Nop> */ - did_cpo = TRUE; - else - for (i = 0; i < 2; ++i) - for (p = (i ? mp->m_str : mp->m_keys); *p; ++p) - if (*p == K_SPECIAL || *p == NL) - did_cpo = TRUE; + if (*mp->m_str == NUL) { // Will use <Nop>. + did_cpo = true; + } else { + const char specials[] = { (char)(uint8_t)K_SPECIAL, NL, NUL }; + if (strpbrk((const char *)mp->m_str, specials) != NULL + || strpbrk((const char *)mp->m_keys, specials) != NULL) { + did_cpo = true; + } + } if (did_cpo) { if (fprintf(fd, "let s:cpo_save=&cpo") < 0 || put_eol(fd) < 0 @@ -4024,12 +3995,10 @@ int put_escstr(FILE *fd, char_u *strstart, int what) return OK; } - for (; *str != NUL; ++str) { - char_u *p; - - /* Check for a multi-byte character, which may contain escaped - * K_SPECIAL and CSI bytes */ - p = mb_unescape(&str); + for (; *str != NUL; str++) { + // Check for a multi-byte character, which may contain escaped + // K_SPECIAL and CSI bytes. + const char *p = mb_unescape((const char **)&str); if (p != NULL) { while (*p != NUL) if (fputc(*p++, fd) < 0) @@ -4185,8 +4154,7 @@ void add_map(char_u *map, int mode) } // Translate an internal mapping/abbreviation representation into the -// corresponding external one recognized by :map/:abbrev commands; -// respects the current B/k/< settings of 'cpoption'. +// corresponding external one recognized by :map/:abbrev commands. // // This function is called when expanding mappings/abbreviations on the // command-line, and for building the "Ambiguous mapping..." error message. @@ -4206,7 +4174,6 @@ static char_u * translate_mapping ( ga_init(&ga, 1, 40); bool cpo_bslash = !(cpo_flags&FLAG_CPO_BSLASH); - bool cpo_special = !(cpo_flags&FLAG_CPO_SPECI); for (; *str; ++str) { int c = *str; @@ -4219,7 +4186,7 @@ static char_u * translate_mapping ( } if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) { - if (expmap && cpo_special) { + if (expmap) { ga_clear(&ga); return NULL; } @@ -4230,8 +4197,8 @@ static char_u * translate_mapping ( } str += 2; } - if (IS_SPECIAL(c) || modifiers) { /* special key */ - if (expmap && cpo_special) { + if (IS_SPECIAL(c) || modifiers) { // special key + if (expmap) { ga_clear(&ga); return NULL; } @@ -4241,7 +4208,7 @@ static char_u * translate_mapping ( } if (c == ' ' || c == '\t' || c == Ctrl_J || c == Ctrl_V - || (c == '<' && !cpo_special) || (c == '\\' && !cpo_bslash)) { + || (c == '\\' && !cpo_bslash)) { ga_append(&ga, cpo_bslash ? Ctrl_V : '\\'); } @@ -4263,3 +4230,17 @@ static bool typebuf_match_len(const uint8_t *str, int *mlen) *mlen = i; return str[i] == NUL; // matched the whole string } + +/// Retrieve the mapblock at the index either globally or for a certain buffer +/// +/// @param index The index in the maphash[] +/// @param buf The buffer to get the maphash from. NULL for global +mapblock_T *get_maphash(int index, buf_T *buf) + FUNC_ATTR_PURE +{ + if (index > MAX_MAPHASH) { + return NULL; + } + + return (buf == NULL) ? maphash[index] : buf->b_maphash[index]; +} diff --git a/src/nvim/getchar.h b/src/nvim/getchar.h index bdf65909b6..e634273e0d 100644 --- a/src/nvim/getchar.h +++ b/src/nvim/getchar.h @@ -1,17 +1,25 @@ #ifndef NVIM_GETCHAR_H #define NVIM_GETCHAR_H -/* Values for "noremap" argument of ins_typebuf(). Also used for - * map->m_noremap and menu->noremap[]. */ -#define REMAP_YES 0 /* allow remapping */ -#define REMAP_NONE -1 /* no remapping */ -#define REMAP_SCRIPT -2 /* remap script-local mappings only */ -#define REMAP_SKIP -3 /* no remapping for first char */ +#include "nvim/types.h" +#include "nvim/buffer_defs.h" +#include "nvim/ex_cmds_defs.h" + +/// Values for "noremap" argument of ins_typebuf(). Also used for +/// map->m_noremap and menu->noremap[]. +/// @addtogroup REMAP_VALUES +/// @{ +#define REMAP_YES 0 ///< allow remapping +#define REMAP_NONE -1 ///< no remapping +#define REMAP_SCRIPT -2 ///< remap script-local mappings only +#define REMAP_SKIP -3 ///< no remapping for first char +/// @} #define KEYLEN_PART_KEY -1 /* keylen value for incomplete key-code */ #define KEYLEN_PART_MAP -2 /* keylen value for incomplete mapping */ #define KEYLEN_REMOVED 9999 /* keylen value for removed sequence */ + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "getchar.h.generated.h" #endif diff --git a/src/nvim/gettext.h b/src/nvim/gettext.h new file mode 100644 index 0000000000..aa0e97233e --- /dev/null +++ b/src/nvim/gettext.h @@ -0,0 +1,21 @@ +#ifndef NVIM_GETTEXT_H +#define NVIM_GETTEXT_H + +#ifdef HAVE_WORKING_LIBINTL +# include <libintl.h> +# define _(x) gettext((char *)(x)) +// XXX do we actually need this? +# ifdef gettext_noop +# define N_(x) gettext_noop(x) +# else +# define N_(x) x +# endif +#else +# define _(x) ((char *)(x)) +# define N_(x) x +# define bindtextdomain(x, y) // empty +# define bind_textdomain_codeset(x, y) // empty +# define textdomain(x) // empty +#endif + +#endif // NVIM_GETTEXT_H diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 463f4fcd8d..2ee72cdb6a 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -12,10 +12,7 @@ #include "nvim/syntax_defs.h" #include "nvim/types.h" #include "nvim/event/loop.h" - -/* - * definition of global variables - */ +#include "nvim/os/os_defs.h" #define IOSIZE (1024+1) // file I/O and sprintf buffer size @@ -25,19 +22,6 @@ # define MSG_BUF_CLEN (MSG_BUF_LEN / 6) // cell length (worst case: utf-8 // takes 6 bytes for one cell) -/* - * Maximum length of a path (for non-unix systems) Make it a bit long, to stay - * on the safe side. But not too long to put on the stack. - * TODO(metrix78): Move this to os_defs.h - */ -#ifndef MAXPATHL -# ifdef MAXPATHLEN -# define MAXPATHL MAXPATHLEN -# else -# define MAXPATHL 256 -# endif -#endif - #ifdef WIN32 # define _PATHSEPSTR "\\" #else @@ -108,14 +92,39 @@ typedef enum { * They may have different values when the screen wasn't (re)allocated yet * after setting Rows or Columns (e.g., when starting up). */ - -#define DFLT_COLS 80 /* default value for 'columns' */ -#define DFLT_ROWS 24 /* default value for 'lines' */ - +#define DFLT_COLS 80 // default value for 'columns' +#define DFLT_ROWS 24 // default value for 'lines' EXTERN long Rows INIT(= DFLT_ROWS); // nr of rows in the screen - EXTERN long Columns INIT(= DFLT_COLS); // nr of columns in the screen +// We use 64-bit file functions here, if available. E.g. ftello() returns +// off_t instead of long, which helps if long is 32 bit and off_t is 64 bit. +// We assume that when fseeko() is available then ftello() is too. +// Note that Windows has different function names. +#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__MINGW32__) +typedef __int64 off_T; +# ifdef __MINGW32__ +# define vim_lseek lseek64 +# define vim_fseek fseeko64 +# define vim_ftell ftello64 +# else +# define vim_lseek _lseeki64 +# define vim_fseek _fseeki64 +# define vim_ftell _ftelli64 +# endif +#else +typedef off_t off_T; +# ifdef HAVE_FSEEKO +# define vim_lseek lseek +# define vim_ftell ftello +# define vim_fseek fseeko +# else +# define vim_lseek lseek +# define vim_ftell ftell +# define vim_fseek(a, b, c) fseek(a, (long)b, c) +# endif +#endif + /* * The characters and attributes cached for the screen. */ @@ -398,6 +407,9 @@ EXTERN int garbage_collect_at_exit INIT(= FALSE); /* ID of script being sourced or was sourced to define the current function. */ EXTERN scid_T current_SID INIT(= 0); + +EXTERN bool did_source_packages INIT(= false); + // Scope information for the code that indirectly triggered the current // provider function call EXTERN struct caller_scope { @@ -430,79 +442,6 @@ EXTERN int did_check_timestamps INIT(= FALSE); /* did check timestamps recently */ EXTERN int no_check_timestamps INIT(= 0); /* Don't check timestamps */ -/* - * Values for index in highlight_attr[]. - * When making changes, also update HL_FLAGS below! And update the default - * value of 'highlight' in option.c. - */ -typedef enum { - HLF_8 = 0 /* Meta & special keys listed with ":map", text that is - displayed different from what it is */ - , HLF_EOB // after the last line in the buffer - , HLF_TERM // terminal cursor focused - , HLF_TERMNC // terminal cursor unfocused - , HLF_AT // @ characters at end of screen, characters that - // don't really exist in the text - , HLF_D // directories in CTRL-D listing - , HLF_E // error messages - , HLF_I // incremental search - , HLF_L // last search string - , HLF_M // "--More--" message - , HLF_CM // Mode (e.g., "-- INSERT --") - , HLF_N // line number for ":number" and ":#" commands - , HLF_CLN // current line number - , HLF_R // return to continue message and yes/no questions - , HLF_S // status lines - , HLF_SNC // status lines of not-current windows - , HLF_C // column to separate vertically split windows - , HLF_T // Titles for output from ":set all", ":autocmd" etc. - , HLF_V // Visual mode - , HLF_VNC // Visual mode, autoselecting and not clipboard owner - , HLF_W // warning messages - , HLF_WM // Wildmenu highlight - , HLF_FL // Folded line - , HLF_FC // Fold column - , HLF_ADD // Added diff line - , HLF_CHD // Changed diff line - , HLF_DED // Deleted diff line - , HLF_TXD // Text Changed in diff line - , HLF_CONCEAL // Concealed text - , HLF_SC // Sign column - , HLF_SPB // SpellBad - , HLF_SPC // SpellCap - , HLF_SPR // SpellRare - , HLF_SPL // SpellLocal - , HLF_PNI // popup menu normal item - , HLF_PSI // popup menu selected item - , HLF_PSB // popup menu scrollbar - , HLF_PST // popup menu scrollbar thumb - , HLF_TP // tabpage line - , HLF_TPS // tabpage line selected - , HLF_TPF // tabpage line filler - , HLF_CUC // 'cursurcolumn' - , HLF_CUL // 'cursurline' - , HLF_MC // 'colorcolumn' - , HLF_QFL // selected quickfix line - , HLF_COUNT // MUST be the last one -} hlf_T; - -/* The HL_FLAGS must be in the same order as the HLF_ enums! - * When changing this also adjust the default for 'highlight'. */ -#define HL_FLAGS { '8', '~', 'z', 'Z', '@', 'd', 'e', 'i', 'l', 'm', 'M', 'n', \ - 'N', 'r', 's', 'S', 'c', 't', 'v', 'V', 'w', 'W', 'f', 'F', \ - 'A', 'C', 'D', 'T', '-', '>', 'B', 'P', 'R', 'L', '+', '=', \ - 'x', 'X', '*', '#', '_', '!', '.', 'o', 'q' } - -EXTERN int highlight_attr[HLF_COUNT]; /* Highl. attr for each context. */ -EXTERN int highlight_user[9]; /* User[1-9] attributes */ -EXTERN int highlight_stlnc[9]; /* On top of user */ -EXTERN int cterm_normal_fg_color INIT(= 0); -EXTERN int cterm_normal_fg_bold INIT(= 0); -EXTERN int cterm_normal_bg_color INIT(= 0); -EXTERN RgbValue normal_fg INIT(= -1); -EXTERN RgbValue normal_bg INIT(= -1); -EXTERN RgbValue normal_sp INIT(= -1); - EXTERN int autocmd_busy INIT(= FALSE); /* Is apply_autocmds() busy? */ EXTERN int autocmd_no_enter INIT(= FALSE); /* *Enter autocmds disabled */ EXTERN int autocmd_no_leave INIT(= FALSE); /* *Leave autocmds disabled */ @@ -512,9 +451,9 @@ EXTERN int keep_filetype INIT(= FALSE); /* value for did_filetype when starting to execute autocommands */ -/* When deleting the current buffer, another one must be loaded. If we know - * which one is preferred, au_new_curbuf is set to it */ -EXTERN buf_T *au_new_curbuf INIT(= NULL); +// When deleting the current buffer, another one must be loaded. +// If we know which one is preferred, au_new_curbuf is set to it. +EXTERN bufref_T au_new_curbuf INIT(= { NULL, 0, 0 }); // When deleting a buffer/window and autocmd_busy is TRUE, do not free the // buffer/window. but link it in the list starting with @@ -558,6 +497,7 @@ EXTERN int updating_screen INIT(= FALSE); EXTERN win_T *firstwin; /* first window */ EXTERN win_T *lastwin; /* last window */ EXTERN win_T *prevwin INIT(= NULL); /* previous window */ +# define ONE_WINDOW (firstwin == lastwin) /* * When using this macro "break" only breaks out of the inner loop. Use "goto" * to break out of the tabpage loop. @@ -566,7 +506,7 @@ EXTERN win_T *prevwin INIT(= NULL); /* previous window */ FOR_ALL_TABS(tp) \ FOR_ALL_WINDOWS_IN_TAB(wp, tp) -# define FOR_ALL_WINDOWS(wp) for (wp = firstwin; wp != NULL; wp = wp->w_next) +// -V:FOR_ALL_WINDOWS_IN_TAB:501 # define FOR_ALL_WINDOWS_IN_TAB(wp, tp) \ for (win_T *wp = ((tp) == curtab) \ ? firstwin : (tp)->tp_firstwin; wp != NULL; wp = wp->w_next) @@ -602,7 +542,10 @@ EXTERN buf_T *lastbuf INIT(= NULL); // last buffer EXTERN buf_T *curbuf INIT(= NULL); // currently active buffer // Iterates over all buffers in the buffer list. -# define FOR_ALL_BUFFERS(buf) for (buf_T *buf = firstbuf; buf != NULL; buf = buf->b_next) +#define FOR_ALL_BUFFERS(buf) \ + for (buf_T *buf = firstbuf; buf != NULL; buf = buf->b_next) +#define FOR_ALL_BUFFERS_BACKWARDS(buf) \ + for (buf_T *buf = lastbuf; buf != NULL; buf = buf->b_prev) /* Flag that is set when switching off 'swapfile'. It means that all blocks * are to be loaded into memory. Shouldn't be global... */ @@ -840,13 +783,11 @@ EXTERN int ex_no_reprint INIT(= FALSE); /* no need to print after z or p */ EXTERN int Recording INIT(= FALSE); /* TRUE when recording into a reg. */ EXTERN int Exec_reg INIT(= FALSE); /* TRUE when executing a register */ -EXTERN int no_mapping INIT(= FALSE); /* currently no mapping allowed */ -EXTERN int no_zero_mapping INIT(= 0); /* mapping zero not allowed */ -EXTERN int allow_keys INIT(= FALSE); /* allow key codes when no_mapping - * is set */ -EXTERN int no_u_sync INIT(= 0); /* Don't call u_sync() */ -EXTERN int u_sync_once INIT(= 0); /* Call u_sync() once when evaluating - an expression. */ +EXTERN int no_mapping INIT(= false); // currently no mapping allowed +EXTERN int no_zero_mapping INIT(= 0); // mapping zero not allowed +EXTERN int no_u_sync INIT(= 0); // Don't call u_sync() +EXTERN int u_sync_once INIT(= 0); // Call u_sync() once when evaluating + // an expression. EXTERN bool force_restart_edit INIT(= false); // force restart_edit after // ex_normal returns @@ -886,9 +827,16 @@ EXTERN int swap_exists_action INIT(= SEA_NONE); EXTERN int swap_exists_did_quit INIT(= FALSE); /* Selected "quit" at the dialog. */ -EXTERN char_u IObuff[IOSIZE]; /* sprintf's are done in this buffer */ -EXTERN char_u NameBuff[MAXPATHL]; /* buffer for expanding file names */ -EXTERN char_u msg_buf[MSG_BUF_LEN]; /* small buffer for messages */ +EXTERN char_u IObuff[IOSIZE]; ///< Buffer for sprintf, I/O, etc. +EXTERN char_u NameBuff[MAXPATHL]; ///< Buffer for expanding file names +EXTERN char_u msg_buf[MSG_BUF_LEN]; ///< Small buffer for messages +EXTERN char os_buf[ ///< Buffer for the os/ layer +#if MAXPATHL > IOSIZE +MAXPATHL +#else +IOSIZE +#endif +]; /* When non-zero, postpone redrawing. */ EXTERN int RedrawingDisabled INIT(= 0); @@ -953,7 +901,7 @@ EXTERN int did_cursorhold INIT(= false); // set when CursorHold t'gerd // for CursorMoved event EXTERN pos_T last_cursormoved INIT(= INIT_POS_T(0, 0, 0)); -EXTERN int last_changedtick INIT(= 0); // for TextChanged event +EXTERN varnumber_T last_changedtick INIT(= 0); // for TextChanged event EXTERN buf_T *last_changedtick_buf INIT(= NULL); EXTERN int postponed_split INIT(= 0); /* for CTRL-W CTRL-] command */ @@ -986,8 +934,11 @@ EXTERN char_u langmap_mapchar[256]; /* mapping for language keys */ EXTERN int save_p_ls INIT(= -1); /* Save 'laststatus' setting */ EXTERN int save_p_wmh INIT(= -1); /* Save 'winminheight' setting */ EXTERN int wild_menu_showing INIT(= 0); -# define WM_SHOWN 1 /* wildmenu showing */ -# define WM_SCROLLED 2 /* wildmenu showing with scroll */ +enum { + WM_SHOWN = 1, ///< wildmenu showing + WM_SCROLLED = 2, ///< wildmenu showing with scroll + WM_LIST = 3, ///< cmdline CTRL-D +}; EXTERN char breakat_flags[256]; /* which characters are in 'breakat' */ @@ -1124,7 +1075,7 @@ EXTERN char_u e_isadir2[] INIT(= N_("E17: \"%s\" is a directory")); EXTERN char_u e_invjob[] INIT(= N_("E900: Invalid job id")); EXTERN char_u e_jobtblfull[] INIT(= N_("E901: Job table is full")); EXTERN char_u e_jobspawn[] INIT(= N_( - "E903: Process for command \"%s\" could not be spawned")); + "E903: Process failed to start: %s: \"%s\"")); EXTERN char_u e_jobnotpty[] INIT(= N_("E904: Job is not connected to a pty")); EXTERN char_u e_libcall[] INIT(= N_("E364: Library call failed for \"%s()\"")); EXTERN char_u e_mkdir[] INIT(= N_("E739: Cannot create directory %s: %s")); @@ -1150,7 +1101,6 @@ EXTERN char_u e_noprev[] INIT(= N_("E34: No previous command")); EXTERN char_u e_noprevre[] INIT(= N_("E35: No previous regular expression")); EXTERN char_u e_norange[] INIT(= N_("E481: No range allowed")); EXTERN char_u e_noroom[] INIT(= N_("E36: Not enough room")); -EXTERN char_u e_notcreate[] INIT(= N_("E482: Can't create file %s")); EXTERN char_u e_notmp[] INIT(= N_("E483: Can't get temp file name")); EXTERN char_u e_notopen[] INIT(= N_("E484: Can't open file %s")); EXTERN char_u e_notread[] INIT(= N_("E485: Can't read file %s")); @@ -1172,11 +1122,7 @@ EXTERN char_u e_loclist[] INIT(= N_("E776: No location list")); EXTERN char_u e_re_damg[] INIT(= N_("E43: Damaged match string")); EXTERN char_u e_re_corr[] INIT(= N_("E44: Corrupted regexp program")); EXTERN char_u e_readonly[] INIT(= N_( - "E45: 'readonly' option is set (add ! to override)")); -EXTERN char_u e_readonlyvar[] INIT(= N_( - "E46: Cannot change read-only variable \"%s\"")); -EXTERN char_u e_readonlysbx[] INIT(= N_( - "E794: Cannot set variable in the sandbox: \"%s\"")); + "E45: 'readonly' option is set (add ! to override)")); EXTERN char_u e_readerrf[] INIT(= N_("E47: Error while reading errorfile")); EXTERN char_u e_sandbox[] INIT(= N_("E48: Not allowed in sandbox")); EXTERN char_u e_secure[] INIT(= N_("E523: Not allowed here")); @@ -1192,6 +1138,7 @@ EXTERN char_u e_longname[] INIT(= N_("E75: Name too long")); EXTERN char_u e_toomsbra[] INIT(= N_("E76: Too many [")); EXTERN char_u e_toomany[] INIT(= N_("E77: Too many file names")); EXTERN char_u e_trailing[] INIT(= N_("E488: Trailing characters")); +EXTERN char_u e_trailing2[] INIT(= N_("E488: Trailing characters: %s")); EXTERN char_u e_umark[] INIT(= N_("E78: Unknown mark")); EXTERN char_u e_wildexpand[] INIT(= N_("E79: Cannot expand wildcards")); EXTERN char_u e_winheight[] INIT(= N_( @@ -1215,6 +1162,8 @@ EXTERN char_u e_invalidreg[] INIT(= N_("E850: Invalid register name")); EXTERN char_u e_dirnotf[] INIT(= N_( "E919: Directory not found in '%s': \"%s\"")); EXTERN char_u e_unsupportedoption[] INIT(= N_("E519: Option not supported")); +EXTERN char_u e_fnametoolong[] INIT(= N_("E856: Filename too long")); +EXTERN char_u e_float_as_string[] INIT(= N_("E806: using Float as a String")); EXTERN char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM")); @@ -1233,8 +1182,6 @@ EXTERN FILE *time_fd INIT(= NULL); /* where to write startup timing */ EXTERN int ignored; EXTERN char *ignoredp; -EXTERN bool in_free_unref_items INIT(= false); - // If a msgpack-rpc channel should be started over stdin/stdout EXTERN bool embedded_mode INIT(= false); @@ -1249,4 +1196,20 @@ typedef enum { kBroken } WorkingStatus; +/// The scope of a working-directory command like `:cd`. +/// +/// Scopes are enumerated from lowest to highest. When adding a scope make sure +/// to update all functions using scopes as well, such as the implementation of +/// `getcwd()`. When using scopes as limits (e.g. in loops) don't use the scopes +/// directly, use `MIN_CD_SCOPE` and `MAX_CD_SCOPE` instead. +typedef enum { + kCdScopeInvalid = -1, + kCdScopeWindow, ///< Affects one window. + kCdScopeTab, ///< Affects one tab page. + kCdScopeGlobal, ///< Affects the entire Nvim instance. +} CdScope; + +#define MIN_CD_SCOPE kCdScopeWindow +#define MAX_CD_SCOPE kCdScopeGlobal + #endif /* NVIM_GLOBALS_H */ diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c index cb0415a486..abc4773d84 100644 --- a/src/nvim/hardcopy.c +++ b/src/nvim/hardcopy.c @@ -1,3 +1,6 @@ +// 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 + /* * hardcopy.c: printing to paper */ @@ -369,7 +372,6 @@ static void prt_get_attr(int hl_id, prt_text_attr_T *pattr, int modec) { int colorindex; uint32_t fg_color; - char *color; pattr->bold = (highlight_has_attr(hl_id, HL_BOLD, modec) != NULL); pattr->italic = (highlight_has_attr(hl_id, HL_ITALIC, modec) != NULL); @@ -377,11 +379,12 @@ static void prt_get_attr(int hl_id, prt_text_attr_T *pattr, int modec) pattr->undercurl = (highlight_has_attr(hl_id, HL_UNDERCURL, modec) != NULL); { - color = (char *)highlight_color(hl_id, (char_u *)"fg", modec); - if (color == NULL) + const char *color = highlight_color(hl_id, "fg", modec); + if (color == NULL) { colorindex = 0; - else + } else { colorindex = atoi(color); + } if (colorindex >= 0 && colorindex < t_colors) fg_color = prt_get_term_color(colorindex); @@ -845,12 +848,10 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T * Loop over the columns until the end of the file line or right margin. */ for (col = ppos->column; line[col] != NUL && !need_break; col += outputlen) { - outputlen = 1; - if (has_mbyte && (outputlen = (*mb_ptr2len)(line + col)) < 1) + if ((outputlen = (*mb_ptr2len)(line + col)) < 1) { outputlen = 1; - /* - * syntax highlighting stuff. - */ + } + // syntax highlighting stuff. if (psettings->do_syntax) { id = syn_get_id(curwin, ppos->file_line, col, 1, NULL, FALSE); if (id > 0) @@ -1544,8 +1545,8 @@ static int prt_find_resource(char *name, struct prt_ps_resource_S *resource) /* Look for named resource file in runtimepath */ STRCPY(buffer, "print"); add_pathsep((char *)buffer); - vim_strcat(buffer, (char_u *)name, MAXPATHL); - vim_strcat(buffer, (char_u *)".ps", MAXPATHL); + xstrlcat((char *)buffer, name, MAXPATHL); + xstrlcat((char *)buffer, ".ps", MAXPATHL); resource->filename[0] = NUL; retval = (do_in_runtimepath(buffer, 0, prt_resource_name, resource->filename) && resource->filename[0] != NUL); @@ -2578,13 +2579,12 @@ int mch_print_begin(prt_settings_T *psettings) prt_conv.vc_type = CONV_NONE; if (!(enc_canon_props(p_enc) & enc_canon_props(p_encoding) & ENC_8BIT)) { - /* Set up encoding conversion if required */ - if (FAIL == convert_setup(&prt_conv, p_enc, p_encoding)) { - EMSG2(_("E620: Unable to convert to print encoding \"%s\""), - p_encoding); - return FALSE; + // Set up encoding conversion if required + if (convert_setup(&prt_conv, p_enc, p_encoding) == FAIL) { + emsgf(_("E620: Unable to convert to print encoding \"%s\""), + p_encoding); + return false; } - prt_do_conv = TRUE; } prt_do_conv = prt_conv.vc_type != CONV_NONE; diff --git a/src/nvim/hardcopy.h b/src/nvim/hardcopy.h index 4ead8dd5d4..a70b20e6f5 100644 --- a/src/nvim/hardcopy.h +++ b/src/nvim/hardcopy.h @@ -2,6 +2,10 @@ #define NVIM_HARDCOPY_H #include <stdint.h> +#include <stdlib.h> // for size_t + +#include "nvim/types.h" // for char_u +#include "nvim/ex_cmds_defs.h" // for exarg_T /* * Structure to hold printing color and font attributes. diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c index 376f33e23e..3397788b00 100644 --- a/src/nvim/hashtab.c +++ b/src/nvim/hashtab.c @@ -1,3 +1,6 @@ +// 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 + /// @file hashtab.c /// /// Handling of a hashtable with Vim-specific properties. @@ -82,22 +85,43 @@ void hash_clear_all(hashtab_T *ht, unsigned int off) /// used for that key. /// WARNING: Returned pointer becomes invalid as soon as the hash table /// is changed in any way. -hashitem_T* hash_find(hashtab_T *ht, char_u *key) +hashitem_T *hash_find(const hashtab_T *const ht, const char_u *const key) { - return hash_lookup(ht, key, hash_hash(key)); + return hash_lookup(ht, (const char *)key, STRLEN(key), hash_hash(key)); +} + +/// Like hash_find, but key is not NUL-terminated +/// +/// @param[in] ht Hashtab to look in. +/// @param[in] key Key of the looked-for item. Must not be NULL. +/// @param[in] len Key length. +/// +/// @return Pointer to the hash item corresponding to the given key. +/// If not found, then return pointer to the empty item that would be +/// used for that key. +/// +/// @warning Returned pointer becomes invalid as soon as the hash table +/// is changed in any way. +hashitem_T *hash_find_len(const hashtab_T *const ht, const char *const key, + const size_t len) +{ + return hash_lookup(ht, key, len, hash_hash_len(key, len)); } /// Like hash_find(), but caller computes "hash". /// -/// @param key The key of the looked-for item. Must not be NULL. -/// @param hash The precomputed hash for the key. +/// @param[in] key The key of the looked-for item. Must not be NULL. +/// @param[in] key_len Key length. +/// @param[in] hash The precomputed hash for the key. /// /// @return Pointer to the hashitem corresponding to the given key. /// If not found, then return pointer to the empty item that would be /// used for that key. /// WARNING: Returned pointer becomes invalid as soon as the hash table /// is changed in any way. -hashitem_T* hash_lookup(hashtab_T *ht, char_u *key, hash_T hash) +hashitem_T *hash_lookup(const hashtab_T *const ht, + const char *const key, const size_t key_len, + const hash_T hash) { #ifdef HT_DEBUG hash_count_lookup++; @@ -117,7 +141,9 @@ hashitem_T* hash_lookup(hashtab_T *ht, char_u *key, hash_T hash) hashitem_T *freeitem = NULL; if (hi->hi_key == HI_KEY_REMOVED) { freeitem = hi; - } else if ((hi->hi_hash == hash) && (STRCMP(hi->hi_key, key) == 0)) { + } else if ((hi->hi_hash == hash) + && (STRNCMP(hi->hi_key, key, key_len) == 0) + && hi->hi_key[key_len] == NUL) { return hi; } @@ -142,7 +168,8 @@ hashitem_T* hash_lookup(hashtab_T *ht, char_u *key, hash_T hash) if ((hi->hi_hash == hash) && (hi->hi_key != HI_KEY_REMOVED) - && (STRCMP(hi->hi_key, key) == 0)) { + && (STRNCMP(hi->hi_key, key, key_len) == 0) + && hi->hi_key[key_len] == NUL) { return hi; } @@ -179,7 +206,7 @@ void hash_debug_results(void) int hash_add(hashtab_T *ht, char_u *key) { hash_T hash = hash_hash(key); - hashitem_T *hi = hash_lookup(ht, key, hash); + hashitem_T *hi = hash_lookup(ht, (const char *)key, STRLEN(key), hash); if (!HASHITEM_EMPTY(hi)) { EMSG2(_(e_intern2), "hash_add()"); return FAIL; @@ -359,13 +386,16 @@ static void hash_may_resize(hashtab_T *ht, size_t minitems) ht->ht_filled = ht->ht_used; } +#define HASH_CYCLE_BODY(hash, p) \ + hash = hash * 101 + *p++ + /// Get the hash number for a key. /// /// If you think you know a better hash function: Compile with HT_DEBUG set and /// 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(char_u *key) +hash_T hash_hash(const char_u *key) { hash_T hash = *key; @@ -375,14 +405,43 @@ hash_T hash_hash(char_u *key) // A simplistic algorithm that appears to do very well. // Suggested by George Reilly. - char_u *p = key + 1; + const uint8_t *p = key + 1; while (*p != NUL) { - hash = hash * 101 + *p++; + HASH_CYCLE_BODY(hash, p); + } + + return hash; +} + +/// Get the hash number for a key that is not a NUL-terminated string +/// +/// @warning Function does not check whether key contains NUL. But you will not +/// be able to get hash entry in this case. +/// +/// @param[in] key Key. +/// @param[in] len Key length. +/// +/// @return Key hash. +hash_T hash_hash_len(const char *key, const size_t len) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (len == 0) { + return 0; + } + + hash_T hash = *(uint8_t *)key; + const uint8_t *end = (uint8_t *)key + len; + + const uint8_t *p = (const uint8_t *)key + 1; + while (p < end) { + HASH_CYCLE_BODY(hash, p); } return hash; } +#undef HASH_CYCLE_BODY + /// Function to get HI_KEY_REMOVED value /// /// Used for testing because luajit ffi does not allow getting addresses of diff --git a/src/nvim/hashtab.h b/src/nvim/hashtab.h index 0da2b13f2e..973b97d476 100644 --- a/src/nvim/hashtab.h +++ b/src/nvim/hashtab.h @@ -70,6 +70,25 @@ typedef struct hashtable_S { hashitem_T ht_smallarray[HT_INIT_SIZE]; /// initial array } hashtab_T; +/// Iterate over a hashtab +/// +/// @param[in] ht Hashtab to iterate over. +/// @param hi Name of the variable with current hashtab entry. +/// @param code Cycle body. +#define HASHTAB_ITER(ht, hi, code) \ + do { \ + hashtab_T *const hi##ht_ = (ht); \ + size_t hi##todo_ = hi##ht_->ht_used; \ + for (hashitem_T *hi = hi##ht_->ht_array; hi##todo_; hi++) { \ + if (!HASHITEM_EMPTY(hi)) { \ + { \ + code \ + } \ + hi##todo_--; \ + } \ + } \ + } while (0) + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "hashtab.h.generated.h" #endif diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h new file mode 100644 index 0000000000..927fc94bbe --- /dev/null +++ b/src/nvim/highlight_defs.h @@ -0,0 +1,126 @@ +#ifndef NVIM_HIGHLIGHT_DEFS_H +#define NVIM_HIGHLIGHT_DEFS_H + +#include <inttypes.h> + +#include "nvim/macros.h" + +typedef int32_t RgbValue; + +/// Values for index in highlight_attr[]. +/// When making changes, also update hlf_names below! +typedef enum { + HLF_8 = 0 // Meta & special keys listed with ":map", text that is + // displayed different from what it is + , HLF_EOB // after the last line in the buffer + , HLF_TERM // terminal cursor focused + , HLF_TERMNC // terminal cursor unfocused + , HLF_AT // @ characters at end of screen, characters that + // don't really exist in the text + , HLF_D // directories in CTRL-D listing + , HLF_E // error messages + , HLF_I // incremental search + , HLF_L // last search string + , HLF_M // "--More--" message + , HLF_CM // Mode (e.g., "-- INSERT --") + , HLF_N // line number for ":number" and ":#" commands + , HLF_CLN // current line number + , HLF_R // return to continue message and yes/no questions + , HLF_S // status lines + , HLF_SNC // status lines of not-current windows + , HLF_C // column to separate vertically split windows + , HLF_T // Titles for output from ":set all", ":autocmd" etc. + , HLF_V // Visual mode + , HLF_VNC // Visual mode, autoselecting and not clipboard owner + , HLF_W // warning messages + , HLF_WM // Wildmenu highlight + , HLF_FL // Folded line + , HLF_FC // Fold column + , HLF_ADD // Added diff line + , HLF_CHD // Changed diff line + , HLF_DED // Deleted diff line + , HLF_TXD // Text Changed in diff line + , HLF_SC // Sign column + , HLF_CONCEAL // Concealed text + , HLF_SPB // SpellBad + , HLF_SPC // SpellCap + , HLF_SPR // SpellRare + , HLF_SPL // SpellLocal + , HLF_PNI // popup menu normal item + , HLF_PSI // popup menu selected item + , HLF_PSB // popup menu scrollbar + , HLF_PST // popup menu scrollbar thumb + , HLF_TP // tabpage line + , HLF_TPS // tabpage line selected + , HLF_TPF // tabpage line filler + , HLF_CUC // 'cursurcolumn' + , HLF_CUL // 'cursurline' + , HLF_MC // 'colorcolumn' + , HLF_QFL // selected quickfix line + , HLF_0 // Whitespace + , HLF_INACTIVE // NormalNC: Normal text in non-current windows + , HLF_COUNT // MUST be the last one +} hlf_T; + +EXTERN const char *hlf_names[] INIT(= { + [HLF_8] = "SpecialKey", + [HLF_EOB] = "EndOfBuffer", + [HLF_TERM] = "TermCursor", + [HLF_TERMNC] = "TermCursorNC", + [HLF_AT] = "NonText", + [HLF_D] = "Directory", + [HLF_E] = "ErrorMsg", + [HLF_I] = "IncSearch", + [HLF_L] = "Search", + [HLF_M] = "MoreMsg", + [HLF_CM] = "ModeMsg", + [HLF_N] = "LineNr", + [HLF_CLN] = "CursorLineNr", + [HLF_R] = "Question", + [HLF_S] = "StatusLine", + [HLF_SNC] = "StatusLineNC", + [HLF_C] = "VertSplit", + [HLF_T] = "Title", + [HLF_V] = "Visual", + [HLF_VNC] = "VisualNC", + [HLF_W] = "WarningMsg", + [HLF_WM] = "WildMenu", + [HLF_FL] = "Folded", + [HLF_FC] = "FoldColumn", + [HLF_ADD] = "DiffAdd", + [HLF_CHD] = "DiffChange", + [HLF_DED] = "DiffDelete", + [HLF_TXD] = "DiffText", + [HLF_SC] = "SignColumn", + [HLF_CONCEAL] = "Conceal", + [HLF_SPB] = "SpellBad", + [HLF_SPC] = "SpellCap", + [HLF_SPR] = "SpellRare", + [HLF_SPL] = "SpellLocal", + [HLF_PNI] = "Pmenu", + [HLF_PSI] = "PmenuSel", + [HLF_PSB] = "PmenuSbar", + [HLF_PST] = "PmenuThumb", + [HLF_TP] = "TabLine", + [HLF_TPS] = "TabLineSel", + [HLF_TPF] = "TabLineFill", + [HLF_CUC] = "CursorColumn", + [HLF_CUL] = "CursorLine", + [HLF_MC] = "ColorColumn", + [HLF_QFL] = "QuickFixLine", + [HLF_0] = "Whitespace", + [HLF_INACTIVE] = "NormalNC" +}); + + +EXTERN int highlight_attr[HLF_COUNT]; // Highl. attr for each context. +EXTERN int highlight_user[9]; // User[1-9] attributes +EXTERN int highlight_stlnc[9]; // On top of user +EXTERN int cterm_normal_fg_color INIT(= 0); +EXTERN int cterm_normal_fg_bold INIT(= 0); +EXTERN int cterm_normal_bg_color INIT(= 0); +EXTERN RgbValue normal_fg INIT(= -1); +EXTERN RgbValue normal_bg INIT(= -1); +EXTERN RgbValue normal_sp INIT(= -1); + +#endif // NVIM_HIGHLIGHT_DEFS_H diff --git a/src/nvim/iconv.h b/src/nvim/iconv.h index bf29b15247..d7234090c4 100644 --- a/src/nvim/iconv.h +++ b/src/nvim/iconv.h @@ -10,9 +10,7 @@ // USE_ICONV, or to put the USE_ICONV definition in config.h.in directly. As // it stands, globals.h needs to be included alongside iconv.h. -#ifdef HAVE_CONFIG_H -# include "auto/config.h" -#endif +#include "auto/config.h" // Use iconv() when it's available, either by linking to the library at // compile time or by loading it at runtime. diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c index 0b20647771..0f9ecdf2d7 100644 --- a/src/nvim/if_cscope.c +++ b/src/nvim/if_cscope.c @@ -1,3 +1,6 @@ +// 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 + /* * CSCOPE support for Vim added by Andy Kahn <kahn@zk3.dec.com> * Ported to Win32 by Sergey Khorev <sergey.khorev@gmail.com> @@ -140,44 +143,39 @@ char_u *get_cscope_name(expand_T *xp, int idx) /* * Handle command line completion for :cscope command. */ -void set_context_in_cscope_cmd(expand_T *xp, char_u *arg, cmdidx_T cmdidx) +void set_context_in_cscope_cmd(expand_T *xp, const char *arg, cmdidx_T cmdidx) { - char_u *p; - - /* Default: expand subcommands */ + // Default: expand subcommands. xp->xp_context = EXPAND_CSCOPE; - xp->xp_pattern = arg; - expand_what = (cmdidx == CMD_scscope) - ? EXP_SCSCOPE_SUBCMD : EXP_CSCOPE_SUBCMD; + xp->xp_pattern = (char_u *)arg; + expand_what = ((cmdidx == CMD_scscope) + ? EXP_SCSCOPE_SUBCMD : EXP_CSCOPE_SUBCMD); /* (part of) subcommand already typed */ if (*arg != NUL) { - p = skiptowhite(arg); - if (*p != NUL) { /* past first word */ - xp->xp_pattern = skipwhite(p); - if (*skiptowhite(xp->xp_pattern) != NUL) + const char *p = (const char *)skiptowhite((const char_u *)arg); + if (*p != NUL) { // Past first word. + xp->xp_pattern = skipwhite((const char_u *)p); + if (*skiptowhite(xp->xp_pattern) != NUL) { xp->xp_context = EXPAND_NOTHING; - else if (STRNICMP(arg, "add", p - arg) == 0) + } else if (STRNICMP(arg, "add", p - arg) == 0) { xp->xp_context = EXPAND_FILES; - else if (STRNICMP(arg, "kill", p - arg) == 0) + } else if (STRNICMP(arg, "kill", p - arg) == 0) { expand_what = EXP_CSCOPE_KILL; - else if (STRNICMP(arg, "find", p - arg) == 0) + } else if (STRNICMP(arg, "find", p - arg) == 0) { expand_what = EXP_CSCOPE_FIND; - else + } else { xp->xp_context = EXPAND_NOTHING; + } } } } -/* - * PRIVATE: do_cscope_general - * - * Find the command, print help if invalid, and then call the corresponding - * command function. - */ -static void -do_cscope_general ( +/// Find the command, print help if invalid, and then call the corresponding +/// command function. +static void +do_cscope_general( exarg_T *eap, int make_split /* whether to split window */ ) @@ -206,29 +204,20 @@ do_cscope_general ( postponed_split_tab = 0; } -/* - * PUBLIC: do_cscope - */ -void do_cscope(exarg_T *eap) +/// Implementation of ":cscope" and ":lcscope" +void ex_cscope(exarg_T *eap) { do_cscope_general(eap, FALSE); } -/* - * PUBLIC: do_scscope - * - * same as do_cscope, but splits window, too. - */ -void do_scscope(exarg_T *eap) +/// Implementation of ":scscope". Same as ex_cscope(), but splits window, too. +void ex_scscope(exarg_T *eap) { do_cscope_general(eap, TRUE); } -/* - * PUBLIC: do_cstag - * - */ -void do_cstag(exarg_T *eap) +/// Implementation of ":cstag" +void ex_cstag(exarg_T *eap) { int ret = FALSE; @@ -283,18 +272,13 @@ void do_cstag(exarg_T *eap) (void)EMSG(_("E257: cstag: tag not found")); g_do_tagpreview = 0; } - -} /* do_cscope */ +} -/* - * PUBLIC: cs_find - * - * this simulates a vim_fgets(), but for cscope, returns the next line - * from the cscope output. should only be called from find_tags() - * - * returns TRUE if eof, FALSE otherwise - */ +/// This simulates a vim_fgets(), but for cscope, returns the next line +/// from the cscope output. should only be called from find_tags() +/// +/// @return TRUE if eof, FALSE otherwise int cs_fgets(char_u *buf, int size) { char *p; @@ -307,21 +291,13 @@ int cs_fgets(char_u *buf, int size) } /* cs_fgets */ -/* - * PUBLIC: cs_free_tags - * - * called only from do_tag(), when popping the tag stack - */ +/// Called only from do_tag(), when popping the tag stack. void cs_free_tags(void) { cs_manage_matches(NULL, NULL, 0, Free); } -/* - * PUBLIC: cs_print_tags - * - * called from do_tag() - */ +/// Called from do_tag(). void cs_print_tags(void) { cs_manage_matches(NULL, NULL, 0, Print); @@ -402,14 +378,8 @@ int cs_connection(int num, char_u *dbpath, char_u *ppath) * PRIVATE functions ****************************************************************************/ -/* - * PRIVATE: cs_add - * - * add cscope database or a directory name (to look for cscope.out) - * to the cscope connection list - * - * MAXPATHL 256 - */ +/// Add cscope database or a directory name (to look for cscope.out) +/// to the cscope connection list. static int cs_add(exarg_T *eap) { char *fname, *ppath, *flags = NULL; @@ -435,17 +405,13 @@ static void cs_stat_emsg(char *fname) } -/* - * PRIVATE: cs_add_common - * - * the common routine to add a new cscope connection. called by - * cs_add() and cs_reset(). i really don't like to do this, but this - * routine uses a number of goto statements. - */ -static int -cs_add_common ( - char *arg1, /* filename - may contain environment variables */ - char *arg2, /* prepend path - may contain environment variables */ +/// The common routine to add a new cscope connection. Called by +/// cs_add() and cs_reset(). I really don't like to do this, but this +/// routine uses a number of goto statements. +static int +cs_add_common( + char *arg1, // filename - may contain environment variables + char *arg2, // prepend path - may contain environment variables char *flags ) { @@ -559,11 +525,7 @@ static int cs_check_for_tags(void) return p_tags[0] != NUL && curbuf->b_p_tags != NULL; } /* cs_check_for_tags */ -/* - * PRIVATE: cs_cnt_connections - * - * count the number of cscope connections - */ +/// Count the number of cscope connections. static size_t cs_cnt_connections(void) { size_t cnt = 0; @@ -583,11 +545,7 @@ static void cs_reading_emsg( } #define CSREAD_BUFSIZE 2048 -/* - * PRIVATE: cs_cnt_matches - * - * count the number of matches for a given cscope connection. - */ +/// Count the number of matches for a given cscope connection. static int cs_cnt_matches(size_t idx) { char *stok; @@ -637,11 +595,7 @@ static int cs_cnt_matches(size_t idx) } /* cs_cnt_matches */ -/* - * PRIVATE: cs_create_cmd - * - * Creates the actual cscope command query from what the user entered. - */ +/// Creates the actual cscope command query from what the user entered. static char *cs_create_cmd(char *csoption, char *pattern) { char *cmd; @@ -697,12 +651,8 @@ static char *cs_create_cmd(char *csoption, char *pattern) } /* cs_create_cmd */ -/* - * PRIVATE: cs_create_connection - * - * This piece of code was taken/adapted from nvi. do we need to add - * the BSD license notice? - */ +/// This piece of code was taken/adapted from nvi. do we need to add +/// the BSD license notice? static int cs_create_connection(size_t i) { #ifdef UNIX @@ -891,14 +841,10 @@ err_closing: } /* cs_create_connection */ -/* - * PRIVATE: cs_find - * - * query cscope using command line interface. parse the output and use tselect - * to allow choices. like Nvi, creates a pipe to send to/from query/cscope. - * - * returns TRUE if we jump to a tag or abort, FALSE if not. - */ +/// Query cscope using command line interface. Parse the output and use tselect +/// to allow choices. Like Nvi, creates a pipe to send to/from query/cscope. +/// +/// @return TRUE if we jump to a tag or abort, FALSE if not. static int cs_find(exarg_T *eap) { char *opt, *pat; @@ -932,11 +878,7 @@ static int cs_find(exarg_T *eap) } /* cs_find */ -/* - * PRIVATE: cs_find_common - * - * common code for cscope find, shared by cs_find() and do_cstag() - */ +/// Common code for cscope find, shared by cs_find() and ex_cstag(). static int cs_find_common(char *opt, char *pat, int forceit, int verbose, int use_ll, char_u *cmdline) { @@ -994,11 +936,12 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose, return FALSE; } - if (*qfpos != '0') { - apply_autocmds(EVENT_QUICKFIXCMDPRE, (char_u *)"cscope", - curbuf->b_fname, TRUE, curbuf); - if (did_throw || force_abort) - return FALSE; + if (*qfpos != '0' + && apply_autocmds(EVENT_QUICKFIXCMDPRE, (char_u *)"cscope", + curbuf->b_fname, true, curbuf)) { + if (aborting()) { + return false; + } } } @@ -1108,11 +1051,7 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose, } /* cs_find_common */ -/* - * PRIVATE: cs_help - * - * print help - */ +/// Print help. static int cs_help(exarg_T *eap) { cscmd_T *cmdp = cs_cmds; @@ -1160,11 +1099,7 @@ static void clear_csinfo(size_t i) csinfo[i].to_fp = NULL; } -/* - * PRIVATE: cs_insert_filelist - * - * insert a new cscope database filename into the filelist - */ +/// Insert a new cscope database filename into the filelist. static int cs_insert_filelist(char *fname, char *ppath, char *flags, FileInfo *file_info) { @@ -1224,11 +1159,7 @@ static int cs_insert_filelist(char *fname, char *ppath, char *flags, } /* cs_insert_filelist */ -/* - * PRIVATE: cs_lookup_cmd - * - * find cscope command in command table - */ +/// Find cscope command in command table. static cscmd_T * cs_lookup_cmd(exarg_T *eap) { cscmd_T *cmdp; @@ -1253,11 +1184,7 @@ static cscmd_T * cs_lookup_cmd(exarg_T *eap) } /* cs_lookup_cmd */ -/* - * PRIVATE: cs_kill - * - * nuke em - */ +/// Nuke em. static int cs_kill(exarg_T *eap) { char *stok; @@ -1294,9 +1221,10 @@ static int cs_kill(exarg_T *eap) } } - if (i >= csinfo_size || csinfo[i].fname == NULL) { - if (p_csverbose) + if (!killall && (i >= csinfo_size || csinfo[i].fname == NULL)) { + if (p_csverbose) { (void)EMSG2(_("E261: cscope connection %s not found"), stok); + } return CSCOPE_FAILURE; } else { if (killall) { @@ -1313,11 +1241,7 @@ static int cs_kill(exarg_T *eap) } /* cs_kill */ -/* - * PRIVATE: cs_kill_execute - * - * Actually kills a specific cscope connection. - */ +/// Actually kills a specific cscope connection. static void cs_kill_execute( size_t i, /* cscope table index */ char *cname /* cscope database name */ @@ -1332,26 +1256,22 @@ static void cs_kill_execute( } -/* - * PRIVATE: cs_make_vim_style_matches - * - * convert the cscope output into a ctags style entry (as might be found - * in a ctags tags file). there's one catch though: cscope doesn't tell you - * the type of the tag you are looking for. for example, in Darren Hiebert's - * ctags (the one that comes with vim), #define's use a line number to find the - * tag in a file while function definitions use a regexp search pattern. - * - * i'm going to always use the line number because cscope does something - * quirky (and probably other things i don't know about): - * - * if you have "# define" in your source file, which is - * perfectly legal, cscope thinks you have "#define". this - * will result in a failed regexp search. :( - * - * besides, even if this particular case didn't happen, the search pattern - * would still have to be modified to escape all the special regular expression - * characters to comply with ctags formatting. - */ +/// Convert the cscope output into a ctags style entry (as might be found +/// in a ctags tags file). there's one catch though: cscope doesn't tell you +/// the type of the tag you are looking for. for example, in Darren Hiebert's +/// ctags (the one that comes with vim), #define's use a line number to find the +/// tag in a file while function definitions use a regexp search pattern. +/// +/// I'm going to always use the line number because cscope does something +/// quirky (and probably other things i don't know about): +/// +/// if you have "# define" in your source file, which is +/// perfectly legal, cscope thinks you have "#define". this +/// will result in a failed regexp search. :( +/// +/// Besides, even if this particular case didn't happen, the search pattern +/// would still have to be modified to escape all the special regular expression +/// characters to comply with ctags formatting. static char *cs_make_vim_style_matches(char *fname, char *slno, char *search, char *tagstr) { @@ -1385,24 +1305,20 @@ static char *cs_make_vim_style_matches(char *fname, char *slno, char *search, } /* cs_make_vim_style_matches */ -/* - * PRIVATE: cs_manage_matches - * - * this is kind of hokey, but i don't see an easy way round this.. - * - * Store: keep a ptr to the (malloc'd) memory of matches originally - * generated from cs_find(). the matches are originally lines directly - * from cscope output, but transformed to look like something out of a - * ctags. see cs_make_vim_style_matches for more details. - * - * Get: used only from cs_fgets(), this simulates a vim_fgets() to return - * the next line from the cscope output. it basically keeps track of which - * lines have been "used" and returns the next one. - * - * Free: frees up everything and resets - * - * Print: prints the tags - */ +/// This is kind of hokey, but i don't see an easy way round this. +/// +/// Store: keep a ptr to the (malloc'd) memory of matches originally +/// generated from cs_find(). the matches are originally lines directly +/// from cscope output, but transformed to look like something out of a +/// ctags. see cs_make_vim_style_matches for more details. +/// +/// Get: used only from cs_fgets(), this simulates a vim_fgets() to return +/// the next line from the cscope output. it basically keeps track of which +/// lines have been "used" and returns the next one. +/// +/// Free: frees up everything and resets +/// +/// Print: prints the tags static char *cs_manage_matches(char **matches, char **contexts, size_t totmatches, mcmd_e cmd) { @@ -1457,11 +1373,7 @@ static char *cs_manage_matches(char **matches, char **contexts, } /* cs_manage_matches */ -/* - * PRIVATE: cs_parse_results - * - * parse cscope output - */ +/// Parse cscope output. static char *cs_parse_results(size_t cnumber, char *buf, int bufsize, char **context, char **linenumber, char **search) { @@ -1511,11 +1423,7 @@ static char *cs_parse_results(size_t cnumber, char *buf, int bufsize, return name; } -/* - * PRIVATE: cs_file_results - * - * write cscope find results to file - */ +/// Write cscope find results to file. static void cs_file_results(FILE *f, int *nummatches_a) { char *search, *slno; @@ -1556,13 +1464,9 @@ static void cs_file_results(FILE *f, int *nummatches_a) xfree(buf); } -/* - * PRIVATE: cs_fill_results - * - * get parsed cscope output and calls cs_make_vim_style_matches to convert - * into ctags format - * When there are no matches sets "*matches_p" to NULL. - */ +/// Get parsed cscope output and calls cs_make_vim_style_matches to convert +/// into ctags format. +/// When there are no matches sets "*matches_p" to NULL. static void cs_fill_results(char *tagstr, size_t totmatches, int *nummatches_a, char ***matches_p, char ***cntxts_p, size_t *matched) @@ -1754,11 +1658,7 @@ static void cs_print_tags_priv(char **matches, char **cntxts, xfree(buf); } -/* - * PRIVATE: cs_read_prompt - * - * read a cscope prompt (basically, skip over the ">> ") - */ +/// Read a cscope prompt (basically, skip over the ">> "). static int cs_read_prompt(size_t i) { int ch; @@ -1843,12 +1743,8 @@ static void sig_handler(int s) { #endif -/* - * PRIVATE: cs_release_csp - * - * Does the actual free'ing for the cs ptr with an optional flag of whether - * or not to free the filename. Called by cs_kill and cs_reset. - */ +/// Does the actual free'ing for the cs ptr with an optional flag of whether +/// or not to free the filename. Called by cs_kill and cs_reset. static void cs_release_csp(size_t i, int freefnpp) { // Trying to exit normally (not sure whether it is fit to Unix cscope) @@ -1960,15 +1856,11 @@ static void cs_release_csp(size_t i, int freefnpp) } /* cs_release_csp */ -/* - * PRIVATE: cs_reset - * - * calls cs_kill on all cscope connections then reinits - */ +/// Calls cs_kill on all cscope connections then reinits. static int cs_reset(exarg_T *eap) { char **dblist = NULL, **pplist = NULL, **fllist = NULL; - char buf[20]; /* for snprintf " (#%zu)" */ + char buf[25]; // for snprintf " (#%zu)" if (csinfo_size == 0) return CSCOPE_SUCCESS; @@ -2007,23 +1899,20 @@ static int cs_reset(exarg_T *eap) xfree(pplist); xfree(fllist); - if (p_csverbose) - MSG_ATTR(_("All cscope databases reset"), hl_attr(HLF_R) | MSG_HIST); + if (p_csverbose) { + msg_attr(_("All cscope databases reset"), hl_attr(HLF_R) | MSG_HIST); + } return CSCOPE_SUCCESS; } /* cs_reset */ -/* - * PRIVATE: cs_resolve_file - * - * Construct the full pathname to a file found in the cscope database. - * (Prepends ppath, if there is one and if it's not already prepended, - * otherwise just uses the name found.) - * - * We need to prepend the prefix because on some cscope's (e.g., the one that - * ships with Solaris 2.6), the output never has the prefix prepended. - * Contrast this with my development system (Digital Unix), which does. - */ +/// Construct the full pathname to a file found in the cscope database. +/// (Prepends ppath, if there is one and if it's not already prepended, +/// otherwise just uses the name found.) +/// +/// We need to prepend the prefix because on some cscope's (e.g., the one that +/// ships with Solaris 2.6), the output never has the prefix prepended. +/// Contrast this with my development system (Digital Unix), which does. static char *cs_resolve_file(size_t i, char *name) { char *fullname; @@ -2069,11 +1958,7 @@ static char *cs_resolve_file(size_t i, char *name) } -/* - * PRIVATE: cs_show - * - * show all cscope connections - */ +/// Show all cscope connections. static int cs_show(exarg_T *eap) { if (cs_cnt_connections() == 0) @@ -2101,11 +1986,7 @@ static int cs_show(exarg_T *eap) } /* cs_show */ -/* - * PUBLIC: cs_end - * - * Only called when VIM exits to quit any cscope sessions. - */ +/// Only called when VIM exits to quit any cscope sessions. void cs_end(void) { for (size_t i = 0; i < csinfo_size; i++) diff --git a/src/nvim/if_cscope.h b/src/nvim/if_cscope.h index 351d9caef6..e20462576a 100644 --- a/src/nvim/if_cscope.h +++ b/src/nvim/if_cscope.h @@ -1,6 +1,9 @@ #ifndef NVIM_IF_CSCOPE_H #define NVIM_IF_CSCOPE_H +#include "nvim/types.h" // for char_u and expand_T +#include "nvim/ex_cmds_defs.h" // for exarg_T + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "if_cscope.h.generated.h" #endif diff --git a/src/nvim/if_cscope_defs.h b/src/nvim/if_cscope_defs.h index f9d06eaea3..fa18866840 100644 --- a/src/nvim/if_cscope_defs.h +++ b/src/nvim/if_cscope_defs.h @@ -18,6 +18,7 @@ #include "nvim/os/os_defs.h" #include "nvim/os/fs_defs.h" +#include "nvim/ex_cmds_defs.h" #define CSCOPE_SUCCESS 0 #define CSCOPE_FAILURE -1 diff --git a/src/nvim/indent.c b/src/nvim/indent.c index 7f31bb8c5c..efca739c2d 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -1,3 +1,6 @@ +// 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 <inttypes.h> #include <stdbool.h> @@ -7,6 +10,7 @@ #include "nvim/eval.h" #include "nvim/charset.h" #include "nvim/cursor.h" +#include "nvim/mark.h" #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/misc1.h" @@ -467,7 +471,7 @@ int get_breakindent_win(win_T *wp, char_u *line) { || prev_tick != wp->w_buffer->b_changedtick) { prev_line = line; prev_ts = wp->w_buffer->b_p_ts; - prev_tick = wp->w_buffer->b_changedtick; + prev_tick = (int)wp->w_buffer->b_changedtick; prev_indent = get_indent_str(line, (int)wp->w_buffer->b_p_ts, wp->w_p_list); } @@ -534,7 +538,7 @@ int get_expr_indent(void) sandbox++; } textlock++; - indent = eval_to_number(curbuf->b_p_inde); + indent = (int)eval_to_number(curbuf->b_p_inde); if (use_sandbox) { sandbox--; @@ -598,7 +602,7 @@ int get_lisp_indent(void) paren = *pos; pos = findmatch(NULL, '['); - if ((pos == NULL) || ltp(pos, &paren)) { + if ((pos == NULL) || lt(*pos, paren)) { pos = &paren; } } diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c index 6f03cf6037..4a6393ac36 100644 --- a/src/nvim/indent_c.c +++ b/src/nvim/indent_c.c @@ -1,3 +1,6 @@ +// 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 <inttypes.h> #include <stdint.h> @@ -10,6 +13,7 @@ #include "nvim/edit.h" #include "nvim/indent.h" #include "nvim/indent_c.h" +#include "nvim/mark.h" #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/option.h" @@ -173,9 +177,8 @@ static char_u *skip_string(char_u *p) char_u *delim = p + 2; char_u *paren = vim_strchr(delim, '('); - if (paren != NULL) - { - long delim_len = paren - delim; + if (paren != NULL) { + const ptrdiff_t delim_len = paren - delim; for (p += 3; *p; ++p) if (p[0] == ')' && STRNCMP(p + 1, delim, delim_len) == 0 @@ -512,34 +515,41 @@ int cin_isscopedecl(char_u *s) /* Maximum number of lines to search back for a "namespace" line. */ #define FIND_NAMESPACE_LIM 20 -/* - * Recognize a "namespace" scope declaration. - */ -static int cin_is_cpp_namespace(char_u *s) +// Recognize a "namespace" scope declaration. +static bool cin_is_cpp_namespace(char_u *s) { - char_u *p; - int has_name = FALSE; + char_u *p; + bool has_name = false; + bool has_name_start = false; s = cin_skipcomment(s); if (STRNCMP(s, "namespace", 9) == 0 && (s[9] == NUL || !vim_iswordc(s[9]))) { p = cin_skipcomment(skipwhite(s + 9)); while (*p != NUL) { if (ascii_iswhite(*p)) { - has_name = TRUE; /* found end of a name */ + has_name = true; // found end of a name p = cin_skipcomment(skipwhite(p)); } else if (*p == '{') { break; } else if (vim_iswordc(*p)) { - if (has_name) - return FALSE; /* word character after skipping past name */ - ++p; + has_name_start = true; + if (has_name) { + return false; // word character after skipping past name + } + p++; + } else if (p[0] == ':' && p[1] == ':' && vim_iswordc(p[2])) { + if (!has_name_start || has_name) { + return false; + } + // C++ 17 nested namespace + p += 3; } else { - return FALSE; + return false; } } - return TRUE; + return true; } - return FALSE; + return false; } /* @@ -819,21 +829,22 @@ cin_isterminated ( return found_start; } -/* - * Recognize the basic picture of a function declaration -- it needs to - * have an open paren somewhere and a close paren at the end of the line and - * no semicolons anywhere. - * When a line ends in a comma we continue looking in the next line. - * "sp" points to a string with the line. When looking at other lines it must - * be restored to the line. When it's NULL fetch lines here. - * "lnum" is where we start looking. - * "min_lnum" is the line before which we will not be looking. - */ +/// Recognizes the basic picture of a function declaration -- it needs to +/// have an open paren somewhere and a close paren at the end of the line and +/// no semicolons anywhere. +/// When a line ends in a comma we continue looking in the next line. +/// +/// @param[in] sp Points to a string with the line. When looking at other +/// lines it must be restored to the line. When it's NULL fetch +/// lines here. +/// @param[in] first_lnum Where to start looking. +/// @param[in] min_lnum The line before which we will not be looking. static int cin_isfuncdecl(char_u **sp, linenr_T first_lnum, linenr_T min_lnum) { char_u *s; linenr_T lnum = first_lnum; - int retval = FALSE; + linenr_T save_lnum = curwin->w_cursor.lnum; + int retval = false; pos_T *trypos; int just_started = TRUE; @@ -842,18 +853,22 @@ static int cin_isfuncdecl(char_u **sp, linenr_T first_lnum, linenr_T min_lnum) else s = *sp; + curwin->w_cursor.lnum = lnum; if (find_last_paren(s, '(', ')') && (trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL) { lnum = trypos->lnum; - if (lnum < min_lnum) - return FALSE; - + if (lnum < min_lnum) { + curwin->w_cursor.lnum = save_lnum; + return false; + } s = ml_get(lnum); } - /* Ignore line starting with #. */ - if (cin_ispreproc(s)) - return FALSE; + curwin->w_cursor.lnum = save_lnum; + // Ignore line starting with #. + if (cin_ispreproc(s)) { + return false; + } while (*s && *s != '(' && *s != ';' && *s != '\'' && *s != '"') { // ignore comments diff --git a/src/nvim/keymap.c b/src/nvim/keymap.c index 99e94fc60f..3d7ebb6382 100644 --- a/src/nvim/keymap.c +++ b/src/nvim/keymap.c @@ -1,3 +1,6 @@ +// 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 <inttypes.h> #include <limits.h> @@ -490,17 +493,19 @@ char_u *get_special_key_name(int c, int modifiers) /// @param[out] dst Location where translation result will be kept. Must have /// at least six bytes. /// @param[in] keycode Prefer key code, e.g. K_DEL in place of DEL. +/// @param[in] in_string Inside a double quoted string /// /// @return Number of characters added to dst, zero for no match. unsigned int trans_special(const char_u **srcp, const size_t src_len, - char_u *const dst, const bool keycode) + char_u *const dst, const bool keycode, + const bool in_string) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { int modifiers = 0; int key; unsigned int dlen = 0; - key = find_special_key(srcp, src_len, &modifiers, keycode, false); + key = find_special_key(srcp, src_len, &modifiers, keycode, false, in_string); if (key == 0) { return 0; } @@ -536,10 +541,12 @@ unsigned int trans_special(const char_u **srcp, const size_t src_len, /// @param[out] modp Location where information about modifiers is saved. /// @param[in] keycode Prefer key code, e.g. K_DEL in place of DEL. /// @param[in] keep_x_key Don’t translate xHome to Home key. +/// @param[in] in_string In string, double quote is escaped /// /// @return Key and modifiers or 0 if there is no match. int find_special_key(const char_u **srcp, const size_t src_len, int *const modp, - const bool keycode, const bool keep_x_key) + const bool keycode, const bool keep_x_key, + const bool in_string) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { const char_u *last_dash; @@ -550,7 +557,7 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp, int modifiers; int bit; int key; - unsigned long n; + uvarnumber_T n; int l; if (src_len == 0) { @@ -573,8 +580,14 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp, } else { l = 1; } - if (end - bp > l && bp[l + 1] == '>') { - bp += l; // anything accepted, like <C-?> + // Anything accepted, like <C-?>. + // <C-"> or <M-"> are not special in strings as " is + // the string delimiter. With a backslash it works: <M-\"> + if (end - bp > l && !(in_string && bp[1] == '"') && bp[2] == '>') { + bp += l; + } else if (end - bp > 2 && in_string && bp[1] == '\\' + && bp[2] == '"' && bp[3] == '>') { + bp += 2; } } } @@ -610,18 +623,17 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp, vim_str2nr(last_dash + 6, NULL, NULL, STR2NR_ALL, NULL, &n, 0); key = (int)n; } else { - /* - * Modifier with single letter, or special key name. - */ - if (has_mbyte) { - l = mb_ptr2len(last_dash + 1); - } else { - l = 1; + int off = 1; + + // Modifier with single letter, or special key name. + if (in_string && last_dash[1] == '\\' && last_dash[2] == '"') { + off = 2; } + l = mb_ptr2len(last_dash + 1); if (modifiers != 0 && last_dash[l + 1] == '>') { - key = PTR2CHAR(last_dash + 1); + key = PTR2CHAR(last_dash + off); } else { - key = get_special_key_code(last_dash + 1); + key = get_special_key_code(last_dash + off); if (!keep_x_key) { key = handle_x_keys(key); } @@ -744,9 +756,9 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag) /// Replace any terminal code strings with the equivalent internal /// representation /// -/// This is used for the "from" and "to" part of a mapping, and the "to" part of +/// Used for the "from" and "to" part of a mapping, and the "to" part of /// a menu command. Any strings like "<C-UP>" are also replaced, unless -/// 'cpoptions' contains '<'. K_SPECIAL by itself is replaced by K_SPECIAL +/// `special` is false. K_SPECIAL by itself is replaced by K_SPECIAL /// KS_SPECIAL KE_FILLER. /// /// @param[in] from What characters to replace. @@ -759,7 +771,7 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag) /// When cpo_flags contains #FLAG_CPO_BSLASH, a backslash /// can be used in place of <C-v>. All other <C-v> /// characters are removed. -/// @param[in] special If true, always accept <key> notation. +/// @param[in] special Replace keycodes, e.g. <CR> becomes a "\n" char. /// @param[in] cpo_flags Relevant flags derived from p_cpo, see /// #CPO_TO_CPO_FLAGS. /// @@ -778,11 +790,9 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len, const char_u *src; const char_u *const end = from + from_len - 1; int do_backslash; // backslash is a special character - int do_special; // recognize <> key codes char_u *result; // buffer for resulting string do_backslash = !(cpo_flags&FLAG_CPO_BSLASH); - do_special = !(cpo_flags&FLAG_CPO_SPECI) || special; // Allocate space for the translation. Worst case a single character is // replaced by 6 bytes (shifted special key), plus a NUL at the end. @@ -805,10 +815,9 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len, // Copy each byte from *from to result[dlen] while (src <= end) { - // If 'cpoptions' does not contain '<', check for special key codes, - // like "<C-S-LeftMouse>" - if (do_special && (do_lt || ((end - src) >= 3 - && STRNCMP(src, "<lt>", 4) != 0))) { + // Check for special <> keycodes, like "<C-S-LeftMouse>" + if (special && (do_lt || ((end - src) >= 3 + && STRNCMP(src, "<lt>", 4) != 0))) { // Replace <SID> by K_SNR <script-nr> _. // (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14) if (end - src >= 4 && STRNICMP(src, "<SID>", 5) == 0) { @@ -826,14 +835,15 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len, } } - slen = trans_special(&src, (size_t) (end - src) + 1, result + dlen, true); + slen = trans_special(&src, (size_t)(end - src) + 1, result + dlen, true, + true); if (slen) { dlen += slen; continue; } } - if (do_special) { + if (special) { char_u *p, *s, len; // Replace <Leader> by the value of "mapleader". @@ -841,10 +851,10 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len, // If "mapleader" or "maplocalleader" isn't set use a backslash. if (end - src >= 7 && STRNICMP(src, "<Leader>", 8) == 0) { len = 8; - p = get_var_value((char_u *)"g:mapleader"); + p = get_var_value("g:mapleader"); } else if (end - src >= 12 && STRNICMP(src, "<LocalLeader>", 13) == 0) { len = 13; - p = get_var_value((char_u *)"g:maplocalleader"); + p = get_var_value("g:maplocalleader"); } else { len = 0; p = NULL; diff --git a/src/nvim/keymap.h b/src/nvim/keymap.h index bb8ba84a6a..b8fed77a90 100644 --- a/src/nvim/keymap.h +++ b/src/nvim/keymap.h @@ -464,13 +464,9 @@ enum key_extra { #define MAX_KEY_CODE_LEN 6 #define FLAG_CPO_BSLASH 0x01 -#define FLAG_CPO_SPECI 0x02 -#define CPO_TO_CPO_FLAGS (((vim_strchr(p_cpo, CPO_BSLASH) == NULL) \ - ? 0 \ - : FLAG_CPO_BSLASH)| \ - (vim_strchr(p_cpo, CPO_SPECI) == NULL \ - ? 0 \ - : FLAG_CPO_SPECI)) +#define CPO_TO_CPO_FLAGS ((vim_strchr(p_cpo, CPO_BSLASH) == NULL) \ + ? 0 \ + : FLAG_CPO_BSLASH) #ifdef INCLUDE_GENERATED_DECLARATIONS # include "keymap.h.generated.h" diff --git a/src/nvim/lib/kbtree.h b/src/nvim/lib/kbtree.h new file mode 100644 index 0000000000..a3943054e6 --- /dev/null +++ b/src/nvim/lib/kbtree.h @@ -0,0 +1,451 @@ +/*- + * Copyright 1997-1999, 2001, John-Mark Gurney. + * 2008-2009, Attractive Chaos <attractor@live.co.uk> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NVIM_LIB_KBTREE_H +#define NVIM_LIB_KBTREE_H + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#include "nvim/memory.h" + +#define KB_MAX_DEPTH 64 + +#define __KB_KEY(type, x) (x->key) +#define __KB_PTR(btr, x) (x->ptr) + +#define __KB_TREE_T(name,key_t,T) \ + typedef struct kbnode_##name##_s kbnode_##name##_t; \ + struct kbnode_##name##_s { \ + int32_t n; \ + bool is_internal; \ + key_t key[2*T-1]; \ + kbnode_##name##_t *ptr[]; \ + } ; \ + \ + typedef struct { \ + kbnode_##name##_t *root; \ + int n_keys, n_nodes; \ + } kbtree_##name##_t; \ + \ + typedef struct { \ + kbnode_##name##_t *x; \ + int i; \ + } kbpos_##name##_t; \ + typedef struct { \ + kbpos_##name##_t stack[KB_MAX_DEPTH], *p; \ + } kbitr_##name##_t; \ + + +#define __kb_destroy(kbnode_t,b) do { \ + int i; \ + unsigned int max = 8; \ + kbnode_t *x, **top, **stack = 0; \ + if (b->root) { \ + top = stack = (kbnode_t**)xcalloc(max, sizeof(kbnode_t*)); \ + *top++ = (b)->root; \ + while (top != stack) { \ + x = *--top; \ + if (x->is_internal == 0) { xfree(x); continue; } \ + for (i = 0; i <= x->n; ++i) \ + if (__KB_PTR(b, x)[i]) { \ + if (top - stack == (int)max) { \ + max <<= 1; \ + stack = (kbnode_t**)xrealloc(stack, max * sizeof(kbnode_t*)); \ + top = stack + (max>>1); \ + } \ + *top++ = __KB_PTR(b, x)[i]; \ + } \ + xfree(x); \ + } \ + } \ + xfree(stack); \ + } while (0) + +#define __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ + static inline int __kb_getp_aux_##name(const kbnode_t * __restrict x, key_t * __restrict k, int *r) \ + { \ + int tr, *rr, begin = 0, end = x->n; \ + if (x->n == 0) return -1; \ + rr = r? r : &tr; \ + while (begin < end) { \ + int mid = (begin + end) >> 1; \ + if (__cmp(__KB_KEY(key_t, x)[mid], *k) < 0) begin = mid + 1; \ + else end = mid; \ + } \ + if (begin == x->n) { *rr = 1; return x->n - 1; } \ + if ((*rr = __cmp(*k, __KB_KEY(key_t, x)[begin])) < 0) --begin; \ + return begin; \ + } + +#define __KB_GET(name, key_t, kbnode_t) \ + static key_t *kb_getp_##name(kbtree_##name##_t *b, key_t * __restrict k) \ + { \ + if (!b->root) { \ + return 0; \ + } \ + int i, r = 0; \ + kbnode_t *x = b->root; \ + while (x) { \ + i = __kb_getp_aux_##name(x, k, &r); \ + if (i >= 0 && r == 0) return &__KB_KEY(key_t, x)[i]; \ + if (x->is_internal == 0) return 0; \ + x = __KB_PTR(b, x)[i + 1]; \ + } \ + return 0; \ + } \ + static inline key_t *kb_get_##name(kbtree_##name##_t *b, key_t k) \ + { \ + return kb_getp_##name(b, &k); \ + } + +#define __KB_INTERVAL(name, key_t, kbnode_t) \ + static inline void kb_intervalp_##name(kbtree_##name##_t *b, key_t * __restrict k, key_t **lower, key_t **upper) \ + { \ + if (!b->root) { \ + return; \ + } \ + int i, r = 0; \ + kbnode_t *x = b->root; \ + *lower = *upper = 0; \ + while (x) { \ + i = __kb_getp_aux_##name(x, k, &r); \ + if (i >= 0 && r == 0) { \ + *lower = *upper = &__KB_KEY(key_t, x)[i]; \ + return; \ + } \ + if (i >= 0) *lower = &__KB_KEY(key_t, x)[i]; \ + if (i < x->n - 1) *upper = &__KB_KEY(key_t, x)[i + 1]; \ + if (x->is_internal == 0) return; \ + x = __KB_PTR(b, x)[i + 1]; \ + } \ + } \ + static inline void kb_interval_##name(kbtree_##name##_t *b, key_t k, key_t **lower, key_t **upper) \ + { \ + kb_intervalp_##name(b, &k, lower, upper); \ + } + +#define __KB_PUT(name, key_t, kbnode_t, __cmp, T, ILEN) \ + /* x must be an internal node */ \ + static inline void __kb_split_##name(kbtree_##name##_t *b, kbnode_t *x, int i, kbnode_t *y) \ + { \ + kbnode_t *z; \ + z = (kbnode_t*)xcalloc(1, y->is_internal? ILEN : sizeof(kbnode_##name##_t)); \ + ++b->n_nodes; \ + z->is_internal = y->is_internal; \ + z->n = T - 1; \ + memcpy(__KB_KEY(key_t, z), &__KB_KEY(key_t, y)[T], sizeof(key_t) * (T - 1)); \ + if (y->is_internal) memcpy(__KB_PTR(b, z), &__KB_PTR(b, y)[T], sizeof(void*) * T); \ + y->n = T - 1; \ + memmove(&__KB_PTR(b, x)[i + 2], &__KB_PTR(b, x)[i + 1], sizeof(void*) * (unsigned int)(x->n - i)); \ + __KB_PTR(b, x)[i + 1] = z; \ + memmove(&__KB_KEY(key_t, x)[i + 1], &__KB_KEY(key_t, x)[i], sizeof(key_t) * (unsigned int)(x->n - i)); \ + __KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[T - 1]; \ + ++x->n; \ + } \ + static inline key_t *__kb_putp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, key_t * __restrict k) \ + { \ + int i = x->n - 1; \ + key_t *ret; \ + if (x->is_internal == 0) { \ + i = __kb_getp_aux_##name(x, k, 0); \ + if (i != x->n - 1) \ + memmove(&__KB_KEY(key_t, x)[i + 2], &__KB_KEY(key_t, x)[i + 1], (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + ret = &__KB_KEY(key_t, x)[i + 1]; \ + *ret = *k; \ + ++x->n; \ + } else { \ + i = __kb_getp_aux_##name(x, k, 0) + 1; \ + if (__KB_PTR(b, x)[i]->n == 2 * T - 1) { \ + __kb_split_##name(b, x, i, __KB_PTR(b, x)[i]); \ + if (__cmp(*k, __KB_KEY(key_t, x)[i]) > 0) ++i; \ + } \ + ret = __kb_putp_aux_##name(b, __KB_PTR(b, x)[i], k); \ + } \ + return ret; \ + } \ + static inline key_t *kb_putp_##name(kbtree_##name##_t *b, key_t * __restrict k) \ + { \ + if (!b->root) { \ + b->root = (kbnode_t*)xcalloc(1, ILEN); \ + ++b->n_nodes; \ + } \ + kbnode_t *r, *s; \ + ++b->n_keys; \ + r = b->root; \ + if (r->n == 2 * T - 1) { \ + ++b->n_nodes; \ + s = (kbnode_t*)xcalloc(1, ILEN); \ + b->root = s; s->is_internal = 1; s->n = 0; \ + __KB_PTR(b, s)[0] = r; \ + __kb_split_##name(b, s, 0, r); \ + r = s; \ + } \ + return __kb_putp_aux_##name(b, r, k); \ + } \ + static inline void kb_put_##name(kbtree_##name##_t *b, key_t k) \ + { \ + kb_putp_##name(b, &k); \ + } + + +#define __KB_DEL(name, key_t, kbnode_t, T) \ + static inline key_t __kb_delp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, key_t * __restrict k, int s) \ + { \ + int yn, zn, i, r = 0; \ + kbnode_t *xp, *y, *z; \ + key_t kp; \ + if (x == 0) return *k; \ + if (s) { /* s can only be 0, 1 or 2 */ \ + r = x->is_internal == 0? 0 : s == 1? 1 : -1; \ + i = s == 1? x->n - 1 : -1; \ + } else i = __kb_getp_aux_##name(x, k, &r); \ + if (x->is_internal == 0) { \ + if (s == 2) ++i; \ + kp = __KB_KEY(key_t, x)[i]; \ + memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, x)[i + 1], (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + --x->n; \ + return kp; \ + } \ + if (r == 0) { \ + if ((yn = __KB_PTR(b, x)[i]->n) >= T) { \ + xp = __KB_PTR(b, x)[i]; \ + kp = __KB_KEY(key_t, x)[i]; \ + __KB_KEY(key_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 1); \ + return kp; \ + } else if ((zn = __KB_PTR(b, x)[i + 1]->n) >= T) { \ + xp = __KB_PTR(b, x)[i + 1]; \ + kp = __KB_KEY(key_t, x)[i]; \ + __KB_KEY(key_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 2); \ + return kp; \ + } else if (yn == T - 1 && zn == T - 1) { \ + y = __KB_PTR(b, x)[i]; z = __KB_PTR(b, x)[i + 1]; \ + __KB_KEY(key_t, y)[y->n++] = *k; \ + memmove(&__KB_KEY(key_t, y)[y->n], __KB_KEY(key_t, z), (unsigned int)z->n * sizeof(key_t)); \ + if (y->is_internal) memmove(&__KB_PTR(b, y)[y->n], __KB_PTR(b, z), (unsigned int)(z->n + 1) * sizeof(void*)); \ + y->n += z->n; \ + memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, x)[i + 1], (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + memmove(&__KB_PTR(b, x)[i + 1], &__KB_PTR(b, x)[i + 2], (unsigned int)(x->n - i - 1) * sizeof(void*)); \ + --x->n; \ + xfree(z); \ + return __kb_delp_aux_##name(b, y, k, s); \ + } \ + } \ + ++i; \ + if ((xp = __KB_PTR(b, x)[i])->n == T - 1) { \ + if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n >= T) { \ + memmove(&__KB_KEY(key_t, xp)[1], __KB_KEY(key_t, xp), (unsigned int)xp->n * sizeof(key_t)); \ + if (xp->is_internal) memmove(&__KB_PTR(b, xp)[1], __KB_PTR(b, xp), (unsigned int)(xp->n + 1) * sizeof(void*)); \ + __KB_KEY(key_t, xp)[0] = __KB_KEY(key_t, x)[i - 1]; \ + __KB_KEY(key_t, x)[i - 1] = __KB_KEY(key_t, y)[y->n - 1]; \ + if (xp->is_internal) __KB_PTR(b, xp)[0] = __KB_PTR(b, y)[y->n]; \ + --y->n; ++xp->n; \ + } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n >= T) { \ + __KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i]; \ + __KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[0]; \ + if (xp->is_internal) __KB_PTR(b, xp)[xp->n] = __KB_PTR(b, y)[0]; \ + --y->n; \ + memmove(__KB_KEY(key_t, y), &__KB_KEY(key_t, y)[1], (unsigned int)y->n * sizeof(key_t)); \ + if (y->is_internal) memmove(__KB_PTR(b, y), &__KB_PTR(b, y)[1], (unsigned int)(y->n + 1) * sizeof(void*)); \ + } else if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n == T - 1) { \ + __KB_KEY(key_t, y)[y->n++] = __KB_KEY(key_t, x)[i - 1]; \ + memmove(&__KB_KEY(key_t, y)[y->n], __KB_KEY(key_t, xp), (unsigned int)xp->n * sizeof(key_t)); \ + if (y->is_internal) memmove(&__KB_PTR(b, y)[y->n], __KB_PTR(b, xp), (unsigned int)(xp->n + 1) * sizeof(void*)); \ + y->n += xp->n; \ + memmove(&__KB_KEY(key_t, x)[i - 1], &__KB_KEY(key_t, x)[i], (unsigned int)(x->n - i) * sizeof(key_t)); \ + memmove(&__KB_PTR(b, x)[i], &__KB_PTR(b, x)[i + 1], (unsigned int)(x->n - i) * sizeof(void*)); \ + --x->n; \ + xfree(xp); \ + xp = y; \ + } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n == T - 1) { \ + __KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i]; \ + memmove(&__KB_KEY(key_t, xp)[xp->n], __KB_KEY(key_t, y), (unsigned int)y->n * sizeof(key_t)); \ + if (xp->is_internal) memmove(&__KB_PTR(b, xp)[xp->n], __KB_PTR(b, y), (unsigned int)(y->n + 1) * sizeof(void*)); \ + xp->n += y->n; \ + memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, x)[i + 1], (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + memmove(&__KB_PTR(b, x)[i + 1], &__KB_PTR(b, x)[i + 2], (unsigned int)(x->n - i - 1) * sizeof(void*)); \ + --x->n; \ + xfree(y); \ + } \ + } \ + return __kb_delp_aux_##name(b, xp, k, s); \ + } \ + static inline key_t kb_delp_##name(kbtree_##name##_t *b, key_t * __restrict k) \ + { \ + kbnode_t *x; \ + key_t ret; \ + ret = __kb_delp_aux_##name(b, b->root, k, 0); \ + --b->n_keys; \ + if (b->root->n == 0 && b->root->is_internal) { \ + --b->n_nodes; \ + x = b->root; \ + b->root = __KB_PTR(b, x)[0]; \ + xfree(x); \ + } \ + return ret; \ + } \ + static inline key_t kb_del_##name(kbtree_##name##_t *b, key_t k) \ + { \ + return kb_delp_##name(b, &k); \ + } + +#define __KB_ITR(name, key_t, kbnode_t) \ + static inline void kb_itr_first_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ + { \ + itr->p = 0; \ + if (b->n_keys == 0) return; \ + itr->p = itr->stack; \ + itr->p->x = b->root; itr->p->i = 0; \ + while (itr->p->x->is_internal && __KB_PTR(b, itr->p->x)[0] != 0) { \ + kbnode_t *x = itr->p->x; \ + ++itr->p; \ + itr->p->x = __KB_PTR(b, x)[0]; itr->p->i = 0; \ + } \ + } \ + static inline int kb_itr_next_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ + { \ + if (itr->p < itr->stack) return 0; \ + for (;;) { \ + ++itr->p->i; \ + while (itr->p->x && itr->p->i <= itr->p->x->n) { \ + itr->p[1].i = 0; \ + itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[itr->p->i] : 0; \ + ++itr->p; \ + } \ + --itr->p; \ + if (itr->p < itr->stack) return 0; \ + if (itr->p->x && itr->p->i < itr->p->x->n) return 1; \ + } \ + } \ + static inline int kb_itr_prev_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ + { \ + if (itr->p < itr->stack) return 0; \ + for (;;) { \ + while (itr->p->x && itr->p->i >= 0) { \ + itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[itr->p->i] : 0; \ + itr->p[1].i = itr->p[1].x ? itr->p[1].x->n : -1; \ + ++itr->p; \ + } \ + --itr->p; \ + if (itr->p < itr->stack) return 0; \ + --itr->p->i; \ + if (itr->p->x && itr->p->i >= 0) return 1; \ + } \ + } \ + static inline int kb_itr_getp_##name(kbtree_##name##_t *b, key_t * __restrict k, kbitr_##name##_t *itr) \ + { \ + if (b->n_keys == 0) { \ + itr->p = NULL; \ + return 0; \ + } \ + int i, r = 0; \ + itr->p = itr->stack; \ + itr->p->x = b->root; \ + while (itr->p->x) { \ + i = __kb_getp_aux_##name(itr->p->x, k, &r); \ + itr->p->i = i; \ + if (i >= 0 && r == 0) return 1; \ + ++itr->p->i; \ + itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[i + 1] : 0; \ + ++itr->p; \ + } \ + return 0; \ + } \ + static inline int kb_itr_get_##name(kbtree_##name##_t *b, key_t k, kbitr_##name##_t *itr) \ + { \ + return kb_itr_getp_##name(b,&k,itr); \ + } \ + static inline void kb_del_itr_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ + { \ + key_t k = kb_itr_key(itr); \ + kb_delp_##name(b, &k); \ + kb_itr_getp_##name(b, &k, itr); \ + } + +#define KBTREE_INIT(name, key_t, __cmp, T) \ + KBTREE_INIT_IMPL(name, key_t, kbnode_##name##_t, __cmp, T, (sizeof(kbnode_##name##_t)+(2*T)*sizeof(void *))) + +#if (!defined(__clang__) && !defined(__INTEL_COMPILER)) && (__GNUC__ > 4 ) + +// The index trickery shouldn't be UB anymore, +// still it is to much for gcc:s -Werror=array-bounds +# define __KB_PRAGMA_START \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Warray-bounds\"") + +# define __KB_PRAGMA_END \ + _Pragma("GCC diagnostic pop") \ + +#else + +# define __KB_PRAGMA_START +# define __KB_PRAGMA_END + +#endif + +#define KBTREE_INIT_IMPL(name, key_t, kbnode_t, __cmp, T, ILEN) \ + __KB_PRAGMA_START \ + __KB_TREE_T(name, key_t, T) \ + __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ + __KB_GET(name, key_t, kbnode_t) \ + __KB_INTERVAL(name, key_t, kbnode_t) \ + __KB_PUT(name, key_t, kbnode_t, __cmp, T, ILEN) \ + __KB_DEL(name, key_t, kbnode_t, T) \ + __KB_ITR(name, key_t, kbnode_t) \ + __KB_PRAGMA_END + +#define KB_DEFAULT_SIZE 512 + +#define kbtree_t(name) kbtree_##name##_t +#define kbitr_t(name) kbitr_##name##_t +#define kb_init(b) ((b)->n_keys = (b)->n_nodes = 0, (b)->root = 0) +#define kb_destroy(name, b) __kb_destroy(kbnode_##name##_t, b) +#define kb_get(name, b, k) kb_get_##name(b, k) +#define kb_put(name, b, k) kb_put_##name(b, k) +#define kb_del(name, b, k) kb_del_##name(b, k) +#define kb_interval(name, b, k, l, u) kb_interval_##name(b, k, l, u) +#define kb_getp(name, b, k) kb_getp_##name(b, k) +#define kb_putp(name, b, k) kb_putp_##name(b, k) +#define kb_delp(name, b, k) kb_delp_##name(b, k) +#define kb_intervalp(name, b, k, l, u) kb_intervalp_##name(b, k, l, u) + +#define kb_itr_first(name, b, i) kb_itr_first_##name(b, i) +#define kb_itr_get(name, b, k, i) kb_itr_get_##name(b, k, i) +#define kb_itr_getp(name, b, k, i) kb_itr_getp_##name(b, k, i) +#define kb_itr_next(name, b, i) kb_itr_next_##name(b, i) +#define kb_itr_prev(name, b, i) kb_itr_prev_##name(b, i) +#define kb_del_itr(name, b, i) kb_del_itr_##name(b, i) +#define kb_itr_key(itr) __KB_KEY(dummy, (itr)->p->x)[(itr)->p->i] +#define kb_itr_valid(itr) ((itr)->p >= (itr)->stack) + +#define kb_size(b) ((b)->n_keys) + +#define kb_generic_cmp(a, b) (((b) < (a)) - ((a) < (b))) +#define kb_str_cmp(a, b) strcmp(a, b) + +#endif // NVIM_LIB_KBTREE_H diff --git a/src/nvim/log.c b/src/nvim/log.c index bbb4dfb944..436a8a4079 100644 --- a/src/nvim/log.c +++ b/src/nvim/log.c @@ -1,23 +1,23 @@ +// 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 <inttypes.h> #include <stdarg.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> +#include <uv.h> #include "nvim/log.h" #include "nvim/types.h" #include "nvim/os/os.h" #include "nvim/os/time.h" -/// First location of the log file used by log_path_init() -#define USR_LOG_FILE "$NVIM_LOG_FILE" - -/// Fall back location of the log file used by log_path_init() -#define USR_LOG_FILE_2 "$HOME" _PATHSEPSTR ".nvimlog" +#define LOG_FILE_ENV "NVIM_LOG_FILE" -/// Cached location of the log file set by log_path_init() -static char expanded_log_file_path[MAXPATHL + 1] = { 0 }; +/// Cached location of the expanded log file path decided by log_path_init(). +static char log_file_path[MAXPATHL + 1] = { 0 }; static uv_mutex_t mutex; @@ -25,31 +25,57 @@ static uv_mutex_t mutex; # include "log.c.generated.h" #endif -/// Initialize path to log file +#ifdef HAVE_EXECINFO_BACKTRACE +# include <execinfo.h> +#endif + +static bool log_try_create(char *fname) +{ + if (fname == NULL || fname[0] == '\0') { + return false; + } + FILE *log_file = fopen(fname, "a"); + if (log_file == NULL) { + return false; + } + fclose(log_file); + return true; +} + +/// Initializes path to log file. Sets $NVIM_LOG_FILE if empty. /// -/// Tries to use #USR_LOG_FILE, then falls back #USR_LOG_FILE_2. Path to log +/// Tries $NVIM_LOG_FILE, or falls back to $XDG_DATA_HOME/nvim/log. Path to log /// file is cached, so only the first call has effect, unless first call was not -/// successful. To make initialization not succeed either a bug in expand_env() -/// is needed or both `$NVIM_LOG_FILE` and `$HOME` environment variables -/// undefined. +/// successful. Failed initialization indicates either a bug in expand_env() +/// or both $NVIM_LOG_FILE and $HOME environment variables are undefined. /// /// @return true if path was initialized, false otherwise. static bool log_path_init(void) { - if (expanded_log_file_path[0]) { + if (log_file_path[0]) { return true; } - expand_env((char_u *)USR_LOG_FILE, (char_u *)expanded_log_file_path, - sizeof(expanded_log_file_path) - 1); - // if the log file path expansion failed then fall back to stderr - if (strcmp(USR_LOG_FILE, expanded_log_file_path) == 0) { - memset(expanded_log_file_path, 0, sizeof(expanded_log_file_path)); - expand_env((char_u *)USR_LOG_FILE_2, (char_u *)expanded_log_file_path, - sizeof(expanded_log_file_path) - 1); - if (strcmp(USR_LOG_FILE_2, expanded_log_file_path) == 0) { - memset(expanded_log_file_path, 0, sizeof(expanded_log_file_path)); + size_t size = sizeof(log_file_path); + expand_env((char_u *)"$" LOG_FILE_ENV, (char_u *)log_file_path, + (int)size - 1); + if (strequal("$" LOG_FILE_ENV, log_file_path) + || log_file_path[0] == '\0' + || os_isdir((char_u *)log_file_path) + || !log_try_create(log_file_path)) { + // Invalid $NVIM_LOG_FILE or failed to expand; fall back to default. + char *defaultpath = stdpaths_user_data_subpath("log", 0, true); + size_t len = xstrlcpy(log_file_path, defaultpath, size); + xfree(defaultpath); + // Fall back to .nvimlog + if (len >= size || !log_try_create(log_file_path)) { + len = xstrlcpy(log_file_path, ".nvimlog", size); + } + // Fall back to stderr + if (len >= size || !log_try_create(log_file_path)) { + log_file_path[0] = '\0'; return false; } + os_setenv(LOG_FILE_ENV, log_file_path, true); } return true; } @@ -72,6 +98,10 @@ void log_unlock(void) bool do_log(int log_level, const char *func_name, int line_num, bool eol, const char* fmt, ...) FUNC_ATTR_UNUSED { + if (log_level < MIN_LOG_LEVEL) { + return false; + } + log_lock(); bool ret = false; FILE *log_file = open_log_file(); @@ -94,26 +124,42 @@ end: return ret; } +void log_uv_handles(void *loop) +{ + uv_loop_t *l = loop; + log_lock(); + FILE *log_file = open_log_file(); + + if (log_file == NULL) { + goto end; + } + + uv_print_all_handles(l, log_file); + + if (log_file != stderr && log_file != stdout) { + fclose(log_file); + } +end: + log_unlock(); +} + /// Open the log file for appending. /// -/// @return The FILE* specified by the USR_LOG_FILE path or stderr in case of -/// error +/// @return FILE* decided by log_path_init() or stderr in case of error FILE *open_log_file(void) { static bool opening_log_file = false; - // check if it's a recursive call if (opening_log_file) { do_log_to_file(stderr, ERROR_LOG_LEVEL, __func__, __LINE__, true, - "Trying to LOG() recursively! Please fix it."); + "Cannot LOG() recursively."); return stderr; } - // expand USR_LOG_FILE if needed and open the file FILE *log_file = NULL; opening_log_file = true; if (log_path_init()) { - log_file = fopen(expanded_log_file_path, "a"); + log_file = fopen(log_file_path, "a"); } opening_log_file = false; @@ -121,13 +167,69 @@ FILE *open_log_file(void) return log_file; } + // May happen if: + // - LOG() is called before early_init() + // - Directory does not exist + // - File is not writable do_log_to_file(stderr, ERROR_LOG_LEVEL, __func__, __LINE__, true, - "Couldn't open USR_LOG_FILE, logging to stderr! This may be " - "caused by attempting to LOG() before initialization " - "functions are called (e.g. init_homedir())."); + "Logging to stderr, failed to open $" LOG_FILE_ENV ": %s", + log_file_path); return stderr; } +#ifdef HAVE_EXECINFO_BACKTRACE +void log_callstack_to_file(FILE *log_file, const char *const func_name, + const int line_num) +{ + void *trace[100]; + int trace_size = backtrace(trace, ARRAY_SIZE(trace)); + + char exepath[MAXPATHL] = { 0 }; + size_t exepathlen = MAXPATHL; + if (os_exepath(exepath, &exepathlen) != 0) { + abort(); + } + assert(24 + exepathlen < IOSIZE); // Must fit in `cmdbuf` below. + + char cmdbuf[IOSIZE + (20 * ARRAY_SIZE(trace))]; + snprintf(cmdbuf, sizeof(cmdbuf), "addr2line -e %s -f -p", exepath); + for (int i = 1; i < trace_size; i++) { + char buf[20]; // 64-bit pointer 0xNNNNNNNNNNNNNNNN with leading space. + snprintf(buf, sizeof(buf), " %p", trace[i]); + xstrlcat(cmdbuf, buf, sizeof(cmdbuf)); + } + // Now we have a command string like: + // addr2line -e /path/to/exe -f -p 0x123 0x456 ... + + do_log_to_file(log_file, DEBUG_LOG_LEVEL, func_name, line_num, true, + "trace:"); + FILE *fp = popen(cmdbuf, "r"); + char linebuf[IOSIZE]; + while (fgets(linebuf, sizeof(linebuf) - 1, fp) != NULL) { + fprintf(log_file, " %s", linebuf); + } + pclose(fp); + + if (log_file != stderr && log_file != stdout) { + fclose(log_file); + } +} + +void log_callstack(const char *const func_name, const int line_num) +{ + log_lock(); + FILE *log_file = open_log_file(); + if (log_file == NULL) { + goto end; + } + + log_callstack_to_file(log_file, func_name, line_num); + +end: + log_unlock(); +} +#endif + static bool do_log_to_file(FILE *log_file, int log_level, const char *func_name, int line_num, bool eol, const char* fmt, ...) @@ -148,8 +250,8 @@ static bool v_do_log_to_file(FILE *log_file, int log_level, static const char *log_levels[] = { [DEBUG_LOG_LEVEL] = "DEBUG", [INFO_LOG_LEVEL] = "INFO ", - [WARNING_LOG_LEVEL] = "WARN ", - [ERROR_LOG_LEVEL] = "ERROR" + [WARN_LOG_LEVEL] = "WARN ", + [ERROR_LOG_LEVEL] = "ERROR", }; assert(log_level >= DEBUG_LOG_LEVEL && log_level <= ERROR_LOG_LEVEL); diff --git a/src/nvim/log.h b/src/nvim/log.h index 32b7276f14..d63bcc366c 100644 --- a/src/nvim/log.h +++ b/src/nvim/log.h @@ -6,7 +6,7 @@ #define DEBUG_LOG_LEVEL 0 #define INFO_LOG_LEVEL 1 -#define WARNING_LOG_LEVEL 2 +#define WARN_LOG_LEVEL 2 #define ERROR_LOG_LEVEL 3 #define DLOG(...) @@ -18,55 +18,52 @@ #define ELOG(...) #define ELOGN(...) -// Logging is disabled if NDEBUG or DISABLE_LOG is defined. -#if !defined(DISABLE_LOG) && defined(NDEBUG) -# define DISABLE_LOG -#endif - -// MIN_LOG_LEVEL can be defined during compilation to adjust the desired level -// of logging. INFO_LOG_LEVEL is used by default. #ifndef MIN_LOG_LEVEL # define MIN_LOG_LEVEL INFO_LOG_LEVEL #endif -#ifndef DISABLE_LOG +#define LOG(level, ...) do_log((level), __func__, __LINE__, true, \ + __VA_ARGS__) -# if MIN_LOG_LEVEL <= DEBUG_LOG_LEVEL -# undef DLOG -# undef DLOGN -# define DLOG(...) do_log(DEBUG_LOG_LEVEL, __func__, __LINE__, true, \ - __VA_ARGS__) -# define DLOGN(...) do_log(DEBUG_LOG_LEVEL, __func__, __LINE__, false, \ - __VA_ARGS__) -# endif +#if MIN_LOG_LEVEL <= DEBUG_LOG_LEVEL +# undef DLOG +# undef DLOGN +# define DLOG(...) do_log(DEBUG_LOG_LEVEL, __func__, __LINE__, true, \ + __VA_ARGS__) +# define DLOGN(...) do_log(DEBUG_LOG_LEVEL, __func__, __LINE__, false, \ + __VA_ARGS__) +#endif -# if MIN_LOG_LEVEL <= INFO_LOG_LEVEL -# undef ILOG -# undef ILOGN -# define ILOG(...) do_log(INFO_LOG_LEVEL, __func__, __LINE__, true, \ - __VA_ARGS__) -# define ILOGN(...) do_log(INFO_LOG_LEVEL, __func__, __LINE__, false, \ - __VA_ARGS__) -# endif +#if MIN_LOG_LEVEL <= INFO_LOG_LEVEL +# undef ILOG +# undef ILOGN +# define ILOG(...) do_log(INFO_LOG_LEVEL, __func__, __LINE__, true, \ + __VA_ARGS__) +# define ILOGN(...) do_log(INFO_LOG_LEVEL, __func__, __LINE__, false, \ + __VA_ARGS__) +#endif -# if MIN_LOG_LEVEL <= WARNING_LOG_LEVEL -# undef WLOG -# undef WLOGN -# define WLOG(...) do_log(WARNING_LOG_LEVEL, __func__, __LINE__, true, \ - __VA_ARGS__) -# define WLOGN(...) do_log(WARNING_LOG_LEVEL, __func__, __LINE__, false, \ - __VA_ARGS__) -# endif +#if MIN_LOG_LEVEL <= WARN_LOG_LEVEL +# undef WLOG +# undef WLOGN +# define WLOG(...) do_log(WARN_LOG_LEVEL, __func__, __LINE__, true, \ + __VA_ARGS__) +# define WLOGN(...) do_log(WARN_LOG_LEVEL, __func__, __LINE__, false, \ + __VA_ARGS__) +#endif -# if MIN_LOG_LEVEL <= ERROR_LOG_LEVEL -# undef ELOG -# undef ELOGN -# define ELOG(...) do_log(ERROR_LOG_LEVEL, __func__, __LINE__, true, \ - __VA_ARGS__) -# define ELOGN(...) do_log(ERROR_LOG_LEVEL, __func__, __LINE__, false, \ - __VA_ARGS__) -# endif +#if MIN_LOG_LEVEL <= ERROR_LOG_LEVEL +# undef ELOG +# undef ELOGN +# define ELOG(...) do_log(ERROR_LOG_LEVEL, __func__, __LINE__, true, \ + __VA_ARGS__) +# define ELOGN(...) do_log(ERROR_LOG_LEVEL, __func__, __LINE__, false, \ + __VA_ARGS__) +#endif +#ifdef HAVE_EXECINFO_BACKTRACE +# define LOG_CALLSTACK() log_callstack(__func__, __LINE__) +# define LOG_CALLSTACK_TO_FILE(fp) log_callstack_to_file(fp, __func__, __LINE__) #endif #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c new file mode 100644 index 0000000000..cacba3ce87 --- /dev/null +++ b/src/nvim/lua/converter.c @@ -0,0 +1,1189 @@ +// 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 <lua.h> +#include <lualib.h> +#include <lauxlib.h> +#include <assert.h> +#include <stdint.h> +#include <stdbool.h> + +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" +#include "nvim/func_attr.h" +#include "nvim/memory.h" +#include "nvim/assert.h" +// FIXME: vim.h is not actually needed, but otherwise it states MAXPATHL is +// redefined +#include "nvim/vim.h" +#include "nvim/globals.h" +#include "nvim/message.h" +#include "nvim/eval/typval.h" +#include "nvim/ascii.h" +#include "nvim/macros.h" + +#include "nvim/lib/kvec.h" +#include "nvim/eval/decode.h" + +#include "nvim/lua/converter.h" +#include "nvim/lua/executor.h" + +/// Determine, which keys lua table contains +typedef struct { + size_t maxidx; ///< Maximum positive integral value found. + size_t string_keys_num; ///< Number of string keys. + bool has_string_with_nul; ///< True if there is string key with NUL byte. + ObjectType type; ///< If has_type_key is true then attached value. Otherwise + ///< either kObjectTypeNil, kObjectTypeDictionary or + ///< kObjectTypeArray, depending on other properties. + lua_Number val; ///< If has_val_key and val_type == LUA_TNUMBER: value. + bool has_type_key; ///< True if type key is present. +} LuaTableProps; + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "lua/converter.c.generated.h" +#endif + +#define TYPE_IDX_VALUE true +#define VAL_IDX_VALUE false + +#define LUA_PUSH_STATIC_STRING(lstate, s) \ + lua_pushlstring(lstate, s, sizeof(s) - 1) + +static LuaTableProps nlua_traverse_table(lua_State *const lstate) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + size_t tsize = 0; // Total number of keys. + int val_type = 0; // If has_val_key: lua type of the value. + bool has_val_key = false; // True if val key was found, + // @see nlua_push_val_idx(). + size_t other_keys_num = 0; // Number of keys that are not string, integral + // or type keys. + LuaTableProps ret; + memset(&ret, 0, sizeof(ret)); + if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) { + emsgf(_("E1502: Lua failed to grow stack to %i"), lua_gettop(lstate) + 2); + ret.type = kObjectTypeNil; + return ret; + } + lua_pushnil(lstate); + while (lua_next(lstate, -2)) { + switch (lua_type(lstate, -2)) { + case LUA_TSTRING: { + size_t len; + const char *s = lua_tolstring(lstate, -2, &len); + if (memchr(s, NUL, len) != NULL) { + ret.has_string_with_nul = true; + } + ret.string_keys_num++; + break; + } + case LUA_TNUMBER: { + const lua_Number n = lua_tonumber(lstate, -2); + if (n > (lua_Number)SIZE_MAX || n <= 0 + || ((lua_Number)((size_t)n)) != n) { + other_keys_num++; + } else { + const size_t idx = (size_t)n; + if (idx > ret.maxidx) { + ret.maxidx = idx; + } + } + break; + } + case LUA_TBOOLEAN: { + const bool b = lua_toboolean(lstate, -2); + if (b == TYPE_IDX_VALUE) { + if (lua_type(lstate, -1) == LUA_TNUMBER) { + lua_Number n = lua_tonumber(lstate, -1); + if (n == (lua_Number)kObjectTypeFloat + || n == (lua_Number)kObjectTypeArray + || n == (lua_Number)kObjectTypeDictionary) { + ret.has_type_key = true; + ret.type = (ObjectType)n; + } else { + other_keys_num++; + } + } else { + other_keys_num++; + } + } else { + has_val_key = true; + val_type = lua_type(lstate, -1); + if (val_type == LUA_TNUMBER) { + ret.val = lua_tonumber(lstate, -1); + } + } + break; + } + default: { + other_keys_num++; + break; + } + } + tsize++; + lua_pop(lstate, 1); + } + if (ret.has_type_key) { + if (ret.type == kObjectTypeFloat + && (!has_val_key || val_type != LUA_TNUMBER)) { + ret.type = kObjectTypeNil; + } else if (ret.type == kObjectTypeArray) { + // Determine what is the last number in a *sequence* of keys. + // This condition makes sure that Neovim will not crash when it gets table + // {[vim.type_idx]=vim.types.array, [SIZE_MAX]=1}: without it maxidx will + // be SIZE_MAX, with this condition it should be zero and [SIZE_MAX] key + // should be ignored. + if (ret.maxidx != 0 + && ret.maxidx != (tsize + - ret.has_type_key + - other_keys_num + - has_val_key + - ret.string_keys_num)) { + for (ret.maxidx = 0;; ret.maxidx++) { + lua_rawgeti(lstate, -1, (int)ret.maxidx + 1); + if (lua_isnil(lstate, -1)) { + lua_pop(lstate, 1); + break; + } + lua_pop(lstate, 1); + } + } + } + } else { + if (tsize == 0 + || (tsize == ret.maxidx + && other_keys_num == 0 + && ret.string_keys_num == 0)) { + ret.type = kObjectTypeArray; + } else if (ret.string_keys_num == tsize) { + ret.type = kObjectTypeDictionary; + } else { + ret.type = kObjectTypeNil; + } + } + return ret; +} + +/// Helper structure for nlua_pop_typval +typedef struct { + typval_T *tv; ///< Location where conversion result is saved. + bool container; ///< True if tv is a container. + bool special; ///< If true then tv is a _VAL part of special dictionary + ///< that represents mapping. + int idx; ///< Container index (used to detect self-referencing structures). +} TVPopStackItem; + +/// Convert lua object to VimL typval_T +/// +/// Should pop exactly one value from lua stack. +/// +/// @param lstate Lua state. +/// @param[out] ret_tv Where to put the result. +/// +/// @return `true` in case of success, `false` in case of failure. Error is +/// reported automatically. +bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv) +{ + bool ret = true; + const int initial_size = lua_gettop(lstate); + kvec_t(TVPopStackItem) stack = KV_INITIAL_VALUE; + kv_push(stack, ((TVPopStackItem) { ret_tv, false, false, 0 })); + while (ret && kv_size(stack)) { + if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) { + emsgf(_("E1502: Lua failed to grow stack to %i"), lua_gettop(lstate) + 3); + ret = false; + break; + } + TVPopStackItem cur = kv_pop(stack); + if (cur.container) { + if (cur.special || cur.tv->v_type == VAR_DICT) { + assert(cur.tv->v_type == (cur.special ? VAR_LIST : VAR_DICT)); + bool next_key_found = false; + while (lua_next(lstate, -2)) { + if (lua_type(lstate, -2) == LUA_TSTRING) { + next_key_found = true; + break; + } + lua_pop(lstate, 1); + } + if (next_key_found) { + size_t len; + const char *s = lua_tolstring(lstate, -2, &len); + if (cur.special) { + list_T *const kv_pair = tv_list_alloc(); + tv_list_append_list(cur.tv->vval.v_list, kv_pair); + listitem_T *const key = tv_list_item_alloc(); + key->li_tv = decode_string(s, len, kTrue, false, false); + tv_list_append(kv_pair, key); + if (key->li_tv.v_type == VAR_UNKNOWN) { + ret = false; + tv_list_unref(kv_pair); + continue; + } + listitem_T *const val = tv_list_item_alloc(); + tv_list_append(kv_pair, val); + kv_push(stack, cur); + cur = (TVPopStackItem) { &val->li_tv, false, false, 0 }; + } else { + dictitem_T *const di = tv_dict_item_alloc_len(s, len); + if (tv_dict_add(cur.tv->vval.v_dict, di) == FAIL) { + assert(false); + } + kv_push(stack, cur); + cur = (TVPopStackItem) { &di->di_tv, false, false, 0 }; + } + } else { + lua_pop(lstate, 1); + continue; + } + } else { + assert(cur.tv->v_type == VAR_LIST); + lua_rawgeti(lstate, -1, cur.tv->vval.v_list->lv_len + 1); + if (lua_isnil(lstate, -1)) { + lua_pop(lstate, 2); + continue; + } + listitem_T *const li = tv_list_item_alloc(); + tv_list_append(cur.tv->vval.v_list, li); + kv_push(stack, cur); + cur = (TVPopStackItem) { &li->li_tv, false, false, 0 }; + } + } + assert(!cur.container); + *cur.tv = (typval_T) { + .v_type = VAR_NUMBER, + .v_lock = VAR_UNLOCKED, + .vval = { .v_number = 0 }, + }; + switch (lua_type(lstate, -1)) { + case LUA_TNIL: { + cur.tv->v_type = VAR_SPECIAL; + cur.tv->vval.v_special = kSpecialVarNull; + break; + } + case LUA_TBOOLEAN: { + cur.tv->v_type = VAR_SPECIAL; + cur.tv->vval.v_special = (lua_toboolean(lstate, -1) + ? kSpecialVarTrue + : kSpecialVarFalse); + break; + } + case LUA_TSTRING: { + size_t len; + const char *s = lua_tolstring(lstate, -1, &len); + *cur.tv = decode_string(s, len, kNone, true, false); + if (cur.tv->v_type == VAR_UNKNOWN) { + ret = false; + } + break; + } + case LUA_TNUMBER: { + const lua_Number n = lua_tonumber(lstate, -1); + if (n > (lua_Number)VARNUMBER_MAX || n < (lua_Number)VARNUMBER_MIN + || ((lua_Number)((varnumber_T)n)) != n) { + cur.tv->v_type = VAR_FLOAT; + cur.tv->vval.v_float = (float_T)n; + } else { + cur.tv->v_type = VAR_NUMBER; + cur.tv->vval.v_number = (varnumber_T)n; + } + break; + } + case LUA_TTABLE: { + const LuaTableProps table_props = nlua_traverse_table(lstate); + + for (size_t i = 0; i < kv_size(stack); i++) { + const TVPopStackItem item = kv_A(stack, i); + if (item.container && lua_rawequal(lstate, -1, item.idx)) { + tv_copy(item.tv, cur.tv); + cur.container = false; + goto nlua_pop_typval_table_processing_end; + } + } + + switch (table_props.type) { + case kObjectTypeArray: { + cur.tv->v_type = VAR_LIST; + cur.tv->vval.v_list = tv_list_alloc(); + cur.tv->vval.v_list->lv_refcount++; + if (table_props.maxidx != 0) { + cur.container = true; + cur.idx = lua_gettop(lstate); + kv_push(stack, cur); + } + break; + } + case kObjectTypeDictionary: { + if (table_props.string_keys_num == 0) { + cur.tv->v_type = VAR_DICT; + cur.tv->vval.v_dict = tv_dict_alloc(); + cur.tv->vval.v_dict->dv_refcount++; + } else { + cur.special = table_props.has_string_with_nul; + if (table_props.has_string_with_nul) { + decode_create_map_special_dict(cur.tv); + assert(cur.tv->v_type == VAR_DICT); + dictitem_T *const val_di = tv_dict_find(cur.tv->vval.v_dict, + S_LEN("_VAL")); + assert(val_di != NULL); + cur.tv = &val_di->di_tv; + assert(cur.tv->v_type == VAR_LIST); + } else { + cur.tv->v_type = VAR_DICT; + cur.tv->vval.v_dict = tv_dict_alloc(); + cur.tv->vval.v_dict->dv_refcount++; + } + cur.container = true; + cur.idx = lua_gettop(lstate); + kv_push(stack, cur); + lua_pushnil(lstate); + } + break; + } + case kObjectTypeFloat: { + cur.tv->v_type = VAR_FLOAT; + cur.tv->vval.v_float = (float_T)table_props.val; + break; + } + case kObjectTypeNil: { + EMSG(_("E5100: Cannot convert given lua table: table " + "should either have a sequence of positive integer keys " + "or contain only string keys")); + ret = false; + break; + } + default: { + assert(false); + } + } +nlua_pop_typval_table_processing_end: + break; + } + default: { + EMSG(_("E5101: Cannot convert given lua type")); + ret = false; + break; + } + } + if (!cur.container) { + lua_pop(lstate, 1); + } + } + kv_destroy(stack); + if (!ret) { + tv_clear(ret_tv); + *ret_tv = (typval_T) { + .v_type = VAR_NUMBER, + .v_lock = VAR_UNLOCKED, + .vval = { .v_number = 0 }, + }; + lua_pop(lstate, lua_gettop(lstate) - initial_size + 1); + } + assert(lua_gettop(lstate) == initial_size - 1); + return ret; +} + +#define TYPVAL_ENCODE_ALLOW_SPECIALS true + +#define TYPVAL_ENCODE_CONV_NIL(tv) \ + lua_pushnil(lstate) + +#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ + lua_pushboolean(lstate, (bool)(num)) + +#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ + lua_pushnumber(lstate, (lua_Number)(num)) + +#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER TYPVAL_ENCODE_CONV_NUMBER + +#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ + TYPVAL_ENCODE_CONV_NUMBER(tv, flt) + +#define TYPVAL_ENCODE_CONV_STRING(tv, str, len) \ + lua_pushlstring(lstate, (const char *)(str), (len)) + +#define TYPVAL_ENCODE_CONV_STR_STRING TYPVAL_ENCODE_CONV_STRING + +#define TYPVAL_ENCODE_CONV_EXT_STRING(tv, str, len, type) \ + TYPVAL_ENCODE_CONV_NIL() + +#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ + do { \ + TYPVAL_ENCODE_CONV_NIL(tv); \ + goto typval_encode_stop_converting_one_item; \ + } while (0) + +#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) +#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) +#define TYPVAL_ENCODE_CONV_FUNC_END(tv) + +#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \ + lua_createtable(lstate, 0, 0) + +#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ + nlua_create_typed_table(lstate, 0, 0, kObjectTypeDictionary) + +#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \ + do { \ + if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) { \ + emsgf(_("E5102: Lua failed to grow stack to %i"), \ + lua_gettop(lstate) + 3); \ + return false; \ + } \ + lua_createtable(lstate, (int)(len), 0); \ + lua_pushnumber(lstate, 1); \ + } while (0) + +#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) + +#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) \ + do { \ + lua_Number idx = lua_tonumber(lstate, -2); \ + lua_rawset(lstate, -3); \ + lua_pushnumber(lstate, idx + 1); \ + } while (0) + +#define TYPVAL_ENCODE_CONV_LIST_END(tv) \ + lua_rawset(lstate, -3) + +#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ + do { \ + if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) { \ + emsgf(_("E5102: Lua failed to grow stack to %i"), \ + lua_gettop(lstate) + 3); \ + return false; \ + } \ + lua_createtable(lstate, 0, (int)(len)); \ + } while (0) + +#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, kv_pair) + +#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) + +#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) + +#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) \ + lua_rawset(lstate, -3) + +#define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \ + TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) + +#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ + do { \ + for (size_t backref = kv_size(*mpstack); backref; backref--) { \ + const MPConvStackVal mpval = kv_A(*mpstack, backref - 1); \ + if (mpval.type == conv_type) { \ + if (conv_type == kMPConvDict \ + ? (void *)mpval.data.d.dict == (void *)(val) \ + : (void *)mpval.data.l.list == (void *)(val)) { \ + lua_pushvalue(lstate, \ + -((int)((kv_size(*mpstack) - backref + 1) * 2))); \ + break; \ + } \ + } \ + } \ + } while (0) + +#define TYPVAL_ENCODE_SCOPE static +#define TYPVAL_ENCODE_NAME lua +#define TYPVAL_ENCODE_FIRST_ARG_TYPE lua_State *const +#define TYPVAL_ENCODE_FIRST_ARG_NAME lstate +#include "nvim/eval/typval_encode.c.h" +#undef TYPVAL_ENCODE_SCOPE +#undef TYPVAL_ENCODE_NAME +#undef TYPVAL_ENCODE_FIRST_ARG_TYPE +#undef TYPVAL_ENCODE_FIRST_ARG_NAME + +#undef TYPVAL_ENCODE_CONV_STRING +#undef TYPVAL_ENCODE_CONV_STR_STRING +#undef TYPVAL_ENCODE_CONV_EXT_STRING +#undef TYPVAL_ENCODE_CONV_NUMBER +#undef TYPVAL_ENCODE_CONV_FLOAT +#undef TYPVAL_ENCODE_CONV_FUNC_START +#undef TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS +#undef TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF +#undef TYPVAL_ENCODE_CONV_FUNC_END +#undef TYPVAL_ENCODE_CONV_EMPTY_LIST +#undef TYPVAL_ENCODE_CONV_LIST_START +#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START +#undef TYPVAL_ENCODE_CONV_EMPTY_DICT +#undef TYPVAL_ENCODE_CONV_NIL +#undef TYPVAL_ENCODE_CONV_BOOL +#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER +#undef TYPVAL_ENCODE_CONV_DICT_START +#undef TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START +#undef TYPVAL_ENCODE_CONV_DICT_END +#undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY +#undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS +#undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK +#undef TYPVAL_ENCODE_CONV_LIST_END +#undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS +#undef TYPVAL_ENCODE_CONV_RECURSE +#undef TYPVAL_ENCODE_ALLOW_SPECIALS + +/// Convert VimL typval_T to lua value +/// +/// Should leave single value in lua stack. May only fail if lua failed to grow +/// stack. +/// +/// @param lstate Lua interpreter state. +/// @param[in] tv typval_T to convert. +/// +/// @return true in case of success, false otherwise. +bool nlua_push_typval(lua_State *lstate, typval_T *const tv) +{ + const int initial_size = lua_gettop(lstate); + if (!lua_checkstack(lstate, initial_size + 2)) { + emsgf(_("E1502: Lua failed to grow stack to %i"), initial_size + 4); + return false; + } + if (encode_vim_to_lua(lstate, tv, "nlua_push_typval argument") == FAIL) { + return false; + } + assert(lua_gettop(lstate) == initial_size + 1); + return true; +} + +/// Push value which is a type index +/// +/// Used for all “typed†tables: i.e. for all tables which represent VimL +/// values. +static inline void nlua_push_type_idx(lua_State *lstate) + FUNC_ATTR_NONNULL_ALL +{ + lua_pushboolean(lstate, TYPE_IDX_VALUE); +} + +/// Push value which is a value index +/// +/// Used for tables which represent scalar values, like float value. +static inline void nlua_push_val_idx(lua_State *lstate) + FUNC_ATTR_NONNULL_ALL +{ + lua_pushboolean(lstate, VAL_IDX_VALUE); +} + +/// Push type +/// +/// Type is a value in vim.types table. +/// +/// @param[out] lstate Lua state. +/// @param[in] type Type to push. +static inline void nlua_push_type(lua_State *lstate, ObjectType type) + FUNC_ATTR_NONNULL_ALL +{ + lua_pushnumber(lstate, (lua_Number)type); +} + +/// Create lua table which has an entry that determines its VimL type +/// +/// @param[out] lstate Lua state. +/// @param[in] narr Number of “array†entries to be populated later. +/// @param[in] nrec Number of “dictionary†entries to be populated later. +/// @param[in] type Type of the table. +static inline void nlua_create_typed_table(lua_State *lstate, + const size_t narr, + const size_t nrec, + const ObjectType type) + FUNC_ATTR_NONNULL_ALL +{ + lua_createtable(lstate, (int)narr, (int)(1 + nrec)); + nlua_push_type_idx(lstate); + nlua_push_type(lstate, type); + lua_rawset(lstate, -3); +} + + +/// Convert given String to lua string +/// +/// Leaves converted string on top of the stack. +void nlua_push_String(lua_State *lstate, const String s) + FUNC_ATTR_NONNULL_ALL +{ + lua_pushlstring(lstate, s.data, s.size); +} + +/// Convert given Integer to lua number +/// +/// Leaves converted number on top of the stack. +void nlua_push_Integer(lua_State *lstate, const Integer n) + FUNC_ATTR_NONNULL_ALL +{ + lua_pushnumber(lstate, (lua_Number)n); +} + +/// Convert given Float to lua table +/// +/// Leaves converted table on top of the stack. +void nlua_push_Float(lua_State *lstate, const Float f) + FUNC_ATTR_NONNULL_ALL +{ + nlua_create_typed_table(lstate, 0, 1, kObjectTypeFloat); + nlua_push_val_idx(lstate); + lua_pushnumber(lstate, (lua_Number)f); + lua_rawset(lstate, -3); +} + +/// Convert given Float to lua boolean +/// +/// Leaves converted value on top of the stack. +void nlua_push_Boolean(lua_State *lstate, const Boolean b) + FUNC_ATTR_NONNULL_ALL +{ + lua_pushboolean(lstate, b); +} + +/// Convert given Dictionary to lua table +/// +/// Leaves converted table on top of the stack. +void nlua_push_Dictionary(lua_State *lstate, const Dictionary dict) + FUNC_ATTR_NONNULL_ALL +{ + if (dict.size == 0) { + nlua_create_typed_table(lstate, 0, 0, kObjectTypeDictionary); + } else { + lua_createtable(lstate, 0, (int)dict.size); + } + for (size_t i = 0; i < dict.size; i++) { + nlua_push_String(lstate, dict.items[i].key); + nlua_push_Object(lstate, dict.items[i].value); + lua_rawset(lstate, -3); + } +} + +/// Convert given Array to lua table +/// +/// Leaves converted table on top of the stack. +void nlua_push_Array(lua_State *lstate, const Array array) + FUNC_ATTR_NONNULL_ALL +{ + lua_createtable(lstate, (int)array.size, 0); + for (size_t i = 0; i < array.size; i++) { + nlua_push_Object(lstate, array.items[i]); + lua_rawseti(lstate, -2, (int)i + 1); + } +} + +#define GENERATE_INDEX_FUNCTION(type) \ +void nlua_push_##type(lua_State *lstate, const type item) \ + FUNC_ATTR_NONNULL_ALL \ +{ \ + lua_pushnumber(lstate, (lua_Number)(item)); \ +} + +GENERATE_INDEX_FUNCTION(Buffer) +GENERATE_INDEX_FUNCTION(Window) +GENERATE_INDEX_FUNCTION(Tabpage) + +#undef GENERATE_INDEX_FUNCTION + +/// Convert given Object to lua value +/// +/// Leaves converted value on top of the stack. +void nlua_push_Object(lua_State *lstate, const Object obj) + FUNC_ATTR_NONNULL_ALL +{ + switch (obj.type) { + case kObjectTypeNil: { + lua_pushnil(lstate); + break; + } +#define ADD_TYPE(type, data_key) \ + case kObjectType##type: { \ + nlua_push_##type(lstate, obj.data.data_key); \ + break; \ + } + ADD_TYPE(Boolean, boolean) + ADD_TYPE(Integer, integer) + ADD_TYPE(Float, floating) + ADD_TYPE(String, string) + ADD_TYPE(Array, array) + ADD_TYPE(Dictionary, dictionary) +#undef ADD_TYPE +#define ADD_REMOTE_TYPE(type) \ + case kObjectType##type: { \ + nlua_push_##type(lstate, (type)obj.data.integer); \ + break; \ + } + ADD_REMOTE_TYPE(Buffer) + ADD_REMOTE_TYPE(Window) + ADD_REMOTE_TYPE(Tabpage) +#undef ADD_REMOTE_TYPE + } +} + + +/// Convert lua value to string +/// +/// Always pops one value from the stack. +String nlua_pop_String(lua_State *lstate, Error *err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (lua_type(lstate, -1) != LUA_TSTRING) { + lua_pop(lstate, 1); + api_set_error(err, kErrorTypeValidation, "Expected lua string"); + return (String) { .size = 0, .data = NULL }; + } + String ret; + + ret.data = (char *)lua_tolstring(lstate, -1, &(ret.size)); + assert(ret.data != NULL); + ret.data = xmemdupz(ret.data, ret.size); + lua_pop(lstate, 1); + + return ret; +} + +/// Convert lua value to integer +/// +/// Always pops one value from the stack. +Integer nlua_pop_Integer(lua_State *lstate, Error *err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (lua_type(lstate, -1) != LUA_TNUMBER) { + lua_pop(lstate, 1); + api_set_error(err, kErrorTypeValidation, "Expected lua number"); + return 0; + } + const lua_Number n = lua_tonumber(lstate, -1); + lua_pop(lstate, 1); + if (n > (lua_Number)API_INTEGER_MAX || n < (lua_Number)API_INTEGER_MIN + || ((lua_Number)((Integer)n)) != n) { + api_set_error(err, kErrorTypeException, "Number is not integral"); + return 0; + } + return (Integer)n; +} + +/// Convert lua value to boolean +/// +/// Always pops one value from the stack. +Boolean nlua_pop_Boolean(lua_State *lstate, Error *err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + const Boolean ret = lua_toboolean(lstate, -1); + lua_pop(lstate, 1); + return ret; +} + +/// Check whether typed table on top of the stack has given type +/// +/// @param[in] lstate Lua state. +/// @param[out] err Location where error will be saved. May be NULL. +/// @param[in] type Type to check. +/// +/// @return @see nlua_traverse_table(). +static inline LuaTableProps nlua_check_type(lua_State *const lstate, + Error *const err, + const ObjectType type) + FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (lua_type(lstate, -1) != LUA_TTABLE) { + if (err) { + api_set_error(err, kErrorTypeValidation, "Expected lua table"); + } + return (LuaTableProps) { .type = kObjectTypeNil }; + } + LuaTableProps table_props = nlua_traverse_table(lstate); + + if (type == kObjectTypeDictionary && table_props.type == kObjectTypeArray + && table_props.maxidx == 0 && !table_props.has_type_key) { + table_props.type = kObjectTypeDictionary; + } + + if (table_props.type != type) { + if (err) { + api_set_error(err, kErrorTypeValidation, "Unexpected type"); + } + } + + return table_props; +} + +/// Convert lua table to float +/// +/// Always pops one value from the stack. +Float nlua_pop_Float(lua_State *lstate, Error *err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (lua_type(lstate, -1) == LUA_TNUMBER) { + const Float ret = (Float)lua_tonumber(lstate, -1); + lua_pop(lstate, 1); + return ret; + } + + const LuaTableProps table_props = nlua_check_type(lstate, err, + kObjectTypeFloat); + lua_pop(lstate, 1); + if (table_props.type != kObjectTypeFloat) { + return 0; + } else { + return (Float)table_props.val; + } +} + +/// Convert lua table to array without determining whether it is array +/// +/// @param lstate Lua state. +/// @param[in] table_props nlua_traverse_table() output. +/// @param[out] err Location where error will be saved. +static Array nlua_pop_Array_unchecked(lua_State *const lstate, + const LuaTableProps table_props, + Error *const err) +{ + Array ret = { .size = table_props.maxidx, .items = NULL }; + + if (ret.size == 0) { + lua_pop(lstate, 1); + return ret; + } + + ret.items = xcalloc(ret.size, sizeof(*ret.items)); + for (size_t i = 1; i <= ret.size; i++) { + Object val; + + lua_rawgeti(lstate, -1, (int)i); + + val = nlua_pop_Object(lstate, err); + if (ERROR_SET(err)) { + ret.size = i - 1; + lua_pop(lstate, 1); + api_free_array(ret); + return (Array) { .size = 0, .items = NULL }; + } + ret.items[i - 1] = val; + } + lua_pop(lstate, 1); + + return ret; +} + +/// Convert lua table to array +/// +/// Always pops one value from the stack. +Array nlua_pop_Array(lua_State *lstate, Error *err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + const LuaTableProps table_props = nlua_check_type(lstate, err, + kObjectTypeArray); + if (table_props.type != kObjectTypeArray) { + return (Array) { .size = 0, .items = NULL }; + } + return nlua_pop_Array_unchecked(lstate, table_props, err); +} + +/// Convert lua table to dictionary +/// +/// Always pops one value from the stack. Does not check whether whether topmost +/// value on the stack is a table. +/// +/// @param lstate Lua interpreter state. +/// @param[in] table_props nlua_traverse_table() output. +/// @param[out] err Location where error will be saved. +static Dictionary nlua_pop_Dictionary_unchecked(lua_State *lstate, + const LuaTableProps table_props, + Error *err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + Dictionary ret = { .size = table_props.string_keys_num, .items = NULL }; + + if (ret.size == 0) { + lua_pop(lstate, 1); + return ret; + } + ret.items = xcalloc(ret.size, sizeof(*ret.items)); + + lua_pushnil(lstate); + for (size_t i = 0; lua_next(lstate, -2) && i < ret.size;) { + // stack: dict, key, value + + if (lua_type(lstate, -2) == LUA_TSTRING) { + lua_pushvalue(lstate, -2); + // stack: dict, key, value, key + + ret.items[i].key = nlua_pop_String(lstate, err); + // stack: dict, key, value + + if (!ERROR_SET(err)) { + ret.items[i].value = nlua_pop_Object(lstate, err); + // stack: dict, key + } else { + lua_pop(lstate, 1); + // stack: dict, key + } + + if (ERROR_SET(err)) { + ret.size = i; + api_free_dictionary(ret); + lua_pop(lstate, 2); + // stack: + return (Dictionary) { .size = 0, .items = NULL }; + } + i++; + } else { + lua_pop(lstate, 1); + // stack: dict, key + } + } + lua_pop(lstate, 1); + + return ret; +} + +/// Convert lua table to dictionary +/// +/// Always pops one value from the stack. +Dictionary nlua_pop_Dictionary(lua_State *lstate, Error *err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + const LuaTableProps table_props = nlua_check_type(lstate, err, + kObjectTypeDictionary); + if (table_props.type != kObjectTypeDictionary) { + lua_pop(lstate, 1); + return (Dictionary) { .size = 0, .items = NULL }; + } + + return nlua_pop_Dictionary_unchecked(lstate, table_props, err); +} + +/// Helper structure for nlua_pop_Object +typedef struct { + Object *obj; ///< Location where conversion result is saved. + bool container; ///< True if tv is a container. +} ObjPopStackItem; + +/// Convert lua table to object +/// +/// Always pops one value from the stack. +Object nlua_pop_Object(lua_State *const lstate, Error *const err) +{ + Object ret = NIL; + const int initial_size = lua_gettop(lstate); + kvec_t(ObjPopStackItem) stack = KV_INITIAL_VALUE; + kv_push(stack, ((ObjPopStackItem) { &ret, false })); + while (!ERROR_SET(err) && kv_size(stack)) { + if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) { + api_set_error(err, kErrorTypeException, "Lua failed to grow stack"); + break; + } + ObjPopStackItem cur = kv_pop(stack); + if (cur.container) { + if (cur.obj->type == kObjectTypeDictionary) { + // stack: …, dict, key + if (cur.obj->data.dictionary.size + == cur.obj->data.dictionary.capacity) { + lua_pop(lstate, 2); + continue; + } + bool next_key_found = false; + while (lua_next(lstate, -2)) { + // stack: …, dict, new key, val + if (lua_type(lstate, -2) == LUA_TSTRING) { + next_key_found = true; + break; + } + lua_pop(lstate, 1); + // stack: …, dict, new key + } + if (next_key_found) { + // stack: …, dict, new key, val + size_t len; + const char *s = lua_tolstring(lstate, -2, &len); + const size_t idx = cur.obj->data.dictionary.size++; + cur.obj->data.dictionary.items[idx].key = (String) { + .data = xmemdupz(s, len), + .size = len, + }; + kv_push(stack, cur); + cur = (ObjPopStackItem) { + .obj = &cur.obj->data.dictionary.items[idx].value, + .container = false, + }; + } else { + // stack: …, dict + lua_pop(lstate, 1); + // stack: … + continue; + } + } else { + if (cur.obj->data.array.size == cur.obj->data.array.capacity) { + lua_pop(lstate, 1); + continue; + } + const size_t idx = cur.obj->data.array.size++; + lua_rawgeti(lstate, -1, (int)idx + 1); + if (lua_isnil(lstate, -1)) { + lua_pop(lstate, 2); + continue; + } + kv_push(stack, cur); + cur = (ObjPopStackItem) { + .obj = &cur.obj->data.array.items[idx], + .container = false, + }; + } + } + assert(!cur.container); + *cur.obj = NIL; + switch (lua_type(lstate, -1)) { + case LUA_TNIL: { + break; + } + case LUA_TBOOLEAN: { + *cur.obj = BOOLEAN_OBJ(lua_toboolean(lstate, -1)); + break; + } + case LUA_TSTRING: { + size_t len; + const char *s = lua_tolstring(lstate, -1, &len); + *cur.obj = STRING_OBJ(((String) { + .data = xmemdupz(s, len), + .size = len, + })); + break; + } + case LUA_TNUMBER: { + const lua_Number n = lua_tonumber(lstate, -1); + if (n > (lua_Number)API_INTEGER_MAX || n < (lua_Number)API_INTEGER_MIN + || ((lua_Number)((Integer)n)) != n) { + *cur.obj = FLOAT_OBJ((Float)n); + } else { + *cur.obj = INTEGER_OBJ((Integer)n); + } + break; + } + case LUA_TTABLE: { + const LuaTableProps table_props = nlua_traverse_table(lstate); + + switch (table_props.type) { + case kObjectTypeArray: { + *cur.obj = ARRAY_OBJ(((Array) { + .items = NULL, + .size = 0, + .capacity = 0, + })); + if (table_props.maxidx != 0) { + cur.obj->data.array.items = + xcalloc(table_props.maxidx, + sizeof(cur.obj->data.array.items[0])); + cur.obj->data.array.capacity = table_props.maxidx; + cur.container = true; + kv_push(stack, cur); + } + break; + } + case kObjectTypeDictionary: { + *cur.obj = DICTIONARY_OBJ(((Dictionary) { + .items = NULL, + .size = 0, + .capacity = 0, + })); + if (table_props.string_keys_num != 0) { + cur.obj->data.dictionary.items = + xcalloc(table_props.string_keys_num, + sizeof(cur.obj->data.dictionary.items[0])); + cur.obj->data.dictionary.capacity = table_props.string_keys_num; + cur.container = true; + kv_push(stack, cur); + lua_pushnil(lstate); + } + break; + } + case kObjectTypeFloat: { + *cur.obj = FLOAT_OBJ((Float)table_props.val); + break; + } + case kObjectTypeNil: { + api_set_error(err, kErrorTypeValidation, + "Cannot convert given lua table"); + break; + } + default: { + assert(false); + } + } + break; + } + default: { + api_set_error(err, kErrorTypeValidation, + "Cannot convert given lua type"); + break; + } + } + if (!cur.container) { + lua_pop(lstate, 1); + } + } + kv_destroy(stack); + if (ERROR_SET(err)) { + api_free_object(ret); + ret = NIL; + lua_pop(lstate, lua_gettop(lstate) - initial_size + 1); + } + assert(lua_gettop(lstate) == initial_size - 1); + return ret; +} + +#define GENERATE_INDEX_FUNCTION(type) \ +type nlua_pop_##type(lua_State *lstate, Error *err) \ + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT \ +{ \ + type ret; \ + ret = (type)lua_tonumber(lstate, -1); \ + lua_pop(lstate, 1); \ + return ret; \ +} + +GENERATE_INDEX_FUNCTION(Buffer) +GENERATE_INDEX_FUNCTION(Window) +GENERATE_INDEX_FUNCTION(Tabpage) + +#undef GENERATE_INDEX_FUNCTION + +/// Record some auxilary values in vim module +/// +/// Assumes that module table is on top of the stack. +/// +/// Recorded values: +/// +/// `vim.type_idx`: @see nlua_push_type_idx() +/// `vim.val_idx`: @see nlua_push_val_idx() +/// `vim.types`: table mapping possible values of `vim.type_idx` to string +/// names (i.e. `array`, `float`, `dictionary`) and back. +void nlua_init_types(lua_State *const lstate) +{ + LUA_PUSH_STATIC_STRING(lstate, "type_idx"); + nlua_push_type_idx(lstate); + lua_rawset(lstate, -3); + + LUA_PUSH_STATIC_STRING(lstate, "val_idx"); + nlua_push_val_idx(lstate); + lua_rawset(lstate, -3); + + LUA_PUSH_STATIC_STRING(lstate, "types"); + lua_createtable(lstate, 0, 3); + + LUA_PUSH_STATIC_STRING(lstate, "float"); + lua_pushnumber(lstate, (lua_Number)kObjectTypeFloat); + lua_rawset(lstate, -3); + lua_pushnumber(lstate, (lua_Number)kObjectTypeFloat); + LUA_PUSH_STATIC_STRING(lstate, "float"); + lua_rawset(lstate, -3); + + LUA_PUSH_STATIC_STRING(lstate, "array"); + lua_pushnumber(lstate, (lua_Number)kObjectTypeArray); + lua_rawset(lstate, -3); + lua_pushnumber(lstate, (lua_Number)kObjectTypeArray); + LUA_PUSH_STATIC_STRING(lstate, "array"); + lua_rawset(lstate, -3); + + LUA_PUSH_STATIC_STRING(lstate, "dictionary"); + lua_pushnumber(lstate, (lua_Number)kObjectTypeDictionary); + lua_rawset(lstate, -3); + lua_pushnumber(lstate, (lua_Number)kObjectTypeDictionary); + LUA_PUSH_STATIC_STRING(lstate, "dictionary"); + lua_rawset(lstate, -3); + + lua_rawset(lstate, -3); +} diff --git a/src/nvim/lua/converter.h b/src/nvim/lua/converter.h new file mode 100644 index 0000000000..542c56ea3e --- /dev/null +++ b/src/nvim/lua/converter.h @@ -0,0 +1,15 @@ +#ifndef NVIM_LUA_CONVERTER_H +#define NVIM_LUA_CONVERTER_H + +#include <lua.h> +#include <stdbool.h> +#include <stdint.h> + +#include "nvim/api/private/defs.h" +#include "nvim/func_attr.h" +#include "nvim/eval.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "lua/converter.h.generated.h" +#endif +#endif // NVIM_LUA_CONVERTER_H diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c new file mode 100644 index 0000000000..eb821f7831 --- /dev/null +++ b/src/nvim/lua/executor.c @@ -0,0 +1,662 @@ +// 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 <lua.h> +#include <lualib.h> +#include <lauxlib.h> + +#include "nvim/misc1.h" +#include "nvim/getchar.h" +#include "nvim/garray.h" +#include "nvim/func_attr.h" +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" +#include "nvim/api/vim.h" +#include "nvim/vim.h" +#include "nvim/ex_getln.h" +#include "nvim/ex_cmds2.h" +#include "nvim/message.h" +#include "nvim/memline.h" +#include "nvim/buffer_defs.h" +#include "nvim/macros.h" +#include "nvim/screen.h" +#include "nvim/cursor.h" +#include "nvim/undo.h" +#include "nvim/ascii.h" + +#include "nvim/lua/executor.h" +#include "nvim/lua/converter.h" + +typedef struct { + Error err; + String lua_err_str; +} LuaError; + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "lua/vim_module.generated.h" +# include "lua/executor.c.generated.h" +#endif + +/// Name of the run code for use in messages +#define NLUA_EVAL_NAME "<VimL compiled string>" + +/// Call C function which does not expect any arguments +/// +/// @param function Called function +/// @param numret Number of returned arguments +#define NLUA_CALL_C_FUNCTION_0(lstate, function, numret) \ + do { \ + lua_pushcfunction(lstate, &function); \ + lua_call(lstate, 0, numret); \ + } while (0) +/// Call C function which expects one argument +/// +/// @param function Called function +/// @param numret Number of returned arguments +/// @param a… Supplied argument (should be a void* pointer) +#define NLUA_CALL_C_FUNCTION_1(lstate, function, numret, a1) \ + do { \ + lua_pushcfunction(lstate, &function); \ + lua_pushlightuserdata(lstate, a1); \ + lua_call(lstate, 1, numret); \ + } while (0) +/// Call C function which expects two arguments +/// +/// @param function Called function +/// @param numret Number of returned arguments +/// @param a… Supplied argument (should be a void* pointer) +#define NLUA_CALL_C_FUNCTION_2(lstate, function, numret, a1, a2) \ + do { \ + lua_pushcfunction(lstate, &function); \ + lua_pushlightuserdata(lstate, a1); \ + lua_pushlightuserdata(lstate, a2); \ + lua_call(lstate, 2, numret); \ + } while (0) +/// Call C function which expects three arguments +/// +/// @param function Called function +/// @param numret Number of returned arguments +/// @param a… Supplied argument (should be a void* pointer) +#define NLUA_CALL_C_FUNCTION_3(lstate, function, numret, a1, a2, a3) \ + do { \ + lua_pushcfunction(lstate, &function); \ + lua_pushlightuserdata(lstate, a1); \ + lua_pushlightuserdata(lstate, a2); \ + lua_pushlightuserdata(lstate, a3); \ + lua_call(lstate, 3, numret); \ + } while (0) +/// Call C function which expects five arguments +/// +/// @param function Called function +/// @param numret Number of returned arguments +/// @param a… Supplied argument (should be a void* pointer) +#define NLUA_CALL_C_FUNCTION_4(lstate, function, numret, a1, a2, a3, a4) \ + do { \ + lua_pushcfunction(lstate, &function); \ + lua_pushlightuserdata(lstate, a1); \ + lua_pushlightuserdata(lstate, a2); \ + lua_pushlightuserdata(lstate, a3); \ + lua_pushlightuserdata(lstate, a4); \ + lua_call(lstate, 4, numret); \ + } while (0) + +/// Convert lua error into a Vim error message +/// +/// @param lstate Lua interpreter state. +/// @param[in] msg Message base, must contain one `%s`. +static void nlua_error(lua_State *const lstate, const char *const msg) + FUNC_ATTR_NONNULL_ALL +{ + size_t len; + const char *const str = lua_tolstring(lstate, -1, &len); + + emsgf(msg, (int)len, str); + + lua_pop(lstate, 1); +} + +/// Compare two strings, ignoring case +/// +/// Expects two values on the stack: compared strings. Returns one of the +/// following numbers: 0, -1 or 1. +/// +/// Does no error handling: never call it with non-string or with some arguments +/// omitted. +static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + const char *s1 = luaL_checklstring(lstate, 1, NULL); + const char *s2 = luaL_checklstring(lstate, 2, NULL); + const int ret = STRICMP(s1, s2); + lua_pop(lstate, 2); + lua_pushnumber(lstate, (lua_Number)((ret > 0) - (ret < 0))); + return 1; +} + +/// Evaluate lua string +/// +/// Expects two values on the stack: string to evaluate, pointer to the +/// location where result is saved. Always returns nothing (from the lua point +/// of view). +static int nlua_exec_lua_string(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + const String *const str = (const String *)lua_touserdata(lstate, 1); + typval_T *const ret_tv = (typval_T *)lua_touserdata(lstate, 2); + lua_pop(lstate, 2); + + if (luaL_loadbuffer(lstate, str->data, str->size, NLUA_EVAL_NAME)) { + nlua_error(lstate, _("E5104: Error while creating lua chunk: %.*s")); + return 0; + } + if (lua_pcall(lstate, 0, 1, 0)) { + nlua_error(lstate, _("E5105: Error while calling lua chunk: %.*s")); + return 0; + } + if (!nlua_pop_typval(lstate, ret_tv)) { + return 0; + } + return 0; +} + +/// Evaluate lua string for each line in range +/// +/// Expects two values on the stack: string to evaluate and pointer to integer +/// array with line range. Always returns nothing (from the lua point of view). +static int nlua_exec_luado_string(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + const String *const str = (const String *)lua_touserdata(lstate, 1); + const linenr_T *const range = (const linenr_T *)lua_touserdata(lstate, 2); + lua_pop(lstate, 2); + +#define DOSTART "return function(line, linenr) " +#define DOEND " end" + const size_t lcmd_len = (str->size + + (sizeof(DOSTART) - 1) + + (sizeof(DOEND) - 1)); + char *lcmd; + if (lcmd_len < IOSIZE) { + lcmd = (char *)IObuff; + } else { + lcmd = xmalloc(lcmd_len + 1); + } + memcpy(lcmd, DOSTART, sizeof(DOSTART) - 1); + memcpy(lcmd + sizeof(DOSTART) - 1, str->data, str->size); + memcpy(lcmd + sizeof(DOSTART) - 1 + str->size, DOEND, sizeof(DOEND) - 1); +#undef DOSTART +#undef DOEND + + if (luaL_loadbuffer(lstate, lcmd, lcmd_len, NLUA_EVAL_NAME)) { + nlua_error(lstate, _("E5109: Error while creating lua chunk: %.*s")); + if (lcmd_len >= IOSIZE) { + xfree(lcmd); + } + return 0; + } + if (lcmd_len >= IOSIZE) { + xfree(lcmd); + } + if (lua_pcall(lstate, 0, 1, 0)) { + nlua_error(lstate, _("E5110: Error while creating lua function: %.*s")); + return 0; + } + for (linenr_T l = range[0]; l <= range[1]; l++) { + if (l > curbuf->b_ml.ml_line_count) { + break; + } + lua_pushvalue(lstate, -1); + lua_pushstring(lstate, (const char *)ml_get_buf(curbuf, l, false)); + lua_pushnumber(lstate, (lua_Number)l); + if (lua_pcall(lstate, 2, 1, 0)) { + nlua_error(lstate, _("E5111: Error while calling lua function: %.*s")); + break; + } + if (lua_isstring(lstate, -1)) { + size_t new_line_len; + const char *const new_line = lua_tolstring(lstate, -1, &new_line_len); + char *const new_line_transformed = xmemdupz(new_line, new_line_len); + for (size_t i = 0; i < new_line_len; i++) { + if (new_line_transformed[i] == NUL) { + new_line_transformed[i] = '\n'; + } + } + ml_replace(l, (char_u *)new_line_transformed, false); + changed_bytes(l, 0); + } + lua_pop(lstate, 1); + } + lua_pop(lstate, 1); + check_cursor(); + update_screen(NOT_VALID); + return 0; +} + +/// Evaluate lua file +/// +/// Expects one value on the stack: file to evaluate. Always returns nothing +/// (from the lua point of view). +static int nlua_exec_lua_file(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + const char *const filename = (const char *)lua_touserdata(lstate, 1); + lua_pop(lstate, 1); + + if (luaL_loadfile(lstate, filename)) { + nlua_error(lstate, _("E5112: Error while creating lua chunk: %.*s")); + return 0; + } + if (lua_pcall(lstate, 0, 0, 0)) { + nlua_error(lstate, _("E5113: Error while calling lua chunk: %.*s")); + return 0; + } + return 0; +} + +/// Initialize lua interpreter state +/// +/// Called by lua interpreter itself to initialize state. +static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + // stricmp + lua_pushcfunction(lstate, &nlua_stricmp); + lua_setglobal(lstate, "stricmp"); + + // print + lua_pushcfunction(lstate, &nlua_print); + lua_setglobal(lstate, "print"); + + // debug.debug + lua_getglobal(lstate, "debug"); + lua_pushcfunction(lstate, &nlua_debug); + lua_setfield(lstate, -2, "debug"); + lua_pop(lstate, 1); + + // vim + if (luaL_dostring(lstate, (char *)&vim_module[0])) { + nlua_error(lstate, _("E5106: Error while creating vim module: %.*s")); + return 1; + } + // vim.api + nlua_add_api_functions(lstate); + // vim.types, vim.type_idx, vim.val_idx + nlua_init_types(lstate); + lua_setglobal(lstate, "vim"); + return 0; +} + +/// Initialize lua interpreter +/// +/// Crashes NeoVim if initialization fails. Should be called once per lua +/// interpreter instance. +/// +/// @return New lua interpreter instance. +static lua_State *nlua_init(void) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT +{ + lua_State *lstate = luaL_newstate(); + if (lstate == NULL) { + EMSG(_("E970: Failed to initialize lua interpreter")); + preserve_exit(); + } + luaL_openlibs(lstate); + NLUA_CALL_C_FUNCTION_0(lstate, nlua_state_init, 0); + return lstate; +} + +/// Enter lua interpreter +/// +/// Calls nlua_init() if needed. Is responsible for pre-lua call initalization +/// like updating `package.[c]path` with directories derived from &runtimepath. +/// +/// @return Interprter instance to use. Will either be initialized now or taken +/// from previous initalization. +static lua_State *nlua_enter(void) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT +{ + static lua_State *global_lstate = NULL; + if (global_lstate == NULL) { + global_lstate = nlua_init(); + } + lua_State *const lstate = global_lstate; + // Last used p_rtp value. Must not be dereferenced because value pointed to + // may already be freed. Used to check whether &runtimepath option value + // changed. + static const void *last_p_rtp = NULL; + if (last_p_rtp != (const void *)p_rtp) { + // stack: (empty) + lua_getglobal(lstate, "vim"); + // stack: vim + lua_getfield(lstate, -1, "_update_package_paths"); + // stack: vim, vim._update_package_paths + if (lua_pcall(lstate, 0, 0, 0)) { + // stack: vim, error + nlua_error(lstate, _("E5117: Error while updating package paths: %.*s")); + // stack: vim + } + // stack: vim + lua_pop(lstate, 1); + // stack: (empty) + last_p_rtp = (const void *)p_rtp; + } + return lstate; +} + +/// Execute lua string +/// +/// @param[in] str String to execute. +/// @param[out] ret_tv Location where result will be saved. +/// +/// @return Result of the execution. +void executor_exec_lua(const String str, typval_T *const ret_tv) + FUNC_ATTR_NONNULL_ALL +{ + NLUA_CALL_C_FUNCTION_2(nlua_enter(), nlua_exec_lua_string, 0, + (void *)&str, ret_tv); +} + +/// Evaluate lua string +/// +/// Used for luaeval(). Expects three values on the stack: +/// +/// 1. String to evaluate. +/// 2. _A value. +/// 3. Pointer to location where result is saved. +/// +/// @param[in,out] lstate Lua interpreter state. +static int nlua_eval_lua_string(lua_State *const lstate) + FUNC_ATTR_NONNULL_ALL +{ + const String *const str = (const String *)lua_touserdata(lstate, 1); + typval_T *const arg = (typval_T *)lua_touserdata(lstate, 2); + typval_T *const ret_tv = (typval_T *)lua_touserdata(lstate, 3); + lua_pop(lstate, 3); + + garray_T str_ga; + ga_init(&str_ga, 1, 80); +#define EVALHEADER "local _A=select(1,...) return (" + const size_t lcmd_len = sizeof(EVALHEADER) - 1 + str->size + 1; + char *lcmd; + if (lcmd_len < IOSIZE) { + lcmd = (char *)IObuff; + } else { + lcmd = xmalloc(lcmd_len); + } + memcpy(lcmd, EVALHEADER, sizeof(EVALHEADER) - 1); + memcpy(lcmd + sizeof(EVALHEADER) - 1, str->data, str->size); + lcmd[lcmd_len - 1] = ')'; +#undef EVALHEADER + if (luaL_loadbuffer(lstate, lcmd, lcmd_len, NLUA_EVAL_NAME)) { + nlua_error(lstate, + _("E5107: Error while creating lua chunk for luaeval(): %.*s")); + if (lcmd != (char *)IObuff) { + xfree(lcmd); + } + return 0; + } + if (lcmd != (char *)IObuff) { + xfree(lcmd); + } + + if (arg == NULL || arg->v_type == VAR_UNKNOWN) { + lua_pushnil(lstate); + } else { + nlua_push_typval(lstate, arg); + } + if (lua_pcall(lstate, 1, 1, 0)) { + nlua_error(lstate, + _("E5108: Error while calling lua chunk for luaeval(): %.*s")); + return 0; + } + if (!nlua_pop_typval(lstate, ret_tv)) { + return 0; + } + + return 0; +} + +/// Evaluate lua string +/// +/// Expects four values on the stack: string to evaluate, pointer to args array, +/// and locations where result and error are saved, respectively. Always +/// returns nothing (from the lua point of view). +static int nlua_exec_lua_string_api(lua_State *const lstate) + FUNC_ATTR_NONNULL_ALL +{ + const String *str = (const String *)lua_touserdata(lstate, 1); + const Array *args = (const Array *)lua_touserdata(lstate, 2); + Object *retval = (Object *)lua_touserdata(lstate, 3); + Error *err = (Error *)lua_touserdata(lstate, 4); + + lua_pop(lstate, 4); + + if (luaL_loadbuffer(lstate, str->data, str->size, "<nvim>")) { + size_t len; + const char *str = lua_tolstring(lstate, -1, &len); + api_set_error(err, kErrorTypeValidation, + "Error loading lua: %.*s", (int)len, str); + return 0; + } + + for (size_t i = 0; i < args->size; i++) { + nlua_push_Object(lstate, args->items[i]); + } + + if (lua_pcall(lstate, (int)args->size, 1, 0)) { + size_t len; + const char *str = lua_tolstring(lstate, -1, &len); + api_set_error(err, kErrorTypeException, + "Error executing lua: %.*s", (int)len, str); + return 0; + } + + *retval = nlua_pop_Object(lstate, err); + + return 0; +} + +/// Print as a Vim message +/// +/// @param lstate Lua interpreter state. +static int nlua_print(lua_State *const lstate) + FUNC_ATTR_NONNULL_ALL +{ +#define PRINT_ERROR(msg) \ + do { \ + errmsg = msg; \ + errmsg_len = sizeof(msg) - 1; \ + goto nlua_print_error; \ + } while (0) + const int nargs = lua_gettop(lstate); + lua_getglobal(lstate, "tostring"); + const char *errmsg = NULL; + size_t errmsg_len = 0; + garray_T msg_ga; + ga_init(&msg_ga, 1, 80); + int curargidx = 1; + for (; curargidx <= nargs; curargidx++) { + lua_pushvalue(lstate, -1); // tostring + lua_pushvalue(lstate, curargidx); // arg + if (lua_pcall(lstate, 1, 1, 0)) { + errmsg = lua_tolstring(lstate, -1, &errmsg_len); + goto nlua_print_error; + } + size_t len; + const char *const s = lua_tolstring(lstate, -1, &len); + if (s == NULL) { + PRINT_ERROR( + "<Unknown error: lua_tolstring returned NULL for tostring result>"); + } + ga_concat_len(&msg_ga, s, len); + if (curargidx < nargs) { + ga_append(&msg_ga, ' '); + } + lua_pop(lstate, 1); + } +#undef PRINT_ERROR + lua_pop(lstate, nargs + 1); + ga_append(&msg_ga, NUL); + { + const size_t len = (size_t)msg_ga.ga_len - 1; + char *const str = (char *)msg_ga.ga_data; + + for (size_t i = 0; i < len;) { + const size_t start = i; + while (i < len) { + switch (str[i]) { + case NUL: { + str[i] = NL; + i++; + continue; + } + case NL: { + str[i] = NUL; + i++; + break; + } + default: { + i++; + continue; + } + } + break; + } + msg((char_u *)str + start); + } + if (len && str[len - 1] == NUL) { // Last was newline + msg((char_u *)""); + } + } + ga_clear(&msg_ga); + return 0; +nlua_print_error: + emsgf(_("E5114: Error while converting print argument #%i: %.*s"), + curargidx, errmsg_len, errmsg); + ga_clear(&msg_ga); + lua_pop(lstate, lua_gettop(lstate)); + return 0; +} + +/// debug.debug implementation: interaction with user while debugging +/// +/// @param lstate Lua interpreter state. +int nlua_debug(lua_State *lstate) + FUNC_ATTR_NONNULL_ALL +{ + const typval_T input_args[] = { + { + .v_lock = VAR_FIXED, + .v_type = VAR_STRING, + .vval.v_string = (char_u *)"lua_debug> ", + }, + { + .v_type = VAR_UNKNOWN, + }, + }; + for (;;) { + lua_settop(lstate, 0); + typval_T input; + get_user_input(input_args, &input, false); + msg_putchar('\n'); // Avoid outputting on input line. + if (input.v_type != VAR_STRING + || input.vval.v_string == NULL + || *input.vval.v_string == NUL + || STRCMP(input.vval.v_string, "cont") == 0) { + tv_clear(&input); + return 0; + } + if (luaL_loadbuffer(lstate, (const char *)input.vval.v_string, + STRLEN(input.vval.v_string), "=(debug command)")) { + nlua_error(lstate, _("E5115: Error while loading debug string: %.*s")); + } + tv_clear(&input); + if (lua_pcall(lstate, 0, 0, 0)) { + nlua_error(lstate, _("E5116: Error while calling debug string: %.*s")); + } + } + return 0; +} + +/// Evaluate lua string +/// +/// Used for luaeval(). +/// +/// @param[in] str String to execute. +/// @param[in] arg Second argument to `luaeval()`. +/// @param[out] ret_tv Location where result will be saved. +/// +/// @return Result of the execution. +void executor_eval_lua(const String str, typval_T *const arg, + typval_T *const ret_tv) + FUNC_ATTR_NONNULL_ALL +{ + NLUA_CALL_C_FUNCTION_3(nlua_enter(), nlua_eval_lua_string, 0, + (void *)&str, arg, ret_tv); +} + +/// Execute lua string +/// +/// Used for nvim_execute_lua(). +/// +/// @param[in] str String to execute. +/// @param[in] args array of ... args +/// @param[out] err Location where error will be saved. +/// +/// @return Return value of the execution. +Object executor_exec_lua_api(const String str, const Array args, Error *err) +{ + Object retval = NIL; + NLUA_CALL_C_FUNCTION_4(nlua_enter(), nlua_exec_lua_string_api, 0, + (void *)&str, (void *)&args, &retval, err); + return retval; +} + + +/// Run lua string +/// +/// Used for :lua. +/// +/// @param eap VimL command being run. +void ex_lua(exarg_T *const eap) + FUNC_ATTR_NONNULL_ALL +{ + size_t len; + char *const code = script_get(eap, &len); + if (eap->skip) { + xfree(code); + return; + } + typval_T tv = { .v_type = VAR_UNKNOWN }; + executor_exec_lua((String) { .data = code, .size = len }, &tv); + tv_clear(&tv); + xfree(code); +} + +/// Run lua string for each line in range +/// +/// Used for :luado. +/// +/// @param eap VimL command being run. +void ex_luado(exarg_T *const eap) + FUNC_ATTR_NONNULL_ALL +{ + if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL) { + EMSG(_("cannot save undo information")); + return; + } + const String cmd = { + .size = STRLEN(eap->arg), + .data = (char *)eap->arg, + }; + const linenr_T range[] = { eap->line1, eap->line2 }; + NLUA_CALL_C_FUNCTION_2(nlua_enter(), nlua_exec_luado_string, 0, + (void *)&cmd, (void *)range); +} + +/// Run lua file +/// +/// Used for :luafile. +/// +/// @param eap VimL command being run. +void ex_luafile(exarg_T *const eap) + FUNC_ATTR_NONNULL_ALL +{ + NLUA_CALL_C_FUNCTION_1(nlua_enter(), nlua_exec_lua_file, 0, + (void *)eap->arg); +} diff --git a/src/nvim/lua/executor.h b/src/nvim/lua/executor.h new file mode 100644 index 0000000000..0cbf290f64 --- /dev/null +++ b/src/nvim/lua/executor.h @@ -0,0 +1,25 @@ +#ifndef NVIM_LUA_EXECUTOR_H +#define NVIM_LUA_EXECUTOR_H + +#include <lua.h> + +#include "nvim/api/private/defs.h" +#include "nvim/func_attr.h" +#include "nvim/eval/typval.h" +#include "nvim/ex_cmds_defs.h" + +// Generated by msgpack-gen.lua +void nlua_add_api_functions(lua_State *lstate) REAL_FATTR_NONNULL_ALL; + +#define set_api_error(s, err) \ + do { \ + Error *err_ = (err); \ + err_->type = kErrorTypeException; \ + err_->set = true; \ + memcpy(&err_->msg[0], s, sizeof(s)); \ + } while (0) + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "lua/executor.h.generated.h" +#endif +#endif // NVIM_LUA_EXECUTOR_H diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua new file mode 100644 index 0000000000..c7952520b0 --- /dev/null +++ b/src/nvim/lua/vim.lua @@ -0,0 +1,64 @@ +-- TODO(ZyX-I): Create compatibility layer. +--{{{1 package.path updater function +-- Last inserted paths. Used to clear out items from package.[c]path when they +-- are no longer in &runtimepath. +local last_nvim_paths = {} +local function _update_package_paths() + local cur_nvim_paths = {} + local rtps = vim.api.nvim_list_runtime_paths() + local sep = package.config:sub(1, 1) + for _, key in ipairs({'path', 'cpath'}) do + local orig_str = package[key] .. ';' + local pathtrails_ordered = {} + local orig = {} + -- Note: ignores trailing item without trailing `;`. Not using something + -- simpler in order to preserve empty items (stand for default path). + for s in orig_str:gmatch('[^;]*;') do + s = s:sub(1, -2) -- Strip trailing semicolon + orig[#orig + 1] = s + end + if key == 'path' then + -- /?.lua and /?/init.lua + pathtrails_ordered = {sep .. '?.lua', sep .. '?' .. sep .. 'init.lua'} + else + local pathtrails = {} + for _, s in ipairs(orig) do + -- Find out path patterns. pathtrail should contain something like + -- /?.so, \?.dll. This allows not to bother determining what correct + -- suffixes are. + local pathtrail = s:match('[/\\][^/\\]*%?.*$') + if pathtrail and not pathtrails[pathtrail] then + pathtrails[pathtrail] = true + pathtrails_ordered[#pathtrails_ordered + 1] = pathtrail + end + end + end + local new = {} + for _, rtp in ipairs(rtps) do + if not rtp:match(';') then + for _, pathtrail in pairs(pathtrails_ordered) do + local new_path = rtp .. sep .. 'lua' .. pathtrail + -- Always keep paths from &runtimepath at the start: + -- append them here disregarding orig possibly containing one of them. + new[#new + 1] = new_path + cur_nvim_paths[new_path] = true + end + end + end + for _, orig_path in ipairs(orig) do + -- Handle removing obsolete paths originating from &runtimepath: such + -- paths either belong to cur_nvim_paths and were already added above or + -- to last_nvim_paths and should not be added at all if corresponding + -- entry was removed from &runtimepath list. + if not (cur_nvim_paths[orig_path] or last_nvim_paths[orig_path]) then + new[#new + 1] = orig_path + end + end + package[key] = table.concat(new, ';') + end + last_nvim_paths = cur_nvim_paths +end +--{{{1 Module definition +return { + _update_package_paths = _update_package_paths, +} diff --git a/src/nvim/macros.h b/src/nvim/macros.h index df2b431e92..26d4f74b6a 100644 --- a/src/nvim/macros.h +++ b/src/nvim/macros.h @@ -19,24 +19,14 @@ # define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) #endif -/* - * Position comparisons - */ -# define lt(a, b) (((a).lnum != (b).lnum) \ - ? (a).lnum < (b).lnum \ - : (a).col != (b).col \ - ? (a).col < (b).col \ - : (a).coladd < (b).coladd) -# define ltp(a, b) (((a)->lnum != (b)->lnum) \ - ? (a)->lnum < (b)->lnum \ - : (a)->col != (b)->col \ - ? (a)->col < (b)->col \ - : (a)->coladd < (b)->coladd) -# define equalpos(a, b) (((a).lnum == (b).lnum) && ((a).col == (b).col) && \ - ((a).coladd == (b).coladd)) -# define clearpos(a) {(a)->lnum = 0; (a)->col = 0; (a)->coladd = 0; } - -#define ltoreq(a, b) (lt(a, b) || equalpos(a, b)) +/// String with length +/// +/// For use in functions which accept (char *s, size_t len) pair in arguments. +/// +/// @param[in] s Static string. +/// +/// @return `s, sizeof(s) - 1` +#define S_LEN(s) (s), (sizeof(s) - 1) /* * lineempty() - return TRUE if the line is empty @@ -53,7 +43,7 @@ * toupper() and tolower() that use the current locale. * Careful: Only call TOUPPER_LOC() and TOLOWER_LOC() with a character in the * range 0 - 255. toupper()/tolower() on some systems can't handle others. - * Note: It is often better to use vim_tolower() and vim_toupper(), because many + * Note: It is often better to use mb_tolower() and mb_toupper(), because many * toupper() and tolower() implementations only work for ASCII. */ #define TOUPPER_LOC toupper @@ -85,7 +75,7 @@ do { \ if (*p_langmap \ && (condition) \ - && (!p_lnr || (p_lnr && typebuf_maplen() == 0)) \ + && (p_lrm || KeyTyped) \ && !KeyStuffed \ && (c) >= 0) \ { \ @@ -111,8 +101,10 @@ /* mch_open_rw(): invoke os_open() with third argument for user R/W. */ #if defined(UNIX) /* open in rw------- mode */ # define mch_open_rw(n, f) os_open((n), (f), (mode_t)0600) +#elif defined(WIN32) +# define mch_open_rw(n, f) os_open((n), (f), S_IREAD | S_IWRITE) #else -# define mch_open_rw(n, f) os_open((n), (f), 0) +# define mch_open_rw(n, f) os_open((n), (f), 0) #endif # define REPLACE_NORMAL(s) (((s) & REPLACE_FLAG) && !((s) & VREPLACE_FLAG)) @@ -138,7 +130,7 @@ // Backup multi-byte pointer. Only use with "p" > "s" ! # define mb_ptr_back(s, p) (p -= mb_head_off((char_u *)s, (char_u *)p - 1) + 1) // get length of multi-byte char, not including composing chars -# define mb_cptr2len(p) utf_ptr2len(p) +# define MB_CPTR2LEN(p) utf_ptr2len(p) # define MB_COPY_CHAR(f, t) mb_copy_char((const char_u **)(&f), &t); @@ -161,4 +153,34 @@ #define STR_(x) #x #define STR(x) STR_(x) +#ifndef __has_attribute +# define NVIM_HAS_ATTRIBUTE(x) 0 +#elif defined(__clang__) && __clang__ == 1 \ + && (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ <= 5)) +// Starting in Clang 3.6, __has_attribute was fixed to only report true for +// GNU-style attributes. Prior to that, it reported true if _any_ backend +// supported the attribute. +# define NVIM_HAS_ATTRIBUTE(x) 0 +#else +# define NVIM_HAS_ATTRIBUTE __has_attribute +#endif + +#if NVIM_HAS_ATTRIBUTE(fallthrough) +# define FALLTHROUGH __attribute__((fallthrough)) +#else +# define FALLTHROUGH +#endif + +// -V:STRUCT_CAST:641 + +/// Change type of structure pointers: cast `struct a *` to `struct b *` +/// +/// Used to silence PVS errors. +/// +/// @param Type Structure to cast to. +/// @param obj Object to cast. +/// +/// @return ((Type *)obj). +#define STRUCT_CAST(Type, obj) ((Type *)(obj)) + #endif // NVIM_MACROS_H diff --git a/src/nvim/main.c b/src/nvim/main.c index c7a60d07c1..024c56dd05 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1,9 +1,17 @@ +// 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 + #define EXTERN #include <assert.h> #include <stdint.h> #include <string.h> #include <stdbool.h> +#ifdef WIN32 +# include <wchar.h> +# include <winnls.h> +#endif + #include <msgpack.h> #include "nvim/ascii.h" @@ -54,6 +62,7 @@ #include "nvim/os/input.h" #include "nvim/os/os.h" #include "nvim/os/time.h" +#include "nvim/os/fileio.h" #include "nvim/event/loop.h" #include "nvim/os/signal.h" #include "nvim/event/process.h" @@ -94,10 +103,8 @@ typedef struct { bool input_isatty; // stdin is a terminal bool output_isatty; // stdout is a terminal bool err_isatty; // stderr is a terminal - bool headless; // Dont try to start an user interface - // or read/write to stdio(unless - // embedding) - int no_swap_file; /* "-n" argument used */ + bool headless; // Do not start the builtin UI. + int no_swap_file; // "-n" argument used int use_debug_break_level; int window_count; /* number of windows to use */ int window_layout; /* 0, WIN_HOR, WIN_VER or WIN_TABS */ @@ -121,7 +128,7 @@ typedef struct { Loop main_loop; -static char *argv0; +static char *argv0 = NULL; // Error messages static const char *err_arg_missing = N_("Argument missing after"); @@ -150,10 +157,11 @@ void event_init(void) terminal_init(); } -void event_teardown(void) +/// @returns false if main_loop could not be closed gracefully +bool event_teardown(void) { if (!main_loop.events) { - return; + return true; } multiqueue_process_events(main_loop.events); @@ -165,7 +173,7 @@ void event_teardown(void) signal_teardown(); terminal_teardown(); - loop_close(&main_loop, true); + return loop_close(&main_loop, true); } /// Performs early initialization. @@ -176,11 +184,9 @@ void early_init(void) log_init(); fs_init(); handle_init(); - eval_init(); // init global variables - - // Init the table of Normal mode commands. - init_normal_cmds(); + init_path(argv0 ? argv0 : "nvim"); + init_normal_cmds(); // Init the table of Normal mode commands. #if defined(HAVE_LOCALE_H) // Setup to use the current locale (for ctype() and many other things). @@ -214,11 +220,23 @@ void early_init(void) #ifdef MAKE_LIB int nvim_main(int argc, char **argv) +#elif defined(WIN32) +int wmain(int argc, wchar_t **argv_w) // multibyte args on Windows. #7060 #else int main(int argc, char **argv) #endif { - argv0 = (char *)path_tail((char_u *)argv[0]); +#if defined(WIN32) && !defined(MAKE_LIB) + char *argv[argc]; + for (int i = 0; i < argc; i++) { + char *buf = NULL; + utf16_to_utf8(argv_w[i], &buf); + assert(buf); + argv[i] = buf; + } +#endif + + argv0 = argv[0]; char_u *fname = NULL; // file name from command line mparm_T params; // various parameters passed between @@ -238,10 +256,6 @@ int main(int argc, char **argv) // Check if we have an interactive window. check_and_set_isatty(¶ms); - // Get the name with which Nvim was invoked, with and without path. - set_vim_var_string(VV_PROGPATH, argv[0], -1); - set_vim_var_string(VV_PROGNAME, (char *) path_tail((char_u *) argv[0]), -1); - event_init(); /* * Process the command line arguments. File names are put in the global @@ -285,7 +299,7 @@ int main(int argc, char **argv) cmdline_row = (int)(Rows - p_ch); msg_row = cmdline_row; screenalloc(false); /* allocate screen buffers */ - set_init_2(); + set_init_2(params.headless); TIME_MSG("inits 2"); msg_scroll = TRUE; @@ -328,6 +342,12 @@ int main(int argc, char **argv) do_cmdline_cmd("augroup END"); #undef PROTO + // Reset 'loadplugins' for "-u NONE" before "--cmd" arguments. + // Allows for setting 'loadplugins' there. + if (params.use_vimrc != NULL && strcmp(params.use_vimrc, "NONE") == 0) { + p_lpl = false; + } + /* Execute --cmd arguments. */ exe_pre_commands(¶ms); @@ -387,9 +407,10 @@ int main(int argc, char **argv) shada_read_everything(NULL, false, true); TIME_MSG("reading ShaDa"); } - /* It's better to make v:oldfiles an empty list than NULL. */ - if (get_vim_var_list(VV_OLDFILES) == NULL) - set_vim_var_list(VV_OLDFILES, list_alloc()); + // It's better to make v:oldfiles an empty list than NULL. + if (get_vim_var_list(VV_OLDFILES) == NULL) { + set_vim_var_list(VV_OLDFILES, tv_list_alloc()); + } /* * "-q errorfile": Load the error file now. @@ -515,6 +536,12 @@ int main(int argc, char **argv) apply_autocmds(EVENT_VIMENTER, NULL, NULL, false, curbuf); TIME_MSG("VimEnter autocommands"); + // Adjust default register name for "unnamed" in 'clipboard'. Can only be + // done after the clipboard is available and all initial commands that may + // modify the 'clipboard' setting have run; i.e. just before entering the + // main loop. + set_reg_var(get_default_register_name()); + /* When a startup script or session file setup for diff'ing and * scrollbind, sync the scrollbind now. */ if (curwin->w_p_diff && curwin->w_p_scb) { @@ -578,9 +605,9 @@ void getout(int exitval) buf_T *buf = wp->w_buffer; if (buf->b_changedtick != -1) { apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, - buf->b_fname, FALSE, buf); - buf->b_changedtick = -1; /* note that we did it already */ - /* start all over, autocommands may mess up the lists */ + buf->b_fname, false, buf); + buf_set_changedtick(buf, -1); // note that we did it already + // start all over, autocommands may mess up the lists next_tp = first_tabpage; break; } @@ -590,10 +617,13 @@ void getout(int exitval) /* Trigger BufUnload for buffers that are loaded */ FOR_ALL_BUFFERS(buf) { if (buf->b_ml.ml_mfp != NULL) { - apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, - FALSE, buf); - if (!buf_valid(buf)) /* autocmd may delete the buffer */ + bufref_T bufref; + set_bufref(&bufref, buf); + apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, false, buf); + if (!bufref_valid(&bufref)) { + // Autocmd deleted the buffer. break; + } } } apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, FALSE, curbuf); @@ -623,8 +653,9 @@ void getout(int exitval) iconv_end(); #endif cs_end(); - if (garbage_collect_at_exit) - garbage_collect(); + if (garbage_collect_at_exit) { + garbage_collect(false); + } mch_exit(exitval); } @@ -642,8 +673,9 @@ void getout(int exitval) /// /// @return argument's numeric value otherwise static int get_number_arg(const char *p, int *idx, int def) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { - if (ascii_isdigit(p[*idx])) { + if (ascii_isdigit(p[*idx])) { // -V522 def = atoi(&(p[*idx])); while (ascii_isdigit(p[*idx])) { *idx = *idx + 1; @@ -750,16 +782,26 @@ static void command_line_scan(mparm_T *parmp) version(); mch_exit(0); } else if (STRICMP(argv[0] + argv_idx, "api-info") == 0) { - msgpack_sbuffer* b = msgpack_sbuffer_new(); - msgpack_packer* p = msgpack_packer_new(b, msgpack_sbuffer_write); - Object md = DICTIONARY_OBJ(api_metadata()); - msgpack_rpc_from_object(md, p); + FileDescriptor fp; + const int fof_ret = file_open_fd(&fp, OS_STDOUT_FILENO, true); + msgpack_packer *p = msgpack_packer_new(&fp, msgpack_file_write); + + if (fof_ret != 0) { + emsgf(_("E5421: Failed to open stdin: %s"), os_strerror(fof_ret)); + } - for (size_t i = 0; i < b->size; i++) { - putchar(b->data[i]); + if (p == NULL) { + emsgf(_(e_outofmem)); } + Object md = DICTIONARY_OBJ(api_metadata()); + msgpack_rpc_from_object(md, p); + msgpack_packer_free(p); + const int ff_ret = file_flush(&fp); + if (ff_ret < 0) { + msgpack_file_write_error(ff_ret); + } mch_exit(0); } else if (STRICMP(argv[0] + argv_idx, "headless") == 0) { parmp->headless = true; @@ -788,17 +830,18 @@ static void command_line_scan(mparm_T *parmp) argv_idx = -1; /* skip to next argument */ break; - case 'A': /* "-A" start in Arabic mode */ - set_option_value((char_u *)"arabic", 1L, NULL, 0); + case 'A': { // "-A" start in Arabic mode. + set_option_value("arabic", 1L, NULL, 0); break; - - case 'b': /* "-b" binary mode */ - /* Needs to be effective before expanding file names, because - * for Win32 this makes us edit a shortcut file itself, - * instead of the file it links to. */ + } + case 'b': { // "-b" binary mode. + // Needs to be effective before expanding file names, because + // for Win32 this makes us edit a shortcut file itself, + // instead of the file it links to. set_options_bin(curbuf->b_p_bin, 1, 0); - curbuf->b_p_bin = 1; /* binary file I/O */ + curbuf->b_p_bin = 1; // Binary file I/O. break; + } case 'e': /* "-e" Ex mode */ exmode_active = EXMODE_NORMAL; @@ -815,24 +858,27 @@ static void command_line_scan(mparm_T *parmp) main_start_gui(); break; - case 'F': /* "-F" start in Farsi mode: rl + fkmap set */ - p_fkmap = TRUE; - set_option_value((char_u *)"rl", 1L, NULL, 0); + case 'F': { // "-F" start in Farsi mode: rl + fkmap set. + p_fkmap = true; + set_option_value("rl", 1L, NULL, 0); break; + } case 'h': /* "-h" give help message */ usage(); mch_exit(0); - case 'H': /* "-H" start in Hebrew mode: rl + hkmap set */ - p_hkmap = TRUE; - set_option_value((char_u *)"rl", 1L, NULL, 0); + case 'H': { // "-H" start in Hebrew mode: rl + hkmap set. + p_hkmap = true; + set_option_value("rl", 1L, NULL, 0); break; + } - case 'l': /* "-l" lisp mode, 'lisp' and 'showmatch' on */ - set_option_value((char_u *)"lisp", 1L, NULL, 0); - p_sm = TRUE; + case 'l': { // "-l" lisp mode, 'lisp' and 'showmatch' on. + set_option_value("lisp", 1L, NULL, 0); + p_sm = true; break; + } case 'M': /* "-M" no changes or writing of files */ reset_modifiable(); @@ -901,10 +947,11 @@ static void command_line_scan(mparm_T *parmp) break; case 's': - if (exmode_active) /* "-s" silent (batch) mode */ - silent_mode = TRUE; - else /* "-s {scriptin}" read from script file */ - want_argument = TRUE; + if (exmode_active) { // "-es" silent (batch) mode + silent_mode = true; + } else { // "-s {scriptin}" read from script file + want_argument = true; + } break; case 't': /* "-t {tag}" or "-t{tag}" jump to tag */ @@ -931,8 +978,7 @@ static void command_line_scan(mparm_T *parmp) /* default is 10: a little bit verbose */ p_verbose = get_number_arg(argv[0], &argv_idx, 10); if (argv[0][argv_idx] != NUL) { - set_option_value((char_u *)"verbosefile", 0L, - (char_u *)argv[0] + argv_idx, 0); + set_option_value("verbosefile", 0L, argv[0] + argv_idx, 0); argv_idx = (int)STRLEN(argv[0]); } break; @@ -941,7 +987,7 @@ static void command_line_scan(mparm_T *parmp) /* "-w {scriptout}" write to script */ if (ascii_isdigit(((char_u *)argv[0])[argv_idx])) { n = get_number_arg(argv[0], &argv_idx, 10); - set_option_value((char_u *)"window", n, NULL, 0); + set_option_value("window", n, NULL, 0); break; } want_argument = TRUE; @@ -1073,7 +1119,7 @@ scripterror: if (ascii_isdigit(*((char_u *)argv[0]))) { argv_idx = 0; n = get_number_arg(argv[0], &argv_idx, 10); - set_option_value((char_u *)"window", n, NULL, 0); + set_option_value("window", n, NULL, 0); argv_idx = -1; break; } @@ -1194,9 +1240,29 @@ static void check_and_set_isatty(mparm_T *paramp) paramp->err_isatty = os_isatty(fileno(stderr)); TIME_MSG("window checked"); } -/* - * Get filename from command line, given that there is one. - */ + +// Sets v:progname and v:progpath. Also modifies $PATH on Windows. +static void init_path(const char *exename) + FUNC_ATTR_NONNULL_ALL +{ + char exepath[MAXPATHL] = { 0 }; + size_t exepathlen = MAXPATHL; + // Make v:progpath absolute. + if (os_exepath(exepath, &exepathlen) != 0) { + // Fall back to argv[0]. Missing procfs? #6734 + path_guess_exepath(exename, exepath, sizeof(exepath)); + } + set_vim_var_string(VV_PROGPATH, exepath, -1); + set_vim_var_string(VV_PROGNAME, (char *)path_tail((char_u *)exename), -1); + +#ifdef WIN32 + // Append the process start directory to $PATH, so that ":!foo" finds tools + // shipped with Windows package. This also mimics SearchPath(). + os_setenv_append_path(exepath); +#endif +} + +/// Get filename from command line, if any. static char_u *get_fname(mparm_T *parmp, char_u *cwd) { #if !defined(UNIX) @@ -1242,11 +1308,33 @@ static void set_window_layout(mparm_T *paramp) static void load_plugins(void) { if (p_lpl) { - source_runtime((char_u *)"plugin/**/*.vim", DIP_ALL); // NOLINT + char_u *rtp_copy = NULL; + + // First add all package directories to 'runtimepath', so that their + // autoload directories can be found. Only if not done already with a + // :packloadall command. + // Make a copy of 'runtimepath', so that source_runtime does not use the + // pack directories. + if (!did_source_packages) { + rtp_copy = vim_strsave(p_rtp); + add_pack_start_dirs(); + } + + source_in_path(rtp_copy == NULL ? p_rtp : rtp_copy, + (char_u *)"plugin/**/*.vim", // NOLINT + DIP_ALL | DIP_NOAFTER); TIME_MSG("loading plugins"); + xfree(rtp_copy); - ex_packloadall(NULL); + // Only source "start" packages if not done already with a :packloadall + // command. + if (!did_source_packages) { + load_start_packages(); + } TIME_MSG("loading packages"); + + source_runtime((char_u *)"plugin/**/*.vim", DIP_ALL | DIP_AFTER); + TIME_MSG("loading after plugins"); } } @@ -1261,8 +1349,8 @@ static void handle_quickfix(mparm_T *paramp) set_string_option_direct((char_u *)"ef", -1, paramp->use_ef, OPT_FREE, SID_CARG); vim_snprintf((char *)IObuff, IOSIZE, "cfile %s", p_ef); - if (qf_init(NULL, p_ef, p_efm, TRUE, IObuff) < 0) { - ui_putc('\n'); + if (qf_init(NULL, p_ef, p_efm, true, IObuff) < 0) { + ui_linefeed(); mch_exit(3); } TIME_MSG("reading errorfile"); @@ -1642,7 +1730,7 @@ static bool do_user_initialization(void) do { const char *dir; size_t dir_len; - iter = vim_colon_env_iter(config_dirs, iter, &dir, &dir_len); + iter = vim_env_iter(':', config_dirs, iter, &dir, &dir_len); if (dir == NULL || dir_len == 0) { break; } @@ -1682,8 +1770,6 @@ static void source_startup_scripts(const mparm_T *const parmp) if (parmp->use_vimrc != NULL) { if (strcmp(parmp->use_vimrc, "NONE") == 0 || strcmp(parmp->use_vimrc, "NORC") == 0) { - if (parmp->use_vimrc[2] == 'N') - p_lpl = false; // don't load plugins either } else { if (do_source((char_u *)parmp->use_vimrc, FALSE, DOSO_NONE) != OK) EMSG2(_("E282: Cannot read from \"%s\""), parmp->use_vimrc); @@ -1775,6 +1861,7 @@ static int process_env(char *env, bool is_viminit) /// os_fileinfo_link() respectively for extra security. static bool file_owned(const char *fname) { + assert(fname != NULL); uid_t uid = getuid(); FileInfo file_info; bool file_owned = os_fileinfo(fname, &file_info) @@ -1793,9 +1880,11 @@ static bool file_owned(const char *fname) /// @param str string to append to the primary error message, or NULL static void mainerr(const char *errstr, const char *str) { + char *prgname = (char *)path_tail((char_u *)argv0); + signal_stop(); // kill us with CTRL-C here, if you like - mch_errmsg(argv0); + mch_errmsg(prgname); mch_errmsg(": "); mch_errmsg(_(errstr)); if (str != NULL) { @@ -1804,7 +1893,7 @@ static void mainerr(const char *errstr, const char *str) mch_errmsg("\""); } mch_errmsg(_("\nMore info with \"")); - mch_errmsg(argv0); + mch_errmsg(prgname); mch_errmsg(" -h\"\n"); mch_exit(1); @@ -1825,54 +1914,47 @@ static void usage(void) signal_stop(); // kill us with CTRL-C here, if you like mch_msg(_("Usage:\n")); - mch_msg(_(" nvim [arguments] [file ...] Edit specified file(s)\n")); - mch_msg(_(" nvim [arguments] - Read text from stdin\n")); - mch_msg(_(" nvim [arguments] -t <tag> Edit file where tag is defined\n")); - mch_msg(_(" nvim [arguments] -q [errorfile] Edit file with first error\n")); - mch_msg(_("\nArguments:\n")); + mch_msg(_(" nvim [options] [file ...] Edit file(s)\n")); + mch_msg(_(" nvim [options] - Read text from stdin\n")); + mch_msg(_(" nvim [options] -t <tag> Edit file where tag is defined\n")); + mch_msg(_(" nvim [options] -q [errorfile] Edit file with first error\n")); + mch_msg(_("\nOptions:\n")); mch_msg(_(" -- Only file names after this\n")); -#if !defined(UNIX) - mch_msg(_(" --literal Don't expand wildcards\n")); -#endif - mch_msg(_(" -e Ex mode\n")); - mch_msg(_(" -E Improved Ex mode\n")); - mch_msg(_(" -s Silent (batch) mode (only for ex mode)\n")); + mch_msg(_(" + Start at end of file\n")); + mch_msg(_(" --cmd <cmd> Execute <cmd> before any config\n")); + mch_msg(_(" +<cmd>, -c <cmd> Execute <cmd> after config and first file\n")); + mch_msg("\n"); + mch_msg(_(" -b Binary mode\n")); mch_msg(_(" -d Diff mode\n")); - mch_msg(_(" -R Read-only mode\n")); - mch_msg(_(" -Z Restricted mode\n")); + mch_msg(_(" -e, -E Ex mode, Improved Ex mode\n")); + mch_msg(_(" -es Silent (batch) mode\n")); + mch_msg(_(" -h, --help Print this help message\n")); + mch_msg(_(" -i <shada> Use this shada file\n")); mch_msg(_(" -m Modifications (writing files) not allowed\n")); mch_msg(_(" -M Modifications in text not allowed\n")); - mch_msg(_(" -b Binary mode\n")); - mch_msg(_(" -l Lisp mode\n")); - mch_msg(_(" -A Arabic mode\n")); - mch_msg(_(" -F Farsi mode\n")); - mch_msg(_(" -H Hebrew mode\n")); - mch_msg(_(" -V[N][file] Be verbose [level N][log messages to file]\n")); - mch_msg(_(" -D Debugging mode\n")); mch_msg(_(" -n No swap file, use memory only\n")); - mch_msg(_(" -r, -L List swap files and exit\n")); - mch_msg(_(" -r <file> Recover crashed session\n")); - mch_msg(_(" -u <vimrc> Use <vimrc> instead of the default\n")); - mch_msg(_(" -i <shada> Use <shada> instead of the default\n")); - mch_msg(_(" --noplugin Don't load plugin scripts\n")); - mch_msg(_(" -o[N] Open N windows (default: one for each file)\n")); - mch_msg(_(" -O[N] Like -o but split vertically\n")); - mch_msg(_(" -p[N] Open N tab pages (default: one for each file)\n")); - mch_msg(_(" + Start at end of file\n")); - mch_msg(_(" +<linenum> Start at line <linenum>\n")); - mch_msg(_(" +/<pattern> Start at first occurrence of <pattern>\n")); - mch_msg(_(" --cmd <command> Execute <command> before loading any vimrc\n")); - mch_msg(_(" -c <command> Execute <command> after loading the first file\n")); + mch_msg(_(" -o[N] Open N windows (default: one per file)\n")); + mch_msg(_(" -O[N] Open N vertical windows (default: one per file)\n")); + mch_msg(_(" -p[N] Open N tab pages (default: one per file)\n")); + mch_msg(_(" -r, -L List swap files\n")); + mch_msg(_(" -r <file> Recover edit state for this file\n")); + mch_msg(_(" -R Read-only mode\n")); mch_msg(_(" -S <session> Source <session> after loading the first file\n")); mch_msg(_(" -s <scriptin> Read Normal mode commands from <scriptin>\n")); - mch_msg(_(" -w <scriptout> Append all typed characters to <scriptout>\n")); - mch_msg(_(" -W <scriptout> Write all typed characters to <scriptout>\n")); - mch_msg(_(" --startuptime <file> Write startup timing messages to <file>\n")); - mch_msg(_(" --api-info Dump API metadata serialized to msgpack and exit\n")); + mch_msg(_(" -u <config> Use this config file\n")); + mch_msg(_(" -v, --version Print version information\n")); + mch_msg(_(" -V[N][file] Verbose [level][file]\n")); + mch_msg(_(" -Z Restricted mode\n")); + mch_msg("\n"); + mch_msg(_(" --api-info Write msgpack-encoded API metadata to stdout\n")); mch_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n")); mch_msg(_(" --headless Don't start a user interface\n")); - mch_msg(_(" -v, --version Print version information and exit\n")); - mch_msg(_(" -h, --help Print this help message and exit\n")); +#if !defined(UNIX) + mch_msg(_(" --literal Don't expand wildcards\n")); +#endif + mch_msg(_(" --noplugin Don't load plugins\n")); + mch_msg(_(" --startuptime <file> Write startup timing messages to <file>\n")); + mch_msg(_("\nSee \":help startup-options\" for all options.\n")); } diff --git a/src/nvim/map.c b/src/nvim/map.c index 73af487f90..537b6751e2 100644 --- a/src/nvim/map.c +++ b/src/nvim/map.c @@ -1,3 +1,6 @@ +// 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 <stdlib.h> #include <stdbool.h> #include <string.h> @@ -139,7 +142,6 @@ static inline bool String_eq(String a, String b) MAP_IMPL(int, int, DEFAULT_INITIALIZER) -MAP_IMPL(cstr_t, uint64_t, DEFAULT_INITIALIZER) MAP_IMPL(cstr_t, ptr_t, DEFAULT_INITIALIZER) MAP_IMPL(ptr_t, ptr_t, DEFAULT_INITIALIZER) MAP_IMPL(uint64_t, ptr_t, DEFAULT_INITIALIZER) @@ -147,4 +149,3 @@ MAP_IMPL(handle_T, ptr_t, DEFAULT_INITIALIZER) #define MSGPACK_HANDLER_INITIALIZER { .fn = NULL, .async = false } MAP_IMPL(String, MsgpackRpcRequestHandler, MSGPACK_HANDLER_INITIALIZER) #define KVEC_INITIALIZER { .size = 0, .capacity = 0, .items = NULL } -MAP_IMPL(linenr_T, bufhl_vec_T, KVEC_INITIALIZER) diff --git a/src/nvim/map.h b/src/nvim/map.h index ba3e84cb31..047aa163ce 100644 --- a/src/nvim/map.h +++ b/src/nvim/map.h @@ -25,13 +25,11 @@ void map_##T##_##U##_clear(Map(T, U) *map); MAP_DECLS(int, int) -MAP_DECLS(cstr_t, uint64_t) MAP_DECLS(cstr_t, ptr_t) MAP_DECLS(ptr_t, ptr_t) MAP_DECLS(uint64_t, ptr_t) MAP_DECLS(handle_T, ptr_t) MAP_DECLS(String, MsgpackRpcRequestHandler) -MAP_DECLS(linenr_T, bufhl_vec_T) #define map_new(T, U) map_##T##_##U##_new #define map_free(T, U) map_##T##_##U##_free diff --git a/src/nvim/mark.c b/src/nvim/mark.c index bb5b8e8178..7889fabd45 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -1,3 +1,6 @@ +// 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 + /* * mark.c: functions for setting marks and jumping to them */ @@ -62,7 +65,7 @@ int setmark(int c) /// Free fmark_T item void free_fmark(fmark_T fm) { - dict_unref(fm.additional_data); + tv_dict_unref(fm.additional_data); } /// Free xfmark_T item @@ -130,9 +133,15 @@ int setmark_pos(int c, pos_T *pos, int fnum) return OK; } + buf_T *buf = buflist_findnr(fnum); + // Can't set a mark in a non-existant buffer. + if (buf == NULL) { + return FAIL; + } + if (ASCII_ISLOWER(c)) { i = c - 'a'; - RESET_FMARK(curbuf->b_namedm + i, *pos, curbuf->b_fnum); + RESET_FMARK(buf->b_namedm + i, *pos, fnum); return OK; } if (ASCII_ISUPPER(c) || ascii_isdigit(c)) { @@ -879,7 +888,29 @@ void ex_changes(exarg_T *eap) * Example: Insert two lines below 55: mark_adjust(56, MAXLNUM, 2, 0); * or: mark_adjust(56, 55, MAXLNUM, 2); */ -void mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after) +void mark_adjust(linenr_T line1, + linenr_T line2, + long amount, + long amount_after, + bool end_temp) +{ + mark_adjust_internal(line1, line2, amount, amount_after, true, end_temp); +} + +// mark_adjust_nofold() does the same as mark_adjust() but without adjusting +// folds in any way. Folds must be adjusted manually by the caller. +// This is only useful when folds need to be moved in a way different to +// calling foldMarkAdjust() with arguments line1, line2, amount, amount_after, +// for an example of why this may be necessary, see do_move(). +void mark_adjust_nofold(linenr_T line1, linenr_T line2, long amount, + long amount_after, bool end_temp) +{ + mark_adjust_internal(line1, line2, amount, amount_after, false, end_temp); +} + +static void mark_adjust_internal(linenr_T line1, linenr_T line2, + long amount, long amount_after, + bool adjust_folds, bool end_temp) { int i; int fnum = curbuf->b_fnum; @@ -928,7 +959,7 @@ void mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after) } sign_mark_adjust(line1, line2, amount, amount_after); - bufhl_mark_adjust(curbuf, line1, line2, amount, amount_after); + bufhl_mark_adjust(curbuf, line1, line2, amount, amount_after, end_temp); } /* previous context mark */ @@ -1005,8 +1036,9 @@ void mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after) } } - /* adjust folds */ - foldMarkAdjust(win, line1, line2, amount, amount_after); + if (adjust_folds) { + foldMarkAdjust(win, line1, line2, amount, amount_after); + } } } @@ -1407,3 +1439,26 @@ void free_all_marks(void) memset(&namedfm[0], 0, sizeof(namedfm)); } #endif + +/// Adjust position to point to the first byte of a multi-byte character +/// +/// If it points to a tail byte it is move backwards to the head byte. +/// +/// @param[in] buf Buffer to adjust position in. +/// @param[out] lp Position to adjust. +void mark_mb_adjustpos(buf_T *buf, pos_T *lp) + FUNC_ATTR_NONNULL_ALL +{ + if (lp->col > 0 || lp->coladd > 1) { + const char_u *const p = ml_get_buf(buf, lp->lnum, false); + lp->col -= (*mb_head_off)(p, p + lp->col); + // Reset "coladd" when the cursor would be on the right half of a + // double-wide character. + if (lp->coladd == 1 + && p[lp->col] != TAB + && vim_isprintc((*mb_ptr2char)(p + lp->col)) + && ptr2cells(p + lp->col) > 1) { + lp->coladd = 0; + } + } +} diff --git a/src/nvim/mark.h b/src/nvim/mark.h index aff6e7273a..ed4e47907b 100644 --- a/src/nvim/mark.h +++ b/src/nvim/mark.h @@ -4,10 +4,12 @@ #include "nvim/macros.h" #include "nvim/ascii.h" #include "nvim/buffer_defs.h" +#include "nvim/func_attr.h" #include "nvim/mark_defs.h" #include "nvim/memory.h" #include "nvim/pos.h" #include "nvim/os/time.h" +#include "nvim/ex_cmds_defs.h" // for exarg_T /// Set fmark using given value #define SET_FMARK(fmarkp_, mark_, fnum_) \ @@ -29,7 +31,7 @@ /// Clear given fmark #define CLEAR_FMARK(fmarkp_) \ - RESET_FMARK(fmarkp_, ((pos_T) {0, 0, 0}), 0) + RESET_FMARK(fmarkp_, ((pos_T) { 0, 0, 0 }), 0) /// Set given extended mark (regular mark + file name) #define SET_XFMARK(xfmarkp_, mark_, fnum_, fname_) \ @@ -74,6 +76,46 @@ static inline int mark_local_index(const char name) : -1)))); } +static inline bool lt(pos_T, pos_T) REAL_FATTR_CONST REAL_FATTR_ALWAYS_INLINE; +static inline bool equalpos(pos_T, pos_T) + REAL_FATTR_CONST REAL_FATTR_ALWAYS_INLINE; +static inline bool ltoreq(pos_T, pos_T) + REAL_FATTR_CONST REAL_FATTR_ALWAYS_INLINE; +static inline void clearpos(pos_T *) + REAL_FATTR_ALWAYS_INLINE; + +/// Return true if position a is before (less than) position b. +static inline bool lt(pos_T a, pos_T b) +{ + if (a.lnum != b.lnum) { + return a.lnum < b.lnum; + } else if (a.col != b.col) { + return a.col < b.col; + } else { + return a.coladd < b.coladd; + } +} + +/// Return true if position a and b are equal. +static inline bool equalpos(pos_T a, pos_T b) +{ + return (a.lnum == b.lnum) && (a.col == b.col) && (a.coladd == b.coladd); +} + +/// Return true if position a is less than or equal to b. +static inline bool ltoreq(pos_T a, pos_T b) +{ + return lt(a, b) || equalpos(a, b); +} + +/// Clear the pos_T structure pointed to by a. +static inline void clearpos(pos_T *a) +{ + a->lnum = 0; + a->col = 0; + a->coladd = 0; +} + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "mark.h.generated.h" #endif diff --git a/src/nvim/mark_defs.h b/src/nvim/mark_defs.h index 720b2475ed..2cb489501e 100644 --- a/src/nvim/mark_defs.h +++ b/src/nvim/mark_defs.h @@ -3,7 +3,7 @@ #include "nvim/pos.h" #include "nvim/os/time.h" -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" /* * marks: positions in a file diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index ec4969d4f6..b24770a409 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -1,3 +1,6 @@ +// 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 + /// mbyte.c: Code specifically for handling multi-byte characters. /// Multibyte extensions partly by Sung-Hoon Baek /// @@ -50,6 +53,7 @@ #include "nvim/strings.h" #include "nvim/os/os.h" #include "nvim/arabic.h" +#include "nvim/mark.h" typedef struct { int rangeStart; @@ -71,7 +75,7 @@ struct interval { /* * Like utf8len_tab above, but using a zero for illegal lead bytes. */ -static uint8_t utf8len_tab_zero[256] = +const uint8_t utf8len_tab_zero[256] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -355,14 +359,13 @@ int bomb_size(void) */ void remove_bom(char_u *s) { - if (enc_utf8) { - char_u *p = s; + char *p = (char *)s; - while ((p = vim_strbyte(p, 0xef)) != NULL) { - if (p[1] == 0xbb && p[2] == 0xbf) - STRMOVE(p, p + 3); - else - ++p; + while ((p = strchr(p, 0xef)) != NULL) { + if ((uint8_t)p[1] == 0xbb && (uint8_t)p[2] == 0xbf) { + STRMOVE(p, p + 3); + } else { + p++; } } } @@ -376,166 +379,21 @@ void remove_bom(char_u *s) */ int mb_get_class(const char_u *p) { - return mb_get_class_buf(p, curbuf); + return mb_get_class_tab(p, curbuf->b_chartab); } -int mb_get_class_buf(const char_u *p, buf_T *buf) +int mb_get_class_tab(const char_u *p, const uint64_t *const chartab) { if (MB_BYTE2LEN(p[0]) == 1) { - if (p[0] == NUL || ascii_iswhite(p[0])) + if (p[0] == NUL || ascii_iswhite(p[0])) { return 0; - if (vim_iswordc_buf(p[0], buf)) + } + if (vim_iswordc_tab(p[0], chartab)) { return 2; + } return 1; } - if (enc_dbcs != 0 && p[0] != NUL && p[1] != NUL) - return dbcs_class(p[0], p[1]); - if (enc_utf8) - return utf_class(utf_ptr2char(p)); - return 0; -} - -/* - * Get class of a double-byte character. This always returns 3 or bigger. - * TODO: Should return 1 for punctuation. - */ -int dbcs_class(unsigned lead, unsigned trail) -{ - switch (enc_dbcs) { - /* please add classify routine for your language in here */ - - case DBCS_JPNU: /* ? */ - case DBCS_JPN: - { - /* JIS code classification */ - unsigned char lb = lead; - unsigned char tb = trail; - - /* convert process code to JIS */ - /* - * XXX: Code page identification can not use with all - * system! So, some other encoding information - * will be needed. - * In japanese: SJIS,EUC,UNICODE,(JIS) - * Note that JIS-code system don't use as - * process code in most system because it uses - * escape sequences(JIS is context depend encoding). - */ - /* assume process code is JAPANESE-EUC */ - lb &= 0x7f; - tb &= 0x7f; - /* exceptions */ - switch (lb << 8 | tb) { - case 0x2121: /* ZENKAKU space */ - return 0; - case 0x2122: /* TOU-TEN (Japanese comma) */ - case 0x2123: /* KU-TEN (Japanese period) */ - case 0x2124: /* ZENKAKU comma */ - case 0x2125: /* ZENKAKU period */ - return 1; - case 0x213c: /* prolongedsound handled as KATAKANA */ - return 13; - } - /* sieved by KU code */ - switch (lb) { - case 0x21: - case 0x22: - /* special symbols */ - return 10; - case 0x23: - /* alpha-numeric */ - return 11; - case 0x24: - /* hiragana */ - return 12; - case 0x25: - /* katakana */ - return 13; - case 0x26: - /* greek */ - return 14; - case 0x27: - /* russian */ - return 15; - case 0x28: - /* lines */ - return 16; - default: - /* kanji */ - return 17; - } - } - - case DBCS_KORU: /* ? */ - case DBCS_KOR: - { - /* KS code classification */ - unsigned char c1 = lead; - unsigned char c2 = trail; - - /* - * 20 : Hangul - * 21 : Hanja - * 22 : Symbols - * 23 : Alpha-numeric/Roman Letter (Full width) - * 24 : Hangul Letter(Alphabet) - * 25 : Roman Numeral/Greek Letter - * 26 : Box Drawings - * 27 : Unit Symbols - * 28 : Circled/Parenthesized Letter - * 29 : Hiragana/Katakana - * 30 : Cyrillic Letter - */ - - if (c1 >= 0xB0 && c1 <= 0xC8) - /* Hangul */ - return 20; - - else if (c1 >= 0xCA && c1 <= 0xFD) - /* Hanja */ - return 21; - else switch (c1) { - case 0xA1: - case 0xA2: - /* Symbols */ - return 22; - case 0xA3: - /* Alpha-numeric */ - return 23; - case 0xA4: - /* Hangul Letter(Alphabet) */ - return 24; - case 0xA5: - /* Roman Numeral/Greek Letter */ - return 25; - case 0xA6: - /* Box Drawings */ - return 26; - case 0xA7: - /* Unit Symbols */ - return 27; - case 0xA8: - case 0xA9: - if (c2 <= 0xAF) - return 25; /* Roman Letter */ - else if (c2 >= 0xF6) - return 22; /* Symbols */ - else - /* Circled/Parenthesized Letter */ - return 28; - case 0xAA: - case 0xAB: - /* Hiragana/Katakana */ - return 29; - case 0xAC: - /* Cyrillic Letter */ - return 30; - } - } - default: - break; - } - return 3; + return utf_class(utf_ptr2char(p)); } /* @@ -728,7 +586,7 @@ int utf_ptr2char(const char_u *p) * If byte sequence is illegal or incomplete, returns -1 and does not advance * "s". */ -static int utf_safe_read_char_adv(char_u **s, size_t *n) +static int utf_safe_read_char_adv(const char_u **s, size_t *n) { int c; @@ -770,7 +628,7 @@ static int utf_safe_read_char_adv(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(char_u **pp) +int mb_ptr2char_adv(const char_u **const pp) { int c; @@ -783,15 +641,12 @@ int mb_ptr2char_adv(char_u **pp) * Get character at **pp and advance *pp to the next character. * Note: composing characters are returned as separate characters. */ -int mb_cptr2char_adv(char_u **pp) +int mb_cptr2char_adv(const char_u **pp) { int c; c = (*mb_ptr2char)(*pp); - if (enc_utf8) - *pp += utf_ptr2len(*pp); - else - *pp += (*mb_ptr2len)(*pp); + *pp += utf_ptr2len(*pp); return c; } @@ -1077,12 +932,12 @@ int utf_char2len(int c) return 6; } -/* - * Convert Unicode character "c" to UTF-8 string in "buf[]". - * Returns the number of bytes. - * This does not include composing characters. - */ -int utf_char2bytes(int c, char_u *buf) +/// Convert Unicode character to UTF-8 string +/// +/// @param c character to convert to \p buf +/// @param[out] buf UTF-8 string generated from \p c, does not add \0 +/// @return Number of bytes (1-6). Does not include composing characters. +int utf_char2bytes(int c, char_u *const buf) { if (c < 0x80) { /* 7 bits */ buf[0] = c; @@ -1322,11 +1177,14 @@ int utf_fold(int a) return utf_convert(a, foldCase, ARRAY_SIZE(foldCase)); } -/* - * Return the upper-case equivalent of "a", which is a UCS-4 character. Use - * simple case folding. - */ -int utf_toupper(int a) +// Vim's own character class functions. These exist because many library +// islower()/toupper() etc. do not work properly: they crash when used with +// invalid values or can't handle latin1 when the locale is C. +// Speed is most important here. + +/// Return the upper-case equivalent of "a", which is a UCS-4 character. Use +/// simple case folding. +int mb_toupper(int a) { /* If 'casemap' contains "keepascii" use ASCII style toupper(). */ if (a < 128 && (cmp_flags & CMP_KEEPASCII)) @@ -1346,17 +1204,15 @@ int utf_toupper(int a) return utf_convert(a, toUpper, ARRAY_SIZE(toUpper)); } -bool utf_islower(int a) +bool mb_islower(int a) { - /* German sharp s is lower case but has no upper case equivalent. */ - return (utf_toupper(a) != a) || a == 0xdf; + // German sharp s is lower case but has no upper case equivalent. + return (mb_toupper(a) != a) || a == 0xdf; } -/* - * Return the lower-case equivalent of "a", which is a UCS-4 character. Use - * simple case folding. - */ -int utf_tolower(int a) +/// Return the lower-case equivalent of "a", which is a UCS-4 character. Use +/// simple case folding. +int mb_tolower(int a) { /* If 'casemap' contains "keepascii" use ASCII style tolower(). */ if (a < 128 && (cmp_flags & CMP_KEEPASCII)) @@ -1376,12 +1232,13 @@ int utf_tolower(int a) return utf_convert(a, toLower, ARRAY_SIZE(toLower)); } -bool utf_isupper(int a) +bool mb_isupper(int a) { - return utf_tolower(a) != a; + return mb_tolower(a) != a; } -static int utf_strnicmp(char_u *s1, char_u *s2, size_t n1, size_t n2) +static int utf_strnicmp(const char_u *s1, const char_u *s2, size_t n1, + size_t n2) { int c1, c2, cdiff; char_u buffer[6]; @@ -1451,6 +1308,7 @@ static int utf_strnicmp(char_u *s1, char_u *s2, size_t n1, size_t n2) # define CP_UTF8 65001 /* magic number from winnls.h */ #endif +/// Reassigns `strw` to a new, allocated pointer to a UTF16 string. int utf8_to_utf16(const char *str, WCHAR **strw) FUNC_ATTR_NONNULL_ALL { @@ -1484,42 +1342,48 @@ int utf8_to_utf16(const char *str, WCHAR **strw) (WCHAR *)pos, wchar_len); assert(r == wchar_len); + if (r != wchar_len) { + EMSG2("MultiByteToWideChar failed: %d", r); + } *strw = (WCHAR *)pos; return 0; } +/// Reassigns `str` to a new, allocated pointer to a UTF8 string. int utf16_to_utf8(const WCHAR *strw, char **str) FUNC_ATTR_NONNULL_ALL { // Compute the space required to store the string as UTF-8. - ssize_t utf8_len = WideCharToMultiByte(CP_UTF8, - 0, - strw, - -1, - NULL, - 0, - NULL, - NULL); + DWORD utf8_len = WideCharToMultiByte(CP_UTF8, + 0, + strw, + -1, + NULL, + 0, + NULL, + NULL); if (utf8_len == 0) { return GetLastError(); } - ssize_t buf_sz = utf8_len * sizeof(char); - char *buf = xmalloc(buf_sz); - char *pos = buf; + *str = xmallocz(utf8_len); - // Convert string to UTF-8. - int r = WideCharToMultiByte(CP_UTF8, - 0, - strw, - -1, - (LPSTR *)pos, - utf8_len, - NULL, - NULL); - assert(r == utf8_len); - *str = pos; + // Convert to UTF-8. + utf8_len = WideCharToMultiByte(CP_UTF8, + 0, + strw, + -1, + *str, + utf8_len, + NULL, + NULL); + if (utf8_len == 0) { + free(*str); + *str = NULL; + return GetLastError(); + } + (*str)[utf8_len] = '\0'; return 0; } @@ -1534,48 +1398,26 @@ int utf16_to_utf8(const WCHAR *strw, char **str) * Returns zero if s1 and s2 are equal (ignoring case), the difference between * two characters otherwise. */ -int mb_strnicmp(char_u *s1, char_u *s2, size_t nn) -{ - int i, l; - int cdiff; - int n = (int)nn; - - if (enc_utf8) { - return utf_strnicmp(s1, s2, nn, nn); - } else { - for (i = 0; i < n; i += l) { - if (s1[i] == NUL && s2[i] == NUL) /* both strings end */ - return 0; - - l = (*mb_ptr2len)(s1 + i); - if (l <= 1) { - /* Single byte: first check normally, then with ignore case. */ - if (s1[i] != s2[i]) { - cdiff = vim_tolower(s1[i]) - vim_tolower(s2[i]); - if (cdiff != 0) - return cdiff; - } - } else { - /* For non-Unicode multi-byte don't ignore case. */ - if (l > n - i) - l = n - i; - cdiff = STRNCMP(s1 + i, s2 + i, l); - if (cdiff != 0) - return cdiff; - } - } - } - return 0; +int mb_strnicmp(const char_u *s1, const char_u *s2, const size_t nn) +{ + return utf_strnicmp(s1, s2, nn, nn); } -/* We need to call mb_stricmp() even when we aren't dealing with a multi-byte - * encoding because mb_stricmp() takes care of all ascii and non-ascii - * encodings, including characters with umlauts in latin1, etc., while - * STRICMP() only handles the system locale version, which often does not - * handle non-ascii properly. */ -int mb_stricmp(char_u *s1, char_u *s2) +/// Compare strings case-insensitively +/// +/// @note We need to call mb_stricmp() even when we aren't dealing with +/// a multi-byte encoding because mb_stricmp() takes care of all ASCII and +/// non-ascii encodings, including characters with umlauts in latin1, +/// etc., while STRICMP() only handles the system locale version, which +/// often does not handle non-ascii properly. +/// +/// @param[in] s1 First string to compare, not more then #MAXCOL characters. +/// @param[in] s2 Second string to compare, not more then #MAXCOL characters. +/// +/// @return 0 if strings are equal, <0 if s1 < s2, >0 if s1 > s2. +int mb_stricmp(const char *s1, const char *s2) { - return mb_strnicmp(s1, s2, MAXCOL); + return mb_strnicmp((const char_u *)s1, (const char_u *)s2, MAXCOL); } /* @@ -1693,27 +1535,24 @@ int mb_off_next(char_u *base, char_u *p) int i; int j; - if (enc_utf8) { - if (*p < 0x80) /* be quick for ASCII */ - return 0; + if (*p < 0x80) { // be quick for ASCII + return 0; + } - /* Find the next character that isn't 10xx.xxxx */ - for (i = 0; (p[i] & 0xc0) == 0x80; ++i) - ; - if (i > 0) { - /* Check for illegal sequence. */ - for (j = 0; p - j > base; ++j) - if ((p[-j] & 0xc0) != 0x80) - break; - if (utf8len_tab[p[-j]] != i + j) - return 0; + // Find the next character that isn't 10xx.xxxx + for (i = 0; (p[i] & 0xc0) == 0x80; i++) {} + if (i > 0) { + // Check for illegal sequence. + for (j = 0; p - j > base; j++) { + if ((p[-j] & 0xc0) != 0x80) { + break; + } + } + if (utf8len_tab[p[-j]] != i + j) { + return 0; } - return i; } - - /* Only need to check if we're on a trail byte, it doesn't matter if we - * want the offset to the next or current character. */ - return (*mb_head_off)(base, p); + return i; } /* @@ -1756,10 +1595,10 @@ void utf_find_illegal(void) char_u *tofree = NULL; vimconv.vc_type = CONV_NONE; - if (enc_utf8 && (enc_canon_props(curbuf->b_p_fenc) & ENC_8BIT)) { - /* 'encoding' is "utf-8" but we are editing a 8-bit encoded file, - * possibly a utf-8 file with illegal bytes. Setup for conversion - * from utf-8 to 'fileencoding'. */ + if (enc_canon_props(curbuf->b_p_fenc) & ENC_8BIT) { + // 'encoding' is "utf-8" but we are editing a 8-bit encoded file, + // possibly a utf-8 file with illegal bytes. Setup for conversion + // from utf-8 to 'fileencoding'. convert_setup(&vimconv, p_enc, curbuf->b_p_fenc); } @@ -1816,29 +1655,42 @@ theend: */ void mb_adjust_cursor(void) { - mb_adjustpos(curbuf, &curwin->w_cursor); + mark_mb_adjustpos(curbuf, &curwin->w_cursor); } -/* - * Adjust position "*lp" to point to the first byte of a multi-byte character. - * If it points to a tail byte it's moved backwards to the head byte. - */ -void mb_adjustpos(buf_T *buf, pos_T *lp) +/// Checks and adjusts cursor column. Not mode-dependent. +/// @see check_cursor_col_win +/// +/// @param win_ Places cursor on a valid column for this window. +void mb_check_adjust_col(void *win_) { - char_u *p; + win_T *win = (win_T *)win_; + colnr_T oldcol = win->w_cursor.col; + + // Column 0 is always valid. + if (oldcol != 0) { + char_u *p = ml_get_buf(win->w_buffer, win->w_cursor.lnum, false); + colnr_T len = (colnr_T)STRLEN(p); - if (lp->col > 0 - || lp->coladd > 1 - ) { - p = ml_get_buf(buf, lp->lnum, FALSE); - lp->col -= (*mb_head_off)(p, p + lp->col); - /* Reset "coladd" when the cursor would be on the right half of a - * double-wide character. */ - if (lp->coladd == 1 - && p[lp->col] != TAB - && vim_isprintc((*mb_ptr2char)(p + lp->col)) - && ptr2cells(p + lp->col) > 1) - lp->coladd = 0; + // Empty line or invalid column? + if (len == 0 || oldcol < 0) { + win->w_cursor.col = 0; + } else { + // Cursor column too big for line? + if (oldcol > len) { + win->w_cursor.col = len - 1; + } + // Move the cursor to the head byte. + win->w_cursor.col -= (*mb_head_off)(p, p + win->w_cursor.col); + } + + // Reset `coladd` when the cursor would be on the right half of a + // double-wide character. + if (win->w_cursor.coladd == 1 && p[win->w_cursor.col] != TAB + && vim_isprintc((*mb_ptr2char)(p + win->w_cursor.col)) + && ptr2cells(p + win->w_cursor.col) > 1) { + win->w_cursor.coladd = 0; + } } } @@ -1887,52 +1739,55 @@ int mb_charlen_len(char_u *str, int len) return count; } -/* - * Try to un-escape a multi-byte character. - * Used for the "to" and "from" part of a mapping. - * Return the un-escaped string if it is a multi-byte character, and advance - * "pp" to just after the bytes that formed it. - * Return NULL if no multi-byte char was found. - */ -char_u * mb_unescape(char_u **pp) -{ - static char_u buf[6]; - int n; - int m = 0; - char_u *str = *pp; - - /* Must translate K_SPECIAL KS_SPECIAL KE_FILLER to K_SPECIAL and CSI - * KS_EXTRA KE_CSI to CSI. - * Maximum length of a utf-8 character is 4 bytes. */ - for (n = 0; str[n] != NUL && m < 4; ++n) { - if (str[n] == K_SPECIAL - && str[n + 1] == KS_SPECIAL - && str[n + 2] == KE_FILLER) { - buf[m++] = K_SPECIAL; - n += 2; - } else if ((str[n] == K_SPECIAL - ) - && str[n + 1] == KS_EXTRA - && str[n + 2] == (int)KE_CSI) { - buf[m++] = CSI; - n += 2; - } else if (str[n] == K_SPECIAL - ) - break; /* a special key can't be a multibyte char */ - else - buf[m++] = str[n]; - buf[m] = NUL; +/// Try to unescape a multibyte character +/// +/// Used for the rhs and lhs of the mappings. +/// +/// @param[in,out] pp String to unescape. Is advanced to just after the bytes +/// that form a multibyte character. +/// +/// @return Unescaped string if it is a multibyte character, NULL if no +/// multibyte character was found. Returns a static buffer, always one +/// and the same. +const char *mb_unescape(const char **const pp) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL +{ + static char buf[6]; + size_t buf_idx = 0; + uint8_t *str = (uint8_t *)(*pp); + + // Must translate K_SPECIAL KS_SPECIAL KE_FILLER to K_SPECIAL and CSI + // KS_EXTRA KE_CSI to CSI. + // Maximum length of a utf-8 character is 4 bytes. + for (size_t str_idx = 0; str[str_idx] != NUL && buf_idx < 4; str_idx++) { + if (str[str_idx] == K_SPECIAL + && str[str_idx + 1] == KS_SPECIAL + && str[str_idx + 2] == KE_FILLER) { + buf[buf_idx++] = (char)K_SPECIAL; + str_idx += 2; + } else if ((str[str_idx] == K_SPECIAL) + && str[str_idx + 1] == KS_EXTRA + && str[str_idx + 2] == KE_CSI) { + buf[buf_idx++] = (char)CSI; + str_idx += 2; + } else if (str[str_idx] == K_SPECIAL) { + break; // A special key can't be a multibyte char. + } else { + buf[buf_idx++] = (char)str[str_idx]; + } + buf[buf_idx] = NUL; - /* Return a multi-byte character if it's found. An illegal sequence - * will result in a 1 here. */ - if ((*mb_ptr2len)(buf) > 1) { - *pp = str + n + 1; + // Return a multi-byte character if it's found. An illegal sequence + // will result in a 1 here. + if (utf_ptr2len((const char_u *)buf) > 1) { + *pp = (const char *)str + str_idx + 1; return buf; } - /* Bail out quickly for ASCII. */ - if (buf[0] < 128) + // Bail out quickly for ASCII. + if ((uint8_t)buf[0] < 128) { break; + } } return NULL; } @@ -2181,8 +2036,8 @@ void * my_iconv_open(char_u *to, char_u *from) * 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(vimconv_T *vcp, char_u *str, size_t slen, - size_t *unconvlenp, size_t *resultlenp) +static char_u *iconv_string(const vimconv_T *const vcp, char_u *str, + size_t slen, size_t *unconvlenp, size_t *resultlenp) { const char *from; size_t fromlen; @@ -2238,13 +2093,7 @@ static char_u * iconv_string(vimconv_T *vcp, char_u *str, size_t slen, *to++ = '?'; if ((*mb_ptr2cells)((char_u *)from) > 1) *to++ = '?'; - if (enc_utf8) - l = utfc_ptr2len_len((const char_u *)from, (int)fromlen); - else { - l = (*mb_ptr2len)((char_u *)from); - if (l > (int)fromlen) - l = (int)fromlen; - } + l = utfc_ptr2len_len((const char_u *)from, (int)fromlen); from += l; fromlen -= l; } else if (ICONV_ERRNO != ICONV_E2BIG) { @@ -2473,7 +2322,7 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8, * Illegal chars are often changed to "?", unless vcp->vc_fail is set. * When something goes wrong, NULL is returned and "*lenp" is unchanged. */ -char_u * string_convert(vimconv_T *vcp, char_u *ptr, size_t *lenp) +char_u *string_convert(const vimconv_T *const vcp, char_u *ptr, size_t *lenp) { return string_convert_ext(vcp, ptr, lenp, NULL); } @@ -2483,7 +2332,7 @@ char_u * string_convert(vimconv_T *vcp, char_u *ptr, size_t *lenp) * 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(vimconv_T *vcp, char_u *ptr, +char_u * string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp, size_t *unconvlenp) { char_u *retval = NULL; diff --git a/src/nvim/mbyte.h b/src/nvim/mbyte.h index 2c92a0fbb2..bf6ccb13a5 100644 --- a/src/nvim/mbyte.h +++ b/src/nvim/mbyte.h @@ -1,7 +1,14 @@ #ifndef NVIM_MBYTE_H #define NVIM_MBYTE_H +#include <stdint.h> #include <stdbool.h> +#include <string.h> + +#include "nvim/iconv.h" +#include "nvim/func_attr.h" +#include "nvim/os/os_defs.h" // For WCHAR, indirect +#include "nvim/types.h" // for char_u /* * Return byte length of character that starts with byte "b". @@ -12,6 +19,9 @@ #define MB_BYTE2LEN(b) utf8len_tab[b] #define MB_BYTE2LEN_CHECK(b) (((b) < 0 || (b) > 255) ? 1 : utf8len_tab[b]) +// max length of an unicode char +#define MB_MAXCHAR 6 + /* properties used in enc_canon_table[] (first three mutually exclusive) */ #define ENC_8BIT 0x01 #define ENC_DBCS 0x02 @@ -40,7 +50,43 @@ #define mb_ptr2char utf_ptr2char #define mb_head_off utf_head_off +/// Flags for vimconv_T +typedef enum { + CONV_NONE = 0, + CONV_TO_UTF8 = 1, + CONV_9_TO_UTF8 = 2, + CONV_TO_LATIN1 = 3, + CONV_TO_LATIN9 = 4, + CONV_ICONV = 5, +} ConvFlags; + +/// Structure used for string conversions +typedef struct { + int vc_type; ///< Zero or more ConvFlags. + int vc_factor; ///< Maximal expansion factor. +# ifdef USE_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; + +extern const uint8_t utf8len_tab_zero[256]; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "mbyte.h.generated.h" #endif + +static inline int mb_strcmp_ic(bool ic, const char *s1, const char *s2) + REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; + +/// Compare strings +/// +/// @param[in] ic True if case is to be ignored. +/// +/// @return 0 if s1 == s2, <0 if s1 < s2, >0 if s1 > s2. +static inline int mb_strcmp_ic(bool ic, const char *s1, const char *s2) +{ + return (ic ? mb_stricmp(s1, s2) : strcmp(s1, s2)); +} #endif // NVIM_MBYTE_H diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c index 43412e3916..4428dd42aa 100644 --- a/src/nvim/memfile.c +++ b/src/nvim/memfile.c @@ -1,3 +1,6 @@ +// 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 + /// An abstraction to handle blocks of memory which can be stored in a file. /// This is the implementation of a sort of virtual memory. /// @@ -51,6 +54,7 @@ #include "nvim/memory.h" #include "nvim/os_unix.h" #include "nvim/path.h" +#include "nvim/assert.h" #include "nvim/os/os.h" #include "nvim/os/input.h" @@ -105,23 +109,24 @@ memfile_T *mf_open(char_u *fname, int flags) if (mfp->mf_fd >= 0 && os_fileinfo_fd(mfp->mf_fd, &file_info)) { uint64_t blocksize = os_fileinfo_blocksize(&file_info); if (blocksize >= MIN_SWAP_PAGE_SIZE && blocksize <= MAX_SWAP_PAGE_SIZE) { - assert(blocksize <= UINT_MAX); + STATIC_ASSERT(MAX_SWAP_PAGE_SIZE <= UINT_MAX, + "MAX_SWAP_PAGE_SIZE must fit into an unsigned"); mfp->mf_page_size = (unsigned)blocksize; } } - off_t size; + off_T size; // When recovering, the actual block size will be retrieved from block 0 // in ml_recover(). The size used here may be wrong, therefore mf_blocknr_max // must be rounded up. if (mfp->mf_fd < 0 || (flags & (O_TRUNC|O_EXCL)) - || (size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0) { + || (size = vim_lseek(mfp->mf_fd, 0L, SEEK_END)) <= 0) { // no file or empty file mfp->mf_blocknr_max = 0; } else { - assert(sizeof(off_t) <= sizeof(blocknr_T) + assert(sizeof(off_T) <= sizeof(blocknr_T) && mfp->mf_page_size > 0 && mfp->mf_page_size - 1 <= INT64_MAX - size); mfp->mf_blocknr_max = (((blocknr_T)size + mfp->mf_page_size - 1) @@ -684,9 +689,9 @@ static int mf_read(memfile_T *mfp, bhdr_T *hp) return FAIL; unsigned page_size = mfp->mf_page_size; - // TODO(elmart): Check (page_size * hp->bh_bnum) within off_t bounds. - off_t offset = (off_t)(page_size * hp->bh_bnum); - if (lseek(mfp->mf_fd, offset, SEEK_SET) != offset) { + // TODO(elmart): Check (page_size * hp->bh_bnum) within off_T bounds. + off_T offset = (off_T)(page_size * hp->bh_bnum); + if (vim_lseek(mfp->mf_fd, offset, SEEK_SET) != offset) { PERROR(_("E294: Seek error in swap file read")); return FAIL; } @@ -711,7 +716,7 @@ static int mf_read(memfile_T *mfp, bhdr_T *hp) /// - Write error in swap file. static int mf_write(memfile_T *mfp, bhdr_T *hp) { - off_t offset; // offset in the file + off_T offset; // offset in the file blocknr_T nr; // block nr which is being written bhdr_T *hp2; unsigned page_size; // number of bytes in a page @@ -740,9 +745,9 @@ static int mf_write(memfile_T *mfp, bhdr_T *hp) hp2 = hp; } - // TODO(elmart): Check (page_size * nr) within off_t bounds. - offset = (off_t)(page_size * nr); - if (lseek(mfp->mf_fd, offset, SEEK_SET) != offset) { + // TODO(elmart): Check (page_size * nr) within off_T bounds. + offset = (off_T)(page_size * nr); + if (vim_lseek(mfp->mf_fd, offset, SEEK_SET) != offset) { PERROR(_("E296: Seek error in swap file write")); return FAIL; } @@ -890,6 +895,7 @@ static bool mf_do_open(memfile_T *mfp, char_u *fname, int flags) { // fname cannot be NameBuff, because it must have been allocated. mf_set_fnames(mfp, fname); + assert(mfp->mf_fname != NULL); /// Extra security check: When creating a swap file it really shouldn't /// exist yet. If there is a symbolic link, this is most likely an attack. @@ -909,12 +915,7 @@ static bool mf_do_open(memfile_T *mfp, char_u *fname, int flags) return false; } -#ifdef HAVE_FD_CLOEXEC - int fdflags = fcntl(mfp->mf_fd, F_GETFD); - if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) { - (void)fcntl(mfp->mf_fd, F_SETFD, fdflags | FD_CLOEXEC); - } -#endif + (void)os_set_cloexec(mfp->mf_fd); #ifdef HAVE_SELINUX mch_copy_sec(fname, mfp->mf_fname); #endif diff --git a/src/nvim/memfile_defs.h b/src/nvim/memfile_defs.h index cc71e1a7ff..b3c2f3564c 100644 --- a/src/nvim/memfile_defs.h +++ b/src/nvim/memfile_defs.h @@ -3,8 +3,10 @@ #include <stdint.h> #include <stdbool.h> +#include <stdlib.h> #include "nvim/types.h" +#include "nvim/pos.h" /// A block number. /// diff --git a/src/nvim/memline.c b/src/nvim/memline.c index a9a53ebca7..f28a9e60f4 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -1,3 +1,6 @@ +// 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 + /* for debugging */ /* #define CHECK(c, s) if (c) EMSG(s) */ #define CHECK(c, s) @@ -439,14 +442,7 @@ void ml_setname(buf_T *buf) EMSG(_("E301: Oops, lost the swap file!!!")); return; } -#ifdef HAVE_FD_CLOEXEC - { - int fdflags = fcntl(mfp->mf_fd, F_GETFD); - if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) { - (void)fcntl(mfp->mf_fd, F_SETFD, fdflags | FD_CLOEXEC); - } - } -#endif + (void)os_set_cloexec(mfp->mf_fd); } if (!success) EMSG(_("E302: Could not rename swap file")); @@ -623,7 +619,7 @@ static bool ml_check_b0_strings(ZERO_BL *b0p) return (memchr(b0p->b0_version, NUL, 10) && memchr(b0p->b0_uname, NUL, B0_UNAME_SIZE) && memchr(b0p->b0_hname, NUL, B0_HNAME_SIZE) - && memchr(b0p->b0_fname, NUL, B0_FNAME_SIZE_CRYPT)); + && memchr(b0p->b0_fname, NUL, B0_FNAME_SIZE_CRYPT)); // -V512 } /* @@ -767,7 +763,7 @@ void ml_recover(void) int idx; int top; int txt_start; - off_t size; + off_T size; int called_from_main; int serious_error = TRUE; long mtime; @@ -918,10 +914,11 @@ void ml_recover(void) msg_end(); goto theend; } - if ((size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0) - mfp->mf_blocknr_max = 0; /* no file or empty file */ - else + if ((size = vim_lseek(mfp->mf_fd, (off_T)0L, SEEK_END)) <= 0) { + mfp->mf_blocknr_max = 0; // no file or empty file + } else { mfp->mf_blocknr_max = size / mfp->mf_page_size; + } mfp->mf_infile_count = mfp->mf_blocknr_max; /* need to reallocate the memory used to store the data */ @@ -999,7 +996,7 @@ void ml_recover(void) if (b0_ff != 0) set_fileformat(b0_ff - 1, OPT_LOCAL); if (b0_fenc != NULL) { - set_option_value((char_u *)"fenc", 0L, b0_fenc, OPT_LOCAL); + set_option_value("fenc", 0L, (char *)b0_fenc, OPT_LOCAL); xfree(b0_fenc); } unchanged(curbuf, TRUE); @@ -1063,11 +1060,12 @@ void ml_recover(void) if (!cannot_open) { line_count = pp->pb_pointer[idx].pe_line_count; if (readfile(curbuf->b_ffname, NULL, lnum, - pp->pb_pointer[idx].pe_old_lnum - 1, - line_count, NULL, 0) == FAIL) - cannot_open = TRUE; - else + pp->pb_pointer[idx].pe_old_lnum - 1, line_count, + NULL, 0) != OK) { + cannot_open = true; + } else { lnum += line_count; + } } if (cannot_open) { ++error; @@ -1179,7 +1177,7 @@ void ml_recover(void) * empty. Don't set the modified flag then. */ if (!(curbuf->b_ml.ml_line_count == 2 && *ml_get(1) == NUL)) { changed_int(); - ++curbuf->b_changedtick; + buf_set_changedtick(curbuf, curbuf->b_changedtick + 1); } } else { for (idx = 1; idx <= lnum; ++idx) { @@ -1189,7 +1187,7 @@ void ml_recover(void) xfree(p); if (i != 0) { changed_int(); - ++curbuf->b_changedtick; + buf_set_changedtick(curbuf, curbuf->b_changedtick + 1); break; } } @@ -1409,8 +1407,8 @@ recover_names ( for (int i = 0; i < num_files; ++i) { /* print the swap file name */ msg_outnum((long)++file_count); - MSG_PUTS(". "); - msg_puts(path_tail(files[i])); + msg_puts(". "); + msg_puts((const char *)path_tail(files[i])); msg_putchar('\n'); (void)swapfile_info(files[i]); } @@ -1462,6 +1460,7 @@ static int process_still_running; */ static time_t swapfile_info(char_u *fname) { + assert(fname != NULL); int fd; struct block0 b0; time_t x = (time_t)0; @@ -2317,7 +2316,7 @@ ml_append_int ( * * return FAIL for failure, OK otherwise */ -int ml_replace(linenr_T lnum, char_u *line, int copy) +int ml_replace(linenr_T lnum, char_u *line, bool copy) { if (line == NULL) /* just checking... */ return FAIL; @@ -3137,6 +3136,7 @@ attention_message ( char_u *fname /* swap file name */ ) { + assert(buf->b_fname != NULL); time_t x, sx; char *p; @@ -3368,29 +3368,32 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, } if (swap_exists_action != SEA_NONE && choice == 0) { - char *name; + const char *const sw_msg_1 = _("Swap file \""); + const char *const sw_msg_2 = _("\" already exists!"); const size_t fname_len = strlen(fname); - name = xmalloc(fname_len - + strlen(_("Swap file \"")) - + strlen(_("\" already exists!")) + 5); - STRCPY(name, _("Swap file \"")); - home_replace(NULL, (char_u *) fname, (char_u *)&name[strlen(name)], - fname_len, true); - STRCAT(name, _("\" already exists!")); - choice = do_dialog(VIM_WARNING, - (char_u *)_("VIM - ATTENTION"), - (char_u *)(name == NULL - ? _("Swap file already exists!") - : name), + const size_t sw_msg_1_len = strlen(sw_msg_1); + const size_t sw_msg_2_len = strlen(sw_msg_2); + + const size_t name_len = sw_msg_1_len + fname_len + sw_msg_2_len + 5; + + char *const name = xmalloc(name_len); + memcpy(name, sw_msg_1, sw_msg_1_len + 1); + home_replace(NULL, (char_u *)fname, (char_u *)&name[sw_msg_1_len], + fname_len, true); + xstrlcat(name, sw_msg_2, name_len); + choice = do_dialog(VIM_WARNING, (char_u *)_("VIM - ATTENTION"), + (char_u *)name, # if defined(UNIX) - process_still_running - ? (char_u *)_( - "&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort") : + process_still_running + ? (char_u *)_( + "&Open Read-Only\n&Edit anyway\n&Recover" + "\n&Quit\n&Abort") : # endif - (char_u *)_( - "&Open Read-Only\n&Edit anyway\n&Recover\n&Delete it\n&Quit\n&Abort"), - 1, NULL, FALSE); + (char_u *)_( + "&Open Read-Only\n&Edit anyway\n&Recover" + "\n&Delete it\n&Quit\n&Abort"), + 1, NULL, false); # if defined(UNIX) if (process_still_running && choice >= 4) diff --git a/src/nvim/memline.h b/src/nvim/memline.h index f84e86fea0..a239c6a031 100644 --- a/src/nvim/memline.h +++ b/src/nvim/memline.h @@ -2,6 +2,8 @@ #define NVIM_MEMLINE_H #include "nvim/types.h" +#include "nvim/pos.h" // for pos_T, linenr_T, colnr_T +#include "nvim/buffer_defs.h" // for buf_T #ifdef INCLUDE_GENERATED_DECLARATIONS # include "memline.h.generated.h" diff --git a/src/nvim/memory.c b/src/nvim/memory.c index 92ead873ae..328b96fd5c 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -1,3 +1,6 @@ +// 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 + // Various routines dealing with allocation and deallocation of memory. #include <assert.h> @@ -342,10 +345,6 @@ char *xstpcpy(char *restrict dst, const char *restrict src) /// WARNING: xstpncpy will ALWAYS write maxlen bytes. If src is shorter than /// maxlen, zeroes will be written to the remaining bytes. /// -/// TODO(aktau): I don't see a good reason to have this last behaviour, and -/// it is potentially wasteful. Could we perhaps deviate from the standard -/// and not zero the rest of the buffer? -/// /// @param dst /// @param src /// @param maxlen @@ -364,29 +363,58 @@ char *xstpncpy(char *restrict dst, const char *restrict src, size_t maxlen) } } -/// xstrlcpy - Copy a %NUL terminated string into a sized buffer +/// xstrlcpy - Copy a NUL-terminated string into a sized buffer /// -/// Compatible with *BSD strlcpy: the result is always a valid -/// NUL-terminated string that fits in the buffer (unless, -/// of course, the buffer size is zero). It does not pad -/// out the result like strncpy() does. +/// Compatible with *BSD strlcpy: the result is always a valid NUL-terminated +/// string that fits in the buffer (unless, of course, the buffer size is +/// zero). It does not pad out the result like strncpy() does. /// -/// @param dst Where to copy the string to -/// @param src Where to copy the string from -/// @param size Size of destination buffer -/// @return Length of the source string (i.e.: strlen(src)) -size_t xstrlcpy(char *restrict dst, const char *restrict src, size_t size) +/// @param dst Buffer to store the result +/// @param src String to be copied +/// @param dsize Size of `dst` +/// @return strlen(src). If retval >= dstsize, truncation occurs. +size_t xstrlcpy(char *restrict dst, const char *restrict src, size_t dsize) FUNC_ATTR_NONNULL_ALL { - size_t ret = strlen(src); + size_t slen = strlen(src); - if (size) { - size_t len = (ret >= size) ? size - 1 : ret; + if (dsize) { + size_t len = MIN(slen, dsize - 1); memcpy(dst, src, len); dst[len] = '\0'; } - return ret; + return slen; // Does not include NUL. +} + +/// Appends `src` to string `dst` of size `dsize` (unlike strncat, dsize is the +/// full size of `dst`, not space left). At most dsize-1 characters +/// will be copied. Always NUL terminates. `src` and `dst` may overlap. +/// +/// @see vim_strcat from Vim. +/// @see strlcat from OpenBSD. +/// +/// @param dst Buffer to be appended-to. Must have a NUL byte. +/// @param src String to put at the end of `dst` +/// @param dsize Size of `dst` including NUL byte. Must be greater than 0. +/// @return strlen(src) + strlen(initial dst) +/// If retval >= dsize, truncation occurs. +size_t xstrlcat(char *const dst, const char *const src, const size_t dsize) + FUNC_ATTR_NONNULL_ALL +{ + assert(dsize > 0); + const size_t dlen = strlen(dst); + assert(dlen < dsize); + const size_t slen = strlen(src); + + if (slen > dsize - dlen - 1) { + memmove(dst + dlen, src, dsize - dlen - 1); + dst[dsize - 1] = '\0'; + } else { + memmove(dst + dlen, src, slen + 1); + } + + return slen + dlen; // Does not include NUL. } /// strdup() wrapper @@ -401,6 +429,19 @@ char *xstrdup(const char *str) return xmemdupz(str, strlen(str)); } +/// strdup() wrapper +/// +/// Unlike xstrdup() allocates a new empty string if it receives NULL. +char *xstrdupnul(const char *const str) + FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET +{ + if (str == NULL) { + return xmallocz(0); + } else { + return xstrdup(str); + } +} + /// A version of memchr that starts the search at `src + len`. /// /// Based on glibc's memrchr. @@ -446,6 +487,20 @@ void *xmemdup(const void *data, size_t len) return memcpy(xmalloc(len), data, len); } +/// Returns true if strings `a` and `b` are equal. Arguments may be NULL. +bool strequal(const char *a, const char *b) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + return (a == NULL && b == NULL) || (a && b && strcmp(a, b) == 0); +} + +/// Case-insensitive `strequal`. +bool striequal(const char *a, const char *b) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + return (a == NULL && b == NULL) || (a && b && STRICMP(a, b) == 0); +} + /* * Avoid repeating the error message many times (they take 1 second each). * Did_outofmem_msg is reset when a character is read. @@ -530,7 +585,7 @@ void free_all_mem(void) p_ea = false; if (first_tabpage->tp_next != NULL) do_cmdline_cmd("tabonly!"); - if (firstwin != lastwin) + if (!ONE_WINDOW) do_cmdline_cmd("only!"); /* Free all spell info. */ @@ -596,18 +651,6 @@ void free_all_mem(void) /* Destroy all windows. Must come before freeing buffers. */ win_free_all(); - /* Free all buffers. Reset 'autochdir' to avoid accessing things that - * were freed already. */ - p_acd = false; - for (buf = firstbuf; buf != NULL; ) { - nextbuf = buf->b_next; - close_buffer(NULL, buf, DOBUF_WIPE, false); - if (buf_valid(buf)) - buf = nextbuf; /* didn't work, try next one */ - else - buf = firstbuf; - } - free_cmdline_buf(); /* Clear registers. */ @@ -631,6 +674,20 @@ void free_all_mem(void) eval_clear(); + // Free all buffers. Reset 'autochdir' to avoid accessing things that + // were freed already. + // Must be after eval_clear to avoid it trying to access b:changedtick after + // freeing it. + p_acd = false; + for (buf = firstbuf; buf != NULL; ) { + bufref_T bufref; + set_bufref(&bufref, buf); + nextbuf = buf->b_next; + close_buffer(NULL, buf, DOBUF_WIPE, false); + // Didn't work, try next one. + buf = bufref_valid(&bufref) ? nextbuf : firstbuf; + } + /* screenlines (can't display anything now!) */ free_screenlines(); diff --git a/src/nvim/menu.c b/src/nvim/menu.c index 7c0eee64dd..0db250d111 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -1,3 +1,6 @@ +// 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 + /* * Code for menus. Used for the GUI and 'wildmenu'. * GUI/Motif support by Robert Webb @@ -23,7 +26,7 @@ #include "nvim/state.h" #include "nvim/strings.h" #include "nvim/ui.h" - +#include "nvim/eval/typval.h" #define MENUDEPTH 10 /* maximum depth of menus */ @@ -35,8 +38,8 @@ -/* The character for each menu mode */ -static char_u menu_mode_chars[] = {'n', 'v', 's', 'o', 'i', 'c', 't'}; +/// The character for each menu mode +static char_u menu_mode_chars[] = { 'n', 'v', 's', 'o', 'i', 'c', 't' }; static char_u e_notsubmenu[] = N_( "E327: Part of menu-item path is not sub-menu"); @@ -44,20 +47,16 @@ static char_u e_othermode[] = N_("E328: Menu only exists in another mode"); static char_u e_nomenu[] = N_("E329: No menu \"%s\""); -/* - * Do the :menu command and relatives. - */ -void -ex_menu ( - exarg_T *eap /* Ex command arguments */ -) +/// Do the :menu command and relatives. +/// @param eap Ex command arguments +void +ex_menu(exarg_T *eap) { char_u *menu_path; int modes; - char_u *map_to; + char_u *map_to; // command mapped to the menu entry int noremap; bool silent = false; - bool special = false; int unmenu; char_u *map_buf; char_u *arg; @@ -83,7 +82,7 @@ ex_menu ( continue; } if (STRNCMP(arg, "<special>", 9) == 0) { - special = true; + // Ignore obsolete "<special>" modifier. arg = skipwhite(arg + 9); continue; } @@ -91,7 +90,8 @@ ex_menu ( } - /* Locate an optional "icon=filename" argument. */ + // Locate an optional "icon=filename" argument + // TODO(nvim): Currently this is only parsed. Should expose it to UIs. if (STRNCMP(arg, "icon=", 5) == 0) { arg += 5; while (*arg != NUL && *arg != ' ') { @@ -105,12 +105,12 @@ ex_menu ( } } - /* - * Fill in the priority table. - */ - for (p = arg; *p; ++p) - if (!ascii_isdigit(*p) && *p != '.') + // Fill in the priority table. + for (p = arg; *p; p++) { + if (!ascii_isdigit(*p) && *p != '.') { break; + } + } if (ascii_iswhite(*p)) { for (i = 0; i < MENUDEPTH && !ascii_iswhite(*arg); ++i) { pri_tab[i] = getdigits_long(&arg); @@ -219,13 +219,12 @@ ex_menu ( map_buf = NULL; // Menu tips are plain text. } else { map_to = replace_termcodes(map_to, STRLEN(map_to), &map_buf, false, true, - special, CPO_TO_CPO_FLAGS); + true, CPO_TO_CPO_FLAGS); } menuarg.modes = modes; menuarg.noremap[0] = noremap; menuarg.silent[0] = silent; - add_menu_path(menu_path, &menuarg, pri_tab, map_to - ); + add_menu_path(menu_path, &menuarg, pri_tab, map_to); /* * For the PopUp menu, add a menu for each mode separately. @@ -244,22 +243,24 @@ ex_menu ( xfree(map_buf); } - ui_update_menu(); + ui_call_update_menu(); theend: ; } -/* - * Add the menu with the given name to the menu hierarchy - */ -static int -add_menu_path ( - char_u *menu_path, - vimmenu_T *menuarg, /* passes modes, iconfile, iconidx, - icon_builtin, silent[0], noremap[0] */ - long *pri_tab, - char_u *call_data + +/// Add the menu with the given name to the menu hierarchy +/// +/// @param[out] menuarg menu entry +/// @param[] pri_tab priority table +/// @param[in] call_data Right hand side command +static int +add_menu_path( + const char_u *const menu_path, + vimmenu_T *menuarg, + const long *const pri_tab, + const char_u *const call_data ) { char_u *path_name; @@ -294,8 +295,9 @@ add_menu_path ( if (map_to != NULL) { en_name = name; name = map_to; - } else + } else { en_name = NULL; + } dname = menu_text(name, NULL, NULL); if (*dname == NUL) { /* Only a mnemonic or accelerator is not valid. */ @@ -309,14 +311,15 @@ add_menu_path ( while (menu != NULL) { if (menu_name_equal(name, menu) || menu_name_equal(dname, menu)) { if (*next_name == NUL && menu->children != NULL) { - if (!sys_menu) + if (!sys_menu) { EMSG(_("E330: Menu path must not lead to a sub-menu")); + } goto erret; } - if (*next_name != NUL && menu->children == NULL - ) { - if (!sys_menu) + if (*next_name != NUL && menu->children == NULL) { + if (!sys_menu) { EMSG(_(e_notsubmenu)); + } goto erret; } break; @@ -350,7 +353,7 @@ add_menu_path ( menu->modes = modes; menu->enabled = MENU_ALL_MODES; menu->name = vim_strsave(name); - /* separate mnemonic and accelerator text from actual menu name */ + // separate mnemonic and accelerator text from actual menu name menu->dname = menu_text(name, &menu->mnemonic, &menu->actext); if (en_name != NULL) { menu->en_name = vim_strsave(en_name); @@ -362,9 +365,7 @@ add_menu_path ( menu->priority = pri_tab[pri_idx]; menu->parent = parent; - /* - * Add after menu that has lower priority. - */ + // Add after menu that has lower priority. menu->next = *lower_pri; *lower_pri = menu; @@ -390,8 +391,9 @@ add_menu_path ( name = next_name; xfree(dname); dname = NULL; - if (pri_tab[pri_idx + 1] != -1) - ++pri_idx; + if (pri_tab[pri_idx + 1] != -1) { + pri_idx++; + } } xfree(path_name); @@ -417,8 +419,7 @@ add_menu_path ( // Don't do this for "<Nop>". c = 0; d = 0; - if (amenu && call_data != NULL && *call_data != NUL - ) { + if (amenu && call_data != NULL && *call_data != NUL) { switch (1 << i) { case MENU_VISUAL_MODE: case MENU_SELECT_MODE: @@ -436,9 +437,9 @@ add_menu_path ( if (c != 0) { menu->strings[i] = xmalloc(STRLEN(call_data) + 5 ); menu->strings[i][0] = c; - if (d == 0) + if (d == 0) { STRCPY(menu->strings[i] + 1, call_data); - else { + } else { menu->strings[i][1] = d; STRCPY(menu->strings[i] + 2, call_data); } @@ -450,8 +451,9 @@ add_menu_path ( menu->strings[i][len + 1] = Ctrl_G; menu->strings[i][len + 2] = NUL; } - } else + } else { menu->strings[i] = p; + } menu->noremap[i] = menuarg->noremap[0]; menu->silent[i] = menuarg->silent[0]; } @@ -655,20 +657,107 @@ static void free_menu_string(vimmenu_T *menu, int idx) menu->strings[idx] = NULL; } -/* - * Show the mapping associated with a menu item or hierarchy in a sub-menu. - */ -static int show_menus(char_u *path_name, int modes) +/// Export menus +/// +/// @param[in] menu if null, starts from root_menu +/// @param modes, a choice of \ref MENU_MODES +/// @return a dict with name/commands +/// @see menu_get +static dict_T *menu_get_recursive(const vimmenu_T *menu, int modes) +{ + dict_T *dict; + + if (!menu || (menu->modes & modes) == 0x0) { + return NULL; + } + + dict = tv_dict_alloc(); + tv_dict_add_str(dict, S_LEN("name"), (char *)menu->dname); + tv_dict_add_nr(dict, S_LEN("priority"), (int)menu->priority); + tv_dict_add_nr(dict, S_LEN("hidden"), menu_is_hidden(menu->dname)); + + if (menu->mnemonic) { + char buf[MB_MAXCHAR + 1] = { 0 }; // > max value of utf8_char2bytes + utf_char2bytes(menu->mnemonic, (char_u *)buf); + tv_dict_add_str(dict, S_LEN("shortcut"), buf); + } + + if (menu->modes & MENU_TIP_MODE && menu->strings[MENU_INDEX_TIP]) { + tv_dict_add_str(dict, S_LEN("tooltip"), + (char *)menu->strings[MENU_INDEX_TIP]); + } + + if (!menu->children) { + // leaf menu + dict_T *commands = tv_dict_alloc(); + tv_dict_add_dict(dict, S_LEN("mappings"), commands); + + for (int bit = 0; bit < MENU_MODES; bit++) { + if ((menu->modes & modes & (1 << bit)) != 0) { + dict_T *impl = tv_dict_alloc(); + if (*menu->strings[bit] == NUL) { + tv_dict_add_str(impl, S_LEN("rhs"), (char *)"<Nop>"); + } else { + tv_dict_add_str(impl, S_LEN("rhs"), (char *)menu->strings[bit]); + } + tv_dict_add_nr(impl, S_LEN("silent"), menu->silent[bit]); + tv_dict_add_nr(impl, S_LEN("enabled"), + (menu->enabled & (1 << bit)) ? 1 : 0); + tv_dict_add_nr(impl, S_LEN("noremap"), + (menu->noremap[bit] & REMAP_NONE) ? 1 : 0); + tv_dict_add_nr(impl, S_LEN("sid"), + (menu->noremap[bit] & REMAP_SCRIPT) ? 1 : 0); + tv_dict_add_dict(commands, (char *)&menu_mode_chars[bit], 1, impl); + } + } + } else { + // visit recursively all children + list_T *children_list = tv_list_alloc(); + for (menu = menu->children; menu != NULL; menu = menu->next) { + dict_T *dic = menu_get_recursive(menu, modes); + if (tv_dict_len(dict) > 0) { + tv_list_append_dict(children_list, dic); + } + } + tv_dict_add_list(dict, S_LEN("submenus"), children_list); + } + return dict; +} + + +/// Export menus matching path \p path_name +/// +/// @param path_name +/// @param modes supported modes, see \ref MENU_MODES +/// @param[in,out] list must be allocated +/// @return false if could not find path_name +bool menu_get(char_u *const path_name, int modes, list_T *list) { - char_u *p; - char_u *name; vimmenu_T *menu; - vimmenu_T *parent = NULL; + menu = find_menu(root_menu, path_name, modes); + if (!menu) { + return false; + } + for (; menu != NULL; menu = menu->next) { + dict_T *dict = menu_get_recursive(menu, modes); + if (dict && tv_dict_len(dict) > 0) { + tv_list_append_dict(list, dict); + } + } + return true; +} - menu = root_menu; - name = path_name = vim_strsave(path_name); - /* First, find the (sub)menu with the given name */ +/// Find menu matching required name and modes +/// +/// @param menu top menu to start looking from +/// @param name path towards the menu +/// @return menu if \p name is null, found menu or NULL +vimmenu_T * +find_menu(vimmenu_T *menu, char_u * name, int modes) +{ + char_u *p; + while (*name) { p = menu_name_skip(name); while (menu != NULL) { @@ -676,39 +765,46 @@ static int show_menus(char_u *path_name, int modes) /* Found menu */ if (*p != NUL && menu->children == NULL) { EMSG(_(e_notsubmenu)); - xfree(path_name); - return FAIL; + return NULL; } else if ((menu->modes & modes) == 0x0) { EMSG(_(e_othermode)); - xfree(path_name); - return FAIL; + return NULL; } break; } menu = menu->next; } + if (menu == NULL) { EMSG2(_(e_nomenu), name); - xfree(path_name); - return FAIL; + return NULL; } name = p; - parent = menu; menu = menu->children; } - xfree(path_name); + return menu; +} + +/// Show the mapping associated with a menu item or hierarchy in a sub-menu. +static int show_menus(char_u *const path_name, int modes) +{ + vimmenu_T *menu; + + // First, find the (sub)menu with the given name + menu = find_menu(root_menu, path_name, modes); + if (!menu) { + return FAIL; + } /* Now we have found the matching menu, and we list the mappings */ /* Highlight title */ MSG_PUTS_TITLE(_("\n--- Menus ---")); - show_menus_recursive(parent, modes, 0); + show_menus_recursive(menu->parent, modes, 0); return OK; } -/* - * Recursively show the mappings associated with the menus under the given one - */ +/// Recursively show the mappings associated with the menus under the given one static void show_menus_recursive(vimmenu_T *menu, int modes, int depth) { int i; @@ -755,10 +851,11 @@ static void show_menus_recursive(vimmenu_T *menu, int modes, int depth) else msg_putchar(' '); MSG_PUTS(" "); - if (*menu->strings[bit] == NUL) - msg_puts_attr((char_u *)"<Nop>", hl_attr(HLF_8)); - else - msg_outtrans_special(menu->strings[bit], FALSE); + if (*menu->strings[bit] == NUL) { + msg_puts_attr("<Nop>", hl_attr(HLF_8)); + } else { + msg_outtrans_special(menu->strings[bit], false); + } } } else { if (menu == NULL) { @@ -990,12 +1087,13 @@ char_u *get_menu_names(expand_T *xp, int idx) return str; } -/* - * Skip over this element of the menu path and return the start of the next - * element. Any \ and ^Vs are removed from the current element. - * "name" may be modified. - */ -char_u *menu_name_skip(char_u *name) + +/// Skip over this element of the menu path and return the start of the next +/// element. Any \ and ^Vs are removed from the current element. +/// +/// @param name may be modified. +/// @return start of the next element +char_u *menu_name_skip(char_u *const name) { char_u *p; @@ -1015,16 +1113,16 @@ char_u *menu_name_skip(char_u *name) * Return TRUE when "name" matches with menu "menu". The name is compared in * two ways: raw menu name and menu name without '&'. ignore part after a TAB. */ -static int menu_name_equal(char_u *name, vimmenu_T *menu) +static bool menu_name_equal(const char_u *const name, vimmenu_T *const menu) { if (menu->en_name != NULL && (menu_namecmp(name, menu->en_name) || menu_namecmp(name, menu->en_dname))) - return TRUE; + return true; return menu_namecmp(name, menu->name) || menu_namecmp(name, menu->dname); } -static int menu_namecmp(char_u *name, char_u *mname) +static bool menu_namecmp(const char_u *const name, const char_u *const mname) { int i; @@ -1035,18 +1133,20 @@ static int menu_namecmp(char_u *name, char_u *mname) && (mname[i] == NUL || mname[i] == TAB); } -/* - * Return the modes specified by the given menu command (eg :menu! returns - * MENU_CMDLINE_MODE | MENU_INSERT_MODE). - * If "noremap" is not NULL, then the flag it points to is set according to - * whether the command is a "nore" command. - * If "unmenu" is not NULL, then the flag it points to is set according to - * whether the command is an "unmenu" command. - */ -static int -get_menu_cmd_modes ( - char_u *cmd, - int forceit, /* Was there a "!" after the command? */ + +/// Returns the \ref MENU_MODES specified by menu command `cmd`. +/// (eg :menu! returns MENU_CMDLINE_MODE | MENU_INSERT_MODE) +/// +/// @param[in] cmd string like "nmenu", "vmenu", etc. +/// @param[in] forceit bang (!) was given after the command +/// @param[out] noremap If not NULL, the flag it points to is set according +/// to whether the command is a "nore" command. +/// @param[out] unmenu If not NULL, the flag it points to is set according +/// to whether the command is an "unmenu" command. +int +get_menu_cmd_modes( + const char_u * cmd, + bool forceit, int *noremap, int *unmenu ) @@ -1087,12 +1187,15 @@ get_menu_cmd_modes ( } /* FALLTHROUGH */ default: - --cmd; - if (forceit) /* menu!! */ + cmd--; + if (forceit) { + // menu!! modes = MENU_INSERT_MODE | MENU_CMDLINE_MODE; - else /* menu */ + } else { + // menu modes = MENU_NORMAL_MODE | MENU_VISUAL_MODE | MENU_SELECT_MODE | MENU_OP_PENDING_MODE; + } } if (noremap != NULL) @@ -1198,12 +1301,14 @@ int menu_is_separator(char_u *name) return name[0] == '-' && name[STRLEN(name) - 1] == '-'; } -/* - * Return TRUE if the menu is hidden: Starts with ']' - */ + +/// True if a popup menu or starts with \ref MNU_HIDDEN_CHAR +/// +/// @return true if the menu is hidden static int menu_is_hidden(char_u *name) { - return (name[0] == ']') || (menu_is_popup(name) && name[5] != NUL); + return (name[0] == MNU_HIDDEN_CHAR) + || (menu_is_popup(name) && name[5] != NUL); } /* diff --git a/src/nvim/menu.h b/src/nvim/menu.h index 3266c511b4..5ff979f2bf 100644 --- a/src/nvim/menu.h +++ b/src/nvim/menu.h @@ -1,7 +1,14 @@ #ifndef NVIM_MENU_H #define NVIM_MENU_H -/* Indices into vimmenu_T->strings[] and vimmenu_T->noremap[] for each mode */ +#include <stdbool.h> // for bool + +#include "nvim/types.h" // for char_u and expand_T +#include "nvim/ex_cmds_defs.h" // for exarg_T + +/// Indices into vimmenu_T->strings[] and vimmenu_T->noremap[] for each mode +/// \addtogroup MENU_INDEX +/// @{ #define MENU_INDEX_INVALID -1 #define MENU_INDEX_NORMAL 0 #define MENU_INDEX_VISUAL 1 @@ -11,8 +18,12 @@ #define MENU_INDEX_CMDLINE 5 #define MENU_INDEX_TIP 6 #define MENU_MODES 7 +/// @} +/// note MENU_INDEX_TIP is not a 'real' mode -/* Menu modes */ +/// Menu modes +/// \addtogroup MENU_MODES +/// @{ #define MENU_NORMAL_MODE (1 << MENU_INDEX_NORMAL) #define MENU_VISUAL_MODE (1 << MENU_INDEX_VISUAL) #define MENU_SELECT_MODE (1 << MENU_INDEX_SELECT) @@ -21,31 +32,30 @@ #define MENU_CMDLINE_MODE (1 << MENU_INDEX_CMDLINE) #define MENU_TIP_MODE (1 << MENU_INDEX_TIP) #define MENU_ALL_MODES ((1 << MENU_INDEX_TIP) - 1) -/*note MENU_INDEX_TIP is not a 'real' mode*/ +/// @} -/* Start a menu name with this to not include it on the main menu bar */ +/// Start a menu name with this to not include it on the main menu bar #define MNU_HIDDEN_CHAR ']' typedef struct VimMenu vimmenu_T; struct VimMenu { - int modes; /* Which modes is this menu visible for? */ - int enabled; /* for which modes the menu is enabled */ - char_u *name; /* Name of menu, possibly translated */ - char_u *dname; /* Displayed Name ("name" without '&') */ - char_u *en_name; /* "name" untranslated, NULL when "name" - * was not translated */ - char_u *en_dname; /* "dname" untranslated, NULL when "dname" - * was not translated */ - int mnemonic; /* mnemonic key (after '&') */ - char_u *actext; /* accelerator text (after TAB) */ - long priority; /* Menu order priority */ - char_u *strings[MENU_MODES]; /* Mapped string for each mode */ - int noremap[MENU_MODES]; /* A REMAP_ flag for each mode */ - bool silent[MENU_MODES]; /* A silent flag for each mode */ - vimmenu_T *children; /* Children of sub-menu */ - vimmenu_T *parent; /* Parent of menu */ - vimmenu_T *next; /* Next item in menu */ + int modes; ///< Which modes is this menu visible for + int enabled; ///< for which modes the menu is enabled + char_u *name; ///< Name of menu, possibly translated + char_u *dname; ///< Displayed Name ("name" without '&') + char_u *en_name; ///< "name" untranslated, NULL when + ///< was not translated + char_u *en_dname; ///< NULL when "dname" untranslated + int mnemonic; ///< mnemonic key (after '&') + char_u *actext; ///< accelerator text (after TAB) + long priority; ///< Menu order priority + char_u *strings[MENU_MODES]; ///< Mapped string for each mode + int noremap[MENU_MODES]; ///< A \ref REMAP_VALUES flag for each mode + bool silent[MENU_MODES]; ///< A silent flag for each mode + vimmenu_T *children; ///< Children of sub-menu + vimmenu_T *parent; ///< Parent of menu + vimmenu_T *next; ///< Next item in menu }; diff --git a/src/nvim/message.c b/src/nvim/message.c index 2f8feda6ec..b90c475ede 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1,3 +1,6 @@ +// 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 + /* * message.c: functions for displaying messages on the command line */ @@ -7,10 +10,10 @@ #include <stdbool.h> #include <stdarg.h> #include <string.h> -#include <math.h> #include "nvim/vim.h" #include "nvim/ascii.h" +#include "nvim/assert.h" #include "nvim/message.h" #include "nvim/charset.h" #include "nvim/eval.h" @@ -28,6 +31,7 @@ #include "nvim/ops.h" #include "nvim/option.h" #include "nvim/normal.h" +#include "nvim/regexp.h" #include "nvim/screen.h" #include "nvim/strings.h" #include "nvim/ui.h" @@ -128,9 +132,9 @@ int verb_msg(char_u *s) return n; } -int msg_attr(char_u *s, int attr) FUNC_ATTR_NONNULL_ARG(1) +int msg_attr(const char *s, const int attr) FUNC_ATTR_NONNULL_ARG(1) { - return msg_attr_keep(s, attr, FALSE); + return msg_attr_keep((char_u *)s, attr, false); } int @@ -145,6 +149,12 @@ msg_attr_keep ( int retval; char_u *buf = NULL; + // Skip messages not match ":filter pattern". + // Don't filter when there is an error. + if (!emsg_on_display && message_filtered(s)) { + return true; + } + if (attr == 0) { set_vim_var_string(VV_STATUSMSG, (char *) s, -1); } @@ -164,8 +174,9 @@ msg_attr_keep ( || (*s != '<' && last_msg_hist != NULL && last_msg_hist->msg != NULL - && STRCMP(s, last_msg_hist->msg))) - add_msg_hist(s, -1, attr); + && STRCMP(s, last_msg_hist->msg))) { + add_msg_hist((const char *)s, -1, attr); + } /* When displaying keep_msg, don't let msg_start() free it, caller must do * that. */ @@ -236,17 +247,19 @@ msg_strtrunc ( * Truncate a string "s" to "buf" with cell width "room". * "s" and "buf" may be equal. */ -void trunc_string(char_u *s, char_u *buf, int room, int buflen) +void trunc_string(char_u *s, char_u *buf, int room_in, int buflen) { - int half; - int len; + size_t room = room_in - 3; // "..." takes 3 chars + size_t half; + size_t len = 0; int e; int i; int n; - room -= 3; + if (room_in < 3) { + room = 0; + } half = room / 2; - len = 0; /* First part: Start of the string. */ for (e = 0; len < half && e < buflen; ++e) { @@ -256,8 +269,9 @@ void trunc_string(char_u *s, char_u *buf, int room, int buflen) return; } n = ptr2cells(s + e); - if (len + n >= half) + if (len + n > half) { break; + } len += n; buf[e] = s[e]; if (has_mbyte) @@ -268,45 +282,46 @@ void trunc_string(char_u *s, char_u *buf, int room, int buflen) } } - /* Last part: End of the string. */ - i = e; - if (enc_dbcs != 0) { - /* For DBCS going backwards in a string is slow, but - * computing the cell width isn't too slow: go forward - * until the rest fits. */ - n = vim_strsize(s + i); - while (len + n > room) { - n -= ptr2cells(s + i); - i += (*mb_ptr2len)(s + i); - } - } else if (enc_utf8) { - /* For UTF-8 we can go backwards easily. */ - half = i = (int)STRLEN(s); - for (;; ) { - do - half = half - (*mb_head_off)(s, s + half - 1) - 1; - while (utf_iscomposing(utf_ptr2char(s + half)) && half > 0); - n = ptr2cells(s + half); - if (len + n > room) - break; - len += n; - i = half; + // Last part: End of the string. + half = i = (int)STRLEN(s); + for (;;) { + do { + half = half - (*mb_head_off)(s, s + half - 1) - 1; + } while (half > 0 && utf_iscomposing(utf_ptr2char(s + half))); + n = ptr2cells(s + half); + if (len + n > room || half == 0) { + break; } - } else { - for (i = (int)STRLEN(s); len + (n = ptr2cells(s + i - 1)) <= room; --i) - len += n; + len += n; + i = half; } - /* Set the middle and copy the last part. */ - if (e + 3 < buflen) { + if (i <= e + 3) { + // text fits without truncating + if (s != buf) { + len = STRLEN(s); + if (len >= (size_t)buflen) { + len = buflen - 1; + } + len = len - e + 1; + if (len < 1) { + buf[e - 1] = NUL; + } else { + memmove(buf + e, s + e, len); + } + } + } else if (e + 3 < buflen) { + // set the middle and copy the last part memmove(buf + e, "...", (size_t)3); - len = (int)STRLEN(s + i) + 1; - if (len >= buflen - e - 3) + len = STRLEN(s + i) + 1; + if (len >= (size_t)buflen - e - 3) { len = buflen - e - 3 - 1; + } memmove(buf + e + 3, s + i, len); buf[e + 3 + len - 1] = NUL; } else { - buf[e - 1] = NUL; /* make sure it is truncated */ + // can't fit in the "...", just truncate it + buf[e - 1] = NUL; } } @@ -332,7 +347,7 @@ int smsg_attr(int attr, char *s, ...) va_start(arglist, s); vim_vsnprintf((char *)IObuff, IOSIZE, s, arglist, NULL); va_end(arglist); - return msg_attr(IObuff, attr); + return msg_attr((const char *)IObuff, attr); } /* @@ -366,42 +381,40 @@ static int other_sourcing_name(void) return FALSE; } -/* - * Get the message about the source, as used for an error message. - * Returns an allocated string with room for one more character. - * Returns NULL when no message is to be given. - */ -static char_u *get_emsg_source(void) +/// Get the message about the source, as used for an error message +/// +/// @return [allocated] String with room for one more character. NULL when no +/// message is to be given. +static char *get_emsg_source(void) + FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT { - char_u *Buf, *p; - if (sourcing_name != NULL && other_sourcing_name()) { - p = (char_u *)_("Error detected while processing %s:"); - Buf = xmalloc(STRLEN(sourcing_name) + STRLEN(p)); - sprintf((char *)Buf, (char *)p, sourcing_name); - return Buf; + const char *const p = _("Error detected while processing %s:"); + const size_t buf_len = STRLEN(sourcing_name) + strlen(p) + 1; + char *const buf = xmalloc(buf_len); + snprintf(buf, buf_len, p, sourcing_name); + return buf; } return NULL; } -/* - * Get the message about the source lnum, as used for an error message. - * Returns an allocated string with room for one more character. - * Returns NULL when no message is to be given. - */ -static char_u *get_emsg_lnum(void) +/// Get the message about the source lnum, as used for an error message. +/// +/// @return [allocated] String with room for one more character. NULL when no +/// message is to be given. +static char *get_emsg_lnum(void) + FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT { - char_u *Buf, *p; - - /* lnum is 0 when executing a command from the command line - * argument, we don't want a line number then */ + // lnum is 0 when executing a command from the command line + // argument, we don't want a line number then if (sourcing_name != NULL && (other_sourcing_name() || sourcing_lnum != last_sourcing_lnum) && sourcing_lnum != 0) { - p = (char_u *)_("line %4ld:"); - Buf = xmalloc(STRLEN(p) + 20); - sprintf((char *)Buf, (char *)p, (long)sourcing_lnum); - return Buf; + const char *const p = _("line %4ld:"); + const size_t buf_len = 20 + strlen(p); + char *const buf = xmalloc(buf_len); + snprintf(buf, buf_len, p, (long)sourcing_lnum); + return buf; } return NULL; } @@ -413,10 +426,8 @@ static char_u *get_emsg_lnum(void) */ void msg_source(int attr) { - char_u *p; - - ++no_wait_return; - p = get_emsg_source(); + no_wait_return++; + char *p = get_emsg_source(); if (p != NULL) { msg_attr(p, attr); xfree(p); @@ -463,10 +474,10 @@ int emsg_not_now(void) * * return TRUE if wait_return not called */ -int emsg(char_u *s) +int emsg(const char_u *s_) { + const char *s = (const char *)s_; int attr; - char_u *p; int ignore = false; int severe; @@ -493,7 +504,7 @@ int emsg(char_u *s) * when the message should be ignored completely (used for the * interrupt message). */ - if (cause_errthrow(s, severe, &ignore) == true) { + if (cause_errthrow((char_u *)s, severe, &ignore) == true) { if (!ignore) { did_emsg = true; } @@ -501,7 +512,7 @@ int emsg(char_u *s) } // set "v:errmsg", also when using ":silent! cmd" - set_vim_var_string(VV_ERRMSG, (char *) s, -1); + set_vim_var_string(VV_ERRMSG, s, -1); /* * When using ":silent! cmd" ignore error messages. @@ -510,19 +521,21 @@ int emsg(char_u *s) if (emsg_silent != 0) { if (!emsg_noredir) { msg_start(); - p = get_emsg_source(); + char *p = get_emsg_source(); if (p != NULL) { - STRCAT(p, "\n"); - redir_write(p, STRLEN(p)); + const size_t p_len = strlen(p); + p[p_len] = '\n'; + redir_write(p, p_len + 1); xfree(p); } p = get_emsg_lnum(); if (p != NULL) { - STRCAT(p, "\n"); - redir_write(p, STRLEN(p)); + const size_t p_len = strlen(p); + p[p_len] = '\n'; + redir_write(p, p_len + 1); xfree(p); } - redir_write(s, STRLEN(s)); + redir_write(s, strlen(s)); } return true; } @@ -557,10 +570,8 @@ int emsg(char_u *s) */ msg_source(attr); - /* - * Display the error message itself. - */ - msg_nowait = FALSE; /* wait for this msg */ + // Display the error message itself. + msg_nowait = false; // Wait for this msg. return msg_attr(s, attr); } @@ -572,16 +583,17 @@ void emsg_invreg(int name) /// Print an error message with unknown number of arguments bool emsgf(const char *const fmt, ...) { + static char errbuf[IOSIZE]; if (emsg_not_now()) { return true; } va_list ap; va_start(ap, fmt); - vim_vsnprintf((char *) IObuff, IOSIZE, fmt, ap, NULL); + vim_vsnprintf(errbuf, sizeof(errbuf), fmt, ap, NULL); va_end(ap); - return emsg(IObuff); + return emsg((const char_u *)errbuf); } static void msg_emsgf_event(void **argv) @@ -599,7 +611,7 @@ void msg_schedule_emsgf(const char *const fmt, ...) va_end(ap); char *s = xstrdup((char *)IObuff); - loop_schedule(&main_loop, event_create(1, msg_emsgf_event, 1, s)); + loop_schedule(&main_loop, event_create(msg_emsgf_event, 1, s)); } /* @@ -612,14 +624,14 @@ char_u *msg_trunc_attr(char_u *s, int force, int attr) { int n; - /* Add message to history before truncating */ - add_msg_hist(s, -1, attr); + // Add message to history before truncating. + add_msg_hist((const char *)s, -1, attr); s = msg_may_trunc(force, s); - msg_hist_off = TRUE; - n = msg_attr(s, attr); - msg_hist_off = FALSE; + msg_hist_off = true; + n = msg_attr((const char *)s, attr); + msg_hist_off = false; if (n) return s; @@ -658,12 +670,8 @@ char_u *msg_may_trunc(int force, char_u *s) return s; } -static void -add_msg_hist ( - char_u *s, - int len, /* -1 for undetermined length */ - int attr -) +/// @param[in] len Length of s or -1. +static void add_msg_hist(const char *s, int len, int attr) { if (msg_hist_off || msg_silent != 0) return; @@ -681,9 +689,10 @@ add_msg_hist ( ++s; --len; } - while (len > 0 && s[len - 1] == '\n') - --len; - p->msg = vim_strnsave(s, len); + while (len > 0 && s[len - 1] == '\n') { + len--; + } + p->msg = (char_u *)xmemdupz(s, (size_t)len); p->next = NULL; p->attr = attr; if (last_msg_hist != NULL) @@ -716,11 +725,11 @@ int delete_first_msg(void) return OK; } -/* - * ":messages" command. - */ -void ex_messages(exarg_T *eap) +/// :messages command implementation +void ex_messages(void *const eap_p) + FUNC_ATTR_NONNULL_ALL { + const exarg_T *const eap = (const exarg_T *)eap_p; struct msg_hist *p; int c = 0; @@ -758,7 +767,7 @@ void ex_messages(exarg_T *eap) // Display what was not skipped. for (; p != NULL && !got_int; p = p->next) { if (p->msg != NULL) { - msg_attr(p->msg, p->attr); + msg_attr((const char *)p->msg, p->attr); } } @@ -849,23 +858,22 @@ void wait_return(int redraw) * CTRL-C, but we need to loop then. */ had_got_int = got_int; - /* Don't do mappings here, we put the character back in the - * typeahead buffer. */ - ++no_mapping; - ++allow_keys; + // Don't do mappings here, we put the character back in the + // typeahead buffer. + no_mapping++; - /* Temporarily disable Recording. If Recording is active, the - * character will be recorded later, since it will be added to the - * typebuf after the loop */ + // Temporarily disable Recording. If Recording is active, the + // character will be recorded later, since it will be added to the + // typebuf after the loop save_Recording = Recording; save_scriptout = scriptout; Recording = FALSE; scriptout = NULL; c = safe_vgetc(); - if (had_got_int && !global_busy) - got_int = FALSE; - --no_mapping; - --allow_keys; + if (had_got_int && !global_busy) { + got_int = false; + } + no_mapping--; Recording = save_Recording; scriptout = save_scriptout; @@ -1042,9 +1050,10 @@ void msg_start(void) msg_didout = FALSE; /* no output on current line yet */ } - /* when redirecting, may need to start a new line. */ - if (!did_return) - redir_write((char_u *)"\n", -1); + // When redirecting, may need to start a new line. + if (!did_return) { + redir_write("\n", 1); + } } /* @@ -1063,24 +1072,24 @@ void msg_putchar(int c) void msg_putchar_attr(int c, int attr) { - char_u buf[MB_MAXBYTES + 1]; + char buf[MB_MAXBYTES + 1]; if (IS_SPECIAL(c)) { - buf[0] = K_SPECIAL; - buf[1] = K_SECOND(c); - buf[2] = K_THIRD(c); + buf[0] = (char)K_SPECIAL; + buf[1] = (char)K_SECOND(c); + buf[2] = (char)K_THIRD(c); buf[3] = NUL; } else { - buf[(*mb_char2bytes)(c, buf)] = NUL; + buf[(*mb_char2bytes)(c, (char_u *)buf)] = NUL; } msg_puts_attr(buf, attr); } void msg_outnum(long n) { - char_u buf[20]; + char buf[20]; - sprintf((char *)buf, "%" PRId64, (int64_t)n); + snprintf(buf, sizeof(buf), "%ld", n); msg_puts(buf); } @@ -1136,16 +1145,16 @@ char_u *msg_outtrans_one(char_u *p, int attr) msg_outtrans_len_attr(p, l, attr); return p + l; } - msg_puts_attr(transchar_byte(*p), attr); + msg_puts_attr((const char *)transchar_byte(*p), attr); return p + 1; } int msg_outtrans_len_attr(char_u *msgstr, int len, int attr) { int retval = 0; - char_u *str = msgstr; - char_u *plain_start = msgstr; - char_u *s; + const char *str = (const char *)msgstr; + const char *plain_start = (const char *)msgstr; + char_u *s; int mb_l; int c; @@ -1155,60 +1164,59 @@ int msg_outtrans_len_attr(char_u *msgstr, int len, int attr) attr &= ~MSG_HIST; } - /* If the string starts with a composing character first draw a space on - * which the composing char can be drawn. */ - if (enc_utf8 && utf_iscomposing(utf_ptr2char(msgstr))) - msg_puts_attr((char_u *)" ", attr); + // If the string starts with a composing character first draw a space on + // which the composing char can be drawn. + if (enc_utf8 && utf_iscomposing(utf_ptr2char(msgstr))) { + msg_puts_attr(" ", attr); + } /* * Go over the string. Special characters are translated and printed. * Normal characters are printed several at a time. */ while (--len >= 0) { - if (enc_utf8) - /* Don't include composing chars after the end. */ - mb_l = utfc_ptr2len_len(str, len + 1); - else if (has_mbyte) - mb_l = (*mb_ptr2len)(str); - else - mb_l = 1; - if (has_mbyte && mb_l > 1) { - c = (*mb_ptr2char)(str); - if (vim_isprintc(c)) - /* printable multi-byte char: count the cells. */ - retval += (*mb_ptr2cells)(str); - else { - /* unprintable multi-byte char: print the printable chars so - * far and the translation of the unprintable char. */ - if (str > plain_start) - msg_puts_attr_len(plain_start, (int)(str - plain_start), - attr); + // Don't include composing chars after the end. + mb_l = utfc_ptr2len_len((char_u *)str, len + 1); + if (mb_l > 1) { + c = (*mb_ptr2char)((char_u *)str); + if (vim_isprintc(c)) { + // Printable multi-byte char: count the cells. + retval += (*mb_ptr2cells)((char_u *)str); + } else { + // Unprintable multi-byte char: print the printable chars so + // far and the translation of the unprintable char. + if (str > plain_start) { + msg_puts_attr_len(plain_start, str - plain_start, attr); + } plain_start = str + mb_l; - msg_puts_attr(transchar(c), attr == 0 ? hl_attr(HLF_8) : attr); + msg_puts_attr((const char *)transchar(c), + (attr == 0 ? hl_attr(HLF_8) : attr)); retval += char2cells(c); } len -= mb_l - 1; str += mb_l; } else { - s = transchar_byte(*str); + s = transchar_byte((uint8_t)(*str)); if (s[1] != NUL) { - /* unprintable char: print the printable chars so far and the - * translation of the unprintable char. */ - if (str > plain_start) - msg_puts_attr_len(plain_start, (int)(str - plain_start), - attr); + // Unprintable char: print the printable chars so far and the + // translation of the unprintable char. + if (str > plain_start) { + msg_puts_attr_len(plain_start, str - plain_start, attr); + } plain_start = str + 1; - msg_puts_attr(s, attr == 0 ? hl_attr(HLF_8) : attr); + msg_puts_attr((const char *)s, attr == 0 ? hl_attr(HLF_8) : attr); retval += (int)STRLEN(s); - } else - ++retval; - ++str; + } else { + retval++; + } + str++; } } - if (str > plain_start) - /* print the printable chars at the end */ - msg_puts_attr_len(plain_start, (int)(str - plain_start), attr); + if (str > plain_start) { + // Print the printable chars at the end. + msg_puts_attr_len(plain_start, str - plain_start, attr); + } return retval; } @@ -1251,130 +1259,147 @@ msg_outtrans_special ( { char_u *str = strstart; int retval = 0; - char_u *string; int attr; - int len; attr = hl_attr(HLF_8); while (*str != NUL) { - /* Leading and trailing spaces need to be displayed in <> form. */ + const char *string; + // Leading and trailing spaces need to be displayed in <> form. if ((str == strstart || str[1] == NUL) && *str == ' ') { - string = (char_u *)"<Space>"; - ++str; - } else - string = str2special(&str, from); - len = vim_strsize(string); - /* Highlight special keys */ - msg_puts_attr(string, len > 1 - && (*mb_ptr2len)(string) <= 1 - ? attr : 0); + string = "<Space>"; + str++; + } else { + string = str2special((const char **)&str, from, false); + } + const int len = vim_strsize((char_u *)string); + // Highlight special keys + msg_puts_attr(string, (len > 1 + && (*mb_ptr2len)((char_u *)string) <= 1 + ? attr : 0)); retval += len; } return retval; } -/* - * Return the lhs or rhs of a mapping, with the key codes turned into printable - * strings, in an allocated string. - */ -char_u * -str2special_save ( - char_u *str, - int is_lhs /* TRUE for lhs, FALSE for rhs */ -) +/// Convert string, replacing key codes with printables +/// +/// Used for lhs or rhs of mappings. +/// +/// @param[in] str String to convert. +/// @param[in] replace_spaces Convert spaces into `<Space>`, normally used fo +/// lhs, but not rhs. +/// @param[in] replace_lt Convert `<` into `<lt>`. +/// +/// @return [allocated] Converted string. +char *str2special_save(const char *const str, const bool replace_spaces, + const bool replace_lt) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC + FUNC_ATTR_NONNULL_RET { garray_T ga; - char_u *p = str; - ga_init(&ga, 1, 40); - while (*p != NUL) - ga_concat(&ga, str2special(&p, is_lhs)); + + const char *p = str; + while (*p != NUL) { + ga_concat(&ga, (const char_u *)str2special(&p, replace_spaces, replace_lt)); + } ga_append(&ga, NUL); - return (char_u *)ga.ga_data; + return (char *)ga.ga_data; } -/* - * Return the printable string for the key codes at "*sp". - * Used for translating the lhs or rhs of a mapping to printable chars. - * Advances "sp" to the next code. - */ -char_u * -str2special ( - char_u **sp, - int from /* TRUE for lhs of mapping */ -) -{ - int c; - static char_u buf[7]; - char_u *str = *sp; - int modifiers = 0; - int special = FALSE; - - if (has_mbyte) { - char_u *p; - - /* Try to un-escape a multi-byte character. Return the un-escaped - * string if it is a multi-byte character. */ - p = mb_unescape(sp); - if (p != NULL) - return p; +/// Convert character, replacing key one key code with printable representation +/// +/// @param[in,out] sp String to convert. Is advanced to the next key code. +/// @param[in] replace_spaces Convert spaces into <Space>, normally used for +/// lhs, but not rhs. +/// @param[in] replace_lt Convert `<` into `<lt>`. +/// +/// @return Converted key code, in a static buffer. Buffer is always one and the +/// same, so save converted string somewhere before running str2special +/// for the second time. +const char *str2special(const char **const sp, const bool replace_spaces, + const bool replace_lt) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET +{ + static char buf[7]; + + // Try to un-escape a multi-byte character. Return the un-escaped + // string if it is a multi-byte character. + const char *const p = mb_unescape(sp); + if (p != NULL) { + return p; } - c = *str; + const char *str = *sp; + int c = (uint8_t)(*str); + int modifiers = 0; + bool special = false; if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) { - if (str[1] == KS_MODIFIER) { - modifiers = str[2]; + if ((uint8_t)str[1] == KS_MODIFIER) { + modifiers = (uint8_t)str[2]; str += 3; - c = *str; + c = (uint8_t)(*str); } if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) { - c = TO_SPECIAL(str[1], str[2]); + c = TO_SPECIAL((uint8_t)str[1], (uint8_t)str[2]); str += 2; - if (c == KS_ZERO) /* display <Nul> as ^@ or <Nul> */ + if (c == KS_ZERO) { // display <Nul> as ^@ or <Nul> c = NUL; + } + } + if (IS_SPECIAL(c) || modifiers) { // Special key. + special = true; } - if (IS_SPECIAL(c) || modifiers) /* special key */ - special = TRUE; } - if (has_mbyte && !IS_SPECIAL(c)) { - int len = (*mb_ptr2len)(str); + if (!IS_SPECIAL(c)) { + const int len = utf_ptr2len((const char_u *)str); - /* For multi-byte characters check for an illegal byte. */ - if (has_mbyte && MB_BYTE2LEN(*str) > len) { - transchar_nonprint(buf, c); + // Check for an illegal byte. + if (MB_BYTE2LEN((uint8_t)(*str)) > len) { + transchar_nonprint((char_u *)buf, c); *sp = str + 1; return buf; } - /* Since 'special' is TRUE the multi-byte character 'c' will be - * processed by get_special_key_name() */ - c = (*mb_ptr2char)(str); + // Since 'special' is TRUE the multi-byte character 'c' will be + // processed by get_special_key_name(). + c = utf_ptr2char((const char_u *)str); *sp = str + len; - } else + } else { *sp = str + 1; + } - /* Make unprintable characters in <> form, also <M-Space> and <Tab>. - * Use <Space> only for lhs of a mapping. */ - if (special || char2cells(c) > 1 || (from && c == ' ')) - return get_special_key_name(c, modifiers); + // Make unprintable characters in <> form, also <M-Space> and <Tab>. + if (special + || char2cells(c) > 1 + || (replace_spaces && c == ' ') + || (replace_lt && c == '<')) { + return (const char *)get_special_key_name(c, modifiers); + } buf[0] = c; buf[1] = NUL; return buf; } -/* - * Translate a key sequence into special key names. - */ -void str2specialbuf(char_u *sp, char_u *buf, int len) +/// Convert string, replacing key codes with printables +/// +/// @param[in] str String to convert. +/// @param[out] buf Buffer to save results to. +/// @param[in] len Buffer length. +void str2specialbuf(const char *sp, char *buf, size_t len) + FUNC_ATTR_NONNULL_ALL { - char_u *s; - - *buf = NUL; while (*sp) { - s = str2special(&sp, FALSE); - if ((int)(STRLEN(s) + STRLEN(buf)) < len) - STRCAT(buf, s); + const char *s = str2special(&sp, false, false); + const size_t s_len = strlen(s); + if (s_len <= len) { + break; + } + memcpy(buf, s, s_len); + buf += s_len; + len -= s_len; } + *buf = NUL; } /* @@ -1391,7 +1416,6 @@ void msg_prt_line(char_u *s, int list) int attr = 0; char_u *trail = NULL; int l; - char_u buf[MB_MAXBYTES + 1]; if (curwin->w_p_list) list = TRUE; @@ -1417,10 +1441,11 @@ void msg_prt_line(char_u *s, int list) c = *p_extra++; } else if (has_mbyte && (l = (*mb_ptr2len)(s)) > 1) { col += (*mb_ptr2cells)(s); + char buf[MB_MAXBYTES + 1]; if (lcs_nbsp != NUL && list && (mb_ptr2char(s) == 160 || mb_ptr2char(s) == 0x202f)) { - mb_char2bytes(lcs_nbsp, buf); - buf[(*mb_ptr2len)(buf)] = NUL; + mb_char2bytes(lcs_nbsp, (char_u *)buf); + buf[(*mb_ptr2len)((char_u *)buf)] = NUL; } else { memmove(buf, s, (size_t)l); buf[l] = NUL; @@ -1517,12 +1542,12 @@ static char_u *screen_puts_mbyte(char_u *s, int l, int attr) * Output a string to the screen at position msg_row, msg_col. * Update msg_row and msg_col for the next message. */ -void msg_puts(char_u *s) +void msg_puts(const char *s) { msg_puts_attr(s, 0); } -void msg_puts_title(char_u *s) +void msg_puts_title(const char *s) { msg_puts_attr(s, hl_attr(HLF_T)); } @@ -1546,7 +1571,7 @@ void msg_puts_long_len_attr(char_u *longstr, int len, int attr) if (len > room && room >= 20) { slen = (room - 3) / 2; msg_outtrans_len_attr(longstr, slen, attr); - msg_puts_attr((char_u *)"...", hl_attr(HLF_8)); + msg_puts_attr("...", hl_attr(HLF_8)); } msg_outtrans_len_attr(longstr + len - slen, slen, attr); } @@ -1554,18 +1579,22 @@ void msg_puts_long_len_attr(char_u *longstr, int len, int attr) /* * Basic function for writing a message with highlight attributes. */ -void msg_puts_attr(char_u *s, int attr) +void msg_puts_attr(const char *const s, const int attr) { msg_puts_attr_len(s, -1, attr); } -/// Like msg_puts_attr(), but with a maximum length "maxlen" (in bytes). -/// When "maxlen" is -1 there is no maximum length. -/// When "maxlen" is >= 0 the message is not put in the history. -static void msg_puts_attr_len(char_u *str, int maxlen, int attr) +/// Write a message with highlight attributes +/// +/// @param[in] str NUL-terminated message string. +/// @param[in] len Length of the string or -1. +/// @param[in] attr Highlight attribute. +void msg_puts_attr_len(const char *const str, const ptrdiff_t len, int attr) + FUNC_ATTR_NONNULL_ALL { + assert(len < 0 || memchr(str, 0, len) == NULL); // If redirection is on, also write to the redirection file. - redir_write(str, maxlen); + redir_write(str, len); // Don't print anything when using ":silent cmd". if (msg_silent != 0) { @@ -1573,8 +1602,8 @@ static void msg_puts_attr_len(char_u *str, int maxlen, int attr) } // if MSG_HIST flag set, add message to history - if ((attr & MSG_HIST) && maxlen < 0) { - add_msg_hist(str, -1, attr); + if (attr & MSG_HIST) { + add_msg_hist(str, (int)len, attr); attr &= ~MSG_HIST; } @@ -1593,24 +1622,46 @@ static void msg_puts_attr_len(char_u *str, int maxlen, int attr) // different, e.g. for Win32 console) or we just don't know where the // cursor is. if (msg_use_printf()) { - msg_puts_printf((char *)str, maxlen); + msg_puts_printf(str, len); } else { - msg_puts_display(str, maxlen, attr, false); + msg_puts_display((const char_u *)str, len, attr, false); } } +/// Print a formatted message +/// +/// Message printed is limited by #IOSIZE. Must not be used from inside +/// msg_puts_attr(). +/// +/// @param[in] attr Highlight attributes. +/// @param[in] fmt Format string. +void msg_printf_attr(const int attr, const char *const fmt, ...) + FUNC_ATTR_NONNULL_ARG(2) +{ + static char msgbuf[IOSIZE]; + + va_list ap; + va_start(ap, fmt); + const size_t len = vim_vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap, NULL); + va_end(ap); + + msg_scroll = true; + msg_puts_attr_len(msgbuf, (ptrdiff_t)len, attr); +} + /* * The display part of msg_puts_attr_len(). * May be called recursively to display scroll-back text. */ -static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse) +static void msg_puts_display(const char_u *str, int maxlen, int attr, + int recurse) { - char_u *s = str; - char_u *t_s = str; /* string from "t_s" to "s" is still todo */ - int t_col = 0; /* screen cells todo, 0 when "t_s" not used */ + const char_u *s = str; + const char_u *t_s = str; // String from "t_s" to "s" is still todo. + int t_col = 0; // Screen cells todo, 0 when "t_s" not used. int l; int cw; - char_u *sb_str = str; + const char_u *sb_str = str; int sb_col = msg_col; int wrap; int did_last_char; @@ -1652,26 +1703,24 @@ static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse) if (msg_col >= Columns) /* can happen after screen resize */ msg_col = Columns - 1; - /* Display char in last column before showing more-prompt. */ - if (*s >= ' ' - && !cmdmsg_rl - ) { - if (has_mbyte) { - if (enc_utf8 && maxlen >= 0) - /* avoid including composing chars after the end */ - l = utfc_ptr2len_len(s, (int)((str + maxlen) - s)); - else - l = (*mb_ptr2len)(s); - s = screen_puts_mbyte(s, l, attr); - } else - msg_screen_putchar(*s++, attr); - did_last_char = TRUE; - } else - did_last_char = FALSE; - - if (p_more) - /* store text for scrolling back */ - store_sb_text(&sb_str, s, attr, &sb_col, TRUE); + // Display char in last column before showing more-prompt. + if (*s >= ' ' && !cmdmsg_rl) { + if (maxlen >= 0) { + // Avoid including composing chars after the end. + l = utfc_ptr2len_len(s, (int)((str + maxlen) - s)); + } else { + l = utfc_ptr2len(s); + } + s = screen_puts_mbyte((char_u *)s, l, attr); + did_last_char = true; + } else { + did_last_char = false; + } + + if (p_more) { + // Store text for scrolling back. + store_sb_text((char_u **)&sb_str, (char_u *)s, attr, &sb_col, true); + } inc_msg_scrolled(); need_wait_return = TRUE; /* may need wait_return in main() */ @@ -1707,13 +1756,15 @@ static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse) && msg_col + t_col >= Columns - 1) ; if (t_col > 0 && (wrap || *s == '\r' || *s == '\b' - || *s == '\t' || *s == BELL)) - /* output any postponed text */ + || *s == '\t' || *s == BELL)) { + // Output any postponed text. t_puts(&t_col, t_s, s, attr); + } - if (wrap && p_more && !recurse) - /* store text for scrolling back */ - store_sb_text(&sb_str, s, attr, &sb_col, TRUE); + if (wrap && p_more && !recurse) { + // Store text for scrolling back. + store_sb_text((char_u **)&sb_str, (char_u *)s, attr, &sb_col, true); + } if (*s == '\n') { /* go to next line */ msg_didout = FALSE; /* remember that line is empty */ @@ -1751,7 +1802,7 @@ static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse) // characters and draw them all at once later. if (cmdmsg_rl || (cw > 1 && msg_col + t_col >= Columns - 1)) { if (l > 1) { - s = screen_puts_mbyte(s, l, attr) - 1; + s = screen_puts_mbyte((char_u *)s, l, attr) - 1; } else { msg_screen_putchar(*s, attr); } @@ -1766,15 +1817,29 @@ static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse) ++s; } - /* output any postponed text */ - if (t_col > 0) + // Output any postponed text. + if (t_col > 0) { t_puts(&t_col, t_s, s, attr); - if (p_more && !recurse) - store_sb_text(&sb_str, s, attr, &sb_col, FALSE); + } + if (p_more && !recurse) { + store_sb_text((char_u **)&sb_str, (char_u *)s, attr, &sb_col, false); + } msg_check(); } +/// Return true when ":filter pattern" was used and "msg" does not match +/// "pattern". +bool message_filtered(char_u *msg) +{ + if (cmdmod.filter_regmatch.regprog == NULL) { + return false; + } + + bool match = vim_regexec(&cmdmod.filter_regmatch, msg, (colnr_T)0); + return cmdmod.filter_force ? match : !match; +} + /* * Scroll the screen up one line for displaying the next message line. */ @@ -1946,11 +2011,11 @@ static msgchunk_T *disp_sb_line(int row, msgchunk_T *smp) /* * Output any postponed text for msg_puts_attr_len(). */ -static void t_puts(int *t_col, char_u *t_s, char_u *s, int attr) +static void t_puts(int *t_col, const char_u *t_s, const char_u *s, int attr) { - /* output postponed text */ - msg_didout = TRUE; /* remember that line is not empty */ - screen_puts_len(t_s, (int)(s - t_s), msg_row, msg_col, attr); + // Output postponed text. + msg_didout = true; // Remember that line is not empty. + screen_puts_len((char_u *)t_s, (int)(s - t_s), msg_row, msg_col, attr); msg_col += *t_col; *t_col = 0; /* If the string starts with a composing character don't increment the @@ -1971,13 +2036,13 @@ int msg_use_printf(void) } /// Print a message when there is no valid screen. -static void msg_puts_printf(char *str, int maxlen) +static void msg_puts_printf(const char *str, const ptrdiff_t maxlen) { - char *s = str; + const char *s = str; char buf[4]; char *p; - while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen)) { + while ((maxlen < 0 || s - str < maxlen) && *s != NUL) { if (!(silent_mode && p_verbose == 0)) { // NL --> CR NL translation (for Unix, not for "--version") p = &buf[0]; @@ -2434,24 +2499,15 @@ void msg_check(void) * May write a string to the redirection file. * When "maxlen" is -1 write the whole string, otherwise up to "maxlen" bytes. */ -static void redir_write(char_u *str, int maxlen) +static void redir_write(const char *const str, const ptrdiff_t maxlen) { - char_u *s = str; + const char_u *s = (char_u *)str; static int cur_col = 0; if (maxlen == 0) { return; } - // Append output for execute(). - if (capture_ga) { - size_t len = 0; - while (str[len] && (maxlen < 0 ? 1 : (len < (size_t)maxlen))) { - len++; - } - ga_concat_len(capture_ga, (const char *)str, len); - } - /* Don't do anything for displaying prompts and the like. */ if (redir_off) return; @@ -2464,6 +2520,9 @@ static void redir_write(char_u *str, int maxlen) /* If the string doesn't start with CR or NL, go to msg_col */ if (*s != '\n' && *s != '\r') { while (cur_col < msg_col) { + if (capture_ga) { + ga_concat_len(capture_ga, " ", 1); + } if (redir_reg) { write_reg_contents(redir_reg, (char_u *)" ", 1, true); } else if (redir_vname) { @@ -2478,28 +2537,36 @@ static void redir_write(char_u *str, int maxlen) } } + size_t len = maxlen == -1 ? STRLEN(s) : (size_t)maxlen; + if (capture_ga) { + ga_concat_len(capture_ga, (const char *)str, len); + } if (redir_reg) { - size_t len = maxlen == -1 ? STRLEN(s) : (size_t)maxlen; write_reg_contents(redir_reg, s, len, true); } if (redir_vname) { - var_redir_str(s, maxlen); + var_redir_str((char_u *)s, maxlen); } - /* Write and adjust the current column. */ - while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen)) { - if (!redir_reg && !redir_vname) - if (redir_fd != NULL) + // Write and adjust the current column. + while (*s != NUL + && (maxlen < 0 || (int)(s - (const char_u *)str) < maxlen)) { + if (!redir_reg && !redir_vname && !capture_ga) { + if (redir_fd != NULL) { putc(*s, redir_fd); - if (verbose_fd != NULL) + } + } + if (verbose_fd != NULL) { putc(*s, verbose_fd); - if (*s == '\r' || *s == '\n') + } + if (*s == '\r' || *s == '\n') { cur_col = 0; - else if (*s == '\t') + } else if (*s == '\t') { cur_col += (8 - cur_col % 8); - else - ++cur_col; - ++s; + } else { + cur_col++; + } + s++; } if (msg_silent != 0) /* should update msg_col */ @@ -2605,14 +2672,16 @@ void give_warning(char_u *message, bool hl) FUNC_ATTR_NONNULL_ARG(1) set_vim_var_string(VV_WARNINGMSG, (char *) message, -1); xfree(keep_msg); keep_msg = NULL; - if (hl) + if (hl) { keep_msg_attr = hl_attr(HLF_W); - else + } else { keep_msg_attr = 0; - if (msg_attr(message, keep_msg_attr) && msg_scrolled == 0) + } + if (msg_attr((const char *)message, keep_msg_attr) && msg_scrolled == 0) { set_keep_msg(message, keep_msg_attr); - msg_didout = FALSE; /* overwrite this message */ - msg_nowait = TRUE; /* don't wait for this message */ + } + msg_didout = false; // Overwrite this message. + msg_nowait = true; // Don't wait for this message. msg_col = 0; --no_wait_return; @@ -2674,9 +2743,11 @@ do_dialog ( int c; int i; - /* Don't output anything in silent mode ("ex -s") */ - if (silent_mode) - return dfltbutton; /* return default option */ + if (silent_mode // No dialogs in silent mode ("ex -s") + || !ui_active() // Without a UI Nvim waits for input forever. + ) { + return dfltbutton; // return default option + } oldState = State; @@ -2712,8 +2783,8 @@ do_dialog ( break; } - /* Make the character lowercase, as chars in "hotkeys" are. */ - c = vim_tolower(c); + // Make the character lowercase, as chars in "hotkeys" are. + c = mb_tolower(c); retval = 1; for (i = 0; hotkeys[i]; ++i) { if (has_mbyte) { @@ -2759,7 +2830,7 @@ copy_char ( if (has_mbyte) { if (lowercase) { - c = vim_tolower((*mb_ptr2char)(from)); + c = mb_tolower((*mb_ptr2char)(from)); return (*mb_char2bytes)(c, to); } else { len = (*mb_ptr2len)(from); @@ -2948,11 +3019,12 @@ static void copy_hotkeys_and_msg(const char_u *message, char_u *buttons, */ void display_confirm_msg(void) { - /* avoid that 'q' at the more prompt truncates the message here */ - ++confirm_msg_used; - if (confirm_msg != NULL) - msg_puts_attr(confirm_msg, hl_attr(HLF_M)); - --confirm_msg_used; + // Avoid that 'q' at the more prompt truncates the message here. + confirm_msg_used++; + if (confirm_msg != NULL) { + msg_puts_attr((const char *)confirm_msg, hl_attr(HLF_M)); + } + confirm_msg_used--; } int vim_dialog_yesno(int type, char_u *title, char_u *message, int dflt) @@ -2991,802 +3063,3 @@ int vim_dialog_yesnoallcancel(int type, char_u *title, char_u *message, int dflt } return VIM_CANCEL; } - - - -static char *e_printf = N_("E766: Insufficient arguments for printf()"); - -/* - * Get number argument from "idxp" entry in "tvs". First entry is 1. - */ -static long tv_nr(typval_T *tvs, int *idxp) -{ - int idx = *idxp - 1; - long n = 0; - int err = FALSE; - - if (tvs[idx].v_type == VAR_UNKNOWN) - EMSG(_(e_printf)); - else { - ++*idxp; - n = get_tv_number_chk(&tvs[idx], &err); - if (err) - n = 0; - } - return n; -} - -/* - * Get string argument from "idxp" entry in "tvs". First entry is 1. - * Returns NULL for an error. - */ -static char *tv_str(typval_T *tvs, int *idxp) -{ - int idx = *idxp - 1; - char *s = NULL; - - if (tvs[idx].v_type == VAR_UNKNOWN) - EMSG(_(e_printf)); - else { - ++*idxp; - s = (char *)get_tv_string_chk(&tvs[idx]); - } - return s; -} - -/* - * Get float argument from "idxp" entry in "tvs". First entry is 1. - */ -static double tv_float(typval_T *tvs, int *idxp) -{ - int idx = *idxp - 1; - double f = 0; - - if (tvs[idx].v_type == VAR_UNKNOWN) - EMSG(_(e_printf)); - else { - ++*idxp; - if (tvs[idx].v_type == VAR_FLOAT) - f = tvs[idx].vval.v_float; - else if (tvs[idx].v_type == VAR_NUMBER) - f = tvs[idx].vval.v_number; - else - EMSG(_("E807: Expected Float argument for printf()")); - } - return f; -} - -/* - * This code was included to provide a portable vsnprintf() and snprintf(). - * Some systems may provide their own, but we always use this one for - * consistency. - * - * This code is based on snprintf.c - a portable implementation of snprintf - * by Mark Martinec <mark.martinec@ijs.si>, Version 2.2, 2000-10-06. - * Included with permission. It was heavily modified to fit in Vim. - * The original code, including useful comments, can be found here: - * http://www.ijs.si/software/snprintf/ - * - * This snprintf() only supports the following conversion specifiers: - * s, c, b, B, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) - * with flags: '-', '+', ' ', '0' and '#'. - * An asterisk is supported for field width as well as precision. - * - * Limited support for floating point was added: 'f', 'e', 'E', 'g', 'G'. - * - * Length modifiers 'h' (short int) and 'l' (long int) are supported. - * 'll' (long long int) is not supported. - * - * The locale is not used, the string is used as a byte string. This is only - * relevant for double-byte encodings where the second byte may be '%'. - * - * It is permitted for "str_m" to be zero, and it is permitted to specify NULL - * pointer for resulting string argument if "str_m" is zero (as per ISO C99). - * - * The return value is the number of characters which would be generated - * for the given input, excluding the trailing NUL. If this value - * is greater or equal to "str_m", not all characters from the result - * have been stored in str, output bytes beyond the ("str_m"-1) -th character - * are discarded. If "str_m" is greater than zero it is guaranteed - * the resulting string will be NUL-terminated. - */ - -/* - * When va_list is not supported we only define vim_snprintf(). - * - * vim_vsnprintf() can be invoked with either "va_list" or a list of - * "typval_T". When the latter is not used it must be NULL. - */ - -/* Like vim_vsnprintf() but append to the string. */ -int vim_snprintf_add(char *str, size_t str_m, char *fmt, ...) -{ - va_list ap; - int str_l; - size_t len = STRLEN(str); - size_t space; - - if (str_m <= len) - space = 0; - else - space = str_m - len; - va_start(ap, fmt); - str_l = vim_vsnprintf(str + len, space, fmt, ap, NULL); - va_end(ap); - return str_l; -} - -int vim_snprintf(char *str, size_t str_m, const char *fmt, ...) -{ - va_list ap; - int str_l; - - va_start(ap, fmt); - str_l = vim_vsnprintf(str, str_m, fmt, ap, NULL); - va_end(ap); - return str_l; -} - -int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, - typval_T *tvs) -{ - size_t str_l = 0; - bool str_avail = str_l < str_m; - const char *p = fmt; - int arg_idx = 1; - - if (!p) { - p = ""; - } - while (*p) { - if (*p != '%') { - // copy up to the next '%' or NUL without any changes - size_t n = (size_t)(xstrchrnul(p + 1, '%') - p); - if (str_avail) { - size_t avail = str_m - str_l; - memmove(str + str_l, p, MIN(n, avail)); - str_avail = n < avail; - } - p += n; - assert(n <= SIZE_MAX - str_l); - str_l += n; - } else { - size_t min_field_width = 0, precision = 0; - int zero_padding = 0, precision_specified = 0, justify_left = 0; - int alternate_form = 0, force_sign = 0; - - // if both ' ' and '+' flags appear, ' ' flag should be ignored - int space_for_positive = 1; - - // allowed values: \0, h, l, 2 (for ll), z, L - char length_modifier = '\0'; - - // temporary buffer for simple numeric->string conversion -# define TMP_LEN 350 // 1e308 seems reasonable as the maximum printable - char tmp[TMP_LEN]; - - // string address in case of string argument - const char *str_arg; - - // natural field width of arg without padding and sign - size_t str_arg_l; - - // unsigned char argument value (only defined for c conversion); - // standard explicitly states the char argument for the c - // conversion is unsigned - unsigned char uchar_arg; - - // number of zeros to be inserted for numeric conversions as - // required by the precision or minimal field width - size_t number_of_zeros_to_pad = 0; - - // index into tmp where zero padding is to be inserted - size_t zero_padding_insertion_ind = 0; - - // current conversion specifier character - char fmt_spec = '\0'; - - str_arg = NULL; - p++; // skip '%' - - // parse flags - while (*p == '0' || *p == '-' || *p == '+' || *p == ' ' - || *p == '#' || *p == '\'') { - switch (*p) { - case '0': zero_padding = 1; break; - case '-': justify_left = 1; break; - // if both '0' and '-' flags appear, '0' should be ignored - case '+': force_sign = 1; space_for_positive = 0; break; - case ' ': force_sign = 1; break; - // if both ' ' and '+' flags appear, ' ' should be ignored - case '#': alternate_form = 1; break; - case '\'': break; - } - p++; - } - - // parse field width - if (*p == '*') { - p++; - int j = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int); - if (j >= 0) { - min_field_width = j; - } else { - min_field_width = -j; - justify_left = 1; - } - } else if (ascii_isdigit((int)(*p))) { - // size_t could be wider than unsigned int; make sure we treat - // argument like common implementations do - unsigned int uj = *p++ - '0'; - - while (ascii_isdigit((int)(*p))) { - uj = 10 * uj + (unsigned int)(*p++ - '0'); - } - min_field_width = uj; - } - - // parse precision - if (*p == '.') { - p++; - precision_specified = 1; - if (*p == '*') { - int j = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int); - p++; - if (j >= 0) { - precision = j; - } else { - precision_specified = 0; - precision = 0; - } - } else if (ascii_isdigit((int)(*p))) { - // size_t could be wider than unsigned int; make sure we - // treat argument like common implementations do - unsigned int uj = *p++ - '0'; - - while (ascii_isdigit((int)(*p))) { - uj = 10 * uj + (unsigned int)(*p++ - '0'); - } - precision = uj; - } - } - - // parse 'h', 'l', 'll' and 'z' length modifiers - if (*p == 'h' || *p == 'l' || *p == 'z') { - length_modifier = *p; - p++; - if (length_modifier == 'l' && *p == 'l') { // ll, encoded as 2 - length_modifier = '2'; - p++; - } - } - - fmt_spec = *p; - - // common synonyms - switch (fmt_spec) { - case 'i': fmt_spec = 'd'; break; - case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; - case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; - case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; - case 'F': fmt_spec = 'f'; break; - default: break; - } - - // get parameter value, do initial processing - switch (fmt_spec) { - // '%' and 'c' behave similar to 's' regarding flags and field widths - case '%': case 'c': case 's': case 'S': - str_arg_l = 1; - switch (fmt_spec) { - case '%': - str_arg = p; - break; - - case 'c': { - int j = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int); - // standard demands unsigned char - uchar_arg = (unsigned char)j; - str_arg = (char *)&uchar_arg; - break; - } - - case 's': - case 'S': - str_arg = tvs ? tv_str(tvs, &arg_idx) : va_arg(ap, char *); - if (!str_arg) { - str_arg = "[NULL]"; - str_arg_l = 6; - } else if (!precision_specified) { - // make sure not to address string beyond the specified precision - str_arg_l = strlen(str_arg); - } else if (precision == 0) { - // truncate string if necessary as requested by precision - str_arg_l = 0; - } else { - // memchr on HP does not like n > 2^31 - // TODO(elmart): check if this still holds / is relevant - str_arg_l = (size_t)((char *)xmemscan(str_arg, - NUL, - MIN(precision, 0x7fffffff)) - - str_arg); - } - if (fmt_spec == 'S') { - if (min_field_width != 0) - min_field_width += strlen(str_arg) - - mb_string2cells((char_u *) str_arg); - if (precision) { - char_u *p1 = (char_u *)str_arg; - for (size_t i = 0; i < precision && *p1; i++) { - p1 += mb_ptr2len(p1); - } - str_arg_l = precision = p1 - (char_u *)str_arg; - } - } - break; - - default: - break; - } - break; - - case 'd': - case 'u': - case 'b': case 'B': - case 'o': - case 'x': case 'X': - case 'p': { - // u, b, B, o, x, X and p conversion specifiers imply - // the value is unsigned; d implies a signed value - - // 0 if numeric argument is zero (or if pointer is NULL for 'p'), - // +1 if greater than zero (or non NULL for 'p'), - // -1 if negative (unsigned argument is never negative) - int arg_sign = 0; - - // only defined for length modifier h, or for no length modifiers - int int_arg = 0; - unsigned int uint_arg = 0; - - // only defined for length modifier l - long int long_arg = 0; - unsigned long int ulong_arg = 0; - - // only defined for length modifier ll - long long int long_long_arg = 0; - unsigned long long int ulong_long_arg = 0; - - // only defined for length modifier z - size_t size_t_arg = 0; - - // only defined for p conversion - void *ptr_arg = NULL; - - if (fmt_spec == 'p') { - length_modifier = '\0'; - ptr_arg = tvs ? (void *)tv_str(tvs, &arg_idx) : va_arg(ap, void *); - if (ptr_arg) { - arg_sign = 1; - } - } else if (fmt_spec == 'd') { - // signed - switch (length_modifier) { - case '\0': - case 'h': - // char and short arguments are passed as int - int_arg = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int); - if (int_arg > 0) { - arg_sign = 1; - } else if (int_arg < 0) { - arg_sign = -1; - } - break; - case 'l': - long_arg = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, long int); - if (long_arg > 0) { - arg_sign = 1; - } else if (long_arg < 0) { - arg_sign = -1; - } - break; - case '2': - long_long_arg = tvs ? tv_nr(tvs, &arg_idx) - : va_arg(ap, long long int); // NOLINT (runtime/int) - if (long_long_arg > 0) { - arg_sign = 1; - } else if (long_long_arg < 0) { - arg_sign = -1; - } - break; - } - } else { - // unsigned - switch (length_modifier) { - case '\0': - case 'h': - uint_arg = tvs ? (unsigned)tv_nr(tvs, &arg_idx) - : va_arg(ap, unsigned int); - if (uint_arg != 0) { arg_sign = 1; } - break; - case 'l': - ulong_arg = tvs ? (unsigned long)tv_nr(tvs, &arg_idx) - : va_arg(ap, unsigned long int); - if (ulong_arg != 0) { arg_sign = 1; } - break; - case '2': - ulong_long_arg = tvs - ? (unsigned long long)tv_nr(tvs, &arg_idx) // NOLINT (runtime/int) - : va_arg(ap, unsigned long long int); // NOLINT (runtime/int) - if (ulong_long_arg) { arg_sign = 1; } - break; - case 'z': - size_t_arg = tvs ? (size_t)tv_nr(tvs, &arg_idx) - : va_arg(ap, size_t); - if (size_t_arg) { arg_sign = 1; } - break; - } - } - - str_arg = tmp; - str_arg_l = 0; - - // For d, i, u, o, x, and X conversions, if precision is specified, - // '0' flag should be ignored. This is so with Solaris 2.6, Digital UNIX - // 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl. - if (precision_specified) { - zero_padding = 0; - } - - if (fmt_spec == 'd') { - if (force_sign && arg_sign >= 0) { - tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; - } - // leave negative numbers for sprintf to handle, to - // avoid handling tricky cases like (short int)-32768 - } else if (alternate_form) { - if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X' - || fmt_spec == 'b' || fmt_spec == 'B')) { - tmp[str_arg_l++] = '0'; - tmp[str_arg_l++] = fmt_spec; - } - // alternate form should have no effect for p * conversion, but ... - } - - zero_padding_insertion_ind = str_arg_l; - if (!precision_specified) { - precision = 1; // default precision is 1 - } - if (precision == 0 && arg_sign == 0) { - // when zero value is formatted with an explicit precision 0, - // resulting formatted string is empty (d, i, u, b, B, o, x, X, p) - } else { - char f[5]; - int f_l = 0; - - // construct a simple format string for sprintf - f[f_l++] = '%'; - if (!length_modifier) { - } else if (length_modifier == '2') { - f[f_l++] = 'l'; - f[f_l++] = 'l'; - } else - f[f_l++] = length_modifier; - f[f_l++] = fmt_spec; - f[f_l++] = '\0'; - - if (fmt_spec == 'p') - str_arg_l += sprintf(tmp + str_arg_l, f, ptr_arg); - else if (fmt_spec == 'd') { - // signed - switch (length_modifier) { - case '\0': - case 'h': str_arg_l += sprintf(tmp + str_arg_l, f, int_arg); - break; - case 'l': str_arg_l += sprintf(tmp + str_arg_l, f, long_arg); - break; - case '2': str_arg_l += sprintf(tmp + str_arg_l, f, long_long_arg); - break; - } - } else if (fmt_spec == 'b' || fmt_spec == 'B') { - // binary - size_t bits = 0; - switch (length_modifier) { - case '\0': - case 'h': for (bits = sizeof(unsigned) * 8; bits > 0; bits--) { - if ((uint_arg >> (bits - 1)) & 0x1) { break; } } - - while (bits > 0) { - tmp[str_arg_l++] = - ((uint_arg >> --bits) & 0x1) ? '1' : '0'; } - break; - case 'l': for (bits = sizeof(unsigned long) * 8; bits > 0; bits--) { - if ((ulong_arg >> (bits - 1)) & 0x1) { break; } } - - while (bits > 0) { - tmp[str_arg_l++] = - ((ulong_arg >> --bits) & 0x1) ? '1' : '0'; } - break; - case '2': for (bits = sizeof(unsigned long long) * 8; // NOLINT (runtime/int) - bits > 0; bits--) { - if ((ulong_long_arg >> (bits - 1)) & 0x1) { break; } } - - while (bits > 0) { - tmp[str_arg_l++] = - ((ulong_long_arg >> --bits) & 0x1) ? '1' : '0'; } - break; - case 'z': for (bits = sizeof(size_t) * 8; bits > 0; bits--) { - if ((size_t_arg >> (bits - 1)) & 0x1) { break; } } - - while (bits > 0) { - tmp[str_arg_l++] = - ((size_t_arg >> --bits) & 0x1) ? '1' : '0'; } - break; - } - } else { - // unsigned - switch (length_modifier) { - case '\0': - case 'h': str_arg_l += sprintf(tmp + str_arg_l, f, uint_arg); - break; - case 'l': str_arg_l += sprintf(tmp + str_arg_l, f, ulong_arg); - break; - case '2': str_arg_l += sprintf(tmp + str_arg_l, f, ulong_long_arg); - break; - case 'z': str_arg_l += sprintf(tmp + str_arg_l, f, size_t_arg); - break; - } - } - - // include the optional minus sign and possible "0x" in the region - // before the zero padding insertion point - if (zero_padding_insertion_ind < str_arg_l - && tmp[zero_padding_insertion_ind] == '-') - zero_padding_insertion_ind++; - if (zero_padding_insertion_ind + 1 < str_arg_l - && tmp[zero_padding_insertion_ind] == '0' - && (tmp[zero_padding_insertion_ind + 1] == 'x' - || tmp[zero_padding_insertion_ind + 1] == 'X' - || tmp[zero_padding_insertion_ind + 1] == 'b' - || tmp[zero_padding_insertion_ind + 1] == 'B')) - zero_padding_insertion_ind += 2; - } - - { - size_t num_of_digits = str_arg_l - zero_padding_insertion_ind; - - if (alternate_form && fmt_spec == 'o' - // unless zero is already the first character - && !(zero_padding_insertion_ind < str_arg_l - && tmp[zero_padding_insertion_ind] == '0')) { - // assure leading zero for alternate-form octal numbers - if (!precision_specified - || precision < num_of_digits + 1) { - // precision is increased to force the first character to be zero, - // except if a zero value is formatted with an explicit precision - // of zero - precision = num_of_digits + 1; - } - } - // zero padding to specified precision? - if (num_of_digits < precision) - number_of_zeros_to_pad = precision - num_of_digits; - } - // zero padding to specified minimal field width? - if (!justify_left && zero_padding) { - int n = (int)(min_field_width - (str_arg_l - + number_of_zeros_to_pad)); - if (n > 0) - number_of_zeros_to_pad += n; - } - break; - } - - case 'f': - case 'e': - case 'E': - case 'g': - case 'G': - { - // floating point - char format[40]; - int l; - int remove_trailing_zeroes = false; - - double f = tvs ? tv_float(tvs, &arg_idx) : va_arg(ap, double); - double abs_f = f < 0 ? -f : f; - - if (fmt_spec == 'g' || fmt_spec == 'G') { - // can't use %g directly, cause it prints "1.0" as "1" - if ((abs_f >= 0.001 && abs_f < 10000000.0) || abs_f == 0.0) - fmt_spec = 'f'; - else - fmt_spec = fmt_spec == 'g' ? 'e' : 'E'; - remove_trailing_zeroes = true; - } - - if (fmt_spec == 'f' && abs_f > 1.0e307) { - // avoid a buffer overflow - strcpy(tmp, "inf"); - str_arg_l = 3; - } else { - format[0] = '%'; - l = 1; - if (precision_specified) { - size_t max_prec = TMP_LEN - 10; - - // make sure we don't get more digits than we have room for - if (fmt_spec == 'f' && abs_f > 1.0) - max_prec -= (size_t)log10(abs_f); - if (precision > max_prec) - precision = max_prec; - l += sprintf(format + 1, ".%d", (int)precision); - } - format[l] = fmt_spec; - format[l + 1] = NUL; - str_arg_l = sprintf(tmp, format, f); - - if (remove_trailing_zeroes) { - int i; - char *tp; - - // using %g or %G: remove superfluous zeroes - if (fmt_spec == 'f') - tp = tmp + str_arg_l - 1; - else { - tp = (char *)vim_strchr((char_u *)tmp, - fmt_spec == 'e' ? 'e' : 'E'); - if (tp) { - // remove superfluous '+' and leading zeroes from exponent - if (tp[1] == '+') { - // change "1.0e+07" to "1.0e07" - STRMOVE(tp + 1, tp + 2); - --str_arg_l; - } - i = (tp[1] == '-') ? 2 : 1; - while (tp[i] == '0') { - // change "1.0e07" to "1.0e7" - STRMOVE(tp + i, tp + i + 1); - --str_arg_l; - } - --tp; - } - } - - if (tp != NULL && !precision_specified) - // remove trailing zeroes, but keep the one just after a dot - while (tp > tmp + 2 && *tp == '0' && tp[-1] != '.') { - STRMOVE(tp, tp + 1); - --tp; - --str_arg_l; - } - } else { - // be consistent: some printf("%e") use 1.0e+12 and some 1.0e+012; - // remove one zero in the last case - char *tp = (char *)vim_strchr((char_u *)tmp, - fmt_spec == 'e' ? 'e' : 'E'); - if (tp && (tp[1] == '+' || tp[1] == '-') && tp[2] == '0' - && ascii_isdigit(tp[3]) && ascii_isdigit(tp[4])) { - STRMOVE(tp + 2, tp + 3); - --str_arg_l; - } - } - } - str_arg = tmp; - break; - } - - default: - // unrecognized conversion specifier, keep format string as-is - zero_padding = 0; // turn zero padding off for non-numeric conversion - justify_left = 1; - min_field_width = 0; // reset flags - - // discard the unrecognized conversion, just keep - // the unrecognized conversion character - str_arg = p; - str_arg_l = 0; - if (*p) - str_arg_l++; // include invalid conversion specifier - // unchanged if not at end-of-string - break; - } - - if (*p) - p++; // step over the just processed conversion specifier - - // insert padding to the left as requested by min_field_width; - // this does not include the zero padding in case of numerical conversions - if (!justify_left) { - assert(str_arg_l <= SIZE_MAX - number_of_zeros_to_pad); - if (min_field_width > str_arg_l + number_of_zeros_to_pad) { - // left padding with blank or zero - size_t pn = min_field_width - (str_arg_l + number_of_zeros_to_pad); - if (str_avail) { - size_t avail = str_m - str_l; - memset(str + str_l, zero_padding ? '0' : ' ', MIN(pn, avail)); - str_avail = pn < avail; - } - assert(pn <= SIZE_MAX - str_l); - str_l += pn; - } - } - - // zero padding as requested by the precision or by the minimal - // field width for numeric conversions required? - if (number_of_zeros_to_pad == 0) { - // will not copy first part of numeric right now, - // force it to be copied later in its entirety - zero_padding_insertion_ind = 0; - } else { - // insert first part of numerics (sign or '0x') before zero padding - if (zero_padding_insertion_ind > 0) { - size_t zn = zero_padding_insertion_ind; - if (str_avail) { - size_t avail = str_m - str_l; - memmove(str + str_l, str_arg, MIN(zn, avail)); - str_avail = zn < avail; - } - assert(zn <= SIZE_MAX - str_l); - str_l += zn; - } - - // insert zero padding as requested by precision or min field width - if (number_of_zeros_to_pad > 0) { - size_t zn = number_of_zeros_to_pad; - if (str_avail) { - size_t avail = str_m - str_l; - memset(str + str_l, '0', MIN(zn, avail)); - str_avail = zn < avail; - } - assert(zn <= SIZE_MAX - str_l); - str_l += zn; - } - } - - // insert formatted string - // (or as-is conversion specifier for unknown conversions) - if (str_arg_l > zero_padding_insertion_ind) { - size_t sn = str_arg_l - zero_padding_insertion_ind; - if (str_avail) { - size_t avail = str_m - str_l; - memmove(str + str_l, - str_arg + zero_padding_insertion_ind, - MIN(sn, avail)); - str_avail = sn < avail; - } - assert(sn <= SIZE_MAX - str_l); - str_l += sn; - } - - // insert right padding - if (justify_left) { - assert(str_arg_l <= SIZE_MAX - number_of_zeros_to_pad); - if (min_field_width > str_arg_l + number_of_zeros_to_pad) { - // right blank padding to the field width - size_t pn = min_field_width - (str_arg_l + number_of_zeros_to_pad); - if (str_avail) { - size_t avail = str_m - str_l; - memset(str + str_l, ' ', MIN(pn, avail)); - str_avail = pn < avail; - } - assert(pn <= SIZE_MAX - str_l); - str_l += pn; - } - } - } - } - - if (str_m > 0) { - // make sure the string is nul-terminated even at the expense of - // overwriting the last character (shouldn't happen, but just in case) - str[str_l <= str_m - 1 ? str_l : str_m - 1] = '\0'; - } - - if (tvs && tvs[arg_idx - 1].v_type != VAR_UNKNOWN) - EMSG(_("E767: Too many arguments to printf()")); - - // return the number of characters formatted (excluding trailing nul - // character); that is, the number of characters that would have been - // written to the buffer if it were large enough. - return (int)str_l; -} diff --git a/src/nvim/message.h b/src/nvim/message.h index d3a16fff93..904a9d3ca1 100644 --- a/src/nvim/message.h +++ b/src/nvim/message.h @@ -3,8 +3,9 @@ #include <stdbool.h> #include <stdarg.h> -#include "nvim/eval_defs.h" // for typval_T -#include "nvim/ex_cmds_defs.h" // for exarg_T +#include <stddef.h> + +#include "nvim/types.h" /* * Types of dialogs passed to do_dialog(). @@ -29,7 +30,7 @@ #define MSG(s) msg((char_u *)(s)) /// Show message highlighted according to the attr -#define MSG_ATTR(s, attr) msg_attr((char_u *)(s), (attr)) +#define MSG_ATTR(s, attr) msg_attr((const char *)(s), (attr)) /// Display error message /// @@ -49,13 +50,13 @@ #define EMSGU(s, n) emsgf((const char *) (s), (uint64_t)(n)) /// Display message at the recorded position -#define MSG_PUTS(s) msg_puts((char_u *)(s)) +#define MSG_PUTS(s) msg_puts((const char *)(s)) /// Display message at the recorded position, highlighted -#define MSG_PUTS_ATTR(s, a) msg_puts_attr((char_u *)(s), (a)) +#define MSG_PUTS_ATTR(s, a) msg_puts_attr((const char *)(s), (a)) /// Like #MSG_PUTS, but highlight like title -#define MSG_PUTS_TITLE(s) msg_puts_title((char_u *)(s)) +#define MSG_PUTS_TITLE(s) msg_puts_title((const char *)(s)) /// Like #MSG_PUTS, but if middle part of too long messages it will be replaced #define MSG_PUTS_LONG(s) msg_puts_long_attr((char_u *)(s), 0) diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index 71aa6e83e5..5270687a4d 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -1,3 +1,6 @@ +// 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 + /* * misc1.c: functions that didn't seem to fit elsewhere */ @@ -51,6 +54,7 @@ #include "nvim/os/input.h" #include "nvim/os/time.h" #include "nvim/event/stream.h" +#include "nvim/buffer.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "misc1.c.generated.h" @@ -747,7 +751,7 @@ open_line ( // Skip mark_adjust when adding a line after the last one, there can't // be marks there. if (curwin->w_cursor.lnum + 1 < curbuf->b_ml.ml_line_count) { - mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L); + mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L, false); } did_append = true; } else { @@ -1405,7 +1409,6 @@ void ins_char_bytes(char_u *buf, size_t charlen) coladvance_force(getviscol()); } - int c = buf[0]; size_t col = (size_t)curwin->w_cursor.col; linenr_T lnum = curwin->w_cursor.lnum; char_u *oldp = ml_get(lnum); @@ -1498,10 +1501,7 @@ void ins_char_bytes(char_u *buf, size_t charlen) && msg_silent == 0 && !ins_compl_active() ) { - if (has_mbyte) - showmatch(mb_ptr2char(buf)); - else - showmatch(c); + showmatch(mb_ptr2char(buf)); } if (!p_ri || (State & REPLACE_FLAG)) { @@ -1788,7 +1788,7 @@ void changed(void) } changed_int(); } - ++curbuf->b_changedtick; + buf_set_changedtick(curbuf, curbuf->b_changedtick + 1); } /* @@ -1866,7 +1866,7 @@ 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. if (lnum + count < curbuf->b_ml.ml_line_count) { - mark_adjust(lnum + 1, (linenr_T)MAXLNUM, count, 0L); + mark_adjust(lnum + 1, (linenr_T)MAXLNUM, count, 0L, false); } changed_lines(lnum + 1, 0, lnum + 1, count); } @@ -1888,7 +1888,7 @@ void deleted_lines(linenr_T lnum, long count) */ void deleted_lines_mark(linenr_T lnum, long count) { - mark_adjust(lnum, (linenr_T)(lnum + count - 1), (long)MAXLNUM, -count); + mark_adjust(lnum, (linenr_T)(lnum + count - 1), (long)MAXLNUM, -count, false); changed_lines(lnum, 0, lnum + count, -count); } @@ -2147,7 +2147,7 @@ unchanged ( redraw_tabline = TRUE; need_maketitle = TRUE; /* set window title later */ } - ++buf->b_changedtick; + buf_set_changedtick(buf, buf->b_changedtick + 1); } /* @@ -2203,7 +2203,7 @@ change_warning ( set_vim_var_string(VV_WARNINGMSG, _(w_readonly), -1); msg_clr_eos(); (void)msg_end(); - if (msg_silent == 0 && !silent_mode) { + if (msg_silent == 0 && !silent_mode && ui_active()) { ui_flush(); os_delay(1000L, true); /* give the user time to think about it */ } @@ -2214,44 +2214,47 @@ change_warning ( } } -/* - * Ask for a reply from the user, a 'y' or a 'n'. - * No other characters are accepted, the message is repeated until a valid - * reply is entered or CTRL-C is hit. - * If direct is TRUE, don't use vgetc() but ui_inchar(), don't get characters - * from any buffers but directly from the user. - * - * return the 'y' or 'n' - */ -int ask_yesno(char_u *str, int direct) +/// Ask for a reply from the user, 'y' or 'n' +/// +/// No other characters are accepted, the message is repeated until a valid +/// reply is entered or <C-c> is hit. +/// +/// @param[in] str Prompt: question to ask user. Is always followed by +/// " (y/n)?". +/// @param[in] direct Determines what function to use to get user input. If +/// true then ui_inchar() will be used, otherwise vgetc(). +/// I.e. when direct is true then characters are obtained +/// directly from the user without buffers involved. +/// +/// @return 'y' or 'n'. Last is also what will be returned in case of interrupt. +int ask_yesno(const char *const str, const bool direct) { - int r = ' '; - int save_State = State; + const int save_State = State; - ++no_wait_return; - State = CONFIRM; /* mouse behaves like with :confirm */ - setmouse(); /* disables mouse for xterm */ - ++no_mapping; - ++allow_keys; /* no mapping here, but recognize keys */ + no_wait_return++; + State = CONFIRM; // Mouse behaves like with :confirm. + setmouse(); // Disable mouse in xterm. + no_mapping++; + int r = ' '; while (r != 'y' && r != 'n') { - /* same highlighting as for wait_return */ - smsg_attr(hl_attr(HLF_R), - "%s (y/n)?", str); - if (direct) + // Same highlighting as for wait_return. + smsg_attr(hl_attr(HLF_R), "%s (y/n)?", str); + if (direct) { r = get_keystroke(); - else + } else { r = plain_vgetc(); - if (r == Ctrl_C || r == ESC) + } + if (r == Ctrl_C || r == ESC) { r = 'n'; - msg_putchar(r); /* show what you typed */ + } + msg_putchar(r); // Show what you typed. ui_flush(); } - --no_wait_return; + no_wait_return--; State = save_State; setmouse(); - --no_mapping; - --allow_keys; + no_mapping--; return r; } @@ -2324,8 +2327,8 @@ int get_keystroke(void) * terminal code to complete. */ n = os_inchar(buf + len, maxlen, len == 0 ? -1L : 100L, 0); if (n > 0) { - /* Replace zero and CSI by a special key code. */ - n = fix_input_buffer(buf + len, n, FALSE); + // Replace zero and CSI by a special key code. + n = fix_input_buffer(buf + len, n); len += n; waited = 0; } else if (len > 0) @@ -2401,8 +2404,7 @@ get_number ( if (msg_silent != 0) return 0; - ++no_mapping; - ++allow_keys; /* no mapping here, but recognize keys */ + no_mapping++; for (;; ) { ui_cursor_goto(msg_row, msg_col); c = safe_vgetc(); @@ -2430,8 +2432,7 @@ get_number ( } else if (c == CAR || c == NL || c == Ctrl_C || c == ESC) break; } - --no_mapping; - --allow_keys; + no_mapping--; return n; } @@ -2507,8 +2508,9 @@ void msgmore(long n) vim_snprintf((char *)msg_buf, MSG_BUF_LEN, _("%" PRId64 " fewer lines"), (int64_t)pn); } - if (got_int) - vim_strcat(msg_buf, (char_u *)_(" (Interrupted)"), MSG_BUF_LEN); + if (got_int) { + xstrlcat((char *)msg_buf, _(" (Interrupted)"), MSG_BUF_LEN); + } if (msg(msg_buf)) { set_keep_msg(msg_buf, 0); keep_msg_more = TRUE; @@ -2534,9 +2536,9 @@ void vim_beep(unsigned val) if (emsg_silent == 0) { if (!((bo_flags & val) || (bo_flags & BO_ALL))) { if (p_vb) { - ui_visual_bell(); + ui_call_visual_bell(); } else { - ui_putc(BELL); + ui_call_bell(); } } @@ -2544,7 +2546,7 @@ void vim_beep(unsigned val) * function give the user a hint where the beep comes from. */ if (vim_strchr(p_debug, 'e') != NULL) { msg_source(hl_attr(HLF_W)); - msg_attr((char_u *)_("Beep!"), hl_attr(HLF_W)); + msg_attr(_("Beep!"), hl_attr(HLF_W)); } } } @@ -2679,7 +2681,8 @@ void fast_breakcheck(void) } } -// Call shell. Calls os_call_shell, with 'shellxquote' added. +// os_call_shell wrapper. Handles 'verbose', :profile, and v:shell_error. +// Invalidates cached tags. int call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg) { int retval; @@ -2687,9 +2690,8 @@ int call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg) if (p_verbose > 3) { verbose_enter(); - smsg(_("Calling shell to execute: \"%s\""), - cmd == NULL ? p_sh : cmd); - ui_putc('\n'); + smsg(_("Calling shell to execute: \"%s\""), cmd == NULL ? p_sh : cmd); + ui_linefeed(); verbose_leave(); } diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 2ebe199f47..d908a022f1 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -1,3 +1,6 @@ +// 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 <stdbool.h> #include "nvim/mouse.h" @@ -456,6 +459,7 @@ void setmouse(void) { int checkfor; + ui_cursor_shape(); /* be quick when mouse is off */ if (*p_mouse == NUL) @@ -475,9 +479,9 @@ void setmouse(void) checkfor = MOUSE_NORMAL; /* assume normal mode */ if (mouse_has(checkfor)) { - ui_mouse_on(); + ui_call_mouse_on(); } else { - ui_mouse_off(); + ui_call_mouse_off(); } } diff --git a/src/nvim/move.c b/src/nvim/move.c index bb6c032db1..4d646f5a4b 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -1,3 +1,6 @@ +// 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 + /* * move.c: Functions for moving the cursor and scrolling text. * @@ -1760,7 +1763,7 @@ int onepage(int dir, long count) loff.fill = 0; if (dir == FORWARD) { - if (firstwin == lastwin && p_window > 0 && p_window < Rows - 1) { + if (ONE_WINDOW && p_window > 0 && p_window < Rows - 1) { /* Vi compatible scrolling */ if (p_window <= 2) ++curwin->w_topline; @@ -1794,7 +1797,7 @@ int onepage(int dir, long count) max_topfill(); continue; } - if (firstwin == lastwin && p_window > 0 && p_window < Rows - 1) { + if (ONE_WINDOW && p_window > 0 && p_window < Rows - 1) { /* Vi compatible scrolling (sort of) */ if (p_window <= 2) --curwin->w_topline; @@ -1878,8 +1881,10 @@ int onepage(int dir, long count) } foldAdjustCursor(); cursor_correct(); - if (retval == OK) + check_cursor_col(); + if (retval == OK) { beginline(BL_SOL | BL_FIX); + } curwin->w_valid &= ~(VALID_WCOL|VALID_WROW|VALID_VIRTCOL); /* @@ -2137,18 +2142,17 @@ void do_check_cursorbind(void) * loop through the cursorbound windows */ VIsual_select = VIsual_active = 0; - for (curwin = firstwin; curwin; curwin = curwin->w_next) { + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + curwin = wp; curbuf = curwin->w_buffer; /* skip original window and windows with 'noscrollbind' */ if (curwin != old_curwin && curwin->w_p_crb) { - if (curwin->w_p_diff) - curwin->w_cursor.lnum - = diff_get_corresponding_line(old_curbuf, - line, - curbuf, - curwin->w_cursor.lnum); - else + if (curwin->w_p_diff) { + curwin->w_cursor.lnum = + diff_get_corresponding_line(old_curbuf, line); + } else { curwin->w_cursor.lnum = line; + } curwin->w_cursor.col = col; curwin->w_cursor.coladd = coladd; curwin->w_curswant = curswant; diff --git a/src/nvim/move.h b/src/nvim/move.h index 3f3bf70929..00fbcc580f 100644 --- a/src/nvim/move.h +++ b/src/nvim/move.h @@ -2,6 +2,8 @@ #define NVIM_MOVE_H #include <stdbool.h> +#include "nvim/buffer_defs.h" +#include "nvim/pos.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "move.h.generated.h" diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 98636263b9..02f3854f47 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -1,3 +1,6 @@ +// 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 <stdbool.h> #include <string.h> #include <inttypes.h> @@ -9,6 +12,7 @@ #include "nvim/api/vim.h" #include "nvim/api/ui.h" #include "nvim/msgpack_rpc/channel.h" +#include "nvim/msgpack_rpc/server.h" #include "nvim/event/loop.h" #include "nvim/event/libuv_process.h" #include "nvim/event/rstream.h" @@ -25,7 +29,9 @@ #include "nvim/map.h" #include "nvim/log.h" #include "nvim/misc1.h" +#include "nvim/path.h" #include "nvim/lib/kvec.h" +#include "nvim/os/input.h" #define CHANNEL_BUFFER_SIZE 0xffff @@ -37,7 +43,8 @@ typedef enum { kChannelTypeSocket, kChannelTypeProc, - kChannelTypeStdio + kChannelTypeStdio, + kChannelTypeInternal } ChannelType; typedef struct { @@ -55,7 +62,7 @@ typedef struct { ChannelType type; msgpack_unpacker *unpacker; union { - Stream stream; + Stream stream; // bidirectional (socket) Process *proc; struct { Stream in; @@ -86,6 +93,7 @@ static msgpack_sbuffer out_buffer; /// Initializes the module void channel_init(void) { + ch_before_blocking_events = multiqueue_new_child(main_loop.events); channels = pmap_new(uint64_t)(); event_strings = pmap_new(cstr_t)(); msgpack_sbuffer_init(&out_buffer); @@ -109,18 +117,24 @@ void channel_teardown(void) /// Creates an API channel by starting a process and connecting to its /// stdin/stdout. stderr is handled by the job infrastructure. /// -/// @param argv The argument vector for the process. [consumed] -/// @return The channel id (> 0), on success. -/// 0, on error. -uint64_t channel_from_process(Process *proc, uint64_t id) +/// @param proc process object +/// @param id (optional) channel id +/// @param source description of source function, rplugin name, TCP addr, etc +/// +/// @return Channel id (> 0), on success. 0, on error. +uint64_t channel_from_process(Process *proc, uint64_t id, char *source) { - Channel *channel = register_channel(kChannelTypeProc, id, proc->events); + Channel *channel = register_channel(kChannelTypeProc, id, proc->events, + source); incref(channel); // process channels are only closed by the exit_cb channel->data.proc = proc; wstream_init(proc->in, 0); rstream_init(proc->out, 0); - rstream_start(proc->out, parse_msgpack, channel); + rstream_start(proc->out, receive_msgpack, channel); + + DLOG("ch %" PRIu64 " in-stream=%p out-stream=%p", channel->id, proc->in, + proc->out); return channel->id; } @@ -130,14 +144,48 @@ uint64_t channel_from_process(Process *proc, uint64_t id) /// @param watcher The SocketWatcher ready to accept the connection void channel_from_connection(SocketWatcher *watcher) { - Channel *channel = register_channel(kChannelTypeSocket, 0, NULL); + Channel *channel = register_channel(kChannelTypeSocket, 0, NULL, + watcher->addr); socket_watcher_accept(watcher, &channel->data.stream); incref(channel); // close channel only after the stream is closed channel->data.stream.internal_close_cb = close_cb; channel->data.stream.internal_data = channel; wstream_init(&channel->data.stream, 0); rstream_init(&channel->data.stream, CHANNEL_BUFFER_SIZE); - rstream_start(&channel->data.stream, parse_msgpack, channel); + rstream_start(&channel->data.stream, receive_msgpack, channel); + + DLOG("ch %" PRIu64 " in/out-stream=%p", channel->id, + &channel->data.stream); +} + +/// @param source description of source function, rplugin name, TCP addr, etc +uint64_t channel_connect(bool tcp, const char *address, int timeout, + char *source, const char **error) +{ + if (!tcp) { + char *path = fix_fname(address); + if (server_owns_pipe_address(path)) { + // avoid deadlock + xfree(path); + return channel_create_internal(); + } + xfree(path); + } + + Channel *channel = register_channel(kChannelTypeSocket, 0, NULL, source); + if (!socket_connect(&main_loop, &channel->data.stream, + tcp, address, timeout, error)) { + decref(channel); + return 0; + } + + incref(channel); // close channel only after the stream is closed + channel->data.stream.internal_close_cb = close_cb; + channel->data.stream.internal_data = channel; + wstream_init(&channel->data.stream, 0); + rstream_init(&channel->data.stream, CHANNEL_BUFFER_SIZE); + rstream_start(&channel->data.stream, receive_msgpack, channel); + return channel->id; } /// Sends event/arguments to channel @@ -147,7 +195,7 @@ void channel_from_connection(SocketWatcher *watcher) /// @param name The event name, an arbitrary string /// @param args Array with event arguments /// @return True if the event was sent successfully, false otherwise. -bool channel_send_event(uint64_t id, char *name, Array args) +bool channel_send_event(uint64_t id, const char *name, Array args) { Channel *channel = NULL; @@ -160,7 +208,7 @@ bool channel_send_event(uint64_t id, char *name, Array args) if (channel) { if (channel->pending_requests) { // Pending request, queue the notification for later sending. - String method = cstr_as_string(name); + const String method = cstr_as_string((char *)name); WBuffer *buffer = serialize_request(id, 0, method, args, &out_buffer, 1); kv_push(channel->delayed_notifications, buffer); } else { @@ -182,14 +230,14 @@ bool channel_send_event(uint64_t id, char *name, Array args) /// @param[out] error True if the return value is an error /// @return Whatever the remote method returned Object channel_send_call(uint64_t id, - char *method_name, + const char *method_name, Array args, Error *err) { Channel *channel = NULL; if (!(channel = pmap_get(uint64_t)(channels, id)) || channel->closed) { - api_set_error(err, Exception, _("Invalid channel \"%" PRIu64 "\""), id); + api_set_error(err, kErrorTypeException, "Invalid channel: %" PRIu64, id); api_free_array(args); return NIL; } @@ -209,7 +257,8 @@ Object channel_send_call(uint64_t id, if (frame.errored) { if (frame.result.type == kObjectTypeString) { - api_set_error(err, Exception, "%s", frame.result.data.string.data); + api_set_error(err, kErrorTypeException, "%s", + frame.result.data.string.data); } else if (frame.result.type == kObjectTypeArray) { // Should be an error in the form [type, message] Array array = frame.result.data.array; @@ -217,14 +266,13 @@ Object channel_send_call(uint64_t id, && (array.items[0].data.integer == kErrorTypeException || array.items[0].data.integer == kErrorTypeValidation) && array.items[1].type == kObjectTypeString) { - err->type = (ErrorType) array.items[0].data.integer; - xstrlcpy(err->msg, array.items[1].data.string.data, sizeof(err->msg)); - err->set = true; + api_set_error(err, (ErrorType)array.items[0].data.integer, "%s", + array.items[1].data.string.data); } else { - api_set_error(err, Exception, "%s", "unknown error"); + api_set_error(err, kErrorTypeException, "%s", "unknown error"); } } else { - api_set_error(err, Exception, "%s", "unknown error"); + api_set_error(err, kErrorTypeException, "%s", "unknown error"); } api_free_object(frame.result); @@ -292,17 +340,28 @@ bool channel_close(uint64_t id) return true; } -/// Creates an API channel from stdin/stdout. This is used when embedding -/// Neovim +/// Creates an API channel from stdin/stdout. Used to embed Nvim. void channel_from_stdio(void) { - Channel *channel = register_channel(kChannelTypeStdio, 0, NULL); + Channel *channel = register_channel(kChannelTypeStdio, 0, NULL, NULL); incref(channel); // stdio channels are only closed on exit // read stream rstream_init_fd(&main_loop, &channel->data.std.in, 0, CHANNEL_BUFFER_SIZE); - rstream_start(&channel->data.std.in, parse_msgpack, channel); + rstream_start(&channel->data.std.in, receive_msgpack, channel); // write stream wstream_init_fd(&main_loop, &channel->data.std.out, 1, 0); + + DLOG("ch %" PRIu64 " in-stream=%p out-stream=%p", channel->id, + &channel->data.std.in, &channel->data.std.out); +} + +/// Creates a loopback channel. This is used to avoid deadlock +/// when an instance connects to its own named pipe. +uint64_t channel_create_internal(void) +{ + Channel *channel = register_channel(kChannelTypeInternal, 0, NULL, NULL); + incref(channel); // internal channel lives until process exit + return channel->id; } void channel_process_exit(uint64_t id, int status) @@ -313,28 +372,50 @@ void channel_process_exit(uint64_t id, int status) decref(channel); } -static void parse_msgpack(Stream *stream, RBuffer *rbuf, size_t c, void *data, - bool eof) +// rstream.c:read_event() invokes this as stream->read_cb(). +static void receive_msgpack(Stream *stream, RBuffer *rbuf, size_t c, + void *data, bool eof) { Channel *channel = data; incref(channel); if (eof) { close_channel(channel); - call_set_error(channel, "Channel was closed by the client"); + char buf[256]; + snprintf(buf, sizeof(buf), "ch %" PRIu64 " was closed by the client", + channel->id); + call_set_error(channel, buf, WARN_LOG_LEVEL); + goto end; + } + + if ((chan_wstream(channel) != NULL && chan_wstream(channel)->closed) + || (chan_rstream(channel) != NULL && chan_rstream(channel)->closed)) { + char buf[256]; + snprintf(buf, sizeof(buf), + "ch %" PRIu64 ": stream closed unexpectedly. " + "closing channel", + channel->id); + call_set_error(channel, buf, WARN_LOG_LEVEL); goto end; } size_t count = rbuffer_size(rbuf); - DLOG("Feeding the msgpack parser with %u bytes of data from Stream(%p)", - count, - stream); + DLOG("ch %" PRIu64 ": parsing %u bytes from msgpack Stream: %p", + channel->id, count, stream); // Feed the unpacker with data msgpack_unpacker_reserve_buffer(channel->unpacker, count); rbuffer_read(rbuf, msgpack_unpacker_buffer(channel->unpacker), count); msgpack_unpacker_buffer_consumed(channel->unpacker, count); + parse_msgpack(channel); + +end: + decref(channel); +} + +static void parse_msgpack(Channel *channel) +{ msgpack_unpacked unpacked; msgpack_unpacked_init(&unpacked); msgpack_unpack_return result; @@ -350,17 +431,15 @@ static void parse_msgpack(Stream *stream, RBuffer *rbuf, size_t c, void *data, complete_call(&unpacked.data, channel); } else { char buf[256]; - snprintf(buf, - sizeof(buf), - "Channel %" PRIu64 " returned a response that doesn't have " - "a matching request id. Ensure the client is properly " - "synchronized", + snprintf(buf, sizeof(buf), + "ch %" PRIu64 " returned a response with an unknown request " + "id. Ensure the client is properly synchronized", channel->id); - call_set_error(channel, buf); + call_set_error(channel, buf, ERROR_LOG_LEVEL); } msgpack_unpacked_destroy(&unpacked); // Bail out from this event loop iteration - goto end; + return; } handle_request(channel, &unpacked.data); @@ -378,17 +457,15 @@ static void parse_msgpack(Stream *stream, RBuffer *rbuf, size_t c, void *data, // causes for this error(search for 'goto _failed') // // A not so uncommon cause for this might be deserializing objects with - // a high nesting level: msgpack will break when it's internal parse stack - // size exceeds MSGPACK_EMBED_STACK_SIZE(defined as 32 by default) + // a high nesting level: msgpack will break when its internal parse stack + // size exceeds MSGPACK_EMBED_STACK_SIZE (defined as 32 by default) send_error(channel, 0, "Invalid msgpack payload. " "This error can also happen when deserializing " "an object with high level of nesting"); } - -end: - decref(channel); } + static void handle_request(Channel *channel, msgpack_object *request) FUNC_ATTR_NONNULL_ALL { @@ -396,7 +473,7 @@ static void handle_request(Channel *channel, msgpack_object *request) Error error = ERROR_INIT; msgpack_rpc_validate(&request_id, request, &error); - if (error.set) { + if (ERROR_SET(&error)) { // Validation failed, send response with error if (channel_write(channel, serialize_response(channel->id, @@ -406,13 +483,13 @@ static void handle_request(Channel *channel, msgpack_object *request) &out_buffer))) { char buf[256]; snprintf(buf, sizeof(buf), - "Channel %" PRIu64 " sent an invalid message, closed.", + "ch %" PRIu64 " sent an invalid message, closed.", channel->id); - call_set_error(channel, buf); + call_set_error(channel, buf, ERROR_LOG_LEVEL); } + api_clear_error(&error); return; } - // Retrieve the request handler MsgpackRpcRequestHandler handler; msgpack_object *method = msgpack_rpc_method(request); @@ -431,16 +508,24 @@ static void handle_request(Channel *channel, msgpack_object *request) handler.async = true; } - RequestEvent *event_data = xmalloc(sizeof(RequestEvent)); - event_data->channel = channel; - event_data->handler = handler; - event_data->args = args; - event_data->request_id = request_id; + RequestEvent *evdata = xmalloc(sizeof(RequestEvent)); + evdata->channel = channel; + evdata->handler = handler; + evdata->args = args; + evdata->request_id = request_id; incref(channel); if (handler.async) { - on_request_event((void **)&event_data); + bool is_get_mode = handler.fn == handle_nvim_get_mode; + + if (is_get_mode && !input_blocking()) { + // Defer the event to a special queue used by os/input.c. #6247 + multiqueue_put(ch_before_blocking_events, on_request_event, 1, evdata); + } else { + // Invoke immediately. + on_request_event((void **)&evdata); + } } else { - multiqueue_put(channel->events, on_request_event, 1, event_data); + multiqueue_put(channel->events, on_request_event, 1, evdata); } } @@ -468,11 +553,45 @@ static void on_request_event(void **argv) api_free_array(args); decref(channel); xfree(e); + api_clear_error(&error); } +/// Returns the Stream that a Channel writes to. +static Stream *chan_wstream(Channel *chan) +{ + switch (chan->type) { + case kChannelTypeSocket: + return &chan->data.stream; + case kChannelTypeProc: + return chan->data.proc->in; + case kChannelTypeStdio: + return &chan->data.std.out; + case kChannelTypeInternal: + return NULL; + } + abort(); +} + +/// Returns the Stream that a Channel reads from. +static Stream *chan_rstream(Channel *chan) +{ + switch (chan->type) { + case kChannelTypeSocket: + return &chan->data.stream; + case kChannelTypeProc: + return chan->data.proc->out; + case kChannelTypeStdio: + return &chan->data.std.in; + case kChannelTypeInternal: + return NULL; + } + abort(); +} + + static bool channel_write(Channel *channel, WBuffer *buffer) { - bool success; + bool success = false; if (channel->closed) { wstream_release_wbuffer(buffer); @@ -481,16 +600,15 @@ static bool channel_write(Channel *channel, WBuffer *buffer) switch (channel->type) { case kChannelTypeSocket: - success = wstream_write(&channel->data.stream, buffer); - break; case kChannelTypeProc: - success = wstream_write(channel->data.proc->in, buffer); - break; case kChannelTypeStdio: - success = wstream_write(&channel->data.std.out, buffer); + success = wstream_write(chan_wstream(channel), buffer); + break; + case kChannelTypeInternal: + incref(channel); + CREATE_EVENT(channel->events, internal_read_event, 2, channel, buffer); + success = true; break; - default: - abort(); } if (!success) { @@ -498,32 +616,49 @@ static bool channel_write(Channel *channel, WBuffer *buffer) char buf[256]; snprintf(buf, sizeof(buf), - "Before returning from a RPC call, channel %" PRIu64 " was " - "closed due to a failed write", + "ch %" PRIu64 ": stream write failed. " + "RPC canceled; closing channel", channel->id); - call_set_error(channel, buf); + call_set_error(channel, buf, ERROR_LOG_LEVEL); } return success; } +static void internal_read_event(void **argv) +{ + Channel *channel = argv[0]; + WBuffer *buffer = argv[1]; + + msgpack_unpacker_reserve_buffer(channel->unpacker, buffer->size); + memcpy(msgpack_unpacker_buffer(channel->unpacker), + buffer->data, buffer->size); + msgpack_unpacker_buffer_consumed(channel->unpacker, buffer->size); + + parse_msgpack(channel); + + decref(channel); + wstream_release_wbuffer(buffer); +} + static void send_error(Channel *channel, uint64_t id, char *err) { Error e = ERROR_INIT; - api_set_error(&e, Exception, "%s", err); + api_set_error(&e, kErrorTypeException, "%s", err); channel_write(channel, serialize_response(channel->id, id, &e, NIL, &out_buffer)); + api_clear_error(&e); } static void send_request(Channel *channel, uint64_t id, - char *name, + const char *name, Array args) { - String method = {.size = strlen(name), .data = name}; + const String method = cstr_as_string((char *)name); channel_write(channel, serialize_request(channel->id, id, method, @@ -533,10 +668,10 @@ static void send_request(Channel *channel, } static void send_event(Channel *channel, - char *name, + const char *name, Array args) { - String method = {.size = strlen(name), .data = name}; + const String method = cstr_as_string((char *)name); channel_write(channel, serialize_request(channel->id, 0, method, @@ -545,7 +680,7 @@ static void send_event(Channel *channel, 1)); } -static void broadcast_event(char *name, Array args) +static void broadcast_event(const char *name, Array args) { kvec_t(Channel *) subscribed = KV_INITIAL_VALUE; Channel *channel; @@ -561,7 +696,7 @@ static void broadcast_event(char *name, Array args) goto end; } - String method = {.size = strlen(name), .data = name}; + const String method = cstr_as_string((char *)name); WBuffer *buffer = serialize_request(0, 0, method, @@ -622,8 +757,9 @@ static void close_channel(Channel *channel) stream_close(&channel->data.std.out, NULL, NULL); multiqueue_put(main_loop.fast_events, exit_event, 1, channel); return; - default: - abort(); + case kChannelTypeInternal: + // nothing to free. + break; } decref(channel); @@ -664,9 +800,12 @@ static void close_cb(Stream *stream, void *data) decref(data); } +/// @param source description of source function, rplugin name, TCP addr, etc static Channel *register_channel(ChannelType type, uint64_t id, - MultiQueue *events) + MultiQueue *events, char *source) { + // Jobs and channels share the same id namespace. + assert(id == 0 || !pmap_get(uint64_t)(channels, id)); Channel *rv = xmalloc(sizeof(Channel)); rv->events = events ? events : multiqueue_new_child(main_loop.events); rv->type = type; @@ -680,6 +819,14 @@ static Channel *register_channel(ChannelType type, uint64_t id, kv_init(rv->call_stack); kv_init(rv->delayed_notifications); pmap_put(uint64_t)(channels, rv->id, rv); + + ILOG("new channel %" PRIu64 " (%s): %s", rv->id, + (type == kChannelTypeProc ? "proc" + : (type == kChannelTypeSocket ? "socket" + : (type == kChannelTypeStdio ? "stdio" + : (type == kChannelTypeInternal ? "internal" : "?")))), + (source ? source : "?")); + return rv; } @@ -714,13 +861,14 @@ static void complete_call(msgpack_object *obj, Channel *channel) } } -static void call_set_error(Channel *channel, char *msg) +static void call_set_error(Channel *channel, char *msg, int loglevel) { - ELOG("msgpack-rpc: %s", msg); + LOG(loglevel, "RPC: %s", msg); for (size_t i = 0; i < kv_size(channel->call_stack); i++) { ChannelCallFrame *frame = kv_A(channel->call_stack, i); frame->returned = true; frame->errored = true; + api_free_object(frame->result); frame->result = STRING_OBJ(cstr_to_string(msg)); } @@ -729,7 +877,7 @@ static void call_set_error(Channel *channel, char *msg) static WBuffer *serialize_request(uint64_t channel_id, uint64_t request_id, - String method, + const String method, Array args, msgpack_sbuffer *sbuffer, size_t refcount) @@ -789,10 +937,10 @@ static void decref(Channel *channel) } #if MIN_LOG_LEVEL <= DEBUG_LOG_LEVEL -#define REQ "[request] " -#define RES "[response] " -#define NOT "[notification] " -#define ERR "[error] " +#define REQ "[request] " +#define RES "[response] " +#define NOT "[notify] " +#define ERR "[error] " // Cannot define array with negative offsets, so this one is needed to be added // to MSGPACK_UNPACK_\* values. @@ -810,7 +958,7 @@ static void log_server_msg(uint64_t channel_id, { msgpack_unpacked unpacked; msgpack_unpacked_init(&unpacked); - DLOGN("[msgpack-rpc] nvim -> client(%" PRIu64 ") ", channel_id); + DLOGN("RPC ->ch %" PRIu64 ": ", channel_id); const msgpack_unpack_return result = msgpack_unpack_next(&unpacked, packed->data, packed->size, NULL); switch (result) { @@ -847,7 +995,7 @@ static void log_client_msg(uint64_t channel_id, bool is_request, msgpack_object msg) { - DLOGN("[msgpack-rpc] client(%" PRIu64 ") -> nvim ", channel_id); + DLOGN("RPC <-ch %" PRIu64 ": ", channel_id); log_lock(); FILE *f = open_log_file(); fprintf(f, is_request ? REQ : RES); diff --git a/src/nvim/msgpack_rpc/channel.h b/src/nvim/msgpack_rpc/channel.h index 0d92976d02..f8fe6f129b 100644 --- a/src/nvim/msgpack_rpc/channel.h +++ b/src/nvim/msgpack_rpc/channel.h @@ -11,6 +11,11 @@ #define METHOD_MAXLEN 512 +/// HACK: os/input.c drains this queue immediately before blocking for input. +/// Events on this queue are async-safe, but they need the resolved state +/// of os_inchar(), so they are processed "just-in-time". +MultiQueue *ch_before_blocking_events; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "msgpack_rpc/channel.h.generated.h" #endif diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c index 5137b375f0..fecae11d45 100644 --- a/src/nvim/msgpack_rpc/helpers.c +++ b/src/nvim/msgpack_rpc/helpers.c @@ -1,3 +1,6 @@ +// 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 <stdint.h> #include <stdbool.h> #include <inttypes.h> @@ -21,12 +24,12 @@ static msgpack_zone zone; static msgpack_sbuffer sbuffer; #define HANDLE_TYPE_CONVERSION_IMPL(t, lt) \ - bool msgpack_rpc_to_##lt(const msgpack_object *const obj, \ - Integer *const arg) \ - FUNC_ATTR_NONNULL_ALL \ + static bool msgpack_rpc_to_##lt(const msgpack_object *const obj, \ + Integer *const arg) \ + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT \ { \ if (obj->type != MSGPACK_OBJECT_EXT \ - || obj->via.ext.type != kObjectType##t) { \ + || obj->via.ext.type + EXT_OBJECT_TYPE_SHIFT != kObjectType##t) { \ return false; \ } \ \ @@ -45,13 +48,14 @@ static msgpack_sbuffer sbuffer; return true; \ } \ \ - void msgpack_rpc_from_##lt(Integer o, msgpack_packer *res) \ + static void msgpack_rpc_from_##lt(Integer o, msgpack_packer *res) \ FUNC_ATTR_NONNULL_ARG(2) \ { \ msgpack_packer pac; \ msgpack_packer_init(&pac, &sbuffer, msgpack_sbuffer_write); \ msgpack_pack_int64(&pac, (handle_T)o); \ - msgpack_pack_ext(res, sbuffer.size, kObjectType##t); \ + msgpack_pack_ext(res, sbuffer.size, \ + kObjectType##t - EXT_OBJECT_TYPE_SHIFT); \ msgpack_pack_ext_body(res, sbuffer.data, sbuffer.size); \ msgpack_sbuffer_clear(&sbuffer); \ } @@ -73,7 +77,7 @@ typedef struct { size_t idx; } MPToAPIObjectStackItem; -/// Convert type used by msgpack parser to Neovim own API type +/// Convert type used by msgpack parser to Nvim API type. /// /// @param[in] obj Msgpack value to convert. /// @param[out] arg Location where result of conversion will be saved. @@ -84,7 +88,12 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg) { bool ret = true; kvec_t(MPToAPIObjectStackItem) stack = KV_INITIAL_VALUE; - kv_push(stack, ((MPToAPIObjectStackItem) { obj, arg, false, 0 })); + kv_push(stack, ((MPToAPIObjectStackItem) { + .mobj = obj, + .aobj = arg, + .container = false, + .idx = 0, + })); while (ret && kv_size(stack)) { MPToAPIObjectStackItem cur = kv_last(stack); if (!cur.container) { @@ -114,10 +123,16 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg) } break; } - case MSGPACK_OBJECT_FLOAT: { +#ifdef NVIM_MSGPACK_HAS_FLOAT32 + case MSGPACK_OBJECT_FLOAT32: + case MSGPACK_OBJECT_FLOAT64: +#else + case MSGPACK_OBJECT_FLOAT: +#endif + { STATIC_ASSERT(sizeof(Float) == sizeof(cur.mobj->via.f64), "Msgpack floating-point size does not match API integer"); - *cur.aobj = FLOATING_OBJ(cur.mobj->via.f64); + *cur.aobj = FLOAT_OBJ(cur.mobj->via.f64); break; } #define STR_CASE(type, attr, obj, dest, conv) \ @@ -181,7 +196,12 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg) case MSGPACK_OBJECT_BOOLEAN: case MSGPACK_OBJECT_POSITIVE_INTEGER: case MSGPACK_OBJECT_NEGATIVE_INTEGER: +#ifdef NVIM_MSGPACK_HAS_FLOAT32 + case MSGPACK_OBJECT_FLOAT32: + case MSGPACK_OBJECT_FLOAT64: +#else case MSGPACK_OBJECT_FLOAT: +#endif case MSGPACK_OBJECT_EXT: case MSGPACK_OBJECT_MAP: case MSGPACK_OBJECT_ARRAY: { @@ -211,7 +231,7 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg) break; } case MSGPACK_OBJECT_EXT: { - switch (cur.mobj->via.ext.type) { + switch ((ObjectType)(cur.mobj->via.ext.type + EXT_OBJECT_TYPE_SHIFT)) { case kObjectTypeBuffer: { cur.aobj->type = kObjectTypeBuffer; ret = msgpack_rpc_to_buffer(cur.mobj, &cur.aobj->data.integer); @@ -227,6 +247,15 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg) ret = msgpack_rpc_to_tabpage(cur.mobj, &cur.aobj->data.integer); break; } + case kObjectTypeNil: + case kObjectTypeBoolean: + case kObjectTypeInteger: + case kObjectTypeFloat: + case kObjectTypeString: + case kObjectTypeArray: + case kObjectTypeDictionary: { + break; + } } break; } @@ -322,7 +351,7 @@ void msgpack_rpc_from_float(Float result, msgpack_packer *res) msgpack_pack_double(res, result); } -void msgpack_rpc_from_string(String result, msgpack_packer *res) +void msgpack_rpc_from_string(const String result, msgpack_packer *res) FUNC_ATTR_NONNULL_ARG(2) { msgpack_pack_str(res, result.size); @@ -337,7 +366,7 @@ typedef struct { size_t idx; } APIToMPObjectStackItem; -/// Convert type used by Neovim API to msgpack +/// Convert type used by Nvim API to msgpack type. /// /// @param[in] result Object to convert. /// @param[out] res Structure that defines where conversion results are saved. @@ -350,6 +379,9 @@ void msgpack_rpc_from_object(const Object result, msgpack_packer *const res) kv_push(stack, ((APIToMPObjectStackItem) { &result, false, 0 })); while (kv_size(stack)) { APIToMPObjectStackItem cur = kv_last(stack); + STATIC_ASSERT(kObjectTypeWindow == kObjectTypeBuffer + 1 + && kObjectTypeTabpage == kObjectTypeWindow + 1, + "Buffer, window and tabpage enum items are in order"); switch (cur.aobj->type) { case kObjectTypeNil: { msgpack_pack_nil(res); @@ -461,8 +493,7 @@ Object msgpack_rpc_handle_missing_method(uint64_t channel_id, Array args, Error *error) { - snprintf(error->msg, sizeof(error->msg), "Invalid method name"); - error->set = true; + api_set_error(error, kErrorTypeException, "Invalid method name"); return NIL; } @@ -471,14 +502,13 @@ Object msgpack_rpc_handle_invalid_arguments(uint64_t channel_id, Array args, Error *error) { - snprintf(error->msg, sizeof(error->msg), "Invalid method arguments"); - error->set = true; + api_set_error(error, kErrorTypeException, "Invalid method arguments"); return NIL; } /// Serializes a msgpack-rpc request or notification(id == 0) void msgpack_rpc_serialize_request(uint64_t request_id, - String method, + const String method, Array args, msgpack_packer *pac) FUNC_ATTR_NONNULL_ARG(4) @@ -505,7 +535,7 @@ void msgpack_rpc_serialize_response(uint64_t response_id, msgpack_pack_int(pac, 1); msgpack_pack_uint64(pac, response_id); - if (err->set) { + if (ERROR_SET(err)) { // error represented by a [type, message] array msgpack_pack_array(pac, 2); msgpack_rpc_from_integer(err->type, pac); @@ -558,49 +588,49 @@ void msgpack_rpc_validate(uint64_t *response_id, *response_id = NO_RESPONSE; // Validate the basic structure of the msgpack-rpc payload if (req->type != MSGPACK_OBJECT_ARRAY) { - api_set_error(err, Validation, _("Message is not an array")); + api_set_error(err, kErrorTypeValidation, "Message is not an array"); return; } if (req->via.array.size == 0) { - api_set_error(err, Validation, _("Message is empty")); + api_set_error(err, kErrorTypeValidation, "Message is empty"); return; } if (req->via.array.ptr[0].type != MSGPACK_OBJECT_POSITIVE_INTEGER) { - api_set_error(err, Validation, _("Message type must be an integer")); + api_set_error(err, kErrorTypeValidation, "Message type must be an integer"); return; } uint64_t type = req->via.array.ptr[0].via.u64; if (type != kMessageTypeRequest && type != kMessageTypeNotification) { - api_set_error(err, Validation, _("Unknown message type")); + api_set_error(err, kErrorTypeValidation, "Unknown message type"); return; } if ((type == kMessageTypeRequest && req->via.array.size != 4) || (type == kMessageTypeNotification && req->via.array.size != 3)) { - api_set_error(err, Validation, _("Request array size should be 4 (request) " - "or 3 (notification)")); + api_set_error(err, kErrorTypeValidation, + "Request array size must be 4 (request) or 3 (notification)"); return; } if (type == kMessageTypeRequest) { msgpack_object *id_obj = msgpack_rpc_msg_id(req); if (!id_obj) { - api_set_error(err, Validation, _("ID must be a positive integer")); + api_set_error(err, kErrorTypeValidation, "ID must be a positive integer"); return; } *response_id = id_obj->via.u64; } if (!msgpack_rpc_method(req)) { - api_set_error(err, Validation, _("Method must be a string")); + api_set_error(err, kErrorTypeValidation, "Method must be a string"); return; } if (!msgpack_rpc_args(req)) { - api_set_error(err, Validation, _("Parameters must be an array")); + api_set_error(err, kErrorTypeValidation, "Parameters must be an array"); return; } } diff --git a/src/nvim/msgpack_rpc/helpers.h b/src/nvim/msgpack_rpc/helpers.h index 7d9f114140..0e4cd1be6d 100644 --- a/src/nvim/msgpack_rpc/helpers.h +++ b/src/nvim/msgpack_rpc/helpers.h @@ -9,6 +9,13 @@ #include "nvim/event/wstream.h" #include "nvim/api/private/defs.h" +/// Value by which objects represented as EXT type are shifted +/// +/// Subtracted when packing, added when unpacking. Used to allow moving +/// buffer/window/tabpage block inside ObjectType enum. This block yet cannot be +/// split or reordered. +#define EXT_OBJECT_TYPE_SHIFT kObjectTypeBuffer + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "msgpack_rpc/helpers.h.generated.h" #endif diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index d7c2926a0f..1e0cc27886 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -1,3 +1,6 @@ +// 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 <stdlib.h> #include <string.h> @@ -94,39 +97,61 @@ char *server_address_new(void) #endif } -/// Starts listening for API calls on the TCP address or pipe path `endpoint`. +/// Check if this instance owns a pipe address. +/// The argument must already be resolved to an absolute path! +bool server_owns_pipe_address(const char *path) +{ + for (int i = 0; i < watchers.ga_len; i++) { + if (!strcmp(path, ((SocketWatcher **)watchers.ga_data)[i]->addr)) { + return true; + } + } + return false; +} + +/// Starts listening for API calls. +/// /// The socket type is determined by parsing `endpoint`: If it's a valid IPv4 -/// address in 'ip[:port]' format, then it will be TCP socket. The port is -/// optional and if omitted defaults to NVIM_DEFAULT_TCP_PORT. Otherwise it -/// will be a unix socket or named pipe. +/// or IPv6 address in 'ip:[port]' format, then it will be a TCP socket. +/// Otherwise it will be a Unix socket or named pipe (Windows). +/// +/// If no port is given, a random one will be assigned. /// -/// @param endpoint Address of the server. Either a 'ip[:port]' string or an -/// arbitrary identifier (trimmed to 256 bytes) for the unix socket or -/// named pipe. +/// @param endpoint Address of the server. Either a 'ip:[port]' string or an +/// arbitrary identifier (trimmed to 256 bytes) for the Unix +/// socket or named pipe. /// @returns 0 on success, 1 on a regular error, and negative errno -/// on failure to bind or connect. +/// on failure to bind or listen. int server_start(const char *endpoint) { - if (endpoint == NULL) { - ELOG("Attempting to start server on NULL endpoint"); + if (endpoint == NULL || endpoint[0] == '\0') { + WLOG("Empty or NULL endpoint"); return 1; } SocketWatcher *watcher = xmalloc(sizeof(SocketWatcher)); - socket_watcher_init(&main_loop, watcher, endpoint, NULL); + + int result = socket_watcher_init(&main_loop, watcher, endpoint); + if (result < 0) { + xfree(watcher); + return result; + } // Check if a watcher for the endpoint already exists for (int i = 0; i < watchers.ga_len; i++) { if (!strcmp(watcher->addr, ((SocketWatcher **)watchers.ga_data)[i]->addr)) { ELOG("Already listening on %s", watcher->addr); + if (watcher->stream->type == UV_TCP) { + uv_freeaddrinfo(watcher->uv.tcp.addrinfo); + } socket_watcher_close(watcher, free_server); return 1; } } - int result = socket_watcher_start(watcher, MAX_CONNECTIONS, connection_cb); + result = socket_watcher_start(watcher, MAX_CONNECTIONS, connection_cb); if (result < 0) { - ELOG("Failed to start server: %s", uv_strerror(result)); + WLOG("Failed to start server: %s", uv_strerror(result)); socket_watcher_close(watcher, free_server); return result; } diff --git a/src/nvim/msgpack_rpc/server.h b/src/nvim/msgpack_rpc/server.h index f1a6703938..5446e40e0b 100644 --- a/src/nvim/msgpack_rpc/server.h +++ b/src/nvim/msgpack_rpc/server.h @@ -1,6 +1,8 @@ #ifndef NVIM_MSGPACK_RPC_SERVER_H #define NVIM_MSGPACK_RPC_SERVER_H +#include <stdio.h> + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "msgpack_rpc/server.h.generated.h" #endif diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 227bfbe779..f9017164af 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1,3 +1,6 @@ +// 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 + /* * normal.c: Contains the main routine for processing characters in command * mode. Communicates closely with the code in ops.c to handle @@ -10,6 +13,7 @@ #include <stdbool.h> #include <stdlib.h> +#include "nvim/log.h" #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/normal.h" @@ -45,6 +49,7 @@ #include "nvim/screen.h" #include "nvim/search.h" #include "nvim/spell.h" +#include "nvim/spellfile.h" #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tag.h" @@ -152,196 +157,196 @@ static const struct nv_cmd { short cmd_arg; /* value for ca.arg */ } nv_cmds[] = { - {NUL, nv_error, 0, 0}, - {Ctrl_A, nv_addsub, 0, 0}, - {Ctrl_B, nv_page, NV_STS, BACKWARD}, - {Ctrl_C, nv_esc, 0, true}, - {Ctrl_D, nv_halfpage, 0, 0}, - {Ctrl_E, nv_scroll_line, 0, true}, - {Ctrl_F, nv_page, NV_STS, FORWARD}, - {Ctrl_G, nv_ctrlg, 0, 0}, - {Ctrl_H, nv_ctrlh, 0, 0}, - {Ctrl_I, nv_pcmark, 0, 0}, - {NL, nv_down, 0, false}, - {Ctrl_K, nv_error, 0, 0}, - {Ctrl_L, nv_clear, 0, 0}, - {Ctrl_M, nv_down, 0, true}, - {Ctrl_N, nv_down, NV_STS, false}, - {Ctrl_O, nv_ctrlo, 0, 0}, - {Ctrl_P, nv_up, NV_STS, false}, - {Ctrl_Q, nv_visual, 0, false}, - {Ctrl_R, nv_redo, 0, 0}, - {Ctrl_S, nv_ignore, 0, 0}, - {Ctrl_T, nv_tagpop, NV_NCW, 0}, - {Ctrl_U, nv_halfpage, 0, 0}, - {Ctrl_V, nv_visual, 0, false}, - {'V', nv_visual, 0, false}, - {'v', nv_visual, 0, false}, - {Ctrl_W, nv_window, 0, 0}, - {Ctrl_X, nv_addsub, 0, 0}, - {Ctrl_Y, nv_scroll_line, 0, false}, - {Ctrl_Z, nv_suspend, 0, 0}, - {ESC, nv_esc, 0, false}, - {Ctrl_BSL, nv_normal, NV_NCH_ALW, 0}, - {Ctrl_RSB, nv_ident, NV_NCW, 0}, - {Ctrl_HAT, nv_hat, NV_NCW, 0}, - {Ctrl__, nv_error, 0, 0}, - {' ', nv_right, 0, 0}, - {'!', nv_operator, 0, 0}, - {'"', nv_regname, NV_NCH_NOP|NV_KEEPREG, 0}, - {'#', nv_ident, 0, 0}, - {'$', nv_dollar, 0, 0}, - {'%', nv_percent, 0, 0}, - {'&', nv_optrans, 0, 0}, - {'\'', nv_gomark, NV_NCH_ALW, true}, - {'(', nv_brace, 0, BACKWARD}, - {')', nv_brace, 0, FORWARD}, - {'*', nv_ident, 0, 0}, - {'+', nv_down, 0, true}, - {',', nv_csearch, 0, true}, - {'-', nv_up, 0, true}, - {'.', nv_dot, NV_KEEPREG, 0}, - {'/', nv_search, 0, false}, - {'0', nv_beginline, 0, 0}, - {'1', nv_ignore, 0, 0}, - {'2', nv_ignore, 0, 0}, - {'3', nv_ignore, 0, 0}, - {'4', nv_ignore, 0, 0}, - {'5', nv_ignore, 0, 0}, - {'6', nv_ignore, 0, 0}, - {'7', nv_ignore, 0, 0}, - {'8', nv_ignore, 0, 0}, - {'9', nv_ignore, 0, 0}, - {':', nv_colon, 0, 0}, - {';', nv_csearch, 0, false}, - {'<', nv_operator, NV_RL, 0}, - {'=', nv_operator, 0, 0}, - {'>', nv_operator, NV_RL, 0}, - {'?', nv_search, 0, false}, - {'@', nv_at, NV_NCH_NOP, false}, - {'A', nv_edit, 0, 0}, - {'B', nv_bck_word, 0, 1}, - {'C', nv_abbrev, NV_KEEPREG, 0}, - {'D', nv_abbrev, NV_KEEPREG, 0}, - {'E', nv_wordcmd, 0, true}, - {'F', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD}, - {'G', nv_goto, 0, true}, - {'H', nv_scroll, 0, 0}, - {'I', nv_edit, 0, 0}, - {'J', nv_join, 0, 0}, - {'K', nv_ident, 0, 0}, - {'L', nv_scroll, 0, 0}, - {'M', nv_scroll, 0, 0}, - {'N', nv_next, 0, SEARCH_REV}, - {'O', nv_open, 0, 0}, - {'P', nv_put, 0, 0}, - {'Q', nv_exmode, NV_NCW, 0}, - {'R', nv_Replace, 0, false}, - {'S', nv_subst, NV_KEEPREG, 0}, - {'T', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD}, - {'U', nv_Undo, 0, 0}, - {'W', nv_wordcmd, 0, true}, - {'X', nv_abbrev, NV_KEEPREG, 0}, - {'Y', nv_abbrev, NV_KEEPREG, 0}, - {'Z', nv_Zet, NV_NCH_NOP|NV_NCW, 0}, - {'[', nv_brackets, NV_NCH_ALW, BACKWARD}, - {'\\', nv_error, 0, 0}, - {']', nv_brackets, NV_NCH_ALW, FORWARD}, - {'^', nv_beginline, 0, BL_WHITE | BL_FIX}, - {'_', nv_lineop, 0, 0}, - {'`', nv_gomark, NV_NCH_ALW, false}, - {'a', nv_edit, NV_NCH, 0}, - {'b', nv_bck_word, 0, 0}, - {'c', nv_operator, 0, 0}, - {'d', nv_operator, 0, 0}, - {'e', nv_wordcmd, 0, false}, - {'f', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD}, - {'g', nv_g_cmd, NV_NCH_ALW, false}, - {'h', nv_left, NV_RL, 0}, - {'i', nv_edit, NV_NCH, 0}, - {'j', nv_down, 0, false}, - {'k', nv_up, 0, false}, - {'l', nv_right, NV_RL, 0}, - {'m', nv_mark, NV_NCH_NOP, 0}, - {'n', nv_next, 0, 0}, - {'o', nv_open, 0, 0}, - {'p', nv_put, 0, 0}, - {'q', nv_record, NV_NCH, 0}, - {'r', nv_replace, NV_NCH_NOP|NV_LANG, 0}, - {'s', nv_subst, NV_KEEPREG, 0}, - {'t', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD}, - {'u', nv_undo, 0, 0}, - {'w', nv_wordcmd, 0, false}, - {'x', nv_abbrev, NV_KEEPREG, 0}, - {'y', nv_operator, 0, 0}, - {'z', nv_zet, NV_NCH_ALW, 0}, - {'{', nv_findpar, 0, BACKWARD}, - {'|', nv_pipe, 0, 0}, - {'}', nv_findpar, 0, FORWARD}, - {'~', nv_tilde, 0, 0}, - - /* pound sign */ - {POUND, nv_ident, 0, 0}, - {K_MOUSEUP, nv_mousescroll, 0, MSCR_UP}, - {K_MOUSEDOWN, nv_mousescroll, 0, MSCR_DOWN}, - {K_MOUSELEFT, nv_mousescroll, 0, MSCR_LEFT}, - {K_MOUSERIGHT, nv_mousescroll, 0, MSCR_RIGHT}, - {K_LEFTMOUSE, nv_mouse, 0, 0}, - {K_LEFTMOUSE_NM, nv_mouse, 0, 0}, - {K_LEFTDRAG, nv_mouse, 0, 0}, - {K_LEFTRELEASE, nv_mouse, 0, 0}, - {K_LEFTRELEASE_NM, nv_mouse, 0, 0}, - {K_MIDDLEMOUSE, nv_mouse, 0, 0}, - {K_MIDDLEDRAG, nv_mouse, 0, 0}, - {K_MIDDLERELEASE, nv_mouse, 0, 0}, - {K_RIGHTMOUSE, nv_mouse, 0, 0}, - {K_RIGHTDRAG, nv_mouse, 0, 0}, - {K_RIGHTRELEASE, nv_mouse, 0, 0}, - {K_X1MOUSE, nv_mouse, 0, 0}, - {K_X1DRAG, nv_mouse, 0, 0}, - {K_X1RELEASE, nv_mouse, 0, 0}, - {K_X2MOUSE, nv_mouse, 0, 0}, - {K_X2DRAG, nv_mouse, 0, 0}, - {K_X2RELEASE, nv_mouse, 0, 0}, - {K_IGNORE, nv_ignore, NV_KEEPREG, 0}, - {K_NOP, nv_nop, 0, 0}, - {K_INS, nv_edit, 0, 0}, - {K_KINS, nv_edit, 0, 0}, - {K_BS, nv_ctrlh, 0, 0}, - {K_UP, nv_up, NV_SSS|NV_STS, false}, - {K_S_UP, nv_page, NV_SS, BACKWARD}, - {K_DOWN, nv_down, NV_SSS|NV_STS, false}, - {K_S_DOWN, nv_page, NV_SS, FORWARD}, - {K_LEFT, nv_left, NV_SSS|NV_STS|NV_RL, 0}, - {K_S_LEFT, nv_bck_word, NV_SS|NV_RL, 0}, - {K_C_LEFT, nv_bck_word, NV_SSS|NV_RL|NV_STS, 1}, - {K_RIGHT, nv_right, NV_SSS|NV_STS|NV_RL, 0}, - {K_S_RIGHT, nv_wordcmd, NV_SS|NV_RL, false}, - {K_C_RIGHT, nv_wordcmd, NV_SSS|NV_RL|NV_STS, true}, - {K_PAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD}, - {K_KPAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD}, - {K_PAGEDOWN, nv_page, NV_SSS|NV_STS, FORWARD}, - {K_KPAGEDOWN, nv_page, NV_SSS|NV_STS, FORWARD}, - {K_END, nv_end, NV_SSS|NV_STS, false}, - {K_KEND, nv_end, NV_SSS|NV_STS, false}, - {K_S_END, nv_end, NV_SS, false}, - {K_C_END, nv_end, NV_SSS|NV_STS, true}, - {K_HOME, nv_home, NV_SSS|NV_STS, 0}, - {K_KHOME, nv_home, NV_SSS|NV_STS, 0}, - {K_S_HOME, nv_home, NV_SS, 0}, - {K_C_HOME, nv_goto, NV_SSS|NV_STS, false}, - {K_DEL, nv_abbrev, 0, 0}, - {K_KDEL, nv_abbrev, 0, 0}, - {K_UNDO, nv_kundo, 0, 0}, - {K_HELP, nv_help, NV_NCW, 0}, - {K_F1, nv_help, NV_NCW, 0}, - {K_XF1, nv_help, NV_NCW, 0}, - {K_SELECT, nv_select, 0, 0}, - {K_F8, farsi_fkey, 0, 0}, - {K_F9, farsi_fkey, 0, 0}, - {K_EVENT, nv_event, NV_KEEPREG, 0}, - {K_FOCUSGAINED, nv_focusgained, NV_KEEPREG, 0}, - {K_FOCUSLOST, nv_focuslost, NV_KEEPREG, 0}, + { NUL, nv_error, 0, 0 }, + { Ctrl_A, nv_addsub, 0, 0 }, + { Ctrl_B, nv_page, NV_STS, BACKWARD }, + { Ctrl_C, nv_esc, 0, true }, + { Ctrl_D, nv_halfpage, 0, 0 }, + { Ctrl_E, nv_scroll_line, 0, true }, + { Ctrl_F, nv_page, NV_STS, FORWARD }, + { Ctrl_G, nv_ctrlg, 0, 0 }, + { Ctrl_H, nv_ctrlh, 0, 0 }, + { Ctrl_I, nv_pcmark, 0, 0 }, + { NL, nv_down, 0, false }, + { Ctrl_K, nv_error, 0, 0 }, + { Ctrl_L, nv_clear, 0, 0 }, + { Ctrl_M, nv_down, 0, true }, + { Ctrl_N, nv_down, NV_STS, false }, + { Ctrl_O, nv_ctrlo, 0, 0 }, + { Ctrl_P, nv_up, NV_STS, false }, + { Ctrl_Q, nv_visual, 0, false }, + { Ctrl_R, nv_redo, 0, 0 }, + { Ctrl_S, nv_ignore, 0, 0 }, + { Ctrl_T, nv_tagpop, NV_NCW, 0 }, + { Ctrl_U, nv_halfpage, 0, 0 }, + { Ctrl_V, nv_visual, 0, false }, + { 'V', nv_visual, 0, false }, + { 'v', nv_visual, 0, false }, + { Ctrl_W, nv_window, 0, 0 }, + { Ctrl_X, nv_addsub, 0, 0 }, + { Ctrl_Y, nv_scroll_line, 0, false }, + { Ctrl_Z, nv_suspend, 0, 0 }, + { ESC, nv_esc, 0, false }, + { Ctrl_BSL, nv_normal, NV_NCH_ALW, 0 }, + { Ctrl_RSB, nv_ident, NV_NCW, 0 }, + { Ctrl_HAT, nv_hat, NV_NCW, 0 }, + { Ctrl__, nv_error, 0, 0 }, + { ' ', nv_right, 0, 0 }, + { '!', nv_operator, 0, 0 }, + { '"', nv_regname, NV_NCH_NOP|NV_KEEPREG, 0 }, + { '#', nv_ident, 0, 0 }, + { '$', nv_dollar, 0, 0 }, + { '%', nv_percent, 0, 0 }, + { '&', nv_optrans, 0, 0 }, + { '\'', nv_gomark, NV_NCH_ALW, true }, + { '(', nv_brace, 0, BACKWARD }, + { ')', nv_brace, 0, FORWARD }, + { '*', nv_ident, 0, 0 }, + { '+', nv_down, 0, true }, + { ',', nv_csearch, 0, true }, + { '-', nv_up, 0, true }, + { '.', nv_dot, NV_KEEPREG, 0 }, + { '/', nv_search, 0, false }, + { '0', nv_beginline, 0, 0 }, + { '1', nv_ignore, 0, 0 }, + { '2', nv_ignore, 0, 0 }, + { '3', nv_ignore, 0, 0 }, + { '4', nv_ignore, 0, 0 }, + { '5', nv_ignore, 0, 0 }, + { '6', nv_ignore, 0, 0 }, + { '7', nv_ignore, 0, 0 }, + { '8', nv_ignore, 0, 0 }, + { '9', nv_ignore, 0, 0 }, + { ':', nv_colon, 0, 0 }, + { ';', nv_csearch, 0, false }, + { '<', nv_operator, NV_RL, 0 }, + { '=', nv_operator, 0, 0 }, + { '>', nv_operator, NV_RL, 0 }, + { '?', nv_search, 0, false }, + { '@', nv_at, NV_NCH_NOP, false }, + { 'A', nv_edit, 0, 0 }, + { 'B', nv_bck_word, 0, 1 }, + { 'C', nv_abbrev, NV_KEEPREG, 0 }, + { 'D', nv_abbrev, NV_KEEPREG, 0 }, + { 'E', nv_wordcmd, 0, true }, + { 'F', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD }, + { 'G', nv_goto, 0, true }, + { 'H', nv_scroll, 0, 0 }, + { 'I', nv_edit, 0, 0 }, + { 'J', nv_join, 0, 0 }, + { 'K', nv_ident, 0, 0 }, + { 'L', nv_scroll, 0, 0 }, + { 'M', nv_scroll, 0, 0 }, + { 'N', nv_next, 0, SEARCH_REV }, + { 'O', nv_open, 0, 0 }, + { 'P', nv_put, 0, 0 }, + { 'Q', nv_exmode, NV_NCW, 0 }, + { 'R', nv_Replace, 0, false }, + { 'S', nv_subst, NV_KEEPREG, 0 }, + { 'T', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD }, + { 'U', nv_Undo, 0, 0 }, + { 'W', nv_wordcmd, 0, true }, + { 'X', nv_abbrev, NV_KEEPREG, 0 }, + { 'Y', nv_abbrev, NV_KEEPREG, 0 }, + { 'Z', nv_Zet, NV_NCH_NOP|NV_NCW, 0 }, + { '[', nv_brackets, NV_NCH_ALW, BACKWARD }, + { '\\', nv_error, 0, 0 }, + { ']', nv_brackets, NV_NCH_ALW, FORWARD }, + { '^', nv_beginline, 0, BL_WHITE | BL_FIX }, + { '_', nv_lineop, 0, 0 }, + { '`', nv_gomark, NV_NCH_ALW, false }, + { 'a', nv_edit, NV_NCH, 0 }, + { 'b', nv_bck_word, 0, 0 }, + { 'c', nv_operator, 0, 0 }, + { 'd', nv_operator, 0, 0 }, + { 'e', nv_wordcmd, 0, false }, + { 'f', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD }, + { 'g', nv_g_cmd, NV_NCH_ALW, false }, + { 'h', nv_left, NV_RL, 0 }, + { 'i', nv_edit, NV_NCH, 0 }, + { 'j', nv_down, 0, false }, + { 'k', nv_up, 0, false }, + { 'l', nv_right, NV_RL, 0 }, + { 'm', nv_mark, NV_NCH_NOP, 0 }, + { 'n', nv_next, 0, 0 }, + { 'o', nv_open, 0, 0 }, + { 'p', nv_put, 0, 0 }, + { 'q', nv_record, NV_NCH, 0 }, + { 'r', nv_replace, NV_NCH_NOP|NV_LANG, 0 }, + { 's', nv_subst, NV_KEEPREG, 0 }, + { 't', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD }, + { 'u', nv_undo, 0, 0 }, + { 'w', nv_wordcmd, 0, false }, + { 'x', nv_abbrev, NV_KEEPREG, 0 }, + { 'y', nv_operator, 0, 0 }, + { 'z', nv_zet, NV_NCH_ALW, 0 }, + { '{', nv_findpar, 0, BACKWARD }, + { '|', nv_pipe, 0, 0 }, + { '}', nv_findpar, 0, FORWARD }, + { '~', nv_tilde, 0, 0 }, + + // pound sign + { POUND, nv_ident, 0, 0 }, + { K_MOUSEUP, nv_mousescroll, 0, MSCR_UP }, + { K_MOUSEDOWN, nv_mousescroll, 0, MSCR_DOWN }, + { K_MOUSELEFT, nv_mousescroll, 0, MSCR_LEFT }, + { K_MOUSERIGHT, nv_mousescroll, 0, MSCR_RIGHT }, + { K_LEFTMOUSE, nv_mouse, 0, 0 }, + { K_LEFTMOUSE_NM, nv_mouse, 0, 0 }, + { K_LEFTDRAG, nv_mouse, 0, 0 }, + { K_LEFTRELEASE, nv_mouse, 0, 0 }, + { K_LEFTRELEASE_NM, nv_mouse, 0, 0 }, + { K_MIDDLEMOUSE, nv_mouse, 0, 0 }, + { K_MIDDLEDRAG, nv_mouse, 0, 0 }, + { K_MIDDLERELEASE, nv_mouse, 0, 0 }, + { K_RIGHTMOUSE, nv_mouse, 0, 0 }, + { K_RIGHTDRAG, nv_mouse, 0, 0 }, + { K_RIGHTRELEASE, nv_mouse, 0, 0 }, + { K_X1MOUSE, nv_mouse, 0, 0 }, + { K_X1DRAG, nv_mouse, 0, 0 }, + { K_X1RELEASE, nv_mouse, 0, 0 }, + { K_X2MOUSE, nv_mouse, 0, 0 }, + { K_X2DRAG, nv_mouse, 0, 0 }, + { K_X2RELEASE, nv_mouse, 0, 0 }, + { K_IGNORE, nv_ignore, NV_KEEPREG, 0 }, + { K_NOP, nv_nop, 0, 0 }, + { K_INS, nv_edit, 0, 0 }, + { K_KINS, nv_edit, 0, 0 }, + { K_BS, nv_ctrlh, 0, 0 }, + { K_UP, nv_up, NV_SSS|NV_STS, false }, + { K_S_UP, nv_page, NV_SS, BACKWARD }, + { K_DOWN, nv_down, NV_SSS|NV_STS, false }, + { K_S_DOWN, nv_page, NV_SS, FORWARD }, + { K_LEFT, nv_left, NV_SSS|NV_STS|NV_RL, 0 }, + { K_S_LEFT, nv_bck_word, NV_SS|NV_RL, 0 }, + { K_C_LEFT, nv_bck_word, NV_SSS|NV_RL|NV_STS, 1 }, + { K_RIGHT, nv_right, NV_SSS|NV_STS|NV_RL, 0 }, + { K_S_RIGHT, nv_wordcmd, NV_SS|NV_RL, false }, + { K_C_RIGHT, nv_wordcmd, NV_SSS|NV_RL|NV_STS, true }, + { K_PAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD }, + { K_KPAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD }, + { K_PAGEDOWN, nv_page, NV_SSS|NV_STS, FORWARD }, + { K_KPAGEDOWN, nv_page, NV_SSS|NV_STS, FORWARD }, + { K_END, nv_end, NV_SSS|NV_STS, false }, + { K_KEND, nv_end, NV_SSS|NV_STS, false }, + { K_S_END, nv_end, NV_SS, false }, + { K_C_END, nv_end, NV_SSS|NV_STS, true }, + { K_HOME, nv_home, NV_SSS|NV_STS, 0 }, + { K_KHOME, nv_home, NV_SSS|NV_STS, 0 }, + { K_S_HOME, nv_home, NV_SS, 0 }, + { K_C_HOME, nv_goto, NV_SSS|NV_STS, false }, + { K_DEL, nv_abbrev, 0, 0 }, + { K_KDEL, nv_abbrev, 0, 0 }, + { K_UNDO, nv_kundo, 0, 0 }, + { K_HELP, nv_help, NV_NCW, 0 }, + { K_F1, nv_help, NV_NCW, 0 }, + { K_XF1, nv_help, NV_NCW, 0 }, + { K_SELECT, nv_select, 0, 0 }, + { K_F8, farsi_f8, 0, 0 }, + { K_F9, farsi_f9, 0, 0 }, + { K_EVENT, nv_event, NV_KEEPREG, 0 }, + { K_FOCUSGAINED, nv_focusgained, NV_KEEPREG, 0 }, + { K_FOCUSLOST, nv_focuslost, NV_KEEPREG, 0 }, }; /* Number of commands in nv_cmds[]. */ @@ -537,7 +542,7 @@ static bool normal_handle_special_visual_command(NormalState *s) return false; } -static bool normal_need_aditional_char(NormalState *s) +static bool normal_need_additional_char(NormalState *s) { int flags = nv_cmds[s->idx].cmd_flags; bool pending_op = s->oa.op_type != OP_NOP; @@ -617,7 +622,7 @@ static void normal_redraw_mode_message(NormalState *s) update_screen(0); // now reset it, otherwise it's put in the history again keep_msg = kmsg; - msg_attr(kmsg, keep_msg_attr); + msg_attr((const char *)kmsg, keep_msg_attr); xfree(kmsg); } setcursor(); @@ -641,8 +646,7 @@ static void normal_get_additional_char(NormalState *s) bool langmap_active = false; // using :lmap mappings int lang; // getting a text character - ++no_mapping; - ++allow_keys; // no mapping for nchar, but allow key codes + no_mapping++; // Don't generate a CursorHold event here, most commands can't handle // it, e.g., nv_replace(), nv_csearch(). did_cursorhold = true; @@ -680,8 +684,7 @@ static void normal_get_additional_char(NormalState *s) } if (lang && curbuf->b_p_iminsert == B_IMODE_LMAP) { // Allow mappings defined with ":lmap". - --no_mapping; - --allow_keys; + no_mapping--; if (repl) { State = LREPLACE; } else { @@ -694,9 +697,7 @@ static void normal_get_additional_char(NormalState *s) if (langmap_active) { // Undo the decrement done above - ++no_mapping; - ++allow_keys; - State = NORMAL_BUSY; + no_mapping++; } State = NORMAL_BUSY; s->need_flushbuf |= add_to_showcmd(*cp); @@ -780,8 +781,7 @@ static void normal_get_additional_char(NormalState *s) } no_mapping++; } - --no_mapping; - --allow_keys; + no_mapping--; } static void normal_invert_horizontal(NormalState *s) @@ -831,8 +831,7 @@ static bool normal_get_command_count(NormalState *s) } if (s->ctrl_w) { - ++no_mapping; - ++allow_keys; // no mapping for nchar, but keys + no_mapping++; } ++no_zero_mapping; // don't map zero here @@ -840,8 +839,7 @@ static bool normal_get_command_count(NormalState *s) LANGMAP_ADJUST(s->c, true); --no_zero_mapping; if (s->ctrl_w) { - --no_mapping; - --allow_keys; + no_mapping--; } s->need_flushbuf |= add_to_showcmd(s->c); } @@ -851,12 +849,10 @@ static bool normal_get_command_count(NormalState *s) s->ctrl_w = true; s->ca.opcount = s->ca.count0; // remember first count s->ca.count0 = 0; - ++no_mapping; - ++allow_keys; // no mapping for nchar, but keys + no_mapping++; s->c = plain_vgetc(); // get next character LANGMAP_ADJUST(s->c, true); - --no_mapping; - --allow_keys; + no_mapping--; s->need_flushbuf |= add_to_showcmd(s->c); return true; } @@ -924,9 +920,7 @@ normal_end: checkpcmark(); // check if we moved since setting pcmark xfree(s->ca.searchbuf); - if (has_mbyte) { - mb_adjust_cursor(); - } + mb_check_adjust_col(curwin); // #6203 if (curwin->w_p_scb && s->toplevel) { validate_cursor(); // may need to update w_leftcol @@ -1090,7 +1084,7 @@ static int normal_execute(VimState *state, int key) } // Get an additional character if we need one. - if (normal_need_aditional_char(s)) { + if (normal_need_additional_char(s)) { normal_get_additional_char(s); } @@ -1130,6 +1124,7 @@ static int normal_execute(VimState *state, int key) start_selection(); unshift_special(&s->ca); s->idx = find_command(s->ca.cmdchar); + assert(s->idx >= 0); } else if ((nv_cmds[s->idx].cmd_flags & NV_SSS) && (mod_mask & MOD_MASK_SHIFT)) { start_selection(); @@ -1163,7 +1158,7 @@ static void normal_check_stuff_buffer(NormalState *s) if (need_start_insertmode && goto_im() && !VIsual_active) { need_start_insertmode = false; - stuffReadbuff((uint8_t *)"i"); // start insert mode next + stuffReadbuff("i"); // start insert mode next // skip the fileinfo message now, because it would be shown // after insert mode finishes! need_fileinfo = false; @@ -1275,7 +1270,7 @@ static void normal_redraw(NormalState *s) // msg_attr_keep() will set keep_msg to NULL, must free the string here. // Don't reset keep_msg, msg_attr_keep() uses it to check for duplicates. char *p = (char *)keep_msg; - msg_attr((uint8_t *)p, keep_msg_attr); + msg_attr(p, keep_msg_attr); xfree(p); } @@ -1457,9 +1452,8 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) /* Never redo "zf" (define fold). */ if ((vim_strchr(p_cpo, CPO_YANK) != NULL || oap->op_type != OP_YANK) && ((!VIsual_active || oap->motion_force) - /* Also redo Operator-pending Visual mode mappings */ - || (VIsual_active && cap->cmdchar == ':' - && oap->op_type != OP_COLON)) + // Also redo Operator-pending Visual mode mappings. + || (cap->cmdchar == ':' && oap->op_type != OP_COLON)) && cap->cmdchar != 'D' && oap->op_type != OP_FOLD && oap->op_type != OP_FOLDOPEN @@ -1477,8 +1471,9 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) * If 'cpoptions' does not contain 'r', insert the search * pattern to really repeat the same command. */ - if (vim_strchr(p_cpo, CPO_REDO) == NULL) + if (vim_strchr(p_cpo, CPO_REDO) == NULL) { AppendToRedobuffLit(cap->searchbuf, -1); + } AppendToRedobuff(NL_STR); } else if (cap->cmdchar == ':') { /* do_cmdline() has stored the first typed line in @@ -1517,10 +1512,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) coladvance(curwin->w_curswant); } cap->count0 = redo_VIsual_count; - if (redo_VIsual_count != 0) - cap->count1 = redo_VIsual_count; - else - cap->count1 = 1; + cap->count1 = (cap->count0 == 0 ? 1 : cap->count0); } else if (VIsual_active) { if (!gui_yank) { /* Save the current VIsual area for '< and '> marks, and "gv" */ @@ -1597,6 +1589,8 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) oap->start = curwin->w_cursor; } + // Just in case lines were deleted that make the position invalid. + check_pos(curwin->w_buffer, &oap->end); oap->line_count = oap->end.lnum - oap->start.lnum + 1; /* Set "virtual_op" before resetting VIsual_active. */ @@ -1862,10 +1856,12 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) break; case OP_FILTER: - if (vim_strchr(p_cpo, CPO_FILTER) != NULL) - AppendToRedobuff((char_u *)"!\r"); /* use any last used !cmd */ - else - bangredo = true; /* do_bang() will put cmd in redo buffer */ + if (vim_strchr(p_cpo, CPO_FILTER) != NULL) { + AppendToRedobuff("!\r"); // Use any last used !cmd. + } else { + bangredo = true; // do_bang() will put cmd in redo buffer. + } + // fallthrough case OP_INDENT: case OP_COLON: @@ -1900,12 +1896,13 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) break; case OP_FORMAT: - if (*curbuf->b_p_fex != NUL) - op_formatexpr(oap); /* use expression */ - else if (*p_fp != NUL) - op_colon(oap); /* use external command */ - else - op_format(oap, false); /* use internal function */ + if (*curbuf->b_p_fex != NUL) { + op_formatexpr(oap); // use expression + } else if (*p_fp != NUL || *curbuf->b_p_fp != NUL) { + op_colon(oap); // use external command + } else { + op_format(oap, false); // use internal function + } break; case OP_FORMAT2: @@ -1913,7 +1910,10 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) break; case OP_FUNCTION: - op_function(oap); /* call 'operatorfunc' */ + // Restore linebreak, so that when the user edits it looks as + // before. + curwin->w_p_lbr = lbr_saved; + op_function(oap); // call 'operatorfunc' break; case OP_INSERT: @@ -2031,40 +2031,44 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) static void op_colon(oparg_T *oap) { stuffcharReadbuff(':'); - if (oap->is_VIsual) - stuffReadbuff((char_u *)"'<,'>"); - else { - /* - * Make the range look nice, so it can be repeated. - */ - if (oap->start.lnum == curwin->w_cursor.lnum) + if (oap->is_VIsual) { + stuffReadbuff("'<,'>"); + } else { + // Make the range look nice, so it can be repeated. + if (oap->start.lnum == curwin->w_cursor.lnum) { stuffcharReadbuff('.'); - else + } else { stuffnumReadbuff((long)oap->start.lnum); + } if (oap->end.lnum != oap->start.lnum) { stuffcharReadbuff(','); - if (oap->end.lnum == curwin->w_cursor.lnum) + if (oap->end.lnum == curwin->w_cursor.lnum) { stuffcharReadbuff('.'); - else if (oap->end.lnum == curbuf->b_ml.ml_line_count) + } else if (oap->end.lnum == curbuf->b_ml.ml_line_count) { stuffcharReadbuff('$'); - else if (oap->start.lnum == curwin->w_cursor.lnum) { - stuffReadbuff((char_u *)".+"); + } else if (oap->start.lnum == curwin->w_cursor.lnum) { + stuffReadbuff(".+"); stuffnumReadbuff(oap->line_count - 1); - } else + } else { stuffnumReadbuff((long)oap->end.lnum); + } } } - if (oap->op_type != OP_COLON) - stuffReadbuff((char_u *)"!"); + if (oap->op_type != OP_COLON) { + stuffReadbuff("!"); + } if (oap->op_type == OP_INDENT) { - stuffReadbuff(get_equalprg()); - stuffReadbuff((char_u *)"\n"); + stuffReadbuff((const char *)get_equalprg()); + stuffReadbuff("\n"); } else if (oap->op_type == OP_FORMAT) { - if (*p_fp == NUL) - stuffReadbuff((char_u *)"fmt"); - else - stuffReadbuff(p_fp); - stuffReadbuff((char_u *)"\n']"); + if (*curbuf->b_p_fp != NUL) { + stuffReadbuff((const char *)curbuf->b_p_fp); + } else if (*p_fp != NUL) { + stuffReadbuff((const char *)p_fp); + } else { + stuffReadbuff("fmt"); + } + stuffReadbuff("\n']"); } /* @@ -2077,7 +2081,6 @@ static void op_colon(oparg_T *oap) */ static void op_function(oparg_T *oap) { - char_u *(argv[1]); int save_virtual_op = virtual_op; if (*p_opfunc == NUL) @@ -2091,16 +2094,16 @@ static void op_function(oparg_T *oap) decl(&curbuf->b_op_end); } - if (oap->motion_type == kMTBlockWise) { - argv[0] = (char_u *)"block"; - } else if (oap->motion_type == kMTLineWise) { - argv[0] = (char_u *)"line"; - } else { - argv[0] = (char_u *)"char"; - } + const char_u *const argv[1] = { + (const char_u *)(((const char *const[]) { + [kMTBlockWise] = "block", + [kMTLineWise] = "line", + [kMTCharWise] = "char", + })[oap->motion_type]), + }; - /* Reset virtual_op so that 'virtualedit' can be changed in the - * function. */ + // Reset virtual_op so that 'virtualedit' can be changed in the + // function. virtual_op = MAYBE; (void)call_func_retnr(p_opfunc, 1, argv, false); @@ -2307,7 +2310,7 @@ do_mouse ( if (VIsual_active) { if (VIsual_select) { stuffcharReadbuff(Ctrl_G); - stuffReadbuff((char_u *)"\"+p"); + stuffReadbuff("\"+p"); } else { stuffcharReadbuff('y'); stuffcharReadbuff(K_MIDDLEMOUSE); @@ -2334,10 +2337,11 @@ do_mouse ( if (regname == 0 && eval_has_provider("clipboard")) { regname = '*'; } - if ((State & REPLACE_FLAG) && !yank_register_mline(regname)) + if ((State & REPLACE_FLAG) && !yank_register_mline(regname)) { insert_reg(regname, true); - else { - do_put(regname, NULL, BACKWARD, 1L, fixindent | PUT_CURSEND); + } else { + do_put(regname, NULL, BACKWARD, 1L, + (fixindent ? PUT_FIXINDENT : 0) | PUT_CURSEND); /* Repeat it with CTRL-R CTRL-O r or CTRL-R CTRL-P r */ AppendCharToRedobuff(Ctrl_R); @@ -2462,12 +2466,12 @@ do_mouse ( }; typval_T rettv; int doesrange; - (void) call_func((char_u *) tab_page_click_defs[mouse_col].func, - (int) strlen(tab_page_click_defs[mouse_col].func), - &rettv, ARRAY_SIZE(argv), argv, - curwin->w_cursor.lnum, curwin->w_cursor.lnum, - &doesrange, true, NULL, NULL); - clear_tv(&rettv); + (void)call_func((char_u *)tab_page_click_defs[mouse_col].func, + (int)strlen(tab_page_click_defs[mouse_col].func), + &rettv, ARRAY_SIZE(argv), argv, NULL, + curwin->w_cursor.lnum, curwin->w_cursor.lnum, + &doesrange, true, NULL, NULL); + tv_clear(&rettv); break; } } @@ -2689,7 +2693,8 @@ do_mouse ( */ if (restart_edit != 0) where_paste_started = curwin->w_cursor; - do_put(regname, NULL, dir, count, fixindent | PUT_CURSEND); + do_put(regname, NULL, dir, count, + (fixindent ? PUT_FIXINDENT : 0)| PUT_CURSEND); } /* * Ctrl-Mouse click or double click in a quickfix window jumps to the @@ -2698,13 +2703,12 @@ do_mouse ( else if (((mod_mask & MOD_MASK_CTRL) || (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) && bt_quickfix(curbuf)) { - if (State & INSERT) - stuffcharReadbuff(Ctrl_O); - if (curwin->w_llist_ref == NULL) /* quickfix window */ - stuffReadbuff((char_u *)":.cc\n"); - else /* location list window */ - stuffReadbuff((char_u *)":.ll\n"); - got_click = false; /* ignore drag&release now */ + if (curwin->w_llist_ref == NULL) { // quickfix window + do_cmdline_cmd(".cc"); + } else { // location list window + do_cmdline_cmd(".ll"); + } + got_click = false; // ignore drag&release now } /* * Ctrl-Mouse click (or double click in a help window) jumps to the tag @@ -3514,7 +3518,8 @@ void check_scrollbind(linenr_T topline_diff, long leftcol_diff) * loop through the scrollbound windows and scroll accordingly */ VIsual_select = VIsual_active = 0; - for (curwin = firstwin; curwin; curwin = curwin->w_next) { + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + curwin = wp; curbuf = curwin->w_buffer; /* skip original window and windows with 'noscrollbind' */ if (curwin == old_curwin || !curwin->w_p_scb) { @@ -3653,6 +3658,39 @@ nv_gd ( } } +// Return true if line[offset] is not inside a C-style comment or string, false +// otherwise. +static bool is_ident(char_u *line, int offset) +{ + bool incomment = false; + int instring = 0; + int prev = 0; + + for (int i = 0; i < offset && line[i] != NUL; i++) { + if (instring != 0) { + if (prev != '\\' && line[i] == instring) { + instring = 0; + } + } else if ((line[i] == '"' || line[i] == '\'') && !incomment) { + instring = line[i]; + } else { + if (incomment) { + if (prev == '*' && line[i] == '/') { + incomment = false; + } + } else if (prev == '/' && line[i] == '*') { + incomment = true; + } else if (prev == '/' && line[i] == '/') { + return false; + } + } + + prev = line[i]; + } + + return incomment == false && instring == 0; +} + /* * Search for variable declaration of "ptr[len]". * When "locally" is true in the current function ("gd"), otherwise in the @@ -3679,6 +3717,7 @@ find_decl ( bool retval = true; bool incll; int searchflags = flags_arg; + bool valid; pat = xmalloc(len + 7); @@ -3713,6 +3752,7 @@ find_decl ( /* Search forward for the identifier, ignore comment lines. */ clearpos(&found_pos); for (;; ) { + valid = false; t = searchit(curwin, curbuf, &curwin->w_cursor, FORWARD, pat, 1L, searchflags, RE_LAST, (linenr_T)0, NULL); if (curwin->w_cursor.lnum >= old_pos.lnum) @@ -3743,20 +3783,35 @@ find_decl ( curwin->w_cursor.col = 0; continue; } - if (!locally) /* global search: use first match found */ + 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. + if (!valid && found_pos.lnum != 0) { + curwin->w_cursor = found_pos; break; - if (curwin->w_cursor.lnum >= par_pos.lnum) { - /* If we previously found a valid position, use it. */ - if (found_pos.lnum != 0) + } + // global search: use first match found + if (valid && !locally) { + break; + } + if (valid && curwin->w_cursor.lnum >= par_pos.lnum) { + // If we previously found a valid position, use it. + if (found_pos.lnum != 0) { curwin->w_cursor = found_pos; + } break; } - // For finding a local variable and the match is before the "{" search - // to find a later match. For K&R style function declarations this - // skips the function header without types. Remove SEARCH_START from - // flags to avoid getting stuck at one position. - found_pos = curwin->w_cursor; + // For finding a local variable and the match is before the "{" or + // inside a comment, continue searching. For K&R style function + // declarations this skips the function header without types. + if (!valid) { + clearpos(&found_pos); + } else { + found_pos = curwin->w_cursor; + } + // Remove SEARCH_START from flags to avoid getting stuck at one position. searchflags &= ~SEARCH_START; } @@ -4037,12 +4092,10 @@ static void nv_zet(cmdarg_T *cap) return; n = nchar - '0'; for (;; ) { - ++no_mapping; - ++allow_keys; /* no mapping for nchar, but allow key codes */ + no_mapping++; nchar = plain_vgetc(); LANGMAP_ADJUST(nchar, true); - --no_mapping; - --allow_keys; + no_mapping--; (void)add_to_showcmd(nchar); if (nchar == K_DEL || nchar == K_KDEL) n /= 10; @@ -4370,13 +4423,11 @@ dozet: break; - case 'u': /* "zug" and "zuw": undo "zg" and "zw" */ - ++no_mapping; - ++allow_keys; /* no mapping for nchar, but allow key codes */ + case 'u': // "zug" and "zuw": undo "zg" and "zw" + no_mapping++; nchar = plain_vgetc(); LANGMAP_ADJUST(nchar, true); - --no_mapping; - --allow_keys; + no_mapping--; (void)add_to_showcmd(nchar); if (vim_strchr((char_u *)"gGwW", nchar) == NULL) { clearopbeep(cap->oap); @@ -4483,7 +4534,7 @@ static void nv_colon(cmdarg_T *cap) /* translate "count:" into ":.,.+(count - 1)" */ stuffcharReadbuff('.'); if (cap->count0 > 1) { - stuffReadbuff((char_u *)",.+"); + stuffReadbuff(",.+"); stuffnumReadbuff(cap->count0 - 1L); } } @@ -4674,6 +4725,7 @@ static void nv_ident(cmdarg_T *cap) char_u *kp = *curbuf->b_p_kp == NUL ? p_kp : curbuf->b_p_kp; // 'keywordprg' assert(*kp != NUL); // option.c:do_set() should default to ":help" if empty. bool kp_ex = (*kp == ':'); // 'keywordprg' is an ex command + bool kp_help = (STRCMP(kp, ":he") == 0 || STRCMP(kp, ":help") == 0); size_t buf_size = n * 2 + 30 + STRLEN(kp); char *buf = xmalloc(buf_size); buf[0] = NUL; @@ -4696,7 +4748,9 @@ static void nv_ident(cmdarg_T *cap) break; case 'K': - if (kp_ex) { + if (kp_help) { + STRCPY(buf, "he! "); + } else if (kp_ex) { if (cap->count0 != 0) { // Send the count to the ex command. snprintf(buf, buf_size, "%" PRId64, (int64_t)(cap->count0)); } @@ -4758,13 +4812,16 @@ static void nv_ident(cmdarg_T *cap) } } - /* - * Now grab the chars in the identifier - */ - if (cmdchar == 'K' && !kp_ex) { - /* Escape the argument properly for a shell command */ + // Now grab the chars in the identifier + if (cmdchar == 'K' && !kp_help) { ptr = vim_strnsave(ptr, n); - p = vim_strsave_shellescape(ptr, true, true); + if (kp_ex) { + // Escape the argument properly for an Ex command + p = (char_u *)vim_strsave_fnameescape((const char *)ptr, false); + } else { + // Escape the argument properly for a shell command + p = vim_strsave_shellescape(ptr, true, true); + } xfree(ptr); char *newbuf = xrealloc(buf, STRLEN(buf) + STRLEN(p) + 1); buf = newbuf; @@ -5224,6 +5281,7 @@ static void nv_dollar(cmdarg_T *cap) static void nv_search(cmdarg_T *cap) { oparg_T *oap = cap->oap; + pos_T save_cursor = curwin->w_cursor; if (cap->cmdchar == '?' && cap->oap->op_type == OP_ROT13) { /* Translate "g??" to "g?g?" */ @@ -5233,6 +5291,8 @@ static void nv_search(cmdarg_T *cap) return; } + // When using 'incsearch' the cursor may be moved to set a different search + // start position. cap->searchbuf = getcmdline(cap->cmdchar, cap->count1, 0); if (cap->searchbuf == NULL) { @@ -5241,7 +5301,8 @@ static void nv_search(cmdarg_T *cap) } (void)normal_search(cap, cap->cmdchar, cap->searchbuf, - (cap->arg ? 0 : SEARCH_MARK)); + (cap->arg || !equalpos(save_cursor, curwin->w_cursor)) + ? 0 : SEARCH_MARK); } /* @@ -6160,17 +6221,15 @@ static void nv_abbrev(cmdarg_T *cap) */ static void nv_optrans(cmdarg_T *cap) { - static char_u *(ar[8]) = {(char_u *)"dl", (char_u *)"dh", - (char_u *)"d$", (char_u *)"c$", - (char_u *)"cl", (char_u *)"cc", - (char_u *)"yy", (char_u *)":s\r"}; - static char_u *str = (char_u *)"xXDCsSY&"; + static const char *(ar[]) = { "dl", "dh", "d$", "c$", "cl", "cc", "yy", + ":s\r" }; + static const char *str = "xXDCsSY&"; if (!checkclearopq(cap->oap)) { if (cap->count0) { stuffnumReadbuff(cap->count0); } - stuffReadbuff(ar[(int)(vim_strchr(str, cap->cmdchar) - str)]); + stuffReadbuff(ar[strchr(str, (char)cap->cmdchar) - str]); } cap->opcount = 0; } @@ -7196,8 +7255,10 @@ static void nv_wordcmd(cmdarg_T *cap) // Another strangeness: When standing on the end of a word "ce" will // change until the end of the next word, but "cw" will change only one // character! This is done by setting "flag". - cap->oap->inclusive = true; - word_end = true; + if (vim_strchr(p_cpo, CPO_CHANGEW) != NULL) { + cap->oap->inclusive = true; + word_end = true; + } flag = true; } } @@ -7291,11 +7352,11 @@ static bool unadjust_for_sel(void) pp = &curwin->w_cursor; else pp = &VIsual; - if (pp->coladd > 0) - --pp->coladd; - else if (pp->col > 0) { - --pp->col; - mb_adjustpos(curbuf, pp); + if (pp->coladd > 0) { + pp->coladd--; + } else if (pp->col > 0) { + pp->col--; + mark_mb_adjustpos(curbuf, pp); } else if (pp->lnum > 1) { --pp->lnum; pp->col = (colnr_T)STRLEN(ml_get(pp->lnum)); @@ -7421,27 +7482,23 @@ static void nv_esc(cmdarg_T *cap) restart_edit = 'a'; } -/* - * Handle "A", "a", "I", "i" and <Insert> commands. - */ +/// Handle "A", "a", "I", "i" and <Insert> commands. static void nv_edit(cmdarg_T *cap) { - /* <Insert> is equal to "i" */ - if (cap->cmdchar == K_INS || cap->cmdchar == K_KINS) + // <Insert> is equal to "i" + if (cap->cmdchar == K_INS || cap->cmdchar == K_KINS) { cap->cmdchar = 'i'; + } - /* in Visual mode "A" and "I" are an operator */ - if (VIsual_active && (cap->cmdchar == 'A' || cap->cmdchar == 'I')) + // in Visual mode "A" and "I" are an operator + if (VIsual_active && (cap->cmdchar == 'A' || cap->cmdchar == 'I')) { v_visop(cap); - - /* in Visual mode and after an operator "a" and "i" are for text objects */ - else if ((cap->cmdchar == 'a' || cap->cmdchar == 'i') - && (cap->oap->op_type != OP_NOP - || VIsual_active - )) { + // in Visual mode and after an operator "a" and "i" are for text objects + } else if ((cap->cmdchar == 'a' || cap->cmdchar == 'i') + && (cap->oap->op_type != OP_NOP || VIsual_active)) { nv_object(cap); - } else if (!curbuf->b_p_ma && !p_im) { - /* Only give this error when 'insertmode' is off. */ + } else if (!curbuf->b_p_ma && !p_im && !curbuf->terminal) { + // Only give this error when 'insertmode' is off. EMSG(_(e_modifiable)); clearop(cap->oap); } else if (!checkclearopq(cap->oap)) { @@ -7614,11 +7671,13 @@ static void nv_record(cmdarg_T *cap) 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 (!Exec_reg && do_record(cap->nchar) == false) - clearopbeep(cap->oap); + } else { + // (stop) recording into a named register, unless executing a + // register. + if (!Exec_reg && do_record(cap->nchar) == FAIL) { + clearopbeep(cap->oap); + } + } } } @@ -7727,16 +7786,22 @@ static void nv_put(cmdarg_T *cap) savereg = copy_register(regname); } - /* Now delete the selected text. */ - cap->cmdchar = 'd'; - cap->nchar = NUL; - cap->oap->regname = NUL; - nv_operator(cap); - do_pending_operator(cap, 0, false); - empty = (curbuf->b_ml.ml_flags & ML_EMPTY); + // 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. + cap->cmdchar = 'd'; + cap->nchar = NUL; + cap->oap->regname = NUL; + nv_operator(cap); + do_pending_operator(cap, 0, false); + empty = (curbuf->b_ml.ml_flags & ML_EMPTY); - /* delete PUT_LINE_BACKWARD; */ - cap->oap->regname = regname; + // delete PUT_LINE_BACKWARD; + cap->oap->regname = regname; + } /* When deleted a linewise Visual area, put the register as * lines to avoid it joined with the next line. When deletion was @@ -7828,7 +7893,7 @@ static void get_op_vcol( // prevent from moving onto a trail byte if (has_mbyte) { - mb_adjustpos(curwin->w_buffer, &oap->end); + mark_mb_adjustpos(curwin->w_buffer, &oap->end); } getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol); @@ -7893,6 +7958,7 @@ static void nv_event(cmdarg_T *cap) may_garbage_collect = false; multiqueue_process_events(main_loop.events); cap->retval |= CA_COMMAND_BUSY; // don't call edit() now + finish_op = false; } /// Trigger FocusGained event. diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 907353c271..c01840cfd0 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -1,3 +1,6 @@ +// 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 + /* * ops.c: implementation of various operators: op_shift, op_delete, op_tilde, * op_change, op_yank, do_put, do_join @@ -14,8 +17,10 @@ #include "nvim/buffer.h" #include "nvim/charset.h" #include "nvim/cursor.h" +#include "nvim/assert.h" #include "nvim/edit.h" #include "nvim/eval.h" +#include "nvim/eval/typval.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds2.h" #include "nvim/ex_getln.h" @@ -41,6 +46,7 @@ #include "nvim/terminal.h" #include "nvim/ui.h" #include "nvim/undo.h" +#include "nvim/macros.h" #include "nvim/window.h" #include "nvim/os/input.h" #include "nvim/os/time.h" @@ -49,12 +55,11 @@ static yankreg_T y_regs[NUM_REGISTERS]; static yankreg_T *y_previous = NULL; /* ptr to last written yankreg */ -static bool clipboard_didwarn_unnamed = false; - // for behavior between start_batch_changes() and end_batch_changes()) -static bool clipboard_delay_update = false; // delay clipboard update static int batch_change_count = 0; // inside a script +static bool clipboard_delay_update = false; // delay clipboard update static bool clipboard_needs_update = false; // clipboard was updated +static bool clipboard_didwarn = false; /* * structure used by block_prep, op_delete and op_yank for blockwise operators @@ -210,8 +215,6 @@ void op_shift(oparg_T *oap, int curs_top, int amount) } changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L); - /* The cursor line is not in a closed fold */ - foldOpenCursor(); if (oap->motion_type == kMTBlockWise) { curwin->w_cursor.lnum = oap->start.lnum; @@ -222,6 +225,9 @@ void op_shift(oparg_T *oap, int curs_top, int amount) } else --curwin->w_cursor.lnum; /* put cursor on last line, for ":>" */ + // The cursor line is not in a closed fold + foldOpenCursor(); + if (oap->line_count > p_report) { if (oap->op_type == OP_RSHIFT) s = (char_u *)">"; @@ -798,7 +804,6 @@ static bool is_append_register(int regname) /// Returns a copy of contents in register `name` /// for use in do_put. Should be freed by caller. yankreg_T *copy_register(int name) - FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET { yankreg_T *reg = get_yank_register(name, YREG_PASTE); @@ -887,7 +892,7 @@ static void set_yreg_additional_data(yankreg_T *reg, dict_T *additional_data) if (reg->additional_data == additional_data) { return; } - dict_unref(reg->additional_data); + tv_dict_unref(reg->additional_data); reg->additional_data = additional_data; } @@ -932,13 +937,11 @@ static int stuff_yank(int regname, char_u *p) static int execreg_lastc = NUL; -/* - * execute a yank register: copy it into the stuff buffer - * - * return FAIL for failure, OK otherwise - */ -int -do_execreg ( +/// Execute a yank register: copy it into the stuff buffer +/// +/// Return FAIL for failure, OK otherwise +int +do_execreg( int regname, int colon, /* insert ':' before each line */ int addcr, /* always add '\n' to end of line */ @@ -1105,7 +1108,6 @@ int insert_reg( ) { int retval = OK; - char_u *arg; int allocated; /* @@ -1121,21 +1123,24 @@ int insert_reg( if (regname != NUL && !valid_yank_reg(regname, false)) return FAIL; - if (regname == '.') /* insert last inserted text */ - retval = stuff_inserted(NUL, 1L, TRUE); - else if (get_spec_reg(regname, &arg, &allocated, TRUE)) { - if (arg == NULL) + char_u *arg; + if (regname == '.') { // Insert last inserted text. + retval = stuff_inserted(NUL, 1L, true); + } else if (get_spec_reg(regname, &arg, &allocated, true)) { + if (arg == NULL) { return FAIL; - stuffescaped(arg, literally); - if (allocated) + } + stuffescaped((const char *)arg, literally); + if (allocated) { xfree(arg); - } else { /* name or number register */ + } + } else { // Name or number register. yankreg_T *reg = get_yank_register(regname, YREG_PASTE); if (reg->y_array == NULL) { retval = FAIL; } else { for (size_t i = 0; i < reg->y_size; i++) { - stuffescaped(reg->y_array[i], literally); + stuffescaped((const char *)reg->y_array[i], literally); // Insert a newline between lines and after last line if // y_type is kMTLineWise. if (reg->y_type == kMTLineWise || i < reg->y_size - 1) { @@ -1152,29 +1157,29 @@ int insert_reg( * Stuff a string into the typeahead buffer, such that edit() will insert it * literally ("literally" TRUE) or interpret is as typed characters. */ -static void stuffescaped(char_u *arg, int literally) +static void stuffescaped(const char *arg, int literally) { - int c; - char_u *start; - while (*arg != NUL) { - /* Stuff a sequence of normal ASCII characters, that's fast. Also - * stuff K_SPECIAL to get the effect of a special key when "literally" - * is TRUE. */ - start = arg; - while ((*arg >= ' ' && *arg < DEL) || (*arg == K_SPECIAL && !literally)) - ++arg; - if (arg > start) + // Stuff a sequence of normal ASCII characters, that's fast. Also + // stuff K_SPECIAL to get the effect of a special key when "literally" + // is TRUE. + const char *const start = arg; + while ((*arg >= ' ' && *arg < DEL) || ((uint8_t)(*arg) == K_SPECIAL + && !literally)) { + arg++; + } + if (arg > start) { stuffReadbuffLen(start, (long)(arg - start)); + } /* stuff a single special character */ if (*arg != NUL) { - if (has_mbyte) - c = mb_cptr2char_adv(&arg); - else - c = *arg++; - if (literally && ((c < ' ' && c != TAB) || c == DEL)) + const int c = (has_mbyte + ? mb_cptr2char_adv((const char_u **)&arg) + : (uint8_t)(*arg++)); + if (literally && ((c < ' ' && c != TAB) || c == DEL)) { stuffcharReadbuff(Ctrl_V); + } stuffcharReadbuff(c); } } @@ -1260,7 +1265,7 @@ int get_spec_reg( /// Paste a yank register into the command line. /// Only for non-special registers. -/// Used by CTRL-R command in command-line mode +/// Used by CTRL-R in command-line mode. /// insert_reg() can't be used here, because special characters from the /// register contents will be interpreted as commands. /// @@ -1278,9 +1283,8 @@ bool cmdline_paste_reg(int regname, bool literally, bool remcr) for (size_t i = 0; i < reg->y_size; i++) { cmdline_paste_str(reg->y_array[i], literally); - // Insert ^M between lines and after last line if type is kMTLineWise. - // Don't do this when "remcr" is true. - if ((reg->y_type == kMTLineWise || i < reg->y_size - 1) && !remcr) { + // Insert ^M between lines, unless `remcr` is true. + if (i < reg->y_size - 1 && !remcr) { cmdline_paste_str((char_u *)"\r", literally); } @@ -1403,8 +1407,11 @@ int op_delete(oparg_T *oap) } if (oap->regname == 0) { + if (reg == NULL) { + abort(); + } set_clipboard(0, reg); - yank_do_autocmd(oap, reg); + do_autocmd_textyankpost(oap, reg); } } @@ -1951,16 +1958,18 @@ int swapchar(int op_type, pos_T *pos) if (enc_dbcs != 0 && c >= 0x100) /* No lower/uppercase letter */ return FALSE; nc = c; - if (vim_islower(c)) { - if (op_type == OP_ROT13) + if (mb_islower(c)) { + if (op_type == OP_ROT13) { nc = ROT13(c, 'a'); - else if (op_type != OP_LOWER) - nc = vim_toupper(c); - } else if (vim_isupper(c)) { - if (op_type == OP_ROT13) + } else if (op_type != OP_LOWER) { + nc = mb_toupper(c); + } + } else if (mb_isupper(c)) { + if (op_type == OP_ROT13) { nc = ROT13(c, 'A'); - else if (op_type != OP_UPPER) - nc = vim_tolower(c); + } else if (op_type != OP_UPPER) { + nc = mb_tolower(c); + } } if (nc != c) { if (enc_utf8 && (c >= 0x80 || nc >= 0x80)) { @@ -2315,7 +2324,7 @@ bool op_yank(oparg_T *oap, bool message) yankreg_T *reg = get_yank_register(oap->regname, YREG_YANK); op_yank_reg(oap, message, reg, is_append_register(oap->regname)); set_clipboard(oap->regname, reg); - yank_do_autocmd(oap, reg); + do_autocmd_textyankpost(oap, reg); return true; } @@ -2538,7 +2547,7 @@ static void yank_copy_line(yankreg_T *reg, struct block_def *bd, size_t y_idx) /// /// @param oap Operator arguments. /// @param reg The yank register used. -static void yank_do_autocmd(oparg_T *oap, yankreg_T *reg) +static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg) FUNC_ATTR_NONNULL_ALL { static bool recursive = false; @@ -2555,33 +2564,33 @@ static void yank_do_autocmd(oparg_T *oap, yankreg_T *reg) dict_T *dict = get_vim_var_dict(VV_EVENT); // the yanked text - list_T *list = list_alloc(); + list_T *list = tv_list_alloc(); for (size_t i = 0; i < reg->y_size; i++) { - list_append_string(list, reg->y_array[i], -1); + tv_list_append_string(list, (const char *)reg->y_array[i], -1); } list->lv_lock = VAR_FIXED; - dict_add_list(dict, "regcontents", list); + tv_dict_add_list(dict, S_LEN("regcontents"), list); // the register type char buf[NUMBUFLEN+2]; format_reg_type(reg->y_type, reg->y_width, buf, ARRAY_SIZE(buf)); - dict_add_nr_str(dict, "regtype", 0, (char_u *)buf); + tv_dict_add_str(dict, S_LEN("regtype"), buf); // name of requested register or the empty string for an unnamed operation. buf[0] = (char)oap->regname; buf[1] = NUL; - dict_add_nr_str(dict, "regname", 0, (char_u *)buf); + tv_dict_add_str(dict, S_LEN("regname"), buf); // kind of operation (yank/delete/change) buf[0] = (char)get_op_char(oap->op_type); buf[1] = NUL; - dict_add_nr_str(dict, "operator", 0, (char_u *)buf); + tv_dict_add_str(dict, S_LEN("operator"), buf); - dict_set_keys_readonly(dict); + tv_dict_set_keys_readonly(dict); textlock++; apply_autocmds(EVENT_TEXTYANKPOST, NULL, NULL, false, curbuf); textlock--; - dict_clear(dict); + tv_dict_clear(dict); recursive = false; } @@ -2637,12 +2646,79 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) * special characters (newlines, etc.). */ if (regname == '.') { - (void)stuff_inserted((dir == FORWARD ? (count == -1 ? 'o' : 'a') : - (count == -1 ? 'O' : 'i')), count, FALSE); - /* Putting the text is done later, so can't really move the cursor to - * the next character. Use "l" to simulate it. */ - if ((flags & PUT_CURSEND) && gchar_cursor() != NUL) - stuffcharReadbuff('l'); + bool non_linewise_vis = (VIsual_active && VIsual_mode != 'V'); + + // PUT_LINE has special handling below which means we use 'i' to start. + char command_start_char = non_linewise_vis ? 'c' : + (flags & PUT_LINE ? 'i' : (dir == FORWARD ? 'a' : 'i')); + + // To avoid 'autoindent' on linewise puts, create a new line with `:put _`. + if (flags & PUT_LINE) { + do_put('_', NULL, dir, 1, PUT_LINE); + } + + // If given a count when putting linewise, we stuff the readbuf with the + // dot register 'count' times split by newlines. + if (flags & PUT_LINE) { + stuffcharReadbuff(command_start_char); + for (; count > 0; count--) { + (void)stuff_inserted(NUL, 1, count != 1); + if (count != 1) { + // To avoid 'autoindent' affecting the text, use Ctrl_U to remove any + // whitespace. Can't just insert Ctrl_U into readbuf1, this would go + // back to the previous line in the case of 'noautoindent' and + // 'backspace' includes "eol". So we insert a dummy space for Ctrl_U + // to consume. + stuffReadbuff("\n "); + stuffcharReadbuff(Ctrl_U); + } + } + } else { + (void)stuff_inserted(command_start_char, count, false); + } + + // Putting the text is done later, so can't move the cursor to the next + // character. Simulate it with motion commands after the insert. + if (flags & PUT_CURSEND) { + if (flags & PUT_LINE) { + stuffReadbuff("j0"); + } else { + // Avoid ringing the bell from attempting to move into the space after + // the current line. We can stuff the readbuffer with "l" if: + // 1) 'virtualedit' is "all" or "onemore" + // 2) We are not at the end of the line + // 3) We are not (one past the end of the line && on the last line) + // This allows a visual put over a selection one past the end of the + // line joining the current line with the one below. + + // curwin->w_cursor.col marks the byte position of the cursor in the + // currunt line. It increases up to a max of + // STRLEN(ml_get(curwin->w_cursor.lnum)). With 'virtualedit' and the + // cursor past the end of the line, curwin->w_cursor.coladd is + // incremented instead of curwin->w_cursor.col. + char_u *cursor_pos = get_cursor_pos_ptr(); + bool one_past_line = (*cursor_pos == NUL); + bool eol = false; + if (!one_past_line) { + eol = (*(cursor_pos + mb_ptr2len(cursor_pos)) == NUL); + } + + bool ve_allows = (ve_flags == VE_ALL || ve_flags == VE_ONEMORE); + bool eof = curbuf->b_ml.ml_line_count == curwin->w_cursor.lnum + && one_past_line; + if (ve_allows || !(eol || eof)) { + stuffcharReadbuff('l'); + } + } + } else if (flags & PUT_LINE) { + stuffReadbuff("g'["); + } + + // So the 'u' command restores cursor position after ".p, save the cursor + // position now (though not saving any text). + if (command_start_char == 'a') { + u_save(curwin->w_cursor.lnum, curwin->w_cursor.lnum + 1); + } return; } @@ -2712,7 +2788,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) } if (curbuf->terminal) { - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { // -V756 // feed the lines to the terminal for (size_t j = 0; j < y_size; j++) { if (j) { @@ -2831,14 +2907,12 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) else getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col); - if (has_mbyte) - /* move to start of next multi-byte character */ - curwin->w_cursor.col += (*mb_ptr2len)(get_cursor_pos_ptr()); - else if (c != TAB || ve_flags != VE_ALL) - ++curwin->w_cursor.col; - ++col; - } else + // move to start of next multi-byte character + curwin->w_cursor.col += (*mb_ptr2len)(get_cursor_pos_ptr()); + col++; + } else { getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2); + } col += curwin->w_cursor.coladd; if (ve_flags == VE_ALL @@ -2892,8 +2966,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) bd.startspaces = incr - bd.endspaces; --bd.textcol; delcount = 1; - if (has_mbyte) - bd.textcol -= (*mb_head_off)(oldp, oldp + bd.textcol); + bd.textcol -= (*mb_head_off)(oldp, oldp + bd.textcol); if (oldp[bd.textcol] != TAB) { /* Only a Tab can be split into spaces. Other * characters will have to be moved to after the @@ -2975,21 +3048,13 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) // if type is kMTCharWise, FORWARD is the same as BACKWARD on the next // char if (dir == FORWARD && gchar_cursor() != NUL) { - if (has_mbyte) { - int bytelen = (*mb_ptr2len)(get_cursor_pos_ptr()); - - /* put it on the next of the multi-byte character. */ - col += bytelen; - if (yanklen) { - curwin->w_cursor.col += bytelen; - curbuf->b_op_end.col += bytelen; - } - } else { - ++col; - if (yanklen) { - ++curwin->w_cursor.col; - ++curbuf->b_op_end.col; - } + int bytelen = (*mb_ptr2len)(get_cursor_pos_ptr()); + + // put it on the next of the multi-byte character. + col += bytelen; + if (yanklen) { + curwin->w_cursor.col += bytelen; + curbuf->b_op_end.col += bytelen; } } curbuf->b_op_start = curwin->w_cursor; @@ -3027,7 +3092,9 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) } if (VIsual_active) lnum++; - } while (VIsual_active && lnum <= curbuf->b_visual.vi_end.lnum); + } while (VIsual_active + && (lnum <= curbuf->b_visual.vi_end.lnum + || lnum <= curbuf->b_visual.vi_start.lnum)); if (VIsual_active) { /* reset lnum to the last visual line */ lnum--; @@ -3114,7 +3181,7 @@ error: if (curbuf->b_op_start.lnum + (y_type == kMTCharWise) - 1 + nr_lines < curbuf->b_ml.ml_line_count) { mark_adjust(curbuf->b_op_start.lnum + (y_type == kMTCharWise), - (linenr_T)MAXLNUM, nr_lines, 0L); + (linenr_T)MAXLNUM, nr_lines, 0L, false); } // note changed text for displaying and folding @@ -3264,10 +3331,11 @@ void ex_display(exarg_T *eap) get_clipboard(name, &yb, true); - if (name == vim_tolower(redir_reg) - || (redir_reg == '"' && yb == y_previous)) - continue; /* do not list register being written to, the - * pointer can be freed */ + if (name == mb_tolower(redir_reg) + || (redir_reg == '"' && yb == y_previous)) { + continue; // do not list register being written to, the + // pointer can be freed + } if (yb->y_array != NULL) { msg_putchar('\n'); @@ -3380,43 +3448,47 @@ dis_msg ( os_breakcheck(); } -/* - * If "process" is TRUE and the line begins with a comment leader (possibly - * after some white space), return a pointer to the text after it. Put a boolean - * value indicating whether the line ends with an unclosed comment in - * "is_comment". - * line - line to be processed, - * process - if FALSE, will only check whether the line ends with an unclosed - * comment, - * include_space - whether to also skip space following the comment leader, - * is_comment - will indicate whether the current line ends with an unclosed - * comment. - */ -static char_u *skip_comment(char_u *line, int process, int include_space, int *is_comment) +/// If \p "process" is true and the line begins with a comment leader (possibly +/// after some white space), return a pointer to the text after it. +/// Put a boolean value indicating whether the line ends with an unclosed +/// comment in "is_comment". +/// +/// @param line - line to be processed +/// @param process - if false, will only check whether the line ends +/// with an unclosed comment, +/// @param include_space - whether to skip space following the comment leader +/// @param[out] is_comment - whether the current line ends with an unclosed +/// comment. +char_u *skip_comment( + char_u *line, bool process, bool include_space, bool *is_comment +) { char_u *comment_flags = NULL; int lead_len; int leader_offset = get_last_leader_offset(line, &comment_flags); - *is_comment = FALSE; + *is_comment = false; if (leader_offset != -1) { /* Let's check whether the line ends with an unclosed comment. * If the last comment leader has COM_END in flags, there's no comment. */ while (*comment_flags) { if (*comment_flags == COM_END - || *comment_flags == ':') + || *comment_flags == ':') { break; - ++comment_flags; + } + comment_flags++; + } + if (*comment_flags != COM_END) { + *is_comment = true; } - if (*comment_flags != COM_END) - *is_comment = TRUE; } - if (process == FALSE) + if (process == false) { return line; + } - lead_len = get_leader_len(line, &comment_flags, FALSE, include_space); + lead_len = get_leader_len(line, &comment_flags, false, include_space); if (lead_len == 0) return line; @@ -3438,8 +3510,9 @@ static char_u *skip_comment(char_u *line, int process, int include_space, int *i * starting with a closing part of a three-part comment. That's good, * because we don't want to remove those as this would be annoying. */ - if (*comment_flags == ':' || *comment_flags == NUL) + if (*comment_flags == ':' || *comment_flags == NUL) { line += lead_len; + } return line; } @@ -3473,7 +3546,7 @@ int do_join(size_t count, int *comments = NULL; int remove_comments = (use_formatoptions == TRUE) && has_format_option(FO_REMOVE_COMS); - int prev_was_comment; + bool prev_was_comment; if (save_undo && u_save(curwin->w_cursor.lnum - 1, curwin->w_cursor.lnum + (linenr_T)count) == FAIL) { @@ -3784,6 +3857,7 @@ fex_format ( int use_sandbox = was_set_insecurely((char_u *)"formatexpr", OPT_LOCAL); int r; + char_u *fex; /* * Set v:lnum to the first line number and v:count to the number of lines. @@ -3793,16 +3867,22 @@ fex_format ( set_vim_var_nr(VV_COUNT, (varnumber_T)count); set_vim_var_char(c); - /* - * Evaluate the function. - */ - if (use_sandbox) - ++sandbox; - r = eval_to_number(curbuf->b_p_fex); - if (use_sandbox) - --sandbox; + // Make a copy, the option could be changed while calling it. + fex = vim_strsave(curbuf->b_p_fex); + if (fex == NULL) { + return 0; + } + // Evaluate the function. + if (use_sandbox) { + sandbox++; + } + r = (int)eval_to_number(fex); + if (use_sandbox) { + sandbox--; + } set_vim_var_string(VV_CHAR, NULL, -1); + xfree(fex); return r; } @@ -4359,8 +4439,8 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) char_u buf2[NUMBUFLEN]; int pre; // 'X' or 'x': hex; '0': octal; 'B' or 'b': bin static bool hexupper = false; // 0xABC - unsigned long n; - unsigned long oldn; + uvarnumber_T n; + uvarnumber_T oldn; char_u *ptr; int c; int todel; @@ -4397,12 +4477,14 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) if (dobin) { while (col > 0 && ascii_isbdigit(ptr[col])) { col--; + col -= utf_head_off(ptr, ptr + col); } } if (dohex) { while (col > 0 && ascii_isxdigit(ptr[col])) { col--; + col -= utf_head_off(ptr, ptr + col); } } if (dobin @@ -4410,6 +4492,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) && !((col > 0 && (ptr[col] == 'X' || ptr[col] == 'x') && ptr[col - 1] == '0' + && !utf_head_off(ptr, ptr + col - 1) && ascii_isxdigit(ptr[col + 1])))) { // In case of binary/hexadecimal pattern overlap match, rescan @@ -4417,6 +4500,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) while (col > 0 && ascii_isdigit(ptr[col])) { col--; + col -= utf_head_off(ptr, ptr + col); } } @@ -4424,14 +4508,17 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) && col > 0 && (ptr[col] == 'X' || ptr[col] == 'x') && ptr[col - 1] == '0' + && !utf_head_off(ptr, ptr + col - 1) && ascii_isxdigit(ptr[col + 1])) || (dobin && col > 0 && (ptr[col] == 'B' || ptr[col] == 'b') && ptr[col - 1] == '0' + && !utf_head_off(ptr, ptr + col - 1) && ascii_isbdigit(ptr[col + 1]))) { // Found hexadecimal or binary number, move to its start. col--; + col -= utf_head_off(ptr, ptr + col); } else { // Search forward and then backward to find the start of number. col = pos->col; @@ -4453,15 +4540,18 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) if (visual) { while (ptr[col] != NUL && length > 0 && !ascii_isdigit(ptr[col]) && !(doalp && ASCII_ISALPHA(ptr[col]))) { - col++; - length--; + int mb_len = MB_PTR2LEN(ptr + col); + + col += mb_len; + length -= mb_len; } if (length == 0) { goto theend; } - if (col > pos->col && ptr[col - 1] == '-') { + if (col > pos->col && ptr[col - 1] == '-' + && !utf_head_off(ptr, ptr + col - 1)) { negative = true; was_positive = false; } @@ -4507,7 +4597,8 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) endpos = curwin->w_cursor; curwin->w_cursor.col = col; } else { - if (col > 0 && ptr[col - 1] == '-' && !visual) { + if (col > 0 && ptr[col - 1] == '-' + && !utf_head_off(ptr, ptr + col - 1) && !visual) { // negative number col--; negative = true; @@ -4544,20 +4635,20 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) oldn = n; - n = subtract ? n - (unsigned long) Prenum1 - : n + (unsigned long) Prenum1; + n = subtract ? n - (uvarnumber_T)Prenum1 + : n + (uvarnumber_T)Prenum1; // handle wraparound for decimal numbers if (!pre) { if (subtract) { if (n > oldn) { - n = 1 + (n ^ (unsigned long)-1); + n = 1 + (n ^ (uvarnumber_T)-1); negative ^= true; } } else { // add if (n < oldn) { - n = (n ^ (unsigned long)-1); + n = (n ^ (uvarnumber_T)-1); negative ^= true; } } @@ -4763,8 +4854,8 @@ static void *get_reg_wrap_one_line(char_u *s, int flags) if (!(flags & kGRegList)) { return s; } - list_T *list = list_alloc(); - list_append_string(list, NULL, -1); + list_T *list = tv_list_alloc(); + tv_list_append_string(list, NULL, 0); list->lv_first->li_tv.vval.v_string = s; return list; } @@ -4814,9 +4905,9 @@ void *get_reg_contents(int regname, int flags) return NULL; if (flags & kGRegList) { - list_T *list = list_alloc(); + list_T *list = tv_list_alloc(); for (size_t i = 0; i < reg->y_size; i++) { - list_append_string(list, reg->y_array[i], -1); + tv_list_append_string(list, (const char *)reg->y_array[i], -1); } return list; @@ -4897,7 +4988,7 @@ void write_reg_contents(int name, const char_u *str, ssize_t len, write_reg_contents_ex(name, str, len, must_append, kMTUnknown, 0L); } -void write_reg_contents_lst(int name, char_u **strings, int maxlen, +void write_reg_contents_lst(int name, char_u **strings, bool must_append, MotionType yank_type, colnr_T block_len) { @@ -5147,11 +5238,13 @@ void clear_oparg(oparg_T *oap) * case, eol_size will be added to the character count to account for * the size of the EOL character. */ -static long line_count_info(char_u *line, long *wc, long *cc, long limit, int eol_size) +static varnumber_T line_count_info(char_u *line, varnumber_T *wc, + varnumber_T *cc, varnumber_T limit, + int eol_size) { - long i; - long words = 0; - long chars = 0; + varnumber_T i; + varnumber_T words = 0; + varnumber_T chars = 0; int is_word = 0; for (i = 0; i < limit && line[i] != NUL; ) { @@ -5189,15 +5282,15 @@ void cursor_pos_info(dict_T *dict) char_u buf1[50]; char_u buf2[40]; linenr_T lnum; - long byte_count = 0; - long bom_count = 0; - long byte_count_cursor = 0; - long char_count = 0; - long char_count_cursor = 0; - long word_count = 0; - long word_count_cursor = 0; + varnumber_T byte_count = 0; + varnumber_T bom_count = 0; + varnumber_T byte_count_cursor = 0; + varnumber_T char_count = 0; + varnumber_T char_count_cursor = 0; + varnumber_T word_count = 0; + varnumber_T word_count_cursor = 0; int eol_size; - long last_check = 100000L; + varnumber_T last_check = 100000L; long line_count_selected = 0; pos_T min_pos, max_pos; oparg_T oparg; @@ -5304,15 +5397,16 @@ void cursor_pos_info(dict_T *dict) if (lnum == curwin->w_cursor.lnum) { word_count_cursor += word_count; char_count_cursor += char_count; - byte_count_cursor = byte_count + - line_count_info(ml_get(lnum), - &word_count_cursor, &char_count_cursor, - (long)(curwin->w_cursor.col + 1), eol_size); + byte_count_cursor = byte_count + + 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(ml_get(lnum), &word_count, - &char_count, (long)MAXCOL, eol_size); + // Add to the running totals + byte_count += line_count_info(ml_get(lnum), &word_count, &char_count, + (varnumber_T)MAXCOL, eol_size); } // Correction for when last line doesn't have an EOL. @@ -5401,17 +5495,19 @@ void cursor_pos_info(dict_T *dict) if (dict != NULL) { // Don't shorten this message, the user asked for it. - dict_add_nr_str(dict, "words", word_count, NULL); - dict_add_nr_str(dict, "chars", char_count, NULL); - dict_add_nr_str(dict, "bytes", byte_count + bom_count, NULL); - - dict_add_nr_str(dict, l_VIsual_active ? "visual_bytes" : "cursor_bytes", - byte_count_cursor, NULL); - dict_add_nr_str(dict, l_VIsual_active ? "visual_chars" : "cursor_chars", - char_count_cursor, NULL); - dict_add_nr_str(dict, l_VIsual_active ? "visual_words" : "cursor_words", - word_count_cursor, NULL); - } + tv_dict_add_nr(dict, S_LEN("words"), (varnumber_T)word_count); + tv_dict_add_nr(dict, S_LEN("chars"), (varnumber_T)char_count); + tv_dict_add_nr(dict, S_LEN("bytes"), (varnumber_T)(byte_count + bom_count)); + + STATIC_ASSERT(sizeof("visual") == sizeof("cursor"), + "key_len argument in tv_dict_add_nr is wrong"); + tv_dict_add_nr(dict, l_VIsual_active ? "visual_bytes" : "cursor_bytes", + sizeof("visual_bytes") - 1, (varnumber_T)byte_count_cursor); + tv_dict_add_nr(dict, l_VIsual_active ? "visual_chars" : "cursor_chars", + sizeof("visual_chars") - 1, (varnumber_T)char_count_cursor); + tv_dict_add_nr(dict, l_VIsual_active ? "visual_words" : "cursor_words", + sizeof("visual_words") - 1, (varnumber_T)word_count_cursor); + } } /// Check if the default register (used in an unnamed paste) should be a @@ -5427,7 +5523,7 @@ int get_default_register_name(void) } /// Determine if register `*name` should be used as a clipboard. -/// In an unnammed operation, `*name` is `NUL` and will be adjusted to `'*'/'+'` if +/// In an unnamed operation, `*name` is `NUL` and will be adjusted to */+ if /// `clipboard=unnamed[plus]` is set. /// /// @param name The name of register, or `NUL` if unnamed. @@ -5438,33 +5534,41 @@ int get_default_register_name(void) /// if the register isn't a clipboard or provider isn't available. static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing) { - if (*name == '*' || *name == '+') { - if(!eval_has_provider("clipboard")) { - if (!quiet) { - EMSG("clipboard: No provider. Try \":CheckHealth\" or " - "\":h clipboard\"."); - } - return NULL; - } - return &y_regs[*name == '*' ? STAR_REGISTER : PLUS_REGISTER]; - } else if ((*name == NUL) && (cb_flags & CB_UNNAMEDMASK)) { - if(!eval_has_provider("clipboard")) { - if (!quiet && !clipboard_didwarn_unnamed) { - msg((char_u *)"clipboard: No provider. Try \":CheckHealth\" or " - "\":h clipboard\"."); - clipboard_didwarn_unnamed = true; - } - return NULL; +#define MSG_NO_CLIP "clipboard: No provider. " \ + "Try \":CheckHealth\" or \":h clipboard\"." + + yankreg_T *target = NULL; + bool explicit_cb_reg = (*name == '*' || *name == '+'); + bool implicit_cb_reg = (*name == NUL) && (cb_flags & CB_UNNAMEDMASK); + if (!explicit_cb_reg && !implicit_cb_reg) { + goto end; + } + + if (!eval_has_provider("clipboard")) { + if (batch_change_count == 1 && !quiet + && (!clipboard_didwarn || (explicit_cb_reg && !redirecting()))) { + clipboard_didwarn = true; + // Do NOT error (emsg()) here--if it interrupts :redir we get into + // a weird state, stuck in "redirect mode". + msg((char_u *)MSG_NO_CLIP); } + // ... else, be silent (don't flood during :while, :redir, etc.). + goto end; + } + + if (explicit_cb_reg) { + target = &y_regs[*name == '*' ? STAR_REGISTER : PLUS_REGISTER]; + goto end; + } else { // unnamed register: "implicit" clipboard if (writing && clipboard_delay_update) { + // For "set" (copy), defer the clipboard call. clipboard_needs_update = true; - return NULL; + goto end; } else if (!writing && clipboard_needs_update) { - // use the internal value - return NULL; + // For "get" (paste), use the internal value. + goto end; } - yankreg_T *target; if (cb_flags & CB_UNNAMEDPLUS) { *name = (cb_flags & CB_UNNAMED && writing) ? '"': '+'; target = &y_regs[PLUS_REGISTER]; @@ -5472,10 +5576,11 @@ static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing) *name = '*'; target = &y_regs[STAR_REGISTER]; } - return target; // unnamed register + goto end; } - // don't do anything for other register names - return NULL; + +end: + return target; } static bool get_clipboard(int name, yankreg_T **target, bool quiet) @@ -5489,9 +5594,9 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet) } free_register(reg); - list_T *args = list_alloc(); - char_u regname = (char_u)name; - list_append_string(args, ®name, 1); + list_T *const args = tv_list_alloc(); + const char regname = (char)name; + tv_list_append_string(args, ®name, 1); typval_T result = eval_call_provider("clipboard", "get", args); @@ -5503,7 +5608,8 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet) goto err; } - list_T *res = result.vval.v_list, *lines = NULL; + list_T *res = result.vval.v_list; + list_T *lines = NULL; if (res->lv_len == 2 && res->lv_first->li_tv.v_type == VAR_LIST) { lines = res->lv_first->li_tv.vval.v_list; if (res->lv_last->li_tv.v_type != VAR_STRING) { @@ -5547,7 +5653,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet) if (li->li_tv.v_type != VAR_STRING) { goto err; } - reg->y_array[i++] = (uint8_t *)xstrdup((char *)li->li_tv.vval.v_string); + reg->y_array[i++] = (char_u *)xstrdupnul((char *)li->li_tv.vval.v_string); } if (reg->y_size > 0 && strlen((char*)reg->y_array[reg->y_size-1]) == 0) { @@ -5605,40 +5711,44 @@ static void set_clipboard(int name, yankreg_T *reg) return; } - list_T *lines = list_alloc(); + list_T *lines = tv_list_alloc(); for (size_t i = 0; i < reg->y_size; i++) { - list_append_string(lines, reg->y_array[i], -1); + tv_list_append_string(lines, (const char *)reg->y_array[i], -1); } - list_T *args = list_alloc(); - list_append_list(args, lines); + list_T *args = tv_list_alloc(); + tv_list_append_list(args, lines); - char_u regtype; + char regtype; switch (reg->y_type) { - case kMTLineWise: - regtype = 'V'; - list_append_string(lines, (char_u*)"", 0); - break; - case kMTCharWise: - regtype = 'v'; - break; - case kMTBlockWise: - regtype = 'b'; - list_append_string(lines, (char_u*)"", 0); - break; - case kMTUnknown: - assert(false); - } - list_append_string(args, ®type, 1); - - char_u regname = (char_u)name; - list_append_string(args, ®name, 1); + case kMTLineWise: { + regtype = 'V'; + tv_list_append_string(lines, NULL, 0); + break; + } + case kMTCharWise: { + regtype = 'v'; + break; + } + case kMTBlockWise: { + regtype = 'b'; + tv_list_append_string(lines, NULL, 0); + break; + } + case kMTUnknown: { + assert(false); + } + } + tv_list_append_string(args, ®type, 1); + + const char regname = (char)name; + tv_list_append_string(args, ®name, 1); (void)eval_call_provider("clipboard", "set", args); } -/// Avoid clipboard (slow) during batch operations (i.e., a script). +/// Avoid slow things (clipboard) during batch operations (while/for-loops). void start_batch_changes(void) { if (++batch_change_count > 1) { @@ -5648,7 +5758,7 @@ void start_batch_changes(void) clipboard_needs_update = false; } -/// Update the clipboard after batch changes finished. +/// Counterpart to start_batch_changes(). void end_batch_changes(void) { if (--batch_change_count > 0) { @@ -5657,6 +5767,7 @@ void end_batch_changes(void) } clipboard_delay_update = false; if (clipboard_needs_update) { + // unnamed ("implicit" clipboard) set_clipboard(NUL, y_previous); clipboard_needs_update = false; } @@ -5682,7 +5793,7 @@ static inline bool reg_empty(const yankreg_T *const reg) /// @return Pointer that needs to be passed to next `op_register_iter` call or /// NULL if iteration is over. const void *op_register_iter(const void *const iter, char *const name, - yankreg_T *const reg) + yankreg_T *const reg, bool *is_unnamed) FUNC_ATTR_NONNULL_ARG(2, 3) FUNC_ATTR_WARN_UNUSED_RESULT { *name = NUL; @@ -5698,6 +5809,7 @@ const void *op_register_iter(const void *const iter, char *const name, int iter_off = (int)(iter_reg - &(y_regs[0])); *name = (char)get_register_name(iter_off); *reg = *iter_reg; + *is_unnamed = (iter_reg == y_previous); while (++iter_reg - &(y_regs[0]) < NUM_SAVED_REGISTERS) { if (!reg_empty(iter_reg)) { return (void *) iter_reg; @@ -5722,10 +5834,11 @@ size_t op_register_amount(void) /// Set register to a given value /// /// @param[in] name Register name. -/// @param[in] reg Register value. +/// @param[in] reg Register value. +/// @param[in] is_unnamed Whether to set the unnamed regiseter to reg /// /// @return true on success, false on failure. -bool op_register_set(const char name, const yankreg_T reg) +bool op_register_set(const char name, const yankreg_T reg, bool is_unnamed) { int i = op_reg_index(name); if (i == -1) { @@ -5733,6 +5846,10 @@ bool op_register_set(const char name, const yankreg_T reg) } free_register(&y_regs[i]); y_regs[i] = reg; + + if (is_unnamed) { + y_previous = &y_regs[i]; + } return true; } @@ -5749,3 +5866,20 @@ const yankreg_T *op_register_get(const char name) } return &y_regs[i]; } + +/// Set the previous yank register +/// +/// @param[in] name Register name. +/// +/// @return true on success, false on failure. +bool op_register_set_previous(const char name) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + int i = op_reg_index(name); + if (i == -1) { + return false; + } + + y_previous = &y_regs[i]; + return true; +} diff --git a/src/nvim/ops.h b/src/nvim/ops.h index 44df2e9e0c..a8867e02ea 100644 --- a/src/nvim/ops.h +++ b/src/nvim/ops.h @@ -6,8 +6,10 @@ #include "nvim/macros.h" #include "nvim/ascii.h" #include "nvim/types.h" -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" #include "nvim/os/time.h" +#include "nvim/normal.h" // for MotionType and oparg_T +#include "nvim/ex_cmds_defs.h" // for exarg_T typedef int (*Indenter)(void); diff --git a/src/nvim/option.c b/src/nvim/option.c index 52a8b19ca4..8ba10fd38a 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1,24 +1,24 @@ -/* - * Code to handle user-settable options. This is all pretty much table- - * driven. Checklist for adding a new option: - * - Put it in the options array below (copy an existing entry). - * - For a global option: Add a variable for it in option_defs.h. - * - For a buffer or window local option: - * - Add a PV_XX entry to the enum below. - * - Add a variable to the window or buffer struct in buffer_defs.h. - * - For a window option, add some code to copy_winopt(). - * - For a buffer option, add some code to buf_copy_options(). - * - For a buffer string option, add code to check_buf_options(). - * - If it's a numeric option, add any necessary bounds checks to do_set(). - * - If it's a list of flags, add some code in do_set(), search for WW_ALL. - * - When adding an option with expansion (P_EXPAND), but with a different - * default for Vi and Vim (no P_VI_DEF), add some code at VIMEXP. - * - Add documentation! One line in doc/help.txt, full description in - * options.txt, and any other related places. - * - Add an entry in runtime/optwin.vim. - * When making changes: - * - Adjust the help for the option in doc/option.txt. - */ +// 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 + +// User-settable options. Checklist for adding a new option: +// - Put it in options.lua +// - For a global option: Add a variable for it in option_defs.h. +// - For a buffer or window local option: +// - Add a BV_XX or WV_XX entry to option_defs.h +// - Add a variable to the window or buffer struct in buffer_defs.h. +// - For a window option, add some code to copy_winopt(). +// - For a window string option, add code to check_winopt() +// and clear_winopt(). If setting the option needs parsing, +// add some code to didset_window_options(). +// - For a buffer option, add some code to buf_copy_options(). +// - For a buffer string option, add code to check_buf_options(). +// - If it's a numeric option, add any necessary bounds checks to do_set(). +// - If it's a list of flags, add some code in do_set(), search for WW_ALL. +// - When adding an option with expansion (P_EXPAND), but with a different +// default for Vi and Vim (no P_VI_DEF), add some code at VIMEXP. +// - Add documentation! doc/options.txt, and any other related places. +// - Add an entry in runtime/optwin.vim. #define IN_OPTION_C #include <assert.h> @@ -31,6 +31,7 @@ #include <limits.h> #include "nvim/vim.h" +#include "nvim/macros.h" #include "nvim/ascii.h" #include "nvim/edit.h" #include "nvim/option.h" @@ -40,6 +41,7 @@ #include "nvim/diff.h" #include "nvim/digraph.h" #include "nvim/eval.h" +#include "nvim/eval/typval.h" #include "nvim/ex_cmds2.h" #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" @@ -65,6 +67,7 @@ #include "nvim/regexp.h" #include "nvim/screen.h" #include "nvim/spell.h" +#include "nvim/spellfile.h" #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/ui.h" @@ -213,12 +216,12 @@ typedef struct vimoption { #define P_VI_DEF 0x400U /* Use Vi default for Vim */ #define P_VIM 0x800U /* Vim option */ -/* when option changed, what to display: */ -#define P_RSTAT 0x1000U /* redraw status lines */ -#define P_RWIN 0x2000U /* redraw current window */ -#define P_RBUF 0x4000U /* redraw current buffer */ -#define P_RALL 0x6000U /* redraw all windows */ -#define P_RCLR 0x7000U /* clear and redraw all */ +// when option changed, what to display: +#define P_RSTAT 0x1000U ///< redraw status lines +#define P_RWIN 0x2000U ///< redraw current window and recompute text +#define P_RBUF 0x4000U ///< redraw current buffer and recompute text +#define P_RALL 0x6000U ///< redraw all windows +#define P_RCLR 0x7000U ///< clear and redraw all #define P_COMMA 0x8000U ///< comma separated list #define P_ONECOMMA 0x18000U ///< P_COMMA and cannot have two consecutive @@ -238,15 +241,18 @@ typedef struct vimoption { ///< when there is a redraw flag #define P_NO_DEF_EXP 0x8000000U ///< Do not expand default value. +#define P_RWINONLY 0x10000000U ///< only redraw current window + #define HIGHLIGHT_INIT \ "8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText," \ "d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr," \ "N:CursorLineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title," \ - "v:Visual,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn," \ + "v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn," \ "A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal," \ "B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel," \ "x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill," \ - "!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine" + "!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine," \ + "0:Whitespace,I:NormalNC" /* * options[] is initialized here. @@ -335,7 +341,7 @@ static inline size_t compute_double_colon_len(const char *const val, do { size_t dir_len; const char *dir; - iter = vim_colon_env_iter(val, iter, &dir, &dir_len); + iter = vim_env_iter(':', val, iter, &dir, &dir_len); if (dir != NULL && dir_len > 0) { ret += ((dir_len + memcnt(dir, ',', dir_len) + common_suf_len + !after_pathsep(dir, dir + dir_len)) * 2 @@ -379,8 +385,8 @@ static inline char *add_colon_dirs(char *dest, const char *const val, do { size_t dir_len; const char *dir; - iter = (forward ? vim_colon_env_iter : vim_colon_env_iter_rev)( - val, iter, &dir, &dir_len); + iter = (forward ? vim_env_iter : vim_env_iter_rev)(':', val, iter, &dir, + &dir_len); if (dir != NULL && dir_len > 0) { dest = strcpy_comma_escaped(dest, dir, dir_len); if (!after_pathsep(dest - 1, dest)) { @@ -607,7 +613,7 @@ void set_init_1(void) /* * 'maxmemtot' and 'maxmem' may have to be adjusted for available memory */ - opt_idx = findoption((char_u *)"maxmemtot"); + opt_idx = findoption("maxmemtot"); if (opt_idx >= 0) { { /* Use half of amount of memory available to Vim. */ @@ -617,7 +623,7 @@ void set_init_1(void) ? UINTPTR_MAX : (uintptr_t)(available_kib /2); options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n; - opt_idx = findoption((char_u *)"maxmem"); + opt_idx = findoption("maxmem"); if (opt_idx >= 0) { options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n; } @@ -648,7 +654,7 @@ void set_init_1(void) } } buf[j] = NUL; - opt_idx = findoption((char_u *)"cdpath"); + opt_idx = findoption("cdpath"); if (opt_idx >= 0) { options[opt_idx].def_val[VI_DEFAULT] = buf; options[opt_idx].flags |= P_DEF_ALLOCED; @@ -767,8 +773,9 @@ void set_init_1(void) * NOTE: mlterm's author is being asked to 'set' a variable * instead of an environment variable due to inheritance. */ - if (os_env_exists("MLTERM")) - set_option_value((char_u *)"tbidi", 1L, NULL, 0); + if (os_env_exists("MLTERM")) { + set_option_value("tbidi", 1L, NULL, 0); + } didset_options2(); @@ -778,7 +785,7 @@ void set_init_1(void) char_u *p = enc_locale(); if (p == NULL) { // use utf-8 as 'default' if locale encoding can't be detected. - p = vim_strsave((char_u *)"utf-8"); + p = (char_u *)xmemdupz(S_LEN("utf-8")); } fenc_default = p; @@ -885,7 +892,7 @@ set_options_default ( static void set_string_default(const char *name, char *val, bool allocated) FUNC_ATTR_NONNULL_ALL { - int opt_idx = findoption((char_u *)name); + int opt_idx = findoption(name); if (opt_idx >= 0) { if (options[opt_idx].flags & P_DEF_ALLOCED) { xfree(options[opt_idx].def_val[VI_DEFAULT]); @@ -907,9 +914,10 @@ void set_number_default(char *name, long val) { int opt_idx; - opt_idx = findoption((char_u *)name); - if (opt_idx >= 0) + opt_idx = findoption(name); + if (opt_idx >= 0) { options[opt_idx].def_val[VI_DEFAULT] = (char_u *)val; + } } #if defined(EXITFREE) @@ -937,11 +945,8 @@ void free_all_options(void) #endif -/* - * Initialize the options, part two: After getting Rows and Columns and - * setting 'term'. - */ -void set_init_2(void) +/// Initialize the options, part two: After getting Rows and Columns. +void set_init_2(bool headless) { int idx; @@ -950,20 +955,29 @@ void set_init_2(void) * wrong when the window height changes. */ set_number_default("scroll", Rows / 2); - idx = findoption((char_u *)"scroll"); - if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) + idx = findoption("scroll"); + if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) { set_option_default(idx, OPT_LOCAL, p_cp); + } comp_col(); /* * 'window' is only for backwards compatibility with Vi. * Default is Rows - 1. */ - if (!option_was_set((char_u *)"window")) + if (!option_was_set("window")) { p_window = Rows - 1; + } set_number_default("window", Rows - 1); - parse_shape_opt(SHAPE_CURSOR); /* set cursor shapes from 'guicursor' */ - (void)parse_printoptions(); /* parse 'printoptions' default value */ +#if 0 + // This bodges around problems that should be fixed in the TUI layer. + if (!headless && !os_term_is_nice()) { + set_string_option_direct((char_u *)"guicursor", -1, (char_u *)"", + OPT_GLOBAL, SID_NONE); + } +#endif + parse_shape_opt(SHAPE_CURSOR); // set cursor shapes from 'guicursor' + (void)parse_printoptions(); // parse 'printoptions' default value } /* @@ -979,16 +993,18 @@ void set_init_3(void) int idx_sp; int do_sp; - idx_srr = findoption((char_u *)"srr"); - if (idx_srr < 0) - do_srr = FALSE; - else + idx_srr = findoption("srr"); + if (idx_srr < 0) { + do_srr = false; + } else { do_srr = !(options[idx_srr].flags & P_WAS_SET); - idx_sp = findoption((char_u *)"sp"); - if (idx_sp < 0) - do_sp = FALSE; - else + } + idx_sp = findoption("sp"); + if (idx_sp < 0) { + do_sp = false; + } else { do_sp = !(options[idx_sp].flags & P_WAS_SET); + } size_t len = 0; char_u *p = (char_u *)invocation_path_tail(p_sh, &len); @@ -1032,7 +1048,7 @@ void set_init_3(void) } if (bufempty()) { - int idx_ffs = findoption((char_u *)"ffs"); + int idx_ffs = findoption_len(S_LEN("ffs")); // Apply the first entry of 'fileformats' to the initial buffer. if (idx_ffs >= 0 && (options[idx_ffs].flags & P_WAS_SET)) { @@ -1049,16 +1065,20 @@ void set_init_3(void) */ void set_helplang_default(const char *lang) { - int idx; + if (lang == NULL) { + return; + } - if (lang == NULL || STRLEN(lang) < 2) /* safety check */ + const size_t lang_len = strlen(lang); + if (lang_len < 2) { // safety check return; - idx = findoption((char_u *)"hlg"); + } + 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 = (char_u *)xstrdup(lang); - /* zh_CN becomes "cn", zh_TW becomes "tw". */ + p_hlg = (char_u *)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_u)TOLOWER_ASC(p_hlg[3]); p_hlg[1] = (char_u)TOLOWER_ASC(p_hlg[4]); @@ -1085,12 +1105,12 @@ void set_title_defaults(void) * icon name. Saves a bit of time, because the X11 display server does * not need to be contacted. */ - idx1 = findoption((char_u *)"title"); + idx1 = findoption("title"); if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) { options[idx1].def_val[VI_DEFAULT] = (char_u *)(intptr_t)0; p_title = 0; } - idx1 = findoption((char_u *)"icon"); + idx1 = findoption("icon"); if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) { options[idx1].def_val[VI_DEFAULT] = (char_u *)(intptr_t)0; p_icon = 0; @@ -1127,7 +1147,7 @@ do_set ( int afterchar; /* character just after option name */ int len; int i; - long value; + varnumber_T value; int key; uint32_t flags; /* flags for current option */ char_u *varp = NULL; /* pointer to variable for current option */ @@ -1165,10 +1185,6 @@ do_set ( showoptions(1, opt_flags); did_show = TRUE; } - } else if (STRNCMP(arg, "termcap", - 7) == 0 && !(opt_flags & OPT_MODELINE)) { - did_show = TRUE; - arg += 7; } else { prefix = 1; if (STRNCMP(arg, "no", 2) == 0) { @@ -1196,7 +1212,7 @@ do_set ( goto skip; } if (arg[1] == 't' && arg[2] == '_') { // could be term code - opt_idx = findoption_len(arg + 1, (size_t) (len - 1)); + opt_idx = findoption_len((const char *)arg + 1, (size_t)(len - 1)); } len++; if (opt_idx == -1) { @@ -1212,7 +1228,7 @@ do_set ( len++; } } - opt_idx = findoption_len(arg, (size_t) len); + opt_idx = findoption_len((const char *)arg, (size_t)len); if (opt_idx == -1) { key = find_key_option(arg); } @@ -1394,10 +1410,10 @@ do_set ( value = prefix; } - errmsg = set_bool_option(opt_idx, varp, (int)value, - opt_flags); - } else { /* numeric or string */ - if (vim_strchr((char_u *)"=:&<", nextchar) == NULL + errmsg = (char_u *)set_bool_option(opt_idx, varp, (int)value, + opt_flags); + } else { // Numeric or string. + if (vim_strchr((const char_u *)"=:&<", nextchar) == NULL || prefix != 1) { errmsg = e_invarg; goto skip; @@ -1451,15 +1467,19 @@ do_set ( goto skip; } - if (adding) + if (adding) { value = *(long *)varp + value; - if (prepending) + } + if (prepending) { value = *(long *)varp * value; - if (removing) + } + if (removing) { value = *(long *)varp - value; - errmsg = set_num_option(opt_idx, varp, value, - errbuf, sizeof(errbuf), opt_flags); - } else if (opt_idx >= 0) { /* string */ + } + errmsg = (char_u *)set_num_option(opt_idx, varp, (long)value, + errbuf, sizeof(errbuf), + opt_flags); + } else if (opt_idx >= 0) { // String. char_u *save_arg = NULL; char_u *s = NULL; char_u *oldval = NULL; // previous value if *varp @@ -1493,7 +1513,7 @@ do_set ( new_value_alloced = true; if (newval == NULL) { newval = empty_option; - } else if (!(options[opt_idx].flags | P_NO_DEF_EXP)) { + } else if (!(options[opt_idx].flags & P_NO_DEF_EXP)) { s = option_expand(opt_idx, newval); if (s == NULL) { s = newval; @@ -1931,15 +1951,7 @@ did_set_title ( { if (starting != NO_SCREEN) { maketitle(); - if (icon) { - if (!p_icon) { - ui_set_icon(NULL); - } - } else { - if (!p_title) { - ui_set_title(NULL); - } - } + resettitle(); } } @@ -2111,7 +2123,7 @@ static void didset_options(void) static void didset_options2(void) { // Initialize the highlight_attr[] table. - (void)highlight_changed(); + highlight_changed(); // Parse default for 'clipboard'. (void)opt_strings_flags(p_cb, p_cb_values, &cb_flags, true); @@ -2152,6 +2164,7 @@ void check_buf_options(buf_T *buf) check_string_option(&buf->b_p_inex); check_string_option(&buf->b_p_inde); check_string_option(&buf->b_p_indk); + check_string_option(&buf->b_p_fp); check_string_option(&buf->b_p_fex); check_string_option(&buf->b_p_kp); check_string_option(&buf->b_p_mps); @@ -2223,7 +2236,7 @@ static void check_string_option(char_u **pp) */ int was_set_insecurely(char_u *opt, int opt_flags) { - int idx = findoption(opt); + int idx = findoption((const char *)opt); if (idx >= 0) { uint32_t *flagp = insecure_flag(idx, opt_flags); @@ -2285,9 +2298,9 @@ set_string_option_direct ( int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0; int idx = opt_idx; - if (idx == -1) { /* use name */ - idx = findoption(name); - if (idx < 0) { /* not found (should not happen) */ + if (idx == -1) { // Use name. + idx = findoption((const char *)name); + if (idx < 0) { // Not found (should not happen). EMSG2(_(e_intern2), "set_string_option_direct()"); EMSG2(_("For option %s"), name); return; @@ -2440,12 +2453,11 @@ did_set_string_option ( if ((secure || sandbox != 0) && (options[opt_idx].flags & P_SECURE)) { errmsg = e_secure; - } - /* Check for a "normal" file name in some options. Disallow a path - * separator (slash and/or backslash), wildcards and characters that are - * often illegal in a file name. */ - else if ((options[opt_idx].flags & P_NFNAME) - && vim_strpbrk(*varp, (char_u *)"/\\*?[|<>") != NULL) { + } else if ((options[opt_idx].flags & P_NFNAME) + && vim_strpbrk(*varp, (char_u *)"/\\*?[|;&<>\r\n") != NULL) { + // Check for a "normal" file name in some options. Disallow a path + // separator (slash and/or backslash), wildcards and characters that are + // often illegal in a file name. errmsg = e_invarg; } /* 'backupcopy' */ @@ -2524,11 +2536,11 @@ did_set_string_option ( if (s[2] == NUL) break; } - } - /* 'highlight' */ - else if (varp == &p_hl) { - if (highlight_changed() == FAIL) - errmsg = e_invarg; /* invalid flags */ + } else if (varp == &p_hl) { + // 'highlight' + if (strcmp((char *)(*varp), HIGHLIGHT_INIT) != 0) { + errmsg = e_unsupportedoption; + } } /* 'nrformats' */ else if (gvarp == &p_nf) { @@ -2567,12 +2579,11 @@ did_set_string_option ( init_highlight(FALSE, FALSE); - if (dark != (*p_bg == 'd') - && get_var_value((char_u *)"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((char_u *)"g:colors_name", TRUE); + 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 = vim_strsave((char_u *)(dark ? "dark" : "light")); check_string_option(&p_bg); @@ -2626,7 +2637,7 @@ did_set_string_option ( if (varp == &p_enc) { // only encoding=utf-8 allowed if (STRCMP(p_enc, "utf-8") != 0) { - errmsg = e_invarg; + errmsg = e_unsupportedoption; } } } @@ -2768,7 +2779,7 @@ did_set_string_option ( // option. opt_idx = ((options[opt_idx].fullname[0] == 'v') ? (shada_idx == -1 - ? ((shada_idx = findoption((char_u *) "shada"))) + ? ((shada_idx = findoption("shada"))) : shada_idx) : opt_idx); // Update free_oldval now that we have the opt_idx for 'shada', otherwise @@ -2829,9 +2840,10 @@ did_set_string_option ( } } - /* 'guicursor' */ - else if (varp == &p_guicursor) + // 'guicursor' + else if (varp == &p_guicursor) { errmsg = parse_shape_opt(SHAPE_CURSOR); + } else if (varp == &p_popt) errmsg = parse_printoptions(); @@ -3017,7 +3029,7 @@ did_set_string_option ( /* 'pastetoggle': translate key codes like in a mapping */ else if (varp == &p_pt) { if (*p_pt) { - (void)replace_termcodes(p_pt, STRLEN(p_pt), &p, true, true, false, + (void)replace_termcodes(p_pt, STRLEN(p_pt), &p, true, true, true, CPO_TO_CPO_FLAGS); if (p != NULL) { if (new_value_alloced) @@ -3152,6 +3164,10 @@ did_set_string_option ( if (!valid_filetype(*varp)) { errmsg = e_invarg; } + } else if (varp == &curwin->w_p_winhl) { + if (!parse_winhl_opt(curwin)) { + errmsg = e_invarg; + } } else { // Options that are a list of flags. p = NULL; @@ -3189,8 +3205,6 @@ did_set_string_option ( */ if (did_chartab) (void)init_chartab(); - if (varp == &p_hl) - (void)highlight_changed(); } else { /* Remember where the option was set. */ set_option_scriptID_idx(opt_idx, opt_flags, current_SID); @@ -3256,7 +3270,7 @@ did_set_string_option ( if (varp == &p_mouse) { if (*p_mouse == NUL) { - ui_mouse_off(); + ui_call_mouse_off(); } else { setmouse(); // in case 'mouse' changed } @@ -3409,15 +3423,18 @@ static char_u *set_chars_option(char_u **varp) && p[len] == ':' && p[len + 1] != NUL) { s = p + len + 1; - c1 = mb_ptr2char_adv(&s); - if (mb_char2cells(c1) > 1) + c1 = mb_ptr2char_adv((const char_u **)&s); + if (mb_char2cells(c1) > 1) { continue; + } if (tab[i].cp == &lcs_tab2) { - if (*s == NUL) + if (*s == NUL) { continue; - c2 = mb_ptr2char_adv(&s); - if (mb_char2cells(c2) > 1) + } + c2 = mb_ptr2char_adv((const char_u **)&s); + if (mb_char2cells(c2) > 1) { continue; + } } if (*s == ',' || *s == NUL) { if (round) { @@ -3557,6 +3574,47 @@ static char_u *compile_cap_prog(synblock_T *synblock) return NULL; } +/// Handle setting `winhighlight' in window "wp" +static bool parse_winhl_opt(win_T *wp) +{ + int w_hl_id_normal = 0; + int w_hl_ids[HLF_COUNT] = { 0 }; + int hlf; + + const char *p = (const char *)wp->w_p_winhl; + while (*p) { + char *colon = strchr(p, ':'); + if (!colon) { + return false; + } + size_t nlen = (size_t)(colon-p); + char *hi = colon+1; + char *commap = xstrchrnul(hi, ','); + int hl_id = syn_check_group((char_u *)hi, (int)(commap-hi)); + + if (strncmp("Normal", p, nlen) == 0) { + w_hl_id_normal = hl_id; + } else { + for (hlf = 0; hlf < (int)HLF_COUNT; hlf++) { + if (strncmp(hlf_names[hlf], p, nlen) == 0) { + w_hl_ids[hlf] = hl_id; + break; + } + } + if (hlf == HLF_COUNT) { + return false; + } + } + + p = *commap ? commap+1 : ""; + } + + wp->w_hl_id_normal = w_hl_id_normal; + memcpy(wp->w_hl_ids, w_hl_ids, sizeof(w_hl_ids)); + wp->w_hl_needs_update = true; + return true; +} + /* * Set the scriptID for an option, taking care of setting the buffer- or * window-local value. @@ -3578,24 +3636,24 @@ static void set_option_scriptID_idx(int opt_idx, int opt_flags, int id) } } -/* - * Set the value of a boolean option, and take care of side effects. - * Returns NULL for success, or an error message for an error. - */ -static char_u * -set_bool_option ( - int opt_idx, /* index in options[] table */ - char_u *varp, /* pointer to the option variable */ - int value, /* new value */ - int opt_flags /* OPT_LOCAL and/or OPT_GLOBAL */ -) +/// Set the value of a boolean option, taking care of side effects +/// +/// @param[in] opt_idx Option index in options[] table. +/// @param[out] varp Pointer to the option variable. +/// @param[in] value New value. +/// @param[in] opt_flags OPT_LOCAL and/or OPT_GLOBAL. +/// +/// @return NULL on success, error message on error. +static char *set_bool_option(const int opt_idx, char_u *const varp, + const int value, + const int opt_flags) { int old_value = *(int *)varp; /* Disallow changing some options from secure mode */ if ((secure || sandbox != 0) && (options[opt_idx].flags & P_SECURE)) { - return e_secure; + return (char *)e_secure; } *(int *)varp = value; /* set the new value */ @@ -3608,29 +3666,34 @@ set_bool_option ( *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = value; // Ensure that options set to p_force_on cannot be disabled. - if ((int *)varp == &p_force_on && p_force_on == FALSE) { - p_force_on = TRUE; - return e_unsupportedoption; - } + if ((int *)varp == &p_force_on && p_force_on == false) { + p_force_on = true; + return (char *)e_unsupportedoption; // Ensure that options set to p_force_off cannot be enabled. - else if ((int *)varp == &p_force_off && p_force_off == TRUE) { - p_force_off = FALSE; - return e_unsupportedoption; - } - /* 'undofile' */ - else if ((int *)varp == &curbuf->b_p_udf || (int *)varp == &p_udf) { - /* Only take action when the option was set. When reset we do not - * delete the undo file, the option may be set again without making - * any changes in between. */ + } else if ((int *)varp == &p_force_off && p_force_off == true) { + p_force_off = false; + return (char *)e_unsupportedoption; + } else if ((int *)varp == &p_lrm) { + // 'langremap' -> !'langnoremap' + p_lnr = !p_lrm; + } else if ((int *)varp == &p_lnr) { + // 'langnoremap' -> !'langremap' + p_lrm = !p_lnr; + // 'undofile' + } else if ((int *)varp == &curbuf->b_p_udf || (int *)varp == &p_udf) { + // Only take action when the option was set. When reset we do not + // delete the undo file, the option may be set again without making + // any changes in between. if (curbuf->b_p_udf || p_udf) { char_u hash[UNDO_HASH_SIZE]; buf_T *save_curbuf = curbuf; - for (curbuf = firstbuf; curbuf != NULL; curbuf = curbuf->b_next) { - /* When 'undofile' is set globally: for every buffer, otherwise - * only for the current buffer: Try to read in the undofile, - * if one exists, the buffer wasn't changed and the buffer was - * loaded */ + FOR_ALL_BUFFERS(bp) { + curbuf = bp; + // When 'undofile' is set globally: for every buffer, otherwise + // only for the current buffer: Try to read in the undofile, + // if one exists, the buffer wasn't changed and the buffer was + // loaded if ((curbuf == save_curbuf || (opt_flags & OPT_GLOBAL) || opt_flags == 0) && !curbufIsChanged() && curbuf->b_ml.ml_mfp != NULL) { @@ -3742,8 +3805,8 @@ set_bool_option ( if (curwin->w_p_pvw) { FOR_ALL_WINDOWS_IN_TAB(win, curtab) { if (win->w_p_pvw && win != curwin) { - curwin->w_p_pvw = FALSE; - return (char_u *)N_("E590: A preview window already exists"); + curwin->w_p_pvw = false; + return N_("E590: A preview window already exists"); } } } @@ -3884,16 +3947,15 @@ set_bool_option ( "W17: Arabic requires UTF-8, do ':set encoding=utf-8'"); msg_source(hl_attr(HLF_W)); - MSG_ATTR(_(w_arabic), hl_attr(HLF_W)); + msg_attr(_(w_arabic), hl_attr(HLF_W)); set_vim_var_string(VV_WARNINGMSG, _(w_arabic), -1); } /* set 'delcombine' */ p_deco = TRUE; - /* Force-set the necessary keymap for arabic */ - set_option_value((char_u *)"keymap", 0L, (char_u *)"arabic", - OPT_LOCAL); + // Force-set the necessary keymap for arabic. + set_option_value("keymap", 0L, "arabic", OPT_LOCAL); p_altkeymap = 0; p_hkmap = 0; p_fkmap = 0; @@ -3959,20 +4021,18 @@ set_bool_option ( return NULL; } -/* - * Set the value of a number option, and take care of side effects. - * Returns NULL for success, or an error message for an error. - */ -static char_u * -set_num_option ( - int opt_idx, /* index in options[] table */ - char_u *varp, /* pointer to the option variable */ - long value, /* new value */ - char_u *errbuf, /* buffer for error messages */ - size_t errbuflen, /* length of "errbuf" */ - int opt_flags /* OPT_LOCAL, OPT_GLOBAL and - OPT_MODELINE */ -) +/// Set the value of a number option, taking care of side effects +/// +/// @param[in] opt_idx Option index in options[] table. +/// @param[out] varp Pointer to the option variable. +/// @param[in] value New value. +/// @param errbuf Buffer for error messages. +/// @param[in] errbuflen Length of `errbuf`. +/// @param[in] opt_flags OPT_LOCAL, OPT_GLOBAL or OPT_MODELINE. +/// +/// @return NULL on success, error message on error. +static char *set_num_option(int opt_idx, char_u *varp, long value, + char_u *errbuf, size_t errbuflen, int opt_flags) { char_u *errmsg = NULL; long old_value = *(long *)varp; @@ -3983,7 +4043,7 @@ set_num_option ( /* Disallow changing some options from secure mode. */ if ((secure || sandbox != 0) && (options[opt_idx].flags & P_SECURE)) { - return e_secure; + return (char *)e_secure; } *pp = value; @@ -4013,7 +4073,7 @@ set_num_option ( } /* Change window height NOW */ - if (lastwin != firstwin) { + if (!ONE_WINDOW) { if (pp == &p_wh && curwin->w_height < p_wh) win_setheight((int)p_wh); if (pp == &p_hh && curbuf->b_help && curwin->w_height < p_hh) @@ -4042,7 +4102,7 @@ set_num_option ( } /* Change window width NOW */ - if (lastwin != firstwin && curwin->w_width < p_wiw) + if (!ONE_WINDOW && curwin->w_width < p_wiw) win_setwidth((int)p_wiw); } /* 'winminwidth' */ @@ -4200,7 +4260,16 @@ set_num_option ( FOR_ALL_TAB_WINDOWS(tp, wp) { check_colorcolumn(wp); } - + } else if (pp == &curbuf->b_p_scbk || pp == &p_scbk) { + // 'scrollback' + if (*pp < -1 || *pp > SB_MAX + || (*pp != -1 && opt_flags == OPT_LOCAL && !curbuf->terminal)) { + errmsg = e_invarg; + *pp = old_value; + } else if (curbuf->terminal) { + // Force the scrollback to take effect. + terminal_resize(curbuf->terminal, UINT16_MAX, UINT16_MAX); + } } /* @@ -4244,8 +4313,9 @@ set_num_option ( cmdline_row = (int)(Rows - p_ch); } } - if (p_window >= Rows || !option_was_set((char_u *)"window")) + if (p_window >= Rows || !option_was_set("window")) { p_window = Rows - 1; + } } if (curbuf->b_p_ts <= 0) { @@ -4320,6 +4390,11 @@ set_num_option ( if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = *pp; + if (pp == &curbuf->b_p_scbk && !curbuf->terminal) { + // Normal buffer: reset local 'scrollback' after updating the global value. + curbuf->b_p_scbk = -1; + } + options[opt_idx].flags |= P_WAS_SET; if (!starting && errmsg == NULL) { @@ -4345,7 +4420,7 @@ set_num_option ( curwin->w_set_curswant = TRUE; check_redraw(options[opt_idx].flags); - return errmsg; + return (char *)errmsg; } /* @@ -4357,17 +4432,24 @@ static void check_redraw(uint32_t flags) bool doclear = (flags & P_RCLR) == P_RCLR; bool all = ((flags & P_RALL) == P_RALL || doclear); - if ((flags & P_RSTAT) || all) /* mark all status lines dirty */ + if ((flags & P_RSTAT) || all) { // mark all status lines dirty status_redraw_all(); + } - if ((flags & P_RBUF) || (flags & P_RWIN) || all) + if ((flags & P_RBUF) || (flags & P_RWIN) || all) { changed_window_setting(); - if (flags & P_RBUF) + } + if (flags & P_RBUF) { redraw_curbuf_later(NOT_VALID); - if (doclear) + } + if (flags & P_RWINONLY) { + redraw_later(NOT_VALID); + } + if (doclear) { redraw_all_later(CLEAR); - else if (all) + } else if (all) { redraw_all_later(NOT_VALID); + } } /// Find index for named option @@ -4376,39 +4458,36 @@ static void check_redraw(uint32_t flags) /// @param[in] len Length of the option. /// /// @return Index of the option or -1 if option was not found. -int findoption_len(const char_u *const arg, const size_t len) +int findoption_len(const char *const arg, const size_t len) { - char *s, *p; + const char *s; + const char *p; static int quick_tab[27] = { 0, 0 }; // quick access table - int is_term_opt; - /* - * For first call: Initialize the quick-access table. - * It contains the index for the first option that starts with a certain - * letter. There are 26 letters, plus the first "t_" option. - */ + // For first call: Initialize the quick-access table. + // It contains the index for the first option that starts with a certain + // letter. There are 26 letters, plus the first "t_" option. if (quick_tab[1] == 0) { p = options[0].fullname; for (short int i = 1; (s = options[i].fullname) != NULL; i++) { if (s[0] != p[0]) { - if (s[0] == 't' && s[1] == '_') + if (s[0] == 't' && s[1] == '_') { quick_tab[26] = i; - else + } else { quick_tab[CharOrdLow(s[0])] = i; + } } p = s; } } - /* - * Check for name starting with an illegal character. - */ + // Check for name starting with an illegal character. if (len == 0 || arg[0] < 'a' || arg[0] > 'z') { return -1; } int opt_idx; - is_term_opt = (len > 2 && arg[0] == 't' && arg[1] == '_'); + const bool is_term_opt = (len > 2 && arg[0] == 't' && arg[1] == '_'); if (is_term_opt) { opt_idx = quick_tab[26]; } else { @@ -4416,7 +4495,7 @@ int findoption_len(const char_u *const arg, const size_t len) } // Match full name for (; (s = options[opt_idx].fullname) != NULL; opt_idx++) { - if (STRNCMP(arg, s, len) == 0 && s[len] == NUL) { + if (strncmp(arg, s, len) == 0 && s[len] == NUL) { break; } } @@ -4425,20 +4504,22 @@ int findoption_len(const char_u *const arg, const size_t len) // Match short name for (; options[opt_idx].fullname != NULL; opt_idx++) { s = options[opt_idx].shortname; - if (s != NULL && STRNCMP(arg, s, len) == 0 && s[len] == NUL) { + if (s != NULL && strncmp(arg, s, len) == 0 && s[len] == NUL) { break; } s = NULL; } } - if (s == NULL) + if (s == NULL) { opt_idx = -1; + } return opt_idx; } -bool is_tty_option(char *name) +bool is_tty_option(const char *name) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { - return (name[0] == 't' && name[1] == '_') || !strcmp((char *)name, "term"); + return (name[0] == 't' && name[1] == '_') || strcmp(name, "term") == 0; } #define TCO_BUFFER_SIZE 8 @@ -4474,7 +4555,7 @@ bool get_tty_option(char *name, char **value) return false; } -bool set_tty_option(char *name, char *value) +bool set_tty_option(const char *name, const char *value) { if (!strcmp(name, "t_Co")) { int colors = atoi(value); @@ -4485,23 +4566,24 @@ bool set_tty_option(char *name, char *value) if (colors != t_colors) { t_colors = colors; // We now have a different color setup, initialize it again. - init_highlight(TRUE, FALSE); + init_highlight(true, false); } return true; } - return is_tty_option(name) || !strcmp(name, "term") - || !strcmp(name, "ttytype"); + return (is_tty_option(name) || !strcmp(name, "term") + || !strcmp(name, "ttytype")); } -/* - * Find index for option 'arg'. - * Return -1 if not found. - */ -static int findoption(char_u *arg) +/// Find index for an option +/// +/// @param[in] arg Option name. +/// +/// @return Option index or -1 if option was not found. +static int findoption(const char *const arg) { - return findoption_len(arg, STRLEN(arg)); + return findoption_len(arg, strlen(arg)); } /* @@ -4529,9 +4611,10 @@ get_option_value ( int opt_idx; char_u *varp; - opt_idx = findoption(name); - if (opt_idx < 0) /* unknown option */ + opt_idx = findoption((const char *)name); + if (opt_idx < 0) { // Unknown option. return -3; + } varp = get_varp_scope(&(options[opt_idx]), opt_flags); @@ -4554,7 +4637,7 @@ get_option_value ( if ((int *)varp == &curbuf->b_changed) { *numval = curbufIsChanged(); } else { - *numval = *(int *)varp; + *numval = (long) *(int *)varp; // NOLINT(whitespace/cast) } } return 1; @@ -4568,7 +4651,7 @@ get_option_value ( // // Pretends that option is absent if it is not present in the requested scope // (i.e. has no global, window-local or buffer-local value depending on -// opt_type). Uses +// opt_type). // // Returned flags: // 0 hidden or unknown option, also option that does not have requested @@ -4587,14 +4670,13 @@ int get_option_value_strict(char *name, } char_u *varp = NULL; - vimoption_T *p; int rv = 0; - int opt_idx = findoption((uint8_t *)name); + int opt_idx = findoption(name); if (opt_idx < 0) { return 0; } - p = &(options[opt_idx]); + vimoption_T *p = &options[opt_idx]; // Hidden option if (p->var == NULL) { @@ -4610,26 +4692,25 @@ int get_option_value_strict(char *name, } if (p->indir == PV_NONE) { - if (opt_type == SREQ_GLOBAL) + if (opt_type == SREQ_GLOBAL) { rv |= SOPT_GLOBAL; - else - return 0; // Did not request global-only option + } else { + return 0; // Did not request global-only option + } } else { if (p->indir & PV_BOTH) { rv |= SOPT_GLOBAL; - } else if (opt_type == SREQ_GLOBAL) { - return 0; // Requested global option } if (p->indir & PV_WIN) { if (opt_type == SREQ_BUF) { - return 0; // Did not request window-local option + return 0; // Requested buffer-local, not window-local option } else { rv |= SOPT_WIN; } } else if (p->indir & PV_BUF) { if (opt_type == SREQ_WIN) { - return 0; // Did not request buffer-local option + return 0; // Requested window-local, not buffer-local option } else { rv |= SOPT_BUF; } @@ -4641,7 +4722,11 @@ int get_option_value_strict(char *name, } if (opt_type == SREQ_GLOBAL) { - varp = p->var; + if (p->var == VAR_WIN) { + return 0; + } else { + varp = p->var; + } } else { if (opt_type == SREQ_BUF) { // Special case: 'modified' is b_changed, but we also want to @@ -4683,21 +4768,19 @@ int get_option_value_strict(char *name, return rv; } -/* - * Set the value of option "name". - * Use "string" for string options, use "number" for other options. - * - * Returns NULL on success or error message on error. - */ -char_u * -set_option_value ( - char_u *name, - long number, - char_u *string, - int opt_flags /* OPT_LOCAL or 0 (both) */ -) +/// Set the value of an option +/// +/// @param[in] name Option name. +/// @param[in] number New value for the number or boolean option. +/// @param[in] string New value for string option. +/// @param[in] opt_flags Flags: OPT_LOCAL, OPT_GLOBAL, or 0 (both). +/// +/// @return NULL on success, error message on error. +char *set_option_value(const char *const name, const long number, + const char *const string, const int opt_flags) + FUNC_ATTR_NONNULL_ARG(1) { - if (set_tty_option((char *)name, (char *)string)) { + if (set_tty_option(name, string)) { return NULL; } @@ -4705,9 +4788,9 @@ set_option_value ( char_u *varp; opt_idx = findoption(name); - if (opt_idx < 0) + if (opt_idx < 0) { EMSG2(_("E355: Unknown option: %s"), name); - else { + } else { uint32_t flags = options[opt_idx].flags; // Disallow changing some options in the sandbox if (sandbox > 0 && (flags & P_SECURE)) { @@ -4715,11 +4798,11 @@ set_option_value ( return NULL; } if (flags & P_STRING) { - const char *s = (const char *)string; + const char *s = string; if (s == NULL) { s = ""; } - return (char_u *)set_string_option(opt_idx, s, opt_flags); + return set_string_option(opt_idx, s, opt_flags); } else { varp = get_varp_scope(&(options[opt_idx]), opt_flags); if (varp != NULL) { /* hidden option is not changed */ @@ -4738,28 +4821,17 @@ set_option_value ( return NULL; // do nothing as we hit an error } } - if (flags & P_NUM) - return set_num_option(opt_idx, varp, number, - NULL, 0, opt_flags); - else - return set_bool_option(opt_idx, varp, (int)number, - opt_flags); + if (flags & P_NUM) { + return set_num_option(opt_idx, varp, number, NULL, 0, opt_flags); + } else { + return set_bool_option(opt_idx, varp, (int)number, opt_flags); + } } } } return NULL; } -char_u *get_highlight_default(void) -{ - int i; - - i = findoption((char_u *)"hl"); - if (i >= 0) - return options[i].def_val[VI_DEFAULT]; - return (char_u *)NULL; -} - /* * Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number. */ @@ -4775,7 +4847,7 @@ int find_key_option_len(const char_u *arg, size_t len) } else { arg--; // put arg at the '<' modifiers = 0; - key = find_special_key(&arg, len + 1, &modifiers, true, true); + key = find_special_key(&arg, len + 1, &modifiers, true, true, false); if (modifiers) { // can't handle modifiers here key = 0; } @@ -5101,9 +5173,13 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, int e * CTRL-V or backslash */ if (valuep == &p_pt) { s = *valuep; - while (*s != NUL) - if (put_escstr(fd, str2special(&s, FALSE), 2) == FAIL) + while (*s != NUL) { + if (put_escstr(fd, (char_u *)str2special((const char **)&s, false, + false), 2) + == FAIL) { return FAIL; + } + } } else if (expand) { buf = xmalloc(MAXPATHL); home_replace(NULL, *valuep, buf, MAXPATHL, FALSE); @@ -5158,7 +5234,7 @@ static int put_setbool(FILE *fd, char *cmd, char *name, int value) void comp_col(void) { - int last_has_status = (p_ls == 2 || (p_ls == 1 && firstwin != lastwin)); + int last_has_status = (p_ls == 2 || (p_ls == 1 && !ONE_WINDOW)); sc_col = 0; ru_col = 0; @@ -5193,7 +5269,7 @@ void unset_global_local_option(char *name, void *from) vimoption_T *p; buf_T *buf = (buf_T *)from; - int opt_idx = findoption((uint8_t *)name); + int opt_idx = findoption(name); if (opt_idx < 0) { EMSG2(_("E355: Unknown option: %s"), name); return; @@ -5238,6 +5314,9 @@ void unset_global_local_option(char *name, void *from) case PV_TSR: clear_string_option(&buf->b_p_tsr); break; + case PV_FP: + clear_string_option(&buf->b_p_fp); + break; case PV_EFM: clear_string_option(&buf->b_p_efm); break; @@ -5271,6 +5350,7 @@ static char_u *get_varp_scope(vimoption_T *p, int opt_flags) } if ((opt_flags & OPT_LOCAL) && ((int)p->indir & PV_BOTH)) { switch ((int)p->indir) { + case PV_FP: return (char_u *)&(curbuf->b_p_fp); case PV_EFM: return (char_u *)&(curbuf->b_p_efm); case PV_GP: return (char_u *)&(curbuf->b_p_gp); case PV_MP: return (char_u *)&(curbuf->b_p_mp); @@ -5329,6 +5409,8 @@ static char_u *get_varp(vimoption_T *p) ? (char_u *)&(curbuf->b_p_dict) : p->var; case PV_TSR: return *curbuf->b_p_tsr != NUL ? (char_u *)&(curbuf->b_p_tsr) : p->var; + case PV_FP: return *curbuf->b_p_fp != NUL + ? (char_u *)&(curbuf->b_p_fp) : p->var; case PV_EFM: return *curbuf->b_p_efm != NUL ? (char_u *)&(curbuf->b_p_efm) : p->var; case PV_GP: return *curbuf->b_p_gp != NUL @@ -5418,6 +5500,7 @@ static char_u *get_varp(vimoption_T *p) case PV_PI: return (char_u *)&(curbuf->b_p_pi); case PV_QE: return (char_u *)&(curbuf->b_p_qe); case PV_RO: return (char_u *)&(curbuf->b_p_ro); + case PV_SCBK: return (char_u *)&(curbuf->b_p_scbk); case PV_SI: return (char_u *)&(curbuf->b_p_si); case PV_STS: return (char_u *)&(curbuf->b_p_sts); case PV_SUA: return (char_u *)&(curbuf->b_p_sua); @@ -5434,6 +5517,7 @@ static char_u *get_varp(vimoption_T *p) case PV_WM: return (char_u *)&(curbuf->b_p_wm); case PV_KMAP: return (char_u *)&(curbuf->b_p_keymap); case PV_SCL: return (char_u *)&(curwin->w_p_scl); + case PV_WINHL: return (char_u *)&(curwin->w_p_winhl); default: EMSG(_("E356: get_varp ERROR")); } /* always return a valid pointer to avoid a crash! */ @@ -5460,7 +5544,6 @@ void win_copy_options(win_T *wp_from, win_T *wp_to) copy_winopt(&wp_from->w_allbuf_opt, &wp_to->w_allbuf_opt); /* Is this right? */ wp_to->w_farsi = wp_from->w_farsi; - briopt_check(wp_to); } /* @@ -5512,6 +5595,7 @@ void copy_winopt(winopt_T *from, winopt_T *to) to->wo_fdt = vim_strsave(from->wo_fdt); to->wo_fmr = vim_strsave(from->wo_fmr); to->wo_scl = vim_strsave(from->wo_scl); + to->wo_winhl = vim_strsave(from->wo_winhl); check_winopt(to); // don't want NULL pointers } @@ -5541,6 +5625,7 @@ static void check_winopt(winopt_T *wop) check_string_option(&wop->wo_cc); check_string_option(&wop->wo_cocu); check_string_option(&wop->wo_briopt); + check_string_option(&wop->wo_winhl); } /* @@ -5560,8 +5645,17 @@ void clear_winopt(winopt_T *wop) clear_string_option(&wop->wo_cc); clear_string_option(&wop->wo_cocu); clear_string_option(&wop->wo_briopt); + clear_string_option(&wop->wo_winhl); } +void didset_window_options(win_T *wp) +{ + check_colorcolumn(wp); + briopt_check(wp); + parse_winhl_opt(wp); +} + + /* * Copy global option values to local options for one buffer. * Used when creating a new buffer and sometimes when entering a buffer. @@ -5579,12 +5673,6 @@ void buf_copy_options(buf_T *buf, int flags) int did_isk = FALSE; /* - * Don't do anything if the buffer is invalid. - */ - if (buf == NULL || !buf_valid(buf)) - return; - - /* * Skip this when the option defaults have not been set yet. Happens when * main() allocates the first buffer. */ @@ -5625,7 +5713,22 @@ void buf_copy_options(buf_T *buf, int flags) free_buf_options(buf, TRUE); buf->b_p_ro = FALSE; /* don't copy readonly */ buf->b_p_fenc = vim_strsave(p_fenc); - buf->b_p_ff = vim_strsave(p_ff); + switch (*p_ffs) { + case 'm': + buf->b_p_ff = vim_strsave((char_u *)FF_MAC); + break; + case 'd': + buf->b_p_ff = vim_strsave((char_u *)FF_DOS); + break; + case 'u': + buf->b_p_ff = vim_strsave((char_u *)FF_UNIX); + break; + default: + buf->b_p_ff = vim_strsave(p_ff); + } + if (buf->b_p_ff != NULL) { + buf->b_start_ffc = *buf->b_p_ff; + } buf->b_p_bh = empty_option; buf->b_p_bt = empty_option; } else @@ -5634,6 +5737,7 @@ void buf_copy_options(buf_T *buf, int flags) buf->b_p_ai = p_ai; buf->b_p_ai_nopaste = p_ai_nopaste; buf->b_p_sw = p_sw; + buf->b_p_scbk = -1; buf->b_p_tw = p_tw; buf->b_p_tw_nopaste = p_tw_nopaste; buf->b_p_tw_nobin = p_tw_nobin; @@ -5681,6 +5785,7 @@ void buf_copy_options(buf_T *buf, int flags) buf->b_s.b_p_spl = vim_strsave(p_spl); buf->b_p_inde = vim_strsave(p_inde); buf->b_p_indk = vim_strsave(p_indk); + buf->b_p_fp = empty_option; buf->b_p_fex = vim_strsave(p_fex); buf->b_p_sua = vim_strsave(p_sua); buf->b_p_keymap = vim_strsave(p_keymap); @@ -5753,11 +5858,12 @@ void reset_modifiable(void) { int opt_idx; - curbuf->b_p_ma = FALSE; - p_ma = FALSE; - opt_idx = findoption((char_u *)"ma"); - if (opt_idx >= 0) - options[opt_idx].def_val[VI_DEFAULT] = FALSE; + curbuf->b_p_ma = false; + p_ma = false; + opt_idx = findoption("ma"); + if (opt_idx >= 0) { + options[opt_idx].def_val[VI_DEFAULT] = false; + } } /* @@ -5855,15 +5961,15 @@ set_context_in_set_cmd ( expand_option_name[2] = p[-2]; expand_option_name[3] = p[-1]; } else { - /* Allow * wildcard */ - while (ASCII_ISALNUM(*p) || *p == '_' || *p == '*') + // Allow * wildcard. + while (ASCII_ISALNUM(*p) || *p == '_' || *p == '*') { p++; - if (*p == NUL) + } + if (*p == NUL) { return; + } nextchar = *p; - *p = NUL; - opt_idx = findoption(arg); - *p = nextchar; + opt_idx = findoption_len((const char *)arg, (size_t)(p - arg)); if (opt_idx == -1 || options[opt_idx].var == NULL) { xp->xp_context = EXPAND_NOTHING; return; @@ -5960,8 +6066,8 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u *** int count = 0; char_u *str; int loop; - static char *(names[]) = {"all", "termcap"}; - int ic = regmatch->rm_ic; /* remember the ignore-case flag */ + static char *(names[]) = { "all" }; + int ic = regmatch->rm_ic; // remember the ignore-case flag /* do this loop twice: * loop == 0: count the number of matching options @@ -6025,7 +6131,7 @@ void ExpandOldSetting(int *num_file, char_u ***file) * For a terminal key code expand_option_idx is < 0. */ if (expand_option_idx < 0) { - expand_option_idx = findoption(expand_option_name); + expand_option_idx = findoption((const char *)expand_option_name); } if (expand_option_idx >= 0) { @@ -6084,15 +6190,16 @@ option_value2string ( } } else { // P_STRING varp = *(char_u **)(varp); - if (varp == NULL) /* just in case */ + if (varp == NULL) { // Just in case. NameBuff[0] = NUL; - else if (opp->flags & P_EXPAND) - home_replace(NULL, varp, NameBuff, MAXPATHL, FALSE); - /* Translate 'pastetoggle' into special key names */ - else if ((char_u **)opp->var == &p_pt) - str2specialbuf(p_pt, NameBuff, MAXPATHL); - else + } else if (opp->flags & P_EXPAND) { + home_replace(NULL, varp, NameBuff, MAXPATHL, false); + // Translate 'pastetoggle' into special key names. + } else if ((char_u **)opp->var == &p_pt) { + str2specialbuf((const char *)p_pt, (char *)NameBuff, MAXPATHL); + } else { STRLCPY(NameBuff, varp, MAXPATHL); + } } } @@ -6425,20 +6532,22 @@ void vimrc_found(char_u *fname, char_u *envname) } } -/* - * Return TRUE when option "name" has been set. - * Only works correctly for global options. - */ -int option_was_set(char_u *name) +/// Check whether global option has been set +/// +/// @param[in] name Option name. +/// +/// @return True if it was set. +static bool option_was_set(const char *name) { int idx; idx = findoption(name); - if (idx < 0) /* unknown option */ - return FALSE; - if (options[idx].flags & P_WAS_SET) - return TRUE; - return FALSE; + if (idx < 0) { // Unknown option. + return false; + } else if (options[idx].flags & P_WAS_SET) { + return true; + } + return false; } /* @@ -6854,8 +6963,8 @@ void set_fileformat(int eol_style, int opt_flags) need_maketitle = true; // Set window title later. } -/// Skip to next part of an option argument: Skip space and comma. -char_u *skip_to_option_part(char_u *p) +/// Skip to next part of an option argument: skip space and comma +char_u *skip_to_option_part(const char_u *p) { if (*p == ',') { p++; @@ -6863,7 +6972,7 @@ char_u *skip_to_option_part(char_u *p) while (*p == ' ') { p++; } - return p; + return (char_u *)p; } /// Isolate one part of a string option separated by `sep_chars`. @@ -6923,10 +7032,11 @@ bool signcolumn_on(win_T *wp) return wp->w_buffer->b_signlist != NULL; } -/// Get window or buffer local options. -dict_T * get_winbuf_options(int bufopt) +/// Get window or buffer local options +dict_T *get_winbuf_options(const int bufopt) + FUNC_ATTR_WARN_UNUSED_RESULT { - dict_T *d = dict_alloc(); + dict_T *const d = tv_dict_alloc(); for (int opt_idx = 0; options[opt_idx].fullname; opt_idx++) { struct vimoption *opt = &options[opt_idx]; @@ -6937,9 +7047,13 @@ dict_T * get_winbuf_options(int bufopt) if (varp != NULL) { if (opt->flags & P_STRING) { - dict_add_nr_str(d, opt->fullname, 0L, *(char_u **)varp); + tv_dict_add_str(d, opt->fullname, strlen(opt->fullname), + *(const char **)varp); + } else if (opt->flags & P_NUM) { + tv_dict_add_nr(d, opt->fullname, strlen(opt->fullname), + *(long *)varp); } else { - dict_add_nr_str(d, opt->fullname, *varp, NULL); + tv_dict_add_nr(d, opt->fullname, strlen(opt->fullname), *(int *)varp); } } } diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index 32021da922..a2fe90b3c2 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -16,9 +16,9 @@ #define SOPT_UNSET 0x40 // Option does not have local value set // Option types for various functions in option.c -#define SREQ_GLOBAL 0 // Request global option -#define SREQ_WIN 1 // Request window-local option -#define SREQ_BUF 2 // Request buffer-local option +#define SREQ_GLOBAL 0 // Request global option value +#define SREQ_WIN 1 // Request window-local option value +#define SREQ_BUF 2 // Request buffer-local option value /* * Default values for 'errorformat'. @@ -81,57 +81,56 @@ #define DFLT_FO_VIM "tcqj" #define FO_ALL "tcroq2vlb1mMBn,awj" /* for do_set() */ -/* characters for the p_cpo option: */ -#define CPO_ALTREAD 'a' /* ":read" sets alternate file name */ -#define CPO_ALTWRITE 'A' /* ":write" sets alternate file name */ -#define CPO_BAR 'b' /* "\|" ends a mapping */ -#define CPO_BSLASH 'B' /* backslash in mapping is not special */ +// characters for the p_cpo option: +#define CPO_ALTREAD 'a' // ":read" sets alternate file name +#define CPO_ALTWRITE 'A' // ":write" sets alternate file name +#define CPO_BAR 'b' // "\|" ends a mapping +#define CPO_BSLASH 'B' // backslash in mapping is not special #define CPO_SEARCH 'c' -#define CPO_CONCAT 'C' /* Don't concatenate sourced lines */ -#define CPO_DOTTAG 'd' /* "./tags" in 'tags' is in current dir */ -#define CPO_DIGRAPH 'D' /* No digraph after "r", "f", etc. */ +#define CPO_CONCAT 'C' // Don't concatenate sourced lines +#define CPO_DOTTAG 'd' // "./tags" in 'tags' is in current dir +#define CPO_DIGRAPH 'D' // No digraph after "r", "f", etc. #define CPO_EXECBUF 'e' -#define CPO_EMPTYREGION 'E' /* operating on empty region is an error */ -#define CPO_FNAMER 'f' /* set file name for ":r file" */ -#define CPO_FNAMEW 'F' /* set file name for ":w file" */ -#define CPO_INTMOD 'i' /* interrupt a read makes buffer modified */ -#define CPO_INDENT 'I' /* remove auto-indent more often */ -#define CPO_ENDOFSENT 'J' /* need two spaces to detect end of sentence */ -#define CPO_KEYCODE 'k' /* don't recognize raw key code in mappings */ -#define CPO_KOFFSET 'K' /* don't wait for key code in mappings */ -#define CPO_LITERAL 'l' /* take char after backslash in [] literal */ -#define CPO_LISTWM 'L' /* 'list' changes wrapmargin */ +#define CPO_EMPTYREGION 'E' // operating on empty region is an error +#define CPO_FNAMER 'f' // set file name for ":r file" +#define CPO_FNAMEW 'F' // set file name for ":w file" +#define CPO_INTMOD 'i' // interrupt a read makes buffer modified +#define CPO_INDENT 'I' // remove auto-indent more often +#define CPO_ENDOFSENT 'J' // need two spaces to detect end of sentence +#define CPO_KOFFSET 'K' // don't wait for key code in mappings +#define CPO_LITERAL 'l' // take char after backslash in [] literal +#define CPO_LISTWM 'L' // 'list' changes wrapmargin #define CPO_SHOWMATCH 'm' -#define CPO_MATCHBSL 'M' /* "%" ignores use of backslashes */ -#define CPO_NUMCOL 'n' /* 'number' column also used for text */ +#define CPO_MATCHBSL 'M' // "%" ignores use of backslashes +#define CPO_NUMCOL 'n' // 'number' column also used for text #define CPO_LINEOFF 'o' -#define CPO_OVERNEW 'O' /* silently overwrite new file */ -#define CPO_LISP 'p' /* 'lisp' indenting */ -#define CPO_FNAMEAPP 'P' /* set file name for ":w >>file" */ -#define CPO_JOINCOL 'q' /* with "3J" use column after first join */ +#define CPO_OVERNEW 'O' // silently overwrite new file +#define CPO_LISP 'p' // 'lisp' indenting +#define CPO_FNAMEAPP 'P' // set file name for ":w >>file" +#define CPO_JOINCOL 'q' // with "3J" use column after first join #define CPO_REDO 'r' -#define CPO_REMMARK 'R' /* remove marks when filtering */ +#define CPO_REMMARK 'R' // remove marks when filtering #define CPO_BUFOPT 's' #define CPO_BUFOPTGLOB 'S' #define CPO_TAGPAT 't' -#define CPO_UNDO 'u' /* "u" undoes itself */ -#define CPO_BACKSPACE 'v' /* "v" keep deleted text */ -#define CPO_FWRITE 'W' /* "w!" doesn't overwrite readonly files */ +#define CPO_UNDO 'u' // "u" undoes itself +#define CPO_BACKSPACE 'v' // "v" keep deleted text +#define CPO_FWRITE 'W' // "w!" doesn't overwrite readonly files #define CPO_ESC 'x' -#define CPO_REPLCNT 'X' /* "R" with a count only deletes chars once */ +#define CPO_REPLCNT 'X' // "R" with a count only deletes chars once #define CPO_YANK 'y' -#define CPO_KEEPRO 'Z' /* don't reset 'readonly' on ":w!" */ +#define CPO_KEEPRO 'Z' // don't reset 'readonly' on ":w!" #define CPO_DOLLAR '$' #define CPO_FILTER '!' #define CPO_MATCH '%' -#define CPO_PLUS '+' /* ":write file" resets 'modified' */ -#define CPO_SPECI '<' /* don't recognize <> in mappings */ -#define CPO_REGAPPEND '>' /* insert NL when appending to a register */ -#define CPO_SCOLON ';' /* using "," and ";" will skip over char if - * cursor would not move */ -/* default values for Vim and Vi */ -#define CPO_VIM "aABceFs" -#define CPO_VI "aAbBcCdDeEfFiIJkKlLmMnoOpPqrRsStuvWxXyZ$!%+<>;" +#define CPO_PLUS '+' // ":write file" resets 'modified' +#define CPO_REGAPPEND '>' // insert NL when appending to a register +#define CPO_SCOLON ';' // using "," and ";" will skip over char if + // cursor would not move +#define CPO_CHANGEW '_' // "cw" special-case +// default values for Vim and Vi +#define CPO_VIM "aABceFs_" +#define CPO_VI "aAbBcCdDeEfFiIJKlLmMnoOpPqrRsStuvWxXyZ$!%+>;_" /* characters for p_ww option: */ #define WW_ALL "bshl<>[],~" @@ -411,7 +410,6 @@ EXTERN char_u *p_efm; // 'errorformat' EXTERN char_u *p_gefm; // 'grepformat' EXTERN char_u *p_gp; // 'grepprg' EXTERN char_u *p_ei; // 'eventignore' -EXTERN int p_ek; // 'esckeys' EXTERN int p_exrc; // 'exrc' EXTERN char_u *p_fencs; // 'fileencodings' EXTERN char_u *p_ffs; // 'fileformats' @@ -476,8 +474,9 @@ EXTERN char_u *p_isp; // 'isprint' EXTERN int p_js; // 'joinspaces' EXTERN char_u *p_kp; // 'keywordprg' EXTERN char_u *p_km; // 'keymodel' -EXTERN char_u *p_langmap; // 'langmap'*/ -EXTERN int p_lnr; // 'langnoremap'*/ +EXTERN char_u *p_langmap; // 'langmap' +EXTERN int p_lnr; // 'langnoremap' +EXTERN int p_lrm; // 'langremap' EXTERN char_u *p_lm; // 'langmenu' EXTERN char_u *p_lispwords; // 'lispwords' EXTERN long p_ls; // 'laststatus' @@ -524,6 +523,7 @@ EXTERN int p_ru; // 'ruler' EXTERN char_u *p_ruf; // 'rulerformat' EXTERN char_u *p_pp; // 'packpath' EXTERN char_u *p_rtp; // 'runtimepath' +EXTERN long p_scbk; // 'scrollback' EXTERN long p_sj; // 'scrolljump' EXTERN long p_so; // 'scrolloff' EXTERN char_u *p_sbo; // 'scrollopt' @@ -602,11 +602,14 @@ EXTERN int p_tbs; ///< 'tagbsearch' EXTERN char_u *p_tc; ///< 'tagcase' EXTERN unsigned tc_flags; ///< flags from 'tagcase' #ifdef IN_OPTION_C -static char *(p_tc_values[]) = { "followic", "ignore", "match", NULL }; +static char *(p_tc_values[]) = + { "followic", "ignore", "match", "followscs", "smart", NULL }; #endif #define TC_FOLLOWIC 0x01 #define TC_IGNORE 0x02 #define TC_MATCH 0x04 +#define TC_FOLLOWSCS 0x08 +#define TC_SMART 0x10 EXTERN long p_tl; ///< 'taglength' EXTERN int p_tr; ///< 'tagrelative' EXTERN char_u *p_tags; ///< 'tags' @@ -710,6 +713,7 @@ enum { , BV_EP , BV_ET , BV_FENC + , BV_FP , BV_BEXPR , BV_FEX , BV_FF @@ -737,6 +741,7 @@ enum { , BV_PI , BV_QE , BV_RO + , BV_SCBK , BV_SI , BV_SMC , BV_SYN @@ -800,10 +805,13 @@ enum { , WV_WFW , WV_WRAP , WV_SCL + , WV_WINHL , WV_COUNT // must be the last one }; /* Value for b_p_ul indicating the global value must be used. */ #define NO_LOCAL_UNDOLEVEL -123456 +#define SB_MAX 100000 // Maximum 'scrollback' value. + #endif // NVIM_OPTION_DEFS_H diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 70d1f73cf4..103227f6b5 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -17,8 +17,8 @@ -- types: bool, number, string -- lists: (nil), comma, onecomma, flags, flagscomma -- scopes: global, buffer, window --- redraw options: statuslines, current_window, current_buffer, all_windows, --- everything, curswant +-- redraw options: statuslines, current_window, curent_window_only, +-- current_buffer, all_windows, everything, curswant -- default: {vi=…[, vim=…]} -- defaults: {condition=#if condition, if_true=default, if_false=default} -- #if condition: @@ -34,6 +34,11 @@ local macros=function(s) return s end end +local imacros=function(s) + return function() + return '(intptr_t)' .. s + end +end local N_=function(s) return function() return 'N_(' .. cstr(s) .. ')' @@ -190,7 +195,7 @@ return { type='string', list='comma', scope={'global'}, vi_def=true, varname='p_bo', - defaults={if_true={vi=""}} + defaults={if_true={vi="all"}} }, { full_name='binary', abbreviation='bin', @@ -539,7 +544,7 @@ return { full_name='cursorline', abbreviation='cul', type='bool', scope={'window'}, vi_def=true, - redraw={'current_window'}, + redraw={'current_window_only'}, defaults={if_true={vi=false}} }, { @@ -711,13 +716,6 @@ return { defaults={if_true={vi=macros('DFLT_EFM')}} }, { - full_name='esckeys', abbreviation='ek', - type='bool', scope={'global'}, - vim=true, - varname='p_ek', - defaults={if_true={vi=false, vim=true}} - }, - { full_name='eventignore', abbreviation='ei', type='string', list='onecomma', scope={'global'}, deny_duplicates=true, @@ -955,7 +953,7 @@ return { }, { full_name='formatprg', abbreviation='fp', - type='string', scope={'global'}, + type='string', scope={'global', 'buffer'}, secure=true, vi_def=true, expand=true, @@ -1007,7 +1005,7 @@ return { deny_duplicates=true, vi_def=true, varname='p_guicursor', - defaults={if_true={vi="n-v-c:block,o:hor50,i-ci:hor15,r-cr:hor30,sm:block"}} + defaults={if_true={vi="n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20"}} }, { full_name='guifont', abbreviation='gfn', @@ -1033,13 +1031,6 @@ return { enable_if=false, }, { - full_name='guiheadroom', abbreviation='ghr', - type='number', scope={'global'}, - vi_def=true, - enable_if=false, - defaults={if_true={vi=50}} - }, - { full_name='guioptions', abbreviation='go', type='string', list='flags', scope={'global'}, vi_def=true, @@ -1354,6 +1345,12 @@ return { defaults={if_true={vi=false, vim=true}} }, { + full_name='langremap', abbreviation='lrm', + type='bool', scope={'global'}, + varname='p_lrm', + defaults={if_true={vi=true, vim=false}} + }, + { full_name='laststatus', abbreviation='ls', type='number', scope={'global'}, vim=true, @@ -1572,7 +1569,7 @@ return { full_name='mouse', type='string', list='flags', scope={'global'}, varname='p_mouse', - defaults={if_true={vi="", vim="a"}} + defaults={if_true={vi="", vim=""}} }, { full_name='mousefocus', abbreviation='mousef', @@ -1890,7 +1887,7 @@ return { vim=true, redraw={'statuslines'}, varname='p_ru', - defaults={if_true={vi=false}} + defaults={if_true={vi=true}} }, { full_name='rulerformat', abbreviation='ruf', @@ -1920,6 +1917,14 @@ return { defaults={if_true={vi=12}} }, { + full_name='scrollback', abbreviation='scbk', + type='number', scope={'buffer'}, + vi_def=true, + varname='p_scbk', + redraw={'current_buffer'}, + defaults={if_true={vi=1000}} + }, + { full_name='scrollbind', abbreviation='scb', type='bool', scope={'window'}, vi_def=true, @@ -2051,7 +2056,11 @@ return { secure=true, vi_def=true, varname='p_srr', - defaults={if_true={vi=">"}} + defaults={ + condition='WIN32', + if_true={vi=">%s 2>&1"}, + if_false={vi=">"} + } }, { full_name='shellslash', abbreviation='ssl', @@ -2118,11 +2127,7 @@ return { type='bool', scope={'global'}, vim=true, varname='p_sc', - defaults={ - condition='UNIX', - if_true={vi=false, vim=false}, - if_false={vi=false, vim=true}, - } + defaults={if_true={vi=false, vim=true}} }, { full_name='showfulltag', abbreviation='sft', @@ -2508,14 +2513,14 @@ return { vi_def=true, vim=true, varname='p_ttimeout', - defaults={if_true={vi=false}} + defaults={if_true={vi=true}} }, { full_name='ttimeoutlen', abbreviation='ttm', type='number', scope={'global'}, vi_def=true, varname='p_ttm', - defaults={if_true={vi=-1}} + defaults={if_true={vi=50}} }, { full_name='ttyfast', abbreviation='tf', @@ -2648,7 +2653,7 @@ return { type='number', scope={'global'}, vim=true, varname='p_wc', - defaults={if_true={vi=macros('Ctrl_E'), vim=macros('TAB')}} + defaults={if_true={vi=imacros('Ctrl_E'), vim=imacros('TAB')}} }, { full_name='wildcharm', abbreviation='wcm', @@ -2702,6 +2707,14 @@ return { defaults={if_true={vi="menu"}} }, { + full_name='winhighlight', abbreviation='winhl', + type='string', scope={'window'}, + vi_def=true, + alloced=true, + redraw={'current_window'}, + defaults={if_true={vi=""}} + }, + { full_name='window', abbreviation='wi', type='number', scope={'global'}, vi_def=true, diff --git a/src/nvim/os/dl.c b/src/nvim/os/dl.c index fef02cc784..267cf5ae4b 100644 --- a/src/nvim/os/dl.c +++ b/src/nvim/os/dl.c @@ -1,3 +1,6 @@ +// 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 + /// Functions for using external native libraries #include <stdbool.h> diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index 83a0262545..de0cd10d9c 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -1,14 +1,15 @@ -// env.c -- environment variable access +// 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> +// Environment inspection +#include <assert.h> #include <uv.h> -// vim.h must be included before charset.h (and possibly others) or things -// blow up #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/charset.h" +#include "nvim/fileio.h" #include "nvim/os/os.h" #include "nvim/memory.h" #include "nvim/message.h" @@ -18,6 +19,10 @@ #include "nvim/ex_getln.h" #include "nvim/version.h" +#ifdef WIN32 +#include "nvim/mbyte.h" // for utf8_to_utf16, utf16_to_utf8 +#endif + #ifdef HAVE__NSGETENVIRON #include <crt_externs.h> #endif @@ -45,7 +50,21 @@ bool os_env_exists(const char *name) int os_setenv(const char *name, const char *value, int overwrite) FUNC_ATTR_NONNULL_ALL { -#ifdef HAVE_SETENV +#ifdef WIN32 + size_t envbuflen = strlen(name) + strlen(value) + 2; + char *envbuf = xmalloc(envbuflen); + snprintf(envbuf, envbuflen, "%s=%s", name, value); + + WCHAR *p; + utf8_to_utf16(envbuf, &p); + xfree(envbuf); + if (p == NULL) { + return -1; + } + _wputenv(p); + xfree(p); // Unlike Unix systems, we can free the string for _wputenv(). + return 0; +#elif defined(HAVE_SETENV) return setenv(name, value, overwrite); #elif defined(HAVE_PUTENV_S) if (!overwrite && os_getenv(name) != NULL) { @@ -99,7 +118,6 @@ char *os_getenvname_at_index(size_t index) return name; } - /// Get the process ID of the Neovim process. /// /// @return the process ID. @@ -112,11 +130,11 @@ int64_t os_get_pid(void) #endif } -/// Get the hostname of the machine running Neovim. +/// Gets the hostname of the current machine. /// -/// @param hostname Buffer to store the hostname. -/// @param len Length of `hostname`. -void os_get_hostname(char *hostname, size_t len) +/// @param hostname Buffer to store the hostname. +/// @param size Size of `hostname`. +void os_get_hostname(char *hostname, size_t size) { #ifdef HAVE_SYS_UTSNAME_H struct utsname vutsname; @@ -124,13 +142,29 @@ void os_get_hostname(char *hostname, size_t len) if (uname(&vutsname) < 0) { *hostname = '\0'; } else { - strncpy(hostname, vutsname.nodename, len - 1); - hostname[len - 1] = '\0'; + xstrlcpy(hostname, vutsname.nodename, size); + } +#elif defined(WIN32) + WCHAR host_utf16[MAX_COMPUTERNAME_LENGTH + 1]; + DWORD host_wsize = sizeof(host_utf16) / sizeof(host_utf16[0]); + if (GetComputerNameW(host_utf16, &host_wsize) == 0) { + *hostname = '\0'; + DWORD err = GetLastError(); + EMSG2("GetComputerNameW failed: %d", err); + return; + } + host_utf16[host_wsize] = '\0'; + + char *host_utf8; + int conversion_result = utf16_to_utf8(host_utf16, &host_utf8); + if (conversion_result != 0) { + EMSG2("utf16_to_utf8 failed: %d", conversion_result); + return; } + xstrlcpy(hostname, host_utf8, size); + xfree(host_utf8); #else - // TODO(unknown): Implement this for windows. - // See the implementation used in vim: - // https://code.google.com/p/vim/source/browse/src/os_win32.c?r=6b69d8dde19e32909f4ee3a6337e6a2ecfbb6f72#2899 + EMSG("os_get_hostname failed: missing uname()"); *hostname = '\0'; #endif } @@ -146,11 +180,11 @@ static char_u *homedir = NULL; void init_homedir(void) { - // In case we are called a second time (when 'encoding' changes). + // In case we are called a second time. xfree(homedir); homedir = NULL; - char_u *var = (char_u *)os_getenv("HOME"); + const char *var = os_getenv("HOME"); #ifdef WIN32 // Typically, $HOME is not defined on Windows, unless the user has @@ -164,10 +198,10 @@ void init_homedir(void) homepath = "\\"; } if (homedrive != NULL && strlen(homedrive) + strlen(homepath) < MAXPATHL) { - snprintf((char *)NameBuff, MAXPATHL, "%s%s", homedrive, homepath); - if (NameBuff[0] != NUL) { - var = NameBuff; - vim_setenv("HOME", (char *)NameBuff); + snprintf(os_buf, MAXPATHL, "%s%s", homedrive, homepath); + if (os_buf[0] != NUL) { + var = os_buf; + vim_setenv("HOME", os_buf); } } } @@ -177,17 +211,16 @@ void init_homedir(void) #ifdef UNIX // Change to the directory and get the actual path. This resolves // links. Don't do it when we can't return. - if (os_dirname(NameBuff, MAXPATHL) == OK - && os_chdir((char *)NameBuff) == 0) { - if (!os_chdir((char *)var) && os_dirname(IObuff, IOSIZE) == OK) { - var = IObuff; + if (os_dirname((char_u *)os_buf, MAXPATHL) == OK && os_chdir(os_buf) == 0) { + if (!os_chdir(var) && os_dirname(IObuff, IOSIZE) == OK) { + var = (char *)IObuff; } - if (os_chdir((char *)NameBuff) != 0) { + if (os_chdir(os_buf) != 0) { EMSG(_(e_prev_dir)); } } #endif - homedir = vim_strsave(var); + homedir = vim_strsave((char_u *)var); } } @@ -226,25 +259,24 @@ char_u *expand_env_save_opt(char_u *src, bool one) /// "~/" is also expanded, using $HOME. For Unix "~user/" is expanded. /// Skips over "\ ", "\~" and "\$" (not for Win32 though). /// If anything fails no expansion is done and dst equals src. -/// @param src Input string e.g. "$HOME/vim.hlp" -/// @param dst Where to put the result -/// @param dstlen Maximum length of the result +/// +/// @param src Input string e.g. "$HOME/vim.hlp" +/// @param dst[out] Where to put the result +/// @param dstlen Maximum length of the result void expand_env(char_u *src, char_u *dst, int dstlen) { expand_env_esc(src, dst, dstlen, false, false, NULL); } /// Expand environment variable with path name and escaping. -/// "~/" is also expanded, using $HOME. For Unix "~user/" is expanded. -/// Skips over "\ ", "\~" and "\$" (not for Win32 though). -/// If anything fails no expansion is done and dst equals src. -/// prefix recognize the start of a new name, for '~' expansion. -/// @param srcp Input string e.g. "$HOME/vim.hlp" -/// @param dst Where to put the result -/// @param dstlen Maximum length of the result -/// @param esc Should we escape spaces in expanded variables? -/// @param one Should we expand more than one '~'? -/// @param prefix Common prefix for paths, can be NULL +/// @see expand_env +/// +/// @param srcp Input string e.g. "$HOME/vim.hlp" +/// @param dst[out] Where to put the result +/// @param dstlen Maximum length of the result +/// @param esc Escape spaces in expanded variables +/// @param one `srcp` is a single filename +/// @param prefix Start again after this (can be NULL) void expand_env_esc(char_u *restrict srcp, char_u *restrict dst, int dstlen, @@ -489,10 +521,11 @@ static char *remove_tail(char *path, char *pend, char *dirname) return pend; } -/// Iterate over colon-separated list +/// Iterate over a delimited list. /// /// @note Environment variables must not be modified during iteration. /// +/// @param[in] delim Delimiter character. /// @param[in] val Value of the environment variable to iterate over. /// @param[in] iter Pointer used for iteration. Must be NULL on first /// iteration. @@ -501,18 +534,19 @@ static char *remove_tail(char *path, char *pend, char *dirname) /// @param[out] len Location where current directory length should be saved. /// /// @return Next iter argument value or NULL when iteration should stop. -const void *vim_colon_env_iter(const char *const val, - const void *const iter, - const char **const dir, - size_t *const len) - FUNC_ATTR_NONNULL_ARG(1, 3, 4) FUNC_ATTR_WARN_UNUSED_RESULT +const void *vim_env_iter(const char delim, + const char *const val, + const void *const iter, + const char **const dir, + size_t *const len) + FUNC_ATTR_NONNULL_ARG(2, 4, 5) FUNC_ATTR_WARN_UNUSED_RESULT { const char *varval = (const char *) iter; if (varval == NULL) { varval = val; } *dir = varval; - const char *const dirend = strchr(varval, ':'); + const char *const dirend = strchr(varval, delim); if (dirend == NULL) { *len = strlen(varval); return NULL; @@ -522,10 +556,11 @@ const void *vim_colon_env_iter(const char *const val, } } -/// Iterate over colon-separated list in reverse order +/// Iterate over a delimited list in reverse order. /// /// @note Environment variables must not be modified during iteration. /// +/// @param[in] delim Delimiter character. /// @param[in] val Value of the environment variable to iterate over. /// @param[in] iter Pointer used for iteration. Must be NULL on first /// iteration. @@ -534,18 +569,19 @@ const void *vim_colon_env_iter(const char *const val, /// @param[out] len Location where current directory length should be saved. /// /// @return Next iter argument value or NULL when iteration should stop. -const void *vim_colon_env_iter_rev(const char *const val, - const void *const iter, - const char **const dir, - size_t *const len) - FUNC_ATTR_NONNULL_ARG(1, 3, 4) FUNC_ATTR_WARN_UNUSED_RESULT +const void *vim_env_iter_rev(const char delim, + const char *const val, + const void *const iter, + const char **const dir, + size_t *const len) + FUNC_ATTR_NONNULL_ARG(2, 4, 5) FUNC_ATTR_WARN_UNUSED_RESULT { const char *varend = (const char *) iter; if (varend == NULL) { varend = val + strlen(val) - 1; } - const size_t varlen = (size_t) (varend - val) + 1; - const char *const colon = xmemrchr(val, ':', varlen); + const size_t varlen = (size_t)(varend - val) + 1; + const char *const colon = xmemrchr(val, (uint8_t)delim, varlen); if (colon == NULL) { *len = varlen; *dir = val; @@ -560,10 +596,13 @@ const void *vim_colon_env_iter_rev(const char *const val, /// Vim's version of getenv(). /// Special handling of $HOME, $VIM and $VIMRUNTIME, allowing the user to /// override the vim runtime directory at runtime. Also does ACP to 'enc' -/// conversion for Win32. Results must be freed by the calling function. -/// @param name Name of environment variable to expand +/// conversion for Win32. Result must be freed by the caller. +/// @param name Environment variable to expand char *vim_getenv(const char *name) { + // init_path() should have been called before now. + assert(get_vim_var_str(VV_PROGPATH)[0] != NUL); + const char *kos_env_path = os_getenv(name); if (kos_env_path != NULL) { return xstrdup(kos_env_path); @@ -598,6 +637,24 @@ char *vim_getenv(const char *name) if (p_hf != NULL && vim_strchr(p_hf, '$') == NULL) { vim_path = (char *)p_hf; } + + char exe_name[MAXPATHL]; + // Find runtime path relative to the nvim binary: ../share/nvim/runtime + if (vim_path == NULL) { + xstrlcpy(exe_name, (char *)get_vim_var_str(VV_PROGPATH), + sizeof(exe_name)); + char *path_end = (char *)path_tail_with_sep((char_u *)exe_name); + *path_end = '\0'; // remove the trailing "nvim.exe" + path_end = (char *)path_tail((char_u *)exe_name); + *path_end = '\0'; // remove the trailing "bin/" + if (append_path( + exe_name, + "share" _PATHSEPSTR "nvim" _PATHSEPSTR "runtime" _PATHSEPSTR, + MAXPATHL) == OK) { + vim_path = exe_name; // -V507 + } + } + if (vim_path != NULL) { // remove the file name char *vim_path_end = (char *)path_tail((char_u *)vim_path); @@ -627,6 +684,7 @@ char *vim_getenv(const char *name) vim_path = NULL; } } + assert(vim_path != exe_name); } #ifdef HAVE_PATHDEF @@ -668,7 +726,8 @@ char *vim_getenv(const char *name) /// @param dstlen Maximum length of the result /// @param one If true, only replace one file name, including spaces and commas /// in the file name -void home_replace(buf_T *buf, char_u *src, char_u *dst, int dstlen, bool one) +void home_replace(const buf_T *const buf, const char_u *src, + char_u *dst, size_t dstlen, bool one) { size_t dirlen = 0, envlen = 0; size_t len; @@ -682,7 +741,7 @@ void home_replace(buf_T *buf, char_u *src, char_u *dst, int dstlen, bool one) * If the file is a help file, remove the path completely. */ if (buf != NULL && buf->b_help) { - STRCPY(dst, path_tail(src)); + xstrlcpy((char *)dst, (char *)path_tail(src), dstlen); return; } @@ -774,7 +833,7 @@ char_u * home_replace_save(buf_T *buf, char_u *src) FUNC_ATTR_NONNULL_RET len += STRLEN(src); } char_u *dst = xmalloc(len); - home_replace(buf, src, dst, (int)len, true); + home_replace(buf, src, dst, len, true); return dst; } @@ -812,3 +871,86 @@ char_u *get_env_name(expand_T *xp, int idx) return NULL; } +/// Appends the head of `fname` to $PATH and sets it in the environment. +/// +/// @param fname Full path whose parent directory will be appended to $PATH. +/// +/// @return true if `path` was appended-to +bool os_setenv_append_path(const char *fname) + FUNC_ATTR_NONNULL_ALL +{ +#ifdef WIN32 +// 8191 (plus NUL) is considered the practical maximum. +# define MAX_ENVPATHLEN 8192 +#else +// No prescribed maximum on unix. +# define MAX_ENVPATHLEN INT_MAX +#endif + if (!path_is_absolute_path((char_u *)fname)) { + EMSG2(_(e_intern2), "os_setenv_append_path()"); + return false; + } + const char *tail = (char *)path_tail_with_sep((char_u *)fname); + size_t dirlen = (size_t)(tail - fname); + assert(tail >= fname && dirlen + 1 < sizeof(os_buf)); + xstrlcpy(os_buf, fname, dirlen + 1); + const char *path = os_getenv("PATH"); + const size_t pathlen = path ? strlen(path) : 0; + const size_t newlen = pathlen + dirlen + 2; + if (newlen < MAX_ENVPATHLEN) { + char *temp = xmalloc(newlen); + if (pathlen == 0) { + temp[0] = NUL; + } else { + xstrlcpy(temp, path, newlen); + xstrlcat(temp, ENV_SEPSTR, newlen); + } + xstrlcat(temp, os_buf, newlen); + os_setenv("PATH", temp, 1); + xfree(temp); + return true; + } + return false; +} + +/// Returns true if the terminal can be assumed to silently ignore unknown +/// control codes. +bool os_term_is_nice(void) +{ +#if defined(__APPLE__) || defined(WIN32) + return true; +#else + const char *vte_version = os_getenv("VTE_VERSION"); + if ((vte_version && atoi(vte_version) >= 3900) + || os_getenv("KONSOLE_PROFILE_NAME") + || os_getenv("KONSOLE_DBUS_SESSION")) { + return true; + } + const char *termprg = os_getenv("TERM_PROGRAM"); + if (termprg && striequal(termprg, "iTerm.app")) { + return true; + } + const char *term = os_getenv("TERM"); + if (term && strncmp(term, "rxvt", 4) == 0) { + return true; + } + return false; +#endif +} + +/// Returns true if `sh` looks like it resolves to "cmd.exe". +bool os_shell_is_cmdexe(const char *sh) + FUNC_ATTR_NONNULL_ALL +{ + if (*sh == NUL) { + return false; + } + if (striequal(sh, "$COMSPEC")) { + const char *comspec = os_getenv("COMSPEC"); + return striequal("cmd.exe", (char *)path_tail((char_u *)comspec)); + } + if (striequal(sh, "cmd.exe") || striequal(sh, "cmd")) { + return true; + } + return striequal("cmd.exe", (char *)path_tail((char_u *)sh)); +} diff --git a/src/nvim/os/fileio.c b/src/nvim/os/fileio.c index cf5bfd60ae..5d68473982 100644 --- a/src/nvim/os/fileio.c +++ b/src/nvim/os/fileio.c @@ -1,3 +1,6 @@ +// 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 + /// @file fileio.c /// /// Buffered reading/writing to a file. Unlike fileio.c this is not dealing with @@ -23,6 +26,7 @@ #include "nvim/globals.h" #include "nvim/rbuffer.h" #include "nvim/macros.h" +#include "nvim/message.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/fileio.c.generated.h" @@ -45,8 +49,8 @@ int file_open(FileDescriptor *const ret_fp, const char *const fname, FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { int os_open_flags = 0; - int fd; TriState wr = kNone; + // -V:FLAG:501 #define FLAG(flags, flag, fcntl_flags, wrval, cond) \ do { \ if (flags & flag) { \ @@ -62,19 +66,42 @@ int file_open(FileDescriptor *const ret_fp, const char *const fname, FLAG(flags, kFileCreate, O_CREAT|O_WRONLY, kTrue, !(flags & kFileCreateOnly)); FLAG(flags, kFileTruncate, O_TRUNC|O_WRONLY, kTrue, !(flags & kFileCreateOnly)); + FLAG(flags, kFileAppend, O_APPEND|O_WRONLY, kTrue, + !(flags & kFileCreateOnly)); FLAG(flags, kFileReadOnly, O_RDONLY, kFalse, wr != kTrue); #ifdef O_NOFOLLOW FLAG(flags, kFileNoSymlink, O_NOFOLLOW, kNone, true); #endif #undef FLAG + // wr is used for kFileReadOnly flag, but on + // QB:neovim-qb-slave-ubuntu-12-04-64bit it still errors out with + // `error: variable ‘wr’ set but not used [-Werror=unused-but-set-variable]` + (void)wr; - fd = os_open(fname, os_open_flags, mode); + const int fd = os_open(fname, os_open_flags, mode); if (fd < 0) { return fd; } + return file_open_fd(ret_fp, fd, (wr == kTrue)); +} - ret_fp->wr = (wr == kTrue); +/// Wrap file descriptor with FileDescriptor structure +/// +/// @warning File descriptor wrapped like this must not be accessed by other +/// means. +/// +/// @param[out] ret_fp Address where information needed for reading from or +/// writing to a file is saved +/// @param[in] fd File descriptor to wrap. +/// @param[in] wr True if fd is opened for writing only, false if it is read +/// only. +/// +/// @return Error code (@see os_strerror()) or 0. Currently always returns 0. +int file_open_fd(FileDescriptor *const ret_fp, const int fd, const bool wr) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + ret_fp->wr = wr; ret_fp->fd = fd; ret_fp->eof = false; ret_fp->rv = rbuffer_new(kRWBufferSize); @@ -98,7 +125,7 @@ int file_open(FileDescriptor *const ret_fp, const char *const fname, /// @return [allocated] Opened file or NULL in case of error. FileDescriptor *file_open_new(int *const error, const char *const fname, const int flags, const int mode) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { FileDescriptor *const fp = xmalloc(sizeof(*fp)); if ((*error = file_open(fp, fname, flags, mode)) != 0) { @@ -108,30 +135,54 @@ FileDescriptor *file_open_new(int *const error, const char *const fname, return fp; } +/// Like file_open_fd(), but allocate and return ret_fp +/// +/// @param[out] error Error code, @see os_strerror(). Is set to zero on +/// success. +/// @param[in] fd File descriptor to wrap. +/// @param[in] wr True if fd is opened for writing only, false if it is read +/// only. +/// +/// @return [allocated] Opened file or NULL in case of error. +FileDescriptor *file_open_fd_new(int *const error, const int fd, const bool wr) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT +{ + FileDescriptor *const fp = xmalloc(sizeof(*fp)); + if ((*error = file_open_fd(fp, fd, wr)) != 0) { + xfree(fp); + return NULL; + } + return fp; +} + /// Close file and free its buffer /// /// @param[in,out] fp File to close. +/// @param[in] do_fsync If true, use fsync() to write changes to disk. /// /// @return 0 or error code. -int file_close(FileDescriptor *const fp) FUNC_ATTR_NONNULL_ALL +int file_close(FileDescriptor *const fp, const bool do_fsync) + FUNC_ATTR_NONNULL_ALL { - const int error = file_fsync(fp); - const int error2 = os_close(fp->fd); + const int flush_error = (do_fsync ? file_fsync(fp) : file_flush(fp)); + const int close_error = os_close(fp->fd); rbuffer_free(fp->rv); - if (error2 != 0) { - return error2; + if (close_error != 0) { + return close_error; } - return error; + return flush_error; } /// Close and free file obtained using file_open_new() /// /// @param[in,out] fp File to close. +/// @param[in] do_fsync If true, use fsync() to write changes to disk. /// /// @return 0 or error code. -int file_free(FileDescriptor *const fp) FUNC_ATTR_NONNULL_ALL +int file_free(FileDescriptor *const fp, const bool do_fsync) + FUNC_ATTR_NONNULL_ALL { - const int ret = file_close(fp); + const int ret = file_close(fp, do_fsync); xfree(fp); return ret; } @@ -141,19 +192,38 @@ int file_free(FileDescriptor *const fp) FUNC_ATTR_NONNULL_ALL /// @param[in,out] fp File to work with. /// /// @return 0 or error code. -int file_fsync(FileDescriptor *const fp) +int file_flush(FileDescriptor *const fp) FUNC_ATTR_NONNULL_ALL { if (!fp->wr) { return 0; } file_rb_write_full_cb(fp->rv, fp); - if (fp->_error != 0) { - const int error = fp->_error; - fp->_error = 0; - return error; + const int error = fp->_error; + fp->_error = 0; + return error; +} + +/// Flush file modifications to disk and run fsync() +/// +/// @param[in,out] fp File to work with. +/// +/// @return 0 or error code. +int file_fsync(FileDescriptor *const fp) + FUNC_ATTR_NONNULL_ALL +{ + if (!fp->wr) { + return 0; + } + const int flush_error = file_flush(fp); + if (flush_error != 0) { + return flush_error; } - return os_fsync(fp->fd); + const int fsync_error = os_fsync(fp->fd); + if (fsync_error != UV_EINVAL && fsync_error != UV_EROFS) { + return fsync_error; + } + return 0; } /// Buffer used for writing @@ -316,3 +386,32 @@ ptrdiff_t file_skip(FileDescriptor *const fp, const size_t size) return (ptrdiff_t)read_bytes; } + +/// Msgpack callback for writing to a file +/// +/// @param data File to write to. +/// @param[in] buf Data to write. +/// @param[in] len Length of the data to write. +/// +/// @return 0 in case of success, -1 in case of error. +int msgpack_file_write(void *data, const char *buf, size_t len) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + assert(len < PTRDIFF_MAX); + const ptrdiff_t written_bytes = file_write((FileDescriptor *)data, buf, len); + if (written_bytes < 0) { + return msgpack_file_write_error((int)written_bytes); + } + return 0; +} + +/// Print error which occurs when failing to write msgpack data +/// +/// @param[in] error Error code of the error to print. +/// +/// @return -1 (error return for msgpack_packer callbacks). +int msgpack_file_write_error(const int error) +{ + emsgf(_("E5420: Failed to write to file: %s"), os_strerror(error)); + return -1; +} diff --git a/src/nvim/os/fileio.h b/src/nvim/os/fileio.h index 2cffd5c851..0b55cc695f 100644 --- a/src/nvim/os/fileio.h +++ b/src/nvim/os/fileio.h @@ -30,6 +30,8 @@ typedef enum { kFileTruncate = 32, ///< Truncate the file if it exists. ///< Implies kFileWriteOnly. Cannot be used with ///< kFileCreateOnly. + kFileAppend = 64, ///< Append to the file. Implies kFileWriteOnly. Cannot + ///< be used with kFileCreateOnly. } FileOpenFlags; static inline bool file_eof(const FileDescriptor *const fp) diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 3c821936e9..78627f8703 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -1,3 +1,6 @@ +// 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 + // fs.c -- filesystem access #include <stdbool.h> #include <stddef.h> @@ -58,9 +61,9 @@ void fs_init(void) } -/// Change to the given directory. +/// Changes the current directory to `path`. /// -/// @return `0` on success, a libuv error code on failure. +/// @return 0 on success, or negative error code. int os_chdir(const char *path) FUNC_ATTR_NONNULL_ALL { @@ -91,11 +94,11 @@ int os_dirname(char_u *buf, size_t len) /// Check if the given path is a directory and not a symlink to a directory. /// @return `true` if `name` is a directory and NOT a symlink to a directory. /// `false` if `name` is not a directory or if an error occurred. -bool os_isrealdir(const char_u *name) +bool os_isrealdir(const char *name) FUNC_ATTR_NONNULL_ALL { uv_fs_t request; - if (uv_fs_lstat(&fs_loop, &request, (char *)name, NULL) != kLibuvSuccess) { + if (uv_fs_lstat(&fs_loop, &request, name, NULL) != kLibuvSuccess) { return false; } if (S_ISLNK(request.statbuf.st_mode)) { @@ -111,7 +114,7 @@ bool os_isrealdir(const char_u *name) bool os_isdir(const char_u *name) FUNC_ATTR_NONNULL_ALL { - int32_t mode = os_getperm(name); + int32_t mode = os_getperm((const char *)name); if (mode < 0) { return false; } @@ -128,6 +131,7 @@ bool os_isdir(const char_u *name) /// NODE_WRITABLE: writable device, socket, fifo, etc. /// NODE_OTHER: non-writable things int os_nodetype(const char *name) + FUNC_ATTR_NONNULL_ALL { #ifdef WIN32 // Edge case from Vim os_win32.c: @@ -168,6 +172,10 @@ int os_nodetype(const char *name) | O_NONBLOCK #endif , 0); + if (fd == -1) { + return NODE_OTHER; // open() failed. + } + switch (uv_guess_handle(fd)) { case UV_TTY: // FILE_TYPE_CHAR nodetype = NODE_WRITABLE; @@ -192,6 +200,20 @@ int os_nodetype(const char *name) return nodetype; } +/// Gets the absolute path of the currently running executable. +/// May fail if procfs is missing. #6734 +/// @see path_exepath +/// +/// @param[out] buffer Full path to the executable. +/// @param[in] size Size of `buffer`. +/// +/// @return 0 on success, or libuv error code. +int os_exepath(char *buffer, size_t *size) + FUNC_ATTR_NONNULL_ALL +{ + return uv_exepath(buffer, size); +} + /// Checks if the given path represents an executable file. /// /// @param[in] name Name of the executable. @@ -207,49 +229,87 @@ int os_nodetype(const char *name) bool os_can_exe(const char_u *name, char_u **abspath, bool use_path) FUNC_ATTR_NONNULL_ARG(1) { - // when use_path is false or if it's an absolute or relative path don't - // need to use $PATH. - if (!use_path || path_is_absolute_path(name) - || (name[0] == '.' - && (name[1] == '/' - || (name[1] == '.' && name[2] == '/')))) { - // There must be a path separator, files in the current directory - // can't be executed - if (gettail_dir(name) != name && is_executable(name)) { + bool no_path = !use_path || path_is_absolute_path(name); +#ifndef WIN32 + // If the filename is "qualified" (relative or absolute) do not check $PATH. + no_path |= (name[0] == '.' + && (name[1] == '/' || (name[1] == '.' && name[2] == '/'))); +#endif + + if (no_path) { +#ifdef WIN32 + const char *pathext = os_getenv("PATHEXT"); + if (!pathext) { + pathext = ".com;.exe;.bat;.cmd"; + } + bool ok = is_executable((char *)name) || is_executable_ext((char *)name, + pathext); +#else + // Must have path separator, cannot execute files in the current directory. + const bool ok = ((const char_u *)gettail_dir((const char *)name) != name + && is_executable((char *)name)); +#endif + if (ok) { if (abspath != NULL) { *abspath = save_absolute_path(name); } - return true; } - return false; } return is_executable_in_path(name, abspath); } -// Return true if "name" is an executable file, false if not or it doesn't -// exist. -static bool is_executable(const char_u *name) +/// Returns true if `name` is an executable file. +static bool is_executable(const char *name) FUNC_ATTR_NONNULL_ALL { - int32_t mode = os_getperm(name); + int32_t mode = os_getperm((const char *)name); if (mode < 0) { return false; } -#if WIN32 +#ifdef WIN32 // Windows does not have exec bit; just check if the file exists and is not // a directory. return (S_ISREG(mode)); #else return (S_ISREG(mode) && (S_IXUSR & mode)); #endif +} + +#ifdef WIN32 +/// Appends file extensions from `pathext` to `name` and returns true if any +/// such combination is executable. +static bool is_executable_ext(char *name, const char *pathext) + FUNC_ATTR_NONNULL_ALL +{ + xstrlcpy(os_buf, name, sizeof(os_buf)); + char *buf_end = xstrchrnul(os_buf, '\0'); + for (const char *ext = pathext; *ext; ext++) { + // Skip the extension if there is no suffix after a '.'. + if (ext[0] == '.' && (ext[1] == '\0' || ext[1] == ENV_SEPCHAR)) { + ext++; + continue; + } + + const char *ext_end = xstrchrnul(ext, ENV_SEPCHAR); + STRLCPY(buf_end, ext, ext_end - ext + 1); + if (is_executable(os_buf)) { + return true; + } + + if (*ext_end != ENV_SEPCHAR) { + break; + } + ext = ext_end; + } return false; } +#endif /// Checks if a file is inside the `$PATH` and is executable. /// @@ -260,89 +320,69 @@ static bool is_executable(const char_u *name) static bool is_executable_in_path(const char_u *name, char_u **abspath) FUNC_ATTR_NONNULL_ARG(1) { - const char *path = os_getenv("PATH"); - if (path == NULL) { + const char *path_env = os_getenv("PATH"); + if (path_env == NULL) { return false; } - size_t buf_len = STRLEN(name) + STRLEN(path) + 2; +#ifdef WIN32 + // Prepend ".;" to $PATH. + size_t pathlen = strlen(path_env); + char *path = memcpy(xmallocz(pathlen + 3), "." ENV_SEPSTR, 2); + memcpy(path + 2, path_env, pathlen); +#else + char *path = xstrdup(path_env); +#endif + + size_t buf_len = STRLEN(name) + strlen(path) + 2; #ifdef WIN32 const char *pathext = os_getenv("PATHEXT"); if (!pathext) { pathext = ".com;.exe;.bat;.cmd"; } - - buf_len += STRLEN(pathext); + buf_len += strlen(pathext); #endif - char_u *buf = xmalloc(buf_len); + char *buf = xmalloc(buf_len); // Walk through all entries in $PATH to check if "name" exists there and // is an executable file. + char *p = path; + bool rv = false; for (;; ) { - const char *e = xstrchrnul(path, ENV_SEPCHAR); - - // Glue together the given directory from $PATH with name and save into - // buf. - STRLCPY(buf, path, e - path + 1); - append_path((char *) buf, (const char *) name, buf_len); - - if (is_executable(buf)) { - // Check if the caller asked for a copy of the path. - if (abspath != NULL) { - *abspath = save_absolute_path(buf); - } + char *e = xstrchrnul(p, ENV_SEPCHAR); - xfree(buf); - - return true; - } + // Combine the $PATH segment with `name`. + STRLCPY(buf, p, e - p + 1); + append_path(buf, (char *)name, buf_len); #ifdef WIN32 - // Try appending file extensions from $PATHEXT to the name. - char *buf_end = xstrchrnul((char *)buf, '\0'); - for (const char *ext = pathext; *ext; ext++) { - // Skip the extension if there is no suffix after a '.'. - if (ext[0] == '.' && (ext[1] == '\0' || ext[1] == ';')) { - *ext++; - - continue; - } - - const char *ext_end = xstrchrnul(ext, ENV_SEPCHAR); - STRLCPY(buf_end, ext, ext_end - ext + 1); - - if (is_executable(buf)) { - // Check if the caller asked for a copy of the path. - if (abspath != NULL) { - *abspath = save_absolute_path(buf); - } - - xfree(buf); - - return true; + bool ok = is_executable(buf) || is_executable_ext(buf, pathext); +#else + bool ok = is_executable(buf); +#endif + if (ok) { + if (abspath != NULL) { // Caller asked for a copy of the path. + *abspath = save_absolute_path((char_u *)buf); } - if (*ext_end != ENV_SEPCHAR) { - break; - } - ext = ext_end; + rv = true; + goto end; } -#endif if (*e != ENV_SEPCHAR) { // End of $PATH without finding any executable called name. - xfree(buf); - return false; + goto end; } - path = e + 1; + p = e + 1; } - // We should never get to this point. - assert(false); - return false; +end: + xfree(buf); + xfree(path); + return rv; } /// Opens or creates a file and returns a non-negative integer representing @@ -362,6 +402,35 @@ int os_open(const char* path, int flags, int mode) return r; } +/// Sets file descriptor `fd` to close-on-exec. +// +// @return -1 if failed to set, 0 otherwise. +int os_set_cloexec(const int fd) +{ +#ifdef HAVE_FD_CLOEXEC + int e; + int fdflags = fcntl(fd, F_GETFD); + if (fdflags < 0) { + e = errno; + ELOG("Failed to get flags on descriptor %d: %s", fd, strerror(e)); + errno = e; + return -1; + } + if ((fdflags & FD_CLOEXEC) == 0 + && fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC) == -1) { + e = errno; + ELOG("Failed to set CLOEXEC on descriptor %d: %s", fd, strerror(e)); + errno = e; + return -1; + } + return 0; +#endif + + // No FD_CLOEXEC flag. On Windows, the file should have been opened with + // O_NOINHERIT anyway. + return -1; +} + /// Close a file /// /// @return 0 or libuv error code on failure. @@ -395,11 +464,11 @@ ptrdiff_t os_read(const int fd, bool *ret_eof, char *const ret_buf, size_t read_bytes = 0; bool did_try_to_free = false; while (read_bytes != size) { + assert(size >= read_bytes); const ptrdiff_t cur_read_bytes = read(fd, ret_buf + read_bytes, size - read_bytes); if (cur_read_bytes > 0) { read_bytes += (size_t)cur_read_bytes; - assert(read_bytes <= size); } if (cur_read_bytes < 0) { const int error = os_translate_sys_error(errno); @@ -498,6 +567,7 @@ ptrdiff_t os_write(const int fd, const char *const buf, const size_t size) } size_t written_bytes = 0; while (written_bytes != size) { + assert(size >= written_bytes); const ptrdiff_t cur_written_bytes = write(fd, buf + written_bytes, size - written_bytes); if (cur_written_bytes > 0) { @@ -535,8 +605,11 @@ int os_fsync(int fd) /// /// @return libuv return code. static int os_stat(const char *name, uv_stat_t *statbuf) - FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_ARG(2) { + if (!name) { + return UV_ENOENT; + } uv_fs_t request; int result = uv_fs_stat(&fs_loop, &request, name, NULL); *statbuf = request.statbuf; @@ -547,11 +620,10 @@ static int os_stat(const char *name, uv_stat_t *statbuf) /// Get the file permissions for a given file. /// /// @return libuv error code on error. -int32_t os_getperm(const char_u *name) - FUNC_ATTR_NONNULL_ALL +int32_t os_getperm(const char *name) { uv_stat_t statbuf; - int stat_result = os_stat((char *)name, &statbuf); + int stat_result = os_stat(name, &statbuf); if (stat_result == kLibuvSuccess) { return (int32_t)statbuf.st_mode; } else { @@ -562,11 +634,11 @@ int32_t os_getperm(const char_u *name) /// Set the permission of a file. /// /// @return `OK` for success, `FAIL` for failure. -int os_setperm(const char_u *name, int perm) +int os_setperm(const char *const name, int perm) FUNC_ATTR_NONNULL_ALL { int r; - RUN_UV_FS_FUNC(r, uv_fs_chmod, (const char *)name, perm, NULL); + RUN_UV_FS_FUNC(r, uv_fs_chmod, name, perm, NULL); return (r == kLibuvSuccess ? OK : FAIL); } @@ -587,7 +659,6 @@ int os_fchown(int fd, uv_uid_t owner, uv_gid_t group) /// /// @return `true` if `path` exists bool os_path_exists(const char_u *path) - FUNC_ATTR_NONNULL_ALL { uv_stat_t statbuf; return os_stat((char *)path, &statbuf) == kLibuvSuccess; @@ -777,7 +848,7 @@ int os_remove(const char *path) /// @param[out] file_info Pointer to a FileInfo to put the information in. /// @return `true` on success, `false` for failure. bool os_fileinfo(const char *path, FileInfo *file_info) - FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_ARG(2) { return os_stat(path, &(file_info->stat)) == kLibuvSuccess; } @@ -788,8 +859,11 @@ bool os_fileinfo(const char *path, FileInfo *file_info) /// @param[out] file_info Pointer to a FileInfo to put the information in. /// @return `true` on success, `false` for failure. bool os_fileinfo_link(const char *path, FileInfo *file_info) - FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_ARG(2) { + if (path == NULL) { + return false; + } uv_fs_t request; int result = uv_fs_lstat(&fs_loop, &request, path, NULL); file_info->stat = request.statbuf; @@ -920,14 +994,13 @@ bool os_fileid_equal_fileinfo(const FileID *file_id, /// When "fname" is the name of a shortcut (*.lnk) resolve the file it points /// to and return that name in allocated memory. /// Otherwise NULL is returned. -char_u * os_resolve_shortcut(char_u *fname) +char *os_resolve_shortcut(const char *fname) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC { HRESULT hr; IPersistFile *ppf = NULL; OLECHAR wsz[MAX_PATH]; - char_u *rfname = NULL; - int len; - int conversion_result; + char *rfname = NULL; IShellLinkW *pslw = NULL; WIN32_FIND_DATAW ffdw; @@ -936,7 +1009,7 @@ char_u * os_resolve_shortcut(char_u *fname) if (fname == NULL) { return rfname; } - len = (int)STRLEN(fname); + const size_t len = strlen(fname); if (len <= 4 || STRNICMP(fname + len - 4, ".lnk", 4) != 0) { return rfname; } @@ -948,9 +1021,9 @@ char_u * os_resolve_shortcut(char_u *fname) &IID_IShellLinkW, (void **)&pslw); if (hr == S_OK) { WCHAR *p; - int conversion_result = utf8_to_utf16((char *)fname, &p); + const int conversion_result = utf8_to_utf16(fname, &p); if (conversion_result != 0) { - EMSG2("utf8_to_utf16 failed: %s", uv_strerror(conversion_result)); + EMSG2("utf8_to_utf16 failed: %d", conversion_result); } if (p != NULL) { @@ -978,7 +1051,7 @@ char_u * os_resolve_shortcut(char_u *fname) ZeroMemory(wsz, MAX_PATH * sizeof(WCHAR)); hr = pslw->lpVtbl->GetPath(pslw, wsz, MAX_PATH, &ffdw, 0); if (hr == S_OK && wsz[0] != NUL) { - int conversion_result = utf16_to_utf8(wsz, &rfname); + const int conversion_result = utf16_to_utf8(wsz, &rfname); if (conversion_result != 0) { EMSG2("utf16_to_utf8 failed: %s", uv_strerror(conversion_result)); } @@ -1008,7 +1081,7 @@ shortcut_end: int os_translate_sys_error(int sys_errno) { #ifdef HAVE_UV_TRANSLATE_SYS_ERROR return uv_translate_sys_error(sys_errno); -#elif WIN32 +#elif defined(WIN32) // TODO(equalsraf): libuv does not yet expose uv_translate_sys_error() // in its public API, include a version here until it can be used. // See https://github.com/libuv/libuv/issues/79 diff --git a/src/nvim/os/fs_defs.h b/src/nvim/os/fs_defs.h index 0bd9c37750..2277d926b3 100644 --- a/src/nvim/os/fs_defs.h +++ b/src/nvim/os/fs_defs.h @@ -14,7 +14,7 @@ typedef struct { uint64_t device_id; ///< @private The id of the device containing the file } FileID; -#define FILE_ID_EMPTY (FileID) {.inode = 0, .device_id = 0} +#define FILE_ID_EMPTY (FileID) { .inode = 0, .device_id = 0 } typedef struct { uv_fs_t request; ///< @private The request to uv for the directory. diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index b60a7eed36..31e06ce404 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -1,3 +1,6 @@ +// 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 <string.h> #include <stdbool.h> @@ -20,6 +23,7 @@ #include "nvim/main.h" #include "nvim/misc1.h" #include "nvim/state.h" +#include "nvim/msgpack_rpc/channel.h" #define READ_BUFFER_SIZE 0xfff #define INPUT_BUFFER_SIZE (READ_BUFFER_SIZE * 4) @@ -35,6 +39,7 @@ static RBuffer *input_buffer = NULL; static bool input_eof = false; static int global_fd = 0; static int events_enabled = 0; +static bool blocking = false; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/input.c.generated.h" @@ -144,9 +149,15 @@ bool os_char_avail(void) // Check for CTRL-C typed by reading all available characters. void os_breakcheck(void) { + int save_us = updating_screen; + // We do not want screen_resize() to redraw here. + updating_screen++; + if (!got_int) { loop_poll_events(&main_loop, 0); } + + updating_screen = save_us; } void input_enable_events(void) @@ -170,12 +181,14 @@ bool os_isatty(int fd) size_t input_enqueue(String keys) { - char *ptr = keys.data, *end = ptr + keys.size; + char *ptr = keys.data; + char *end = ptr + keys.size; while (rbuffer_space(input_buffer) >= 6 && ptr < end) { uint8_t buf[6] = { 0 }; - unsigned int new_size = trans_special((const uint8_t **)&ptr, keys.size, - buf, true); + unsigned int new_size + = trans_special((const uint8_t **)&ptr, (size_t)(end - ptr), buf, true, + true); if (new_size) { new_size = handle_mouse_event(&ptr, buf, new_size); @@ -185,8 +198,7 @@ size_t input_enqueue(String keys) if (*ptr == '<') { char *old_ptr = ptr; - // Invalid or incomplete key sequence, skip until the next '>' or until - // *end + // Invalid or incomplete key sequence, skip until the next '>' or *end. do { ptr++; } while (ptr < end && *ptr != '>'); @@ -317,13 +329,25 @@ static unsigned int handle_mouse_event(char **ptr, uint8_t *buf, return bufsize; } +/// @return true if the main loop is blocked and waiting for input. +bool input_blocking(void) +{ + return blocking; +} + static bool input_poll(int ms) { if (do_profiling == PROF_YES && ms) { prof_inchar_enter(); } + if ((ms == - 1 || ms > 0) && !events_enabled && !input_eof) { + // The pending input provoked a blocking wait. Do special events now. #6247 + blocking = true; + multiqueue_process_events(ch_before_blocking_events); + } LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, ms, input_ready() || input_eof); + blocking = false; if (do_profiling == PROF_YES && ms) { prof_inchar_exit(); diff --git a/src/nvim/os/mem.c b/src/nvim/os/mem.c index 871ece7a0e..eccb3c97e5 100644 --- a/src/nvim/os/mem.c +++ b/src/nvim/os/mem.c @@ -1,3 +1,6 @@ +// 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 + /// Functions for accessing system memory information. #include <uv.h> diff --git a/src/nvim/os/os_defs.h b/src/nvim/os/os_defs.h index 5e164b54a5..923a362b41 100644 --- a/src/nvim/os/os_defs.h +++ b/src/nvim/os/os_defs.h @@ -13,10 +13,17 @@ # include "nvim/os/unix_defs.h" #endif +/// File descriptor number used for standard IO streams +enum { + OS_STDIN_FILENO = STDIN_FILENO, + OS_STDOUT_FILENO = STDOUT_FILENO, + OS_STDERR_FILENO = STDERR_FILENO, +}; + #define BASENAMELEN (NAME_MAX - 5) // Use the system path length if it makes sense. -#if defined(PATH_MAX) && (PATH_MAX > 1000) +#if defined(PATH_MAX) && (PATH_MAX > 1024) # define MAXPATHL PATH_MAX #else # define MAXPATHL 1024 @@ -27,11 +34,11 @@ // Use up to 5 Mbyte for a buffer. #ifndef DFLT_MAXMEM -# define DFLT_MAXMEM (5*1024) +# define DFLT_MAXMEM (5 * 1024) #endif // use up to 10 Mbyte for Vim. #ifndef DFLT_MAXMEMTOT -# define DFLT_MAXMEMTOT (10*1024) +# define DFLT_MAXMEMTOT (10 * 1024) #endif // Note: Some systems need both string.h and strings.h (Savage). However, diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c index b57a69b82b..ee3ab96a83 100644 --- a/src/nvim/os/pty_process_unix.c +++ b/src/nvim/os/pty_process_unix.c @@ -1,3 +1,6 @@ +// 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 + // Some of the code came from pangoterm and libuv #include <stdbool.h> #include <stdlib.h> @@ -9,7 +12,7 @@ #include <sys/ioctl.h> // forkpty is not in POSIX, so headers are platform-specific -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined (__DragonFly__) # include <libutil.h> #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) # include <util.h> @@ -33,7 +36,8 @@ # include "os/pty_process_unix.c.generated.h" #endif -bool pty_process_spawn(PtyProcess *ptyproc) +/// @returns zero on success, or negative error code +int pty_process_spawn(PtyProcess *ptyproc) FUNC_ATTR_NONNULL_ALL { static struct termios termios; @@ -41,6 +45,7 @@ bool pty_process_spawn(PtyProcess *ptyproc) init_termios(&termios); } + int status = 0; // zero or negative error code (libuv convention) Process *proc = (Process *)ptyproc; assert(!proc->err); uv_signal_start(&proc->loop->children_watcher, chld_handler, SIGCHLD); @@ -50,8 +55,9 @@ bool pty_process_spawn(PtyProcess *ptyproc) int pid = forkpty(&master, NULL, &termios, &ptyproc->winsize); if (pid < 0) { + status = -errno; ELOG("forkpty failed: %s", strerror(errno)); - return false; + return status; } else if (pid == 0) { init_child(ptyproc); abort(); @@ -60,30 +66,41 @@ bool pty_process_spawn(PtyProcess *ptyproc) // make sure the master file descriptor is non blocking int master_status_flags = fcntl(master, F_GETFL); if (master_status_flags == -1) { + status = -errno; ELOG("Failed to get master descriptor status flags: %s", strerror(errno)); goto error; } if (fcntl(master, F_SETFL, master_status_flags | O_NONBLOCK) == -1) { + status = -errno; ELOG("Failed to make master descriptor non-blocking: %s", strerror(errno)); goto error; } - if (proc->in && !set_duplicating_descriptor(master, &proc->in->uv.pipe)) { + // Other jobs and providers should not get a copy of this file descriptor. + if (os_set_cloexec(master) == -1) { + status = -errno; + ELOG("Failed to set CLOEXEC on ptmx file descriptor"); + goto error; + } + + if (proc->in + && (status = set_duplicating_descriptor(master, &proc->in->uv.pipe))) { goto error; } - if (proc->out && !set_duplicating_descriptor(master, &proc->out->uv.pipe)) { + if (proc->out + && (status = set_duplicating_descriptor(master, &proc->out->uv.pipe))) { goto error; } ptyproc->tty_fd = master; proc->pid = pid; - return true; + return 0; error: close(master); kill(pid, SIGKILL); waitpid(pid, NULL, 0); - return false; + return status; } void pty_process_resize(PtyProcess *ptyproc, uint16_t width, uint16_t height) @@ -137,9 +154,10 @@ static void init_child(PtyProcess *ptyproc) FUNC_ATTR_NONNULL_ALL return; } + char *prog = ptyproc->process.argv[0]; setenv("TERM", ptyproc->term_name ? ptyproc->term_name : "ansi", 1); - execvp(ptyproc->process.argv[0], ptyproc->process.argv); - fprintf(stderr, "execvp failed: %s\n", strerror(errno)); + execvp(prog, ptyproc->process.argv); + fprintf(stderr, "execvp failed: %s: %s\n", strerror(errno), prog); } static void init_termios(struct termios *termios) FUNC_ATTR_NONNULL_ALL @@ -197,22 +215,34 @@ static void init_termios(struct termios *termios) FUNC_ATTR_NONNULL_ALL termios->c_cc[VTIME] = 0; } -static bool set_duplicating_descriptor(int fd, uv_pipe_t *pipe) +static int set_duplicating_descriptor(int fd, uv_pipe_t *pipe) FUNC_ATTR_NONNULL_ALL { + int status = 0; // zero or negative error code (libuv convention) int fd_dup = dup(fd); if (fd_dup < 0) { + status = -errno; ELOG("Failed to dup descriptor %d: %s", fd, strerror(errno)); - return false; + return status; } - int uv_result = uv_pipe_open(pipe, fd_dup); - if (uv_result) { + + if (os_set_cloexec(fd_dup) == -1) { + status = -errno; + ELOG("Failed to set CLOEXEC on duplicate fd"); + goto error; + } + + status = uv_pipe_open(pipe, fd_dup); + if (status) { ELOG("Failed to set pipe to descriptor %d: %s", - fd_dup, uv_strerror(uv_result)); - close(fd_dup); - return false; + fd_dup, uv_strerror(status)); + goto error; } - return true; + return status; + +error: + close(fd_dup); + return status; } static void chld_handler(uv_signal_t *handle, int signum) diff --git a/src/nvim/os/pty_process_win.c b/src/nvim/os/pty_process_win.c new file mode 100644 index 0000000000..ef8a699c56 --- /dev/null +++ b/src/nvim/os/pty_process_win.c @@ -0,0 +1,410 @@ +#include <assert.h> +#include <stdbool.h> +#include <stdlib.h> + +#include <winpty_constants.h> + +#include "nvim/os/os.h" +#include "nvim/ascii.h" +#include "nvim/memory.h" +#include "nvim/mbyte.h" // for utf8_to_utf16, utf16_to_utf8 +#include "nvim/os/pty_process_win.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "os/pty_process_win.c.generated.h" +#endif + +static void CALLBACK pty_process_finish1(void *context, BOOLEAN unused) + FUNC_ATTR_NONNULL_ALL +{ + PtyProcess *ptyproc = (PtyProcess *)context; + Process *proc = (Process *)ptyproc; + + uv_timer_init(&proc->loop->uv, &ptyproc->wait_eof_timer); + ptyproc->wait_eof_timer.data = (void *)ptyproc; + uv_timer_start(&ptyproc->wait_eof_timer, wait_eof_timer_cb, 200, 200); +} + +/// @returns zero on success, or negative error code. +int pty_process_spawn(PtyProcess *ptyproc) + FUNC_ATTR_NONNULL_ALL +{ + Process *proc = (Process *)ptyproc; + int status = 0; + winpty_error_ptr_t err = NULL; + winpty_config_t *cfg = NULL; + winpty_spawn_config_t *spawncfg = NULL; + winpty_t *winpty_object = NULL; + char *in_name = NULL; + char *out_name = NULL; + HANDLE process_handle = NULL; + uv_connect_t *in_req = NULL; + uv_connect_t *out_req = NULL; + wchar_t *cmd_line = NULL; + wchar_t *cwd = NULL; + const char *emsg = NULL; + + assert(!proc->err); + + cfg = winpty_config_new(WINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION, &err); + if (cfg == NULL) { + emsg = "Failed, winpty_config_new."; + goto cleanup; + } + + winpty_config_set_initial_size(cfg, ptyproc->width, ptyproc->height); + winpty_object = winpty_open(cfg, &err); + if (winpty_object == NULL) { + emsg = "Failed, winpty_open."; + goto cleanup; + } + + status = utf16_to_utf8(winpty_conin_name(winpty_object), &in_name); + if (status != 0) { + emsg = "Failed to convert in_name from utf16 to utf8."; + goto cleanup; + } + + status = utf16_to_utf8(winpty_conout_name(winpty_object), &out_name); + if (status != 0) { + emsg = "Failed to convert out_name from utf16 to utf8."; + goto cleanup; + } + + if (proc->in != NULL) { + in_req = xmalloc(sizeof(uv_connect_t)); + uv_pipe_connect( + in_req, + &proc->in->uv.pipe, + in_name, + pty_process_connect_cb); + } + + if (proc->out != NULL) { + out_req = xmalloc(sizeof(uv_connect_t)); + uv_pipe_connect( + out_req, + &proc->out->uv.pipe, + out_name, + pty_process_connect_cb); + } + + if (proc->cwd != NULL) { + status = utf8_to_utf16(proc->cwd, &cwd); + if (status != 0) { + emsg = "Failed to convert pwd form utf8 to utf16."; + goto cleanup; + } + } + + status = build_cmd_line(proc->argv, &cmd_line, + os_shell_is_cmdexe(proc->argv[0])); + if (status != 0) { + emsg = "Failed to convert cmd line form utf8 to utf16."; + goto cleanup; + } + + spawncfg = winpty_spawn_config_new( + WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN, + NULL, // Optional application name + cmd_line, + cwd, + NULL, // Optional environment variables + &err); + if (spawncfg == NULL) { + emsg = "Failed winpty_spawn_config_new."; + goto cleanup; + } + + DWORD win_err = 0; + if (!winpty_spawn(winpty_object, + spawncfg, + &process_handle, + NULL, // Optional thread handle + &win_err, + &err)) { + if (win_err) { + status = (int)win_err; + emsg = "Failed spawn process."; + } else { + emsg = "Failed winpty_spawn."; + } + goto cleanup; + } + proc->pid = GetProcessId(process_handle); + + if (!RegisterWaitForSingleObject( + &ptyproc->finish_wait, + process_handle, + pty_process_finish1, + ptyproc, + INFINITE, + WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE)) { + abort(); + } + + // Wait until pty_process_connect_cb is called. + while ((in_req != NULL && in_req->handle != NULL) + || (out_req != NULL && out_req->handle != NULL)) { + uv_run(&proc->loop->uv, UV_RUN_ONCE); + } + + ptyproc->winpty_object = winpty_object; + ptyproc->process_handle = process_handle; + winpty_object = NULL; + process_handle = NULL; + +cleanup: + if (status) { + // In the case of an error of MultiByteToWideChar or CreateProcessW. + ELOG("%s error code: %d", emsg, status); + status = os_translate_sys_error(status); + } else if (err != NULL) { + status = (int)winpty_error_code(err); + ELOG("%s error code: %d", emsg, status); + status = translate_winpty_error(status); + } + winpty_error_free(err); + winpty_config_free(cfg); + winpty_spawn_config_free(spawncfg); + winpty_free(winpty_object); + xfree(in_name); + xfree(out_name); + if (process_handle != NULL) { + CloseHandle(process_handle); + } + xfree(in_req); + xfree(out_req); + xfree(cmd_line); + xfree(cwd); + return status; +} + +void pty_process_resize(PtyProcess *ptyproc, uint16_t width, + uint16_t height) + FUNC_ATTR_NONNULL_ALL +{ + if (ptyproc->winpty_object != NULL) { + winpty_set_size(ptyproc->winpty_object, width, height, NULL); + } +} + +void pty_process_close(PtyProcess *ptyproc) + FUNC_ATTR_NONNULL_ALL +{ + Process *proc = (Process *)ptyproc; + + pty_process_close_master(ptyproc); + + if (proc->internal_close_cb) { + proc->internal_close_cb(proc); + } +} + +void pty_process_close_master(PtyProcess *ptyproc) + FUNC_ATTR_NONNULL_ALL +{ + if (ptyproc->winpty_object != NULL) { + winpty_free(ptyproc->winpty_object); + ptyproc->winpty_object = NULL; + } +} + +void pty_process_teardown(Loop *loop) + FUNC_ATTR_NONNULL_ALL +{ +} + +static void pty_process_connect_cb(uv_connect_t *req, int status) + FUNC_ATTR_NONNULL_ALL +{ + assert(status == 0); + req->handle = NULL; +} + +static void wait_eof_timer_cb(uv_timer_t *wait_eof_timer) + FUNC_ATTR_NONNULL_ALL +{ + PtyProcess *ptyproc = wait_eof_timer->data; + Process *proc = (Process *)ptyproc; + + if (!proc->out || !uv_is_readable(proc->out->uvstream)) { + uv_timer_stop(&ptyproc->wait_eof_timer); + pty_process_finish2(ptyproc); + } +} + +static void pty_process_finish2(PtyProcess *ptyproc) + FUNC_ATTR_NONNULL_ALL +{ + Process *proc = (Process *)ptyproc; + + UnregisterWaitEx(ptyproc->finish_wait, NULL); + uv_close((uv_handle_t *)&ptyproc->wait_eof_timer, NULL); + + DWORD exit_code = 0; + GetExitCodeProcess(ptyproc->process_handle, &exit_code); + proc->status = (int)exit_code; + + CloseHandle(ptyproc->process_handle); + ptyproc->process_handle = NULL; + + proc->internal_exit_cb(proc); +} + +/// Build the command line to pass to CreateProcessW. +/// +/// @param[in] argv Array with string arguments. +/// @param[out] cmd_line Location where saved builded cmd line. +/// +/// @returns zero on success, or error code of MultiByteToWideChar function. +/// +static int build_cmd_line(char **argv, wchar_t **cmd_line, bool is_cmdexe) + FUNC_ATTR_NONNULL_ALL +{ + size_t utf8_cmd_line_len = 0; + size_t argc = 0; + QUEUE args_q; + + QUEUE_INIT(&args_q); + while (*argv) { + size_t buf_len = is_cmdexe ? (strlen(*argv) + 1) : (strlen(*argv) * 2 + 3); + ArgNode *arg_node = xmalloc(sizeof(*arg_node)); + arg_node->arg = xmalloc(buf_len); + if (is_cmdexe) { + xstrlcpy(arg_node->arg, *argv, buf_len); + } else { + quote_cmd_arg(arg_node->arg, buf_len, *argv); + } + utf8_cmd_line_len += strlen(arg_node->arg); + QUEUE_INIT(&arg_node->node); + QUEUE_INSERT_TAIL(&args_q, &arg_node->node); + argc++; + argv++; + } + + utf8_cmd_line_len += argc; + char *utf8_cmd_line = xmalloc(utf8_cmd_line_len); + *utf8_cmd_line = NUL; + while (1) { + QUEUE *head = QUEUE_HEAD(&args_q); + QUEUE_REMOVE(head); + ArgNode *arg_node = QUEUE_DATA(head, ArgNode, node); + xstrlcat(utf8_cmd_line, arg_node->arg, utf8_cmd_line_len); + xfree(arg_node->arg); + xfree(arg_node); + if (QUEUE_EMPTY(&args_q)) { + break; + } else { + xstrlcat(utf8_cmd_line, " ", utf8_cmd_line_len); + } + } + + int result = utf8_to_utf16(utf8_cmd_line, cmd_line); + xfree(utf8_cmd_line); + return result; +} + +/// Emulate quote_cmd_arg of libuv and quotes command line argument. +/// Most of the code came from libuv. +/// +/// @param[out] dest Location where saved quotes argument. +/// @param dest_remaining Destination buffer size. +/// @param[in] src Pointer to argument. +/// +static void quote_cmd_arg(char *dest, size_t dest_remaining, const char *src) + FUNC_ATTR_NONNULL_ALL +{ + size_t src_len = strlen(src); + bool quote_hit = true; + char *start = dest; + + if (src_len == 0) { + // Need double quotation for empty argument. + snprintf(dest, dest_remaining, "\"\""); + return; + } + + if (NULL == strpbrk(src, " \t\"")) { + // No quotation needed. + xstrlcpy(dest, src, dest_remaining); + return; + } + + if (NULL == strpbrk(src, "\"\\")) { + // No embedded double quotes or backlashes, so I can just wrap quote marks. + // around the whole thing. + snprintf(dest, dest_remaining, "\"%s\"", src); + return; + } + + // Expected input/output: + // input : hello"world + // output: "hello\"world" + // input : hello""world + // output: "hello\"\"world" + // input : hello\world + // output: hello\world + // input : hello\\world + // output: hello\\world + // input : hello\"world + // output: "hello\\\"world" + // input : hello\\"world + // output: "hello\\\\\"world" + // input : hello world\ + // output: "hello world\\" + + assert(dest_remaining--); + *(dest++) = NUL; + assert(dest_remaining--); + *(dest++) = '"'; + for (size_t i = src_len; i > 0; i--) { + assert(dest_remaining--); + *(dest++) = src[i - 1]; + if (quote_hit && src[i - 1] == '\\') { + assert(dest_remaining--); + *(dest++) = '\\'; + } else if (src[i - 1] == '"') { + quote_hit = true; + assert(dest_remaining--); + *(dest++) = '\\'; + } else { + quote_hit = false; + } + } + assert(dest_remaining); + *dest = '"'; + + while (start < dest) { + char tmp = *start; + *start = *dest; + *dest = tmp; + start++; + dest--; + } +} + +/// Translate winpty error code to libuv error. +/// +/// @param[in] winpty_errno Winpty error code returned by winpty_error_code +/// function. +/// +/// @returns Error code of libuv error. +int translate_winpty_error(int winpty_errno) +{ + if (winpty_errno <= 0) { + return winpty_errno; // If < 0 then it's already a libuv error. + } + + switch (winpty_errno) { + case WINPTY_ERROR_OUT_OF_MEMORY: return UV_ENOMEM; + case WINPTY_ERROR_SPAWN_CREATE_PROCESS_FAILED: return UV_EAI_FAIL; + case WINPTY_ERROR_LOST_CONNECTION: return UV_ENOTCONN; + case WINPTY_ERROR_AGENT_EXE_MISSING: return UV_ENOENT; + case WINPTY_ERROR_UNSPECIFIED: return UV_UNKNOWN; + case WINPTY_ERROR_AGENT_DIED: return UV_ESRCH; + case WINPTY_ERROR_AGENT_TIMEOUT: return UV_ETIMEDOUT; + case WINPTY_ERROR_AGENT_CREATION_FAILED: return UV_EAI_FAIL; + default: return UV_UNKNOWN; + } +} diff --git a/src/nvim/os/pty_process_win.h b/src/nvim/os/pty_process_win.h index 20cc589925..1a4019e654 100644 --- a/src/nvim/os/pty_process_win.h +++ b/src/nvim/os/pty_process_win.h @@ -1,19 +1,27 @@ #ifndef NVIM_OS_PTY_PROCESS_WIN_H #define NVIM_OS_PTY_PROCESS_WIN_H -#include "nvim/event/libuv_process.h" +#include <uv.h> +#include <winpty.h> + +#include "nvim/event/process.h" +#include "nvim/lib/queue.h" typedef struct pty_process { Process process; char *term_name; uint16_t width, height; + winpty_t *winpty_object; + HANDLE finish_wait; + HANDLE process_handle; + uv_timer_t wait_eof_timer; } PtyProcess; -#define pty_process_spawn(job) libuv_process_spawn((LibuvProcess *)job) -#define pty_process_close(job) libuv_process_close((LibuvProcess *)job) -#define pty_process_close_master(job) libuv_process_close((LibuvProcess *)job) -#define pty_process_resize(job, width, height) -#define pty_process_teardown(loop) +// Structure used by build_cmd_line() +typedef struct arg_node { + char *arg; // pointer to argument. + QUEUE node; // QUEUE structure. +} ArgNode; static inline PtyProcess pty_process_init(Loop *loop, void *data) { @@ -22,7 +30,14 @@ static inline PtyProcess pty_process_init(Loop *loop, void *data) rv.term_name = NULL; rv.width = 80; rv.height = 24; + rv.winpty_object = NULL; + rv.finish_wait = NULL; + rv.process_handle = NULL; return rv; } +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "os/pty_process_win.h.generated.h" +#endif + #endif // NVIM_OS_PTY_PROCESS_WIN_H diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 9514936ad0..32e9a70e57 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -1,3 +1,6 @@ +// 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 <string.h> #include <assert.h> #include <stdbool.h> @@ -39,14 +42,15 @@ typedef struct { #endif /// Builds the argument vector for running the user-configured 'shell' (p_sh) -/// with an optional command prefixed by 'shellcmdflag' (p_shcf). +/// with an optional command prefixed by 'shellcmdflag' (p_shcf). E.g.: +/// +/// ["shell", "-extra_args", "-shellcmdflag", "command with spaces"] /// /// @param cmd Command string, or NULL to run an interactive shell. /// @param extra_args Extra arguments to the shell, or NULL. -/// @return A newly allocated argument vector. It must be freed with -/// `shell_free_argv` when no longer needed. +/// @return Newly allocated argument vector. Must be freed with shell_free_argv. char **shell_build_argv(const char *cmd, const char *extra_args) - FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC + FUNC_ATTR_NONNULL_RET { size_t argc = tokenize(p_sh, NULL) + (cmd ? tokenize(p_shcf, NULL) : 0); char **rv = xmalloc((argc + 4) * sizeof(*rv)); @@ -123,15 +127,9 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args) } size_t nread; - - int status = do_os_system(shell_build_argv((char *)cmd, (char *)extra_args), - input.data, - input.len, - output_ptr, - &nread, - emsg_silent, - forward_output); - + int exitcode = do_os_system(shell_build_argv((char *)cmd, (char *)extra_args), + input.data, input.len, output_ptr, &nread, + emsg_silent, forward_output); xfree(input.data); if (output) { @@ -139,16 +137,16 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args) xfree(output); } - if (!emsg_silent && status != 0 && !(opts & kShellOptSilent)) { + if (!emsg_silent && exitcode != 0 && !(opts & kShellOptSilent)) { MSG_PUTS(_("\nshell returned ")); - msg_outnum(status); + msg_outnum(exitcode); msg_putchar('\n'); } State = current_state; signal_accept_deadly(); - return status; + return exitcode; } /// os_system - synchronously execute a command in the shell @@ -157,7 +155,7 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args) /// char *output = NULL; /// size_t nread = 0; /// char *argv[] = {"ls", "-la", NULL}; -/// int status = os_sytem(argv, NULL, 0, &output, &nread); +/// int exitcode = os_sytem(argv, NULL, 0, &output, &nread); /// /// @param argv The commandline arguments to be passed to the shell. `argv` /// will be consumed. @@ -218,11 +216,14 @@ static int do_os_system(char **argv, proc->in = input != NULL ? &in : NULL; proc->out = &out; proc->err = &err; - if (!process_spawn(proc)) { + int status = process_spawn(proc); + if (status) { loop_poll_events(&main_loop, 0); - // Failed, probably due to 'sh' not being executable + // Failed, probably 'shell' is not executable. if (!silent) { - MSG_PUTS(_("\nCannot execute ")); + MSG_PUTS(_("\nshell failed to start: ")); + msg_outtrans((char_u *)os_strerror(status)); + MSG_PUTS(": "); msg_outtrans((char_u *)prog); msg_putchar('\n'); } @@ -262,7 +263,7 @@ static int do_os_system(char **argv, // busy state. ui_busy_start(); ui_flush(); - int status = process_wait(proc, -1, NULL); + int exitcode = process_wait(proc, -1, NULL); if (!got_int && out_data_decide_throttle(0)) { // Last chunk of output was skipped; display it now. out_data_ring(NULL, SIZE_MAX); @@ -289,7 +290,7 @@ static int do_os_system(char **argv, assert(multiqueue_empty(events)); multiqueue_free(events); - return status; + return exitcode; } /// - ensures at least `desired` bytes in buffer @@ -321,7 +322,7 @@ static void system_data_cb(Stream *stream, RBuffer *buf, size_t count, /// Tracks output received for the current executing shell command, and displays /// a pulsing "..." when output should be skipped. Tracking depends on the /// synchronous/blocking nature of ":!". -// +/// /// Purpose: /// 1. CTRL-C is more responsive. #1234 #5396 /// 2. Improves performance of :! (UI, esp. TUI, is the bottleneck). @@ -446,7 +447,7 @@ static void out_data_append_to_screen(char *output, size_t remaining, size_t off = 0; int last_row = (int)Rows - 1; - while (off < remaining) { + while (output != NULL && off < remaining) { // Found end of line? if (output[off] == NL) { // Can we start a new line or do we need to continue the last one? @@ -463,15 +464,16 @@ static void out_data_append_to_screen(char *output, size_t remaining, continue; } - // Translate NUL to SOH - if (output[off] == NUL) { - output[off] = 1; + // TODO(bfredl): using msg_puts would be better until + // terminal emulation is implemented. + if (output[off] < 0x20) { + output[off] = ' '; } off++; } - if (remaining) { + if (output != NULL && remaining) { if (last_col == 0) { screen_del_lines(0, 0, 1, (int)Rows, NULL); } @@ -683,7 +685,7 @@ static void shell_write_cb(Stream *stream, void *data, int status) uv_err_name(status)); } if (stream->closed) { // Process may have exited before this write. - ELOG("stream was already closed"); + WLOG("stream was already closed"); return; } stream_close(stream, NULL, NULL); diff --git a/src/nvim/os/shell.h b/src/nvim/os/shell.h index 58960db157..48503f2601 100644 --- a/src/nvim/os/shell.h +++ b/src/nvim/os/shell.h @@ -1,6 +1,8 @@ #ifndef NVIM_OS_SHELL_H #define NVIM_OS_SHELL_H +#include <stdio.h> + #include "nvim/types.h" // Flags for os_call_shell() second argument diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c index 1ac6d3f5e1..fd6d3b32e4 100644 --- a/src/nvim/os/signal.c +++ b/src/nvim/os/signal.c @@ -1,3 +1,6 @@ +// 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 <stdbool.h> diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c index afb9bdec31..a41fb7c621 100644 --- a/src/nvim/os/stdpaths.c +++ b/src/nvim/os/stdpaths.c @@ -1,3 +1,6 @@ +// 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 <stdbool.h> #include "nvim/os/stdpaths_defs.h" diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c index 8ce2ecf4f4..c471352c02 100644 --- a/src/nvim/os/time.c +++ b/src/nvim/os/time.c @@ -1,3 +1,6 @@ +// 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 <stdbool.h> diff --git a/src/nvim/os/unix_defs.h b/src/nvim/os/unix_defs.h index 690a39c3cd..5c9daca476 100644 --- a/src/nvim/os/unix_defs.h +++ b/src/nvim/os/unix_defs.h @@ -8,7 +8,7 @@ // POSIX.1-2008 says that NAME_MAX should be in here #include <limits.h> -#define TEMP_DIR_NAMES {"$TMPDIR", "/tmp", ".", "~"} +#define TEMP_DIR_NAMES { "$TMPDIR", "/tmp", ".", "~" } #define TEMP_FILE_PATH_MAXLEN 256 #define HAVE_ACL (HAVE_POSIX_ACL || HAVE_SOLARIS_ACL) @@ -16,7 +16,8 @@ // Special wildcards that need to be handled by the shell. #define SPECIAL_WILDCHAR "`'{" -// Separator character for environment variables. +// Character that separates entries in $PATH. #define ENV_SEPCHAR ':' +#define ENV_SEPSTR ":" #endif // NVIM_OS_UNIX_DEFS_H diff --git a/src/nvim/os/users.c b/src/nvim/os/users.c index 1c94ef0067..82bb918f70 100644 --- a/src/nvim/os/users.c +++ b/src/nvim/os/users.c @@ -1,3 +1,6 @@ +// 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 + // users.c -- operating system user information #include <uv.h> diff --git a/src/nvim/os/win_defs.h b/src/nvim/os/win_defs.h index 6a29f86e79..8fd2e51f8b 100644 --- a/src/nvim/os/win_defs.h +++ b/src/nvim/os/win_defs.h @@ -1,6 +1,10 @@ #ifndef NVIM_OS_WIN_DEFS_H #define NVIM_OS_WIN_DEFS_H +#ifndef WIN32 +# error Header must be included only when compiling for Windows. +#endif + // winsock2.h must be first to avoid incompatibilities // with winsock.h (included by windows.h) #include <winsock2.h> @@ -15,18 +19,24 @@ #define NAME_MAX _MAX_PATH -#define TEMP_DIR_NAMES {"$TMP", "$TEMP", "$USERPROFILE", ""} +#define TEMP_DIR_NAMES { "$TMPDIR", "$TMP", "$TEMP", "$USERPROFILE", "" } #define TEMP_FILE_PATH_MAXLEN _MAX_PATH #define FNAME_ILLEGAL "\"*?><|" -// Separator character for environment variables. +// Character that separates entries in $PATH. #define ENV_SEPCHAR ';' +#define ENV_SEPSTR ";" #define USE_CRNL -// We have our own RGB macro in macros.h. -#undef RGB +// Windows defines a RGB macro that produces 0x00bbggrr color values for use +// with GDI. Our macro is different, and we don't use GDI. +#if defined(RGB) +# undef RGB + // Duplicated from macros.h to avoid include-order sensitivity. +# define RGB(r, g, b) ((r << 16) | (g << 8) | b) +#endif #ifdef _MSC_VER # ifndef inline @@ -86,4 +96,14 @@ typedef SSIZE_T ssize_t; # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) #endif +#ifndef STDIN_FILENO +# define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +# define STDOUT_FILENO 1 +#endif +#ifndef STDERR_FILENO +# define STDERR_FILENO 2 +#endif + #endif // NVIM_OS_WIN_DEFS_H diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c index 08294fa6a0..692bcc97f4 100644 --- a/src/nvim/os_unix.c +++ b/src/nvim/os_unix.c @@ -1,3 +1,6 @@ +// 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 + /* * os_unix.c -- code for all flavors of Unix (BSD, SYSV, SVR4, POSIX, ...) * @@ -62,9 +65,7 @@ static int selinux_enabled = -1; #if defined(HAVE_SELINUX) -/* - * Copy security info from "from_file" to "to_file". - */ +// Copy security info from "from_file" to "to_file". void mch_copy_sec(char_u *from_file, char_u *to_file) { if (from_file == NULL) @@ -78,11 +79,12 @@ void mch_copy_sec(char_u *from_file, char_u *to_file) security_context_t to_context = NULL; if (getfilecon((char *)from_file, &from_context) < 0) { - /* If the filesystem doesn't support extended attributes, - the original had no special security context and the - target cannot have one either. */ - if (errno == EOPNOTSUPP) + // If the filesystem doesn't support extended attributes, + // the original had no special security context and the + // target cannot have one either. + if (errno == EOPNOTSUPP) { return; + } MSG_PUTS(_("\nCould not get security context for ")); msg_outtrans(from_file); @@ -107,22 +109,18 @@ void mch_copy_sec(char_u *from_file, char_u *to_file) freecon(from_context); } } -#endif /* HAVE_SELINUX */ +#endif // HAVE_SELINUX -/* - * 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 mch_get_acl(char_u *fname) +// 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 mch_get_acl(const char_u *fname) { vim_acl_T ret = NULL; return ret; } -/* - * Set the ACL of file "fname" to "acl" (unless it's NULL). - */ -void mch_set_acl(char_u *fname, vim_acl_T aclent) +// Set the ACL of file "fname" to "acl" (unless it's NULL). +void mch_set_acl(const char_u *fname, vim_acl_T aclent) { if (aclent == NULL) return; @@ -135,15 +133,17 @@ void mch_free_acl(vim_acl_T aclent) } #endif -void mch_exit(int r) +void mch_exit(int r) FUNC_ATTR_NORETURN { exiting = true; ui_builtin_stop(); ui_flush(); - ml_close_all(true); /* remove all memfiles */ + ml_close_all(true); // remove all memfiles - event_teardown(); + if (!event_teardown() && r == 0) { + r = 1; // Exit with error if main_loop did not teardown gracefully. + } stream_set_blocking(input_global_fd(), true); // normalize stream (#2598) #ifdef EXITFREE @@ -175,7 +175,7 @@ void mch_exit(int r) /// @returns OK for success or FAIL for error. int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***file, int flags) FUNC_ATTR_NONNULL_ARG(3) - FUNC_ATTR_NONNULL_ARG(4) + FUNC_ATTR_NONNULL_ARG(4) { int i; size_t len; @@ -198,17 +198,22 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, int check_spaces; static bool did_find_nul = false; bool ampersent = false; - /* vimglob() function to define for Posix shell */ + // vimglob() function to define for Posix shell static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo \"$1\"; shift; done }; vimglob >"; - *num_file = 0; /* default: no files found */ + bool is_fish_shell = +#if defined(UNIX) + STRNCMP(invocation_path_tail(p_sh, NULL), "fish", 4) == 0; +#else + false; +#endif + + *num_file = 0; // default: no files found *file = NULL; - /* - * If there are no wildcards, just copy the names to allocated memory. - * Saves a lot of time, because we don't have to start a new shell. - */ + // If there are no wildcards, just copy the names to allocated memory. + // Saves a lot of time, because we don't have to start a new shell. if (!have_wildcard(num_pat, pat)) { save_patterns(num_pat, pat, num_file, file); return OK; @@ -219,87 +224,99 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, return FAIL; } - /* - * Don't allow the use of backticks in secure and restricted mode. - */ - if (secure || restricted) - for (i = 0; i < num_pat; ++i) + // Don't allow the use of backticks in secure and restricted mode. + if (secure || restricted) { + for (i = 0; i < num_pat; i++) { if (vim_strchr(pat[i], '`') != NULL - && (check_restricted() || check_secure())) + && (check_restricted() || check_secure())) { return FAIL; + } + } + } - /* - * get a name for the temp file - */ + // get a name for the temp file if ((tempname = vim_tempname()) == NULL) { EMSG(_(e_notmp)); return FAIL; } - /* - * Let the shell expand the patterns and write the result into the temp - * file. - * STYLE_BT: NL separated - * If expanding `cmd` execute it directly. - * STYLE_GLOB: NUL separated - * If we use *csh, "glob" will work better than "echo". - * STYLE_PRINT: NL or NUL separated - * If we use *zsh, "print -N" will work better than "glob". - * STYLE_VIMGLOB: NL separated - * If we use *sh*, we define "vimglob()". - * STYLE_ECHO: space separated. - * A shell we don't know, stay safe and use "echo". - */ + // Let the shell expand the patterns and write the result into the temp + // file. + // STYLE_BT: NL separated + // If expanding `cmd` execute it directly. + // STYLE_GLOB: NUL separated + // If we use *csh, "glob" will work better than "echo". + // STYLE_PRINT: NL or NUL separated + // If we use *zsh, "print -N" will work better than "glob". + // STYLE_VIMGLOB: NL separated + // If we use *sh*, we define "vimglob()". + // STYLE_ECHO: space separated. + // A shell we don't know, stay safe and use "echo". if (num_pat == 1 && *pat[0] == '`' && (len = STRLEN(pat[0])) > 2 - && *(pat[0] + len - 1) == '`') + && *(pat[0] + len - 1) == '`') { shell_style = STYLE_BT; - else if ((len = STRLEN(p_sh)) >= 3) { - if (STRCMP(p_sh + len - 3, "csh") == 0) + } else if ((len = STRLEN(p_sh)) >= 3) { + if (STRCMP(p_sh + len - 3, "csh") == 0) { shell_style = STYLE_GLOB; - else if (STRCMP(p_sh + len - 3, "zsh") == 0) + } else if (STRCMP(p_sh + len - 3, "zsh") == 0) { shell_style = STYLE_PRINT; + } } if (shell_style == STYLE_ECHO && strstr((char *)path_tail(p_sh), "sh") != NULL) shell_style = STYLE_VIMGLOB; - /* Compute the length of the command. We need 2 extra bytes: for the - * optional '&' and for the NUL. - * Worst case: "unset nonomatch; print -N >" plus two is 29 */ + // Compute the length of the command. We need 2 extra bytes: for the + // optional '&' and for the NUL. + // Worst case: "unset nonomatch; print -N >" plus two is 29 len = STRLEN(tempname) + 29; if (shell_style == STYLE_VIMGLOB) len += STRLEN(sh_vimglob_func); - for (i = 0; i < num_pat; ++i) { - /* Count the length of the patterns in the same way as they are put in - * "command" below. */ - ++len; /* add space */ - for (j = 0; pat[i][j] != NUL; ++j) { - if (vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL) - ++len; /* may add a backslash */ - ++len; + for (i = 0; i < num_pat; i++) { + // Count the length of the patterns in the same way as they are put in + // "command" below. + len++; // add space + for (j = 0; pat[i][j] != NUL; j++) { + if (vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL) { + len++; // may add a backslash + } + len++; } } + + if (is_fish_shell) { + len += sizeof("egin;"" end") - 1; + } + command = xmalloc(len); - /* - * Build the shell command: - * - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell - * recognizes this). - * - Add the shell command to print the expanded names. - * - Add the temp file name. - * - Add the file name patterns. - */ + // Build the shell command: + // - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell + // recognizes this). + // - Add the shell command to print the expanded names. + // - Add the temp file name. + // - Add the file name patterns. if (shell_style == STYLE_BT) { - /* change `command; command& ` to (command; command ) */ - STRCPY(command, "("); - STRCAT(command, pat[0] + 1); /* exclude first backtick */ + // change `command; command& ` to (command; command ) + if (is_fish_shell) { + STRCPY(command, "begin; "); + } else { + STRCPY(command, "("); + } + STRCAT(command, pat[0] + 1); // exclude first backtick p = command + STRLEN(command) - 1; - *p-- = ')'; /* remove last backtick */ - while (p > command && ascii_iswhite(*p)) - --p; - if (*p == '&') { /* remove trailing '&' */ + if (is_fish_shell) { + *p-- = ';'; + STRCAT(command, " end"); + } else { + *p-- = ')'; // remove last backtick + } + while (p > command && ascii_iswhite(*p)) { + p--; + } + if (*p == '&') { // remove trailing '&' ampersent = true; *p = ' '; } @@ -321,113 +338,109 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, STRCAT(command, tempname); - if (shell_style != STYLE_BT) - for (i = 0; i < num_pat; ++i) { - /* Put a backslash before special - * characters, except inside ``. */ + if (shell_style != STYLE_BT) { + for (i = 0; i < num_pat; i++) { + // Put a backslash before special + // characters, except inside ``. bool intick = false; p = command + STRLEN(command); *p++ = ' '; - for (j = 0; pat[i][j] != NUL; ++j) { - if (pat[i][j] == '`') + for (j = 0; pat[i][j] != NUL; j++) { + if (pat[i][j] == '`') { intick = !intick; - else if (pat[i][j] == '\\' && pat[i][j + 1] != NUL) { - /* Remove a backslash, take char literally. But keep - * backslash inside backticks, before a special character - * and before a backtick. */ + } else if (pat[i][j] == '\\' && pat[i][j + 1] != NUL) { + // Remove a backslash, take char literally. But keep + // backslash inside backticks, before a special character + // and before a backtick. if (intick || vim_strchr(SHELL_SPECIAL, pat[i][j + 1]) != NULL - || pat[i][j + 1] == '`') + || pat[i][j + 1] == '`') { *p++ = '\\'; - ++j; + } + j++; } else if (!intick - && ((flags & EW_KEEPDOLLAR) == 0 || pat[i][j] != '$') - && vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL) - /* Put a backslash before a special character, but not - * when inside ``. And not for $var when EW_KEEPDOLLAR is - * set. */ + && ((flags & EW_KEEPDOLLAR) == 0 || pat[i][j] != '$') + && vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL) { + // Put a backslash before a special character, but not + // when inside ``. And not for $var when EW_KEEPDOLLAR is + // set. *p++ = '\\'; + } - /* Copy one character. */ + // Copy one character. *p++ = pat[i][j]; } *p = NUL; } + } if (flags & EW_SILENT) { shellopts |= kShellOptHideMess; } - if (ampersent) - STRCAT(command, "&"); /* put the '&' after the redirection */ - - /* - * Using zsh -G: If a pattern has no matches, it is just deleted from - * the argument list, otherwise zsh gives an error message and doesn't - * expand any other pattern. - */ - if (shell_style == STYLE_PRINT) - extra_shell_arg = (char_u *)"-G"; /* Use zsh NULL_GLOB option */ - - /* - * If we use -f then shell variables set in .cshrc won't get expanded. - * vi can do it, so we will too, but it is only necessary if there is a "$" - * in one of the patterns, otherwise we can still use the fast option. - */ - else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat)) - extra_shell_arg = (char_u *)"-f"; /* Use csh fast option */ - - /* - * execute the shell command - */ + if (ampersent) { + STRCAT(command, "&"); // put the '&' after the redirection + } + + // Using zsh -G: If a pattern has no matches, it is just deleted from + // the argument list, otherwise zsh gives an error message and doesn't + // expand any other pattern. + if (shell_style == STYLE_PRINT) { + extra_shell_arg = (char_u *)"-G"; // Use zsh NULL_GLOB option + + // If we use -f then shell variables set in .cshrc won't get expanded. + // vi can do it, so we will too, but it is only necessary if there is a "$" + // in one of the patterns, otherwise we can still use the fast option. + } else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat)) { + extra_shell_arg = (char_u *)"-f"; // Use csh fast option + } + + // execute the shell command i = call_shell( command, shellopts, extra_shell_arg ); - /* When running in the background, give it some time to create the temp - * file, but don't wait for it to finish. */ - if (ampersent) + // When running in the background, give it some time to create the temp + // file, but don't wait for it to finish. + if (ampersent) { os_delay(10L, true); + } xfree(command); - if (i) { /* os_call_shell() failed */ + if (i) { // os_call_shell() failed os_remove((char *)tempname); xfree(tempname); - /* - * With interactive completion, the error message is not printed. - */ - if (!(flags & EW_SILENT)) - { - redraw_later_clear(); /* probably messed up screen */ - msg_putchar('\n'); /* clear bottom line quickly */ + // With interactive completion, the error message is not printed. + if (!(flags & EW_SILENT)) { + redraw_later_clear(); // probably messed up screen + msg_putchar('\n'); // clear bottom line quickly #if SIZEOF_LONG > SIZEOF_INT assert(Rows <= (long)INT_MAX + 1); #endif - cmdline_row = (int)(Rows - 1); /* continue on last line */ + cmdline_row = (int)(Rows - 1); // continue on last line MSG(_(e_wildexpand)); - msg_start(); /* don't overwrite this message */ + msg_start(); // don't overwrite this message } - /* If a `cmd` expansion failed, don't list `cmd` as a match, even when - * EW_NOTFOUND is given */ - if (shell_style == STYLE_BT) + // If a `cmd` expansion failed, don't list `cmd` as a match, even when + // EW_NOTFOUND is given + if (shell_style == STYLE_BT) { return FAIL; + } goto notfound; } - /* - * read the names from the file into memory - */ + // read the names from the file into memory fd = fopen((char *)tempname, READBIN); if (fd == NULL) { - /* Something went wrong, perhaps a file name with a special char. */ + // Something went wrong, perhaps a file name with a special char. if (!(flags & EW_SILENT)) { MSG(_(e_wildexpand)); - msg_start(); /* don't overwrite this message */ + msg_start(); // don't overwrite this message } xfree(tempname); goto notfound; @@ -438,7 +451,7 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, fclose(fd); return FAIL; } - long long templen = ftell(fd); /* get size of temp file */ + int64_t templen = ftell(fd); // get size of temp file if (templen < 0) { xfree(tempname); fclose(fd); @@ -456,7 +469,7 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, fclose(fd); os_remove((char *)tempname); if (readlen != len) { - /* unexpected read error */ + // unexpected read error EMSG2(_(e_notread), tempname); xfree(tempname); xfree(buffer); @@ -464,41 +477,40 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, } xfree(tempname); - /* file names are separated with Space */ + // file names are separated with Space if (shell_style == STYLE_ECHO) { - buffer[len] = '\n'; /* make sure the buffer ends in NL */ + buffer[len] = '\n'; // make sure the buffer ends in NL p = buffer; - for (i = 0; *p != '\n'; ++i) { /* count number of entries */ - while (*p != ' ' && *p != '\n') - ++p; - p = skipwhite(p); /* skip to next entry */ + for (i = 0; *p != '\n'; i++) { // count number of entries + while (*p != ' ' && *p != '\n') { + p++; + } + p = skipwhite(p); // skip to next entry } - } - /* file names are separated with NL */ - else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB) { - buffer[len] = NUL; /* make sure the buffer ends in NUL */ + // file names are separated with NL + } else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB) { + buffer[len] = NUL; // make sure the buffer ends in NUL p = buffer; - for (i = 0; *p != NUL; ++i) { /* count number of entries */ - while (*p != '\n' && *p != NUL) - ++p; - if (*p != NUL) - ++p; - p = skipwhite(p); /* skip leading white space */ + for (i = 0; *p != NUL; i++) { // count number of entries + while (*p != '\n' && *p != NUL) { + p++; + } + if (*p != NUL) { + p++; + } + p = skipwhite(p); // skip leading white space } - } - /* file names are separated with NUL */ - else { - /* - * Some versions of zsh use spaces instead of NULs to separate - * results. Only do this when there is no NUL before the end of the - * buffer, otherwise we would never be able to use file names with - * embedded spaces when zsh does use NULs. - * When we found a NUL once, we know zsh is OK, set did_find_nul and - * don't check for spaces again. - */ + // file names are separated with NUL + } else { + // Some versions of zsh use spaces instead of NULs to separate + // results. Only do this when there is no NUL before the end of the + // buffer, otherwise we would never be able to use file names with + // embedded spaces when zsh does use NULs. + // When we found a NUL once, we know zsh is OK, set did_find_nul and + // don't check for spaces again. check_spaces = false; if (shell_style == STYLE_PRINT && !did_find_nul) { - /* If there is a NUL, set did_find_nul, else set check_spaces */ + // If there is a NUL, set did_find_nul, else set check_spaces buffer[len] = NUL; if (len && (int)STRLEN(buffer) < (int)len) did_find_nul = true; @@ -506,72 +518,69 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, check_spaces = true; } - /* - * Make sure the buffer ends with a NUL. For STYLE_PRINT there - * already is one, for STYLE_GLOB it needs to be added. - */ - if (len && buffer[len - 1] == NUL) - --len; - else + // Make sure the buffer ends with a NUL. For STYLE_PRINT there + // already is one, for STYLE_GLOB it needs to be added. + if (len && buffer[len - 1] == NUL) { + len--; + } else { buffer[len] = NUL; + } i = 0; - for (p = buffer; p < buffer + len; ++p) - if (*p == NUL || (*p == ' ' && check_spaces)) { /* count entry */ - ++i; + for (p = buffer; p < buffer + len; p++) { + if (*p == NUL || (*p == ' ' && check_spaces)) { // count entry + i++; *p = NUL; } - if (len) - ++i; /* count last entry */ + } + if (len) { + i++; // count last entry + } } assert(buffer[len] == NUL || buffer[len] == '\n'); if (i == 0) { - /* - * Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I". - * /bin/sh will happily expand it to nothing rather than returning an - * error; and hey, it's good to check anyway -- webb. - */ + // Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I". + // /bin/sh will happily expand it to nothing rather than returning an + // error; and hey, it's good to check anyway -- webb. xfree(buffer); goto notfound; } *num_file = i; *file = xmalloc(sizeof(char_u *) * (size_t)i); - /* - * Isolate the individual file names. - */ + // Isolate the individual file names. p = buffer; for (i = 0; i < *num_file; ++i) { (*file)[i] = p; - /* Space or NL separates */ + // Space or NL separates if (shell_style == STYLE_ECHO || shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB) { while (!(shell_style == STYLE_ECHO && *p == ' ') - && *p != '\n' && *p != NUL) - ++p; - if (p == buffer + len) /* last entry */ + && *p != '\n' && *p != NUL) { + p++; + } + if (p == buffer + len) { // last entry *p = NUL; - else { + } else { *p++ = NUL; - p = skipwhite(p); /* skip to next entry */ + p = skipwhite(p); // skip to next entry } - } else { /* NUL separates */ - while (*p && p < buffer + len) /* skip entry */ - ++p; - ++p; /* skip NUL */ + } else { // NUL separates + while (*p && p < buffer + len) { // skip entry + p++; + } + p++; // skip NUL } } - /* - * Move the file names to allocated memory. - */ + // Move the file names to allocated memory. for (j = 0, i = 0; i < *num_file; i++) { // Require the files to exist. Helps when using /bin/sh if (!(flags & EW_NOTFOUND) && !os_path_exists((*file)[i])) { continue; } - /* check if this entry should be included */ + // check if this entry should be included dir = (os_isdir((*file)[i])); if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE))) continue; @@ -584,14 +593,15 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, p = xmalloc(STRLEN((*file)[i]) + 1 + dir); STRCPY(p, (*file)[i]); - if (dir) - add_pathsep((char *)p); /* add '/' to a directory name */ + if (dir) { + add_pathsep((char *)p); // add '/' to a directory name + } (*file)[j++] = p; } xfree(buffer); *num_file = j; - if (*num_file == 0) { /* rejected all entries */ + if (*num_file == 0) { // rejected all entries xfree(*file); *file = NULL; goto notfound; @@ -619,8 +629,8 @@ static void save_patterns(int num_pat, char_u **pat, int *num_file, for (i = 0; i < num_pat; i++) { s = vim_strsave(pat[i]); - /* Be compatible with expand_filename(): halve the number of - * backslashes. */ + // Be compatible with expand_filename(): halve the number of + // backslashes. backslash_halve(s); (*file)[i] = s; } diff --git a/src/nvim/path.c b/src/nvim/path.c index 3d1def8dd4..f2339c8046 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -1,3 +1,6 @@ +// 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 <inttypes.h> #include <stdbool.h> @@ -84,15 +87,15 @@ FileComparison path_full_compare(char_u *s1, char_u *s2, int checkname) /// /// @return pointer just past the last path separator (empty string, if fname /// ends in a slash), or empty string if fname is NULL. -char_u *path_tail(char_u *fname) +char_u *path_tail(const char_u *fname) FUNC_ATTR_NONNULL_RET { if (fname == NULL) { return (char_u *)""; } - char_u *tail = get_past_head(fname); - char_u *p = tail; + const char_u *tail = get_past_head(fname); + const char_u *p = tail; // Find last part of path. while (*p != NUL) { if (vim_ispathsep_nocolon(*p)) { @@ -100,7 +103,7 @@ char_u *path_tail(char_u *fname) } mb_ptr_adv(p); } - return tail; + return (char_u *)tail; } /// Get pointer to tail of "fname", including path separators. @@ -159,7 +162,7 @@ const char_u *invocation_path_tail(const char_u *invocation, size_t *len) /// @param fname A file path. (Must be != NULL.) /// @return Pointer to first found path separator + 1. /// An empty string, if `fname` doesn't contain a path separator, -char_u *path_next_component(char_u *fname) +const char *path_next_component(const char *fname) { assert(fname != NULL); while (*fname != NUL && !vim_ispathsep(*fname)) { @@ -174,9 +177,9 @@ char_u *path_next_component(char_u *fname) /// Get a pointer to one character past the head of a path name. /// Unix: after "/"; Win: after "c:\" /// If there is no head, path is returned. -char_u *get_past_head(char_u *path) +char_u *get_past_head(const char_u *path) { - char_u *retval = path; + const char_u *retval = path; #ifdef WIN32 // May skip "c:" @@ -189,7 +192,7 @@ char_u *get_past_head(char_u *path) ++retval; } - return retval; + return (char_u *)retval; } /* @@ -282,48 +285,63 @@ bool dir_of_file_exists(char_u *fname) return retval; } -/* - * Versions of fnamecmp() and fnamencmp() that handle '/' and '\' equally - * and deal with 'fileignorecase'. - */ -int vim_fnamecmp(char_u *x, char_u *y) +/// Compare two file names +/// +/// Handles '/' and '\\' correctly and deals with &fileignorecase option. +/// +/// @param[in] fname1 First file name. +/// @param[in] fname2 Second file name. +/// +/// @return 0 if they are equal, non-zero otherwise. +int path_fnamecmp(const char *fname1, const char *fname2) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { #ifdef BACKSLASH_IN_FILENAME - return vim_fnamencmp(x, y, MAXPATHL); + const size_t len1 = strlen(fname1); + const size_t len2 = strlen(fname2); + return path_fnamencmp(fname1, fname2, MAX(len1, len2)); #else - if (p_fic) - return mb_stricmp(x, y); - return STRCMP(x, y); + return mb_strcmp_ic((bool)p_fic, fname1, fname2); #endif } -int vim_fnamencmp(char_u *x, char_u *y, size_t len) +/// Compare two file names +/// +/// Handles '/' and '\\' correctly and deals with &fileignorecase option. +/// +/// @param[in] fname1 First file name. +/// @param[in] fname2 Second file name. +/// @param[in] len Compare at most len bytes. +/// +/// @return 0 if they are equal, non-zero otherwise. +int path_fnamencmp(const char *const fname1, const char *const fname2, + size_t len) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { #ifdef BACKSLASH_IN_FILENAME - char_u *px = x; - char_u *py = y; - int cx = NUL; - int cy = NUL; + int c1 = NUL; + int c2 = NUL; + const char *p1 = fname1; + const char *p2 = fname2; while (len > 0) { - cx = PTR2CHAR(px); - cy = PTR2CHAR(py); - if (cx == NUL || cy == NUL - || ((p_fic ? vim_tolower(cx) != vim_tolower(cy) : cx != cy) - && !(cx == '/' && cy == '\\') - && !(cx == '\\' && cy == '/'))) + c1 = PTR2CHAR((const char_u *)p1); + c2 = PTR2CHAR((const char_u *)p2); + if ((c1 == NUL || c2 == NUL + || (!((c1 == '/' || c1 == '\\') && (c2 == '\\' || c2 == '/')))) + && (p_fic ? (c1 != c2 && CH_FOLD(c1) != CH_FOLD(c2)) : c1 != c2)) { break; - len -= MB_PTR2LEN(px); - px += MB_PTR2LEN(px); - py += MB_PTR2LEN(py); + } + len -= MB_PTR2LEN((const char_u *)p1); + p1 += MB_PTR2LEN((const char_u *)p1); + p2 += MB_PTR2LEN((const char_u *)p2); } - if (len == 0) - return 0; - return cx - cy; + return c1 - c2; #else - if (p_fic) - return mb_strnicmp(x, y, len); - return STRNCMP(x, y, len); + if (p_fic) { + return mb_strnicmp((const char_u *)fname1, (const char_u *)fname2, len); + } + return strncmp(fname1, fname2, len); #endif } @@ -391,15 +409,22 @@ char *concat_fnames_realloc(char *fname1, const char *fname2, bool sep) fname2, len2, sep); } -/* - * Add a path separator to a file name, unless it already ends in a path - * separator. - */ -void add_pathsep(char *p) +/// Adds a path separator to a filename, unless it already ends in one. +/// +/// @return `true` if the path separator was added or already existed. +/// `false` if the filename is too long. +bool add_pathsep(char *p) FUNC_ATTR_NONNULL_ALL { - if (*p != NUL && !after_pathsep(p, p + strlen(p))) - strcat(p, PATHSEPSTR); + const size_t len = strlen(p); + if (*p != NUL && !after_pathsep(p, p + len)) { + const size_t pathsep_len = sizeof(PATHSEPSTR); + if (len > MAXPATHL - pathsep_len) { + return false; + } + memcpy(p + len, PATHSEPSTR, pathsep_len); + } + return true; } /// Get an allocated copy of the full path to a file. @@ -409,8 +434,8 @@ void add_pathsep(char *p) /// /// @return [allocated] Copy of absolute path to `fname` or NULL when /// `fname` is NULL. -char *FullName_save(char *fname, bool force) - FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC +char *FullName_save(const char *fname, bool force) + FUNC_ATTR_MALLOC { if (fname == NULL) { return NULL; @@ -428,7 +453,7 @@ char *FullName_save(char *fname, bool force) /// @param name An absolute or relative path. /// @return The absolute path of `name`. char_u *save_absolute_path(const char_u *name) - FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { if (!path_is_absolute_path(name)) { return (char_u *)FullName_save((char *)name, true); @@ -579,7 +604,7 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, } if (has_mbyte) { len = (size_t)(*mb_ptr2len)(path_end); - STRNCPY(p, path_end, len); + memcpy(p, path_end, len); p += len; path_end += len; } else @@ -797,7 +822,7 @@ static void expand_path_option(char_u *curdir, garray_T *gap) } STRMOVE(buf + len + 1, buf); STRCPY(buf, curdir); - buf[len] = PATHSEP; + buf[len] = (char_u)PATHSEP; simplify_filename(buf); } @@ -884,9 +909,9 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern) in_curdir = xcalloc((size_t)gap->ga_len, sizeof(char_u *)); for (int i = 0; i < gap->ga_len && !got_int; i++) { - char_u *path = fnames[i]; + char_u *path = fnames[i]; int is_in_curdir; - char_u *dir_end = gettail_dir(path); + char_u *dir_end = (char_u *)gettail_dir((const char *)path); char_u *pathsep_p; char_u *path_cutoff; @@ -988,20 +1013,22 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern) ga_remove_duplicate_strings(gap); } -/* - * Return the end of the directory name, on the first path - * separator: - * "/path/file", "/path/dir/", "/path//dir", "/file" - * ^ ^ ^ ^ - */ -char_u *gettail_dir(const char_u *fname) +/// Find end of the directory name +/// +/// @param[in] fname File name to process. +/// +/// @return end of the directory name, on the first path separator: +/// +/// "/path/file", "/path/dir/", "/path//dir", "/file" +/// ^ ^ ^ ^ +const char *gettail_dir(const char *const fname) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { - const char_u *dir_end = fname; - const char_u *next_dir_end = fname; + const char *dir_end = fname; + const char *next_dir_end = fname; bool look_for_sep = true; - const char_u *p; - for (p = fname; *p != NUL; ) { + for (const char *p = fname; *p != NUL; ) { if (vim_ispathsep(*p)) { if (look_for_sep) { next_dir_end = p; @@ -1014,7 +1041,7 @@ char_u *gettail_dir(const char_u *fname) } mb_ptr_adv(p); } - return (char_u *)dir_end; + return dir_end; } @@ -1220,7 +1247,7 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file, * "vim c:/" work. */ if (flags & EW_NOTFOUND) { addfile(&ga, t, flags | EW_DIR | EW_FILE); - } else if (os_path_exists(t)) { + } else { addfile(&ga, t, flags); } xfree(t); @@ -1309,12 +1336,12 @@ static int expand_backtick( /// When the path looks like a URL leave it unmodified. void slash_adjust(char_u *p) { - if (path_with_url(p)) { + if (path_with_url((const char *)p)) { return; } while (*p) { - if (*p == psepcN) { - *p = psepc; + if (*p == (char_u)psepcN) { + *p = (char_u)psepc; } mb_ptr_adv(p); } @@ -1533,8 +1560,8 @@ void simplify_filename(char_u *filename) p = tail; /* skip to char after ".." or "../" */ } } else { - ++components; /* simple path component */ - p = path_next_component(p); + components++; // Simple path component. + p = (char_u *)path_next_component((const char *)p); } } while (*p != NUL); } @@ -1688,7 +1715,7 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force) /// /// @param fname is the filename to expand /// @return [allocated] Full path (NULL for failure). -char *fix_fname(char *fname) +char *fix_fname(const char *fname) { #ifdef UNIX return FullName_save(fname, true); @@ -1829,7 +1856,7 @@ int pathcmp(const char *p, const char *q, int maxlen) break; } - if ((p_fic ? vim_toupper(c1) != vim_toupper(c2) : c1 != c2) + if ((p_fic ? mb_toupper(c1) != mb_toupper(c2) : c1 != c2) #ifdef BACKSLASH_IN_FILENAME /* consider '/' and '\\' to be equal */ && !((c1 == '/' && c2 == '\\') @@ -1840,8 +1867,8 @@ int pathcmp(const char *p, const char *q, int maxlen) return -1; if (vim_ispathsep(c2)) return 1; - return p_fic ? vim_toupper(c1) - vim_toupper(c2) - : c1 - c2; /* no match */ + return p_fic ? mb_toupper(c1) - mb_toupper(c2) + : c1 - c2; // no match } i += MB_PTR2LEN((char_u *)p + i); @@ -2124,17 +2151,12 @@ int append_path(char *path, const char *to_append, size_t max_len) size_t current_length = strlen(path); size_t to_append_length = strlen(to_append); - // Do not append empty strings. - if (to_append_length == 0) { + // Do not append empty string or a dot. + if (to_append_length == 0 || strcmp(to_append, ".") == 0) { return OK; } - // Do not append a dot. - if (STRCMP(to_append, ".") == 0) { - return OK; - } - - // Glue both paths with a slash. + // Combine the path segments, separated by a slash. if (current_length > 0 && !vim_ispathsep_nocolon(path[current_length-1])) { current_length += 1; // Count the trailing slash. @@ -2143,7 +2165,7 @@ int append_path(char *path, const char *to_append, size_t max_len) return FAIL; } - STRCAT(path, PATHSEPSTR); + xstrlcat(path, PATHSEPSTR, max_len); } // +1 for the NUL at the end. @@ -2151,7 +2173,7 @@ int append_path(char *path, const char *to_append, size_t max_len) return FAIL; } - STRCAT(path, to_append); + xstrlcat(path, to_append, max_len); return OK; } @@ -2181,7 +2203,8 @@ static int path_get_absolute_path(const char_u *fname, char_u *buf, relative_directory[0] = '/'; relative_directory[1] = NUL; } else { - STRNCPY(relative_directory, fname, p-fname); + assert(p >= fname); + memcpy(relative_directory, fname, (size_t)(p - fname)); relative_directory[p-fname] = NUL; } end_of_path = (char *) (p + 1); @@ -2214,3 +2237,50 @@ int path_is_absolute_path(const char_u *fname) return *fname == '/' || *fname == '~'; #endif } + +/// Builds a full path from an invocation name `argv0`, based on heuristics. +/// +/// @param[in] argv0 Name by which Nvim was invoked. +/// @param[out] buf Guessed full path to `argv0`. +/// @param[in] bufsize Size of `buf`. +/// +/// @see os_exepath +void path_guess_exepath(const char *argv0, char *buf, size_t bufsize) + FUNC_ATTR_NONNULL_ALL +{ + char *path = getenv("PATH"); + + if (path == NULL || path_is_absolute_path((char_u *)argv0)) { + xstrlcpy(buf, argv0, bufsize); + } else if (argv0[0] == '.' || strchr(argv0, PATHSEP)) { + // Relative to CWD. + if (os_dirname((char_u *)buf, MAXPATHL) != OK) { + buf[0] = NUL; + } + xstrlcat(buf, PATHSEPSTR, bufsize); + xstrlcat(buf, argv0, bufsize); + } else { + // Search $PATH for plausible location. + const void *iter = NULL; + do { + const char *dir; + size_t dir_len; + iter = vim_env_iter(ENV_SEPCHAR, path, iter, &dir, &dir_len); + if (dir == NULL || dir_len == 0) { + break; + } + if (dir_len + 1 > sizeof(NameBuff)) { + continue; + } + xstrlcpy((char *)NameBuff, dir, dir_len + 1); + xstrlcat((char *)NameBuff, PATHSEPSTR, sizeof(NameBuff)); + xstrlcat((char *)NameBuff, argv0, sizeof(NameBuff)); + if (os_can_exe(NameBuff, NULL, false)) { + xstrlcpy(buf, (char *)NameBuff, bufsize); + return; + } + } while (iter != NULL); + // Not found in $PATH, fall back to argv0. + xstrlcpy(buf, argv0, bufsize); + } +} diff --git a/src/nvim/po/CMakeLists.txt b/src/nvim/po/CMakeLists.txt index d2b62f89a0..121f22129a 100644 --- a/src/nvim/po/CMakeLists.txt +++ b/src/nvim/po/CMakeLists.txt @@ -32,10 +32,10 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG) zh_CN.UTF-8 zh_TW.UTF-8) - set(NEOVIM_RELATIVE_SOURCES) - foreach(SRC ${NEOVIM_SOURCES} ${NEOVIM_HEADERS}) + set(NVIM_RELATIVE_SOURCES) + foreach(SRC ${NVIM_SOURCES} ${NVIM_HEADERS}) file(RELATIVE_PATH RELATIVE_SRC ${CMAKE_CURRENT_SOURCE_DIR} ${SRC}) - list(APPEND NEOVIM_RELATIVE_SOURCES ${RELATIVE_SRC}) + list(APPEND NVIM_RELATIVE_SOURCES ${RELATIVE_SRC}) endforeach() set(NVIM_POT ${CMAKE_CURRENT_BINARY_DIR}/nvim.pot) @@ -46,9 +46,9 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG) -DXGETTEXT_PRG=${XGETTEXT_PRG} -DPOT_FILE=${NVIM_POT} -DSEARCH_DIR=${CMAKE_CURRENT_SOURCE_DIR} - "\"-DSOURCES=${NEOVIM_RELATIVE_SOURCES}\"" + "\"-DSOURCES=${NVIM_RELATIVE_SOURCES}\"" -P ${PROJECT_SOURCE_DIR}/cmake/RunXgettext.cmake - DEPENDS ${NEOVIM_SOURCES}) + DEPENDS ${NVIM_SOURCES}) add_custom_target(potfile DEPENDS ${NVIM_POT}) diff --git a/src/nvim/po/check.vim b/src/nvim/po/check.vim index 1622741da6..b323174550 100644 --- a/src/nvim/po/check.vim +++ b/src/nvim/po/check.vim @@ -33,36 +33,66 @@ func! GetMline() return substitute(idline, '[^%]*\(%[-+ #''.0-9*]*l\=[dsuxXpoc%]\)\=', '\1', 'g') endfunc -" This only works when 'wrapscan' is set. +" This only works when 'wrapscan' is not set. let s:save_wrapscan = &wrapscan -set wrapscan +set nowrapscan " Start at the first "msgid" line. 1 -/^msgid -let startline = line('.') +/^msgid\> + +" When an error is detected this is set to the line number. +" Note: this is used in the Makefile. let error = 0 while 1 if getline(line('.') - 1) !~ "no-c-format" - let fromline = GetMline() + " go over the "msgid" and "msgid_plural" lines + let prevfromline = 'foobar' + while 1 + let fromline = GetMline() + if prevfromline != 'foobar' && prevfromline != fromline + echomsg 'Mismatching % in line ' . (line('.') - 1) + echomsg 'msgid: ' . prevfromline + echomsg 'msgid ' . fromline + if error == 0 + let error = line('.') + endif + endif + if getline('.') !~ 'msgid_plural' + break + endif + let prevfromline = fromline + endwhile + if getline('.') !~ '^msgstr' - echo 'Missing "msgstr" in line ' . line('.') - let error = 1 - endif - let toline = GetMline() - if fromline != toline - echo 'Mismatching % in line ' . (line('.') - 1) - echo 'msgid: ' . fromline - echo 'msgstr: ' . toline - let error = 1 + echomsg 'Missing "msgstr" in line ' . line('.') + if error == 0 + let error = line('.') + endif endif + + " check all the 'msgstr' lines + while getline('.') =~ '^msgstr' + let toline = GetMline() + if fromline != toline + echomsg 'Mismatching % in line ' . (line('.') - 1) + echomsg 'msgid: ' . fromline + echomsg 'msgstr: ' . toline + if error == 0 + let error = line('.') + endif + endif + if line('.') == line('$') + break + endif + endwhile endif - " Find next msgid. - " Wrap around at the end of the file, quit when back at the first one. - /^msgid - if line('.') == startline + " Find next msgid. Quit when there is no more. + let lnum = line('.') + silent! /^msgid\> + if line('.') == lnum break endif endwhile @@ -77,12 +107,16 @@ endwhile " 1 if search('msgid "\("\n"\)\?\([EW][0-9]\+:\).*\nmsgstr "\("\n"\)\?[^"]\@=\2\@!') > 0 - echo 'Mismatching error/warning code in line ' . line('.') - let error = 1 + echomsg 'Mismatching error/warning code in line ' . line('.') + if error == 0 + let error = line('.') + endif endif if error == 0 - echo "OK" + echomsg "OK" +else + exe error endif redir END diff --git a/src/nvim/po/eo.po b/src/nvim/po/eo.po index d0a47d6e9b..3fb300c63f 100644 --- a/src/nvim/po/eo.po +++ b/src/nvim/po/eo.po @@ -5,7 +5,7 @@ # # UNUA TRADUKISTO Dominique PELLE <dominique.pelle ĉe gmail.com> # PROVLEGANTO(J) Felipe CASTRO <fefcas ĉe gmail.com> -# Antono MECHELYNCK <antoine.mechelynck ĉe skynet.be> +# Antono MECHELYNCK <antoine.mechelynck ĉe gmail.com> # Yves NEVELSTEEN # # Uzitaj vortaroj kaj fakvortaroj: @@ -23,8 +23,8 @@ msgid "" msgstr "" "Project-Id-Version: Vim(Esperanto)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-03-29 23:03+0200\n" -"PO-Revision-Date: 2016-03-29 23:05+0200\n" +"POT-Creation-Date: 2017-01-16 00:30+0100\n" +"PO-Revision-Date: 2017-01-16 01:14+0100\n" "Last-Translator: Dominique PELLÉ <dominique.pelle@gmail.com>\n" "Language-Team: \n" "Language: eo\n" @@ -32,203 +32,169 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../api/private/helpers.c:201 -#, fuzzy -msgid "Unable to get option value" -msgstr "fiaskis akiri valoron de opcio" +msgid "E831: bf_key_init() called with empty password" +msgstr "E831: bf_key_init() alvokita kun malplena pasvorto" -#: ../api/private/helpers.c:204 -#, fuzzy -msgid "internal error: unknown option type" -msgstr "interna eraro: neniu vim-a listero" +msgid "E820: sizeof(uint32_t) != 4" +msgstr "E820: sizeof(uint32_t) != 4" + +msgid "E817: Blowfish big/little endian use wrong" +msgstr "E817: Misuzo de pezkomenca/pezfina en blowfish" + +msgid "E818: sha256 test failed" +msgstr "E818: Testo de sha256 malsukcesis" + +msgid "E819: Blowfish test failed" +msgstr "E819: Testo de blowfish malsukcesis" -#: ../buffer.c:92 msgid "[Location List]" msgstr "[Listo de lokoj]" # DP: Ĉu vere indas traduki Quickfix? -#: ../buffer.c:93 msgid "[Quickfix List]" msgstr "[Listo de rapidriparoj]" -#: ../buffer.c:94 msgid "E855: Autocommands caused command to abort" msgstr "E855: AÅtokomandoj haltigis komandon" -#: ../buffer.c:135 msgid "E82: Cannot allocate any buffer, exiting..." msgstr "E82: Ne eblas disponigi iun ajn bufron, nun eliras..." -#: ../buffer.c:138 msgid "E83: Cannot allocate buffer, using other one..." msgstr "E83: Ne eblas disponigi bufron, nun uzas alian..." -#: ../buffer.c:763 +msgid "E931: Buffer cannot be registered" +msgstr "E931: Bufro ne povas esti registrita" + +msgid "E937: Attempt to delete a buffer that is in use" +msgstr "E937: Provo de forviÅo de bufro, kiu estas uzanta" + msgid "E515: No buffers were unloaded" msgstr "E515: Neniu bufro estis malÅargita" -#: ../buffer.c:765 msgid "E516: No buffers were deleted" msgstr "E516: Neniu bufro estis forviÅita" -#: ../buffer.c:767 msgid "E517: No buffers were wiped out" msgstr "E517: Neniu bufro estis detruita" -#: ../buffer.c:772 msgid "1 buffer unloaded" msgstr "1 bufro malÅargita" -#: ../buffer.c:774 #, c-format msgid "%d buffers unloaded" msgstr "%d bufroj malÅargitaj" -#: ../buffer.c:777 msgid "1 buffer deleted" msgstr "1 bufro forviÅita" -#: ../buffer.c:779 #, c-format msgid "%d buffers deleted" msgstr "%d bufroj forviÅitaj" -#: ../buffer.c:782 msgid "1 buffer wiped out" msgstr "1 bufro detruita" -#: ../buffer.c:784 #, c-format msgid "%d buffers wiped out" msgstr "%d bufroj detruitaj" -#: ../buffer.c:806 msgid "E90: Cannot unload last buffer" msgstr "E90: Ne eblas malÅargi la lastan bufron" -#: ../buffer.c:874 msgid "E84: No modified buffer found" msgstr "E84: Neniu modifita bufro trovita" #. back where we started, didn't find anything. -#: ../buffer.c:903 msgid "E85: There is no listed buffer" msgstr "E85: Estas neniu listigita bufro" -#: ../buffer.c:915 msgid "E87: Cannot go beyond last buffer" msgstr "E87: Ne eblas iri preter la lastan bufron" -#: ../buffer.c:917 msgid "E88: Cannot go before first buffer" msgstr "E88: Ne eblas iri antaÅ la unuan bufron" -#: ../buffer.c:945 #, c-format -msgid "" -"E89: No write since last change for buffer %<PRId64> (add ! to override)" +msgid "E89: No write since last change for buffer %ld (add ! to override)" msgstr "" -"E89: Neniu skribo de post la lasta ÅanÄo de la bufro %<PRId64> (aldonu ! por " +"E89: Neniu skribo de post la lasta ÅanÄo de la bufro %ld (aldonu ! por " "transpasi)" -#. wrap around (may cause duplicates) -#: ../buffer.c:1423 msgid "W14: Warning: List of file names overflow" msgstr "W14: Averto: Listo de dosiernomoj troas" -#: ../buffer.c:1555 ../quickfix.c:3361 #, c-format -msgid "E92: Buffer %<PRId64> not found" -msgstr "E92: Bufro %<PRId64> ne trovita" +msgid "E92: Buffer %ld not found" +msgstr "E92: Bufro %ld ne trovita" -#: ../buffer.c:1798 #, c-format msgid "E93: More than one match for %s" msgstr "E93: Pli ol unu kongruo kun %s" -#: ../buffer.c:1800 #, c-format msgid "E94: No matching buffer for %s" msgstr "E94: Neniu bufro kongruas kun %s" -#: ../buffer.c:2161 #, c-format -msgid "line %<PRId64>" -msgstr "linio %<PRId64>" +msgid "line %ld" +msgstr "linio %ld" -#: ../buffer.c:2233 msgid "E95: Buffer with this name already exists" msgstr "E95: Bufro kun tiu nomo jam ekzistas" -#: ../buffer.c:2498 msgid " [Modified]" msgstr "[Modifita]" -#: ../buffer.c:2501 msgid "[Not edited]" msgstr "[Ne redaktita]" -#: ../buffer.c:2504 msgid "[New file]" msgstr "[Nova dosiero]" -#: ../buffer.c:2505 msgid "[Read errors]" msgstr "[Eraroj de legado]" -#: ../buffer.c:2506 ../buffer.c:3217 ../fileio.c:1807 ../screen.c:4895 msgid "[RO]" msgstr "[Nurlegebla]" -#: ../buffer.c:2507 ../fileio.c:1807 msgid "[readonly]" msgstr "[nurlegebla]" -#: ../buffer.c:2524 #, c-format msgid "1 line --%d%%--" msgstr "1 linio --%d%%--" -#: ../buffer.c:2526 #, c-format -msgid "%<PRId64> lines --%d%%--" -msgstr "%<PRId64> linioj --%d%%--" +msgid "%ld lines --%d%%--" +msgstr "%ld linioj --%d%%--" -#: ../buffer.c:2530 #, c-format -msgid "line %<PRId64> of %<PRId64> --%d%%-- col " -msgstr "linio %<PRId64> de %<PRId64> --%d%%-- kol " +msgid "line %ld of %ld --%d%%-- col " +msgstr "linio %ld de %ld --%d%%-- kol " -#: ../buffer.c:2632 ../buffer.c:4292 ../memline.c:1554 msgid "[No Name]" msgstr "[Neniu nomo]" #. must be a help buffer -#: ../buffer.c:2667 msgid "help" msgstr "helpo" -#: ../buffer.c:3225 ../screen.c:4883 msgid "[Help]" msgstr "[Helpo]" -#: ../buffer.c:3254 ../screen.c:4887 msgid "[Preview]" msgstr "[AntaÅvido]" -#: ../buffer.c:3528 msgid "All" msgstr "Ĉio" -#: ../buffer.c:3528 msgid "Bot" msgstr "Subo" -#: ../buffer.c:3531 msgid "Top" msgstr "Supro" -#: ../buffer.c:4244 msgid "" "\n" "# Buffer list:\n" @@ -236,12 +202,10 @@ msgstr "" "\n" "# Listo de bufroj:\n" -#: ../buffer.c:4289 msgid "[Scratch]" msgstr "[Malneto]" # DP: Vidu ":help sign-support" por klarigo pri "Sign" -#: ../buffer.c:4529 msgid "" "\n" "--- Signs ---" @@ -249,200 +213,235 @@ msgstr "" "\n" "--- Emfazaj simbolaĵoj ---" -#: ../buffer.c:4538 #, c-format msgid "Signs for %s:" msgstr "Emfazaj simbolaĵoj de %s:" -#: ../buffer.c:4543 #, c-format -msgid " line=%<PRId64> id=%d name=%s" -msgstr " linio=%<PRId64> id=%d nomo=%s" +msgid " line=%ld id=%d name=%s" +msgstr " linio=%ld id=%d nomo=%s" -#: ../cursor_shape.c:68 -msgid "E545: Missing colon" -msgstr "E545: Mankas dupunkto" +msgid "E902: Cannot connect to port" +msgstr "E902: Ne eblas konekti al pordo" -#: ../cursor_shape.c:70 ../cursor_shape.c:94 -msgid "E546: Illegal mode" -msgstr "E546: ReÄimo nepermesata" +msgid "E901: gethostbyname() in channel_open()" +msgstr "E901: gethostbyname() en channel_open()" -#: ../cursor_shape.c:134 -msgid "E548: digit expected" -msgstr "E548: cifero atendata" +msgid "E898: socket() in channel_open()" +msgstr "E898: gethostbyname() en channel_open()" -#: ../cursor_shape.c:138 -msgid "E549: Illegal percentage" -msgstr "E549: Nevalida procento" +msgid "E903: received command with non-string argument" +msgstr "E903: ricevis komandon kun argumento, kiu ne estas ĉeno" + +msgid "E904: last argument for expr/call must be a number" +msgstr "E904: lasta argumento de \"expr/call\" devas esti nombro" + +msgid "E904: third argument for call must be a list" +msgstr "E904: tria argumento de \"call\" devas esti listo" + +#, c-format +msgid "E905: received unknown command: %s" +msgstr "E905: nekonata komando ricevita: %s" + +#, c-format +msgid "E630: %s(): write while not connected" +msgstr "E630: %s(): konservo dum nekonektita" + +#, c-format +msgid "E631: %s(): write failed" +msgstr "E631: %s(): Konservo malsukcesis" + +#, c-format +msgid "E917: Cannot use a callback with %s()" +msgstr "E917: Ne eblas uzi reagfunkcion kun %s()" + +msgid "E912: cannot use ch_evalexpr()/ch_sendexpr() with a raw or nl channel" +msgstr "E912: ne eblas uzi ch_evalexpr()/ch_sendexpr() kun kruda aÅ nl kanalo" + +msgid "E906: not an open channel" +msgstr "E906: ne estas malfermita kanalo" + +msgid "E920: _io file requires _name to be set" +msgstr "E920: dosiero _io bezonas _name" + +msgid "E915: in_io buffer requires in_buf or in_name to be set" +msgstr "E915: bufro in_io bezonas in_buf aÅ in_name" + +#, c-format +msgid "E918: buffer must be loaded: %s" +msgstr "E918: bufro devas esti Åargita: %s" + +msgid "E821: File is encrypted with unknown method" +msgstr "E821: Dosiero estas ĉifrita per nekonata metodo" + +msgid "Warning: Using a weak encryption method; see :help 'cm'" +msgstr "Averto: uzo de malfortika ĉifrada metodo; vidu :help 'cm'" + +msgid "Enter encryption key: " +msgstr "Tajpu la Ålosilon de ĉifrado: " + +msgid "Enter same key again: " +msgstr "Tajpu la Ålosilon denove: " + +msgid "Keys don't match!" +msgstr "Åœlosiloj ne kongruas!" + +msgid "[crypted]" +msgstr "[ĉifrita]" + +#, c-format +msgid "E720: Missing colon in Dictionary: %s" +msgstr "E720: Mankas dupunkto en la vortaro: %s" + +#, c-format +msgid "E721: Duplicate key in Dictionary: \"%s\"" +msgstr "E721: Ripetita Ålosilo en la vortaro: \"%s\"" + +#, c-format +msgid "E722: Missing comma in Dictionary: %s" +msgstr "E722: Mankas komo en la vortaro: %s" + +#, c-format +msgid "E723: Missing end of Dictionary '}': %s" +msgstr "E723: Mankas fino de vortaro '}': %s" + +msgid "extend() argument" +msgstr "argumento de extend()" -#: ../diff.c:146 #, c-format -msgid "E96: Can not diff more than %<PRId64> buffers" -msgstr "E96: Ne eblas dosierdiferenci pli ol %<PRId64> bufrojn" +msgid "E737: Key already exists: %s" +msgstr "E737: Åœlosilo jam ekzistas: %s" + +#, c-format +msgid "E96: Cannot diff more than %ld buffers" +msgstr "E96: Ne eblas dosierdiferenci pli ol %ld bufrojn" -#: ../diff.c:753 msgid "E810: Cannot read or write temp files" msgstr "E810: Ne eblas legi aÅ skribi provizorajn dosierojn" -#: ../diff.c:755 msgid "E97: Cannot create diffs" msgstr "E97: Ne eblas krei dosierdiferencojn" -#: ../diff.c:966 +msgid "Patch file" +msgstr "Flika dosiero" + msgid "E816: Cannot read patch output" msgstr "E816: Ne eblas legi eliron de flikilo \"patch\"" -#: ../diff.c:1220 msgid "E98: Cannot read diff output" msgstr "E98: Ne eblas legi eliron de dosierdiferencilo \"diff\"" -#: ../diff.c:2081 msgid "E99: Current buffer is not in diff mode" msgstr "E99: Aktuala bufro ne estas en dosierdiferenca reÄimo" -#: ../diff.c:2100 msgid "E793: No other buffer in diff mode is modifiable" msgstr "E793: Neniu alia bufro en dosierdiferenca reÄimo estas modifebla" -#: ../diff.c:2102 msgid "E100: No other buffer in diff mode" msgstr "E100: Neniu alia bufro en dosierdiferenca reÄimo" -#: ../diff.c:2112 msgid "E101: More than two buffers in diff mode, don't know which one to use" msgstr "E101: Pli ol du bufroj en dosierdiferenca reÄimo, ne scias kiun uzi" -#: ../diff.c:2141 #, c-format msgid "E102: Can't find buffer \"%s\"" msgstr "E102: Ne eblas trovi bufron \"%s\"" -#: ../diff.c:2152 #, c-format msgid "E103: Buffer \"%s\" is not in diff mode" msgstr "E103: Bufro \"%s\" ne estas en dosierdiferenca reÄimo" -#: ../diff.c:2193 msgid "E787: Buffer changed unexpectedly" msgstr "E787: Bufro ÅanÄiÄis neatendite" -#: ../digraph.c:1598 msgid "E104: Escape not allowed in digraph" msgstr "E104: Eskapsigno nepermesebla en duliteraĵo" -#: ../digraph.c:1760 msgid "E544: Keymap file not found" msgstr "E544: Dosiero de klavmapo ne troveblas" -#: ../digraph.c:1785 msgid "E105: Using :loadkeymap not in a sourced file" msgstr "E105: Uzo de \":loadkeymap\" nur eblas en vim-skripto" -#: ../digraph.c:1821 msgid "E791: Empty keymap entry" msgstr "E791: Malplena rikordo en klavmapo" -#: ../edit.c:82 msgid " Keyword completion (^N^P)" msgstr " Kompletigo de Ålosilvorto (^N^P)" #. ctrl_x_mode == 0, ^P/^N compl. -#: ../edit.c:83 msgid " ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" msgstr " ReÄimo ^X (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" -#: ../edit.c:85 msgid " Whole line completion (^L^N^P)" msgstr " Kompletigo de tuta linio (^L^N^P)" -#: ../edit.c:86 msgid " File name completion (^F^N^P)" msgstr " Kompletigo de dosiernomo (^F^N^P)" -#: ../edit.c:87 msgid " Tag completion (^]^N^P)" msgstr " Kompletigo de etikedo (^]^N^P)" -#: ../edit.c:88 msgid " Path pattern completion (^N^P)" msgstr " Kompletigo de Åablona dosierindiko (^N^P)" -#: ../edit.c:89 msgid " Definition completion (^D^N^P)" msgstr " Kompletigo de difino (^D^N^P)" -#: ../edit.c:91 msgid " Dictionary completion (^K^N^P)" msgstr " Kompletigo de vortaro (^K^N^P)" -#: ../edit.c:92 msgid " Thesaurus completion (^T^N^P)" msgstr " Kompletigo de tezaÅro (^T^N^P)" -#: ../edit.c:93 msgid " Command-line completion (^V^N^P)" msgstr " Kompletigo de komanda linio (^V^N^P)" -#: ../edit.c:94 msgid " User defined completion (^U^N^P)" msgstr " Kompletigo difinita de uzanto (^U^N^P)" # DP: Ĉu eblas trovi pli bonan tradukon? -#: ../edit.c:95 msgid " Omni completion (^O^N^P)" msgstr " Kompletigo Omni (^O^N^P)" -#: ../edit.c:96 msgid " Spelling suggestion (s^N^P)" msgstr " Sugesto de literumo (s^N^P)" -#: ../edit.c:97 msgid " Keyword Local completion (^N^P)" msgstr " Kompletigo loka de Ålosilvorto (^N/^P)" -#: ../edit.c:100 msgid "Hit end of paragraph" msgstr "Atingis finon de alineo" -#: ../edit.c:101 msgid "E839: Completion function changed window" msgstr "E839: Kompletiga funkcio ÅanÄis la fenestron" -#: ../edit.c:102 msgid "E840: Completion function deleted text" msgstr "E840: Kompletiga funkcio forviÅis tekston" -#: ../edit.c:1847 msgid "'dictionary' option is empty" msgstr "La opcio 'dictionary' estas malplena" -#: ../edit.c:1848 msgid "'thesaurus' option is empty" msgstr "La opcio 'thesaurus' estas malplena" -#: ../edit.c:2655 #, c-format msgid "Scanning dictionary: %s" msgstr "Analizas vortaron: %s" -#: ../edit.c:3079 msgid " (insert) Scroll (^E/^Y)" msgstr " (enmeto) Rulumo (^E/^Y)" -#: ../edit.c:3081 msgid " (replace) Scroll (^E/^Y)" msgstr " (anstataÅigo) Rulumo (^E/^Y)" -#: ../edit.c:3587 #, c-format msgid "Scanning: %s" msgstr "Analizas: %s" -#: ../edit.c:3614 msgid "Scanning tags." msgstr "Analizas etikedojn." -#: ../edit.c:4519 msgid " Adding" msgstr " Aldonanta" @@ -450,429 +449,159 @@ msgstr " Aldonanta" #. * be called before line = ml_get(), or when this address is no #. * longer needed. -- Acevedo. #. -#: ../edit.c:4562 msgid "-- Searching..." msgstr "-- Serĉanta..." -#: ../edit.c:4618 msgid "Back at original" msgstr "Reveninta al originalo" -#: ../edit.c:4621 msgid "Word from other line" msgstr "Vorto el alia linio" -#: ../edit.c:4624 msgid "The only match" msgstr "La sola kongruo" -#: ../edit.c:4680 #, c-format msgid "match %d of %d" msgstr "kongruo %d de %d" -#: ../edit.c:4684 #, c-format msgid "match %d" msgstr "kongruo %d" -#: ../eval.c:137 +#. maximum nesting of lists and dicts msgid "E18: Unexpected characters in :let" msgstr "E18: Neatenditaj signoj en \":let\"" -#: ../eval.c:138 -#, c-format -msgid "E684: list index out of range: %<PRId64>" -msgstr "E684: indekso de listo ekster limoj: %<PRId64>" - -#: ../eval.c:139 #, c-format msgid "E121: Undefined variable: %s" msgstr "E121: Nedifinita variablo: %s" -#: ../eval.c:140 msgid "E111: Missing ']'" msgstr "E111: Mankas ']'" -#: ../eval.c:141 -#, c-format -msgid "E686: Argument of %s must be a List" -msgstr "E686: Argumento de %s devas esti Listo" - -#: ../eval.c:143 -#, c-format -msgid "E712: Argument of %s must be a List or Dictionary" -msgstr "E712: Argumento de %s devas esti Listo aÅ Vortaro" - -#: ../eval.c:145 -msgid "E714: List required" -msgstr "E714: Listo bezonata" - -#: ../eval.c:146 -msgid "E715: Dictionary required" -msgstr "E715: Vortaro bezonata" - -#: ../eval.c:147 -#, c-format -msgid "E118: Too many arguments for function: %s" -msgstr "E118: Tro da argumentoj por funkcio: %s" - -#: ../eval.c:148 -#, c-format -msgid "E716: Key not present in Dictionary: %s" -msgstr "E716: Åœlosilo malekzistas en Vortaro: %s" - -#: ../eval.c:150 -#, c-format -msgid "E122: Function %s already exists, add ! to replace it" -msgstr "E122: La funkcio %s jam ekzistas (aldonu ! por anstataÅigi Äin)" - -#: ../eval.c:151 -msgid "E717: Dictionary entry already exists" -msgstr "E717: Rikordo de vortaro jam ekzistas" - -#: ../eval.c:152 -msgid "E718: Funcref required" -msgstr "E718: Funcref bezonata" - -#: ../eval.c:153 msgid "E719: Cannot use [:] with a Dictionary" msgstr "E719: Uzo de [:] ne eblas kun Vortaro" -#: ../eval.c:154 #, c-format msgid "E734: Wrong variable type for %s=" msgstr "E734: Nevalida datumtipo de variablo de %s=" -#: ../eval.c:155 -#, c-format -msgid "E130: Unknown function: %s" -msgstr "E130: Nekonata funkcio: %s" - -#: ../eval.c:156 #, c-format msgid "E461: Illegal variable name: %s" msgstr "E461: Nevalida nomo de variablo: %s" -#: ../eval.c:157 msgid "E806: using Float as a String" msgstr "E806: uzo de Glitpunktnombro kiel Ĉeno" -#: ../eval.c:1830 msgid "E687: Less targets than List items" msgstr "E687: Malpli da celoj ol Listeroj" -#: ../eval.c:1834 msgid "E688: More targets than List items" msgstr "E688: Pli da celoj ol Listeroj" -#: ../eval.c:1906 msgid "Double ; in list of variables" msgstr "Duobla ; en listo de variabloj" -#: ../eval.c:2078 #, c-format msgid "E738: Can't list variables for %s" msgstr "E738: Ne eblas listigi variablojn de %s" -#: ../eval.c:2391 msgid "E689: Can only index a List or Dictionary" msgstr "E689: Nur eblas indeksi Liston aÅ Vortaron" -#: ../eval.c:2396 msgid "E708: [:] must come last" msgstr "E708: [:] devas esti laste" -#: ../eval.c:2439 msgid "E709: [:] requires a List value" msgstr "E709: [:] bezonas listan valoron" -#: ../eval.c:2674 msgid "E710: List value has more items than target" msgstr "E710: Lista valoro havas pli da eroj ol la celo" -#: ../eval.c:2678 msgid "E711: List value has not enough items" msgstr "E711: Lista valoro ne havas sufiĉe da eroj" -#: ../eval.c:2867 msgid "E690: Missing \"in\" after :for" msgstr "E690: \"in\" mankas post \":for\"" -#: ../eval.c:3063 -#, c-format -msgid "E107: Missing parentheses: %s" -msgstr "E107: Mankas krampoj: %s" - -#: ../eval.c:3263 #, c-format msgid "E108: No such variable: \"%s\"" msgstr "E108: Ne estas tia variablo: \"%s\"" -#: ../eval.c:3333 msgid "E743: variable nested too deep for (un)lock" msgstr "E743: variablo ingita tro profunde por malÅlosi" -#: ../eval.c:3630 msgid "E109: Missing ':' after '?'" msgstr "E109: Mankas ':' post '?'" -#: ../eval.c:3893 msgid "E691: Can only compare List with List" msgstr "E691: Eblas nur kompari Liston kun Listo" -#: ../eval.c:3895 -msgid "E692: Invalid operation for Lists" +msgid "E692: Invalid operation for List" msgstr "E692: Nevalida operacio de Listoj" -#: ../eval.c:3915 msgid "E735: Can only compare Dictionary with Dictionary" msgstr "E735: Eblas nur kompari Vortaron kun Vortaro" -#: ../eval.c:3917 msgid "E736: Invalid operation for Dictionary" msgstr "E736: Nevalida operacio de Vortaro" -#: ../eval.c:3932 -msgid "E693: Can only compare Funcref with Funcref" -msgstr "E693: Eblas nur kompari Funcref kun Funcref" - -#: ../eval.c:3934 msgid "E694: Invalid operation for Funcrefs" msgstr "E694: Nevalida operacio de Funcref-oj" -#: ../eval.c:4277 msgid "E804: Cannot use '%' with Float" msgstr "E804: Ne eblas uzi '%' kun Glitpunktnombro" -#: ../eval.c:4478 msgid "E110: Missing ')'" msgstr "E110: Mankas ')'" -#: ../eval.c:4609 msgid "E695: Cannot index a Funcref" msgstr "E695: Ne eblas indeksi Funcref" msgid "E909: Cannot index a special variable" msgstr "E909: Ne eblas indeksi specialan variablon" -#: ../eval.c:4839 #, c-format msgid "E112: Option name missing: %s" msgstr "E112: Mankas nomo de opcio: %s" -#: ../eval.c:4855 #, c-format msgid "E113: Unknown option: %s" msgstr "E113: Nekonata opcio: %s" -#: ../eval.c:4904 #, c-format msgid "E114: Missing quote: %s" msgstr "E114: Mankas citilo: %s" -#: ../eval.c:5020 #, c-format msgid "E115: Missing quote: %s" msgstr "E115: Mankas citilo: %s" -#: ../eval.c:5084 -#, c-format -msgid "E696: Missing comma in List: %s" -msgstr "E696: Mankas komo en Listo: %s" - -#: ../eval.c:5091 -#, c-format -msgid "E697: Missing end of List ']': %s" -msgstr "E697: Mankas fino de Listo ']': %s" - -#: ../eval.c:5750 msgid "Not enough memory to set references, garbage collection aborted!" msgstr "Ne sufiĉa memoro por valorigi referencojn, senrubigado ĉesigita!" -#: ../eval.c:6475 -#, c-format -msgid "E720: Missing colon in Dictionary: %s" -msgstr "E720: Mankas dupunkto en la vortaro: %s" - -#: ../eval.c:6499 -#, c-format -msgid "E721: Duplicate key in Dictionary: \"%s\"" -msgstr "E721: Ripetita Ålosilo en la vortaro: \"%s\"" - -#: ../eval.c:6517 -#, c-format -msgid "E722: Missing comma in Dictionary: %s" -msgstr "E722: Mankas komo en la vortaro: %s" - -#: ../eval.c:6524 -#, c-format -msgid "E723: Missing end of Dictionary '}': %s" -msgstr "E723: Mankas fino de vortaro '}': %s" - -#: ../eval.c:6555 msgid "E724: variable nested too deep for displaying" msgstr "E724: variablo ingita tro profunde por vidigi" -#: ../eval.c:7188 -#, c-format -msgid "E740: Too many arguments for function %s" -msgstr "E740: Tro da argumentoj por funkcio: %s" - -#: ../eval.c:7190 -#, c-format -msgid "E116: Invalid arguments for function %s" -msgstr "E116: Nevalidaj argumentoj por funkcio: %s" - -#: ../eval.c:7377 -#, c-format -msgid "E117: Unknown function: %s" -msgstr "E117: Nekonata funkcio: %s" - -#: ../eval.c:7383 -#, c-format -msgid "E119: Not enough arguments for function: %s" -msgstr "E119: Ne sufiĉe da argumentoj por funkcio: %s" - -#: ../eval.c:7387 -#, c-format -msgid "E120: Using <SID> not in a script context: %s" -msgstr "E120: <SID> estas uzata ekster kunteksto de skripto: %s" - -#: ../eval.c:7391 -#, c-format -msgid "E725: Calling dict function without Dictionary: %s" -msgstr "E725: Alvoko de funkcio dict sen Vortaro: %s" - -#: ../eval.c:7453 -msgid "E808: Number or Float required" -msgstr "E808: Nombro aÅ Glitpunktnombro bezonata" - -#: ../eval.c:7503 -msgid "add() argument" -msgstr "argumento de add()" - -#: ../eval.c:7907 -msgid "E699: Too many arguments" -msgstr "E699: Tro da argumentoj" - -#: ../eval.c:8073 -msgid "E785: complete() can only be used in Insert mode" -msgstr "E785: complete() uzeblas nur en Enmeta reÄimo" - -#: ../eval.c:8156 -msgid "&Ok" -msgstr "&Bone" - -#: ../eval.c:8676 -#, c-format -msgid "E737: Key already exists: %s" -msgstr "E737: Åœlosilo jam ekzistas: %s" - -#: ../eval.c:8692 -msgid "extend() argument" -msgstr "argumento de extend()" - -#: ../eval.c:8915 -msgid "map() argument" -msgstr "argumento de map()" - -#: ../eval.c:8916 -msgid "filter() argument" -msgstr "argumento de filter()" - -#: ../eval.c:9229 -#, c-format -msgid "+-%s%3ld lines: " -msgstr "+-%s%3ld linioj: " - -#: ../eval.c:9291 -#, c-format -msgid "E700: Unknown function: %s" -msgstr "E700: Nekonata funkcio: %s" - -#: ../eval.c:10729 -msgid "called inputrestore() more often than inputsave()" -msgstr "alvokis inputrestore() pli ofte ol inputsave()" - -#: ../eval.c:10771 -msgid "insert() argument" -msgstr "argumento de insert()" - -#: ../eval.c:10841 -msgid "E786: Range not allowed" -msgstr "E786: Amplekso nepermesebla" - -#: ../eval.c:11140 -msgid "E701: Invalid type for len()" -msgstr "E701: Nevalida datumtipo de len()" - -#: ../eval.c:11980 -msgid "E726: Stride is zero" -msgstr "E726: PaÅo estas nul" - -#: ../eval.c:11982 -msgid "E727: Start past end" -msgstr "E727: Komenco preter fino" - -#: ../eval.c:12024 ../eval.c:15297 -msgid "<empty>" -msgstr "<malplena>" - -#: ../eval.c:12282 -msgid "remove() argument" -msgstr "argumento de remove()" - -#: ../eval.c:12466 -msgid "E655: Too many symbolic links (cycle?)" -msgstr "E655: Tro da simbolaj ligiloj (ĉu estas ciklo?)" - -#: ../eval.c:12593 -msgid "reverse() argument" -msgstr "argumento de reverse()" - -#: ../eval.c:13721 -msgid "sort() argument" -msgstr "argumento de sort()" - -#: ../eval.c:13721 -#, fuzzy -msgid "uniq() argument" -msgstr "argumento de add()" - -#: ../eval.c:13776 -msgid "E702: Sort compare function failed" -msgstr "E702: Ordiga funkcio fiaskis" - -#: ../eval.c:13806 -#, fuzzy -msgid "E882: Uniq compare function failed" -msgstr "E702: Ordiga funkcio fiaskis" - -#: ../eval.c:14085 -msgid "(Invalid)" -msgstr "(Nevalida)" - -#: ../eval.c:14590 -msgid "E677: Error writing temp file" -msgstr "E677: Eraro dum skribo de provizora dosiero" - -#: ../eval.c:16159 msgid "E805: Using a Float as a Number" msgstr "E805: Uzo de Glitpunktnombro kiel Nombro" -#: ../eval.c:16162 msgid "E703: Using a Funcref as a Number" msgstr "E703: Uzo de Funcref kiel Nombro" -#: ../eval.c:16170 msgid "E745: Using a List as a Number" msgstr "E745: Uzo de Listo kiel Nombro" -#: ../eval.c:16173 msgid "E728: Using a Dictionary as a Number" msgstr "E728: Uzo de Vortaro kiel Nombro" +msgid "E910: Using a Job as a Number" +msgstr "E910: Uzo de Tasko kiel Nombro" + +msgid "E913: Using a Channel as a Number" +msgstr "E913: Uzo de Kanalo kiel Nombro" + msgid "E891: Using a Funcref as a Float" msgstr "E891: Uzo de Funcref kiel Glitpunktnombro" @@ -885,268 +614,280 @@ msgstr "E893: Uzo de Listo kiel Glitpunktnombro" msgid "E894: Using a Dictionary as a Float" msgstr "E894: Uzo de Vortaro kiel Glitpunktnombro" -#: ../eval.c:16259 +msgid "E907: Using a special value as a Float" +msgstr "E907: Uzo de speciala valoro kiel Glitpunktnombro" + +msgid "E911: Using a Job as a Float" +msgstr "E911: Uzo de Tasko kiel Glitpunktnombro" + +msgid "E914: Using a Channel as a Float" +msgstr "E914: Uzo de Kanalo kiel Glitpunktnombro" + msgid "E729: using Funcref as a String" msgstr "E729: uzo de Funcref kiel Ĉeno" -#: ../eval.c:16262 msgid "E730: using List as a String" msgstr "E730: uzo de Listo kiel Ĉeno" -#: ../eval.c:16265 msgid "E731: using Dictionary as a String" msgstr "E731: uzo de Vortaro kiel Ĉeno" msgid "E908: using an invalid value as a String" msgstr "E908: uzo de nevalida valoro kiel Ĉeno" -#: ../eval.c:16619 -#, c-format -msgid "E706: Variable type mismatch for: %s" -msgstr "E706: Nekongrua datumtipo de variablo: %s" - -#: ../eval.c:16705 #, c-format msgid "E795: Cannot delete variable %s" msgstr "E795: Ne eblas forviÅi variablon %s" -#: ../eval.c:16724 #, c-format msgid "E704: Funcref variable name must start with a capital: %s" msgstr "E704: Nomo de variablo Funcref devas finiÄi per majusklo: %s" -#: ../eval.c:16732 #, c-format msgid "E705: Variable name conflicts with existing function: %s" msgstr "E705: Nomo de variablo konfliktas kun ekzistanta funkcio: %s" -#: ../eval.c:16763 #, c-format msgid "E741: Value is locked: %s" msgstr "E741: Valoro estas Ålosita: %s" -#: ../eval.c:16764 ../eval.c:16769 ../message.c:1839 msgid "Unknown" msgstr "Nekonata" -#: ../eval.c:16768 #, c-format msgid "E742: Cannot change value of %s" msgstr "E742: Ne eblas ÅanÄi valoron de %s" -#: ../eval.c:16838 msgid "E698: variable nested too deep for making a copy" msgstr "E698: variablo ingita tro profunde por fari kopion" -#: ../eval.c:17249 -#, c-format -msgid "E123: Undefined function: %s" -msgstr "E123: Nedifinita funkcio: %s" +msgid "" +"\n" +"# global variables:\n" +msgstr "" +"\n" +"# mallokaj variabloj:\n" -#: ../eval.c:17260 -#, c-format -msgid "E124: Missing '(': %s" -msgstr "E124: Mankas '(': %s" +msgid "" +"\n" +"\tLast set from " +msgstr "" +"\n" +"\tLaste Åaltita de " -#: ../eval.c:17293 -msgid "E862: Cannot use g: here" -msgstr "E862: Ne eblas uzi g: ĉi tie" +msgid "map() argument" +msgstr "argumento de map()" -#: ../eval.c:17312 -#, c-format -msgid "E125: Illegal argument: %s" -msgstr "E125: Nevalida argumento: %s" +msgid "filter() argument" +msgstr "argumento de filter()" -#: ../eval.c:17323 #, c-format -msgid "E853: Duplicate argument name: %s" -msgstr "E853: Ripetita nomo de argumento: %s" +msgid "E686: Argument of %s must be a List" +msgstr "E686: Argumento de %s devas esti Listo" -#: ../eval.c:17416 -msgid "E126: Missing :endfunction" -msgstr "E126: Mankas \":endfunction\"" +msgid "E928: String required" +msgstr "E928: Ĉeno bezonata" -#: ../eval.c:17537 -#, c-format -msgid "E707: Function name conflicts with variable: %s" -msgstr "E707: Nomo de funkcio konfliktas kun variablo: %s" +msgid "E808: Number or Float required" +msgstr "E808: Nombro aÅ Glitpunktnombro bezonata" + +msgid "add() argument" +msgstr "argumento de add()" + +msgid "E785: complete() can only be used in Insert mode" +msgstr "E785: complete() uzeblas nur en Enmeta reÄimo" + +#. +#. * Yes this is ugly, I don't particularly like it either. But doing it +#. * this way has the compelling advantage that translations need not to +#. * be touched at all. See below what 'ok' and 'ync' are used for. +#. +msgid "&Ok" +msgstr "&Bone" -#: ../eval.c:17549 #, c-format -msgid "E127: Cannot redefine function %s: It is in use" -msgstr "E127: Ne eblas redifini funkcion %s: Estas nuntempe uzata" +msgid "+-%s%3ld line: " +msgid_plural "+-%s%3ld lines: " +msgstr[0] "+-%s%3ld linio: " +msgstr[1] "+-%s%3ld linioj: " -#: ../eval.c:17604 #, c-format -msgid "E746: Function name does not match script file name: %s" -msgstr "E746: Nomo de funkcio ne kongruas kun dosiernomo de skripto: %s" +msgid "E700: Unknown function: %s" +msgstr "E700: Nekonata funkcio: %s" -#: ../eval.c:17716 -msgid "E129: Function name required" -msgstr "E129: Nomo de funkcio bezonata" +msgid "E922: expected a dict" +msgstr "E922: vortaro atendita" -#: ../eval.c:17824 -#, fuzzy, c-format -msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "E128: Nomo de funkcio devas eki per majusklo aÅ enhavi dupunkton: %s" +msgid "E923: Second argument of function() must be a list or a dict" +msgstr "E923: Dua argumento de function() devas esti listo aÅ Vortaro" -#: ../eval.c:17833 -#, fuzzy, c-format -msgid "E884: Function name cannot contain a colon: %s" -msgstr "E128: Nomo de funkcio devas eki per majusklo aÅ enhavi dupunkton: %s" +msgid "" +"&OK\n" +"&Cancel" +msgstr "" +"&Bone\n" +"&Rezigni" -#: ../eval.c:18336 -#, c-format -msgid "E131: Cannot delete function %s: It is in use" -msgstr "E131: Ne eblas forviÅi funkcion %s: Estas nuntempe uzata" +msgid "called inputrestore() more often than inputsave()" +msgstr "alvokis inputrestore() pli ofte ol inputsave()" -#: ../eval.c:18441 -msgid "E132: Function call depth is higher than 'maxfuncdepth'" -msgstr "E132: Profundo de funkcia alvoko superas 'maxfuncdepth'" +msgid "insert() argument" +msgstr "argumento de insert()" -#: ../eval.c:18568 -#, c-format -msgid "calling %s" -msgstr "alvokas %s" +msgid "E786: Range not allowed" +msgstr "E786: Amplekso nepermesebla" -#: ../eval.c:18651 -#, c-format -msgid "%s aborted" -msgstr "%s ĉesigita" +msgid "E916: not a valid job" +msgstr "E916: nevalida tasko" + +msgid "E701: Invalid type for len()" +msgstr "E701: Nevalida datumtipo de len()" -#: ../eval.c:18653 #, c-format -msgid "%s returning #%<PRId64>" -msgstr "%s liveras #%<PRId64>" +msgid "E798: ID is reserved for \":match\": %ld" +msgstr "E798: ID estas rezervita por \":match\": %ld" + +msgid "E726: Stride is zero" +msgstr "E726: PaÅo estas nul" + +msgid "E727: Start past end" +msgstr "E727: Komenco preter fino" + +msgid "<empty>" +msgstr "<malplena>" + +msgid "E240: No connection to Vim server" +msgstr "E240: Neniu konekto al Vim-servilo" -#: ../eval.c:18670 #, c-format -msgid "%s returning %s" -msgstr "%s liveras %s" +msgid "E241: Unable to send to %s" +msgstr "E241: Ne eblas sendi al %s" + +msgid "E277: Unable to read a server reply" +msgstr "E277: Ne eblas legi respondon de servilo" + +msgid "remove() argument" +msgstr "argumento de remove()" + +msgid "E655: Too many symbolic links (cycle?)" +msgstr "E655: Tro da simbolaj ligiloj (ĉu estas ciklo?)" + +msgid "reverse() argument" +msgstr "argumento de reverse()" + +msgid "E258: Unable to send to client" +msgstr "E258: Ne eblas sendi al kliento" -#: ../eval.c:18691 ../ex_cmds2.c:2695 #, c-format -msgid "continuing in %s" -msgstr "daÅrigas en %s" +msgid "E927: Invalid action: '%s'" +msgstr "E927: Nevalida ago: '%s'" -#: ../eval.c:18795 -msgid "E133: :return not inside a function" -msgstr "E133: \":return\" ekster funkcio" +msgid "sort() argument" +msgstr "argumento de sort()" -#: ../eval.c:19159 -msgid "" -"\n" -"# global variables:\n" -msgstr "" -"\n" -"# mallokaj variabloj:\n" +msgid "uniq() argument" +msgstr "argumento de uniq()" -#: ../eval.c:19254 -msgid "" -"\n" -"\tLast set from " -msgstr "" -"\n" -"\tLaste Åaltita de " +msgid "E702: Sort compare function failed" +msgstr "E702: Ordiga funkcio malsukcesis" -#: ../eval.c:19272 -msgid "No old files" -msgstr "Neniu malnova dosiero" +msgid "E882: Uniq compare function failed" +msgstr "E882: kompara funkcio de uniq() malsukcesis" + +msgid "(Invalid)" +msgstr "(Nevalida)" + +#, c-format +msgid "E935: invalid submatch number: %d" +msgstr "E935: nevalida indekso de \"submatch\": %d" + +msgid "E677: Error writing temp file" +msgstr "E677: Eraro dum skribo de provizora dosiero" + +msgid "E921: Invalid callback argument" +msgstr "E921: Nevalida argumento de reagfunctio" -#: ../ex_cmds.c:122 #, c-format msgid "<%s>%s%s %d, Hex %02x, Octal %03o" msgstr "<%s>%s%s %d, Deksesuma %02x, Okuma %03o" -#: ../ex_cmds.c:145 #, c-format msgid "> %d, Hex %04x, Octal %o" msgstr "> %d, Deksesuma %04x, Okuma %o" -#: ../ex_cmds.c:146 #, c-format msgid "> %d, Hex %08x, Octal %o" msgstr "> %d, Deksesuma %08x, Okuma %o" -#: ../ex_cmds.c:684 msgid "E134: Move lines into themselves" msgstr "E134: Movas liniojn en ilin mem" -#: ../ex_cmds.c:747 msgid "1 line moved" msgstr "1 linio movita" -#: ../ex_cmds.c:749 #, c-format -msgid "%<PRId64> lines moved" -msgstr "%<PRId64> linioj movitaj" +msgid "%ld lines moved" +msgstr "%ld linioj movitaj" -#: ../ex_cmds.c:1175 #, c-format -msgid "%<PRId64> lines filtered" -msgstr "%<PRId64> linioj filtritaj" +msgid "%ld lines filtered" +msgstr "%ld linioj filtritaj" -#: ../ex_cmds.c:1194 msgid "E135: *Filter* Autocommands must not change current buffer" msgstr "E135: *Filtraj* AÅtokomandoj ne rajtas ÅanÄi aktualan bufron" -#: ../ex_cmds.c:1244 msgid "[No write since last change]\n" msgstr "[Neniu skribo de post lasta ÅanÄo]\n" -#: ../ex_cmds.c:1424 #, c-format msgid "%sviminfo: %s in line: " msgstr "%sviminfo: %s en linio: " -#: ../ex_cmds.c:1431 msgid "E136: viminfo: Too many errors, skipping rest of file" msgstr "E136: viminfo: Tro da eraroj, nun ignoras la reston de la dosiero" -#: ../ex_cmds.c:1458 #, c-format msgid "Reading viminfo file \"%s\"%s%s%s" msgstr "Legado de dosiero viminfo \"%s\"%s%s%s" -#: ../ex_cmds.c:1460 msgid " info" msgstr " informo" -#: ../ex_cmds.c:1461 msgid " marks" msgstr " markoj" -#: ../ex_cmds.c:1462 msgid " oldfiles" msgstr " malnovaj dosieroj" -#: ../ex_cmds.c:1463 msgid " FAILED" -msgstr " FIASKIS" +msgstr " MALSUKCESIS" #. avoid a wait_return for this message, it's annoying -#: ../ex_cmds.c:1541 #, c-format msgid "E137: Viminfo file is not writable: %s" msgstr "E137: Dosiero viminfo ne skribeblas: %s" -#: ../ex_cmds.c:1626 +#, c-format +msgid "E929: Too many viminfo temp files, like %s!" +msgstr "E929: Tro da provizoraj dosieroj viminfo, kiel %s!" + #, c-format msgid "E138: Can't write viminfo file %s!" msgstr "E138: Ne eblas skribi dosieron viminfo %s!" -#: ../ex_cmds.c:1635 #, c-format msgid "Writing viminfo file \"%s\"" msgstr "Skribas dosieron viminfo \"%s\"" +#, c-format +msgid "E886: Can't rename viminfo file to %s!" +msgstr "E886: Ne eblas renomi dosieron viminfo al %s!" + #. Write the info: -#: ../ex_cmds.c:1720 #, c-format msgid "# This viminfo file was generated by Vim %s.\n" msgstr "# Tiu dosiero viminfo estis kreita de Vim %s.\n" -#: ../ex_cmds.c:1722 msgid "" "# You may edit it if you're careful!\n" "\n" @@ -1154,47 +895,47 @@ msgstr "" "# Vi povas redakti Äin se vi estas singarda.\n" "\n" -#: ../ex_cmds.c:1723 msgid "# Value of 'encoding' when this file was written\n" msgstr "# Valoro de 'encoding' kiam tiu dosiero estis kreita\n" -#: ../ex_cmds.c:1800 msgid "Illegal starting char" msgstr "Nevalida eka signo" -#: ../ex_cmds.c:2162 +msgid "" +"\n" +"# Bar lines, copied verbatim:\n" +msgstr "" +"\n" +"# Linioj komencantaj per |, kopiitaj sen ÅanÄo:\n" + +msgid "Save As" +msgstr "Konservi kiel" + msgid "Write partial file?" msgstr "Ĉu skribi partan dosieron?" -#: ../ex_cmds.c:2166 msgid "E140: Use ! to write partial buffer" msgstr "E140: Uzu ! por skribi partan bufron" -#: ../ex_cmds.c:2281 #, c-format msgid "Overwrite existing file \"%s\"?" msgstr "Ĉu anstataÅigi ekzistantan dosieron \"%s\"?" -#: ../ex_cmds.c:2317 #, c-format msgid "Swap file \"%s\" exists, overwrite anyway?" msgstr "Permutodosiero .swp \"%s\" ekzistas, ĉu tamen anstataÅigi Äin?" -#: ../ex_cmds.c:2326 #, c-format msgid "E768: Swap file exists: %s (:silent! overrides)" msgstr "E768: Permutodosiero .swp ekzistas: %s (:silent! por transpasi)" -#: ../ex_cmds.c:2381 #, c-format -msgid "E141: No file name for buffer %<PRId64>" -msgstr "E141: Neniu dosiernomo de bufro %<PRId64>" +msgid "E141: No file name for buffer %ld" +msgstr "E141: Neniu dosiernomo de bufro %ld" -#: ../ex_cmds.c:2412 msgid "E142: File not written: Writing is disabled by 'write' option" msgstr "E142: Dosiero ne skribita: Skribo malÅaltita per la opcio 'write'" -#: ../ex_cmds.c:2434 #, c-format msgid "" "'readonly' option is set for \"%s\".\n" @@ -1203,7 +944,6 @@ msgstr "" "La opcio 'readonly' estas Åaltita por \"%s\".\n" "Ĉu vi tamen volas skribi?" -#: ../ex_cmds.c:2439 #, c-format msgid "" "File permissions of \"%s\" are read-only.\n" @@ -1214,84 +954,69 @@ msgstr "" "BonÅance Äi eble skribeblus.\n" "Ĉu vi volas provi?" -#: ../ex_cmds.c:2451 #, c-format msgid "E505: \"%s\" is read-only (add ! to override)" msgstr "E505: \"%s\" estas nurlegebla (aldonu ! por transpasi)" -#: ../ex_cmds.c:3120 +msgid "Edit File" +msgstr "Redakti dosieron" + #, c-format msgid "E143: Autocommands unexpectedly deleted new buffer %s" msgstr "E143: AÅtokomandoj neatendite forviÅis novan bufron %s" -#: ../ex_cmds.c:3313 msgid "E144: non-numeric argument to :z" msgstr "E144: nenumera argumento de :z" -#: ../ex_cmds.c:3404 msgid "E145: Shell commands not allowed in rvim" msgstr "E145: Åœelkomandoj nepermeseblaj en rvim" -#: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Ne eblas limigi regulesprimon per literoj" -#: ../ex_cmds.c:3964 #, c-format msgid "replace with %s (y/n/a/q/l/^E/^Y)?" msgstr "ĉu anstataÅigi per %s (y/n/a/q/l/^E/^Y)?" -#: ../ex_cmds.c:4379 msgid "(Interrupted) " msgstr "(Interrompita) " -#: ../ex_cmds.c:4384 msgid "1 match" msgstr "1 kongruo" -#: ../ex_cmds.c:4384 msgid "1 substitution" msgstr "1 anstataÅigo" -#: ../ex_cmds.c:4387 #, c-format -msgid "%<PRId64> matches" -msgstr "%<PRId64> kongruoj" +msgid "%ld matches" +msgstr "%ld kongruoj" -#: ../ex_cmds.c:4388 #, c-format -msgid "%<PRId64> substitutions" -msgstr "%<PRId64> anstataÅigoj" +msgid "%ld substitutions" +msgstr "%ld anstataÅigoj" -#: ../ex_cmds.c:4392 msgid " on 1 line" msgstr " en 1 linio" -#: ../ex_cmds.c:4395 #, c-format -msgid " on %<PRId64> lines" -msgstr " en %<PRId64> linioj" +msgid " on %ld lines" +msgstr " en %ld linioj" -#: ../ex_cmds.c:4438 msgid "E147: Cannot do :global recursive" msgstr "E147: Ne eblas fari \":global\" rekursie" # DP: global estas por ":global" do mi ne tradukis Äin -#: ../ex_cmds.c:4467 msgid "E148: Regular expression missing from global" msgstr "E148: Regulesprimo mankas el global" -#: ../ex_cmds.c:4508 #, c-format msgid "Pattern found in every line: %s" msgstr "Åœablono trovita en ĉiuj linioj: %s" -#: ../ex_cmds.c:4510 #, c-format msgid "Pattern not found: %s" msgstr "Åœablono ne trovita: %s" -#: ../ex_cmds.c:4587 msgid "" "\n" "# Last Substitute String:\n" @@ -1302,104 +1027,100 @@ msgstr "" "$" # This message should *so* be E42! -#: ../ex_cmds.c:4679 msgid "E478: Don't panic!" msgstr "E478: Ne paniku!" -#: ../ex_cmds.c:4717 #, c-format msgid "E661: Sorry, no '%s' help for %s" msgstr "E661: BedaÅrinde estas neniu helpo '%s' por %s" -#: ../ex_cmds.c:4719 #, c-format msgid "E149: Sorry, no help for %s" msgstr "E149: BedaÅrinde estas neniu helpo por %s" -#: ../ex_cmds.c:4751 #, c-format msgid "Sorry, help file \"%s\" not found" msgstr "BedaÅrinde, la helpdosiero \"%s\" ne troveblas" -#: ../ex_cmds.c:5323 #, c-format -msgid "E150: Not a directory: %s" -msgstr "E150: Ne estas dosierujo: %s" +msgid "E151: No match: %s" +msgstr "E151: Neniu kongruo: %s" -#: ../ex_cmds.c:5446 #, c-format msgid "E152: Cannot open %s for writing" msgstr "E152: Ne eblas malfermi %s en skribreÄimo" -#: ../ex_cmds.c:5471 #, c-format msgid "E153: Unable to open %s for reading" msgstr "E153: Ne eblas malfermi %s en legreÄimo" -#: ../ex_cmds.c:5500 #, c-format msgid "E670: Mix of help file encodings within a language: %s" msgstr "E670: Miksaĵo de kodoprezento de helpa dosiero en lingvo: %s" -#: ../ex_cmds.c:5565 #, c-format msgid "E154: Duplicate tag \"%s\" in file %s/%s" msgstr "E154: Ripetita etikedo \"%s\" en dosiero %s/%s" #, c-format +msgid "E150: Not a directory: %s" +msgstr "E150: Ne estas dosierujo: %s" + +#, c-format msgid "E160: Unknown sign command: %s" msgstr "E160: Nekonata simbola komando: %s" -#: ../ex_cmds.c:5704 msgid "E156: Missing sign name" msgstr "E156: Mankas nomo de simbolo" -#: ../ex_cmds.c:5746 msgid "E612: Too many signs defined" msgstr "E612: Tro da simboloj estas difinitaj" -#: ../ex_cmds.c:5813 #, c-format msgid "E239: Invalid sign text: %s" msgstr "E239: Nevalida teksto de simbolo: %s" -#: ../ex_cmds.c:5844 ../ex_cmds.c:6035 #, c-format msgid "E155: Unknown sign: %s" msgstr "E155: Nekonata simbolo: %s" -#: ../ex_cmds.c:5877 msgid "E159: Missing sign number" msgstr "E159: Mankas numero de simbolo" -#: ../ex_cmds.c:5971 #, c-format msgid "E158: Invalid buffer name: %s" msgstr "E158: Nevalida nomo de bufro: %s" -#: ../ex_cmds.c:6008 +msgid "E934: Cannot jump to a buffer that does not have a name" +msgstr "E934: Ne eblas salti al sennoma bufro" + +#, c-format +msgid "E157: Invalid sign ID: %ld" +msgstr "E157: Nevalida identigilo de simbolo: %ld" + #, c-format -msgid "E157: Invalid sign ID: %<PRId64>" -msgstr "E157: Nevalida identigilo de simbolo: %<PRId64>" +msgid "E885: Not possible to change sign %s" +msgstr "E885: Ne eblas ÅanÄi simbolon %s" + +msgid " (NOT FOUND)" +msgstr " (NETROVITA)" -#: ../ex_cmds.c:6066 msgid " (not supported)" msgstr " (nesubtenata)" -#: ../ex_cmds.c:6169 msgid "[Deleted]" msgstr "[ForviÅita]" -#: ../ex_cmds2.c:139 +msgid "No old files" +msgstr "Neniu malnova dosiero" + msgid "Entering Debug mode. Type \"cont\" to continue." msgstr "Eniras sencimigan reÄimon. Tajpu \"cont\" por daÅrigi." -#: ../ex_cmds2.c:143 ../ex_docmd.c:759 #, c-format -msgid "line %<PRId64>: %s" -msgstr "linio %<PRId64>: %s" +msgid "line %ld: %s" +msgstr "linio %ld: %s" -#: ../ex_cmds2.c:145 #, c-format msgid "cmd: %s" msgstr "kmd: %s" @@ -1411,231 +1132,183 @@ msgstr "kadro estas nul" msgid "frame at highest level: %d" msgstr "kadro je la plej alta nivelo: %d" -#: ../ex_cmds2.c:322 #, c-format -msgid "Breakpoint in \"%s%s\" line %<PRId64>" -msgstr "Kontrolpunkto en \"%s%s\" linio %<PRId64>" +msgid "Breakpoint in \"%s%s\" line %ld" +msgstr "Kontrolpunkto en \"%s%s\" linio %ld" -#: ../ex_cmds2.c:581 #, c-format msgid "E161: Breakpoint not found: %s" msgstr "E161: Kontrolpunkto ne trovita: %s" -#: ../ex_cmds2.c:611 msgid "No breakpoints defined" msgstr "Neniu kontrolpunkto estas difinita" -#: ../ex_cmds2.c:617 #, c-format -msgid "%3d %s %s line %<PRId64>" -msgstr "%3d %s %s linio %<PRId64>" +msgid "%3d %s %s line %ld" +msgstr "%3d %s %s linio %ld" -#: ../ex_cmds2.c:942 msgid "E750: First use \":profile start {fname}\"" msgstr "E750: Uzu unue \":profile start {dosiernomo}\"" -#: ../ex_cmds2.c:1269 #, c-format msgid "Save changes to \"%s\"?" msgstr "Ĉu konservi ÅanÄojn al \"%s\"?" -#: ../ex_cmds2.c:1271 ../ex_docmd.c:8851 msgid "Untitled" msgstr "Sen titolo" -#: ../ex_cmds2.c:1421 #, c-format msgid "E162: No write since last change for buffer \"%s\"" msgstr "E162: Neniu skribo de post la lasta ÅanÄo por bufro \"%s\"" -#: ../ex_cmds2.c:1480 msgid "Warning: Entered other buffer unexpectedly (check autocommands)" msgstr "Averto: Eniris neatendite alian bufron (kontrolu aÅtokomandojn)" -#: ../ex_cmds2.c:1826 msgid "E163: There is only one file to edit" msgstr "E163: Estas nur unu redaktenda dosiero" -#: ../ex_cmds2.c:1828 msgid "E164: Cannot go before first file" msgstr "E164: Ne eblas iri antaÅ ol la unuan dosieron" -#: ../ex_cmds2.c:1830 msgid "E165: Cannot go beyond last file" msgstr "E165: Ne eblas iri preter la lastan dosieron" -#: ../ex_cmds2.c:2175 #, c-format msgid "E666: compiler not supported: %s" msgstr "E666: kompililo nesubtenata: %s" -#: ../ex_cmds2.c:2257 #, c-format msgid "Searching for \"%s\" in \"%s\"" msgstr "Serĉado de \"%s\" en \"%s\"" -#: ../ex_cmds2.c:2284 #, c-format msgid "Searching for \"%s\"" msgstr "Serĉado de \"%s\"" -#: ../ex_cmds2.c:2307 #, c-format msgid "not found in '%s': \"%s\"" msgstr "ne trovita en '%s: \"%s\"" -#: ../ex_cmds2.c:2472 +msgid "Source Vim script" +msgstr "Ruli Vim-skripton" + #, c-format msgid "Cannot source a directory: \"%s\"" msgstr "Ne eblas ruli dosierujon: \"%s\"" -#: ../ex_cmds2.c:2518 #, c-format msgid "could not source \"%s\"" msgstr "ne eblis ruli \"%s\"" -#: ../ex_cmds2.c:2520 #, c-format -msgid "line %<PRId64>: could not source \"%s\"" -msgstr "linio %<PRId64>: ne eblis ruli \"%s\"" +msgid "line %ld: could not source \"%s\"" +msgstr "linio %ld: ne eblis ruli \"%s\"" -#: ../ex_cmds2.c:2535 #, c-format msgid "sourcing \"%s\"" msgstr "rulas \"%s\"" -#: ../ex_cmds2.c:2537 #, c-format -msgid "line %<PRId64>: sourcing \"%s\"" -msgstr "linio %<PRId64>: rulas \"%s\"" +msgid "line %ld: sourcing \"%s\"" +msgstr "linio %ld: rulas \"%s\"" -#: ../ex_cmds2.c:2693 #, c-format msgid "finished sourcing %s" msgstr "finis ruli %s" -#: ../ex_cmds2.c:2765 +#, c-format +msgid "continuing in %s" +msgstr "daÅrigas en %s" + msgid "modeline" msgstr "reÄimlinio" -#: ../ex_cmds2.c:2767 msgid "--cmd argument" msgstr "--cmd argumento" -#: ../ex_cmds2.c:2769 msgid "-c argument" msgstr "-c argumento" -#: ../ex_cmds2.c:2771 msgid "environment variable" msgstr "medivariablo" -#: ../ex_cmds2.c:2773 msgid "error handler" msgstr "erartraktilo" -#: ../ex_cmds2.c:3020 msgid "W15: Warning: Wrong line separator, ^M may be missing" msgstr "W15: Averto: NeÄusta disigilo de linio, ^M eble mankas" -#: ../ex_cmds2.c:3139 msgid "E167: :scriptencoding used outside of a sourced file" msgstr "E167: \":scriptencoding\" uzita ekster rulita dosiero" -#: ../ex_cmds2.c:3166 msgid "E168: :finish used outside of a sourced file" msgstr "E168: \":finish\" uzita ekster rulita dosiero" -#: ../ex_cmds2.c:3389 #, c-format msgid "Current %slanguage: \"%s\"" msgstr "Aktuala %slingvo: \"%s\"" -#: ../ex_cmds2.c:3404 #, c-format msgid "E197: Cannot set language to \"%s\"" msgstr "E197: Ne eblas ÅanÄi la lingvon al \"%s\"" -#. don't redisplay the window -#. don't wait for return -#: ../ex_docmd.c:387 msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." msgstr "Eniras reÄimon Ex. Tajpu \"visual\" por iri al reÄimo Normala." -#: ../ex_docmd.c:428 msgid "E501: At end-of-file" msgstr "E501: Ĉe fino-de-dosiero" -#: ../ex_docmd.c:513 msgid "E169: Command too recursive" msgstr "E169: Komando tro rekursia" -#: ../ex_docmd.c:1006 #, c-format msgid "E605: Exception not caught: %s" msgstr "E605: Escepto nekaptita: %s" -#: ../ex_docmd.c:1085 msgid "End of sourced file" msgstr "Fino de rulita dosiero" -#: ../ex_docmd.c:1086 msgid "End of function" msgstr "Fino de funkcio" -#: ../ex_docmd.c:1628 msgid "E464: Ambiguous use of user-defined command" msgstr "E464: Ambigua uzo de komando difinita de uzanto" -#: ../ex_docmd.c:1638 msgid "E492: Not an editor command" msgstr "E492: Ne estas redaktila komando" -#: ../ex_docmd.c:1729 msgid "E493: Backwards range given" msgstr "E493: Inversa amplekso donita" -#: ../ex_docmd.c:1733 msgid "Backwards range given, OK to swap" msgstr "Inversa amplekso donita, permuteblas" -#. append -#. typed wrong -#: ../ex_docmd.c:1787 msgid "E494: Use w or w>>" msgstr "E494: Uzu w aÅ w>>" -#: ../ex_docmd.c:3454 -msgid "E319: The command is not available in this version" +msgid "E319: Sorry, the command is not available in this version" msgstr "E319: BedaÅrinde, tiu komando ne haveblas en tiu versio" -#: ../ex_docmd.c:3752 msgid "E172: Only one file name allowed" msgstr "E172: Nur unu dosiernomo permesebla" -#: ../ex_docmd.c:4238 msgid "1 more file to edit. Quit anyway?" msgstr "1 plia redaktenda dosiero. Ĉu tamen eliri?" -#: ../ex_docmd.c:4242 #, c-format msgid "%d more files to edit. Quit anyway?" msgstr "%d pliaj redaktendaj dosieroj. Ĉu tamen eliri?" -#: ../ex_docmd.c:4248 msgid "E173: 1 more file to edit" msgstr "E173: 1 plia redaktenda dosiero" -#: ../ex_docmd.c:4250 #, c-format -msgid "E173: %<PRId64> more files to edit" -msgstr "E173: %<PRId64> pliaj redaktendaj dosieroj" +msgid "E173: %ld more files to edit" +msgstr "E173: %ld pliaj redaktendaj dosieroj" -#: ../ex_docmd.c:4320 msgid "E174: Command already exists: add ! to replace it" msgstr "E174: La komando jam ekzistas: aldonu ! por anstataÅigi Äin" -#: ../ex_docmd.c:4432 msgid "" "\n" " Name Args Address Complete Definition" @@ -1643,352 +1316,308 @@ msgstr "" "\n" " Nomo Argumentoj Adreso Kompleto Difino" -#: ../ex_docmd.c:4516 msgid "No user-defined commands found" msgstr "Neniu komando difinita de uzanto trovita" -#: ../ex_docmd.c:4538 msgid "E175: No attribute specified" msgstr "E175: Neniu atributo specifita" -#: ../ex_docmd.c:4583 msgid "E176: Invalid number of arguments" msgstr "E176: Nevalida nombro de argumentoj" -#: ../ex_docmd.c:4594 msgid "E177: Count cannot be specified twice" msgstr "E177: Kvantoro ne povas aperi dufoje" -#: ../ex_docmd.c:4603 msgid "E178: Invalid default value for count" msgstr "E178: Nevalida defaÅlta valoro de kvantoro" -#: ../ex_docmd.c:4625 msgid "E179: argument required for -complete" msgstr "E179: argumento bezonata por -complete" -#: ../ex_docmd.c:4933 msgid "E179: argument required for -addr" msgstr "E179: argumento bezonata por -addr" -#: ../ex_docmd.c:4635 #, c-format msgid "E181: Invalid attribute: %s" msgstr "E181: Nevalida atributo: %s" -#: ../ex_docmd.c:4678 msgid "E182: Invalid command name" msgstr "E182: Nevalida komanda nomo" -#: ../ex_docmd.c:4691 msgid "E183: User defined commands must start with an uppercase letter" msgstr "E183: Komandoj difinataj de uzanto devas eki per majusklo" -#: ../ex_docmd.c:4696 msgid "E841: Reserved name, cannot be used for user defined command" msgstr "E841: Rezervita nomo, neuzebla por komando difinita de uzanto" -#: ../ex_docmd.c:4751 #, c-format msgid "E184: No such user-defined command: %s" msgstr "E184: Neniu komando-difinita-de-uzanto kiel: %s" -#: ../ex_docmd.c:5516 #, c-format msgid "E180: Invalid address type value: %s" msgstr "E180: Nevalida valoro de tipo de adreso: %s" -#: ../ex_docmd.c:5219 #, c-format msgid "E180: Invalid complete value: %s" msgstr "E180: Nevalida valoro de kompletigo: %s" -#: ../ex_docmd.c:5225 msgid "E468: Completion argument only allowed for custom completion" msgstr "" "E468: Argumento de kompletigo nur permesebla por kompletigo difinita de " "uzanto" -#: ../ex_docmd.c:5231 msgid "E467: Custom completion requires a function argument" msgstr "E467: Uzula kompletigo bezonas funkcian argumenton" -#: ../ex_docmd.c:5257 +msgid "unknown" +msgstr "nekonata" + #, c-format msgid "E185: Cannot find color scheme '%s'" msgstr "E185: Ne eblas trovi agordaron de koloroj '%s'" -#: ../ex_docmd.c:5263 msgid "Greetings, Vim user!" msgstr "Bonvenon, uzanto de Vim!" -#: ../ex_docmd.c:5431 msgid "E784: Cannot close last tab page" msgstr "E784: Ne eblas fermi lastan langeton" -#: ../ex_docmd.c:5462 msgid "Already only one tab page" msgstr "Jam nur unu langeto" -#: ../ex_docmd.c:6004 +msgid "Edit File in new window" +msgstr "Redakti Dosieron en nova fenestro" + #, c-format msgid "Tab page %d" msgstr "Langeto %d" -#: ../ex_docmd.c:6295 msgid "No swap file" msgstr "Neniu permutodosiero .swp" -#: ../ex_docmd.c:6478 +msgid "Append File" +msgstr "Postaldoni dosieron" + msgid "E747: Cannot change directory, buffer is modified (add ! to override)" msgstr "" "E747: Ne eblas ÅanÄi dosierujon, bufro estas ÅanÄita (aldonu ! por transpasi)" -#: ../ex_docmd.c:6485 msgid "E186: No previous directory" msgstr "E186: Neniu antaÅa dosierujo" -#: ../ex_docmd.c:6530 msgid "E187: Unknown" msgstr "E187: Nekonata" -#: ../ex_docmd.c:6610 msgid "E465: :winsize requires two number arguments" msgstr "E465: \":winsize\" bezonas du numerajn argumentojn" -#: ../ex_docmd.c:6655 +#, c-format +msgid "Window position: X %d, Y %d" +msgstr "Pozicio de fenestro: X %d, Y %d" + msgid "E188: Obtaining window position not implemented for this platform" msgstr "" "E188: Akiro de pozicio de fenestro ne estas realigita por tiu platformo" -#: ../ex_docmd.c:6662 msgid "E466: :winpos requires two number arguments" msgstr "E466: \":winpos\" bezonas du numerajn argumentojn" -#: ../ex_docmd.c:7241 +msgid "E930: Cannot use :redir inside execute()" +msgstr "E930: Ne eblas uzi :redir en execute()" + +msgid "Save Redirection" +msgstr "Konservi alidirekton" + +# DP: mi ne certas pri superflugo +msgid "Save View" +msgstr "Konservi superflugon" + +msgid "Save Session" +msgstr "Konservi seancon" + +msgid "Save Setup" +msgstr "Konservi agordaron" + #, c-format msgid "E739: Cannot create directory: %s" msgstr "E739: Ne eblas krei dosierujon %s" -#: ../ex_docmd.c:7268 #, c-format msgid "E189: \"%s\" exists (add ! to override)" msgstr "E189: \"%s\" ekzistas (aldonu ! por transpasi)" -#: ../ex_docmd.c:7273 #, c-format msgid "E190: Cannot open \"%s\" for writing" msgstr "E190: Ne eblas malfermi \"%s\" por skribi" #. set mark -#: ../ex_docmd.c:7294 msgid "E191: Argument must be a letter or forward/backward quote" msgstr "E191: Argumento devas esti litero, citilo aÅ retrocitilo" -#: ../ex_docmd.c:7333 msgid "E192: Recursive use of :normal too deep" msgstr "E192: Tro profunda rekursia alvoko de \":normal\"" -#: ../ex_docmd.c:7807 +msgid "E809: #< is not available without the +eval feature" +msgstr "E809: #< ne haveblas sen la eblo +eval" + msgid "E194: No alternate file name to substitute for '#'" msgstr "E194: Neniu alterna dosiernomo por anstataÅigi al '#'" -#: ../ex_docmd.c:7841 msgid "E495: no autocommand file name to substitute for \"<afile>\"" msgstr "E495: neniu dosiernomo de aÅtokomando por anstataÅigi al \"<afile>\"" -#: ../ex_docmd.c:7850 msgid "E496: no autocommand buffer number to substitute for \"<abuf>\"" msgstr "" "E496: neniu numero de bufro de aÅtokomando por anstataÅigi al \"<abuf>\"" # DP: ĉu match estas verbo aÅ nomo en la angla version? # AM: ĉi tie, nomo, Åajnas al mi -#: ../ex_docmd.c:7861 msgid "E497: no autocommand match name to substitute for \"<amatch>\"" msgstr "" "E497: neniu nomo de kongruo de aÅtokomando por anstataÅigi al \"<amatch>\"" -#: ../ex_docmd.c:7870 msgid "E498: no :source file name to substitute for \"<sfile>\"" msgstr "E498: neniu dosiernomo \":source\" por anstataÅigi al \"<sfile>\"" -#: ../ex_docmd.c:7876 msgid "E842: no line number to use for \"<slnum>\"" msgstr "E842: neniu uzebla numero de linio por \"<slnum>\"" -#: ../ex_docmd.c:7903 -#, fuzzy, c-format +#, no-c-format msgid "E499: Empty file name for '%' or '#', only works with \":p:h\"" msgstr "E499: Malplena dosiernomo por '%' aÅ '#', nur funkcias kun \":p:h\"" -#: ../ex_docmd.c:7905 msgid "E500: Evaluates to an empty string" msgstr "E500: Liveras malplenan ĉenon" -#: ../ex_docmd.c:8838 msgid "E195: Cannot open viminfo file for reading" msgstr "E195: Ne eblas malfermi dosieron viminfo en lega reÄimo" -#: ../ex_eval.c:464 +msgid "E196: No digraphs in this version" +msgstr "E196: Neniu duliteraĵo en tiu versio" + msgid "E608: Cannot :throw exceptions with 'Vim' prefix" msgstr "E608: Ne eblas lanĉi (:throw) escepton kun prefikso 'Vim'" #. always scroll up, don't overwrite -#: ../ex_eval.c:496 #, c-format msgid "Exception thrown: %s" msgstr "Escepto lanĉita: %s" -#: ../ex_eval.c:545 #, c-format msgid "Exception finished: %s" msgstr "Escepto finiÄis: %s" -#: ../ex_eval.c:546 #, c-format msgid "Exception discarded: %s" msgstr "Escepto ne konservita: %s" -#: ../ex_eval.c:588 ../ex_eval.c:634 #, c-format -msgid "%s, line %<PRId64>" -msgstr "%s, linio %<PRId64>" +msgid "%s, line %ld" +msgstr "%s, linio %ld" #. always scroll up, don't overwrite -#: ../ex_eval.c:608 #, c-format msgid "Exception caught: %s" msgstr "Kaptis escepton: %s" -#: ../ex_eval.c:676 #, c-format msgid "%s made pending" msgstr "%s iÄis atendanta(j)" -#: ../ex_eval.c:679 #, c-format msgid "%s resumed" msgstr "%s daÅrigita(j)" -#: ../ex_eval.c:683 #, c-format msgid "%s discarded" msgstr "%s ne konservita(j)" -#: ../ex_eval.c:708 msgid "Exception" msgstr "Escepto" -#: ../ex_eval.c:713 msgid "Error and interrupt" msgstr "Eraro kaj interrompo" -#: ../ex_eval.c:715 msgid "Error" msgstr "Eraro" #. if (pending & CSTP_INTERRUPT) -#: ../ex_eval.c:717 msgid "Interrupt" msgstr "Interrompo" -#: ../ex_eval.c:795 msgid "E579: :if nesting too deep" msgstr "E579: \":if\" tro profunde ingita" -#: ../ex_eval.c:830 msgid "E580: :endif without :if" msgstr "E580: \":endif\" sen \":if\"" -#: ../ex_eval.c:873 msgid "E581: :else without :if" msgstr "E581: \":else\" sen \":if\"" -#: ../ex_eval.c:876 msgid "E582: :elseif without :if" msgstr "E582: \":elseif\" sen \":if\"" -#: ../ex_eval.c:880 msgid "E583: multiple :else" msgstr "E583: pluraj \":else\"" -#: ../ex_eval.c:883 msgid "E584: :elseif after :else" msgstr "E584: \":elseif\" post \":else\"" -#: ../ex_eval.c:941 msgid "E585: :while/:for nesting too deep" msgstr "E585: \":while/:for\" ingita tro profunde" -#: ../ex_eval.c:1028 msgid "E586: :continue without :while or :for" msgstr "E586: \":continue\" sen \":while\" aÅ \":for\"" -#: ../ex_eval.c:1061 msgid "E587: :break without :while or :for" msgstr "E587: \":break\" sen \":while\" aÅ \":for\"" -#: ../ex_eval.c:1102 msgid "E732: Using :endfor with :while" msgstr "E732: Uzo de \":endfor\" kun \":while\"" -#: ../ex_eval.c:1104 msgid "E733: Using :endwhile with :for" msgstr "E733: Uzo de \":endwhile\" kun \":for\"" -#: ../ex_eval.c:1247 msgid "E601: :try nesting too deep" msgstr "E601: \":try\" ingita tro profunde" -#: ../ex_eval.c:1317 msgid "E603: :catch without :try" msgstr "E603: \":catch\" sen \":try\"" #. Give up for a ":catch" after ":finally" and ignore it. #. * Just parse. -#: ../ex_eval.c:1332 msgid "E604: :catch after :finally" msgstr "E604: \":catch\" post \":finally\"" -#: ../ex_eval.c:1451 msgid "E606: :finally without :try" msgstr "E606: \":finally\" sen \":try\"" #. Give up for a multiple ":finally" and ignore it. -#: ../ex_eval.c:1467 msgid "E607: multiple :finally" msgstr "E607: pluraj \":finally\"" -#: ../ex_eval.c:1571 msgid "E602: :endtry without :try" msgstr "E602: \":endtry\" sen \":try\"" -#: ../ex_eval.c:2026 msgid "E193: :endfunction not inside a function" msgstr "E193: \":endfunction\" ekster funkcio" -#: ../ex_getln.c:1643 msgid "E788: Not allowed to edit another buffer now" msgstr "E788: Ne eblas redakti alian bufron nun" -#: ../ex_getln.c:1656 msgid "E811: Not allowed to change buffer information now" msgstr "E811: Ne eblas ÅanÄi informon de bufro nun" -#: ../ex_getln.c:3178 msgid "tagname" msgstr "nomo de etikedo" -#: ../ex_getln.c:3181 msgid " kind file\n" msgstr " tipo de dosiero\n" -#: ../ex_getln.c:4799 msgid "'history' option is zero" msgstr "opcio 'history' estas nul" -#: ../ex_getln.c:5046 #, c-format msgid "" "\n" @@ -1997,303 +1626,224 @@ msgstr "" "\n" "# Historio %s (de plej nova al plej malnova):\n" -#: ../ex_getln.c:5047 msgid "Command Line" msgstr "Komanda linio" -#: ../ex_getln.c:5048 msgid "Search String" msgstr "Serĉa ĉeno" -#: ../ex_getln.c:5049 msgid "Expression" msgstr "Esprimo" -#: ../ex_getln.c:5050 msgid "Input Line" msgstr "Eniga linio" -#: ../ex_getln.c:5117 +msgid "Debug Line" +msgstr "Sencimiga linio" + msgid "E198: cmd_pchar beyond the command length" msgstr "E198: cmd_pchar preter la longo de komando" -#: ../ex_getln.c:5279 msgid "E199: Active window or buffer deleted" msgstr "E199: Aktiva fenestro aÅ bufro forviÅita" -#: ../file_search.c:203 -msgid "E854: path too long for completion" -msgstr "E854: tro longa vojo por kompletigo" - -#: ../file_search.c:446 -#, c-format -msgid "" -"E343: Invalid path: '**[number]' must be at the end of the path or be " -"followed by '%s'." -msgstr "" -"E343: Nevalida vojo: '**[nombro]' devas esti ĉe la fino de la vojo aÅ " -"sekvita de '%s'." - -#: ../file_search.c:1505 -#, c-format -msgid "E344: Can't find directory \"%s\" in cdpath" -msgstr "E344: Ne eblas trovi dosierujon \"%s\" en cdpath" - -#: ../file_search.c:1508 -#, c-format -msgid "E345: Can't find file \"%s\" in path" -msgstr "E345: Ne eblas trovi dosieron \"%s\" en serĉvojo" - -#: ../file_search.c:1512 -#, c-format -msgid "E346: No more directory \"%s\" found in cdpath" -msgstr "E346: Ne plu trovis dosierujon \"%s\" en cdpath" - -#: ../file_search.c:1515 -#, c-format -msgid "E347: No more file \"%s\" found in path" -msgstr "E347: Ne plu trovis dosieron \"%s\" en serĉvojo" - -#: ../fileio.c:137 msgid "E812: Autocommands changed buffer or buffer name" msgstr "E812: AÅtokomandoj ÅanÄis bufron aÅ nomon de bufro" -#: ../fileio.c:368 msgid "Illegal file name" msgstr "Nevalida dosiernomo" -#: ../fileio.c:395 ../fileio.c:476 ../fileio.c:2543 ../fileio.c:2578 msgid "is a directory" msgstr "estas dosierujo" -#: ../fileio.c:397 msgid "is not a file" msgstr "ne estas dosiero" -#: ../fileio.c:508 ../fileio.c:3522 +msgid "is a device (disabled with 'opendevice' option)" +msgstr "estas aparatdosiero (malÅaltita per la opcio 'opendevice')" + msgid "[New File]" msgstr "[Nova dosiero]" -#: ../fileio.c:511 msgid "[New DIRECTORY]" msgstr "[Nova DOSIERUJO]" -#: ../fileio.c:529 ../fileio.c:532 msgid "[File too big]" msgstr "[Dosiero tro granda]" -#: ../fileio.c:534 msgid "[Permission Denied]" msgstr "[Permeso rifuzita]" -#: ../fileio.c:653 msgid "E200: *ReadPre autocommands made the file unreadable" msgstr "E200: La aÅtokomandoj *ReadPre igis la dosieron nelegebla" -#: ../fileio.c:655 msgid "E201: *ReadPre autocommands must not change current buffer" msgstr "E201: La aÅtokomandoj *ReadPre ne rajtas ÅanÄi la aktualan bufron" -#: ../fileio.c:672 -msgid "Nvim: Reading from stdin...\n" +msgid "Vim: Reading from stdin...\n" msgstr "Vim: Legado el stdin...\n" +msgid "Reading from stdin..." +msgstr "Legado el stdin..." + #. Re-opening the original file failed! -#: ../fileio.c:909 msgid "E202: Conversion made file unreadable!" msgstr "E202: Konverto igis la dosieron nelegebla!" -#. fifo or socket -#: ../fileio.c:1782 msgid "[fifo/socket]" msgstr "[rektvica memoro/kontaktoskatolo]" -#. fifo -#: ../fileio.c:1788 msgid "[fifo]" msgstr "[rektvica memoro]" -#. or socket -#: ../fileio.c:1794 msgid "[socket]" msgstr "[kontaktoskatolo]" -#. or character special -#: ../fileio.c:1801 msgid "[character special]" msgstr "[speciala signo]" -#: ../fileio.c:1815 msgid "[CR missing]" msgstr "[CR mankas]" -#: ../fileio.c:1819 msgid "[long lines split]" msgstr "[divido de longaj linioj]" -#: ../fileio.c:1823 ../fileio.c:3512 msgid "[NOT converted]" msgstr "[NE konvertita]" -#: ../fileio.c:1826 ../fileio.c:3515 msgid "[converted]" msgstr "[konvertita]" -#: ../fileio.c:1831 #, c-format -msgid "[CONVERSION ERROR in line %<PRId64>]" -msgstr "[ERARO DE KONVERTO en linio %<PRId64>]" +msgid "[CONVERSION ERROR in line %ld]" +msgstr "[ERARO DE KONVERTO en linio %ld]" -#: ../fileio.c:1835 #, c-format -msgid "[ILLEGAL BYTE in line %<PRId64>]" -msgstr "[NEVALIDA BAJTO en linio %<PRId64>]" +msgid "[ILLEGAL BYTE in line %ld]" +msgstr "[NEVALIDA BAJTO en linio %ld]" -#: ../fileio.c:1838 msgid "[READ ERRORS]" msgstr "[ERAROJ DE LEGADO]" -#: ../fileio.c:2104 msgid "Can't find temp file for conversion" msgstr "Ne eblas trovi provizoran dosieron por konverti" -#: ../fileio.c:2110 msgid "Conversion with 'charconvert' failed" -msgstr "Konverto kun 'charconvert' fiaskis" +msgstr "Konverto kun 'charconvert' malsukcesis" -#: ../fileio.c:2113 msgid "can't read output of 'charconvert'" msgstr "ne eblas legi la eligon de 'charconvert'" -#: ../fileio.c:2437 msgid "E676: No matching autocommands for acwrite buffer" msgstr "E676: Neniu kongrua aÅtokomando por la bufro acwrite" -#: ../fileio.c:2466 msgid "E203: Autocommands deleted or unloaded buffer to be written" msgstr "E203: AÅtokomandoj forviÅis aÅ malÅargis la skribendan bufron" -#: ../fileio.c:2486 msgid "E204: Autocommand changed number of lines in unexpected way" msgstr "E204: AÅtokomando ÅanÄis la nombron de linioj neatendite" -#: ../fileio.c:2548 ../fileio.c:2565 +msgid "NetBeans disallows writes of unmodified buffers" +msgstr "NetBeans malpermesas skribojn de neÅanÄitaj bufroj" + +msgid "Partial writes disallowed for NetBeans buffers" +msgstr "Partaj skriboj malpermesitaj ĉe bufroj NetBeans" + msgid "is not a file or writable device" msgstr "ne estas dosiero aÅ skribebla aparatdosiero" -#: ../fileio.c:2601 +msgid "writing to device disabled with 'opendevice' option" +msgstr "skribo al aparatdosiero malÅaltita per la opcio 'opendevice'" + msgid "is read-only (add ! to override)" msgstr "estas nurlegebla (aldonu ! por transpasi)" -#: ../fileio.c:2886 msgid "E506: Can't write to backup file (add ! to override)" msgstr "E506: Ne eblas skribi restaÅrkopion (aldonu ! por transpasi)" -#: ../fileio.c:2898 msgid "E507: Close error for backup file (add ! to override)" msgstr "E507: Eraro dum fermo de restaÅrkopio (aldonu ! transpasi)" -#: ../fileio.c:2901 msgid "E508: Can't read file for backup (add ! to override)" msgstr "E508: Ne eblas legi restaÅrkopion (aldonu ! por transpasi)" -#: ../fileio.c:2923 msgid "E509: Cannot create backup file (add ! to override)" msgstr "E509: Ne eblas krei restaÅrkopion (aldonu ! por transpasi)" -#: ../fileio.c:3008 msgid "E510: Can't make backup file (add ! to override)" msgstr "E510: Ne eblas krei restaÅrkopion (aldonu ! por transpasi)" -#. Can't write without a tempfile! -#: ../fileio.c:3121 +msgid "E460: The resource fork would be lost (add ! to override)" +msgstr "E460: La rimeda forko estus perdita (aldonu ! por transpasi)" + msgid "E214: Can't find temp file for writing" msgstr "E214: Ne eblas trovi provizoran dosieron por skribi" -#: ../fileio.c:3134 msgid "E213: Cannot convert (add ! to write without conversion)" msgstr "E213: Ne eblas konverti (aldonu ! por skribi sen konverto)" -#: ../fileio.c:3169 msgid "E166: Can't open linked file for writing" msgstr "E166: Ne eblas malfermi ligitan dosieron por skribi" -#: ../fileio.c:3173 msgid "E212: Can't open file for writing" msgstr "E212: Ne eblas malfermi la dosieron por skribi" # AM: fsync: ne traduku (nomo de C-komando) -#: ../fileio.c:3363 msgid "E667: Fsync failed" -msgstr "E667: Fsync fiaskis" +msgstr "E667: Fsync malsukcesis" -#: ../fileio.c:3398 msgid "E512: Close failed" -msgstr "E512: Fermo fiaskis" +msgstr "E512: Fermo malsukcesis" -#: ../fileio.c:3436 msgid "E513: write error, conversion failed (make 'fenc' empty to override)" -msgstr "E513: skriberaro, konverto fiaskis (igu 'fenc' malplena por transpasi)" +msgstr "" +"E513: skriberaro, konverto malsukcesis (igu 'fenc' malplena por transpasi)" -#: ../fileio.c:3441 #, c-format msgid "" -"E513: write error, conversion failed in line %<PRId64> (make 'fenc' empty to " +"E513: write error, conversion failed in line %ld (make 'fenc' empty to " "override)" msgstr "" -"E513: skriberaro, konverto fiaskis en linio %<PRId64> (igu 'fenc' malplena " +"E513: skriberaro, konverto malsukcesis en linio %ld (igu 'fenc' malplena " "por transpasi)" -#: ../fileio.c:3448 msgid "E514: write error (file system full?)" msgstr "E514: skriberaro (ĉu plena dosiersistemo?)" -#: ../fileio.c:3506 msgid " CONVERSION ERROR" msgstr " ERARO DE KONVERTO" -#: ../fileio.c:3509 #, c-format -msgid " in line %<PRId64>;" -msgstr " en linio %<PRId64>;" +msgid " in line %ld;" +msgstr " en linio %ld;" -#: ../fileio.c:3519 msgid "[Device]" msgstr "[Aparatdosiero]" -#: ../fileio.c:3522 msgid "[New]" msgstr "[Nova]" -#: ../fileio.c:3535 msgid " [a]" msgstr " [a]" -#: ../fileio.c:3535 msgid " appended" msgstr " postaldonita(j)" -#: ../fileio.c:3537 msgid " [w]" msgstr " [s]" -#: ../fileio.c:3537 msgid " written" msgstr " skribita(j)" -#: ../fileio.c:3579 msgid "E205: Patchmode: can't save original file" msgstr "E205: Patchmode: ne eblas konservi originalan dosieron" -#: ../fileio.c:3602 msgid "E206: patchmode: can't touch empty original file" msgstr "E206: patchmode: ne eblas tuÅi malplenan originalan dosieron" -#: ../fileio.c:3616 msgid "E207: Can't delete backup file" msgstr "E207: Ne eblas forviÅi restaÅrkopion" -#: ../fileio.c:3672 msgid "" "\n" "WARNING: Original file may be lost or damaged\n" @@ -2301,96 +1851,75 @@ msgstr "" "\n" "AVERTO: Originala dosiero estas eble perdita aÅ difekta\n" -#: ../fileio.c:3675 msgid "don't quit the editor until the file is successfully written!" msgstr "ne eliru el la redaktilo Äis kiam la dosiero estas sukcese konservita!" -#: ../fileio.c:3795 msgid "[dos]" msgstr "[dos]" -#: ../fileio.c:3795 msgid "[dos format]" msgstr "[formato dos]" -#: ../fileio.c:3801 msgid "[mac]" msgstr "[mac]" -#: ../fileio.c:3801 msgid "[mac format]" msgstr "[formato mac]" -#: ../fileio.c:3807 msgid "[unix]" msgstr "[unikso]" -#: ../fileio.c:3807 msgid "[unix format]" msgstr "[formato unikso]" -#: ../fileio.c:3831 msgid "1 line, " msgstr "1 linio, " -#: ../fileio.c:3833 #, c-format -msgid "%<PRId64> lines, " -msgstr "%<PRId64> linioj, " +msgid "%ld lines, " +msgstr "%ld linioj, " -#: ../fileio.c:3836 msgid "1 character" msgstr "1 signo" -#: ../fileio.c:3838 #, c-format -msgid "%<PRId64> characters" -msgstr "%<PRId64> signoj" +msgid "%lld characters" +msgstr "%lld signoj" -#: ../fileio.c:3849 msgid "[noeol]" msgstr "[sen EOL]" -#: ../fileio.c:3849 msgid "[Incomplete last line]" msgstr "[Nekompleta lasta linio]" #. don't overwrite messages here #. must give this prompt #. don't use emsg() here, don't want to flush the buffers -#: ../fileio.c:3865 msgid "WARNING: The file has been changed since reading it!!!" msgstr "AVERTO: La dosiero estas ÅanÄita de post kiam Äi estis legita!!!" -#: ../fileio.c:3867 msgid "Do you really want to write to it" msgstr "Ĉu vi vere volas skribi al Äi" -#: ../fileio.c:4648 #, c-format msgid "E208: Error writing to \"%s\"" msgstr "E208: Eraro dum skribo de \"%s\"" -#: ../fileio.c:4655 #, c-format msgid "E209: Error closing \"%s\"" msgstr "E209: Eraro dum fermo de \"%s\"" -#: ../fileio.c:4657 #, c-format msgid "E210: Error reading \"%s\"" msgstr "E210: Eraro dum lego de \"%s\"" -#: ../fileio.c:4883 msgid "E246: FileChangedShell autocommand deleted buffer" msgstr "E246: AÅtokomando FileChangedShell forviÅis bufron" -#: ../fileio.c:4894 #, c-format msgid "E211: File \"%s\" no longer available" msgstr "E211: Dosiero \"%s\" ne plu haveblas" -#: ../fileio.c:4906 #, c-format msgid "" "W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as " @@ -2398,38 +1927,30 @@ msgid "" msgstr "" "W12: Averto: Dosiero \"%s\" ÅanÄiÄis kaj la bufro estis ÅanÄita ankaÅ en Vim" -#: ../fileio.c:4907 msgid "See \":help W12\" for more info." msgstr "Vidu \":help W12\" por pliaj informoj." -#: ../fileio.c:4910 #, c-format msgid "W11: Warning: File \"%s\" has changed since editing started" msgstr "W11: Averto: La dosiero \"%s\" ÅanÄiÄis ekde redakti Äin" -#: ../fileio.c:4911 msgid "See \":help W11\" for more info." msgstr "Vidu \":help W11\" por pliaj informoj." -#: ../fileio.c:4914 #, c-format msgid "W16: Warning: Mode of file \"%s\" has changed since editing started" msgstr "W16: Averto: Permeso de dosiero \"%s\" ÅanÄiÄis ekde redakti Äin" -#: ../fileio.c:4915 msgid "See \":help W16\" for more info." msgstr "Vidu \":help W16\" por pliaj informoj." -#: ../fileio.c:4927 #, c-format msgid "W13: Warning: File \"%s\" has been created after editing started" msgstr "W13: Averto: Dosiero \"%s\" kreiÄis post la komenco de redaktado" -#: ../fileio.c:4947 msgid "Warning" msgstr "Averto" -#: ../fileio.c:4948 msgid "" "&OK\n" "&Load File" @@ -2437,48 +1958,45 @@ msgstr "" "&Bone\n" "Åœ&argi Dosieron" -#: ../fileio.c:5065 #, c-format msgid "E462: Could not prepare for reloading \"%s\"" msgstr "E462: Ne eblis prepari por reÅargi \"%s\"" -#: ../fileio.c:5078 #, c-format msgid "E321: Could not reload \"%s\"" msgstr "E321: Ne eblis reÅargi \"%s\"" -#: ../fileio.c:5601 msgid "--Deleted--" msgstr "--ForviÅita--" -#: ../fileio.c:5732 #, c-format msgid "auto-removing autocommand: %s <buffer=%d>" msgstr "aÅto-forviÅas aÅtokomandon: %s <bufro=%d>" #. the group doesn't exist -#: ../fileio.c:5772 #, c-format msgid "E367: No such group: \"%s\"" msgstr "E367: Ne ekzistas tia grupo: \"%s\"" -#: ../fileio.c:5897 +msgid "E936: Cannot delete the current group" +msgstr "E936: Ne eblas forviÅi la aktualan grupon" + +msgid "W19: Deleting augroup that is still in use" +msgstr "W19: ForviÅo de augroup kiu estas ankoraÅ uzata" + #, c-format msgid "E215: Illegal character after *: %s" msgstr "E215: Nevalida signo post *: %s" -#: ../fileio.c:5905 #, c-format msgid "E216: No such event: %s" msgstr "E216: Ne estas tia evento: %s" -#: ../fileio.c:5907 #, c-format msgid "E216: No such group or event: %s" msgstr "E216: Ne ekzistas tia grupo aÅ evento: %s" #. Highlight title -#: ../fileio.c:6090 msgid "" "\n" "--- Auto-Commands ---" @@ -2486,767 +2004,561 @@ msgstr "" "\n" "--- AÅto-Komandoj ---" -#: ../fileio.c:6293 #, c-format msgid "E680: <buffer=%d>: invalid buffer number " msgstr "E680: <bufro=%d>: nevalida numero de bufro " -#: ../fileio.c:6370 msgid "E217: Can't execute autocommands for ALL events" msgstr "E217: Ne eblas plenumi aÅtokomandojn por ĈIUJ eventoj" -#: ../fileio.c:6393 msgid "No matching autocommands" msgstr "Neniu kongrua aÅtokomando" -#: ../fileio.c:6831 msgid "E218: autocommand nesting too deep" msgstr "E218: aÅtokomando tro ingita" -#: ../fileio.c:7143 #, c-format msgid "%s Auto commands for \"%s\"" msgstr "%s AÅtokomandoj por \"%s\"" -#: ../fileio.c:7149 #, c-format msgid "Executing %s" msgstr "Plenumado de %s" -#: ../fileio.c:7211 #, c-format msgid "autocommand %s" msgstr "aÅtokomando %s" -#: ../fileio.c:7795 msgid "E219: Missing {." msgstr "E219: Mankas {." -#: ../fileio.c:7797 msgid "E220: Missing }." msgstr "E220: Mankas }." -#: ../fold.c:93 msgid "E490: No fold found" msgstr "E490: Neniu faldo trovita" -#: ../fold.c:544 msgid "E350: Cannot create fold with current 'foldmethod'" msgstr "E350: Ne eblas krei faldon per la aktuala 'foldmethod'" -#: ../fold.c:546 msgid "E351: Cannot delete fold with current 'foldmethod'" msgstr "E351: Ne eblas forviÅi faldon per la aktuala 'foldmethod'" -#: ../fold.c:1784 #, c-format -msgid "+--%3ld lines folded " -msgstr "+--%3ld linioj falditaj " +msgid "+--%3ld line folded " +msgid_plural "+--%3ld lines folded " +msgstr[0] "+--%3ld linio faldita " +msgstr[1] "+--%3ld linioj falditaj " -#. buffer has already been read -#: ../getchar.c:273 msgid "E222: Add to read buffer" msgstr "E222: Aldoni al lega bufro" -#: ../getchar.c:2040 msgid "E223: recursive mapping" msgstr "E223: rekursia mapo" -#: ../getchar.c:2849 #, c-format msgid "E224: global abbreviation already exists for %s" msgstr "E224: malloka mallongigo jam ekzistas por %s" -#: ../getchar.c:2852 #, c-format msgid "E225: global mapping already exists for %s" msgstr "E225: malloka mapo jam ekzistas por %s" -#: ../getchar.c:2952 #, c-format msgid "E226: abbreviation already exists for %s" msgstr "E226: mallongigo jam ekzistas por %s" -#: ../getchar.c:2955 #, c-format msgid "E227: mapping already exists for %s" msgstr "E227: mapo jam ekzistas por %s" -#: ../getchar.c:3008 msgid "No abbreviation found" msgstr "Neniu mallongigo trovita" -#: ../getchar.c:3010 msgid "No mapping found" msgstr "Neniu mapo trovita" -#: ../getchar.c:3974 msgid "E228: makemap: Illegal mode" msgstr "E228: makemap: Nevalida reÄimo" -#. key value of 'cedit' option -#. type of cmdline window or 0 -#. result of cmdline window or 0 -#: ../globals.h:924 -msgid "--No lines in buffer--" -msgstr "--Neniu linio en bufro--" - -#. -#. * The error messages that can be shared are included here. -#. * Excluded are errors that are only used once and debugging messages. -#. -#: ../globals.h:996 -msgid "E470: Command aborted" -msgstr "E470: komando ĉesigita" +msgid "E851: Failed to create a new process for the GUI" +msgstr "E851: Malsukcesis krei novan procezon por la grafika interfaco" -#: ../globals.h:997 -msgid "E471: Argument required" -msgstr "E471: Argumento bezonata" +msgid "E852: The child process failed to start the GUI" +msgstr "E852: La ida procezo malsukcesis startigi la grafikan interfacon" -#: ../globals.h:998 -msgid "E10: \\ should be followed by /, ? or &" -msgstr "E10: \\ devus esti sekvita de /, ? aÅ &" +msgid "E229: Cannot start the GUI" +msgstr "E229: Ne eblas lanĉi la grafikan interfacon" -#: ../globals.h:1000 -msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" -msgstr "" -"E11: Nevalida en fenestro de komanda linio; <CR> plenumas, CTRL-C eliras" +#, c-format +msgid "E230: Cannot read from \"%s\"" +msgstr "E230: Ne eblas legi el \"%s\"" -#: ../globals.h:1002 -msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" +msgid "E665: Cannot start GUI, no valid font found" msgstr "" -"E12: Nepermesebla komando el exrc/vimrc en aktuala dosierujo aÅ etikeda serĉo" +"E665: Ne eblas startigi grafikan interfacon, neniu valida tiparo trovita" -#: ../globals.h:1003 -msgid "E171: Missing :endif" -msgstr "E171: Mankas \":endif\"" +msgid "E231: 'guifontwide' invalid" +msgstr "E231: 'guifontwide' nevalida" -#: ../globals.h:1004 -msgid "E600: Missing :endtry" -msgstr "E600: Mankas \":endtry\"" +msgid "E599: Value of 'imactivatekey' is invalid" +msgstr "E599: Valoro de 'imactivatekey' estas nevalida" -#: ../globals.h:1005 -msgid "E170: Missing :endwhile" -msgstr "E170: Mankas \":endwhile\"" +#, c-format +msgid "E254: Cannot allocate color %s" +msgstr "E254: Ne eblas disponigi koloron %s" -#: ../globals.h:1006 -msgid "E170: Missing :endfor" -msgstr "E170: Mankas \":endfor\"" +msgid "No match at cursor, finding next" +msgstr "Neniu kongruo ĉe kursorpozicio, trovas sekvan" -#: ../globals.h:1007 -msgid "E588: :endwhile without :while" -msgstr "E588: \":endwhile\" sen \":while\"" +msgid "<cannot open> " +msgstr "<ne eblas malfermi> " -#: ../globals.h:1008 -msgid "E588: :endfor without :for" -msgstr "E588: \":endfor\" sen \":for\"" +#, c-format +msgid "E616: vim_SelFile: can't get font %s" +msgstr "E616: vim_SelFile: ne eblas akiri tiparon %s" -#: ../globals.h:1009 -msgid "E13: File exists (add ! to override)" -msgstr "E13: Dosiero ekzistas (aldonu ! por transpasi)" +msgid "E614: vim_SelFile: can't return to current directory" +msgstr "E614: vim_SelFile: ne eblas reveni al la aktuala dosierujo" -#: ../globals.h:1010 -msgid "E472: Command failed" -msgstr "E472: La komando fiaskis" +msgid "Pathname:" +msgstr "Serĉvojo:" -#: ../globals.h:1011 -msgid "E473: Internal error" -msgstr "E473: Interna eraro" +msgid "E615: vim_SelFile: can't get current directory" +msgstr "E615: vim_SelFile: ne eblas akiri aktualan dosierujon" -#: ../globals.h:1012 -msgid "Interrupted" -msgstr "Interrompita" +msgid "OK" +msgstr "Bone" -#: ../globals.h:1013 -msgid "E14: Invalid address" -msgstr "E14: Nevalida adreso" +msgid "Cancel" +msgstr "Rezigni" -#: ../globals.h:1014 -msgid "E474: Invalid argument" -msgstr "E474: Nevalida argumento" +msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." +msgstr "" +"Fenestraĵo de rulumskalo: Ne eblis akiri geometrion de reduktita rastrumbildo" -#: ../globals.h:1015 -#, c-format -msgid "E475: Invalid argument: %s" -msgstr "E475: Nevalida argumento: %s" +msgid "Vim dialog" +msgstr "Vim dialogo" -#: ../globals.h:1016 -#, c-format -msgid "E15: Invalid expression: %s" -msgstr "E15: Nevalida esprimo: %s" +msgid "E232: Cannot create BalloonEval with both message and callback" +msgstr "E232: Ne eblas krei BalloonEval kun ambaÅ mesaÄo kaj reagfunkcio" -#: ../globals.h:1017 -msgid "E16: Invalid range" -msgstr "E16: Nevalida amplekso" +msgid "_Cancel" +msgstr "_Rezigni" -#: ../globals.h:1018 -msgid "E476: Invalid command" -msgstr "E476: Nevalida komando" +msgid "_Save" +msgstr "_Konservi" -#: ../globals.h:1019 -#, c-format -msgid "E17: \"%s\" is a directory" -msgstr "E17: \"%s\" estas dosierujo" +msgid "_Open" +msgstr "_Malfermi" -#: ../globals.h:1020 -#, fuzzy -msgid "E900: Invalid job id" -msgstr "E49: Nevalida grando de rulumo" +msgid "_OK" +msgstr "_Bone" -#: ../globals.h:1021 -msgid "E901: Job table is full" +msgid "" +"&Yes\n" +"&No\n" +"&Cancel" msgstr "" +"&Jes\n" +"&Ne\n" +"&Rezigni" -#: ../globals.h:1024 -#, c-format -msgid "E364: Library call failed for \"%s()\"" -msgstr "E364: Alvoko al biblioteko fiaskis por \"%s()\"" +msgid "Yes" +msgstr "Jes" -#: ../globals.h:1026 -msgid "E19: Mark has invalid line number" -msgstr "E19: Marko havas nevalidan numeron de linio" +msgid "No" +msgstr "Ne" -#: ../globals.h:1027 -msgid "E20: Mark not set" -msgstr "E20: Marko ne estas agordita" +# todo '_' is for hotkey, i guess? +msgid "Input _Methods" +msgstr "Enigaj _metodoj" -#: ../globals.h:1029 -msgid "E21: Cannot make changes, 'modifiable' is off" -msgstr "E21: Ne eblas fari ÅanÄojn, 'modifiable' estas malÅaltita" +msgid "VIM - Search and Replace..." +msgstr "VIM - Serĉi kaj anstataÅigi..." -#: ../globals.h:1030 -msgid "E22: Scripts nested too deep" -msgstr "E22: Tro profunde ingitaj skriptoj" +msgid "VIM - Search..." +msgstr "VIM- Serĉi..." -#: ../globals.h:1031 -msgid "E23: No alternate file" -msgstr "E23: Neniu alterna dosiero" +msgid "Find what:" +msgstr "Serĉi kion:" -#: ../globals.h:1032 -msgid "E24: No such abbreviation" -msgstr "E24: Ne estas tia mallongigo" +msgid "Replace with:" +msgstr "AnstataÅigi per:" -#: ../globals.h:1033 -msgid "E477: No ! allowed" -msgstr "E477: Neniu ! permesebla" +#. whole word only button +msgid "Match whole word only" +msgstr "Kongrui kun nur plena vorto" -#: ../globals.h:1035 -msgid "E25: Nvim does not have a built-in GUI" -msgstr "E25: Grafika interfaco ne uzeblas: MalÅaltita dum kompilado" +#. match case button +msgid "Match case" +msgstr "Uskleca kongruo" -#: ../globals.h:1036 -#, c-format -msgid "E28: No such highlight group name: %s" -msgstr "E28: Neniu grupo de emfazo kiel: %s" +msgid "Direction" +msgstr "Direkto" -#: ../globals.h:1037 -msgid "E29: No inserted text yet" -msgstr "E29: AnkoraÅ neniu enmetita teksto" +#. 'Up' and 'Down' buttons +msgid "Up" +msgstr "Supren" -#: ../globals.h:1038 -msgid "E30: No previous command line" -msgstr "E30: Neniu antaÅa komanda linio" +msgid "Down" +msgstr "Suben" -#: ../globals.h:1039 -msgid "E31: No such mapping" -msgstr "E31: Neniu tiel mapo" +msgid "Find Next" +msgstr "Trovi sekvantan" -#: ../globals.h:1040 -msgid "E479: No match" -msgstr "E479: Neniu kongruo" +msgid "Replace" +msgstr "AnstataÅigi" -#: ../globals.h:1041 -#, c-format -msgid "E480: No match: %s" -msgstr "E480: Neniu kongruo: %s" +msgid "Replace All" +msgstr "AnstataÅigi ĉiujn" -#: ../globals.h:1042 -msgid "E32: No file name" -msgstr "E32: Neniu dosiernomo" +msgid "_Close" +msgstr "_Fermi" -#: ../globals.h:1044 -msgid "E33: No previous substitute regular expression" -msgstr "E33: Neniu antaÅa regulesprimo de anstataÅigo" +msgid "Vim: Received \"die\" request from session manager\n" +msgstr "Vim: Ricevis peton \"die\" (morti) el la seanca administrilo\n" -#: ../globals.h:1045 -msgid "E34: No previous command" -msgstr "E34: Neniu antaÅa komando" +msgid "Close tab" +msgstr "Fermi langeton" -#: ../globals.h:1046 -msgid "E35: No previous regular expression" -msgstr "E35: Neniu antaÅa regulesprimo" +msgid "New tab" +msgstr "Nova langeto" -#: ../globals.h:1047 -msgid "E481: No range allowed" -msgstr "E481: Amplekso nepermesebla" +msgid "Open Tab..." +msgstr "Malfermi langeton..." -#: ../globals.h:1048 -msgid "E36: Not enough room" -msgstr "E36: Ne sufiĉe da spaco" +msgid "Vim: Main window unexpectedly destroyed\n" +msgstr "Vim: Ĉefa fenestro neatendite detruiÄis\n" -#: ../globals.h:1049 -#, c-format -msgid "E482: Can't create file %s" -msgstr "E482: Ne eblas krei dosieron %s" +msgid "&Filter" +msgstr "&Filtri" -#: ../globals.h:1050 -msgid "E483: Can't get temp file name" -msgstr "E483: Ne eblas akiri provizoran dosiernomon" +msgid "&Cancel" +msgstr "&Rezigni" -#: ../globals.h:1051 -#, c-format -msgid "E484: Can't open file %s" -msgstr "E484: Ne eblas malfermi dosieron %s" +msgid "Directories" +msgstr "Dosierujoj" -#: ../globals.h:1052 -#, c-format -msgid "E485: Can't read file %s" -msgstr "E485: Ne eblas legi dosieron %s" +msgid "Filter" +msgstr "Filtri" -#: ../globals.h:1054 -msgid "E37: No write since last change (add ! to override)" -msgstr "E37: Neniu skribo de post lasta ÅanÄo (aldonu ! por transpasi)" +msgid "&Help" +msgstr "&Helpo" -#: ../globals.h:1055 -#, fuzzy -msgid "E37: No write since last change" -msgstr "[Neniu skribo de post lasta ÅanÄo]\n" +msgid "Files" +msgstr "Dosieroj" -#: ../globals.h:1056 -msgid "E38: Null argument" -msgstr "E38: Nula argumento" +msgid "&OK" +msgstr "&Bone" -#: ../globals.h:1057 -msgid "E39: Number expected" -msgstr "E39: Nombro atendita" +msgid "Selection" +msgstr "Apartigo" -#: ../globals.h:1058 -#, c-format -msgid "E40: Can't open errorfile %s" -msgstr "E40: Ne eblas malfermi eraran dosieron %s" +msgid "Find &Next" +msgstr "Trovi &Sekvanta" -#: ../globals.h:1059 -msgid "E41: Out of memory!" -msgstr "E41: Ne plu restas memoro!" +msgid "&Replace" +msgstr "&AnstataÅigi" -#: ../globals.h:1060 -msgid "Pattern not found" -msgstr "Åœablono ne trovita" +msgid "Replace &All" +msgstr "AnstataÅigi ĉi&on" -#: ../globals.h:1061 -#, c-format -msgid "E486: Pattern not found: %s" -msgstr "E486: Åœablono ne trovita: %s" - -#: ../globals.h:1062 -msgid "E487: Argument must be positive" -msgstr "E487: La argumento devas esti pozitiva" +msgid "&Undo" +msgstr "&Malfari" -#: ../globals.h:1064 -msgid "E459: Cannot go back to previous directory" -msgstr "E459: Ne eblas reiri al antaÅa dosierujo" - -#: ../globals.h:1066 -msgid "E42: No Errors" -msgstr "E42: Neniu eraro" +msgid "Open tab..." +msgstr "Malfermi langeton..." -#: ../globals.h:1067 -msgid "E776: No location list" -msgstr "E776: Neniu listo de loko" +msgid "Find string (use '\\\\' to find a '\\')" +msgstr "Trovi ĉenon (uzu '\\\\' por trovi '\\')" -#: ../globals.h:1068 -msgid "E43: Damaged match string" -msgstr "E43: Difekta kongruenda ĉeno" +msgid "Find & Replace (use '\\\\' to find a '\\')" +msgstr "Trovi kaj anstataÅigi (uzu '\\\\' por trovi '\\')" -#: ../globals.h:1069 -msgid "E44: Corrupted regexp program" -msgstr "E44: Difekta programo de regulesprimo" +#. We fake this: Use a filter that doesn't select anything and a default +#. * file name that won't be used. +msgid "Not Used" +msgstr "Ne uzata" -#: ../globals.h:1071 -msgid "E45: 'readonly' option is set (add ! to override)" -msgstr "E45: La opcio 'readonly' estas Åaltita '(aldonu ! por transpasi)" +msgid "Directory\t*.nothing\n" +msgstr "Dosierujo\t*.nenio\n" -#: ../globals.h:1073 #, c-format -msgid "E46: Cannot change read-only variable \"%s\"" -msgstr "E46: Ne eblas ÅanÄi nurlegeblan variablon \"%s\"" +msgid "E671: Cannot find window title \"%s\"" +msgstr "E671: Ne eblas trovi titolon de fenestro \"%s\"" -#: ../globals.h:1075 #, c-format -msgid "E794: Cannot set variable in the sandbox: \"%s\"" -msgstr "E794: Ne eblas agordi variablon en la sabloludejo: \"%s\"" +msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." +msgstr "E243: Ne subtenata argumento: \"-%s\"; Uzu la version OLE." -msgid "E713: Cannot use empty key for Dictionary" -msgstr "E713: Ne eblas uzi malplenan Ålosilon de Vortaro" - -#: ../globals.h:1076 -msgid "E47: Error while reading errorfile" -msgstr "E47: Eraro dum legado de erardosiero" - -#: ../globals.h:1078 -msgid "E48: Not allowed in sandbox" -msgstr "E48: Nepermesebla en sabloludejo" - -#: ../globals.h:1080 -msgid "E523: Not allowed here" -msgstr "E523: Nepermesebla tie" +msgid "E672: Unable to open window inside MDI application" +msgstr "E672: Ne eblas malfermi fenestron interne de aplikaĵo MDI" -#: ../globals.h:1082 -msgid "E359: Screen mode setting not supported" -msgstr "E359: ReÄimo de ekrano ne subtenata" - -#: ../globals.h:1083 -msgid "E49: Invalid scroll size" -msgstr "E49: Nevalida grando de rulumo" - -#: ../globals.h:1084 -msgid "E91: 'shell' option is empty" -msgstr "E91: La opcio 'shell' estas malplena" - -#: ../globals.h:1085 -msgid "E255: Couldn't read in sign data!" -msgstr "E255: Ne eblis legi datumojn de simboloj!" - -#: ../globals.h:1086 -msgid "E72: Close error on swap file" -msgstr "E72: Eraro dum malfermo de permutodosiero .swp" - -#: ../globals.h:1087 -msgid "E73: tag stack empty" -msgstr "E73: malplena stako de etikedo" - -#: ../globals.h:1088 -msgid "E74: Command too complex" -msgstr "E74: Komando tro kompleksa" - -#: ../globals.h:1089 -msgid "E75: Name too long" -msgstr "E75: Nomo tro longa" +msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" +msgstr "" +"Vim E458: Ne eblas disponigi rikordon de kolormapo, iuj koloroj estas eble " +"neÄustaj" -#: ../globals.h:1090 -msgid "E76: Too many [" -msgstr "E76: Tro da [" +#, c-format +msgid "E250: Fonts for the following charsets are missing in fontset %s:" +msgstr "E250: Tiparoj de tiuj signaroj mankas en aro de tiparo %s:" -#: ../globals.h:1091 -msgid "E77: Too many file names" -msgstr "E77: Tro da dosiernomoj" +#, c-format +msgid "E252: Fontset name: %s" +msgstr "E252: Nomo de tiparo: %s" -#: ../globals.h:1092 -msgid "E488: Trailing characters" -msgstr "E488: Vostaj signoj" +#, c-format +msgid "Font '%s' is not fixed-width" +msgstr "Tiparo '%s' ne estas egallarÄa" -#: ../globals.h:1093 -msgid "E78: Unknown mark" -msgstr "E78: Nekonata marko" +#, c-format +msgid "E253: Fontset name: %s" +msgstr "E253: Nomo de tiparo: %s" -#: ../globals.h:1094 -msgid "E79: Cannot expand wildcards" -msgstr "E79: Ne eblas malvolvi ĵokerojn" +#, c-format +msgid "Font0: %s" +msgstr "Font0: %s" -#: ../globals.h:1096 -msgid "E591: 'winheight' cannot be smaller than 'winminheight'" -msgstr "E591: 'winheight' ne rajtas esti malpli ol 'winminheight'" +#, c-format +msgid "Font1: %s" +msgstr "Font1: %s" -#: ../globals.h:1098 -msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" -msgstr "E592: 'winwidth' ne rajtas esti malpli ol 'winminwidth'" +#, c-format +msgid "Font%ld width is not twice that of font0" +msgstr "Font%ld ne estas duoble pli larÄa ol font0" -#: ../globals.h:1099 -msgid "E80: Error while writing" -msgstr "E80: Eraro dum skribado" +#, c-format +msgid "Font0 width: %ld" +msgstr "LarÄo de font0: %ld" -#: ../globals.h:1100 -msgid "Zero count" -msgstr "Nul kvantoro" +#, c-format +msgid "Font1 width: %ld" +msgstr "LarÄo de Font1: %ld" -#: ../globals.h:1101 -msgid "E81: Using <SID> not in a script context" -msgstr "E81: Uzo de <SID> ekster kunteksto de skripto" +msgid "Invalid font specification" +msgstr "Nevalida tiparo specifita" -#: ../globals.h:1102 -#, c-format -msgid "E685: Internal error: %s" -msgstr "E685: Interna eraro: %s" +msgid "&Dismiss" +msgstr "&Forlasi" -#: ../globals.h:1104 -msgid "E363: pattern uses more memory than 'maxmempattern'" -msgstr "E363: Åablono uzas pli da memoro ol 'maxmempattern'" +msgid "no specific match" +msgstr "Neniu specifa kongruo" -#: ../globals.h:1105 -msgid "E749: empty buffer" -msgstr "E749: malplena bufro" +msgid "Vim - Font Selector" +msgstr "Vim - Elektilo de tiparo" -#: ../globals.h:1226 -#, c-format -msgid "E86: Buffer %<PRId64> does not exist" -msgstr "E86: La bufro %<PRId64> ne ekzistas" +msgid "Name:" +msgstr "Nomo:" -#: ../globals.h:1108 -msgid "E682: Invalid search pattern or delimiter" -msgstr "E682: Nevalida serĉa Åablono aÅ disigilo" +#. create toggle button +msgid "Show size in Points" +msgstr "Montri grandon en punktoj" -#: ../globals.h:1109 -msgid "E139: File is loaded in another buffer" -msgstr "E139: Dosiero estas Åargita en alia bufro" +msgid "Encoding:" +msgstr "Kodoprezento:" -#: ../globals.h:1110 -#, c-format -msgid "E764: Option '%s' is not set" -msgstr "E764: La opcio '%s' ne estas Åaltita" +msgid "Font:" +msgstr "Tiparo:" -#: ../globals.h:1111 -msgid "E850: Invalid register name" -msgstr "E850: Nevalida nomo de reÄistro" +msgid "Style:" +msgstr "Stilo:" -#: ../globals.h:1114 -msgid "search hit TOP, continuing at BOTTOM" -msgstr "serĉo atingis SUPRON, daÅrigonte al SUBO" +msgid "Size:" +msgstr "Grando:" -#: ../globals.h:1115 -msgid "search hit BOTTOM, continuing at TOP" -msgstr "serĉo atingis SUBON, daÅrigonte al SUPRO" +msgid "E256: Hangul automata ERROR" +msgstr "E256: ERARO en aÅtomato de korea alfabeto" -#: ../hardcopy.c:240 msgid "E550: Missing colon" msgstr "E550: Mankas dupunkto" -#: ../hardcopy.c:252 msgid "E551: Illegal component" msgstr "E551: Nevalida komponento" -#: ../hardcopy.c:259 msgid "E552: digit expected" msgstr "E552: cifero atendita" -#: ../hardcopy.c:473 #, c-format msgid "Page %d" msgstr "PaÄo %d" -#: ../hardcopy.c:597 msgid "No text to be printed" msgstr "Neniu presenda teksto" -#: ../hardcopy.c:668 #, c-format msgid "Printing page %d (%d%%)" msgstr "Presas paÄon %d (%d%%)" -#: ../hardcopy.c:680 #, c-format msgid " Copy %d of %d" msgstr " Kopio %d de %d" -#: ../hardcopy.c:733 #, c-format msgid "Printed: %s" msgstr "Presis: %s" -#: ../hardcopy.c:740 msgid "Printing aborted" msgstr "Presado ĉesigita" -#: ../hardcopy.c:1365 msgid "E455: Error writing to PostScript output file" msgstr "E455: Eraro dum skribo de PostSkripta eliga dosiero" -#: ../hardcopy.c:1747 #, c-format msgid "E624: Can't open file \"%s\"" msgstr "E624: Ne eblas malfermi dosieron \"%s\"" -#: ../hardcopy.c:1756 ../hardcopy.c:2470 #, c-format msgid "E457: Can't read PostScript resource file \"%s\"" msgstr "E457: Ne eblas legi dosieron de PostSkripta rimedo \"%s\"" -#: ../hardcopy.c:1772 #, c-format msgid "E618: file \"%s\" is not a PostScript resource file" msgstr "E618: \"%s\" ne estas dosiero de PostSkripta rimedo" -#: ../hardcopy.c:1788 ../hardcopy.c:1805 ../hardcopy.c:1844 #, c-format msgid "E619: file \"%s\" is not a supported PostScript resource file" msgstr "E619: \"%s\" ne estas subtenata dosiero de PostSkripta rimedo" -#: ../hardcopy.c:1856 #, c-format msgid "E621: \"%s\" resource file has wrong version" msgstr "E621: \"%s\" dosiero de rimedo havas neÄustan version" -#: ../hardcopy.c:2225 msgid "E673: Incompatible multi-byte encoding and character set." msgstr "E673: Nekongrua plurbajta kodoprezento kaj signaro." -#: ../hardcopy.c:2238 msgid "E674: printmbcharset cannot be empty with multi-byte encoding." msgstr "" "E674: printmbcharset ne rajtas esti malplena kun plurbajta kodoprezento." -#: ../hardcopy.c:2254 msgid "E675: No default font specified for multi-byte printing." msgstr "E675: Neniu defaÅlta tiparo specifita por plurbajta presado." -#: ../hardcopy.c:2426 msgid "E324: Can't open PostScript output file" msgstr "E324: Ne eblas malfermi eligan PostSkriptan dosieron" -#: ../hardcopy.c:2458 #, c-format msgid "E456: Can't open file \"%s\"" msgstr "E456: Ne eblas malfermi dosieron \"%s\"" -#: ../hardcopy.c:2583 msgid "E456: Can't find PostScript resource file \"prolog.ps\"" msgstr "E456: Dosiero de PostSkripta rimedo \"prolog.ps\" ne troveblas" -#: ../hardcopy.c:2593 msgid "E456: Can't find PostScript resource file \"cidfont.ps\"" msgstr "E456: Dosiero de PostSkripta rimedo \"cidfont.ps\" ne troveblas" -#: ../hardcopy.c:2622 ../hardcopy.c:2639 ../hardcopy.c:2665 #, c-format msgid "E456: Can't find PostScript resource file \"%s.ps\"" msgstr "E456: Dosiero de PostSkripta rimedo \"%s.ps\" ne troveblas" -#: ../hardcopy.c:2654 #, c-format msgid "E620: Unable to convert to print encoding \"%s\"" msgstr "E620: Ne eblas konverti al la presa kodoprezento \"%s\"" -#: ../hardcopy.c:2877 msgid "Sending to printer..." msgstr "Sendas al presilo..." -#: ../hardcopy.c:2881 msgid "E365: Failed to print PostScript file" -msgstr "E365: Presado de PostSkripta dosiero fiaskis" +msgstr "E365: Presado de PostSkripta dosiero malsukcesis" -#: ../hardcopy.c:2883 msgid "Print job sent." msgstr "Laboro de presado sendita." -#: ../if_cscope.c:85 msgid "Add a new database" msgstr "Aldoni novan datumbazon" -#: ../if_cscope.c:87 msgid "Query for a pattern" msgstr "Serĉi Åablonon" -#: ../if_cscope.c:89 msgid "Show this message" msgstr "Montri tiun mesaÄon" -#: ../if_cscope.c:91 msgid "Kill a connection" msgstr "Ĉesigi konekton" -#: ../if_cscope.c:93 msgid "Reinit all connections" msgstr "Repravalorizi ĉiujn konektojn" -#: ../if_cscope.c:95 msgid "Show connections" msgstr "Montri konektojn" -#: ../if_cscope.c:101 #, c-format msgid "E560: Usage: cs[cope] %s" msgstr "E560: Uzo: cs[cope] %s" -#: ../if_cscope.c:225 msgid "This cscope command does not support splitting the window.\n" msgstr "Tiu ĉi komando de cscope ne subtenas dividon de fenestro.\n" -#: ../if_cscope.c:266 msgid "E562: Usage: cstag <ident>" msgstr "E562: Uzo: cstag <ident>" -#: ../if_cscope.c:313 msgid "E257: cstag: tag not found" msgstr "E257: cstag: etikedo netrovita" -#: ../if_cscope.c:461 #, c-format msgid "E563: stat(%s) error: %d" msgstr "E563: Eraro de stat(%s): %d" -#: ../if_cscope.c:551 +msgid "E563: stat error" +msgstr "E563: Eraro de stat" + #, c-format msgid "E564: %s is not a directory or a valid cscope database" msgstr "E564: %s ne estas dosierujo aÅ valida datumbazo de cscope" -#: ../if_cscope.c:566 #, c-format msgid "Added cscope database %s" msgstr "Aldonis datumbazon de cscope %s" -#: ../if_cscope.c:616 #, c-format -msgid "E262: error reading cscope connection %<PRId64>" -msgstr "E262: eraro dum legado de konekto de cscope %<PRId64>" +msgid "E262: error reading cscope connection %ld" +msgstr "E262: eraro dum legado de konekto de cscope %ld" -#: ../if_cscope.c:711 msgid "E561: unknown cscope search type" msgstr "E561: nekonata tipo de serĉo de cscope" -#: ../if_cscope.c:752 ../if_cscope.c:789 msgid "E566: Could not create cscope pipes" msgstr "E566: Ne eblis krei duktojn de cscope" -#: ../if_cscope.c:767 msgid "E622: Could not fork for cscope" msgstr "E622: Ne eblis forki cscope" -#: ../if_cscope.c:849 -#, fuzzy msgid "cs_create_connection setpgid failed" -msgstr "plenumo de cs_create_connection fiaskis" +msgstr "plenumo de cs_create_connection-setgpid malsukcesis" -#: ../if_cscope.c:853 ../if_cscope.c:889 msgid "cs_create_connection exec failed" -msgstr "plenumo de cs_create_connection fiaskis" +msgstr "plenumo de cs_create_connection malsukcesis" -#: ../if_cscope.c:863 ../if_cscope.c:902 msgid "cs_create_connection: fdopen for to_fp failed" -msgstr "cs_create_connection: fdopen de to_fp fiaskis" +msgstr "cs_create_connection: fdopen de to_fp malsukcesis" -#: ../if_cscope.c:865 ../if_cscope.c:906 msgid "cs_create_connection: fdopen for fr_fp failed" -msgstr "cs_create_connection: fdopen de fr_fp fiaskis" +msgstr "cs_create_connection: fdopen de fr_fp malsukcesis" -#: ../if_cscope.c:890 msgid "E623: Could not spawn cscope process" msgstr "E623: Ne eblis naskigi procezon cscope" -#: ../if_cscope.c:932 msgid "E567: no cscope connections" msgstr "E567: neniu konekto al cscope" -#: ../if_cscope.c:1009 #, c-format msgid "E469: invalid cscopequickfix flag %c for %c" msgstr "E469: nevalida flago cscopequickfix %c de %c" -#: ../if_cscope.c:1058 #, c-format msgid "E259: no matches found for cscope query %s of %s" msgstr "E259: neniu kongruo trovita por serĉo per cscope %s de %s" -#: ../if_cscope.c:1142 msgid "cscope commands:\n" msgstr "komandoj de cscope:\n" -#: ../if_cscope.c:1150 #, c-format msgid "%-5s: %s%*s (Usage: %s)" msgstr "%-5s: %s%*s (Uzo: %s)" -#: ../if_cscope.c:1155 msgid "" "\n" +" a: Find assignments to this symbol\n" " c: Find functions calling this function\n" " d: Find functions called by this function\n" " e: Find this egrep pattern\n" @@ -3257,6 +2569,7 @@ msgid "" " t: Find this text string\n" msgstr "" "\n" +" a: Trovi valirizojn al tiu simbolo\n" " c: Trovi funkciojn, kiuj alvokas tiun funkcion\n" " d: Trovi funkciojn alvokataj de tiu funkcio\n" " e: Trovi tiun egrep-Åablonon\n" @@ -3266,31 +2579,32 @@ msgstr "" " s: Trovi tiun C-simbolon\n" " t: Trovi tiun ĉenon\n" -#: ../if_cscope.c:1226 +#, c-format +msgid "E625: cannot open cscope database: %s" +msgstr "E625: ne eblas malfermi datumbazon de cscope: %s" + +msgid "E626: cannot get cscope database information" +msgstr "E626: ne eblas akiri informojn pri la datumbazo de cscope" + msgid "E568: duplicate cscope database not added" msgstr "E568: ripetita datumbazo de cscope ne aldonita" -#: ../if_cscope.c:1335 #, c-format msgid "E261: cscope connection %s not found" msgstr "E261: konekto cscope %s netrovita" -#: ../if_cscope.c:1364 #, c-format msgid "cscope connection %s closed" msgstr "konekto cscope %s fermita" #. should not reach here -#: ../if_cscope.c:1486 msgid "E570: fatal error in cs_manage_matches" msgstr "E570: neriparebla eraro en cs_manage_matches" -#: ../if_cscope.c:1693 #, c-format msgid "Cscope tag: %s" msgstr "Etikedo de cscope: %s" -#: ../if_cscope.c:1711 msgid "" "\n" " # line" @@ -3298,87 +2612,306 @@ msgstr "" "\n" " nro linio" -#: ../if_cscope.c:1713 msgid "filename / context / line\n" msgstr "dosiernomo / kunteksto / linio\n" -#: ../if_cscope.c:1809 #, c-format msgid "E609: Cscope error: %s" msgstr "E609: Eraro de cscope: %s" -#: ../if_cscope.c:2053 msgid "All cscope databases reset" msgstr "ReÅargo de ĉiuj datumbazoj de cscope" -#: ../if_cscope.c:2123 msgid "no cscope connections\n" msgstr "neniu konekto de cscope\n" -#: ../if_cscope.c:2126 msgid " # pid database name prepend path\n" msgstr " # pid nomo de datumbazo prefiksa vojo\n" -#: ../main.c:144 +msgid "Lua library cannot be loaded." +msgstr "La biblioteko Lua no Åargeblis." + +msgid "cannot save undo information" +msgstr "ne eblas konservi informojn de malfaro" + +msgid "" +"E815: Sorry, this command is disabled, the MzScheme libraries could not be " +"loaded." +msgstr "" +"E815: BedaÅrinde, tiu komando estas malÅaltita, ne eblis Åargi la " +"bibliotekojn." + +msgid "" +"E895: Sorry, this command is disabled, the MzScheme's racket/base module " +"could not be loaded." +msgstr "" +"E895: BedaÅrinde, tiu komando estas malÅaltita, ne eblis Åargi la modulon de " +"MzScheme racket/base." + +msgid "invalid expression" +msgstr "nevalida esprimo" + +msgid "expressions disabled at compile time" +msgstr "esprimoj malÅaltitaj dum kompilado" + +msgid "hidden option" +msgstr "kaÅita opcio" + +msgid "unknown option" +msgstr "nekonata opcio" + +msgid "window index is out of range" +msgstr "indekso de fenestro estas ekster limoj" + +msgid "couldn't open buffer" +msgstr "ne eblis malfermi bufron" + +msgid "cannot delete line" +msgstr "ne eblas forviÅi linion" + +msgid "cannot replace line" +msgstr "ne eblas anstataÅigi linion" + +msgid "cannot insert line" +msgstr "ne eblas enmeti linion" + +msgid "string cannot contain newlines" +msgstr "ĉeno ne rajtas enhavi liniavancojn" + +msgid "error converting Scheme values to Vim" +msgstr "eraro dum konverto de Scheme-valoro al Vim" + +msgid "Vim error: ~a" +msgstr "Eraro de Vim: ~a" + +msgid "Vim error" +msgstr "Eraro de Vim" + +msgid "buffer is invalid" +msgstr "bufro estas nevalida" + +msgid "window is invalid" +msgstr "fenestro estas nevalida" + +msgid "linenr out of range" +msgstr "numero de linio ekster limoj" + +msgid "not allowed in the Vim sandbox" +msgstr "nepermesebla en sabloludejo de Vim" + +msgid "E836: This Vim cannot execute :python after using :py3" +msgstr "E836: Vim ne povas plenumi :python post uzo de :py3" + +msgid "" +"E263: Sorry, this command is disabled, the Python library could not be " +"loaded." +msgstr "" +"E263: BedaÅrinde tiu komando estas malÅaltita: la biblioteko de Pitono ne " +"Åargeblis." + +msgid "" +"E887: Sorry, this command is disabled, the Python's site module could not be " +"loaded." +msgstr "" +"E887` BedaÅrinde tiu komando estas malÅaltita: la biblioteko de Pitono ne " +"Åargeblis." + +msgid "E659: Cannot invoke Python recursively" +msgstr "E659: Ne eblas alvoki Pitonon rekursie" + +msgid "E837: This Vim cannot execute :py3 after using :python" +msgstr "E837: Vim ne povas plenumi :py3 post uzo de :python" + +msgid "E265: $_ must be an instance of String" +msgstr "E265: $_ devas esti apero de Ĉeno" + +msgid "" +"E266: Sorry, this command is disabled, the Ruby library could not be loaded." +msgstr "" +"E266: BedaÅrinde tiu komando estas malÅaltita, la biblioteko Ruby ne " +"Åargeblis." + +msgid "E267: unexpected return" +msgstr "E267: \"return\" neatendita" + +msgid "E268: unexpected next" +msgstr "E268: \"next\" neatendita" + +msgid "E269: unexpected break" +msgstr "E269: \"break\" neatendita" + +msgid "E270: unexpected redo" +msgstr "E270: \"redo\" neatendita" + +msgid "E271: retry outside of rescue clause" +msgstr "E271: \"retry\" ekster klaÅzo \"rescue\"" + +msgid "E272: unhandled exception" +msgstr "E272: netraktita escepto" + +#, c-format +msgid "E273: unknown longjmp status %d" +msgstr "E273: nekonata stato de longjmp: %d" + +msgid "invalid buffer number" +msgstr "nevalida numero de bufro" + +msgid "not implemented yet" +msgstr "ankoraÅ ne realigita" + +#. ??? +msgid "cannot set line(s)" +msgstr "ne eblas meti la linio(j)n" + +msgid "invalid mark name" +msgstr "nevalida nomo de marko" + +msgid "mark not set" +msgstr "marko ne estas metita" + +#, c-format +msgid "row %d column %d" +msgstr "linio %d kolumno %d" + +msgid "cannot insert/append line" +msgstr "ne eblas enmeti/postaldoni linion" + +msgid "line number out of range" +msgstr "numero de linio ekster limoj" + +msgid "unknown flag: " +msgstr "nekonata flago: " + +# DP: ĉu traduki vimOption +msgid "unknown vimOption" +msgstr "nekonata vimOption" + +msgid "keyboard interrupt" +msgstr "klavara interrompo" + +msgid "vim error" +msgstr "eraro de Vim" + +msgid "cannot create buffer/window command: object is being deleted" +msgstr "ne eblas krei komandon de bufro/fenestro: objekto estas forviÅiÄanta" + +msgid "" +"cannot register callback command: buffer/window is already being deleted" +msgstr "" +"ne eblas registri postalvokan komandon: bufro/fenestro estas jam forviÅiÄanta" + +#. This should never happen. Famous last word? +msgid "" +"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim." +"org" +msgstr "" +"E280: NERIPAREBLA TCL-ERARO: reflist difekta!? Bv. retpoÅti al vim-dev@vim." +"org" + +msgid "cannot register callback command: buffer/window reference not found" +msgstr "" +"ne eblas registri postalvokan komandon: referenco de bufro/fenestro ne " +"troveblas" + +msgid "" +"E571: Sorry, this command is disabled: the Tcl library could not be loaded." +msgstr "" +"E571: BedaÅrinde tiu komando estas malÅaltita: la biblioteko Tcl ne " +"Åargeblis." + +#, c-format +msgid "E572: exit code %d" +msgstr "E572: elira kodo %d" + +msgid "cannot get line" +msgstr "ne eblas akiri linion" + +msgid "Unable to register a command server name" +msgstr "Ne eblas registri nomon de komanda servilo" + +msgid "E248: Failed to send command to the destination program" +msgstr "E248: Sendo de komando al cela programo malsukcesis" + +#, c-format +msgid "E573: Invalid server id used: %s" +msgstr "E573: Nevalida identigilo de servilo uzita: %s" + +msgid "E251: VIM instance registry property is badly formed. Deleted!" +msgstr "" +"E251: Ecoj de registro de apero de VIM estas nevalide formata. ForviÅita!" + +#, c-format +msgid "E938: Duplicate key in JSON: \"%s\"" +msgstr "E938: Ripetita Ålosilo en JSON: \"%s\"" + +#, c-format +msgid "E696: Missing comma in List: %s" +msgstr "E696: Mankas komo en Listo: %s" + +#, c-format +msgid "E697: Missing end of List ']': %s" +msgstr "E697: Mankas fino de Listo ']': %s" + msgid "Unknown option argument" msgstr "Nekonata argumento de opcio" -#: ../main.c:146 msgid "Too many edit arguments" msgstr "Tro da argumentoj de redakto" -#: ../main.c:148 msgid "Argument missing after" msgstr "Argumento mankas post" -#: ../main.c:150 msgid "Garbage after option argument" msgstr "Forĵetindaĵo post argumento de opcio" -#: ../main.c:152 msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments" msgstr "Tro da argumentoj \"+komando\", \"-c komando\" aÅ \"--cmd komando\"" -#: ../main.c:154 msgid "Invalid argument for" msgstr "Nevalida argumento por" -#: ../main.c:294 #, c-format msgid "%d files to edit\n" msgstr "%d redaktendaj dosieroj\n" -#: ../main.c:1342 +msgid "netbeans is not supported with this GUI\n" +msgstr "netbeans ne estas subtenata kun tiu grafika interfaco\n" + +msgid "'-nb' cannot be used: not enabled at compile time\n" +msgstr "'-nb' ne uzeblas: malÅaltita dum kompilado\n" + +msgid "This Vim was not compiled with the diff feature." +msgstr "Tiu Vim ne estis kompilita kun la kompara eblo." + msgid "Attempt to open script file again: \"" msgstr "Provas malfermi skriptan dosieron denove: \"" -#: ../main.c:1350 msgid "Cannot open for reading: \"" msgstr "Ne eblas malfermi en lega reÄimo: \"" -#: ../main.c:1393 msgid "Cannot open for script output: \"" msgstr "Ne eblas malfermi por eligo de skripto: \"" -#: ../main.c:1622 +msgid "Vim: Error: Failure to start gvim from NetBeans\n" +msgstr "Vim: Eraro: malsukcesis lanĉi gvim el NetBeans\n" + +msgid "Vim: Error: This version of Vim does not run in a Cygwin terminal\n" +msgstr "Vim: Eraro: Tiu versio de Vim ne ruliÄas en terminalo Cygwin\n" + msgid "Vim: Warning: Output is not to a terminal\n" msgstr "Vim: Averto: Eligo ne estas al terminalo\n" -#: ../main.c:1624 msgid "Vim: Warning: Input is not from a terminal\n" msgstr "Vim: Averto: Enigo ne estas el terminalo\n" #. just in case.. -#: ../main.c:1891 msgid "pre-vimrc command line" msgstr "komanda linio pre-vimrc" -#: ../main.c:1964 #, c-format msgid "E282: Cannot read from \"%s\"" msgstr "E282: Ne eblas legi el \"%s\"" -#: ../main.c:2149 msgid "" "\n" "More info with: \"vim -h\"\n" @@ -3387,23 +2920,18 @@ msgstr "" "Pliaj informoj per: \"vim -h\"\n" # DP: tajpu "vim --help" por testi tiujn mesaÄojn -#: ../main.c:2178 msgid "[file ..] edit specified file(s)" msgstr "[dosiero...] redakti specifita(j)n dosiero(j)n" -#: ../main.c:2179 msgid "- read text from stdin" msgstr "- legi tekston el stdin" -#: ../main.c:2180 msgid "-t tag edit file where tag is defined" msgstr "-t etikedo redakti dosieron kie etikedo estas difinata" -#: ../main.c:2181 msgid "-q [errorfile] edit file with first error" msgstr "-q [erardosiero] redakti dosieron kun unua eraro" -#: ../main.c:2187 msgid "" "\n" "\n" @@ -3413,11 +2941,9 @@ msgstr "" "\n" " uzo:" -#: ../main.c:2189 msgid " vim [arguments] " msgstr " vim [argumentoj] " -#: ../main.c:2193 msgid "" "\n" " or:" @@ -3425,7 +2951,13 @@ msgstr "" "\n" " aÅ:" -#: ../main.c:2196 +msgid "" +"\n" +"Where case is ignored prepend / to make flag upper case" +msgstr "" +"\n" +"Kie uskleco estas ignorita antaÅaldonu / por igi flagon majuskla" + msgid "" "\n" "\n" @@ -3435,197 +2967,336 @@ msgstr "" "\n" "Argumentoj:\n" -#: ../main.c:2197 msgid "--\t\t\tOnly file names after this" msgstr "--\t\t\tNur dosiernomoj post tio" -#: ../main.c:2199 msgid "--literal\t\tDon't expand wildcards" msgstr "--literal\t\tNe malvolvi ĵokerojn" -#: ../main.c:2201 +msgid "-register\t\tRegister this gvim for OLE" +msgstr "-register\t\tRegistri tiun gvim al OLE" + +msgid "-unregister\t\tUnregister gvim for OLE" +msgstr "-unregister\t\tMalregistri gvim de OLE" + +msgid "-g\t\t\tRun using GUI (like \"gvim\")" +msgstr "-g\t\t\tRuli per grafika interfaco (kiel \"gvim\")" + +msgid "-f or --nofork\tForeground: Don't fork when starting GUI" +msgstr "-f aÅ --nofork\tMalfono: ne forki kiam lanĉas grafikan interfacon" + msgid "-v\t\t\tVi mode (like \"vi\")" msgstr "-v\t\t\tReÄimo Vi (kiel \"vi\")" -#: ../main.c:2202 msgid "-e\t\t\tEx mode (like \"ex\")" msgstr "-e\t\t\tReÄimo Ex (kiel \"ex\")" -#: ../main.c:2203 msgid "-E\t\t\tImproved Ex mode" msgstr "-E\t\t\tPlibonigita Ex-reÄimo" -#: ../main.c:2204 msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")" msgstr "-s\t\t\tSilenta (stapla) reÄimo (nur por \"ex\")" -#: ../main.c:2205 msgid "-d\t\t\tDiff mode (like \"vimdiff\")" msgstr "-d\t\t\tKompara reÄimo (kiel \"vimdiff\")" -#: ../main.c:2206 msgid "-y\t\t\tEasy mode (like \"evim\", modeless)" msgstr "-y\t\t\tFacila reÄimo (kiel \"evim\", senreÄima)" -#: ../main.c:2207 msgid "-R\t\t\tReadonly mode (like \"view\")" msgstr "-R\t\t\tNurlegebla reÄimo (kiel \"view\")" -#: ../main.c:2208 msgid "-Z\t\t\tRestricted mode (like \"rvim\")" msgstr "-Z\t\t\tLimigita reÄimo (kiel \"rvim\")" -#: ../main.c:2209 msgid "-m\t\t\tModifications (writing files) not allowed" msgstr "-m\t\t\tÅœanÄoj (skribo al dosieroj) nepermeseblaj" -#: ../main.c:2210 msgid "-M\t\t\tModifications in text not allowed" msgstr "-M\t\t\tÅœanÄoj al teksto nepermeseblaj" -#: ../main.c:2211 msgid "-b\t\t\tBinary mode" msgstr "-b\t\t\tDuuma reÄimo" -#: ../main.c:2212 msgid "-l\t\t\tLisp mode" msgstr "-l\t\t\tReÄimo Lisp" -#: ../main.c:2213 msgid "-C\t\t\tCompatible with Vi: 'compatible'" msgstr "-C\t\t\tKongrua kun Vi: 'compatible'" -#: ../main.c:2214 msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'" msgstr "-N\t\t\tNe tute kongrua kun Vi: 'nocompatible'" -#: ../main.c:2215 msgid "-V[N][fname]\t\tBe verbose [level N] [log messages to fname]" msgstr "" "-V[N][dosiernomo]\tEsti babilema [nivelo N] [konservi mesaÄojn al dosiernomo]" -#: ../main.c:2216 msgid "-D\t\t\tDebugging mode" msgstr "-D\t\t\tSencimiga reÄimo" -#: ../main.c:2217 msgid "-n\t\t\tNo swap file, use memory only" msgstr "-n\t\t\tNeniu permutodosiero .swp, uzas nur memoron" -#: ../main.c:2218 msgid "-r\t\t\tList swap files and exit" msgstr "-r\t\t\tListigi permutodosierojn .swp kaj eliri" -#: ../main.c:2219 msgid "-r (with file name)\tRecover crashed session" msgstr "-r (kun dosiernomo)\tRestaÅri kolapsintan seancon" -#: ../main.c:2220 msgid "-L\t\t\tSame as -r" msgstr "-L\t\t\tKiel -r" -#: ../main.c:2221 +msgid "-f\t\t\tDon't use newcli to open window" +msgstr "-f\t\t\tNe uzi newcli por malfermi fenestrojn" + +msgid "-dev <device>\t\tUse <device> for I/O" +msgstr "-dev <aparatdosiero>\t\tUzi <aparatdosiero>-n por eneligo" + msgid "-A\t\t\tstart in Arabic mode" msgstr "-A\t\t\tKomenci en araba reÄimo" -#: ../main.c:2222 msgid "-H\t\t\tStart in Hebrew mode" msgstr "-H\t\t\tKomenci en hebrea reÄimo" -#: ../main.c:2223 msgid "-F\t\t\tStart in Farsi mode" msgstr "-F\t\t\tKomenci en persa reÄimo" -#: ../main.c:2224 msgid "-T <terminal>\tSet terminal type to <terminal>" msgstr "-T <terminalo>\tAgordi terminalon al <terminalo>" -#: ../main.c:2225 +msgid "--not-a-term\t\tSkip warning for input/output not being a terminal" +msgstr "" +"--not-a-term\t\tPreterpasi averton por enigo/eligo, kiu ne estas terminalo" + +msgid "--ttyfail\t\tExit if input or output is not a terminal" +msgstr "" +"--ttyfail\t\tEliri se le eniro aÅ eliro ne estas terminalo" + msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc" msgstr "-u <vimrc>\t\tUzi <vimrc> anstataÅ iun ajn .vimrc" -#: ../main.c:2226 +msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" +msgstr "-U <gvimrc>\t\tUzi <gvimrc> anstataÅ iun ajn .gvimrc" + msgid "--noplugin\t\tDon't load plugin scripts" msgstr "--noplugin\t\tNe Åargi kromaĵajn skriptojn" -#: ../main.c:2227 msgid "-p[N]\t\tOpen N tab pages (default: one for each file)" msgstr "-p[N]\t\tMalfermi N langetojn (defaÅlto: po unu por ĉiu dosiero)" -#: ../main.c:2228 msgid "-o[N]\t\tOpen N windows (default: one for each file)" msgstr "-o[N]\t\tMalfermi N fenestrojn (defaÅlto: po unu por ĉiu dosiero)" -#: ../main.c:2229 msgid "-O[N]\t\tLike -o but split vertically" msgstr "-O[N]\t\tKiel -o sed dividi vertikale" -#: ../main.c:2230 msgid "+\t\t\tStart at end of file" msgstr "+\t\t\tKomenci ĉe la fino de la dosiero" -#: ../main.c:2231 msgid "+<lnum>\t\tStart at line <lnum>" msgstr "+<numL>\t\tKomenci ĉe linio <numL>" -#: ../main.c:2232 msgid "--cmd <command>\tExecute <command> before loading any vimrc file" msgstr "" "--cmd <komando>\tPlenumi <komando>-n antaÅ ol Åargi iun ajn dosieron vimrc" -#: ../main.c:2233 msgid "-c <command>\t\tExecute <command> after loading the first file" msgstr "-c <komando>\t\tPlenumi <komando>-n post kiam la unua dosiero ÅargiÄis" -#: ../main.c:2235 msgid "-S <session>\t\tSource file <session> after loading the first file" msgstr "" "-S <seanco>\t\tRuli dosieron <seanco>-n post kiam la unua dosiero ÅargiÄis" -#: ../main.c:2236 msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>" msgstr "-s <skripto>\t\tLegi komandojn en Normala reÄimo el dosiero <skripto>" -#: ../main.c:2237 msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>" msgstr "" "-w <eligaskripto>\tPostaldoni ĉiujn tajpitajn komandojn al dosiero " "<eligaskripto>" -#: ../main.c:2238 msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>" msgstr "" "-W <eligaskripto>\tSkribi ĉiujn tajpitajn komandojn al dosiero <eligaskripto>" -#: ../main.c:2240 +msgid "-x\t\t\tEdit encrypted files" +msgstr "-x\t\t\tRedakti ĉifradan dosieron" + +msgid "-display <display>\tConnect vim to this particular X-server" +msgstr "-display <ekrano>\tKonekti Vim al tiu X-servilo" + +msgid "-X\t\t\tDo not connect to X server" +msgstr "-X\t\t\tNe konekti al X-servilo" + +msgid "--remote <files>\tEdit <files> in a Vim server if possible" +msgstr "--remote <dosieroj>\tRedakti <dosieroj>-n en Vim-servilo se eblas" + +msgid "--remote-silent <files> Same, don't complain if there is no server" +msgstr "--remote-silent <dosieroj> Same, sed ne plendi se ne estas servilo" + +msgid "" +"--remote-wait <files> As --remote but wait for files to have been edited" +msgstr "" +"--remote-wait <dosieroj> Kiel --remote sed atendi Äis dosieroj estas " +"redaktitaj" + +msgid "" +"--remote-wait-silent <files> Same, don't complain if there is no server" +msgstr "" +"--remote-wait-silent <dosieroj> Same, sed ne plendi se ne estas servilo" + +msgid "" +"--remote-tab[-wait][-silent] <files> As --remote but use tab page per file" +msgstr "" +"--remote-tab[-wait][-silent] <dosieroj> Kiel --remote sed uzi langeton por " +"ĉiu dosiero" + +msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" +msgstr "--remote-send <klavoj> Sendi <klavoj>-n al Vim-servilo kaj eliri" + +msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" +msgstr "--remote-expr <espr>\tKomputi <espr> en Vim-servilo kaj afiÅi rezulton" + +msgid "--serverlist\t\tList available Vim server names and exit" +msgstr "--serverlist\t\tListigi haveblajn nomojn de Vim-serviloj kaj eliri" + +msgid "--servername <name>\tSend to/become the Vim server <name>" +msgstr "--servername <nomo>\tSendu al/iÄi la Vim-servilo <nomo>" + msgid "--startuptime <file>\tWrite startup timing messages to <file>" msgstr "" "--startuptime <dosiero> Skribi mesaÄojn de komenca tempomezurado al " "<dosiero>" -#: ../main.c:2242 msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo" msgstr "-i <viminfo>\t\tUzi <viminfo> anstataÅ .viminfo" -#: ../main.c:2243 msgid "-h or --help\tPrint Help (this message) and exit" msgstr "-h aÅ --help\tAfiÅi Helpon (tiun mesaÄon) kaj eliri" -#: ../main.c:2244 msgid "--version\t\tPrint version information and exit" msgstr "--version\t\tAfiÅi informon de versio kaj eliri" -#: ../mark.c:676 +msgid "" +"\n" +"Arguments recognised by gvim (Motif version):\n" +msgstr "" +"\n" +"Argumentoj agnoskitaj de gvim (versio Motif):\n" + +msgid "" +"\n" +"Arguments recognised by gvim (neXtaw version):\n" +msgstr "" +"\n" +"Argumentoj agnoskitaj de gvim (versio neXtaw):\n" + +msgid "" +"\n" +"Arguments recognised by gvim (Athena version):\n" +msgstr "" +"\n" +"Argumentoj agnoskitaj de gvim (versio Athena):\n" + +msgid "-display <display>\tRun vim on <display>" +msgstr "-display <ekrano>\tLanĉi vim sur <ekrano>" + +msgid "-iconic\t\tStart vim iconified" +msgstr "-iconic\t\tLanĉi vim piktograme" + +msgid "-background <color>\tUse <color> for the background (also: -bg)" +msgstr "-background <koloro>\tUzi <koloro>-n por la fona koloro (ankaÅ: -bg)" + +msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" +msgstr "" +"-foreground <koloro>\tUzi <koloro>-n por la malfona koloro (ankaÅ: -fg)" + +msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" +msgstr "-font <tiparo>\tUzi <tiparo>-n por normala teksto (ankaÅ: -fn)" + +msgid "-boldfont <font>\tUse <font> for bold text" +msgstr "-boldfont <tiparo>\tUzi <tiparo>-n por grasa teksto" + +msgid "-italicfont <font>\tUse <font> for italic text" +msgstr "-italicfont <tiparo>\tUzi <tiparo>-n por kursiva teksto" + +msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" +msgstr "-geometry <geom>\tUzi <geom> kiel komenca geometrio (ankaÅ: -geom)" + +msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" +msgstr "-borderwidth <larÄo>\tUzi <larÄo>-n kiel larÄo de bordero (ankaÅ: -bw)" + +msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" +msgstr "" +"-scrollbarwidth <larÄo> Uzi <larÄo>-n kiel larÄo de rulumskalo (ankaÅ: -sw)" + +msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" +msgstr "" +"-menuheight <alto>\tUzi <alto>-n kiel alto de menuzona alto (ankaÅ: -mh)" + +msgid "-reverse\t\tUse reverse video (also: -rv)" +msgstr "-reverse\t\tUzi inversan videon (ankaÅ: -rv)" + +msgid "+reverse\t\tDon't use reverse video (also: +rv)" +msgstr "+reverse\t\tNe uzi inversan videon (ankaÅ: +rv)" + +msgid "-xrm <resource>\tSet the specified resource" +msgstr "-xrm <rimedo>\tAgordi la specifitan <rimedo>-n" + +msgid "" +"\n" +"Arguments recognised by gvim (GTK+ version):\n" +msgstr "" +"\n" +"Argumentoj agnoskitaj de gvim (versio GTK+):\n" + +msgid "-display <display>\tRun vim on <display> (also: --display)" +msgstr "-display <ekrano>\tLanĉi Vim sur tiu <ekrano> (ankaÅ: --display)" + +msgid "--role <role>\tSet a unique role to identify the main window" +msgstr "--role <rolo>\tDoni unikan rolon por identigi la ĉefan fenestron" + +msgid "--socketid <xid>\tOpen Vim inside another GTK widget" +msgstr "--socketid <xid>\tMalfermi Vim en alia GTK fenestraĵo" + +msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" +msgstr "--echo-wid\t\tIgas gvim afiÅi la identigilon de vindozo sur stdout" + +msgid "-P <parent title>\tOpen Vim inside parent application" +msgstr "-P <gepatra titolo>\tMalfermi Vim en gepatra aplikaĵo" + +msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" +msgstr "--windowid <HWND>\tMalfermi Vim en alia win32 fenestraĵo" + +msgid "No display" +msgstr "Neniu ekrano" + +#. Failed to send, abort. +msgid ": Send failed.\n" +msgstr ": Sendo malsukcesis.\n" + +#. Let vim start normally. +msgid ": Send failed. Trying to execute locally\n" +msgstr ": Sendo malsukcesis. Provo de loka plenumo\n" + +#, c-format +msgid "%d of %d edited" +msgstr "%d de %d redaktita(j)" + +msgid "No display: Send expression failed.\n" +msgstr "Neniu ekrano: Sendado de esprimo malsukcesis.\n" + +msgid ": Send expression failed.\n" +msgstr ": Sendado de esprimo malsukcesis.\n" + msgid "No marks set" msgstr "Neniu marko" -#: ../mark.c:678 #, c-format msgid "E283: No marks matching \"%s\"" msgstr "E283: Neniu marko kongruas kun \"%s\"" #. Highlight title -#: ../mark.c:687 msgid "" "\n" "mark line col file/text" @@ -3634,7 +3305,6 @@ msgstr "" "mark linio kol dosiero/teksto" #. Highlight title -#: ../mark.c:789 msgid "" "\n" " jump line col file/text" @@ -3643,7 +3313,6 @@ msgstr "" " salt linio kol dosiero/teksto" #. Highlight title -#: ../mark.c:831 msgid "" "\n" "change line col text" @@ -3651,7 +3320,6 @@ msgstr "" "\n" "ÅanÄo linio kol teksto" -#: ../mark.c:1238 msgid "" "\n" "# File marks:\n" @@ -3660,7 +3328,6 @@ msgstr "" "# Markoj de dosiero:\n" #. Write the jumplist with -' -#: ../mark.c:1271 msgid "" "\n" "# Jumplist (newest first):\n" @@ -3668,7 +3335,6 @@ msgstr "" "\n" "# Saltlisto (plej novaj unue):\n" -#: ../mark.c:1352 msgid "" "\n" "# History of marks within files (newest to oldest):\n" @@ -3676,85 +3342,90 @@ msgstr "" "\n" "# Historio de markoj en dosieroj (de plej nova al plej malnova):\n" -#: ../mark.c:1431 msgid "Missing '>'" msgstr "Mankas '>'" -#: ../memfile.c:426 +msgid "E543: Not a valid codepage" +msgstr "E543: Nevalida kodpaÄo" + +msgid "E284: Cannot set IC values" +msgstr "E284: Ne eblas agordi valorojn de IC" + +msgid "E285: Failed to create input context" +msgstr "E285: Kreado de eniga kunteksto malsukcesis" + +msgid "E286: Failed to open input method" +msgstr "E286: Malfermo de eniga metodo malsukcesis" + +msgid "E287: Warning: Could not set destroy callback to IM" +msgstr "E287: Averto: Ne eblis agordi detruan reagfunkcion al IM" + +msgid "E288: input method doesn't support any style" +msgstr "E288: eniga metodo subtenas neniun stilon" + +# DP: mi ne scias, kio estas "preedit" +msgid "E289: input method doesn't support my preedit type" +msgstr "E289: eniga metodo ne subtenas mian antaÅredaktan tipon" + msgid "E293: block was not locked" msgstr "E293: bloko ne estis Ålosita" -#: ../memfile.c:799 msgid "E294: Seek error in swap file read" msgstr "E294: Eraro de enpoziciigo dum lego de permutodosiero .swp" -#: ../memfile.c:803 msgid "E295: Read error in swap file" msgstr "E295: Eraro de lego en permutodosiero .swp" -#: ../memfile.c:849 msgid "E296: Seek error in swap file write" msgstr "E296: Eraro de enpoziciigo dum skribo de permutodosiero .swp" -#: ../memfile.c:865 msgid "E297: Write error in swap file" msgstr "E297: Skriberaro en permutodosiero .swp" -#: ../memfile.c:1036 msgid "E300: Swap file already exists (symlink attack?)" msgstr "E300: Permutodosiero .swp jam ekzistas (ĉu atako per simbola ligilo?)" -#: ../memline.c:318 msgid "E298: Didn't get block nr 0?" msgstr "E298: Ĉu ne akiris blokon n-ro 0?" -#: ../memline.c:361 msgid "E298: Didn't get block nr 1?" msgstr "E298: Ĉu ne akiris blokon n-ro 1?" -#: ../memline.c:377 msgid "E298: Didn't get block nr 2?" msgstr "E298: Ĉu ne akiris blokon n-ro 2?" +msgid "E843: Error while updating swap file crypt" +msgstr "E843: Eraro dum Äisdatigo de ĉifrada permutodosiero .swp" + #. could not (re)open the swap file, what can we do???? -#: ../memline.c:465 msgid "E301: Oops, lost the swap file!!!" msgstr "E301: Ve, perdis la permutodosieron .swp!!!" -#: ../memline.c:477 msgid "E302: Could not rename swap file" msgstr "E302: Ne eblis renomi la permutodosieron .swp" -#: ../memline.c:554 #, c-format msgid "E303: Unable to open swap file for \"%s\", recovery impossible" msgstr "" "E303: Ne eblas malfermi permutodosieron .swp de \"%s\", restaÅro neeblas" -#: ../memline.c:666 msgid "E304: ml_upd_block0(): Didn't get block 0??" msgstr "E304: ml_upd_block0(): Ne akiris blokon 0??" -#. no swap files found -#: ../memline.c:830 #, c-format msgid "E305: No swap file found for %s" msgstr "E305: Neniu permutodosiero .swp trovita por %s" -#: ../memline.c:839 msgid "Enter number of swap file to use (0 to quit): " msgstr "Entajpu la uzendan numeron de permutodosiero .swp (0 por eliri): " -#: ../memline.c:879 #, c-format msgid "E306: Cannot open %s" msgstr "E306: Ne eblas malfermi %s" -#: ../memline.c:897 msgid "Unable to read block 0 from " msgstr "Ne eblas legi blokon 0 de " -#: ../memline.c:900 msgid "" "\n" "Maybe no changes were made or Vim did not update the swap file." @@ -3762,28 +3433,22 @@ msgstr "" "\n" "Eble neniu ÅanÄo estis farita aÅ Vim ne Äisdatigis la permutodosieron .swp." -#: ../memline.c:909 msgid " cannot be used with this version of Vim.\n" msgstr " ne uzeblas per tiu versio de vim.\n" -#: ../memline.c:911 msgid "Use Vim version 3.0.\n" msgstr "Uzu version 3.0 de Vim\n" -#: ../memline.c:916 #, c-format msgid "E307: %s does not look like a Vim swap file" msgstr "E307: %s ne aspektas kiel permutodosiero .swp de Vim" -#: ../memline.c:922 msgid " cannot be used on this computer.\n" msgstr " ne uzeblas per tiu komputilo.\n" -#: ../memline.c:924 msgid "The file was created on " msgstr "La dosiero estas kreita je " -#: ../memline.c:928 msgid "" ",\n" "or the file has been damaged." @@ -3791,85 +3456,104 @@ msgstr "" ",\n" "aÅ la dosiero estas difekta." -#: ../memline.c:945 +#, c-format +msgid "" +"E833: %s is encrypted and this version of Vim does not support encryption" +msgstr "E833: %s estas ĉifrata kaj tiu versio de Vim ne subtenas ĉifradon" + msgid " has been damaged (page size is smaller than minimum value).\n" msgstr " difektiÄis (paÄa grando pli malgranda ol minimuma valoro).\n" -#: ../memline.c:974 #, c-format msgid "Using swap file \"%s\"" msgstr "Uzado de permutodosiero .swp \"%s\"" -#: ../memline.c:980 #, c-format msgid "Original file \"%s\"" msgstr "Originala dosiero \"%s\"" -#: ../memline.c:995 msgid "E308: Warning: Original file may have been changed" msgstr "E308: Averto: Originala dosiero eble ÅanÄiÄis" -#: ../memline.c:1061 +#, c-format +msgid "Swap file is encrypted: \"%s\"" +msgstr "Perumutodosiero .swp estas ĉifrata: \"%s\"" + +msgid "" +"\n" +"If you entered a new crypt key but did not write the text file," +msgstr "" +"\n" +"Se vi tajpis novan Ålosilon de ĉifrado sed ne skribis la tekstan dosieron," + +msgid "" +"\n" +"enter the new crypt key." +msgstr "" +"\n" +"tajpu la novan Ålosilon de ĉifrado." + +msgid "" +"\n" +"If you wrote the text file after changing the crypt key press enter" +msgstr "" +"\n" +"Se vi skribis la tekstan dosieron post ÅanÄo de la Ålosilo de ĉifrado, premu " +"enenklavon" + +msgid "" +"\n" +"to use the same key for text file and swap file" +msgstr "" +"\n" +"por uzi la saman Ålosilon por la teksta dosiero kaj permuto dosiero .swp" + #, c-format msgid "E309: Unable to read block 1 from %s" msgstr "E309: Ne eblas legi blokon 1 de %s" -#: ../memline.c:1065 msgid "???MANY LINES MISSING" msgstr "???MULTAJ LINIOJ MANKAS" -#: ../memline.c:1076 msgid "???LINE COUNT WRONG" msgstr "???NOMBRO DE LINIOJ NE ÄœUSTAS" -#: ../memline.c:1082 msgid "???EMPTY BLOCK" msgstr "???MALPLENA BLOKO" -#: ../memline.c:1103 msgid "???LINES MISSING" msgstr "???LINIOJ MANKANTAJ" -#: ../memline.c:1128 #, c-format msgid "E310: Block 1 ID wrong (%s not a .swp file?)" msgstr "" "E310: Nevalida identigilo de bloko 1 (ĉu %s ne estas permutodosiero .swp?)" -#: ../memline.c:1133 msgid "???BLOCK MISSING" msgstr "???MANKAS BLOKO" -#: ../memline.c:1147 msgid "??? from here until ???END lines may be messed up" msgstr "??? ekde tie Äis ???FINO linioj estas eble difektaj" -#: ../memline.c:1164 msgid "??? from here until ???END lines may have been inserted/deleted" msgstr "??? ekde tie Äis ???FINO linioj estas eble enmetitaj/forviÅitaj" -#: ../memline.c:1181 msgid "???END" msgstr "???FINO" -#: ../memline.c:1238 msgid "E311: Recovery Interrupted" msgstr "E311: RestaÅro interrompita" -#: ../memline.c:1243 msgid "" "E312: Errors detected while recovering; look for lines starting with ???" msgstr "E312: Eraroj dum restaÅro; rigardu liniojn komencantajn per ???" -#: ../memline.c:1245 msgid "See \":help E312\" for more information." msgstr "Vidu \":help E312\" por pliaj informoj." -#: ../memline.c:1249 msgid "Recovery completed. You should check if everything is OK." msgstr "RestaÅro finiÄis. Indus kontroli ĉu ĉio estas en ordo." -#: ../memline.c:1251 msgid "" "\n" "(You might want to write out this file under another name\n" @@ -3877,16 +3561,13 @@ msgstr "" "\n" "(Indas konservi tiun dosieron per alia nomo\n" -#: ../memline.c:1252 msgid "and run diff with the original file to check for changes)" msgstr "kaj lanĉi diff kun la originala dosiero por kontroli la ÅanÄojn)" -#: ../memline.c:1254 msgid "Recovery completed. Buffer contents equals file contents." msgstr "" "RestaÅro finiÄis. La enhavo de la bufro samas kun la enhavo de la dosiero." -#: ../memline.c:1255 msgid "" "\n" "You may want to delete the .swp file now.\n" @@ -3896,52 +3577,44 @@ msgstr "" "La dosiero .swp nun forviÅindas.\n" "\n" +msgid "Using crypt key from swap file for the text file.\n" +msgstr "" +"Uzas Ålosilon de ĉifrado el permuto dosiero .swp por la teksta dosiero.\n" + #. use msg() to start the scrolling properly -#: ../memline.c:1327 msgid "Swap files found:" msgstr "Permutodosiero .swp trovita:" -#: ../memline.c:1446 msgid " In current directory:\n" msgstr " En la aktuala dosierujo:\n" -#: ../memline.c:1448 msgid " Using specified name:\n" msgstr " Uzado de specifita nomo:\n" -#: ../memline.c:1450 msgid " In directory " msgstr " En dosierujo " -#: ../memline.c:1465 msgid " -- none --\n" msgstr " -- nenio --\n" -#: ../memline.c:1527 msgid " owned by: " msgstr " posedata de: " -#: ../memline.c:1529 msgid " dated: " msgstr " dato: " -#: ../memline.c:1532 ../memline.c:3231 msgid " dated: " msgstr " dato: " -#: ../memline.c:1548 msgid " [from Vim version 3.0]" msgstr " [de Vim versio 3.0]" -#: ../memline.c:1550 msgid " [does not look like a Vim swap file]" msgstr " [ne aspektas kiel permutodosiero .swp de Vim]" -#: ../memline.c:1552 msgid " file name: " msgstr " dosiernomo: " -#: ../memline.c:1558 msgid "" "\n" " modified: " @@ -3949,15 +3622,12 @@ msgstr "" "\n" " modifita: " -#: ../memline.c:1559 msgid "YES" msgstr "JES" -#: ../memline.c:1559 msgid "no" msgstr "ne" -#: ../memline.c:1562 msgid "" "\n" " user name: " @@ -3965,11 +3635,9 @@ msgstr "" "\n" " uzantonomo: " -#: ../memline.c:1568 msgid " host name: " msgstr " komputila nomo: " -#: ../memline.c:1570 msgid "" "\n" " host name: " @@ -3977,7 +3645,6 @@ msgstr "" "\n" " komputila nomo: " -#: ../memline.c:1575 msgid "" "\n" " process ID: " @@ -3985,11 +3652,16 @@ msgstr "" "\n" " proceza ID: " -#: ../memline.c:1579 msgid " (still running)" msgstr " (ankoraÅ ruliÄas)" -#: ../memline.c:1586 +msgid "" +"\n" +" [not usable with this version of Vim]" +msgstr "" +"\n" +" [ne uzebla per tiu versio de Vim]" + msgid "" "\n" " [not usable on this computer]" @@ -3997,97 +3669,75 @@ msgstr "" "\n" " [neuzebla per tiu komputilo]" -#: ../memline.c:1590 msgid " [cannot be read]" msgstr " [nelegebla]" -#: ../memline.c:1593 msgid " [cannot be opened]" msgstr " [nemalfermebla]" -#: ../memline.c:1698 msgid "E313: Cannot preserve, there is no swap file" msgstr "E313: Ne eblas konservi, ne estas permutodosiero .swp" -#: ../memline.c:1747 msgid "File preserved" msgstr "Dosiero konservita" -#: ../memline.c:1749 msgid "E314: Preserve failed" -msgstr "E314: Konservo fiaskis" +msgstr "E314: Konservo malsukcesis" -#: ../memline.c:1819 #, c-format -msgid "E315: ml_get: invalid lnum: %<PRId64>" -msgstr "E315: ml_get: nevalida lnum: %<PRId64>" +msgid "E315: ml_get: invalid lnum: %ld" +msgstr "E315: ml_get: nevalida lnum: %ld" -#: ../memline.c:1851 #, c-format -msgid "E316: ml_get: cannot find line %<PRId64>" -msgstr "E316: ml_get: ne eblas trovi linion %<PRId64>" +msgid "E316: ml_get: cannot find line %ld" +msgstr "E316: ml_get: ne eblas trovi linion %ld" -#: ../memline.c:2236 msgid "E317: pointer block id wrong 3" msgstr "E317: nevalida referenco de bloko id 3" -#: ../memline.c:2311 msgid "stack_idx should be 0" msgstr "stack_idx devus esti 0" -#: ../memline.c:2369 msgid "E318: Updated too many blocks?" msgstr "E318: Ĉu Äisdatigis tro da blokoj?" -#: ../memline.c:2511 msgid "E317: pointer block id wrong 4" msgstr "E317: nevalida referenco de bloko id 4" -#: ../memline.c:2536 msgid "deleted block 1?" msgstr "ĉu forviÅita bloko 1?" -#: ../memline.c:2707 #, c-format -msgid "E320: Cannot find line %<PRId64>" -msgstr "E320: Ne eblas trovi linion %<PRId64>" +msgid "E320: Cannot find line %ld" +msgstr "E320: Ne eblas trovi linion %ld" -#: ../memline.c:2916 msgid "E317: pointer block id wrong" msgstr "E317: nevalida referenco de bloko id" -#: ../memline.c:2930 msgid "pe_line_count is zero" msgstr "pe_line_count estas nul" -#: ../memline.c:2955 #, c-format -msgid "E322: line number out of range: %<PRId64> past the end" -msgstr "E322: numero de linio ekster limoj: %<PRId64> preter la fino" +msgid "E322: line number out of range: %ld past the end" +msgstr "E322: numero de linio ekster limoj: %ld preter la fino" -#: ../memline.c:2959 #, c-format -msgid "E323: line count wrong in block %<PRId64>" -msgstr "E323: nevalida nombro de linioj en bloko %<PRId64>" +msgid "E323: line count wrong in block %ld" +msgstr "E323: nevalida nombro de linioj en bloko %ld" -#: ../memline.c:2999 msgid "Stack size increases" msgstr "Stako pligrandiÄas" -#: ../memline.c:3038 msgid "E317: pointer block id wrong 2" msgstr "E317: nevalida referenco de bloko id 2" -#: ../memline.c:3070 #, c-format msgid "E773: Symlink loop for \"%s\"" msgstr "E773: Buklo de simbolaj ligiloj por \"%s\"" -#: ../memline.c:3221 msgid "E325: ATTENTION" msgstr "E325: ATENTO" -#: ../memline.c:3222 msgid "" "\n" "Found a swap file by the name \"" @@ -4095,15 +3745,14 @@ msgstr "" "\n" "Trovis permutodosieron .swp kun la nomo \"" -#: ../memline.c:3226 msgid "While opening file \"" msgstr "Dum malfermo de dosiero \"" -#: ../memline.c:3239 msgid " NEWER than swap file!\n" msgstr " PLI NOVA ol permutodosiero .swp!\n" -#: ../memline.c:3244 +#. Some of these messages are long to allow translation to +#. * other languages. msgid "" "\n" "(1) Another program may be editing the same file. If this is the case,\n" @@ -4115,19 +3764,12 @@ msgstr "" " por ne havi du malsamajn aperojn de la sama dosiero, kiam vi faros\n" " ÅanÄojn. Eliru aÅ daÅrigu singarde.\n" -#: ../memline.c:3245 -msgid " Quit, or continue with caution.\n" -msgstr " Eliru, aÅ daÅrigu singarde.\n" - -#: ../memline.c:3246 msgid "(2) An edit session for this file crashed.\n" msgstr "(2) Redakta seanco de tiu dosiero kolapsis.\n" -#: ../memline.c:3247 msgid " If this is the case, use \":recover\" or \"vim -r " msgstr " Se veras, uzu \":recover\" aÅ \"vim -r " -#: ../memline.c:3249 msgid "" "\"\n" " to recover the changes (see \":help recovery\").\n" @@ -4135,11 +3777,9 @@ msgstr "" "\"\n" " por restaÅri la ÅanÄojn (vidu \":help recovery\").\n" -#: ../memline.c:3250 msgid " If you did this already, delete the swap file \"" msgstr " Se vi jam faris Äin, forviÅu la permutodosieron .swp \"" -#: ../memline.c:3252 msgid "" "\"\n" " to avoid this message.\n" @@ -4147,25 +3787,20 @@ msgstr "" "\"\n" " por eviti tiun mesaÄon.\n" -#: ../memline.c:3450 ../memline.c:3452 msgid "Swap file \"" msgstr "Permutodosiero .swp \"" -#: ../memline.c:3451 ../memline.c:3455 msgid "\" already exists!" msgstr "\" jam ekzistas!" -#: ../memline.c:3457 msgid "VIM - ATTENTION" msgstr "VIM - ATENTO" -#: ../memline.c:3459 msgid "Swap file already exists!" msgstr "Permutodosiero .swp jam ekzistas!" # AM: ĉu Vim konvertos la unuliterajn respondojn de la uzulo? # DP: jes, la '&' respondoj bone funkcias (mi kontrolis) -#: ../memline.c:3464 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4179,7 +3814,6 @@ msgstr "" "&Eliri\n" "Ĉe&sigi" -#: ../memline.c:3467 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4195,56 +3829,34 @@ msgstr "" "&Eliri\n" "Ĉe&sigi" -#. -#. * Change the ".swp" extension to find another file that can be used. -#. * First decrement the last char: ".swo", ".swn", etc. -#. * If that still isn't enough decrement the last but one char: ".svz" -#. * Can happen when editing many "No Name" buffers. -#. -#. ".s?a" -#. ".saa": tried enough, give up -#: ../memline.c:3528 msgid "E326: Too many swap files found" msgstr "E326: Tro da dosieroj trovitaj" -#: ../memory.c:227 -#, c-format -msgid "E342: Out of memory! (allocating %<PRIu64> bytes)" -msgstr "E342: Ne plu restas memoro! (disponigo de %<PRIu64> bajtoj)" - -#: ../menu.c:62 msgid "E327: Part of menu-item path is not sub-menu" msgstr "E327: Parto de vojo de menuero ne estas sub-menuo" -#: ../menu.c:63 msgid "E328: Menu only exists in another mode" msgstr "E328: Menuo nur ekzistas en alia reÄimo" -#: ../menu.c:64 #, c-format msgid "E329: No menu \"%s\"" msgstr "E329: Neniu menuo \"%s\"" #. Only a mnemonic or accelerator is not valid. -#: ../menu.c:329 msgid "E792: Empty menu name" msgstr "E792: Malplena nomo de menuo" -#: ../menu.c:340 msgid "E330: Menu path must not lead to a sub-menu" msgstr "E330: Vojo de menuo ne rajtas konduki al sub-menuo" -#: ../menu.c:365 msgid "E331: Must not add menu items directly to menu bar" msgstr "E331: Aldono de menueroj direkte al menuzono estas malpermesita" -#: ../menu.c:370 msgid "E332: Separator cannot be part of a menu path" msgstr "E332: Disigilo ne rajtas esti ero de vojo de menuo" #. Now we have found the matching menu, and we list the mappings #. Highlight title -#: ../menu.c:762 msgid "" "\n" "--- Menus ---" @@ -4252,69 +3864,60 @@ msgstr "" "\n" "--- Menuoj ---" -#: ../menu.c:1313 +msgid "Tear off this menu" +msgstr "Disigi tiun menuon" + msgid "E333: Menu path must lead to a menu item" msgstr "E333: Vojo de menuo devas konduki al menuero" -#: ../menu.c:1330 #, c-format msgid "E334: Menu not found: %s" msgstr "E334: Menuo netrovita: %s" -#: ../menu.c:1396 #, c-format msgid "E335: Menu not defined for %s mode" msgstr "E335: Menuo ne estas difinita por reÄimo %s" -#: ../menu.c:1426 msgid "E336: Menu path must lead to a sub-menu" msgstr "E336: Vojo de menuo devas konduki al sub-menuo" -#: ../menu.c:1447 msgid "E337: Menu not found - check menu names" msgstr "E337: Menuo ne trovita - kontrolu nomojn de menuoj" -#: ../message.c:423 #, c-format msgid "Error detected while processing %s:" msgstr "Eraro okazis dum traktado de %s:" -#: ../message.c:445 #, c-format msgid "line %4ld:" msgstr "linio %4ld:" -#: ../message.c:617 #, c-format msgid "E354: Invalid register name: '%s'" msgstr "E354: Nevalida nomo de reÄistro: '%s'" -#: ../message.c:986 +msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>" +msgstr "Flegado de mesaÄoj: Dominique PELLÉ <dominique.pelle@gmail.com>" + msgid "Interrupt: " msgstr "Interrompo: " -#: ../message.c:988 msgid "Press ENTER or type command to continue" msgstr "Premu ENEN-KLAVON aÅ tajpu komandon por daÅrigi" -#: ../message.c:1843 #, c-format -msgid "%s line %<PRId64>" -msgstr "%s linio %<PRId64>" +msgid "%s line %ld" +msgstr "%s linio %ld" -#: ../message.c:2392 msgid "-- More --" msgstr "-- Pli --" -#: ../message.c:2398 msgid " SPACE/d/j: screen/page/line down, b/u/k: up, q: quit " msgstr " SPACETO/d/j: ekrano/paÄo/sub linio, b/u/k: supre, q: eliri " -#: ../message.c:3021 ../message.c:3031 msgid "Question" msgstr "Demando" -#: ../message.c:3023 msgid "" "&Yes\n" "&No" @@ -4322,19 +3925,8 @@ msgstr "" "&Jes\n" "&Ne" -#: ../message.c:3033 -msgid "" -"&Yes\n" -"&No\n" -"&Cancel" -msgstr "" -"&Jes\n" -"&Ne\n" -"&Rezigni" - # AM: ĉu Vim konvertos unuliterajn respondojn? # DP: jes, '&' bone funkcias (mi kontrolis) -#: ../message.c:3045 msgid "" "&Yes\n" "&No\n" @@ -4348,175 +3940,249 @@ msgstr "" "&Forlasi Ĉion\n" "&Rezigni" -#: ../message.c:3058 +msgid "Select Directory dialog" +msgstr "Dialogujo de dosiera elekto" + +msgid "Save File dialog" +msgstr "Dialogujo de dosiera konservo" + +msgid "Open File dialog" +msgstr "Dialogujo de dosiera malfermo" + +#. TODO: non-GUI file selector here +msgid "E338: Sorry, no file browser in console mode" +msgstr "E338: BedaÅrinde ne estas dosierfoliumilo en konzola reÄimo" + msgid "E766: Insufficient arguments for printf()" msgstr "E766: Ne sufiĉaj argumentoj por printf()" -#: ../message.c:3119 msgid "E807: Expected Float argument for printf()" -msgstr "E807: Atendis Glitpunktnombron kiel argumento de printf()" +msgstr "E807: Atendis Glitpunktnombron kiel argumenton de printf()" -#: ../message.c:3873 msgid "E767: Too many arguments to printf()" msgstr "E767: Tro da argumentoj al printf()" -#: ../misc1.c:2256 msgid "W10: Warning: Changing a readonly file" msgstr "W10: Averto: ÅœanÄo de nurlegebla dosiero" -#: ../misc1.c:2537 msgid "Type number and <Enter> or click with mouse (empty cancels): " msgstr "" "Tajpu nombron kaj <Enenklavon> aÅ alklaku per la muso (malpleno rezignas): " -#: ../misc1.c:2539 msgid "Type number and <Enter> (empty cancels): " msgstr "Tajpu nombron kaj <Enenklavon> (malpleno rezignas): " -#: ../misc1.c:2585 msgid "1 more line" msgstr "1 plia linio" -#: ../misc1.c:2588 msgid "1 line less" msgstr "1 malplia linio" -#: ../misc1.c:2593 #, c-format -msgid "%<PRId64> more lines" -msgstr "%<PRId64> pliaj linioj" +msgid "%ld more lines" +msgstr "%ld pliaj linioj" -#: ../misc1.c:2596 #, c-format -msgid "%<PRId64> fewer lines" -msgstr "%<PRId64> malpliaj linioj" +msgid "%ld fewer lines" +msgstr "%ld malpliaj linioj" -#: ../misc1.c:2599 msgid " (Interrupted)" msgstr " (Interrompita)" -#: ../misc1.c:2635 msgid "Beep!" msgstr "Bip!" -#: ../misc2.c:738 +msgid "ERROR: " +msgstr "ERARO: " + +#, c-format +msgid "" +"\n" +"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n" +msgstr "" +"\n" +"[bajtoj] totalaj disponigitaj/maldisponigitaj %lu-%lu, nun uzataj %lu, " +"kulmina uzo %lu\n" + +#, c-format +msgid "" +"[calls] total re/malloc()'s %lu, total free()'s %lu\n" +"\n" +msgstr "" +"[alvokoj] totalaj re/malloc() %lu, totalaj free() %lu\n" +"\n" + +msgid "E340: Line is becoming too long" +msgstr "E340: Linio iÄas tro longa" + +#, c-format +msgid "E341: Internal error: lalloc(%ld, )" +msgstr "E341: Interna eraro: lalloc(%ld, )" + +#, c-format +msgid "E342: Out of memory! (allocating %lu bytes)" +msgstr "E342: Ne plu restas memoro! (disponigo de %lu bajtoj)" + #, c-format msgid "Calling shell to execute: \"%s\"" msgstr "Alvokas Åelon por plenumi: \"%s\"" -#: ../normal.c:183 +msgid "E545: Missing colon" +msgstr "E545: Mankas dupunkto" + +msgid "E546: Illegal mode" +msgstr "E546: ReÄimo nepermesata" + +msgid "E547: Illegal mouseshape" +msgstr "E547: Nevalida formo de muskursoro" + +msgid "E548: digit expected" +msgstr "E548: cifero atendata" + +msgid "E549: Illegal percentage" +msgstr "E549: Nevalida procento" + +msgid "E854: path too long for completion" +msgstr "E854: tro longa vojo por kompletigo" + +#, c-format +msgid "" +"E343: Invalid path: '**[number]' must be at the end of the path or be " +"followed by '%s'." +msgstr "" +"E343: Nevalida vojo: '**[nombro]' devas esti ĉe la fino de la vojo aÅ " +"sekvita de '%s'." + +#, c-format +msgid "E344: Can't find directory \"%s\" in cdpath" +msgstr "E344: Ne eblas trovi dosierujon \"%s\" en cdpath" + +#, c-format +msgid "E345: Can't find file \"%s\" in path" +msgstr "E345: Ne eblas trovi dosieron \"%s\" en serĉvojo" + +#, c-format +msgid "E346: No more directory \"%s\" found in cdpath" +msgstr "E346: Ne plu trovis dosierujon \"%s\" en cdpath" + +#, c-format +msgid "E347: No more file \"%s\" found in path" +msgstr "E347: Ne plu trovis dosieron \"%s\" en serĉvojo" + +#, c-format +msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" +msgstr "" +"E668: Nevalida permeso de dosiero de informo de konekto NetBeans: \"%s\"" + +#, c-format +msgid "E658: NetBeans connection lost for buffer %ld" +msgstr "E658: Konekto de NetBeans perdita por bufro %ld" + +msgid "E838: netbeans is not supported with this GUI" +msgstr "E838: netbeans ne estas subtenata kun tiu grafika interfaco" + +msgid "E511: netbeans already connected" +msgstr "E511: nebeans jam konektata" + +#, c-format +msgid "E505: %s is read-only (add ! to override)" +msgstr "E505: %s estas nurlegebla (aldonu ! por transpasi)" + msgid "E349: No identifier under cursor" msgstr "E349: Neniu identigilo sub la kursoro" -#: ../normal.c:1866 msgid "E774: 'operatorfunc' is empty" msgstr "E774: 'operatorfunc' estas malplena" -#: ../normal.c:2637 +# DP: ĉu Eval devas esti tradukita? +msgid "E775: Eval feature not available" +msgstr "E775: Eval eblo ne disponeblas" + msgid "Warning: terminal cannot highlight" msgstr "Averto: terminalo ne povas emfazi" -#: ../normal.c:2807 msgid "E348: No string under cursor" msgstr "E348: Neniu ĉeno sub la kursoro" -#: ../normal.c:3937 msgid "E352: Cannot erase folds with current 'foldmethod'" msgstr "E352: Ne eblas forviÅi faldon per aktuala 'foldmethod'" -#: ../normal.c:5897 msgid "E664: changelist is empty" msgstr "E664: Listo de ÅanÄoj estas malplena" -#: ../normal.c:5899 msgid "E662: At start of changelist" msgstr "E662: Ĉe komenco de ÅanÄlisto" -#: ../normal.c:5901 msgid "E663: At end of changelist" msgstr "E663: Ĉe fino de ÅanÄlisto" -#: ../normal.c:7053 -msgid "Type :quit<Enter> to exit Nvim" +msgid "Type :quit<Enter> to exit Vim" msgstr "Tajpu \":quit<Enenklavo>\" por eliri el Vim" -#: ../ops.c:248 #, c-format msgid "1 line %sed 1 time" msgstr "1 linio %sita 1 foje" -#: ../ops.c:250 #, c-format msgid "1 line %sed %d times" msgstr "1 linio %sita %d foje" -#: ../ops.c:253 #, c-format -msgid "%<PRId64> lines %sed 1 time" -msgstr "%<PRId64> linio %sita 1 foje" +msgid "%ld lines %sed 1 time" +msgstr "%ld linio %sita 1 foje" -#: ../ops.c:256 #, c-format -msgid "%<PRId64> lines %sed %d times" -msgstr "%<PRId64> linioj %sitaj %d foje" +msgid "%ld lines %sed %d times" +msgstr "%ld linioj %sitaj %d foje" -#: ../ops.c:592 #, c-format -msgid "%<PRId64> lines to indent... " -msgstr "%<PRId64> krommarÄenendaj linioj... " +msgid "%ld lines to indent... " +msgstr "%ld krommarÄenendaj linioj... " -#: ../ops.c:634 msgid "1 line indented " msgstr "1 linio krommarÄenita " -#: ../ops.c:636 #, c-format -msgid "%<PRId64> lines indented " -msgstr "%<PRId64> linioj krommarÄenitaj " +msgid "%ld lines indented " +msgstr "%ld linioj krommarÄenitaj " -#: ../ops.c:938 msgid "E748: No previously used register" msgstr "E748: Neniu reÄistro antaÅe uzata" #. must display the prompt -#: ../ops.c:1433 msgid "cannot yank; delete anyway" -msgstr "ne eblas kopii; forviÅi tamene" +msgstr "ne eblas kopii; tamen forviÅi" -#: ../ops.c:1929 msgid "1 line changed" msgstr "1 linio ÅanÄita" -#: ../ops.c:1931 #, c-format -msgid "%<PRId64> lines changed" -msgstr "%<PRId64> linioj ÅanÄitaj" +msgid "%ld lines changed" +msgstr "%ld linioj ÅanÄitaj" + +#, c-format +msgid "freeing %ld lines" +msgstr "malokupas %ld liniojn" -#: ../ops.c:2521 msgid "block of 1 line yanked" msgstr "bloko de 1 linio kopiita" -#: ../ops.c:2523 msgid "1 line yanked" msgstr "1 linio kopiita" -#: ../ops.c:2525 #, c-format -msgid "block of %<PRId64> lines yanked" -msgstr "bloko de %<PRId64> linioj kopiita" +msgid "block of %ld lines yanked" +msgstr "bloko de %ld linioj kopiita" -#: ../ops.c:2528 #, c-format -msgid "%<PRId64> lines yanked" -msgstr "%<PRId64> linioj kopiitaj" +msgid "%ld lines yanked" +msgstr "%ld linioj kopiitaj" -#: ../ops.c:2710 #, c-format msgid "E353: Nothing in register %s" msgstr "E353: Nenio en reÄistro %s" #. Highlight title -#: ../ops.c:3185 msgid "" "\n" "--- Registers ---" @@ -4524,11 +4190,9 @@ msgstr "" "\n" "--- ReÄistroj ---" -#: ../ops.c:4455 msgid "Illegal register name" msgstr "Nevalida nomo de reÄistro" -#: ../ops.c:4533 msgid "" "\n" "# Registers:\n" @@ -4536,186 +4200,173 @@ msgstr "" "\n" "# ReÄistroj:\n" -#: ../ops.c:4575 #, c-format msgid "E574: Unknown register type %d" msgstr "E574: Nekonata tipo de reÄistro %d" -#: ../ops.c:5089 +msgid "" +"E883: search pattern and expression register may not contain two or more " +"lines" +msgstr "" +"E883: serĉa Åablono kaj esprima reÄistro ne povas enhavi du aÅ pliajn liniojn" + #, c-format -msgid "%<PRId64> Cols; " -msgstr "%<PRId64> Kolumnoj; " +msgid "%ld Cols; " +msgstr "%ld Kolumnoj; " -#: ../ops.c:5097 #, c-format -msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Bytes" +msgid "Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Bytes" msgstr "" -"Apartigis %s%<PRId64> de %<PRId64> Linioj; %<PRId64> de %<PRId64> Vortoj; " -"%<PRId64> de %<PRId64> Bajtoj" +"Apartigis %s%ld de %ld Linioj; %lld de %lld Vortoj; %lld de %lld Bajtoj" -#: ../ops.c:5105 #, c-format msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Chars; %<PRId64> of %<PRId64> Bytes" +"Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Chars; %lld of " +"%lld Bytes" msgstr "" -"Apartigis %s%<PRId64> de %<PRId64> Linioj; %<PRId64> de %<PRId64> Vortoj; " -"%<PRId64> de %<PRId64> Signoj; %<PRId64> de %<PRId64> Bajtoj" +"Apartigis %s%ld de %ld Linioj; %lld de %lld Vortoj; %lld de %lld Signoj; " +"%lld de %lld Bajtoj" -#: ../ops.c:5123 #, c-format -msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Byte " -"%<PRId64> of %<PRId64>" -msgstr "" -"Kol %s de %s; Linio %<PRId64> de %<PRId64>; Vorto %<PRId64> de %<PRId64>; " -"Bajto %<PRId64> de %<PRId64>" +msgid "Col %s of %s; Line %ld of %ld; Word %lld of %lld; Byte %lld of %lld" +msgstr "Kol %s de %s; Linio %ld de %ld; Vorto %lld de %lld; Bajto %lld de %lld" -#: ../ops.c:5133 #, c-format msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Char " -"%<PRId64> of %<PRId64>; Byte %<PRId64> of %<PRId64>" +"Col %s of %s; Line %ld of %ld; Word %lld of %lld; Char %lld of %lld; Byte " +"%lld of %lld" msgstr "" -"Kol %s de %s; Linio %<PRId64> de %<PRId64>; Vorto %<PRId64> de %<PRId64>; " -"Signo %<PRId64> de %<PRId64>; Bajto %<PRId64> de %<PRId64>" +"Kol %s de %s; Linio %ld de %ld; Vorto %lld de %lld; Signo %lld de %lld; " +"Bajto %lld de %lld" -#: ../ops.c:5146 #, c-format -msgid "(+%<PRId64> for BOM)" -msgstr "(+%<PRId64> por BOM)" +msgid "(+%ld for BOM)" +msgstr "(+%ld por BOM)" -#: ../option.c:1238 msgid "%<%f%h%m%=Page %N" msgstr "%<%f%h%m%=Folio %N" -#: ../option.c:1574 msgid "Thanks for flying Vim" msgstr "Dankon pro flugi per Vim" -#. found a mismatch: skip -#: ../option.c:2698 msgid "E518: Unknown option" msgstr "E518: Nekonata opcio" -#: ../option.c:2709 msgid "E519: Option not supported" msgstr "E519: Opcio ne subtenata" -#: ../option.c:2740 msgid "E520: Not allowed in a modeline" msgstr "E520: Nepermesebla en reÄimlinio" -#: ../option.c:2815 msgid "E846: Key code not set" msgstr "E846: Klavkodo ne agordita" -#: ../option.c:2924 msgid "E521: Number required after =" msgstr "E521: Nombro bezonata post =" -#: ../option.c:3226 ../option.c:3864 msgid "E522: Not found in termcap" msgstr "E522: Netrovita en termcap" -#: ../option.c:3335 #, c-format msgid "E539: Illegal character <%s>" msgstr "E539: Nevalida signo <%s>" -#: ../option.c:2253 #, c-format msgid "For option %s" msgstr "Por opcio %s" -#: ../option.c:3862 msgid "E529: Cannot set 'term' to empty string" msgstr "E529: Ne eblas agordi 'term' al malplena ĉeno" -#: ../option.c:3885 +msgid "E530: Cannot change term in GUI" +msgstr "E530: term ne ÅanÄeblas en grafika interfaco" + +msgid "E531: Use \":gui\" to start the GUI" +msgstr "E531: Uzu \":gui\" por lanĉi la grafikan interfacon" + msgid "E589: 'backupext' and 'patchmode' are equal" msgstr "E589: 'backupext' kaj 'patchmode' estas egalaj" -#: ../option.c:3964 msgid "E834: Conflicts with value of 'listchars'" msgstr "E834: Konfliktoj kun la valoro de 'listchars'" -#: ../option.c:3966 msgid "E835: Conflicts with value of 'fillchars'" msgstr "E835: Konfliktoj kun la valoro de 'fillchars'" -#: ../option.c:4163 +msgid "E617: Cannot be changed in the GTK+ 2 GUI" +msgstr "E617: Ne ÅanÄeblas en la grafika interfaco GTK+ 2" + msgid "E524: Missing colon" msgstr "E524: Mankas dupunkto" -#: ../option.c:4165 msgid "E525: Zero length string" msgstr "E525: Ĉeno de nula longo" -#: ../option.c:4220 #, c-format msgid "E526: Missing number after <%s>" msgstr "E526: Mankas nombro post <%s>" -#: ../option.c:4232 msgid "E527: Missing comma" msgstr "E527: Mankas komo" -#: ../option.c:4239 msgid "E528: Must specify a ' value" msgstr "E528: Devas specifi ' valoron" -#: ../option.c:4271 msgid "E595: contains unprintable or wide character" msgstr "E595: enhavas nepreseblan aÅ plurĉellarÄan signon" -#: ../option.c:4469 +msgid "E596: Invalid font(s)" +msgstr "E596: Nevalida(j) tiparo(j)" + +msgid "E597: can't select fontset" +msgstr "E597: ne eblas elekti tiparon" + +msgid "E598: Invalid fontset" +msgstr "E598: Nevalida tiparo" + +msgid "E533: can't select wide font" +msgstr "E533: ne eblas elekti larÄan tiparon" + +msgid "E534: Invalid wide font" +msgstr "E534: Nevalida larÄa tiparo" + #, c-format msgid "E535: Illegal character after <%c>" msgstr "E535: Nevalida signo post <%c>" -#: ../option.c:4534 msgid "E536: comma required" msgstr "E536: komo bezonata" -#: ../option.c:4543 #, c-format msgid "E537: 'commentstring' must be empty or contain %s" msgstr "E537: 'commentstring' devas esti malplena aÅ enhavi %s" -#: ../option.c:4928 +msgid "E538: No mouse support" +msgstr "E538: Neniu muso subtenata" + msgid "E540: Unclosed expression sequence" msgstr "E540: '}' mankas" -#: ../option.c:4932 msgid "E541: too many items" msgstr "E541: tro da elementoj" -#: ../option.c:4934 msgid "E542: unbalanced groups" -msgstr "E542: misekvilibritaj grupoj" +msgstr "E542: misekvilibraj grupoj" -#: ../option.c:5148 msgid "E590: A preview window already exists" msgstr "E590: AntaÅvida fenestro jam ekzistas" -#: ../option.c:5311 msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'" msgstr "W17: La araba bezonas UTF-8, tajpu \":set encoding=utf-8\"" -#: ../option.c:5623 #, c-format msgid "E593: Need at least %d lines" msgstr "E593: Bezonas almenaÅ %d liniojn" -#: ../option.c:5631 #, c-format msgid "E594: Need at least %d columns" msgstr "E594: Bezonas almenaÅ %d kolumnojn" -#: ../option.c:6011 #, c-format msgid "E355: Unknown option: %s" msgstr "E355: Nekonata opcio: %s" @@ -4723,12 +4374,10 @@ msgstr "E355: Nekonata opcio: %s" #. 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. -#: ../option.c:6037 #, c-format msgid "E521: Number required: &%s = '%s'" msgstr "E521: Nombro bezonata: &%s = '%s'" -#: ../option.c:6149 msgid "" "\n" "--- Terminal codes ---" @@ -4736,7 +4385,6 @@ msgstr "" "\n" "--- Kodoj de terminalo ---" -#: ../option.c:6151 msgid "" "\n" "--- Global option values ---" @@ -4744,7 +4392,6 @@ msgstr "" "\n" "--- Mallokaj opcioj ---" -#: ../option.c:6153 msgid "" "\n" "--- Local option values ---" @@ -4752,7 +4399,6 @@ msgstr "" "\n" "--- Valoroj de lokaj opcioj ---" -#: ../option.c:6155 msgid "" "\n" "--- Options ---" @@ -4760,37 +4406,116 @@ msgstr "" "\n" "--- Opcioj ---" -#: ../option.c:6816 msgid "E356: get_varp ERROR" msgstr "E356: ERARO get_varp" -#: ../option.c:7696 #, c-format msgid "E357: 'langmap': Matching character missing for %s" msgstr "E357: 'langmap': Kongrua signo mankas por %s" -#: ../option.c:7715 #, c-format msgid "E358: 'langmap': Extra characters after semicolon: %s" msgstr "E358: 'langmap': Ekstraj signoj post punktokomo: %s" -#: ../os/shell.c:194 -msgid "" -"\n" -"Cannot execute shell " -msgstr "" -"\n" -"Ne eblas plenumi Åelon " +msgid "cannot open " +msgstr "ne eblas malfermi " + +msgid "VIM: Can't open window!\n" +msgstr "VIM: Ne eblas malfermi fenestron!\n" + +msgid "Need Amigados version 2.04 or later\n" +msgstr "Bezonas version 2.04 de Amigados aÅ pli novan\n" + +#, c-format +msgid "Need %s version %ld\n" +msgstr "Bezonas %s-on versio %ld\n" + +msgid "Cannot open NIL:\n" +msgstr "Ne eblas malfermi NIL:\n" + +msgid "Cannot create " +msgstr "Ne eblas krei " + +#, c-format +msgid "Vim exiting with %d\n" +msgstr "Vim eliras kun %d\n" + +msgid "cannot change console mode ?!\n" +msgstr "ne eblas ÅanÄi reÄimon de konzolo?!\n" + +msgid "mch_get_shellsize: not a console??\n" +msgstr "mch_get_shellsize: ne estas konzolo??\n" + +#. if Vim opened a window: Executing a shell may cause crashes +msgid "E360: Cannot execute shell with -f option" +msgstr "E360: Ne eblas plenumi Åelon kun opcio -f" + +msgid "Cannot execute " +msgstr "Ne eblas plenumi " + +msgid "shell " +msgstr "Åelo " + +msgid " returned\n" +msgstr " liveris\n" + +msgid "ANCHOR_BUF_SIZE too small." +msgstr "ANCHOR_BUF_SIZE tro malgranda." + +msgid "I/O ERROR" +msgstr "ERARO DE ENIGO/ELIGO" + +msgid "Message" +msgstr "MesaÄo" + +msgid "E237: Printer selection failed" +msgstr "E237: Elekto de presilo malsukcesis" + +#, c-format +msgid "to %s on %s" +msgstr "al %s de %s" + +#, c-format +msgid "E613: Unknown printer font: %s" +msgstr "E613: Nekonata tiparo de presilo: %s" + +#, c-format +msgid "E238: Print error: %s" +msgstr "E238: Eraro de presado: %s" + +#, c-format +msgid "Printing '%s'" +msgstr "Presas '%s'" + +#, c-format +msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" +msgstr "E244: Nevalida nomo de signaro \"%s\" en nomo de tiparo \"%s\"" + +#, c-format +msgid "E244: Illegal quality name \"%s\" in font name \"%s\"" +msgstr "E244: Nevalida nomo de kvalito \"%s\" en nomo de tiparo \"%s\"" + +#, c-format +msgid "E245: Illegal char '%c' in font name \"%s\"" +msgstr "E245: Nevalida signo '%c' en nomo de tiparo \"%s\"" + +#, c-format +msgid "Opening the X display took %ld msec" +msgstr "Malfermo de vidigo X daÅris %ld msek" -#: ../os/shell.c:439 msgid "" "\n" -"shell returned " +"Vim: Got X error\n" msgstr "" "\n" -"Åelo liveris " +"Vim: Alvenis X eraro\n" + +msgid "Testing the X display failed" +msgstr "Testo de la vidigo X malsukcesis" + +msgid "Opening the X display timed out" +msgstr "Tempolimo okazis dum malfermo de vidigo X" -#: ../os_unix.c:465 ../os_unix.c:471 msgid "" "\n" "Could not get security context for " @@ -4798,7 +4523,6 @@ msgstr "" "\n" "Ne povis akiri kuntekston de sekureco por " -#: ../os_unix.c:479 msgid "" "\n" "Could not set security context for " @@ -4815,219 +4539,293 @@ msgid "Could not get security context %s for %s. Removing it!" msgstr "" "Ne povis akiri kuntekston de sekureco %s por %s. Gi nun estas forigata!" -#: ../os_unix.c:1558 ../os_unix.c:1647 +msgid "" +"\n" +"Cannot execute shell sh\n" +msgstr "" +"\n" +"Ne eblas plenumi Åelon sh\n" + +msgid "" +"\n" +"shell returned " +msgstr "" +"\n" +"Åelo liveris " + +msgid "" +"\n" +"Cannot create pipes\n" +msgstr "" +"\n" +"Ne eblas krei duktojn\n" + +msgid "" +"\n" +"Cannot fork\n" +msgstr "" +"\n" +"Ne eblas forki\n" + +msgid "" +"\n" +"Cannot execute shell " +msgstr "" +"\n" +"Ne eblas plenumi Åelon " + +msgid "" +"\n" +"Command terminated\n" +msgstr "" +"\n" +"Komando terminigita\n" + +msgid "XSMP lost ICE connection" +msgstr "XSMP perdis la konekton ICE" + #, c-format msgid "dlerror = \"%s\"" msgstr "dlerror = \"%s\"" -#: ../path.c:1449 +msgid "Opening the X display failed" +msgstr "Malfermo de vidigo X malsukcesis" + +msgid "XSMP handling save-yourself request" +msgstr "XSMP: traktado de peto konservi-mem" + +msgid "XSMP opening connection" +msgstr "XSMP: malfermo de konekto" + +msgid "XSMP ICE connection watch failed" +msgstr "XSMP: kontrolo de konekto ICE malsukcesis" + #, c-format -msgid "E447: Can't find file \"%s\" in path" -msgstr "E447: Ne eblas trovi dosieron \"%s\" en serĉvojo" +msgid "XSMP SmcOpenConnection failed: %s" +msgstr "XSMP: SmcOpenConnection malsukcesis: %s" + +msgid "At line" +msgstr "Ĉe linio" + +msgid "Could not load vim32.dll!" +msgstr "Ne eblis Åargi vim32.dll!" + +msgid "VIM Error" +msgstr "Eraro de VIM" + +msgid "Could not fix up function pointers to the DLL!" +msgstr "Ne eblis ripari referencojn de funkcioj al la DLL!" + +# DP: la eventoj estas tiuj, kiuj estas en la sekvantaj ĉenoj +#, c-format +msgid "Vim: Caught %s event\n" +msgstr "Vim: Kaptis eventon %s\n" + +msgid "close" +msgstr "fermo" + +msgid "logoff" +msgstr "elsaluto" + +msgid "shutdown" +msgstr "sistemfermo" + +msgid "E371: Command not found" +msgstr "E371: Netrovebla komando" + +msgid "" +"VIMRUN.EXE not found in your $PATH.\n" +"External commands will not pause after completion.\n" +"See :help win32-vimrun for more information." +msgstr "" +"VIMRUN.EXE ne troveblas en via $PATH.\n" +"Eksteraj komandoj ne paÅzos post kompletigo.\n" +"Vidu :help win32-vimrun por pliaj informoj." + +msgid "Vim Warning" +msgstr "Averto de Vim" + +#, c-format +msgid "shell returned %d" +msgstr "la Åelo liveris %d" -#: ../quickfix.c:359 #, c-format msgid "E372: Too many %%%c in format string" msgstr "E372: Tro da %%%c en formata ĉeno" -#: ../quickfix.c:371 #, c-format msgid "E373: Unexpected %%%c in format string" msgstr "E373: Neatendita %%%c en formata ĉeno" -#: ../quickfix.c:420 msgid "E374: Missing ] in format string" msgstr "E374: Mankas ] en formata ĉeno" -#: ../quickfix.c:431 #, c-format msgid "E375: Unsupported %%%c in format string" msgstr "E375: Nesubtenata %%%c en formata ĉeno" -#: ../quickfix.c:448 #, c-format msgid "E376: Invalid %%%c in format string prefix" msgstr "E376: Nevalida %%%c en prefikso de formata ĉeno" -#: ../quickfix.c:454 #, c-format msgid "E377: Invalid %%%c in format string" msgstr "E377: Nevalida %%%c en formata ĉeno" #. nothing found -#: ../quickfix.c:477 msgid "E378: 'errorformat' contains no pattern" msgstr "E378: 'errorformat' enhavas neniun Åablonon" -#: ../quickfix.c:695 msgid "E379: Missing or empty directory name" msgstr "E379: Nomo de dosierujo mankas aÅ estas malplena" -#: ../quickfix.c:1305 msgid "E553: No more items" msgstr "E553: Ne plu estas eroj" -#: ../quickfix.c:1674 +msgid "E924: Current window was closed" +msgstr "E924: Aktuala vindozo fermiÄis" + +msgid "E925: Current quickfix was changed" +msgstr "E925: Aktuala rapidriparo ÅanÄiÄis" + +msgid "E926: Current location list was changed" +msgstr "E926: Aktuala listo de lokoj ÅanÄiÄis" + #, c-format msgid "(%d of %d)%s%s: " msgstr "(%d de %d)%s%s: " -#: ../quickfix.c:1676 msgid " (line deleted)" msgstr " (forviÅita linio)" -#: ../quickfix.c:1863 +#, c-format +msgid "%serror list %d of %d; %d errors " +msgstr "%slisto de eraroj %d de %d; %d eraroj" + msgid "E380: At bottom of quickfix stack" msgstr "E380: Ĉe la subo de stako de rapidriparo" -#: ../quickfix.c:1869 msgid "E381: At top of quickfix stack" msgstr "E381: Ĉe la supro de stako de rapidriparo" -#: ../quickfix.c:1880 -#, c-format -msgid "error list %d of %d; %d errors" -msgstr "listo de eraroj %d de %d; %d eraroj" +msgid "No entries" +msgstr "Neniu ano" -#: ../quickfix.c:2427 msgid "E382: Cannot write, 'buftype' option is set" msgstr "E382: Ne eblas skribi, opcio 'buftype' estas Åaltita" -#: ../quickfix.c:2812 +msgid "Error file" +msgstr "Erara Dosiero" + msgid "E683: File name missing or invalid pattern" msgstr "E683: Dosiernomo mankas aÅ nevalida Åablono" -#: ../quickfix.c:2911 #, c-format msgid "Cannot open file \"%s\"" msgstr "Ne eblas malfermi dosieron \"%s\"" -#: ../quickfix.c:3429 msgid "E681: Buffer is not loaded" msgstr "E681: Bufro ne estas Åargita" -#: ../quickfix.c:3487 msgid "E777: String or List expected" msgstr "E777: Ĉeno aÅ Listo atendita" -#: ../regexp.c:359 #, c-format msgid "E369: invalid item in %s%%[]" msgstr "E369: nevalida ano en %s%%[]" -#: ../regexp.c:374 #, c-format msgid "E769: Missing ] after %s[" msgstr "E769: Mankas ] post %s[" -#: ../regexp.c:375 #, c-format msgid "E53: Unmatched %s%%(" msgstr "E53: Neekvilibra %s%%(" -#: ../regexp.c:376 #, c-format msgid "E54: Unmatched %s(" msgstr "E54: Neekvilibra %s(" -#: ../regexp.c:377 #, c-format msgid "E55: Unmatched %s)" msgstr "E55: Neekvilibra %s" -#: ../regexp.c:378 msgid "E66: \\z( not allowed here" -msgstr "E66: \\z( estas permesebla tie" +msgstr "E66: \\z( estas nepermesebla tie" # DP: vidu http://www.thefreedictionary.com/et+al. -#: ../regexp.c:379 msgid "E67: \\z1 et al. not allowed here" msgstr "E67: \\z1 kaj aliaj estas nepermeseblaj tie" -#: ../regexp.c:380 #, c-format msgid "E69: Missing ] after %s%%[" msgstr "E69: Mankas ] post %s%%[" -#: ../regexp.c:381 #, c-format msgid "E70: Empty %s%%[]" msgstr "E70: Malplena %s%%[]" -#: ../regexp.c:1209 ../regexp.c:1224 msgid "E339: Pattern too long" msgstr "E339: Åœablono tro longa" -#: ../regexp.c:1371 msgid "E50: Too many \\z(" msgstr "E50: Tro da \\z(" -#: ../regexp.c:1378 #, c-format msgid "E51: Too many %s(" msgstr "E51: Tro da %s(" -#: ../regexp.c:1427 msgid "E52: Unmatched \\z(" msgstr "E52: Neekvilibra \\z(" -#: ../regexp.c:1637 #, c-format msgid "E59: invalid character after %s@" msgstr "E59: nevalida signo post %s@" -#: ../regexp.c:1672 #, c-format msgid "E60: Too many complex %s{...}s" msgstr "E60: Tro da kompleksaj %s{...}-oj" -#: ../regexp.c:1687 #, c-format msgid "E61: Nested %s*" msgstr "E61: Ingita %s*" -#: ../regexp.c:1690 #, c-format msgid "E62: Nested %s%c" msgstr "E62: Ingita %s%c" -#: ../regexp.c:1800 msgid "E63: invalid use of \\_" msgstr "E63: nevalida uzo de \\_" -#: ../regexp.c:1850 #, c-format msgid "E64: %s%c follows nothing" msgstr "E64: %s%c sekvas nenion" -#: ../regexp.c:1902 msgid "E65: Illegal back reference" msgstr "E65: Nevalida retro-referenco" -#: ../regexp.c:1943 msgid "E68: Invalid character after \\z" msgstr "E68: Nevalida signo post \\z" -#: ../regexp.c:2049 ../regexp_nfa.c:1296 #, c-format msgid "E678: Invalid character after %s%%[dxouU]" msgstr "E678: Nevalida signo post %s%%[dxouU]" -#: ../regexp.c:2107 #, c-format msgid "E71: Invalid character after %s%%" msgstr "E71: Nevalida signo post %s%%" -#: ../regexp.c:3017 #, c-format msgid "E554: Syntax error in %s{...}" msgstr "E554: Sintaksa eraro en %s{...}" -#: ../regexp.c:3805 msgid "External submatches:\n" msgstr "Eksteraj subkongruoj:\n" -#: ../regexp.c:7022 +#, c-format +msgid "E888: (NFA regexp) cannot repeat %s" +msgstr "E888: (NFA-regulesprimo) ne eblas ripeti %s" + msgid "" "E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be " "used " @@ -5035,65 +4833,58 @@ msgstr "" "E864: \\%#= povas nur esti sekvita de 0, 1, aÅ 2. La aÅtomata motoro de " "regulesprimo estos uzata " -#: ../regexp_nfa.c:239 +msgid "Switching to backtracking RE engine for pattern: " +msgstr "Åœangota al malavanca motoro de regulesprimo por Åablono: " + msgid "E865: (NFA) Regexp end encountered prematurely" msgstr "E865: (NFA) Trovis finon de regulesprimo tro frue" -#: ../regexp_nfa.c:240 #, c-format msgid "E866: (NFA regexp) Misplaced %c" msgstr "E866: (NFA-regulesprimo) Mispoziciigita %c" -#: ../regexp_nfa.c:242 -#, fuzzy, c-format -msgid "E877: (NFA regexp) Invalid character class: %<PRId64>" -msgstr "E877: (NFA-regulesprimo) Nevalida klaso de signo " +#, c-format +msgid "E877: (NFA regexp) Invalid character class: %ld" +msgstr "E877: (NFA-regulesprimo) Nevalida klaso de signo: %ld" -#: ../regexp_nfa.c:1261 #, c-format msgid "E867: (NFA) Unknown operator '\\z%c'" msgstr "E867: (NFA) Nekonata operatoro '\\z%c'" -#: ../regexp_nfa.c:1387 -#, fuzzy, c-format +#, c-format msgid "E867: (NFA) Unknown operator '\\%%%c'" -msgstr "E867: (NFA) Nekonata operatoro '\\z%c'" +msgstr "E867: (NFA) Nekonata operatoro '\\%%%c'" + +#. should never happen +msgid "E868: Error building NFA with equivalence class!" +msgstr "E868: Eraro dum prekomputado de NFA kun ekvivalentoklaso!" -#: ../regexp_nfa.c:1802 #, c-format msgid "E869: (NFA) Unknown operator '\\@%c'" msgstr "E869: (NFA) Nekonata operatoro '\\@%c'" -#: ../regexp_nfa.c:1831 msgid "E870: (NFA regexp) Error reading repetition limits" msgstr "E870: (NFS-regulesprimo) Eraro dum legado de limoj de ripeto" #. Can't have a multi follow a multi. -#: ../regexp_nfa.c:1895 msgid "E871: (NFA regexp) Can't have a multi follow a multi !" msgstr "" "E871: (NFA-regulesprimo) Ne povas havi mult-selekton tuj post alia mult-" "selekto!" #. Too many `(' -#: ../regexp_nfa.c:2037 msgid "E872: (NFA regexp) Too many '('" msgstr "E872: (NFA-regulesprimo) tro da '('" -#: ../regexp_nfa.c:2042 -#, fuzzy msgid "E879: (NFA regexp) Too many \\z(" -msgstr "E872: (NFA-regulesprimo) tro da '('" +msgstr "E879: (NFA-regulesprimo) tro da \\z(" -#: ../regexp_nfa.c:2066 msgid "E873: (NFA regexp) proper termination error" msgstr "E873: (NFA-regulesprimo) propra end-eraro" -#: ../regexp_nfa.c:2599 msgid "E874: (NFA) Could not pop the stack !" msgstr "E874: (NFA) Ne povis elpreni de la staplo!" -#: ../regexp_nfa.c:3298 msgid "" "E875: (NFA regexp) (While converting from postfix to NFA), too many states " "left on stack" @@ -5101,177 +4892,136 @@ msgstr "" "E875: (NFA-regulesprimo) (dum konverto de postmeto al NFA), restas tro da " "statoj en la staplo" -#: ../regexp_nfa.c:3302 msgid "E876: (NFA regexp) Not enough space to store the whole NFA " msgstr "E876: (NFA-regulesprimo) ne sufiĉa spaco por enmomorigi la tutan NFA " -#: ../regexp_nfa.c:4571 ../regexp_nfa.c:4869 +msgid "E878: (NFA) Could not allocate memory for branch traversal!" +msgstr "E878: (NFA) Ne povis asigni memoron por traigi branĉojn!" + msgid "" "Could not open temporary log file for writing, displaying on stderr ... " msgstr "" "Ne povis malfermi provizoran protokolan dosieron por skribi, nun montras sur " "stderr ..." -#: ../regexp_nfa.c:4840 #, c-format msgid "(NFA) COULD NOT OPEN %s !" msgstr "(NFA) NE POVIS MALFERMI %s!" -#: ../regexp_nfa.c:6049 msgid "Could not open temporary log file for writing " msgstr "Ne povis malfermi la provizoran protokolan dosieron por skribi " -#: ../screen.c:7435 msgid " VREPLACE" msgstr " V-ANSTATAŬIGO" -#: ../screen.c:7437 msgid " REPLACE" msgstr " ANSTATAŬIGO" -#: ../screen.c:7440 msgid " REVERSE" msgstr " INVERSI" -#: ../screen.c:7441 msgid " INSERT" msgstr " ENMETO" -#: ../screen.c:7443 msgid " (insert)" msgstr " (enmeto)" -#: ../screen.c:7445 msgid " (replace)" msgstr " (anstataÅigo)" -#: ../screen.c:7447 msgid " (vreplace)" msgstr " (v-anstataÅigo)" -#: ../screen.c:7449 msgid " Hebrew" msgstr " hebrea" -#: ../screen.c:7454 msgid " Arabic" msgstr " araba" -#: ../screen.c:7456 -msgid " (lang)" -msgstr " (lingvo)" - -#: ../screen.c:7459 msgid " (paste)" msgstr " (algluo)" -#: ../screen.c:7469 msgid " VISUAL" msgstr " VIDUMA" -#: ../screen.c:7470 msgid " VISUAL LINE" msgstr " VIDUMA LINIO" -#: ../screen.c:7471 msgid " VISUAL BLOCK" msgstr " VIDUMA BLOKO" -#: ../screen.c:7472 msgid " SELECT" msgstr " APARTIGO" -#: ../screen.c:7473 msgid " SELECT LINE" msgstr " APARTIGITA LINIO" -#: ../screen.c:7474 msgid " SELECT BLOCK" msgstr " APARTIGITA BLOKO" -#: ../screen.c:7486 ../screen.c:7541 msgid "recording" msgstr "registrado" -#: ../search.c:487 #, c-format msgid "E383: Invalid search string: %s" msgstr "E383: Nevalida serĉenda ĉeno: %s" -#: ../search.c:832 #, c-format msgid "E384: search hit TOP without match for: %s" msgstr "E384: serĉo atingis SUPRON sen trovi: %s" -#: ../search.c:835 #, c-format msgid "E385: search hit BOTTOM without match for: %s" msgstr "E385: serĉo atingis SUBON sen trovi: %s" -#: ../search.c:1200 msgid "E386: Expected '?' or '/' after ';'" msgstr "E386: Atendis '?' aÅ '/' post ';'" -#: ../search.c:4085 msgid " (includes previously listed match)" msgstr " (enhavas antaÅe listigitajn kongruojn)" #. cursor at status line -#: ../search.c:4104 msgid "--- Included files " msgstr "--- Inkluzivitaj dosieroj " -#: ../search.c:4106 msgid "not found " msgstr "netrovitaj " -#: ../search.c:4107 msgid "in path ---\n" msgstr "en serĉvojo ---\n" -#: ../search.c:4168 msgid " (Already listed)" msgstr " (Jam listigita)" -#: ../search.c:4170 msgid " NOT FOUND" msgstr " NETROVITA" -#: ../search.c:4211 #, c-format msgid "Scanning included file: %s" msgstr "Skanado de inkluzivitaj dosieroj: %s" -#: ../search.c:4216 #, c-format msgid "Searching included file %s" msgstr "Serĉado de inkluzivitaj dosieroj %s" -#: ../search.c:4405 msgid "E387: Match is on current line" msgstr "E387: Kongruo estas ĉe aktuala linio" -#: ../search.c:4517 msgid "All included files were found" msgstr "Ĉiuj inkluzivitaj dosieroj estis trovitaj" -#: ../search.c:4519 msgid "No included files" msgstr "Neniu inkluzivita dosiero" -#: ../search.c:4527 msgid "E388: Couldn't find definition" msgstr "E388: Ne eblis trovi difinon" -#: ../search.c:4529 msgid "E389: Couldn't find pattern" msgstr "E389: Ne eblis trovi Åablonon" -#: ../search.c:4668 msgid "Substitute " msgstr "AnstataÅigi " -#: ../search.c:4681 #, c-format msgid "" "\n" @@ -5282,97 +5032,128 @@ msgstr "" "# Lasta serĉa Åablono %s:\n" "~" -#: ../spell.c:951 -msgid "E759: Format error in spell file" -msgstr "E759: Eraro de formato en literuma dosiero" +msgid "E756: Spell checking is not enabled" +msgstr "E756: Literumilo ne estas Åaltita" + +#, c-format +msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" +msgstr "Averto: Ne eblas trovi vortliston \"%s_%s.spl\" aÅ \"%s_ascii.spl\"" + +#, c-format +msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" +msgstr "Averto: Ne eblas trovi vortliston \"%s.%s.spl\" aÅ \"%s.ascii.spl\"" + +msgid "E797: SpellFileMissing autocommand deleted buffer" +msgstr "E797: AÅtokomando SpellFileMissing forviÅis bufron" + +#, c-format +msgid "Warning: region %s not supported" +msgstr "Averto: regiono %s ne subtenata" + +msgid "Sorry, no suggestions" +msgstr "BedaÅrinde ne estas sugestoj" + +#, c-format +msgid "Sorry, only %ld suggestions" +msgstr "BedaÅrinde estas nur %ld sugestoj" + +#. for when 'cmdheight' > 1 +#. avoid more prompt +#, c-format +msgid "Change \"%.*s\" to:" +msgstr "AnstataÅigi \"%.*s\" per:" + +#, c-format +msgid " < \"%.*s\"" +msgstr " < \"%.*s\"" + +msgid "E752: No previous spell replacement" +msgstr "E752: Neniu antaÅa literuma anstataÅigo" + +#, c-format +msgid "E753: Not found: %s" +msgstr "E753: Netrovita: %s" -#: ../spell.c:952 msgid "E758: Truncated spell file" msgstr "E758: Trunkita literuma dosiero" -#: ../spell.c:953 #, c-format msgid "Trailing text in %s line %d: %s" msgstr "Vosta teksto en %s linio %d: %s" -#: ../spell.c:954 #, c-format msgid "Affix name too long in %s line %d: %s" msgstr "Nomo de afikso tro longa en %s linio %d: %s" -#: ../spell.c:955 msgid "E761: Format error in affix file FOL, LOW or UPP" msgstr "E761: Eraro de formato en afiksa dosiero FOL, LOW aÅ UPP" -#: ../spell.c:957 msgid "E762: Character in FOL, LOW or UPP is out of range" msgstr "E762: Signo en FOL, LOW aÅ UPP estas ekster limoj" -#: ../spell.c:958 msgid "Compressing word tree..." msgstr "Densigas arbon de vortoj..." -#: ../spell.c:1951 -msgid "E756: Spell checking is not enabled" -msgstr "E756: Literumilo ne estas Åaltita" - -#: ../spell.c:2249 -#, c-format -msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" -msgstr "Averto: Ne eblas trovi vortliston \"%s.%s.spl\" aÅ \"%s.ascii.spl\"" - -#: ../spell.c:2473 #, c-format msgid "Reading spell file \"%s\"" msgstr "Legado de literuma dosiero \"%s\"" -#: ../spell.c:2496 msgid "E757: This does not look like a spell file" msgstr "E757: Tio ne Åajnas esti literuma dosiero" -#: ../spell.c:2501 msgid "E771: Old spell file, needs to be updated" msgstr "E771: Malnova literuma dosiero, Äisdatigo bezonata" -#: ../spell.c:2504 msgid "E772: Spell file is for newer version of Vim" msgstr "E772: Literuma dosiero estas por pli nova versio de Vim" -#: ../spell.c:2602 msgid "E770: Unsupported section in spell file" msgstr "E770: Nesubtenata sekcio en literuma dosiero" -#: ../spell.c:3762 #, c-format -msgid "Warning: region %s not supported" -msgstr "Averto: regiono %s ne subtenata" +msgid "E778: This does not look like a .sug file: %s" +msgstr "E778: Tio ne Åajnas esti dosiero .sug: %s" + +#, c-format +msgid "E779: Old .sug file, needs to be updated: %s" +msgstr "E779: Malnova dosiero .sug, bezonas Äisdatigon: %s" + +#, c-format +msgid "E780: .sug file is for newer version of Vim: %s" +msgstr "E780: Dosiero .sug estas por pli nova versio de Vim: %s" + +#, c-format +msgid "E781: .sug file doesn't match .spl file: %s" +msgstr "E781: Dosiero .sug ne kongruas kun dosiero .spl: %s" + +#, c-format +msgid "E782: error while reading .sug file: %s" +msgstr "E782: eraro dum legado de dosiero .sug: %s" -#: ../spell.c:4550 #, c-format msgid "Reading affix file %s ..." msgstr "Legado de afiksa dosiero %s ..." -#: ../spell.c:4589 ../spell.c:5635 ../spell.c:6140 #, c-format msgid "Conversion failure for word in %s line %d: %s" msgstr "Malsukceso dum konverto de vorto en %s linio %d: %s" -#: ../spell.c:4630 ../spell.c:6170 #, c-format msgid "Conversion in %s not supported: from %s to %s" msgstr "Konverto en %s nesubtenata: de %s al %s" -#: ../spell.c:4642 +#, c-format +msgid "Conversion in %s not supported" +msgstr "Konverto en %s nesubtenata" + #, c-format msgid "Invalid value for FLAG in %s line %d: %s" msgstr "Nevalida valoro de FLAG en %s linio %d: %s" -#: ../spell.c:4655 #, c-format msgid "FLAG after using flags in %s line %d: %s" msgstr "FLAG post flagoj en %s linio %d: %s" -#: ../spell.c:4723 #, c-format msgid "" "Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line " @@ -5381,7 +5162,6 @@ msgstr "" "Difino de COMPOUNDFORBIDFLAG post ano PFX povas doni neÄustajn rezultojn en " "%s linio %d" -#: ../spell.c:4731 #, c-format msgid "" "Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line " @@ -5390,42 +5170,34 @@ msgstr "" "Difino de COMPOUNDPERMITFLAG post ano PFX povas doni neÄustajn rezultojn en " "%s linio %d" -#: ../spell.c:4747 #, c-format msgid "Wrong COMPOUNDRULES value in %s line %d: %s" msgstr "Nevalida valoro de COMPOUNDRULES en %s linio %d: %s" -#: ../spell.c:4771 #, c-format msgid "Wrong COMPOUNDWORDMAX value in %s line %d: %s" msgstr "Nevalida valoro de COMPOUNDWORDMAX en %s linio %d: %s" -#: ../spell.c:4777 #, c-format msgid "Wrong COMPOUNDMIN value in %s line %d: %s" msgstr "Nevalida valoro de COMPOUNDMIN en %s linio %d: %s" -#: ../spell.c:4783 #, c-format msgid "Wrong COMPOUNDSYLMAX value in %s line %d: %s" msgstr "Nevalida valoro de COMPOUNDSYLMAX en %s linio %d: %s" -#: ../spell.c:4795 #, c-format msgid "Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s" msgstr "Nevalida valoro de CHECKCOMPOUNDPATTERN en %s linio %d: %s" -#: ../spell.c:4847 #, c-format msgid "Different combining flag in continued affix block in %s line %d: %s" msgstr "Malsama flago de kombino en daÅra bloko de afikso en %s linio %d: %s" -#: ../spell.c:4850 #, c-format msgid "Duplicate affix in %s line %d: %s" msgstr "Ripetita afikso en %s linio %d: %s" -#: ../spell.c:4871 #, c-format msgid "" "Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in %s " @@ -5434,308 +5206,206 @@ msgstr "" "Afikso ankaÅ uzata por BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST en " "%s linio %d: %s" -#: ../spell.c:4893 #, c-format msgid "Expected Y or N in %s line %d: %s" msgstr "Y aÅ N atendita en %s linio %d: %s" -#: ../spell.c:4968 #, c-format msgid "Broken condition in %s line %d: %s" msgstr "Nevalida kondiĉo en %s linio %d: %s" -#: ../spell.c:5091 #, c-format msgid "Expected REP(SAL) count in %s line %d" msgstr "Neatendita nombro REP(SAL) en %s linio %d" -#: ../spell.c:5120 #, c-format msgid "Expected MAP count in %s line %d" msgstr "Neatendita nombro de MAPen %s linio %d" -#: ../spell.c:5132 #, c-format msgid "Duplicate character in MAP in %s line %d" msgstr "Ripetita signo en MAP en %s linio %d" -#: ../spell.c:5176 #, c-format msgid "Unrecognized or duplicate item in %s line %d: %s" msgstr "Neagnoskita aÅ ripetita ano en %s linio %d: %s" -#: ../spell.c:5197 #, c-format msgid "Missing FOL/LOW/UPP line in %s" msgstr "Mankas linio FOL/LOW/UPP en %s" -#: ../spell.c:5220 msgid "COMPOUNDSYLMAX used without SYLLABLE" msgstr "COMPOUNDSYLMAX uzita sen SYLLABLE" -#: ../spell.c:5236 msgid "Too many postponed prefixes" msgstr "Tro da prokrastitaj prefiksoj" -#: ../spell.c:5238 msgid "Too many compound flags" msgstr "Tro da kunmetitaj flagoj" -#: ../spell.c:5240 msgid "Too many postponed prefixes and/or compound flags" msgstr "Tro da prokrastitaj prefiksoj kaj/aÅ kunmetitaj flagoj" -#: ../spell.c:5250 #, c-format msgid "Missing SOFO%s line in %s" msgstr "Mankas SOFO%s-aj linioj en %s" -#: ../spell.c:5253 #, c-format msgid "Both SAL and SOFO lines in %s" msgstr "AmbaÅ SAL kaj SOFO linioj en %s" -#: ../spell.c:5331 #, c-format msgid "Flag is not a number in %s line %d: %s" msgstr "Flago ne estas nombro en %s linio %d: %s" -#: ../spell.c:5334 #, c-format msgid "Illegal flag in %s line %d: %s" msgstr "Nevalida flago en %s linio %d: %s" -#: ../spell.c:5493 ../spell.c:5501 #, c-format msgid "%s value differs from what is used in another .aff file" msgstr "Valoro de %s malsamas ol tiu en alia dosiero .aff" -#: ../spell.c:5602 #, c-format msgid "Reading dictionary file %s ..." msgstr "Legado de vortardosiero %s ..." -#: ../spell.c:5611 #, c-format msgid "E760: No word count in %s" msgstr "E760: Ne estas nombro de vortoj en %s" -#: ../spell.c:5669 #, c-format msgid "line %6d, word %6d - %s" msgstr "linio %6d, vorto %6d - %s" -#: ../spell.c:5691 #, c-format msgid "Duplicate word in %s line %d: %s" msgstr "Ripetita vorto en %s linio %d: %s" -#: ../spell.c:5694 #, c-format msgid "First duplicate word in %s line %d: %s" msgstr "Unua ripetita vorto en %s linio %d: %s" -#: ../spell.c:5746 #, c-format msgid "%d duplicate word(s) in %s" msgstr "%d ripetita(j) vorto(j) en %s" -#: ../spell.c:5748 #, c-format msgid "Ignored %d word(s) with non-ASCII characters in %s" msgstr "%d ignorita(j) vorto(j) kun neaskiaj signoj en %s" -#: ../spell.c:6115 #, c-format msgid "Reading word file %s ..." msgstr "Legado de dosiero de vortoj %s ..." -#: ../spell.c:6155 #, c-format msgid "Duplicate /encoding= line ignored in %s line %d: %s" msgstr "Ripetita linio /encoding= ignorita en %s linio %d: %s" -#: ../spell.c:6159 #, c-format msgid "/encoding= line after word ignored in %s line %d: %s" msgstr "Linio /encoding= post vorto ignorita en %s linio %d: %s" -#: ../spell.c:6180 #, c-format msgid "Duplicate /regions= line ignored in %s line %d: %s" msgstr "Ripetita linio /regions= ignorita en %s linio %d: %s" -#: ../spell.c:6185 #, c-format msgid "Too many regions in %s line %d: %s" msgstr "Tro da regionoj en %s linio %d: %s" -#: ../spell.c:6198 #, c-format msgid "/ line ignored in %s line %d: %s" msgstr "Linio / ignorita en %s linio %d: %s" -#: ../spell.c:6224 #, c-format msgid "Invalid region nr in %s line %d: %s" msgstr "Nevalida regiono nr en %s linio %d: %s" -#: ../spell.c:6230 #, c-format msgid "Unrecognized flags in %s line %d: %s" msgstr "Nekonata flago en %s linio %d: %s" -#: ../spell.c:6257 #, c-format msgid "Ignored %d words with non-ASCII characters" msgstr "Ignoris %d vorto(j)n kun neaskiaj signoj" -#: ../spell.c:6656 +msgid "E845: Insufficient memory, word list will be incomplete" +msgstr "E845: Ne sufiĉe da memoro, vortlisto estos nekompleta." + #, c-format msgid "Compressed %d of %d nodes; %d (%d%%) remaining" msgstr "Densigis %d de %d nodoj; %d (%d%%) restantaj" -#: ../spell.c:7340 msgid "Reading back spell file..." msgstr "Relegas la dosieron de literumo..." -#. Go through the trie of good words, soundfold each word and add it to -#. the soundfold trie. -#: ../spell.c:7357 +#. +#. * Go through the trie of good words, soundfold each word and add it to +#. * the soundfold trie. +#. msgid "Performing soundfolding..." msgstr "Fonetika analizado..." -#: ../spell.c:7368 #, c-format -msgid "Number of words after soundfolding: %<PRId64>" -msgstr "Nombro de vortoj post fonetika analizado: %<PRId64>" +msgid "Number of words after soundfolding: %ld" +msgstr "Nombro de vortoj post fonetika analizado: %ld" -#: ../spell.c:7476 #, c-format msgid "Total number of words: %d" msgstr "Totala nombro de vortoj: %d" -#: ../spell.c:7655 #, c-format msgid "Writing suggestion file %s ..." msgstr "Skribado de dosiero de sugesto %s ..." -#: ../spell.c:7707 ../spell.c:7927 #, c-format msgid "Estimated runtime memory use: %d bytes" msgstr "Evaluo de memoro uzata: %d bajtoj" -#: ../spell.c:7820 msgid "E751: Output file name must not have region name" msgstr "E751: Nomo de eliga dosiero ne devas havi nomon de regiono" -#: ../spell.c:7822 msgid "E754: Only up to 8 regions supported" msgstr "E754: Nur 8 regionoj subtenataj" -#: ../spell.c:7846 #, c-format msgid "E755: Invalid region in %s" msgstr "E755: Nevalida regiono en %s" -#: ../spell.c:7907 msgid "Warning: both compounding and NOBREAK specified" msgstr "Averto: ambaÅ NOBREAK kaj NOBREAK specifitaj" -#: ../spell.c:7920 #, c-format msgid "Writing spell file %s ..." msgstr "Skribado de literuma dosiero %s ..." -#: ../spell.c:7925 msgid "Done!" msgstr "Farita!" -#: ../spell.c:8034 #, c-format -msgid "E765: 'spellfile' does not have %<PRId64> entries" -msgstr "E765: 'spellfile' ne havas %<PRId64> rikordojn" +msgid "E765: 'spellfile' does not have %ld entries" +msgstr "E765: 'spellfile' ne havas %ld rikordojn" -#: ../spell.c:8074 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' removed from %s" -msgstr "Vorto fortirita el %s" +msgstr "Vorto '%.*s' fortirita el %s" -#: ../spell.c:8117 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' added to %s" -msgstr "Vorto aldonita al %s" +msgstr "Vorto '%.*s' aldonita al %s" -#: ../spell.c:8381 msgid "E763: Word characters differ between spell files" msgstr "E763: Signoj de vorto malsamas tra literumaj dosieroj" -#: ../spell.c:8684 -msgid "Sorry, no suggestions" -msgstr "BedaÅrinde ne estas sugestoj" - -#: ../spell.c:8687 -#, c-format -msgid "Sorry, only %<PRId64> suggestions" -msgstr "BedaÅrinde estas nur %<PRId64> sugestoj" - -#. for when 'cmdheight' > 1 -#. avoid more prompt -#: ../spell.c:8704 -#, c-format -msgid "Change \"%.*s\" to:" -msgstr "AnstataÅigi \"%.*s\" per:" - -#: ../spell.c:8737 -#, c-format -msgid " < \"%.*s\"" -msgstr " < \"%.*s\"" - -#: ../spell.c:8882 -msgid "E752: No previous spell replacement" -msgstr "E752: Neniu antaÅa literuma anstataÅigo" - -#: ../spell.c:8925 -#, c-format -msgid "E753: Not found: %s" -msgstr "E753: Netrovita: %s" - -#: ../spell.c:9276 -#, c-format -msgid "E778: This does not look like a .sug file: %s" -msgstr "E778: Tio ne Åajnas esti dosiero .sug: %s" - -#: ../spell.c:9282 -#, c-format -msgid "E779: Old .sug file, needs to be updated: %s" -msgstr "E779: Malnova dosiero .sug, bezonas Äisdatigon: %s" - -#: ../spell.c:9286 -#, c-format -msgid "E780: .sug file is for newer version of Vim: %s" -msgstr "E780: Dosiero .sug estas por pli nova versio de Vim: %s" - -#: ../spell.c:9295 -#, c-format -msgid "E781: .sug file doesn't match .spl file: %s" -msgstr "E781: Dosiero .sug ne kongruas kun dosiero .spl: %s" - -#: ../spell.c:9305 -#, c-format -msgid "E782: error while reading .sug file: %s" -msgstr "E782: eraro dum legado de dosiero .sug: %s" - #. This should have been checked when generating the .spl -#. file. -#: ../spell.c:11575 +#. * file. msgid "E783: duplicate char in MAP entry" msgstr "E783: ripetita signo en rikordo MAP" -#: ../syntax.c:266 msgid "No Syntax items defined for this buffer" msgstr "Neniu sintaksa elemento difinita por tiu bufro" -#: ../syntax.c:3083 ../syntax.c:3104 ../syntax.c:3127 #, c-format msgid "E390: Illegal argument: %s" msgstr "E390: Nevalida argumento: %s" @@ -5743,28 +5413,22 @@ msgstr "E390: Nevalida argumento: %s" msgid "syntax iskeyword " msgstr "sintakso iskeyword " -#: ../syntax.c:3299 #, c-format msgid "E391: No such syntax cluster: %s" msgstr "E391: Nenia sintaksa fasko: %s" -#: ../syntax.c:3433 msgid "syncing on C-style comments" msgstr "sinkronigo per C-stilaj komentoj" -#: ../syntax.c:3439 msgid "no syncing" msgstr "neniu sinkronigo" -#: ../syntax.c:3441 msgid "syncing starts " msgstr "sinkronigo ekas " -#: ../syntax.c:3443 ../syntax.c:3506 msgid " lines before top line" msgstr " linioj antaÅ supra linio" -#: ../syntax.c:3448 msgid "" "\n" "--- Syntax sync items ---" @@ -5772,7 +5436,6 @@ msgstr "" "\n" "--- Eroj de sintaksa sinkronigo ---" -#: ../syntax.c:3452 msgid "" "\n" "syncing on items" @@ -5780,7 +5443,6 @@ msgstr "" "\n" "sinkronigo per eroj" -#: ../syntax.c:3457 msgid "" "\n" "--- Syntax items ---" @@ -5788,53 +5450,41 @@ msgstr "" "\n" "--- Sintakseroj ---" -#: ../syntax.c:3475 #, c-format msgid "E392: No such syntax cluster: %s" msgstr "E392: Nenia sintaksa fasko: %s" -#: ../syntax.c:3497 msgid "minimal " msgstr "minimuma " -#: ../syntax.c:3503 msgid "maximal " msgstr "maksimuma " -#: ../syntax.c:3513 msgid "; match " msgstr "; kongruo " -#: ../syntax.c:3515 msgid " line breaks" msgstr " liniavancoj" -#: ../syntax.c:4076 msgid "E395: contains argument not accepted here" msgstr "E395: La argumento \"contains\" ne akcepteblas tie" -#: ../syntax.c:4096 msgid "E844: invalid cchar value" msgstr "E844: nevalida valoro de cchar" -#: ../syntax.c:4107 msgid "E393: group[t]here not accepted here" msgstr "E393: La argumento \"group[t]here\" ne akcepteblas tie" -#: ../syntax.c:4126 #, c-format msgid "E394: Didn't find region item for %s" msgstr "E394: Ne trovis regionan elementon por %s" -#: ../syntax.c:4188 msgid "E397: Filename required" msgstr "E397: Dosiernomo bezonata" -#: ../syntax.c:4221 msgid "E847: Too many syntax includes" msgstr "E847: Tro da sintaksaj inkluzivoj" -#: ../syntax.c:4303 #, c-format msgid "E789: Missing ']': %s" msgstr "E789: Mankas ']': %s" @@ -5843,221 +5493,174 @@ msgstr "E789: Mankas ']': %s" msgid "E890: trailing char after ']': %s]%s" msgstr "E890: vosta signo post ']': %s]%s" -#: ../syntax.c:4531 #, c-format msgid "E398: Missing '=': %s" msgstr "E398: Mankas '=': %s" -#: ../syntax.c:4666 #, c-format msgid "E399: Not enough arguments: syntax region %s" msgstr "E399: Ne sufiĉaj argumentoj: sintaksa regiono %s" -#: ../syntax.c:4870 msgid "E848: Too many syntax clusters" msgstr "E848: Tro da sintaksaj grupoj" -#: ../syntax.c:4954 msgid "E400: No cluster specified" msgstr "E400: Neniu fasko specifita" -#. end delimiter not found -#: ../syntax.c:4986 #, c-format msgid "E401: Pattern delimiter not found: %s" msgstr "E401: Disigilo de Åablono netrovita: %s" -#: ../syntax.c:5049 #, c-format msgid "E402: Garbage after pattern: %s" msgstr "E402: Forĵetindaĵo post Åablono: %s" -#: ../syntax.c:5120 msgid "E403: syntax sync: line continuations pattern specified twice" msgstr "E403: sintaksa sinkronigo: Åablono de linia daÅrigo specifita dufoje" -#: ../syntax.c:5169 #, c-format msgid "E404: Illegal arguments: %s" msgstr "E404: Nevalidaj argumentoj: %s" -#: ../syntax.c:5217 #, c-format msgid "E405: Missing equal sign: %s" msgstr "E405: Mankas egalsigno: %s" -#: ../syntax.c:5222 #, c-format msgid "E406: Empty argument: %s" msgstr "E406: Malplena argumento: %s" -#: ../syntax.c:5240 #, c-format msgid "E407: %s not allowed here" msgstr "E407: %s ne estas permesebla tie" -#: ../syntax.c:5246 #, c-format msgid "E408: %s must be first in contains list" msgstr "E408: %s devas esti la unua ano de la listo \"contains\"" -#: ../syntax.c:5304 #, c-format msgid "E409: Unknown group name: %s" msgstr "E409: Nekonata nomo de grupo: %s" -#: ../syntax.c:5512 #, c-format msgid "E410: Invalid :syntax subcommand: %s" msgstr "E410: Nevalida \":syntax\" subkomando: %s" -#: ../syntax.c:5854 msgid "" " TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN" msgstr "" +" TOTALO NOMBRO KONGRUO PLEJ MALRAPID MEZA NOMO ÅœABLONO" -#: ../syntax.c:6146 msgid "E679: recursive loop loading syncolor.vim" msgstr "E679: rekursia buklo dum Åargo de syncolor.vim" -#: ../syntax.c:6256 #, c-format msgid "E411: highlight group not found: %s" msgstr "E411: emfaza grupo netrovita: %s" -#: ../syntax.c:6278 #, c-format msgid "E412: Not enough arguments: \":highlight link %s\"" msgstr "E412: Ne sufiĉaj argumentoj: \":highlight link %s\"" -#: ../syntax.c:6284 #, c-format msgid "E413: Too many arguments: \":highlight link %s\"" -msgstr "E413: Tro argumentoj: \":highlight link %s\"" +msgstr "E413: Tro da argumentoj: \":highlight link %s\"" -#: ../syntax.c:6302 msgid "E414: group has settings, highlight link ignored" msgstr "E414: grupo havas agordojn, ligilo de emfazo ignorita" -#: ../syntax.c:6367 #, c-format msgid "E415: unexpected equal sign: %s" msgstr "E415: neatendita egalsigno: %s" -#: ../syntax.c:6395 #, c-format msgid "E416: missing equal sign: %s" msgstr "E416: mankas egalsigno: %s" -#: ../syntax.c:6418 #, c-format msgid "E417: missing argument: %s" msgstr "E417: mankas argumento: %s" -#: ../syntax.c:6446 #, c-format msgid "E418: Illegal value: %s" msgstr "E418: Nevalida valoro: %s" -#: ../syntax.c:6496 msgid "E419: FG color unknown" msgstr "E419: Nekonata malfona koloro" -#: ../syntax.c:6504 msgid "E420: BG color unknown" msgstr "E420: Nekonata fona koloro" -#: ../syntax.c:6564 #, c-format msgid "E421: Color name or number not recognized: %s" msgstr "E421: Kolora nomo aÅ nombro nerekonita: %s" -#: ../syntax.c:6714 #, c-format msgid "E422: terminal code too long: %s" msgstr "E422: kodo de terminalo estas tro longa: %s" -#: ../syntax.c:6753 #, c-format msgid "E423: Illegal argument: %s" msgstr "E423: Nevalida argumento: %s" -#: ../syntax.c:6925 msgid "E424: Too many different highlighting attributes in use" msgstr "E424: Tro da malsamaj atributoj de emfazo uzataj" -#: ../syntax.c:7427 msgid "E669: Unprintable character in group name" msgstr "E669: Nepresebla signo en nomo de grupo" -#: ../syntax.c:7434 msgid "W18: Invalid character in group name" msgstr "W18: Nevalida signo en nomo de grupo" -#: ../syntax.c:7448 msgid "E849: Too many highlight and syntax groups" msgstr "E849: Tro da emfazaj kaj sintaksaj grupoj" -#: ../tag.c:104 msgid "E555: at bottom of tag stack" msgstr "E555: ĉe subo de stako de etikedoj" -#: ../tag.c:105 msgid "E556: at top of tag stack" msgstr "E556: ĉe supro de stako de etikedoj" -#: ../tag.c:380 msgid "E425: Cannot go before first matching tag" msgstr "E425: Ne eblas iri antaÅ la unuan kongruan etikedon" -#: ../tag.c:504 #, c-format msgid "E426: tag not found: %s" msgstr "E426: etikedo netrovita: %s" # DP: "pri" estas "priority" -#: ../tag.c:528 msgid " # pri kind tag" msgstr "nro pri tipo etikedo" -#: ../tag.c:531 msgid "file\n" msgstr "dosiero\n" -#: ../tag.c:829 msgid "E427: There is only one matching tag" msgstr "E427: Estas nur unu kongrua etikedo" -#: ../tag.c:831 msgid "E428: Cannot go beyond last matching tag" msgstr "E428: Ne eblas iri preter lastan kongruan etikedon" -#: ../tag.c:850 #, c-format msgid "File \"%s\" does not exist" msgstr "La dosiero \"%s\" ne ekzistas" #. Give an indication of the number of matching tags -#: ../tag.c:859 #, c-format msgid "tag %d of %d%s" msgstr "etikedo %d de %d%s" -#: ../tag.c:862 msgid " or more" msgstr " aÅ pli" -#: ../tag.c:864 msgid " Using tag with different case!" msgstr " Uzo de etikedo kun malsama uskleco!" -#: ../tag.c:909 #, c-format msgid "E429: File \"%s\" does not exist" msgstr "E429: Dosiero \"%s\" ne ekzistas" #. Highlight title -#: ../tag.c:960 msgid "" "\n" " # TO tag FROM line in file/text" @@ -6065,79 +5668,66 @@ msgstr "" "\n" "nro AL etikedo DE linio en dosiero/teksto" -#: ../tag.c:1303 #, c-format msgid "Searching tags file %s" msgstr "Serĉado de dosiero de etikedoj %s" -#: ../tag.c:1545 +#, c-format +msgid "E430: Tag file path truncated for %s\n" +msgstr "E430: Vojo de etikeda dosiero trunkita por %s\n" + msgid "Ignoring long line in tags file" msgstr "Ignoro de longa linio en etikeda dosiero" -#: ../tag.c:1915 #, c-format msgid "E431: Format error in tags file \"%s\"" msgstr "E431: Eraro de formato en etikeda dosiero \"%s\"" -#: ../tag.c:1917 #, c-format -msgid "Before byte %<PRId64>" -msgstr "AntaÅ bajto %<PRId64>" +msgid "Before byte %ld" +msgstr "AntaÅ bajto %ld" -#: ../tag.c:1929 #, c-format msgid "E432: Tags file not sorted: %s" msgstr "E432: Etikeda dosiero ne estas ordigita: %s" #. never opened any tags file -#: ../tag.c:1960 msgid "E433: No tags file" msgstr "E433: Neniu etikeda dosiero" -#: ../tag.c:2536 msgid "E434: Can't find tag pattern" msgstr "E434: Ne eblas trovi Åablonon de etikedo" -#: ../tag.c:2544 msgid "E435: Couldn't find tag, just guessing!" msgstr "E435: Ne eblis trovi etikedon, nur divenas!" -#: ../tag.c:2797 #, c-format msgid "Duplicate field name: %s" msgstr "Ripetita kamponomo: %s" -#: ../term.c:1442 msgid "' not known. Available builtin terminals are:" msgstr "' nekonata. Haveblaj terminaloj estas:" -#: ../term.c:1463 msgid "defaulting to '" msgstr "defaÅlto al '" -#: ../term.c:1731 msgid "E557: Cannot open termcap file" msgstr "E557: Ne eblas malfermi la dosieron termcap" -#: ../term.c:1735 msgid "E558: Terminal entry not found in terminfo" msgstr "E558: Ne trovis rikordon de terminalo terminfo" -#: ../term.c:1737 msgid "E559: Terminal entry not found in termcap" msgstr "E559: Ne trovis rikordon de terminalo en termcap" -#: ../term.c:1878 #, c-format msgid "E436: No \"%s\" entry in termcap" msgstr "E436: Neniu rikordo \"%s\" en termcap" -#: ../term.c:2249 msgid "E437: terminal capability \"cm\" required" msgstr "E437: kapablo de terminalo \"cm\" bezonata" #. Highlight title -#: ../term.c:4376 msgid "" "\n" "--- Terminal keys ---" @@ -6145,169 +5735,339 @@ msgstr "" "\n" "--- Klavoj de terminalo ---" -#: ../ui.c:481 +msgid "Cannot open $VIMRUNTIME/rgb.txt" +msgstr "Ne povas malfermi $VIMRUNTIME/rgb.txt" + +msgid "new shell started\n" +msgstr "nova Åelo lanĉita\n" + msgid "Vim: Error reading input, exiting...\n" msgstr "Vim: Eraro dum legado de eniro, elironta...\n" +msgid "Used CUT_BUFFER0 instead of empty selection" +msgstr "Uzis CUT_BUFFER0 anstataÅ malplenan apartigon" + #. This happens when the FileChangedRO autocommand changes the #. * file in a way it becomes shorter. -#: ../undo.c:379 -#, fuzzy msgid "E881: Line count changed unexpectedly" -msgstr "E834: Nombro de linioj ÅanÄiÄis neatendite" +msgstr "E881: Nombro de linioj ÅanÄiÄis neatendite" + +#. must display the prompt +msgid "No undo possible; continue anyway" +msgstr "Malfaro neebla; tamen daÅrigi" -#: ../undo.c:627 #, c-format msgid "E828: Cannot open undo file for writing: %s" msgstr "E828: Ne eblas malfermi la malfaran dosieron por skribi: %s" -#: ../undo.c:717 #, c-format msgid "E825: Corrupted undo file (%s): %s" msgstr "E825: Difektita malfara dosiero (%s): %s" -#: ../undo.c:1039 msgid "Cannot write undo file in any directory in 'undodir'" msgstr "Ne eblis skribi malfaran dosieron en iu dosiero ajn de 'undodir'" -#: ../undo.c:1074 #, c-format msgid "Will not overwrite with undo file, cannot read: %s" msgstr "Ne superskribos malfaran dosieron, ne eblis legi: %s" -#: ../undo.c:1092 #, c-format msgid "Will not overwrite, this is not an undo file: %s" msgstr "Ne superskribos, tio ne estas malfara dosiero: %s" -#: ../undo.c:1108 msgid "Skipping undo file write, nothing to undo" msgstr "Preterpasas skribon de malfara dosiero, nenio por malfari" -#: ../undo.c:1121 #, c-format msgid "Writing undo file: %s" msgstr "Skribas malfaran dosieron: %s" -#: ../undo.c:1213 #, c-format msgid "E829: write error in undo file: %s" msgstr "E829: Skriberaro en malfara dosiero: %s" -#: ../undo.c:1280 #, c-format msgid "Not reading undo file, owner differs: %s" msgstr "Ne legas malfaran dosieron, posedanto malsamas: %s" -#: ../undo.c:1292 #, c-format msgid "Reading undo file: %s" msgstr "Legado de malfara dosiero: %s" -#: ../undo.c:1299 #, c-format msgid "E822: Cannot open undo file for reading: %s" msgstr "E822: Ne eblas malfermi malfaran dosieron por legi: %s" -#: ../undo.c:1308 #, c-format msgid "E823: Not an undo file: %s" msgstr "E823: Ne estas malfara dosiero: %s" -#: ../undo.c:1313 +#, c-format +msgid "E832: Non-encrypted file has encrypted undo file: %s" +msgstr "E832: Ne ĉifrata dosiero havas ĉifratan malfaran dosieron: %s" + +#, c-format +msgid "E826: Undo file decryption failed: %s" +msgstr "E826: Malĉifrado de malfara dosiero malsukcesis: %s" + +#, c-format +msgid "E827: Undo file is encrypted: %s" +msgstr "E827: Malfara dosiero estas ĉifrata: %s" + #, c-format msgid "E824: Incompatible undo file: %s" msgstr "E824: Malkongrua malfara dosiero: %s" -#: ../undo.c:1328 msgid "File contents changed, cannot use undo info" msgstr "Enhavo de dosiero ÅanÄiÄis, ne eblas uzi malfarajn informojn" -#: ../undo.c:1497 #, c-format msgid "Finished reading undo file %s" msgstr "Finis legi malfaran dosieron %s" -#: ../undo.c:1586 ../undo.c:1812 msgid "Already at oldest change" msgstr "Jam al la plej malnova ÅanÄo" -#: ../undo.c:1597 ../undo.c:1814 msgid "Already at newest change" msgstr "Jam al la plej nova ÅanÄo" -#: ../undo.c:1806 #, c-format -msgid "E830: Undo number %<PRId64> not found" -msgstr "E830: Malfara numero %<PRId64> netrovita" +msgid "E830: Undo number %ld not found" +msgstr "E830: Malfara numero %ld netrovita" -#: ../undo.c:1979 msgid "E438: u_undo: line numbers wrong" msgstr "E438: u_undo: nevalidaj numeroj de linioj" -#: ../undo.c:2183 msgid "more line" msgstr "plia linio" -#: ../undo.c:2185 msgid "more lines" msgstr "pliaj linioj" -#: ../undo.c:2187 msgid "line less" msgstr "malpli linio" -#: ../undo.c:2189 msgid "fewer lines" msgstr "malpli linioj" -#: ../undo.c:2193 msgid "change" msgstr "ÅanÄo" -#: ../undo.c:2195 msgid "changes" msgstr "ÅanÄoj" -#: ../undo.c:2225 #, c-format -msgid "%<PRId64> %s; %s #%<PRId64> %s" -msgstr "%<PRId64> %s; %s #%<PRId64> %s" +msgid "%ld %s; %s #%ld %s" +msgstr "%ld %s; %s #%ld %s" -#: ../undo.c:2228 msgid "before" msgstr "antaÅ" -#: ../undo.c:2228 msgid "after" msgstr "post" -#: ../undo.c:2325 msgid "Nothing to undo" msgstr "Nenio por malfari" -#: ../undo.c:2330 msgid "number changes when saved" msgstr "numero ÅanÄoj tempo konservita" -#: ../undo.c:2360 #, c-format -msgid "%<PRId64> seconds ago" -msgstr "antaÅ %<PRId64> sekundoj" +msgid "%ld seconds ago" +msgstr "antaÅ %ld sekundoj" -#: ../undo.c:2372 msgid "E790: undojoin is not allowed after undo" msgstr "E790: undojoin estas nepermesebla post malfaro" -#: ../undo.c:2466 msgid "E439: undo list corrupt" msgstr "E439: listo de malfaro estas difekta" -#: ../undo.c:2495 msgid "E440: undo line missing" msgstr "E440: linio de malfaro mankas" -#: ../version.c:600 +#, c-format +msgid "E122: Function %s already exists, add ! to replace it" +msgstr "E122: La funkcio %s jam ekzistas (aldonu ! por anstataÅigi Äin)" + +msgid "E717: Dictionary entry already exists" +msgstr "E717: Rikordo de vortaro jam ekzistas" + +msgid "E718: Funcref required" +msgstr "E718: Funcref bezonata" + +#, c-format +msgid "E130: Unknown function: %s" +msgstr "E130: Nekonata funkcio: %s" + +#, c-format +msgid "E125: Illegal argument: %s" +msgstr "E125: Nevalida argumento: %s" + +#, c-format +msgid "E853: Duplicate argument name: %s" +msgstr "E853: Ripetita nomo de argumento: %s" + +#, c-format +msgid "E740: Too many arguments for function %s" +msgstr "E740: Tro da argumentoj por funkcio: %s" + +#, c-format +msgid "E116: Invalid arguments for function %s" +msgstr "E116: Nevalidaj argumentoj por funkcio: %s" + +msgid "E132: Function call depth is higher than 'maxfuncdepth'" +msgstr "E132: Profundo de funkcia alvoko superas 'maxfuncdepth'" + +#, c-format +msgid "calling %s" +msgstr "alvokas %s" + +#, c-format +msgid "%s aborted" +msgstr "%s ĉesigita" + +#, c-format +msgid "%s returning #%ld" +msgstr "%s liveras #%ld" + +#, c-format +msgid "%s returning %s" +msgstr "%s liveras %s" + +msgid "E699: Too many arguments" +msgstr "E699: Tro da argumentoj" + +#, c-format +msgid "E117: Unknown function: %s" +msgstr "E117: Nekonata funkcio: %s" + +#, c-format +msgid "E933: Function was deleted: %s" +msgstr "E933: funkcio estis forviÅita: %s" + +#, c-format +msgid "E119: Not enough arguments for function: %s" +msgstr "E119: Ne sufiĉe da argumentoj por funkcio: %s" + +#, c-format +msgid "E120: Using <SID> not in a script context: %s" +msgstr "E120: <SID> estas uzata ekster kunteksto de skripto: %s" + +#, c-format +msgid "E725: Calling dict function without Dictionary: %s" +msgstr "E725: Alvoko de funkcio dict sen Vortaro: %s" + +msgid "E129: Function name required" +msgstr "E129: Nomo de funkcio bezonata" + +#, c-format +msgid "E128: Function name must start with a capital or \"s:\": %s" +msgstr "E128: Nomo de funkcio devas eki per majusklo aÅ per \"s:\": %s" + +#, c-format +msgid "E884: Function name cannot contain a colon: %s" +msgstr "E884: Nomo de funkcio ne povas enhavi dupunkton: %s" + +#, c-format +msgid "E123: Undefined function: %s" +msgstr "E123: Nedifinita funkcio: %s" + +#, c-format +msgid "E124: Missing '(': %s" +msgstr "E124: Mankas '(': %s" + +msgid "E862: Cannot use g: here" +msgstr "E862: Ne eblas uzi g: ĉi tie" + +#, c-format +msgid "E932: Closure function should not be at top level: %s" +msgstr "E932: Fermo-funkcio devus esti je la plej alta nivelo: %s" + +msgid "E126: Missing :endfunction" +msgstr "E126: Mankas \":endfunction\"" + +#, c-format +msgid "E707: Function name conflicts with variable: %s" +msgstr "E707: Nomo de funkcio konfliktas kun variablo: %s" + +#, c-format +msgid "E127: Cannot redefine function %s: It is in use" +msgstr "E127: Ne eblas redifini funkcion %s: Estas nuntempe uzata" + +#, c-format +msgid "E746: Function name does not match script file name: %s" +msgstr "E746: Nomo de funkcio ne kongruas kun dosiernomo de skripto: %s" + +#, c-format +msgid "E131: Cannot delete function %s: It is in use" +msgstr "E131: Ne eblas forviÅi funkcion %s: Estas nuntempe uzata" + +msgid "E133: :return not inside a function" +msgstr "E133: \":return\" ekster funkcio" + +#, c-format +msgid "E107: Missing parentheses: %s" +msgstr "E107: Mankas krampoj: %s" + +msgid "" +"\n" +"MS-Windows 64-bit GUI version" +msgstr "" +"\n" +"Grafika versio MS-Vindozo 64-bitoj" + +msgid "" +"\n" +"MS-Windows 32-bit GUI version" +msgstr "" +"\n" +"Grafika versio MS-Vindozo 32-bitoj" + +msgid " with OLE support" +msgstr " kun subteno de OLE" + +msgid "" +"\n" +"MS-Windows 64-bit console version" +msgstr "" +"\n" +"Versio konzola MS-Vindozo 64-bitoj" + +msgid "" +"\n" +"MS-Windows 32-bit console version" +msgstr "" +"\n" +"Versio konzola MS-Vindozo 32-bitoj" + +msgid "" +"\n" +"MacOS X (unix) version" +msgstr "" +"\n" +"Versio Mak OS X (unikso)" + +msgid "" +"\n" +"MacOS X version" +msgstr "" +"\n" +"Versio Mak OS X" + +msgid "" +"\n" +"MacOS version" +msgstr "" +"\n" +"Versio Mak OS" + +msgid "" +"\n" +"OpenVMS version" +msgstr "" +"\n" +"Versio OpenVMS" + msgid "" "\n" "Included patches: " @@ -6315,7 +6075,6 @@ msgstr "" "\n" "Flikaĵoj inkluzivitaj: " -#: ../version.c:627 msgid "" "\n" "Extra patches: " @@ -6323,11 +6082,9 @@ msgstr "" "\n" "Ekstraj flikaĵoj: " -#: ../version.c:639 ../version.c:864 msgid "Modified by " msgstr "Modifita de " -#: ../version.c:646 msgid "" "\n" "Compiled " @@ -6335,11 +6092,9 @@ msgstr "" "\n" "Kompilita " -#: ../version.c:649 msgid "by " msgstr "de " -#: ../version.c:660 msgid "" "\n" "Huge version " @@ -6347,1903 +6102,936 @@ msgstr "" "\n" "Grandega versio " -#: ../version.c:661 +msgid "" +"\n" +"Big version " +msgstr "" +"\n" +"Granda versio " + +msgid "" +"\n" +"Normal version " +msgstr "" +"\n" +"Normala versio " + +msgid "" +"\n" +"Small version " +msgstr "" +"\n" +"Malgranda versio " + +msgid "" +"\n" +"Tiny version " +msgstr "" +"\n" +"Malgrandega versio " + msgid "without GUI." msgstr "sen grafika interfaco." -#: ../version.c:662 +msgid "with GTK3 GUI." +msgstr "kun grafika interfaco GTK3." + +msgid "with GTK2-GNOME GUI." +msgstr "kun grafika interfaco GTK2-GNOME." + +msgid "with GTK2 GUI." +msgstr "kun grafika interfaco GTK2." + +msgid "with X11-Motif GUI." +msgstr "kun grafika interfaco X11-Motif." + +msgid "with X11-neXtaw GUI." +msgstr "kun grafika interfaco X11-neXtaw." + +msgid "with X11-Athena GUI." +msgstr "kun grafika interfaco X11-Athena." + +msgid "with Photon GUI." +msgstr "kun grafika interfaco Photon." + +msgid "with GUI." +msgstr "sen grafika interfaco." + +msgid "with Carbon GUI." +msgstr "kun grafika interfaco Carbon." + +msgid "with Cocoa GUI." +msgstr "kun grafika interfaco Cocoa." + +msgid "with (classic) GUI." +msgstr "kun (klasika) grafika interfaco." + msgid " Features included (+) or not (-):\n" msgstr " Ebloj inkluzivitaj (+) aÅ ne (-):\n" -#: ../version.c:667 msgid " system vimrc file: \"" msgstr " sistema dosiero vimrc: \"" -#: ../version.c:672 msgid " user vimrc file: \"" msgstr " dosiero vimrc de uzanto: \"" -#: ../version.c:677 msgid " 2nd user vimrc file: \"" msgstr " 2-a dosiero vimrc de uzanto: \"" -#: ../version.c:682 msgid " 3rd user vimrc file: \"" msgstr " 3-a dosiero vimrc de uzanto: \"" -#: ../version.c:687 msgid " user exrc file: \"" msgstr " dosiero exrc de uzanto: \"" -#: ../version.c:692 msgid " 2nd user exrc file: \"" msgstr " 2-a dosiero exrc de uzanto: \"" -#: ../version.c:699 +msgid " system gvimrc file: \"" +msgstr " sistema dosiero gvimrc: \"" + +msgid " user gvimrc file: \"" +msgstr " dosiero gvimrc de uzanto: \"" + +msgid "2nd user gvimrc file: \"" +msgstr " 2-a dosiero gvimrc de uzanto: \"" + +msgid "3rd user gvimrc file: \"" +msgstr " 3-a dosiero gvimrc de uzanto: \"" + +msgid " defaults file: \"" +msgstr " dosiero de defaÅltoj: \"" + +msgid " system menu file: \"" +msgstr " dosiero de sistema menuo: \"" + msgid " fall-back for $VIM: \"" msgstr " defaÅlto de $VIM: \"" -#: ../version.c:705 msgid " f-b for $VIMRUNTIME: \"" msgstr " defaÅlto de VIMRUNTIME: \"" -#: ../version.c:709 msgid "Compilation: " msgstr "Kompilado: " -#: ../version.c:712 +msgid "Compiler: " +msgstr "Kompililo: " + msgid "Linking: " msgstr "Ligado: " -#: ../version.c:717 msgid " DEBUG BUILD" msgstr " SENCIMIGA MUNTO" -#: ../version.c:767 msgid "VIM - Vi IMproved" msgstr "VIM - Vi plibonigita" -#: ../version.c:769 msgid "version " msgstr "versio " # DP: vidu http://www.thefreedictionary.com/et+al. -#: ../version.c:770 msgid "by Bram Moolenaar et al." msgstr "de Bram Moolenaar kaj aliuloj" -#: ../version.c:774 msgid "Vim is open source and freely distributable" msgstr "Vim estas libera programo kaj disdoneblas libere" -#: ../version.c:776 msgid "Help poor children in Uganda!" msgstr "Helpu malriĉajn infanojn en Ugando!" # DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon -#: ../version.c:777 msgid "type :help iccf<Enter> for information " msgstr "tajpu :help iccf<Enenklavo> por pliaj informoj " # DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon -#: ../version.c:779 msgid "type :q<Enter> to exit " msgstr "tajpu :q<Enenklavo> por eliri " # DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon -#: ../version.c:780 msgid "type :help<Enter> or <F1> for on-line help" msgstr "tajpu :help<Enenklavo> aÅ <F1> por aliri la helpon " # DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon -#: ../version.c:781 -msgid "type :help version7<Enter> for version info" -msgstr "tajpu :help version7<Enenklavo> por informo de versio" +msgid "type :help version8<Enter> for version info" +msgstr "tajpu :help version8<Enenklavo> por informo de versio" -#: ../version.c:784 msgid "Running in Vi compatible mode" msgstr "RuliÄas en reÄimo kongrua kun Vi" # DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon -#: ../version.c:785 msgid "type :set nocp<Enter> for Vim defaults" msgstr "tajpu :set nocp<Enenklavo> por Vim defaÅltoj " # DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon -#: ../version.c:786 msgid "type :help cp-default<Enter> for info on this" msgstr "tajpu :help cp-default<Enenklavo> por pliaj informoj " -#: ../version.c:827 +# DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon +msgid "menu Help->Orphans for information " +msgstr "menuo Help->Orfinoj por pliaj informoj " + +msgid "Running modeless, typed text is inserted" +msgstr "RuliÄas senreÄime, tajpita teksto estas enmetita" + +# DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon +msgid "menu Edit->Global Settings->Toggle Insert Mode " +msgstr "menuo Redakti->Mallokaj Agordoj->Baskuligi Enmetan ReÄimon" + +# DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon +msgid " for two modes " +msgstr " por du reÄimoj " + +# DP: tiu ĉeno pli longas (mi ne volas igi ĉiujn aliajn ĉenojn +# pli longajn) +msgid "menu Edit->Global Settings->Toggle Vi Compatible" +msgstr "menuo Redakti->Mallokaj Agordoj->Baskuligi ReÄimon Kongruan kun Vi" + +# DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon +msgid " for Vim defaults " +msgstr " por defaÅltoj de Vim " + msgid "Sponsor Vim development!" msgstr "Subtenu la programadon de Vim!" -#: ../version.c:828 msgid "Become a registered Vim user!" msgstr "IÄu registrita uzanto de Vim!" # DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon -#: ../version.c:831 msgid "type :help sponsor<Enter> for information " msgstr "tajpu :help sponsor<Enenklavo> por pliaj informoj " # DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon -#: ../version.c:832 msgid "type :help register<Enter> for information " msgstr "tajpu :help register<Enenklavo> por pliaj informoj " # DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon -#: ../version.c:834 msgid "menu Help->Sponsor/Register for information " msgstr "menuo Helpo->Subteni/Registri por pliaj informoj " -#: ../window.c:119 msgid "Already only one window" msgstr "Jam nur unu fenestro" -#: ../window.c:224 msgid "E441: There is no preview window" msgstr "E441: Ne estas antaÅvida fenestro" -#: ../window.c:559 msgid "E442: Can't split topleft and botright at the same time" msgstr "E442: Ne eblas dividi supralivan kaj subdekstran samtempe" -#: ../window.c:1228 msgid "E443: Cannot rotate when another window is split" msgstr "E443: Ne eblas rotacii kiam alia fenestro estas dividita" -#: ../window.c:1803 msgid "E444: Cannot close last window" msgstr "E444: Ne eblas fermi la lastan fenestron" -#: ../window.c:1810 msgid "E813: Cannot close autocmd window" msgstr "E813: Ne eblas fermi la fenestron de aÅtokomandoj" -#: ../window.c:1814 msgid "E814: Cannot close window, only autocmd window would remain" msgstr "E814: Ne eblas fermi fenestron, nur la fenestro de aÅtokomandoj restus" -#: ../window.c:2717 msgid "E445: Other window contains changes" msgstr "E445: La alia fenestro enhavas ÅanÄojn" -#: ../window.c:4805 msgid "E446: No file name under cursor" msgstr "E446: Neniu dosiernomo sub la kursoro" -#~ msgid "E831: bf_key_init() called with empty password" -#~ msgstr "E831: bf_key_init() alvokita kun malplena pasvorto" - -#~ msgid "E820: sizeof(uint32_t) != 4" -#~ msgstr "E820: sizeof(uint32_t) != 4" - -#~ msgid "E817: Blowfish big/little endian use wrong" -#~ msgstr "E817: Misuzo de pezkomenca/pezfina en blowfish" - -#~ msgid "E818: sha256 test failed" -#~ msgstr "E818: Testo de sha256 fiaskis" - -#~ msgid "E819: Blowfish test failed" -#~ msgstr "E819: Testo de blowfish fiaskis" - -#~ msgid "Patch file" -#~ msgstr "Flika dosiero" - -#~ msgid "" -#~ "&OK\n" -#~ "&Cancel" -#~ msgstr "" -#~ "&Bone\n" -#~ "&Rezigni" - -#~ msgid "E240: No connection to Vim server" -#~ msgstr "E240: Neniu konekto al Vim-servilo" - -#~ msgid "E241: Unable to send to %s" -#~ msgstr "E241: Ne eblas sendi al %s" - -#~ msgid "E277: Unable to read a server reply" -#~ msgstr "E277: Ne eblas legi respondon de servilo" - -#~ msgid "E258: Unable to send to client" -#~ msgstr "E258: Ne eblas sendi al kliento" - -#~ msgid "Save As" -#~ msgstr "Konservi kiel" - -#~ msgid "Edit File" -#~ msgstr "Redakti dosieron" - -#~ msgid " (NOT FOUND)" -#~ msgstr " (NETROVITA)" - -#~ msgid "Source Vim script" -#~ msgstr "Ruli Vim-skripton" - -#~ msgid "unknown" -#~ msgstr "nekonata" - -#~ msgid "Edit File in new window" -#~ msgstr "Redakti Dosieron en nova fenestro" - -#~ msgid "Append File" -#~ msgstr "Postaldoni dosieron" - -#~ msgid "Window position: X %d, Y %d" -#~ msgstr "Pozicio de fenestro: X %d, Y %d" - -#~ msgid "Save Redirection" -#~ msgstr "Konservi alidirekton" - -# DP: mi ne certas pri superflugo -#~ msgid "Save View" -#~ msgstr "Konservi superflugon" - -#~ msgid "Save Session" -#~ msgstr "Konservi seancon" - -#~ msgid "Save Setup" -#~ msgstr "Konservi agordaron" - -#~ msgid "E809: #< is not available without the +eval feature" -#~ msgstr "E809: #< ne haveblas sen la eblo +eval" - -#~ msgid "E196: No digraphs in this version" -#~ msgstr "E196: Neniu duliteraĵo en tiu versio" - -#~ msgid "is a device (disabled with 'opendevice' option)" -#~ msgstr "estas aparatdosiero (malÅaltita per la opcio 'opendevice')" - -#~ msgid "Reading from stdin..." -#~ msgstr "Legado el stdin..." - -#~ msgid "[crypted]" -#~ msgstr "[ĉifrita]" - -#~ msgid "E821: File is encrypted with unknown method" -#~ msgstr "E821: Dosiero estas ĉifrata per nekonata metodo" - -#~ msgid "Warning: Using a weak encryption method; see :help 'cm'" -#~ msgstr "Averto: uzo de malfortika ĉifrada metodo; vidu :help 'cm'" - -#~ msgid "NetBeans disallows writes of unmodified buffers" -#~ msgstr "NetBeans malpermesas skribojn de neÅanÄitaj bufroj" - -#~ msgid "Partial writes disallowed for NetBeans buffers" -#~ msgstr "Partaj skriboj malpermesitaj ĉe bufroj NetBeans" - -#~ msgid "writing to device disabled with 'opendevice' option" -#~ msgstr "skribo al aparatdosiero malÅaltita per la opcio 'opendevice'" - -#~ msgid "E460: The resource fork would be lost (add ! to override)" -#~ msgstr "E460: La rimeda forko estus perdita (aldonu ! por transpasi)" - -#~ msgid "E851: Failed to create a new process for the GUI" -#~ msgstr "E851: Ne sukcesis krei novan procezon por la grafika interfaco" - -#~ msgid "E852: The child process failed to start the GUI" -#~ msgstr "E852: La ida procezo ne sukcesis startigi la grafikan interfacon" - -#~ msgid "E229: Cannot start the GUI" -#~ msgstr "E229: Ne eblas lanĉi la grafikan interfacon" - -#~ msgid "E230: Cannot read from \"%s\"" -#~ msgstr "E230: Ne eblas legi el \"%s\"" - -#~ msgid "E665: Cannot start GUI, no valid font found" -#~ msgstr "" -#~ "E665: Ne eblas startigi grafikan interfacon, neniu valida tiparo trovita" - -#~ msgid "E231: 'guifontwide' invalid" -#~ msgstr "E231: 'guifontwide' nevalida" - -#~ msgid "E599: Value of 'imactivatekey' is invalid" -#~ msgstr "E599: Valoro de 'imactivatekey' estas nevalida" - -#~ msgid "E254: Cannot allocate color %s" -#~ msgstr "E254: Ne eblas disponigi koloron %s" - -#~ msgid "No match at cursor, finding next" -#~ msgstr "Neniu kongruo ĉe kursorpozicio, trovas sekvan" - -#~ msgid "<cannot open> " -#~ msgstr "<ne eblas malfermi> " - -#~ msgid "E616: vim_SelFile: can't get font %s" -#~ msgstr "E616: vim_SelFile: ne eblas akiri tiparon %s" - -#~ msgid "E614: vim_SelFile: can't return to current directory" -#~ msgstr "E614: vim_SelFile: ne eblas reveni al la aktuala dosierujo" - -#~ msgid "Pathname:" -#~ msgstr "Serĉvojo:" - -#~ msgid "E615: vim_SelFile: can't get current directory" -#~ msgstr "E615: vim_SelFile: ne eblas akiri aktualan dosierujon" - -#~ msgid "OK" -#~ msgstr "Bone" - -#~ msgid "Cancel" -#~ msgstr "Rezigni" - -#~ msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." -#~ msgstr "" -#~ "Fenestraĵo de rulumskalo: Ne eblis akiri geometrion de reduktita " -#~ "rastrumbildo" - -#~ msgid "Vim dialog" -#~ msgstr "Vim dialogo" - -#~ msgid "E232: Cannot create BalloonEval with both message and callback" -#~ msgstr "E232: Ne eblas krei BalloonEval kun ambaÅ mesaÄo kaj reagfunkcio" - -msgid "Yes" -msgstr "Jes" - -msgid "No" -msgstr "Ne" - -# todo '_' is for hotkey, i guess? -#~ msgid "Input _Methods" -#~ msgstr "Enigaj _metodoj" - -#~ msgid "VIM - Search and Replace..." -#~ msgstr "VIM - Serĉi kaj anstataÅigi..." - -#~ msgid "VIM - Search..." -#~ msgstr "VIM- Serĉi..." - -#~ msgid "Find what:" -#~ msgstr "Serĉi kion:" - -#~ msgid "Replace with:" -#~ msgstr "AnstataÅigi per:" - -#~ msgid "Match whole word only" -#~ msgstr "Kongrui kun nur plena vorto" - -#~ msgid "Match case" -#~ msgstr "Uskleca kongruo" - -#~ msgid "Direction" -#~ msgstr "Direkto" - -#~ msgid "Up" -#~ msgstr "Supren" - -#~ msgid "Down" -#~ msgstr "Suben" - -#~ msgid "Find Next" -#~ msgstr "Trovi sekvantan" - -#~ msgid "Replace" -#~ msgstr "AnstataÅigi" - -#~ msgid "Replace All" -#~ msgstr "AnstataÅigi ĉiujn" - -#~ msgid "Vim: Received \"die\" request from session manager\n" -#~ msgstr "Vim: Ricevis peton \"die\" (morti) el la seanca administrilo\n" - -#~ msgid "Close tab" -#~ msgstr "Fermi langeton" - -#~ msgid "New tab" -#~ msgstr "Nova langeto" - -#~ msgid "Open Tab..." -#~ msgstr "Malfermi langeton..." - -#~ msgid "Vim: Main window unexpectedly destroyed\n" -#~ msgstr "Vim: Ĉefa fenestro neatendite detruiÄis\n" - -#~ msgid "&Filter" -#~ msgstr "&Filtri" - -#~ msgid "&Cancel" -#~ msgstr "&Rezigni" - -#~ msgid "Directories" -#~ msgstr "Dosierujoj" - -#~ msgid "Filter" -#~ msgstr "Filtri" - -#~ msgid "&Help" -#~ msgstr "&Helpo" - -#~ msgid "Files" -#~ msgstr "Dosieroj" - -#~ msgid "&OK" -#~ msgstr "&Bone" - -#~ msgid "Selection" -#~ msgstr "Apartigo" - -#~ msgid "Find &Next" -#~ msgstr "Trovi &Sekvanta" - -#~ msgid "&Replace" -#~ msgstr "&AnstataÅigi" - -#~ msgid "Replace &All" -#~ msgstr "AnstataÅigi ĉi&on" - -#~ msgid "&Undo" -#~ msgstr "&Malfari" - -#~ msgid "E671: Cannot find window title \"%s\"" -#~ msgstr "E671: Ne eblas trovi titolon de fenestro \"%s\"" - -#~ msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." -#~ msgstr "E243: Ne subtenata argumento: \"-%s\"; Uzu la version OLE." - -#~ msgid "E672: Unable to open window inside MDI application" -#~ msgstr "E672: Ne eblas malfermi fenestron interne de aplikaĵo MDI" - -#~ msgid "Open tab..." -#~ msgstr "Malfermi langeton..." - -#~ msgid "Find string (use '\\\\' to find a '\\')" -#~ msgstr "Trovi ĉenon (uzu '\\\\' por trovi '\\')" - -#~ msgid "Find & Replace (use '\\\\' to find a '\\')" -#~ msgstr "Trovi kaj anstataÅigi (uzu '\\\\' por trovi '\\')" - -#~ msgid "Not Used" -#~ msgstr "Ne uzata" - -#~ msgid "Directory\t*.nothing\n" -#~ msgstr "Dosierujo\t*.nenio\n" - -#~ msgid "" -#~ "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" -#~ msgstr "" -#~ "Vim E458: Ne eblas disponigi rikordon de kolormapo, iuj koloroj estas " -#~ "eble neÄustaj" - -#~ msgid "E250: Fonts for the following charsets are missing in fontset %s:" -#~ msgstr "E250: Tiparoj de tiuj signaroj mankas en aro de tiparo %s:" - -#~ msgid "E252: Fontset name: %s" -#~ msgstr "E252: Nomo de tiparo: %s" - -#~ msgid "Font '%s' is not fixed-width" -#~ msgstr "Tiparo '%s' ne estas egallarÄa" - -#~ msgid "E253: Fontset name: %s\n" -#~ msgstr "E253: Nomo de tiparo: %s\n" - -#~ msgid "Font0: %s\n" -#~ msgstr "Font0: %s\n" - -#~ msgid "Font1: %s\n" -#~ msgstr "Font1: %s\n" - -#~ msgid "Font%<PRId64> width is not twice that of font0\n" -#~ msgstr "Font%<PRId64> ne estas duoble pli larÄa ol font0\n" - -#~ msgid "Font0 width: %<PRId64>\n" -#~ msgstr "LarÄo de font0: %<PRId64>\n" - -#~ msgid "" -#~ "Font1 width: %<PRId64>\n" -#~ "\n" -#~ msgstr "" -#~ "LarÄo de Font1: %<PRId64>\n" -#~ "\n" - -#~ msgid "Invalid font specification" -#~ msgstr "Nevalida tiparo specifita" - -#~ msgid "&Dismiss" -#~ msgstr "&Forlasi" - -#~ msgid "no specific match" -#~ msgstr "Neniu specifa kongruo" - -#~ msgid "Vim - Font Selector" -#~ msgstr "Vim - Elektilo de tiparo" - -#~ msgid "Name:" -#~ msgstr "Nomo:" - -#~ msgid "Show size in Points" -#~ msgstr "Montri grandon en punktoj" - -#~ msgid "Encoding:" -#~ msgstr "Kodoprezento:" - -#~ msgid "Font:" -#~ msgstr "Tiparo:" - -#~ msgid "Style:" -#~ msgstr "Stilo:" - -#~ msgid "Size:" -#~ msgstr "Grando:" - -#~ msgid "E256: Hangul automata ERROR" -#~ msgstr "E256: ERARO en aÅtomato de korea alfabeto" - -#~ msgid "E563: stat error" -#~ msgstr "E563: Eraro de stat" - -#~ msgid "E625: cannot open cscope database: %s" -#~ msgstr "E625: ne eblas malfermi datumbazon de cscope: %s" - -#~ msgid "E626: cannot get cscope database information" -#~ msgstr "E626: ne eblas akiri informojn pri la datumbazo de cscope" - -#~ msgid "Lua library cannot be loaded." -#~ msgstr "La biblioteko Lua no Åargeblis." - -#~ msgid "cannot save undo information" -#~ msgstr "ne eblas konservi informojn de malfaro" - -#~ msgid "" -#~ "E815: Sorry, this command is disabled, the MzScheme libraries could not " -#~ "be loaded." -#~ msgstr "" -#~ "E815: BedaÅrinde, tiu komando estas malÅaltita, ne eblis Åargi la " -#~ "bibliotekojn." - -#~ msgid "invalid expression" -#~ msgstr "nevalida esprimo" - -#~ msgid "expressions disabled at compile time" -#~ msgstr "esprimoj malÅaltitaj dum kompilado" - -#~ msgid "hidden option" -#~ msgstr "kaÅita opcio" - -#~ msgid "unknown option" -#~ msgstr "nekonata opcio" - -#~ msgid "window index is out of range" -#~ msgstr "indekso de fenestro estas ekster limoj" - -#~ msgid "couldn't open buffer" -#~ msgstr "ne eblis malfermi bufron" - -#~ msgid "cannot delete line" -#~ msgstr "ne eblas forviÅi linion" - -#~ msgid "cannot replace line" -#~ msgstr "ne eblas anstataÅigi linion" - -#~ msgid "cannot insert line" -#~ msgstr "ne eblas enmeti linion" - -#~ msgid "string cannot contain newlines" -#~ msgstr "ĉeno ne rajtas enhavi liniavancojn" - -#~ msgid "error converting Scheme values to Vim" -#~ msgstr "eraro dum konverto de Scheme-valoro al Vim" - -#~ msgid "Vim error: ~a" -#~ msgstr "Eraro de Vim: ~a" - -#~ msgid "Vim error" -#~ msgstr "Eraro de Vim" - -#~ msgid "buffer is invalid" -#~ msgstr "bufro estas nevalida" - -#~ msgid "window is invalid" -#~ msgstr "fenestro estas nevalida" - -#~ msgid "linenr out of range" -#~ msgstr "numero de linio ekster limoj" - -#~ msgid "not allowed in the Vim sandbox" -#~ msgstr "nepermesebla en sabloludejo de Vim" - -#~ msgid "E836: This Vim cannot execute :python after using :py3" -#~ msgstr "E836: Vim ne povas plenumi :python post uzo de :py3" - -#~ msgid "only string keys are allowed" -#~ msgstr "nur ĉenaj Ålosiloj estas permeseblaj" - -#~ msgid "" -#~ "E263: Sorry, this command is disabled, the Python library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E263: BedaÅrinde tiu komando estas malÅaltita: la biblioteko de Pitono ne " -#~ "Åargeblis." - -#~ msgid "E659: Cannot invoke Python recursively" -#~ msgstr "E659: Ne eblas alvoki Pitonon rekursie" - -#~ msgid "E837: This Vim cannot execute :py3 after using :python" -#~ msgstr "E837: Vim ne povas plenumi :py3 post uzo de :python" - -#~ msgid "index must be int or slice" -#~ msgstr "indekso devas esti 'int' aÅ 'slice'" - -#~ msgid "E265: $_ must be an instance of String" -#~ msgstr "E265: $_ devas esti apero de Ĉeno" - -#~ msgid "" -#~ "E266: Sorry, this command is disabled, the Ruby library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E266: BedaÅrinde tiu komando estas malÅaltita, la biblioteko Ruby ne " -#~ "Åargeblis." - -#~ msgid "E267: unexpected return" -#~ msgstr "E267: \"return\" neatendita" - -#~ msgid "E268: unexpected next" -#~ msgstr "E268: \"next\" neatendita" - -#~ msgid "E269: unexpected break" -#~ msgstr "E269: \"break\" neatendita" - -#~ msgid "E270: unexpected redo" -#~ msgstr "E270: \"redo\" neatendita" - -#~ msgid "E271: retry outside of rescue clause" -#~ msgstr "E271: \"retry\" ekster klaÅzo \"rescue\"" - -#~ msgid "E272: unhandled exception" -#~ msgstr "E272: netraktita escepto" - -#~ msgid "E273: unknown longjmp status %d" -#~ msgstr "E273: nekonata stato de longjmp: %d" - -#~ msgid "Toggle implementation/definition" -#~ msgstr "Baskuligi realigon/difinon" - -#~ msgid "Show base class of" -#~ msgstr "Vidigi bazan klason de" - -#~ msgid "Show overridden member function" -#~ msgstr "Montri anajn homonimigajn funkciojn" - -#~ msgid "Retrieve from file" -#~ msgstr "Rekuperi el dosiero" - -#~ msgid "Retrieve from project" -#~ msgstr "Rekuperi el projekto" - -#~ msgid "Retrieve from all projects" -#~ msgstr "Rekuperi de ĉiuj projektoj" - -#~ msgid "Retrieve" -#~ msgstr "Rekuperi" - -#~ msgid "Show source of" -#~ msgstr "Vidigi fonton de" - -#~ msgid "Find symbol" -#~ msgstr "Trovi simbolon" - -#~ msgid "Browse class" -#~ msgstr "Foliumi klasojn" - -#~ msgid "Show class in hierarchy" -#~ msgstr "Montri klason en hierarkio" - -#~ msgid "Show class in restricted hierarchy" -#~ msgstr "Montri klason en hierarkio restriktita" - -# todo -#~ msgid "Xref refers to" -#~ msgstr "Xref ligas al" - -#~ msgid "Xref referred by" -#~ msgstr "Xref ligiÄas de" - -#~ msgid "Xref has a" -#~ msgstr "Xref havas" - -#~ msgid "Xref used by" -#~ msgstr "Xref uzita de" - -# DP: mi ne certas pri kio temas -#~ msgid "Show docu of" -#~ msgstr "Vidigi dokumentaron de" - -#~ msgid "Generate docu for" -#~ msgstr "Krei dokumentaron de" - -#~ msgid "" -#~ "Cannot connect to SNiFF+. Check environment (sniffemacs must be found in " -#~ "$PATH).\n" -#~ msgstr "" -#~ "Konekto al SNiFF+ neeblas. Kontrolu medion (sniffemacs trovendas en " -#~ "$PATH).\n" - -#~ msgid "E274: Sniff: Error during read. Disconnected" -#~ msgstr "E274: Sniff: Eraro dum lego. Malkonektita" - -# DP: Tiuj 3 mesaÄoj estas kune -#~ msgid "SNiFF+ is currently " -#~ msgstr "SNiFF+ estas aktuale " - -#~ msgid "not " -#~ msgstr "ne " - -#~ msgid "connected" -#~ msgstr "konektita" - -#~ msgid "E275: Unknown SNiFF+ request: %s" -#~ msgstr "E275: Nekonata peto de SNiFF+: %s" - -#~ msgid "E276: Error connecting to SNiFF+" -#~ msgstr "E276: Eraro dum konekto al SNiFF+" - -#~ msgid "E278: SNiFF+ not connected" -#~ msgstr "E278: SNiFF+ ne estas konektita" - -#~ msgid "E279: Not a SNiFF+ buffer" -#~ msgstr "E279: Ne estas bufro SNiFF+" - -#~ msgid "Sniff: Error during write. Disconnected" -#~ msgstr "Sniff: Eraro dum skribo. Malkonektita" - -#~ msgid "invalid buffer number" -#~ msgstr "nevalida numero de bufro" - -#~ msgid "not implemented yet" -#~ msgstr "ankoraÅ ne realigita" - -#~ msgid "cannot set line(s)" -#~ msgstr "ne eblas meti la linio(j)n" - -#~ msgid "invalid mark name" -#~ msgstr "nevalida nomo de marko" - -#~ msgid "mark not set" -#~ msgstr "marko ne estas metita" - -#~ msgid "row %d column %d" -#~ msgstr "linio %d kolumno %d" - -#~ msgid "cannot insert/append line" -#~ msgstr "ne eblas enmeti/postaldoni linion" - -#~ msgid "line number out of range" -#~ msgstr "numero de linio ekster limoj" - -#~ msgid "unknown flag: " -#~ msgstr "nekonata flago: " - -# DP: ĉu traduki vimOption -#~ msgid "unknown vimOption" -#~ msgstr "nekonata vimOption" - -#~ msgid "keyboard interrupt" -#~ msgstr "klavara interrompo" - -#~ msgid "vim error" -#~ msgstr "eraro de Vim" - -#~ msgid "cannot create buffer/window command: object is being deleted" -#~ msgstr "" -#~ "ne eblas krei komandon de bufro/fenestro: objekto estas forviÅiÄanta" - -#~ msgid "" -#~ "cannot register callback command: buffer/window is already being deleted" -#~ msgstr "" -#~ "ne eblas registri postalvokan komandon: bufro/fenestro estas jam " -#~ "forviÅiÄanta" - -#~ msgid "" -#~ "E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-" -#~ "dev@vim.org" -#~ msgstr "" -#~ "E280: NERIPAREBLA TCL-ERARO: reflist difekta!? Bv. retpoÅti al vim-" -#~ "dev@vim.org" - -#~ msgid "cannot register callback command: buffer/window reference not found" -#~ msgstr "" -#~ "ne eblas registri postalvokan komandon: referenco de bufro/fenestro ne " -#~ "troveblas" - -#~ msgid "" -#~ "E571: Sorry, this command is disabled: the Tcl library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E571: BedaÅrinde tiu komando estas malÅaltita: la biblioteko Tcl ne " -#~ "Åargeblis." - -#~ msgid "E572: exit code %d" -#~ msgstr "E572: elira kodo %d" - -#~ msgid "cannot get line" -#~ msgstr "ne eblas akiri linion" - -#~ msgid "Unable to register a command server name" -#~ msgstr "Ne eblas registri nomon de komanda servilo" - -#~ msgid "E248: Failed to send command to the destination program" -#~ msgstr "E248: Sendo de komando al cela programo fiaskis" - -#~ msgid "E573: Invalid server id used: %s" -#~ msgstr "E573: Nevalida identigilo de servilo uzita: %s" - -#~ msgid "E251: VIM instance registry property is badly formed. Deleted!" -#~ msgstr "" -#~ "E251: Ecoj de registro de apero de VIM estas nevalide formata. ForviÅita!" - -#~ msgid "netbeans is not supported with this GUI\n" -#~ msgstr "netbeans ne estas subtenata kun tiu grafika interfaco\n" - -#~ msgid "This Vim was not compiled with the diff feature." -#~ msgstr "Tiu Vim ne estis kompilita kun la kompara eblo." - -#~ msgid "'-nb' cannot be used: not enabled at compile time\n" -#~ msgstr "'-nb' ne uzeblas: malÅaltita dum kompilado\n" - -#~ msgid "Vim: Error: Failure to start gvim from NetBeans\n" -#~ msgstr "Vim: Eraro: Fiaskis lanĉi gvim el NetBeans\n" - -#~ msgid "" -#~ "\n" -#~ "Where case is ignored prepend / to make flag upper case" -#~ msgstr "" -#~ "\n" -#~ "Kie uskleco estas ignorita antaÅaldonu / por igi flagon majuskla" - -#~ msgid "-register\t\tRegister this gvim for OLE" -#~ msgstr "-register\t\tRegistri tiun gvim al OLE" - -#~ msgid "-unregister\t\tUnregister gvim for OLE" -#~ msgstr "-unregister\t\tMalregistri gvim de OLE" - -#~ msgid "-g\t\t\tRun using GUI (like \"gvim\")" -#~ msgstr "-g\t\t\tRuli per grafika interfaco (kiel \"gvim\")" - -#~ msgid "-f or --nofork\tForeground: Don't fork when starting GUI" -#~ msgstr "-f aÅ --nofork\tMalfono: ne forki kiam lanĉas grafikan interfacon" - -#~ msgid "-f\t\t\tDon't use newcli to open window" -#~ msgstr "-f\t\t\tNe uzi newcli por malfermi fenestrojn" - -#~ msgid "-dev <device>\t\tUse <device> for I/O" -#~ msgstr "-dev <aparatdosiero>\t\tUzi <aparatdosiero>-n por eneligo" - -#~ msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" -#~ msgstr "-U <gvimrc>\t\tUzi <gvimrc> anstataÅ iun ajn .gvimrc" - -#~ msgid "-x\t\t\tEdit encrypted files" -#~ msgstr "-x\t\t\tRedakti ĉifradan dosieron" - -#~ msgid "-display <display>\tConnect vim to this particular X-server" -#~ msgstr "-display <ekrano>\tKonekti Vim al tiu X-servilo" - -#~ msgid "-X\t\t\tDo not connect to X server" -#~ msgstr "-X\t\t\tNe konekti al X-servilo" - -#~ msgid "--remote <files>\tEdit <files> in a Vim server if possible" -#~ msgstr "--remote <dosieroj>\tRedakti <dosieroj>-n en Vim-servilo se eblas" - -#~ msgid "--remote-silent <files> Same, don't complain if there is no server" -#~ msgstr "--remote-silent <dosieroj> Same, sed ne plendi se ne estas servilo" - -#~ msgid "" -#~ "--remote-wait <files> As --remote but wait for files to have been edited" -#~ msgstr "" -#~ "--remote-wait <dosieroj> Kiel --remote sed atendi Äis dosieroj estas " -#~ "redaktitaj" - -#~ msgid "" -#~ "--remote-wait-silent <files> Same, don't complain if there is no server" -#~ msgstr "" -#~ "--remote-wait-silent <dosieroj> Same, sed ne plendi se ne estas servilo" - -#~ msgid "" -#~ "--remote-tab[-wait][-silent] <files> As --remote but use tab page per " -#~ "file" -#~ msgstr "" -#~ "--remote-tab[-wait][-silent] <dosieroj> Kiel --remote sed uzi langeton " -#~ "por ĉiu dosiero" - -#~ msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" -#~ msgstr "--remote-send <klavoj> Sendi <klavoj>-n al Vim-servilo kaj eliri" - -#~ msgid "" -#~ "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" -#~ msgstr "" -#~ "--remote-expr <espr>\tKomputi <espr> en Vim-servilo kaj afiÅi rezulton" - -#~ msgid "--serverlist\t\tList available Vim server names and exit" -#~ msgstr "--serverlist\t\tListigi haveblajn nomojn de Vim-serviloj kaj eliri" - -#~ msgid "--servername <name>\tSend to/become the Vim server <name>" -#~ msgstr "--servername <nomo>\tSendu al/iÄi la Vim-servilo <nomo>" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (Motif version):\n" -#~ msgstr "" -#~ "\n" -#~ "Argumentoj agnoskitaj de gvim (versio Motif):\n" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (neXtaw version):\n" -#~ msgstr "" -#~ "\n" -#~ "Argumentoj agnoskitaj de gvim (versio neXtaw):\n" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (Athena version):\n" -#~ msgstr "" -#~ "\n" -#~ "Argumentoj agnoskitaj de gvim (versio Athena):\n" - -#~ msgid "-display <display>\tRun vim on <display>" -#~ msgstr "-display <ekrano>\tLanĉi vim sur <ekrano>" - -#~ msgid "-iconic\t\tStart vim iconified" -#~ msgstr "-iconic\t\tLanĉi vim piktograme" - -#~ msgid "-background <color>\tUse <color> for the background (also: -bg)" -#~ msgstr "" -#~ "-background <koloro>\tUzi <koloro>-n por la fona koloro (ankaÅ: -bg)" - -#~ msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" -#~ msgstr "" -#~ "-foreground <koloro>\tUzi <koloro>-n por la malfona koloro (ankaÅ: -fg)" - -#~ msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" -#~ msgstr "-font <tiparo>\tUzi <tiparo>-n por normala teksto (ankaÅ: -fn)" - -#~ msgid "-boldfont <font>\tUse <font> for bold text" -#~ msgstr "-boldfont <tiparo>\tUzi <tiparo>-n por grasa teksto" - -#~ msgid "-italicfont <font>\tUse <font> for italic text" -#~ msgstr "-italicfont <tiparo>\tUzi <tiparo>-n por kursiva teksto" - -#~ msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" -#~ msgstr "-geometry <geom>\tUzi <geom> kiel komenca geometrio (ankaÅ: -geom)" - -#~ msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" -#~ msgstr "" -#~ "-borderwidth <larÄo>\tUzi <larÄo>-n kiel larÄo de bordero (ankaÅ: -bw)" - -#~ msgid "" -#~ "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" -#~ msgstr "" -#~ "-scrollbarwidth <larÄo> Uzi <larÄo>-n kiel larÄo de rulumskalo (ankaÅ: -" -#~ "sw)" - -#~ msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" -#~ msgstr "" -#~ "-menuheight <alto>\tUzi <alto>-n kiel alto de menuzona alto (ankaÅ: -mh)" - -#~ msgid "-reverse\t\tUse reverse video (also: -rv)" -#~ msgstr "-reverse\t\tUzi inversan videon (ankaÅ: -rv)" - -#~ msgid "+reverse\t\tDon't use reverse video (also: +rv)" -#~ msgstr "+reverse\t\tNe uzi inversan videon (ankaÅ: +rv)" +#, c-format +msgid "E447: Can't find file \"%s\" in path" +msgstr "E447: Ne eblas trovi dosieron \"%s\" en serĉvojo" -#~ msgid "-xrm <resource>\tSet the specified resource" -#~ msgstr "-xrm <rimedo>\tAgordi la specifitan <rimedo>-n" +#, c-format +msgid "E799: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E799: Nevalida ID: %ld (devas esti egala aÅ pli granda ol 1)" -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (GTK+ version):\n" -#~ msgstr "" -#~ "\n" -#~ "Argumentoj agnoskitaj de gvim (versio GTK+):\n" +#, c-format +msgid "E801: ID already taken: %ld" +msgstr "E801: ID jam uzata: %ld" -#~ msgid "-display <display>\tRun vim on <display> (also: --display)" -#~ msgstr "-display <ekrano>\tLanĉi Vim sur tiu <ekrano> (ankaÅ: --display)" +msgid "List or number required" +msgstr "Listo aÅ nombro bezonata" -#~ msgid "--role <role>\tSet a unique role to identify the main window" -#~ msgstr "--role <rolo>\tDoni unikan rolon por identigi la ĉefan fenestron" +#, c-format +msgid "E802: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E802: Nevalida ID: %ld (devas esti egala aÅ pli granda ol 1)" -#~ msgid "--socketid <xid>\tOpen Vim inside another GTK widget" -#~ msgstr "--socketid <xid>\tMalfermi Vim en alia GTK fenestraĵo" +#, c-format +msgid "E803: ID not found: %ld" +msgstr "E803: ID netrovita: %ld" -#~ msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" -#~ msgstr "--echo-wid\t\tIgas gvim afiÅi la identigilon de vindozo sur stdout" +#, c-format +msgid "E370: Could not load library %s" +msgstr "E370: Ne eblis Åargi bibliotekon %s" -#~ msgid "-P <parent title>\tOpen Vim inside parent application" -#~ msgstr "-P <gepatra titolo>\tMalfermi Vim en gepatra aplikaĵo" +msgid "Sorry, this command is disabled: the Perl library could not be loaded." +msgstr "" +"BedaÅrinde tiu komando estas malÅaltita: la biblioteko de Perl ne Åargeblis." -#~ msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" -#~ msgstr "--windowid <HWND>\tMalfermi Vim en alia win32 fenestraĵo" +msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" +msgstr "" +"E299: Plenumo de Perl esprimoj malpermesata en sabloludejo sen la modulo Safe" -#~ msgid "No display" -#~ msgstr "Neniu ekrano" +msgid "Edit with &multiple Vims" +msgstr "Redakti per &pluraj Vim-oj" -#~ msgid ": Send failed.\n" -#~ msgstr ": Sendo fiaskis.\n" +msgid "Edit with single &Vim" +msgstr "Redakti per unuopa &Vim" -#~ msgid ": Send failed. Trying to execute locally\n" -#~ msgstr ": Sendo fiaskis. Provo de loka plenumo\n" +msgid "Diff with Vim" +msgstr "Kompari per Vim" -#~ msgid "%d of %d edited" -#~ msgstr "%d de %d redaktita(j)" +msgid "Edit with &Vim" +msgstr "Redakti per &Vim" -#~ msgid "No display: Send expression failed.\n" -#~ msgstr "Neniu ekrano: Sendado de esprimo fiaskis.\n" +#. Now concatenate +msgid "Edit with existing Vim - " +msgstr "Redakti per ekzistanta Vim - " -#~ msgid ": Send expression failed.\n" -#~ msgstr ": Sendado de esprimo fiaskis.\n" +msgid "Edits the selected file(s) with Vim" +msgstr "Redakti la apartigita(j)n dosiero(j)n per Vim" -#~ msgid "E543: Not a valid codepage" -#~ msgstr "E543: Nevalida kodpaÄo" +msgid "Error creating process: Check if gvim is in your path!" +msgstr "Eraro dum kreo de procezo: Kontrolu ĉu gvim estas en via serĉvojo!" -#~ msgid "E284: Cannot set IC values" -#~ msgstr "E284: Ne eblas agordi valorojn de IC" +msgid "gvimext.dll error" +msgstr "Eraro de gvimext.dll" -#~ msgid "E285: Failed to create input context" -#~ msgstr "E285: Ne eblis krei enigan kuntekston" +msgid "Path length too long!" +msgstr "Serĉvojo estas tro longa!" -#~ msgid "E286: Failed to open input method" -#~ msgstr "E286: Ne eblis malfermi enigan metodon" +msgid "--No lines in buffer--" +msgstr "--Neniu linio en bufro--" -#~ msgid "E287: Warning: Could not set destroy callback to IM" -#~ msgstr "E287: Averto: Ne eblis agordi detruan reagfunkcion al IM" +#. +#. * The error messages that can be shared are included here. +#. * Excluded are errors that are only used once and debugging messages. +#. +msgid "E470: Command aborted" +msgstr "E470: komando ĉesigita" -#~ msgid "E288: input method doesn't support any style" -#~ msgstr "E288: eniga metodo subtenas neniun stilon" +msgid "E471: Argument required" +msgstr "E471: Argumento bezonata" -# DP: mi ne scias, kio estas "preedit" -#~ msgid "E289: input method doesn't support my preedit type" -#~ msgstr "E289: eniga metodo ne subtenas mian antaÅredaktan tipon" - -#~ msgid "E843: Error while updating swap file crypt" -#~ msgstr "E843: Eraro dum Äisdatigo de ĉifrada permutodosiero .swp" - -#~ msgid "" -#~ "E833: %s is encrypted and this version of Vim does not support encryption" -#~ msgstr "E833: %s estas ĉifrata kaj tiu versio de Vim ne subtenas ĉifradon" - -#~ msgid "Swap file is encrypted: \"%s\"" -#~ msgstr "Perumutodosiero .swp estas ĉifrata: \"%s\"" - -#~ msgid "" -#~ "\n" -#~ "If you entered a new crypt key but did not write the text file," -#~ msgstr "" -#~ "\n" -#~ "Se vi tajpis novan Ålosilon de ĉifrado sed ne skribis la tekstan dosieron," - -#~ msgid "" -#~ "\n" -#~ "enter the new crypt key." -#~ msgstr "" -#~ "\n" -#~ "tajpu la novan Ålosilon de ĉifrado." +msgid "E10: \\ should be followed by /, ? or &" +msgstr "E10: \\ devus esti sekvita de /, ? aÅ &" -#~ msgid "" -#~ "\n" -#~ "If you wrote the text file after changing the crypt key press enter" -#~ msgstr "" -#~ "\n" -#~ "Se vi skribis la tekstan dosieron post ÅanÄo de la Ålosilo de ĉifrado, " -#~ "premu enenklavon" +msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" +msgstr "" +"E11: Nevalida en fenestro de komanda linio; <CR> plenumas, CTRL-C eliras" -#~ msgid "" -#~ "\n" -#~ "to use the same key for text file and swap file" -#~ msgstr "" -#~ "\n" -#~ "por uzi la saman Ålosilon por la teksta dosiero kaj permuto dosiero .swp" +msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" +msgstr "" +"E12: Nepermesebla komando el exrc/vimrc en aktuala dosierujo aÅ etikeda serĉo" -#~ msgid "Using crypt key from swap file for the text file.\n" -#~ msgstr "" -#~ "Uzas Ålosilon de ĉifrado el permuto dosiero .swp por la teksta dosiero.\n" +msgid "E171: Missing :endif" +msgstr "E171: Mankas \":endif\"" -#~ msgid "" -#~ "\n" -#~ " [not usable with this version of Vim]" -#~ msgstr "" -#~ "\n" -#~ " [ne uzebla per tiu versio de Vim]" +msgid "E600: Missing :endtry" +msgstr "E600: Mankas \":endtry\"" -#~ msgid "Tear off this menu" -#~ msgstr "Disigi tiun menuon" +msgid "E170: Missing :endwhile" +msgstr "E170: Mankas \":endwhile\"" -#~ msgid "Select Directory dialog" -#~ msgstr "Dialogujo de dosiera elekto" +msgid "E170: Missing :endfor" +msgstr "E170: Mankas \":endfor\"" -#~ msgid "Save File dialog" -#~ msgstr "Dialogujo de dosiera konservo" +msgid "E588: :endwhile without :while" +msgstr "E588: \":endwhile\" sen \":while\"" -#~ msgid "Open File dialog" -#~ msgstr "Dialogujo de dosiera malfermo" +msgid "E588: :endfor without :for" +msgstr "E588: \":endfor\" sen \":for\"" -#~ msgid "E338: Sorry, no file browser in console mode" -#~ msgstr "E338: BedaÅrinde ne estas dosierfoliumilo en konzola reÄimo" +msgid "E13: File exists (add ! to override)" +msgstr "E13: Dosiero ekzistas (aldonu ! por transpasi)" -#~ msgid "Vim: preserving files...\n" -#~ msgstr "Vim: konservo de dosieroj...\n" +msgid "E472: Command failed" +msgstr "E472: La komando malsukcesis" -#~ msgid "Vim: Finished.\n" -#~ msgstr "Vim: Finita.\n" +#, c-format +msgid "E234: Unknown fontset: %s" +msgstr "E234: Nekonata familio de tiparo: %s" -#~ msgid "ERROR: " -#~ msgstr "ERARO: " +#, c-format +msgid "E235: Unknown font: %s" +msgstr "E235: Nekonata tiparo: %s" -#~ msgid "" -#~ "\n" -#~ "[bytes] total alloc-freed %<PRIu64>-%<PRIu64>, in use %<PRIu64>, peak use " -#~ "%<PRIu64>\n" -#~ msgstr "" -#~ "\n" -#~ "[bajtoj] totalaj disponigitaj/maldisponigitaj %<PRIu64>-%<PRIu64>, nun " -#~ "uzataj %<PRIu64>, kulmina uzo %<PRIu64>\n" +#, c-format +msgid "E236: Font \"%s\" is not fixed-width" +msgstr "E236: La tiparo \"%s\" ne estas egallarÄa" -#~ msgid "" -#~ "[calls] total re/malloc()'s %<PRIu64>, total free()'s %<PRIu64>\n" -#~ "\n" -#~ msgstr "" -#~ "[alvokoj] totalaj re/malloc() %<PRIu64>, totalaj free() %<PRIu64>\n" -#~ "\n" +msgid "E473: Internal error" +msgstr "E473: Interna eraro" -#~ msgid "E340: Line is becoming too long" -#~ msgstr "E340: Linio iÄas tro longa" +#, c-format +msgid "E685: Internal error: %s" +msgstr "E685: Interna eraro: %s" -#~ msgid "E341: Internal error: lalloc(%<PRId64>, )" -#~ msgstr "E341: Interna eraro: lalloc(%<PRId64>, )" +msgid "Interrupted" +msgstr "Interrompita" -#~ msgid "E547: Illegal mouseshape" -#~ msgstr "E547: Nevalida formo de muskursoro" +msgid "E14: Invalid address" +msgstr "E14: Nevalida adreso" -#~ msgid "Enter encryption key: " -#~ msgstr "Tajpu la Ålosilon de ĉifrado: " +msgid "E474: Invalid argument" +msgstr "E474: Nevalida argumento" -#~ msgid "Enter same key again: " -#~ msgstr "Tajpu la Ålosilon denove: " +#, c-format +msgid "E475: Invalid argument: %s" +msgstr "E475: Nevalida argumento: %s" -#~ msgid "Keys don't match!" -#~ msgstr "Åœlosiloj ne kongruas!" +#, c-format +msgid "E15: Invalid expression: %s" +msgstr "E15: Nevalida esprimo: %s" -#~ msgid "Cannot connect to Netbeans #2" -#~ msgstr "Ne eblas konekti al Netbeans n-ro 2" +msgid "E16: Invalid range" +msgstr "E16: Nevalida amplekso" -#~ msgid "Cannot connect to Netbeans" -#~ msgstr "Ne eblas konekti al Netbeans" +msgid "E476: Invalid command" +msgstr "E476: Nevalida komando" -#~ msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" -#~ msgstr "" -#~ "E668: Nevalida permeso de dosiero de informo de konekto NetBeans: \"%s\"" +#, c-format +msgid "E17: \"%s\" is a directory" +msgstr "E17: \"%s\" estas dosierujo" -#~ msgid "read from Netbeans socket" -#~ msgstr "lego el kontaktoskatolo de Netbeans" +#, c-format +msgid "E364: Library call failed for \"%s()\"" +msgstr "E364: Alvoko al biblioteko malsukcesis por \"%s()\"" -#~ msgid "E658: NetBeans connection lost for buffer %<PRId64>" -#~ msgstr "E658: Konekto de NetBeans perdita por bufro %<PRId64>" +#, c-format +msgid "E448: Could not load library function %s" +msgstr "E448: Ne eblis Åargi bibliotekan funkcion %s" -#~ msgid "E838: netbeans is not supported with this GUI" -#~ msgstr "E838: netbeans ne estas subtenata kun tiu grafika interfaco" +msgid "E19: Mark has invalid line number" +msgstr "E19: Marko havas nevalidan numeron de linio" -#~ msgid "E511: netbeans already connected" -#~ msgstr "E511: nebeans jam konektata" +msgid "E20: Mark not set" +msgstr "E20: Marko ne estas agordita" -#~ msgid "E505: %s is read-only (add ! to override)" -#~ msgstr "E505: %s estas nurlegebla (aldonu ! por transpasi)" +msgid "E21: Cannot make changes, 'modifiable' is off" +msgstr "E21: Ne eblas fari ÅanÄojn, 'modifiable' estas malÅaltita" -# DP: ĉu Eval devas esti tradukita? -#~ msgid "E775: Eval feature not available" -#~ msgstr "E775: Eval eblo ne disponeblas" +msgid "E22: Scripts nested too deep" +msgstr "E22: Tro profunde ingitaj skriptoj" -#~ msgid "freeing %<PRId64> lines" -#~ msgstr "malokupas %<PRId64> liniojn" +msgid "E23: No alternate file" +msgstr "E23: Neniu alterna dosiero" -#~ msgid "E530: Cannot change term in GUI" -#~ msgstr "E530: term ne ÅanÄeblas en grafika interfaco" +msgid "E24: No such abbreviation" +msgstr "E24: Ne estas tia mallongigo" -#~ msgid "E531: Use \":gui\" to start the GUI" -#~ msgstr "E531: Uzu \":gui\" por lanĉi la grafikan interfacon" +msgid "E477: No ! allowed" +msgstr "E477: Neniu ! permesebla" -#~ msgid "E617: Cannot be changed in the GTK+ 2 GUI" -#~ msgstr "E617: Ne ÅanÄeblas en la grafika interfaco GTK+ 2" +msgid "E25: GUI cannot be used: Not enabled at compile time" +msgstr "E25: Grafika interfaco ne uzeblas: MalÅaltita dum kompilado" -#~ msgid "E596: Invalid font(s)" -#~ msgstr "E596: Nevalida(j) tiparo(j)" +msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" +msgstr "E26: La hebrea ne uzeblas: MalÅaltita dum kompilado\n" -#~ msgid "E597: can't select fontset" -#~ msgstr "E597: ne eblas elekti tiparon" +msgid "E27: Farsi cannot be used: Not enabled at compile time\n" +msgstr "E27: La persa ne uzeblas: MalÅaltita dum kompilado\n" -#~ msgid "E598: Invalid fontset" -#~ msgstr "E598: Nevalida tiparo" +msgid "E800: Arabic cannot be used: Not enabled at compile time\n" +msgstr "E800: La araba ne uzeblas: MalÅaltita dum kompilado\n" -#~ msgid "E533: can't select wide font" -#~ msgstr "E533: ne eblas elekti larÄan tiparon" +#, c-format +msgid "E28: No such highlight group name: %s" +msgstr "E28: Neniu grupo de emfazo kiel: %s" -#~ msgid "E534: Invalid wide font" -#~ msgstr "E534: Nevalida larÄa tiparo" +msgid "E29: No inserted text yet" +msgstr "E29: AnkoraÅ neniu enmetita teksto" -#~ msgid "E538: No mouse support" -#~ msgstr "E538: Neniu muso subtenata" +msgid "E30: No previous command line" +msgstr "E30: Neniu antaÅa komanda linio" -#~ msgid "cannot open " -#~ msgstr "ne eblas malfermi " +msgid "E31: No such mapping" +msgstr "E31: Neniu tiel mapo" -#~ msgid "VIM: Can't open window!\n" -#~ msgstr "VIM: Ne eblas malfermi fenestron!\n" +msgid "E479: No match" +msgstr "E479: Neniu kongruo" -#~ msgid "Need Amigados version 2.04 or later\n" -#~ msgstr "Bezonas version 2.04 de Amigados aÅ pli novan\n" +#, c-format +msgid "E480: No match: %s" +msgstr "E480: Neniu kongruo: %s" -#~ msgid "Need %s version %<PRId64>\n" -#~ msgstr "Bezonas %s-on versio %<PRId64>\n" +msgid "E32: No file name" +msgstr "E32: Neniu dosiernomo" -#~ msgid "Cannot open NIL:\n" -#~ msgstr "Ne eblas malfermi NIL:\n" +msgid "E33: No previous substitute regular expression" +msgstr "E33: Neniu antaÅa regulesprimo de anstataÅigo" -#~ msgid "Cannot create " -#~ msgstr "Ne eblas krei " +msgid "E34: No previous command" +msgstr "E34: Neniu antaÅa komando" -#~ msgid "Vim exiting with %d\n" -#~ msgstr "Vim eliras kun %d\n" +msgid "E35: No previous regular expression" +msgstr "E35: Neniu antaÅa regulesprimo" -#~ msgid "cannot change console mode ?!\n" -#~ msgstr "ne eblas ÅanÄi reÄimon de konzolo?!\n" +msgid "E481: No range allowed" +msgstr "E481: Amplekso nepermesebla" -#~ msgid "mch_get_shellsize: not a console??\n" -#~ msgstr "mch_get_shellsize: ne estas konzolo??\n" +msgid "E36: Not enough room" +msgstr "E36: Ne sufiĉe da spaco" -#~ msgid "E360: Cannot execute shell with -f option" -#~ msgstr "E360: Ne eblas plenumi Åelon kun opcio -f" +#, c-format +msgid "E247: no registered server named \"%s\"" +msgstr "E247: neniu registrita servilo nomita \"%s\"" -#~ msgid "Cannot execute " -#~ msgstr "Ne eblas plenumi " +#, c-format +msgid "E482: Can't create file %s" +msgstr "E482: Ne eblas krei dosieron %s" -#~ msgid "shell " -#~ msgstr "Åelo " +msgid "E483: Can't get temp file name" +msgstr "E483: Ne eblas akiri provizoran dosiernomon" -#~ msgid " returned\n" -#~ msgstr " liveris\n" +#, c-format +msgid "E484: Can't open file %s" +msgstr "E484: Ne eblas malfermi dosieron %s" -#~ msgid "ANCHOR_BUF_SIZE too small." -#~ msgstr "ANCHOR_BUF_SIZE tro malgranda." +#, c-format +msgid "E485: Can't read file %s" +msgstr "E485: Ne eblas legi dosieron %s" -#~ msgid "I/O ERROR" -#~ msgstr "ERARO DE ENIGO/ELIGO" +msgid "E37: No write since last change (add ! to override)" +msgstr "E37: Neniu skribo de post lasta ÅanÄo (aldonu ! por transpasi)" -#~ msgid "Message" -#~ msgstr "MesaÄo" +msgid "E37: No write since last change" +msgstr "E37: Neniu skribo de post lasta ÅanÄo" -#~ msgid "'columns' is not 80, cannot execute external commands" -#~ msgstr "'columns' ne estas 80, ne eblas plenumi eksternajn komandojn" +msgid "E38: Null argument" +msgstr "E38: Nula argumento" -#~ msgid "E237: Printer selection failed" -#~ msgstr "E237: Elekto de presilo fiaskis" +msgid "E39: Number expected" +msgstr "E39: Nombro atendita" -#~ msgid "to %s on %s" -#~ msgstr "al %s de %s" +#, c-format +msgid "E40: Can't open errorfile %s" +msgstr "E40: Ne eblas malfermi eraran dosieron %s" -#~ msgid "E613: Unknown printer font: %s" -#~ msgstr "E613: Nekonata tiparo de presilo: %s" +msgid "E233: cannot open display" +msgstr "E233: ne eblas malfermi vidigon" -#~ msgid "E238: Print error: %s" -#~ msgstr "E238: Eraro de presado: %s" +msgid "E41: Out of memory!" +msgstr "E41: Ne plu restas memoro!" -#~ msgid "Printing '%s'" -#~ msgstr "Presas '%s'" +msgid "Pattern not found" +msgstr "Åœablono ne trovita" -#~ msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" -#~ msgstr "E244: Nevalida nomo de signaro \"%s\" en nomo de tiparo \"%s\"" +#, c-format +msgid "E486: Pattern not found: %s" +msgstr "E486: Åœablono ne trovita: %s" -#~ msgid "E245: Illegal char '%c' in font name \"%s\"" -#~ msgstr "E245: Nevalida signo '%c' en nomo de tiparo \"%s\"" +msgid "E487: Argument must be positive" +msgstr "E487: La argumento devas esti pozitiva" -#~ msgid "Vim: Double signal, exiting\n" -#~ msgstr "Vim: Duobla signalo, eliranta\n" +msgid "E459: Cannot go back to previous directory" +msgstr "E459: Ne eblas reiri al antaÅa dosierujo" -#~ msgid "Vim: Caught deadly signal %s\n" -#~ msgstr "Vim: Kaptis mortigantan signalon %s\n" +msgid "E42: No Errors" +msgstr "E42: Neniu eraro" -#~ msgid "Vim: Caught deadly signal\n" -#~ msgstr "Vim: Kaptis mortigantan signalon\n" +msgid "E776: No location list" +msgstr "E776: Neniu listo de lokoj" -#~ msgid "Opening the X display took %<PRId64> msec" -#~ msgstr "Malfermo de vidigo X daÅris %<PRId64> msek" +msgid "E43: Damaged match string" +msgstr "E43: Difekta kongruenda ĉeno" -#~ msgid "" -#~ "\n" -#~ "Vim: Got X error\n" -#~ msgstr "" -#~ "\n" -#~ "Vim: Alvenis X eraro\n" +msgid "E44: Corrupted regexp program" +msgstr "E44: Difekta programo de regulesprimo" -#~ msgid "Testing the X display failed" -#~ msgstr "Testo de la vidigo X fiaskis" +msgid "E45: 'readonly' option is set (add ! to override)" +msgstr "E45: La opcio 'readonly' estas Åaltita '(aldonu ! por transpasi)" -#~ msgid "Opening the X display timed out" -#~ msgstr "Tempolimo okazis dum malfermo de vidigo X" +#, c-format +msgid "E46: Cannot change read-only variable \"%s\"" +msgstr "E46: Ne eblas ÅanÄi nurlegeblan variablon \"%s\"" -#~ msgid "" -#~ "\n" -#~ "Cannot execute shell sh\n" -#~ msgstr "" -#~ "\n" -#~ "Ne eblas plenumi Åelon sh\n" +#, c-format +msgid "E794: Cannot set variable in the sandbox: \"%s\"" +msgstr "E794: Ne eblas agordi variablon en la sabloludejo: \"%s\"" -#~ msgid "" -#~ "\n" -#~ "Cannot create pipes\n" -#~ msgstr "" -#~ "\n" -#~ "Ne eblas krei duktojn\n" +msgid "E713: Cannot use empty key for Dictionary" +msgstr "E713: Ne eblas uzi malplenan Ålosilon de Vortaro" -#~ msgid "" -#~ "\n" -#~ "Cannot fork\n" -#~ msgstr "" -#~ "\n" -#~ "Ne eblas forki\n" +msgid "E715: Dictionary required" +msgstr "E715: Vortaro bezonata" -#~ msgid "" -#~ "\n" -#~ "Command terminated\n" -#~ msgstr "" -#~ "\n" -#~ "Komando terminigita\n" +#, c-format +msgid "E684: list index out of range: %ld" +msgstr "E684: indekso de listo ekster limoj: %ld" -#~ msgid "XSMP lost ICE connection" -#~ msgstr "XSMP perdis la konekton ICE" +#, c-format +msgid "E118: Too many arguments for function: %s" +msgstr "E118: Tro da argumentoj por funkcio: %s" -#~ msgid "Opening the X display failed" -#~ msgstr "Malfermo de vidigo X fiaskis" +#, c-format +msgid "E716: Key not present in Dictionary: %s" +msgstr "E716: Åœlosilo malekzistas en Vortaro: %s" -#~ msgid "XSMP handling save-yourself request" -#~ msgstr "XSMP: traktado de peto konservi-mem" +msgid "E714: List required" +msgstr "E714: Listo bezonata" -#~ msgid "XSMP opening connection" -#~ msgstr "XSMP: malfermo de konekto" +#, c-format +msgid "E712: Argument of %s must be a List or Dictionary" +msgstr "E712: Argumento de %s devas esti Listo aÅ Vortaro" -#~ msgid "XSMP ICE connection watch failed" -#~ msgstr "XSMP: kontrolo de konekto ICE fiaskis" +msgid "E47: Error while reading errorfile" +msgstr "E47: Eraro dum legado de erardosiero" -#~ msgid "XSMP SmcOpenConnection failed: %s" -#~ msgstr "XSMP: SmcOpenConnection fiaskis: %s" +msgid "E48: Not allowed in sandbox" +msgstr "E48: Nepermesebla en sabloludejo" -#~ msgid "At line" -#~ msgstr "Ĉe linio" +msgid "E523: Not allowed here" +msgstr "E523: Nepermesebla tie" -#~ msgid "Could not load vim32.dll!" -#~ msgstr "Ne eblis Åargi vim32.dll!" +msgid "E359: Screen mode setting not supported" +msgstr "E359: ReÄimo de ekrano ne subtenata" -#~ msgid "VIM Error" -#~ msgstr "Eraro de VIM" +msgid "E49: Invalid scroll size" +msgstr "E49: Nevalida grando de rulumo" -#~ msgid "Could not fix up function pointers to the DLL!" -#~ msgstr "Ne eblis ripari referencojn de funkcioj al la DLL!" +msgid "E91: 'shell' option is empty" +msgstr "E91: La opcio 'shell' estas malplena" -#~ msgid "shell returned %d" -#~ msgstr "la Åelo liveris %d" +msgid "E255: Couldn't read in sign data!" +msgstr "E255: Ne eblis legi datumojn de simboloj!" -# DP: la eventoj estas tiuj, kiuj estas en la sekvantaj ĉenoj -#~ msgid "Vim: Caught %s event\n" -#~ msgstr "Vim: Kaptis eventon %s\n" +msgid "E72: Close error on swap file" +msgstr "E72: Eraro dum malfermo de permutodosiero .swp" -#~ msgid "close" -#~ msgstr "fermo" +msgid "E73: tag stack empty" +msgstr "E73: malplena stako de etikedo" -#~ msgid "logoff" -#~ msgstr "elsaluto" +msgid "E74: Command too complex" +msgstr "E74: Komando tro kompleksa" -#~ msgid "shutdown" -#~ msgstr "sistemfermo" +msgid "E75: Name too long" +msgstr "E75: Nomo tro longa" -#~ msgid "E371: Command not found" -#~ msgstr "E371: Netrovebla komando" +msgid "E76: Too many [" +msgstr "E76: Tro da [" -#~ msgid "" -#~ "VIMRUN.EXE not found in your $PATH.\n" -#~ "External commands will not pause after completion.\n" -#~ "See :help win32-vimrun for more information." -#~ msgstr "" -#~ "VIMRUN.EXE ne troveblas en via $PATH.\n" -#~ "Eksteraj komandoj ne paÅzos post kompletigo.\n" -#~ "Vidu :help win32-vimrun por pliaj informoj." - -#~ msgid "Vim Warning" -#~ msgstr "Averto de Vim" - -#~ msgid "Error file" -#~ msgstr "Erara Dosiero" - -#~ msgid "E868: Error building NFA with equivalence class!" -#~ msgstr "E868: Eraro dum prekomputado de NFA kun ekvivalentoklaso!" - -#~ msgid "E999: (NFA regexp internal error) Should not process NOT node !" -#~ msgstr "" -#~ "E999: (interna eraro de NFA-regulesprimo) Ne devus procezi nodon 'NOT'!" - -#~ msgid "E878: (NFA) Could not allocate memory for branch traversal!" -#~ msgstr "E878: (NFA) Ne povis asigni memoron por traigi branĉojn!" - -#~ msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" -#~ msgstr "Averto: Ne eblas trovi vortliston \"%s_%s.spl\" aÅ \"%s_ascii.spl\"" - -#~ msgid "Conversion in %s not supported" -#~ msgstr "Konverto en %s nesubtenata" - -#~ msgid "E845: Insufficient memory, word list will be incomplete" -#~ msgstr "E845: Ne sufiĉe da memoro, vortlisto estos nekompleta." - -#~ msgid "E430: Tag file path truncated for %s\n" -#~ msgstr "E430: Vojo de etikeda dosiero trunkita por %s\n" - -#~ msgid "new shell started\n" -#~ msgstr "nova Åelo lanĉita\n" - -#~ msgid "Used CUT_BUFFER0 instead of empty selection" -#~ msgstr "Uzis CUT_BUFFER0 anstataÅ malplenan apartigon" - -#~ msgid "No undo possible; continue anyway" -#~ msgstr "Malfaro neebla; daÅrigi tamene" - -#~ msgid "E832: Non-encrypted file has encrypted undo file: %s" -#~ msgstr "E832: Ne ĉifrata dosiero havas ĉifratan malfaran dosieron: %s" - -#~ msgid "E826: Undo file decryption failed: %s" -#~ msgstr "E826: Malĉifrado de malfara dosiero fiaskis: %s" - -#~ msgid "E827: Undo file is encrypted: %s" -#~ msgstr "E827: Malfara dosiero estas ĉifrata: %s" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16/32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Grafika versio MS-Vindozo 16/32-bitoj" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Grafika versio MS-Vindozo 64-bitoj" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Grafika versio MS-Vindozo 32-bitoj" - -#~ msgid " in Win32s mode" -#~ msgstr " en reÄimo Win32s" - -#~ msgid " with OLE support" -#~ msgstr " kun subteno de OLE" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit console version" -#~ msgstr "" -#~ "\n" -#~ "Versio konzola MS-Vindozo 64-bitoj" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit console version" -#~ msgstr "" -#~ "\n" -#~ "Versio konzola MS-Vindozo 32-bitoj" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16-bit version" -#~ msgstr "" -#~ "\n" -#~ "Versio MS-Vindozo 16-bitoj" - -#~ msgid "" -#~ "\n" -#~ "32-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "Versio MS-DOS 32-bitoj" - -#~ msgid "" -#~ "\n" -#~ "16-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "Versio MS-DOS 16-bitoj" - -#~ msgid "" -#~ "\n" -#~ "MacOS X (unix) version" -#~ msgstr "" -#~ "\n" -#~ "Versio Mak OS X (unikso)" - -#~ msgid "" -#~ "\n" -#~ "MacOS X version" -#~ msgstr "" -#~ "\n" -#~ "Versio Mak OS X" - -#~ msgid "" -#~ "\n" -#~ "MacOS version" -#~ msgstr "" -#~ "\n" -#~ "Versio Mak OS" - -#~ msgid "" -#~ "\n" -#~ "OpenVMS version" -#~ msgstr "" -#~ "\n" -#~ "Versio OpenVMS" - -#~ msgid "" -#~ "\n" -#~ "Big version " -#~ msgstr "" -#~ "\n" -#~ "Granda versio " - -#~ msgid "" -#~ "\n" -#~ "Normal version " -#~ msgstr "" -#~ "\n" -#~ "Normala versio " - -#~ msgid "" -#~ "\n" -#~ "Small version " -#~ msgstr "" -#~ "\n" -#~ "Malgranda versio " - -#~ msgid "" -#~ "\n" -#~ "Tiny version " -#~ msgstr "" -#~ "\n" -#~ "Malgrandega versio " - -#~ msgid "with GTK2-GNOME GUI." -#~ msgstr "kun grafika interfaco GTK2-GNOME." - -#~ msgid "with GTK2 GUI." -#~ msgstr "kun grafika interfaco GTK2." - -#~ msgid "with X11-Motif GUI." -#~ msgstr "kun grafika interfaco X11-Motif." - -#~ msgid "with X11-neXtaw GUI." -#~ msgstr "kun grafika interfaco X11-neXtaw." - -#~ msgid "with X11-Athena GUI." -#~ msgstr "kun grafika interfaco X11-Athena." - -#~ msgid "with Photon GUI." -#~ msgstr "kun grafika interfaco Photon." - -#~ msgid "with GUI." -#~ msgstr "sen grafika interfaco." - -#~ msgid "with Carbon GUI." -#~ msgstr "kun grafika interfaco Carbon." - -#~ msgid "with Cocoa GUI." -#~ msgstr "kun grafika interfaco Cocoa." - -#~ msgid "with (classic) GUI." -#~ msgstr "kun (klasika) grafika interfaco." - -#~ msgid " system gvimrc file: \"" -#~ msgstr " sistema dosiero gvimrc: \"" - -#~ msgid " user gvimrc file: \"" -#~ msgstr " dosiero gvimrc de uzanto: \"" - -#~ msgid "2nd user gvimrc file: \"" -#~ msgstr " 2-a dosiero gvimrc de uzanto: \"" - -#~ msgid "3rd user gvimrc file: \"" -#~ msgstr " 3-a dosiero gvimrc de uzanto: \"" - -#~ msgid " system menu file: \"" -#~ msgstr " dosiero de sistema menuo: \"" - -#~ msgid "Compiler: " -#~ msgstr "Kompililo: " +msgid "E77: Too many file names" +msgstr "E77: Tro da dosiernomoj" -# DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon -#~ msgid "menu Help->Orphans for information " -#~ msgstr "menuo Help->Orfinoj por pliaj informoj " +msgid "E488: Trailing characters" +msgstr "E488: Vostaj signoj" -#~ msgid "Running modeless, typed text is inserted" -#~ msgstr "RuliÄas senreÄime, tajpita teksto estas enmetita" +msgid "E78: Unknown mark" +msgstr "E78: Nekonata marko" -# DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon -#~ msgid "menu Edit->Global Settings->Toggle Insert Mode " -#~ msgstr "menuo Redakti->Mallokaj Agordoj->Baskuligi Enmetan ReÄimon" +msgid "E79: Cannot expand wildcards" +msgstr "E79: Ne eblas malvolvi ĵokerojn" -# DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon -#~ msgid " for two modes " -#~ msgstr " por du reÄimoj " +msgid "E591: 'winheight' cannot be smaller than 'winminheight'" +msgstr "E591: 'winheight' ne rajtas esti malpli ol 'winminheight'" -# DP: tiu ĉeno pli longas (mi ne volas igi ĉiujn aliajn ĉenojn -# pli longajn) -#~ msgid "menu Edit->Global Settings->Toggle Vi Compatible" -#~ msgstr "menuo Redakti->Mallokaj Agordoj->Baskuligi ReÄimon Kongruan kun Vi" +msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" +msgstr "E592: 'winwidth' ne rajtas esti malpli ol 'winminwidth'" -# DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon -#~ msgid " for Vim defaults " -#~ msgstr " por defaÅltoj de Vim " +msgid "E80: Error while writing" +msgstr "E80: Eraro dum skribado" -#~ msgid "WARNING: Windows 95/98/ME detected" -#~ msgstr "AVERTO: Trovis Vindozon 95/98/ME" +msgid "Zero count" +msgstr "Nul kvantoro" -# DP: atentu al la spacetoj: ĉiuj ĉenoj devas havi la saman longon -#~ msgid "type :help windows95<Enter> for info on this" -#~ msgstr "tajpu :help windows95<Enenklavo> por pliaj informoj " +msgid "E81: Using <SID> not in a script context" +msgstr "E81: Uzo de <SID> ekster kunteksto de skripto" -#~ msgid "E370: Could not load library %s" -#~ msgstr "E370: Ne eblis Åargi bibliotekon %s" +msgid "E449: Invalid expression received" +msgstr "E449: Nevalida esprimo ricevita" -#~ msgid "" -#~ "Sorry, this command is disabled: the Perl library could not be loaded." -#~ msgstr "" -#~ "BedaÅrinde tiu komando estas malÅaltita: la biblioteko de Perl ne " -#~ "Åargeblis." +msgid "E463: Region is guarded, cannot modify" +msgstr "E463: Regiono estas gardita, ne eblas ÅanÄi" -#~ msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" -#~ msgstr "" -#~ "E299: Plenumo de Perl esprimoj malpermesata en sabloludejo sen la modulo " -#~ "Safe" +msgid "E744: NetBeans does not allow changes in read-only files" +msgstr "E744: NetBeans ne permesas ÅanÄojn en nurlegeblaj dosieroj" -#~ msgid "Edit with &multiple Vims" -#~ msgstr "Redakti per &pluraj Vim-oj" +msgid "E363: pattern uses more memory than 'maxmempattern'" +msgstr "E363: Åablono uzas pli da memoro ol 'maxmempattern'" -#~ msgid "Edit with single &Vim" -#~ msgstr "Redakti per unuopa &Vim" +msgid "E749: empty buffer" +msgstr "E749: malplena bufro" -#~ msgid "Diff with Vim" -#~ msgstr "Kompari per Vim" +#, c-format +msgid "E86: Buffer %ld does not exist" +msgstr "E86: La bufro %ld ne ekzistas" -#~ msgid "Edit with &Vim" -#~ msgstr "Redakti per &Vim" +msgid "E682: Invalid search pattern or delimiter" +msgstr "E682: Nevalida serĉa Åablono aÅ disigilo" -#~ msgid "Edit with existing Vim - " -#~ msgstr "Redakti per ekzistanta Vim - " +msgid "E139: File is loaded in another buffer" +msgstr "E139: Dosiero estas Åargita en alia bufro" -#~ msgid "Edits the selected file(s) with Vim" -#~ msgstr "Redakti la apartigita(j)n dosiero(j)n per Vim" +#, c-format +msgid "E764: Option '%s' is not set" +msgstr "E764: La opcio '%s' ne estas Åaltita" -#~ msgid "Error creating process: Check if gvim is in your path!" -#~ msgstr "Eraro dum kreo de procezo: Kontrolu ĉu gvim estas en via serĉvojo!" +msgid "E850: Invalid register name" +msgstr "E850: Nevalida nomo de reÄistro" -#~ msgid "gvimext.dll error" -#~ msgstr "Eraro de gvimext.dll" +#, c-format +msgid "E919: Directory not found in '%s': \"%s\"" +msgstr "E919: Dosierujo ne trovita en '%s': \"%s\"" -#~ msgid "Path length too long!" -#~ msgstr "Serĉvojo estas tro longa!" +msgid "search hit TOP, continuing at BOTTOM" +msgstr "serĉo atingis SUPRON, daÅrigonte al SUBO" -#~ msgid "E234: Unknown fontset: %s" -#~ msgstr "E234: Nekonata familio de tiparo: %s" +msgid "search hit BOTTOM, continuing at TOP" +msgstr "serĉo atingis SUBON, daÅrigonte al SUPRO" -#~ msgid "E235: Unknown font: %s" -#~ msgstr "E235: Nekonata tiparo: %s" +#, c-format +msgid "Need encryption key for \"%s\"" +msgstr "Åœlosilo de ĉifrado bezonata por \"%s\"" -#~ msgid "E236: Font \"%s\" is not fixed-width" -#~ msgstr "E236: La tiparo \"%s\" ne estas egallarÄa" +msgid "empty keys are not allowed" +msgstr "malplenaj Ålosiloj nepermeseblaj" -#~ msgid "E448: Could not load library function %s" -#~ msgstr "E448: Ne eblis Åargi bibliotekan funkcion %s" +msgid "dictionary is locked" +msgstr "vortaro estas Ålosita" -#~ msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" -#~ msgstr "E26: La hebrea ne uzeblas: MalÅaltita dum kompilado\n" +msgid "list is locked" +msgstr "listo estas Ålosita" -#~ msgid "E27: Farsi cannot be used: Not enabled at compile time\n" -#~ msgstr "E27: La persa ne uzeblas: MalÅaltita dum kompilado\n" +#, c-format +msgid "failed to add key '%s' to dictionary" +msgstr "aldono de Ålosilo '%s' al vortaro malsukcesis" -#~ msgid "E800: Arabic cannot be used: Not enabled at compile time\n" -#~ msgstr "E800: La araba ne uzeblas: MalÅaltita dum kompilado\n" +#, c-format +msgid "index must be int or slice, not %s" +msgstr "indekso devas esti 'int' aÅ 'slice', ne %s" -#~ msgid "E247: no registered server named \"%s\"" -#~ msgstr "E247: neniu registrita servilo nomita \"%s\"" +#, c-format +msgid "expected str() or unicode() instance, but got %s" +msgstr "atendis aperon de str() aÅ unicode(), sed ricevis %s" -#~ msgid "E233: cannot open display" -#~ msgstr "E233: ne eblas malfermi vidigon" +#, c-format +msgid "expected bytes() or str() instance, but got %s" +msgstr "atendis aperon de bytes() aÅ str(), sed ricevis %s" -#~ msgid "E449: Invalid expression received" -#~ msgstr "E449: Nevalida esprimo ricevita" +#, c-format +msgid "" +"expected int(), long() or something supporting coercing to long(), but got %s" +msgstr "atendis int(), long() aÅ ion konverteblan al long(), sed ricevis %s" -#~ msgid "E463: Region is guarded, cannot modify" -#~ msgstr "E463: Regiono estas gardita, ne eblas ÅanÄi" +#, c-format +msgid "expected int() or something supporting coercing to int(), but got %s" +msgstr "atendis int() aÅ ion konverteblan al int(), sed ricevis %s" -#~ msgid "E744: NetBeans does not allow changes in read-only files" -#~ msgstr "E744: NetBeans ne permesas ÅanÄojn en nurlegeblaj dosieroj" +msgid "value is too large to fit into C int type" +msgstr "valoro estas tro grada por C-tipo 'int'" -#~ msgid "Need encryption key for \"%s\"" -#~ msgstr "Åœlosilo de ĉifrado bezonata por \"%s\"" +msgid "value is too small to fit into C int type" +msgstr "valoro estas tro malgranda por C-tipo 'int'" -#~ msgid "can't delete OutputObject attributes" -#~ msgstr "ne eblas forviÅi atributojn de OutputObject" +msgid "number must be greater than zero" +msgstr "nombro devas esti pli granda ol nul" -#~ msgid "softspace must be an integer" -#~ msgstr "malmolspaceto (softspace) devas esti entjero" +msgid "number must be greater or equal to zero" +msgstr "nombro devas esti egala aÅ pli granda ol nul" -#~ msgid "invalid attribute" -#~ msgstr "nevalida atributo" +msgid "can't delete OutputObject attributes" +msgstr "ne eblas forviÅi atributojn de OutputObject" -#~ msgid "writelines() requires list of strings" -#~ msgstr "writelines() bezonas liston de ĉenoj" +#, c-format +msgid "invalid attribute: %s" +msgstr "nevalida atributo: %s" -#~ msgid "E264: Python: Error initialising I/O objects" -#~ msgstr "E264: Pitono: Eraro de pravalorizo de eneligaj objektoj" +msgid "E264: Python: Error initialising I/O objects" +msgstr "E264: Pitono: Eraro de pravalorizo de eneligaj objektoj" -#~ msgid "empty keys are not allowed" -#~ msgstr "malplenaj Ålosiloj nepermeseblaj" +msgid "failed to change directory" +msgstr "malsukcesis ÅanÄi dosierujon" -#~ msgid "Cannot delete DictionaryObject attributes" -#~ msgstr "ne eblas forviÅi atributojn de DictionaryObject" +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got %s" +msgstr "atendis 3-opon kiel rezulto de imp.find_module(), sed ricevis %s" -#~ msgid "Cannot modify fixed dictionary" -#~ msgstr "Ne eblas ÅanÄi fiksan vortaron" +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got tuple of size %d" +msgstr "atendis 3-opon kiel rezulto de imp.find_module(), sed ricevis %d-opon" -#~ msgid "Cannot set this attribute" -#~ msgstr "Ne eblas agordi tiun atributon" +msgid "internal error: imp.find_module returned tuple with NULL" +msgstr "interna eraro: imp.find_module liveris opon kun NULL" -#~ msgid "dict is locked" -#~ msgstr "vortaro estas Ålosita" +msgid "cannot delete vim.Dictionary attributes" +msgstr "ne eblas forviÅi atributojn de 'vim.Dictionary'" -#~ msgid "failed to add key to dictionary" -#~ msgstr "aldono de Ålosilo al vortaro fiaskis" +msgid "cannot modify fixed dictionary" +msgstr "ne eblas ÅanÄi fiksan vortaron" -#~ msgid "list index out of range" -#~ msgstr "indekso de listo ekster limoj" +#, c-format +msgid "cannot set attribute %s" +msgstr "ne eblas agordi atributon %s" -#~ msgid "internal error: failed to get vim list item" -#~ msgstr "interna eraro: obteno de vim-a listero fiaskis" +msgid "hashtab changed during iteration" +msgstr "hakettabelo ÅanÄiÄis dum iteracio" -#~ msgid "list is locked" -#~ msgstr "listo estas Ålosita" +#, c-format +msgid "expected sequence element of size 2, but got sequence of size %d" +msgstr "atendis 2-longan sekvencon, sed ricevis %d-longan sekvencon" -#~ msgid "Failed to add item to list" -#~ msgstr "Aldono de listero fiaskis" +msgid "list constructor does not accept keyword arguments" +msgstr "konstruilo de listo ne akceptas Ålosilvortajn argumentojn" -#~ msgid "can only assign lists to slice" -#~ msgstr "nur eblas pravalorizi listojn al segmento" +msgid "list index out of range" +msgstr "indekso de listo ekster limoj" -#~ msgid "internal error: failed to add item to list" -#~ msgstr "interna eraro: aldono de listero fiaskis" +#. No more suitable format specifications in python-2.3 +#, c-format +msgid "internal error: failed to get vim list item %d" +msgstr "interna eraro: obteno de vim-a listero %d malsukcesis" -#~ msgid "can only concatenate with lists" -#~ msgstr "eblas nur kunmeti kun listoj" +msgid "slice step cannot be zero" +msgstr "paÅo de sekco ne povas esti nul" -#~ msgid "cannot delete vim.dictionary attributes" -#~ msgstr "ne eblas forviÅi atributojn de 'vim.dictionary'" +#, c-format +msgid "attempt to assign sequence of size greater than %d to extended slice" +msgstr "provis valorizi sekvencon kun pli ol %d eroj en etendita sekco" -#~ msgid "cannot modify fixed list" -#~ msgstr "ne eblas ÅanÄi fiksan liston" +#, c-format +msgid "internal error: no vim list item %d" +msgstr "interna eraro: neniu vim-a listero %d" -#~ msgid "cannot set this attribute" -#~ msgstr "ne eblas agordi tiun atributon" +msgid "internal error: not enough list items" +msgstr "interna eraro: ne sufiĉaj listeroj" -#~ msgid "'self' argument must be a dictionary" -#~ msgstr "argumento 'self' devas esti vortaro" +msgid "internal error: failed to add item to list" +msgstr "interna eraro: aldono de listero malsukcesis" -#~ msgid "failed to run function" -#~ msgstr "fiaskis ruli funkcion" +#, c-format +msgid "attempt to assign sequence of size %d to extended slice of size %d" +msgstr "provis valorizi sekvencon kun %d eroj al etendita sekco kun %d eroj" -#~ msgid "unable to unset global option" -#~ msgstr "ne povis malÅalti mallokan opcion" +msgid "failed to add item to list" +msgstr "aldono de listero malsukcesis" -#~ msgid "unable to unset option without global value" -#~ msgstr "ne povis malÅalti opcion sen malloka valoro" +msgid "cannot delete vim.List attributes" +msgstr "ne eblas forviÅi atributojn de 'vim.List'" -#~ msgid "object must be integer" -#~ msgstr "objekto devas esti entjero." +msgid "cannot modify fixed list" +msgstr "ne eblas ÅanÄi fiksan liston" -#~ msgid "object must be string" -#~ msgstr "objekto devas esti ĉeno" +#, c-format +msgid "unnamed function %s does not exist" +msgstr "sennoma funkcio %s ne ekzistas" -#~ msgid "attempt to refer to deleted tab page" -#~ msgstr "provo de referenco al forviÅita langeto" +#, c-format +msgid "function %s does not exist" +msgstr "funkcio %s ne ekzistas" -#~ msgid "<tabpage object (deleted) at %p>" -#~ msgstr "<langeta objekto (forviÅita) ĉe %p>" +#, c-format +msgid "failed to run function %s" +msgstr "malsukcesis ruli funkcion %s" -#~ msgid "<tabpage object (unknown) at %p>" -#~ msgstr "<langeta objekto (nekonata) ĉe %p>" +msgid "unable to get option value" +msgstr "malsukcesis akiri valoron de opcio" -#~ msgid "<tabpage %d>" -#~ msgstr "<langeto %d>" +msgid "internal error: unknown option type" +msgstr "interna eraro: nekonata tipo de opcio" -#~ msgid "no such tab page" -#~ msgstr "ne estas tia langeto" +msgid "problem while switching windows" +msgstr "problemo dum salto al vindozoj" -#~ msgid "attempt to refer to deleted window" -#~ msgstr "provo de referenco al forviÅita fenestro" +#, c-format +msgid "unable to unset global option %s" +msgstr "ne povis malÅalti mallokan opcion %s" -#~ msgid "readonly attribute" -#~ msgstr "nurlegebla atributo" +#, c-format +msgid "unable to unset option %s which does not have global value" +msgstr "ne povis malÅalti opcion %s, kiu ne havas mallokan valoron" -#~ msgid "cursor position outside buffer" -#~ msgstr "kursoro poziciita ekster bufro" +msgid "attempt to refer to deleted tab page" +msgstr "provo de referenco al forviÅita langeto" -#~ msgid "<window object (deleted) at %p>" -#~ msgstr "<fenestra objekto (forviÅita) ĉe %p>" +msgid "no such tab page" +msgstr "ne estas tia langeto" -#~ msgid "<window object (unknown) at %p>" -#~ msgstr "<objekta fenestro (nekonata) ĉe %p>" +msgid "attempt to refer to deleted window" +msgstr "provo de referenco al forviÅita fenestro" -#~ msgid "<window %d>" -#~ msgstr "<fenestro %d>" +msgid "readonly attribute: buffer" +msgstr "nurlegebla atributo: buffer" -#~ msgid "no such window" -#~ msgstr "ne estas tia fenestro" +msgid "cursor position outside buffer" +msgstr "kursoro poziciita ekster bufro" -#~ msgid "attempt to refer to deleted buffer" -#~ msgstr "provo de referenco al forviÅita bufro" +msgid "no such window" +msgstr "ne estas tia fenestro" -#~ msgid "<buffer object (deleted) at %p>" -#~ msgstr "<bufra objekto (forviÅita) ĉe %p>" +msgid "attempt to refer to deleted buffer" +msgstr "provo de referenco al forviÅita bufro" -#~ msgid "key must be integer" -#~ msgstr "Ålosilo devas esti entjero." +msgid "failed to rename buffer" +msgstr "malsukcesis renomi bufron" -#~ msgid "expected vim.buffer object" -#~ msgstr "atendis objekton vim.buffer" +msgid "mark name must be a single character" +msgstr "nomo de marko devas esti unuopa signo" -#~ msgid "failed to switch to given buffer" -#~ msgstr "ne povis salti al la specifita bufro" +#, c-format +msgid "expected vim.Buffer object, but got %s" +msgstr "atendis objekton vim.Buffer, sed ricevis %s" -#~ msgid "expected vim.window object" -#~ msgstr "atendis objekton vim.window" +#, c-format +msgid "failed to switch to buffer %d" +msgstr "salto al la bufro %d malsukcesis" -#~ msgid "failed to find window in the current tab page" -#~ msgstr "ne povis trovi vindozon en la nuna langeto" +#, c-format +msgid "expected vim.Window object, but got %s" +msgstr "atendis objekton vim.window, sed ricevis %s" -#~ msgid "did not switch to the specified window" -#~ msgstr "ne saltis al la specifita vindozo" +msgid "failed to find window in the current tab page" +msgstr "malsukcesis trovi vindozon en la nuna langeto" -#~ msgid "expected vim.tabpage object" -#~ msgstr "atendis objekton vim.tabpage" +msgid "did not switch to the specified window" +msgstr "ne saltis al la specifita vindozo" -#~ msgid "did not switch to the specified tab page" -#~ msgstr "ne saltis al la specifita langeto" +#, c-format +msgid "expected vim.TabPage object, but got %s" +msgstr "atendis objekton vim.TabPage, sed ricevis %s" -#~ msgid "failed to run the code" -#~ msgstr "fiaskis ruli la kodon" +msgid "did not switch to the specified tab page" +msgstr "ne saltis al la specifita langeto" -#~ msgid "E858: Eval did not return a valid python object" -#~ msgstr "E858: Eval ne revenis kun valida python-objekto" +msgid "failed to run the code" +msgstr "malsukcesis ruli la kodon" -#~ msgid "E859: Failed to convert returned python object to vim value" -#~ msgstr "E859: Konverto de revena python-objekto al vim-valoro fiaskis" +msgid "E858: Eval did not return a valid python object" +msgstr "E858: Eval ne revenis kun valida python-objekto" -#~ msgid "unable to convert to vim structure" -#~ msgstr "ne povis konverti al vim-strukturo" +msgid "E859: Failed to convert returned python object to vim value" +msgstr "E859: Konverto de revena python-objekto al vim-valoro malsukcesis" -#~ msgid "NULL reference passed" -#~ msgstr "NULL-referenco argumento" +#, c-format +msgid "unable to convert %s to vim dictionary" +msgstr "ne povis konverti %s al vim-vortaro" -#~ msgid "internal error: invalid value type" -#~ msgstr "interna eraro: nevalida tipo de valoro" +#, c-format +msgid "unable to convert %s to vim list" +msgstr "ne povis konverti %s al vim-listo" -#~ msgid "E863: return value must be an instance of str" -#~ msgstr "E863: elira valoro devas esti apero de str" +#, c-format +msgid "unable to convert %s to vim structure" +msgstr "ne povis konverti %s al vim-strukturo" -#~ msgid "E860: Eval did not return a valid python 3 object" -#~ msgstr "E860: Eval ne revenis kun valida python3-objekto" +msgid "internal error: NULL reference passed" +msgstr "interna eraro: NULL-referenco argumento" -#~ msgid "E861: Failed to convert returned python 3 object to vim value" -#~ msgstr "E861: Konverto de revena python3-objekto al vim-valoro fiaskis" +msgid "internal error: invalid value type" +msgstr "interna eraro: nevalida tipo de valoro" -#~ msgid "Only boolean objects are allowed" -#~ msgstr "Nur buleaj objektoj estas permeseblaj" +msgid "" +"Failed to set path hook: sys.path_hooks is not a list\n" +"You should now do the following:\n" +"- append vim.path_hook to sys.path_hooks\n" +"- append vim.VIM_SPECIAL_PATH to sys.path\n" +msgstr "" +"Valorizo de sys.path_hooks malsukcesis: sys.path_hooks ne estas listo\n" +"Vi nun devas fari tion:\n" +"- postaldoni vim.path_hook al sys.path_hooks\n" +"- postaldoni vim.VIM_SPECIAL_PATH al sys.path\n" -#~ msgid "no such key in dictionary" -#~ msgstr "tiu Ålosilo ne ekzistas en vortaro" +msgid "" +"Failed to set path: sys.path is not a list\n" +"You should now append vim.VIM_SPECIAL_PATH to sys.path" +msgstr "" +"Agordo de serĉvojo malsukcesis: sys.path ne estas listo\n" +"Vi nun devas aldoni vim.VIM_SPECIAL_PATH al sys.path" diff --git a/src/nvim/po/fi.po b/src/nvim/po/fi.po index d30faeb554..3551c07ff2 100644 --- a/src/nvim/po/fi.po +++ b/src/nvim/po/fi.po @@ -1,247 +1,419 @@ # Finnish translation for Vim. # Copyright (C) 2003-2006 Free Software Foundation, Inc. -# 2007-2010, Flammie Pirinen <flammie@iki.fi> +# 2007-2016, Flammie Pirinen <flammie@iki.fi> # -# Vimin käyttäjät on nörttejä. Sanasto on jargonia :-p -# -# Lähinnä latin-1:tä, sillä vim pitää portata ilmeisen obskuureille -# alustoille. Myös: pluralit puuttuu, ohjelman käyttöliittymän fontti -# tasavälinen, tila rajattu, jne. jne., luovia ratkaisuja edessä. +# Jargonia ei ole yritetty suotta kotoperäistää missä teknisempi lainasanasto +# tulee paremmin kyseeseen. # # Sanastosta: -# Fold on sellainen moderneissa ohjelmointi-IDE:issä oleva toiminto, jolla -# lohko koodia esim. funktio piilotetaan näkymästä: suom. taitos alkup. +# * Fold on sellainen moderneissa ohjelmointi-IDE:issä oleva toiminto, jolla +# lohko koodia esim. funktio piilotetaan näkymästä: suom. taitos alkup. # analogian mukaan -# source v. lataa tiedoston, kuten bash-komento source (tai .) +# * source, v. lataa tiedoston, kuten bash-komento source (tai .) +# * dictionary (dict) on vaihtelevasti sanakirja tai tietorakenne # msgid "" msgstr "" "Project-Id-Version: Vim 7\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-05-26 14:21+0200\n" -"PO-Revision-Date: 2010-08-09 02:35+0300\n" -"Last-Translator: Flammie Pirinen <flammie@iki.fi>\n" +"POT-Creation-Date: 2017-04-19 16:46+0200\n" +"PO-Revision-Date: 2016-08-29 11:27+0200\n" +"Last-Translator: Flammie A Pirinen <flammie@iki.fi>\n" "Language-Team: Finnish <laatu@lokalisointi.org>\n" "Language: fi\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../api/private/helpers.c:201 #, fuzzy -msgid "Unable to get option value" -msgstr "Roskaa argumentin perässä" +#~ msgid "Index out of bounds" +#~ msgstr "ei löytynyt " -#: ../api/private/helpers.c:204 -msgid "internal error: unknown option type" -msgstr "" +#, fuzzy +#~ msgid "Line index is too high" +#~ msgstr "ikkunan indeksi alueen ulkopuolella" + +#~ msgid "Argument \"start\" is higher than \"end\"" +#~ msgstr "" + +#~ msgid "All items in the replacement array must be strings" +#~ msgstr "" + +msgid "string cannot contain newlines" +msgstr "merkkijono ei saa sisältää rivinvaihtoja" + +#, fuzzy +#~ msgid "Failed to save undo information" +#~ msgstr "ei voitu tallentaa kumoustietoja" + +#, fuzzy +#~ msgid "Failed to delete line" +#~ msgstr "ei voitu poistaa riviä" + +#~ msgid "Index value is too high" +#~ msgstr "" + +#, fuzzy +#~ msgid "Failed to replace line" +#~ msgstr "ei voitu korvata riviä" + +#, fuzzy +#~ msgid "Failed to insert line" +#~ msgstr "ei voitu lisätä riviä" + +#, fuzzy +#~ msgid "Failed to rename buffer" +#~ msgstr "ei voity uudelleennimetä puskuria" + +#, fuzzy +#~ msgid "Mark name must be a single character" +#~ msgstr "merkin nimen pitää olla yksi merkki" + +#, fuzzy +#~ msgid "Invalid mark name" +#~ msgstr "virheellinen merkin nimi" + +#, fuzzy +#~ msgid "Line number outside range" +#~ msgstr "rivinumero arvoalueen ulkopuolella" + +#, fuzzy +#~ msgid "Column value outside range" +#~ msgstr "rivinumero arvoalueen ulkopuolella" + +#, fuzzy +#~ msgid "Keyboard interrupt" +#~ msgstr "näppäimistökeskeytys" + +#, fuzzy +#~ msgid "Key not found" +#~ msgstr "ei löytynyt " + +#, fuzzy +#~ msgid "Dictionary is locked" +#~ msgstr "dictionary on lukittu" + +#, fuzzy +#~ msgid "Empty variable names aren't allowed" +#~ msgstr "tyhjiä avaimia ei voi käyttää" + +#, fuzzy +#~ msgid "Key length is too high" +#~ msgstr "Liian pitkä polku" + +#, c-format +#~ msgid "Key is read-only: %s" +#~ msgstr "" + +#, c-format +#~ msgid "Key is fixed: %s" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "Key is locked: %s" +#~ msgstr "E741: Arvo on lukittu: %s" + +#. Doesn't exist, fail +#, fuzzy, c-format +#~ msgid "Key does not exist: %s" +#~ msgstr "Tiedostoa %s ei ole" + +#, fuzzy +#~ msgid "Empty option name" +#~ msgstr "E792: tyhjä valikkonimi" + +#, fuzzy, c-format +#~ msgid "Invalid option name \"%s\"" +#~ msgstr "E755: Virheellinen alue kohteelle %s" + +#, fuzzy, c-format +#~ msgid "Unable to get value for option \"%s\"" +#~ msgstr "ei voi tyhjentää yleistä asetusta %s" + +#, fuzzy, c-format +#~ msgid "Unknown type for option \"%s\"" +#~ msgstr "E113: Tuntematon asetus: %s" + +#, fuzzy, c-format +#~ msgid "Unable to unset option \"%s\"" +#~ msgstr "ei voi tyhjentää yleistä asetusta %s" + +#, fuzzy, c-format +#~ msgid "Cannot unset option \"%s\" because it doesn't have a global value" +#~ msgstr "ei voi tyhjentää asetusta %s jolla ei ole yleistä arvoa" + +#, c-format +#~ msgid "Option \"%s\" requires a boolean value" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "Option \"%s\" requires an integer value" +#~ msgstr "E709: [:] toimii vain listalla" + +#, c-format +#~ msgid "Value for option \"%s\" is outside range" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "Option \"%s\" requires a string value" +#~ msgstr "E709: [:] toimii vain listalla" + +#, fuzzy +#~ msgid "Invalid buffer id" +#~ msgstr "virheellinen puskurinumero" + +#, fuzzy +#~ msgid "Invalid window id" +#~ msgstr "E534: Viallinen leveä fontti" + +#, fuzzy +#~ msgid "Invalid tabpage id" +#~ msgstr "Väärä argumentti valitsimelle" + +#~ msgid "Integer value outside range" +#~ msgstr "" + +#, fuzzy +#~ msgid "Empty dictionary keys aren't allowed" +#~ msgstr "tyhjiä avaimia ei voi käyttää" + +#, fuzzy +#~ msgid "Problem while switching windows" +#~ msgstr "virhe ikkunaa vaihtaessa" + +#, fuzzy +#~ msgid "UI already attached for channel" +#~ msgstr "Vanhimmassa muutoksessa" + +#~ msgid "Expected width > 0 and height > 0" +#~ msgstr "" + +#~ msgid "UI is not attached for channel" +#~ msgstr "" + +#~ msgid "rgb must be a Boolean" +#~ msgstr "" + +#~ msgid "popupmenu_external must be a Boolean" +#~ msgstr "" + +#, fuzzy +#~ msgid "No such ui option" +#~ msgstr "E24: Lyhennettä ei ole" + +#~ msgid "Function called with too many arguments." +#~ msgstr "" + +#~ msgid "Error calling function." +#~ msgstr "" + +#, fuzzy +#~ msgid "String length is too high" +#~ msgstr "Liian pitkä polku" + +#~ msgid "Directory string is too long" +#~ msgstr "" + +#, fuzzy +#~ msgid "Failed to change directory" +#~ msgstr "hakemistoa ei voitu muuttaa" + +#, fuzzy, c-format +#~ msgid "Failed to switch to buffer %d" +#~ msgstr "ei voitu vaihtaa puskuriin %d" + +#, fuzzy, c-format +#~ msgid "Failed to switch to window %d" +#~ msgstr "ei voitu vaihtaa puskuriin %d" + +#, fuzzy, c-format +#~ msgid "Failed to switch to tabpage %d" +#~ msgstr "ei voitu vaihtaa puskuriin %d" + +#~ msgid "All items in calls array must be arrays" +#~ msgstr "" + +#~ msgid "All items in calls array must be arrays of size 2" +#~ msgstr "" + +#~ msgid "name must be String" +#~ msgstr "" + +#~ msgid "args must be Array" +#~ msgstr "" + +# datarakenteita +#, fuzzy +#~ msgid "Argument \"pos\" must be a [row, col] array" +#~ msgstr "E712: Argumentin %s pitää olla lista tai sanakirja" + +#, fuzzy +#~ msgid "Cursor position outside buffer" +#~ msgstr "kursorin sijainti puskurin ulkopuolella" + +#~ msgid "Height value outside range" +#~ msgstr "" + +#~ msgid "Width value outside range" +#~ msgstr "" -#: ../buffer.c:92 msgid "[Location List]" msgstr "[Sijaintiluettelo]" -#: ../buffer.c:93 msgid "[Quickfix List]" msgstr "[Pikakorjausluettelo]" -#: ../buffer.c:94 -#, fuzzy msgid "E855: Autocommands caused command to abort" -msgstr "E812: Autocommands muutti puskurin tai sen nimen" +msgstr "E855: Autocommands lopetti komennon" -#: ../buffer.c:135 msgid "E82: Cannot allocate any buffer, exiting..." -msgstr "E82: Mitään puskuria ei voitu varata, lopetetaan..." +msgstr "E82: Mitään puskuria ei voitu varata, lopetetaan..." -#: ../buffer.c:138 msgid "E83: Cannot allocate buffer, using other one..." -msgstr "E83: Puskuria ei voitu varata, käytetään toista..." +msgstr "E83: Puskuria ei voitu varata, käytetään toista..." + +#, fuzzy +#~ msgid "E937: Attempt to delete a buffer that is in use" +#~ msgstr "E934: Ei voida hypätä puskuriin jolla ei ole nimeä" -#: ../buffer.c:763 msgid "E515: No buffers were unloaded" msgstr "E515: Puskureita ei vapautettu" -#: ../buffer.c:765 msgid "E516: No buffers were deleted" msgstr "E516: Puskureita ei poistettu" -#: ../buffer.c:767 msgid "E517: No buffers were wiped out" msgstr "E517: Puskureita ei pyyhitty" -#: ../buffer.c:772 msgid "1 buffer unloaded" msgstr "1 puskuri vapautettiin" -#: ../buffer.c:774 #, c-format msgid "%d buffers unloaded" msgstr "%d puskuria vapautettiin" -#: ../buffer.c:777 msgid "1 buffer deleted" msgstr "1 puskuri poistettu" -#: ../buffer.c:779 #, c-format msgid "%d buffers deleted" msgstr "%d puskuria poistettu" -#: ../buffer.c:782 msgid "1 buffer wiped out" msgstr "1 puskuri pyyhitty" -#: ../buffer.c:784 #, c-format msgid "%d buffers wiped out" msgstr "%d puskuria pyyhitty" -#: ../buffer.c:806 msgid "E90: Cannot unload last buffer" -msgstr "E90: Ei voi vapauttaa viimeistä puskuria" +msgstr "E90: Ei voi vapauttaa viimeistä puskuria" -#: ../buffer.c:874 msgid "E84: No modified buffer found" msgstr "E84: Ei muokattuja puskureita" #. back where we started, didn't find anything. -#: ../buffer.c:903 msgid "E85: There is no listed buffer" msgstr "E85: Luetteloitua puskuria ei ole" -#: ../buffer.c:913 -#, c-format -msgid "E86: Buffer %<PRId64> does not exist" -msgstr "E86: Puskuria %<PRId64> ei ole" - -#: ../buffer.c:915 msgid "E87: Cannot go beyond last buffer" -msgstr "E87: Viimeisen puskurin ohi ei voi edetä" +msgstr "E87: Viimeisen puskurin ohi ei voi edetä" -#: ../buffer.c:917 msgid "E88: Cannot go before first buffer" -msgstr "E88: Ensimmäisen puskurin ohi ei voi edetä" +msgstr "E88: Ensimmäisen puskurin ohi ei voi edetä" -#: ../buffer.c:945 -#, c-format +#, fuzzy, c-format +#~ msgid "E89: %s will be killed(add ! to override)" +#~ msgstr "E189: %s on jo olemassa (lisää komentoon ! ohittaaksesi)" + +#, fuzzy, c-format msgid "" "E89: No write since last change for buffer %<PRId64> (add ! to override)" msgstr "" -"E89: Puskurin %<PRId64> muutoksia ei ole tallennettu (lisää komentoon ! " +"E89: Puskurin %ld muutoksia ei ole tallennettu (lisää komentoon ! " "ohittaaksesi)" #. wrap around (may cause duplicates) -#: ../buffer.c:1423 msgid "W14: Warning: List of file names overflow" msgstr "W14: Varoitus: Tiedostonimiluettelon ylivuoto" -#: ../buffer.c:1555 ../quickfix.c:3361 -#, c-format -msgid "E92: Buffer %<PRId64> not found" -msgstr "E92: Puskuria %<PRId64> ei löydy" +#, fuzzy, c-format +#~ msgid "E92: Buffer %<PRId64> not found" +#~ msgstr "E92: Puskuria %ld ei löydy" -#: ../buffer.c:1798 #, c-format msgid "E93: More than one match for %s" -msgstr "E93: %s täsmää useampaan kuin yhteen puskuriin" +msgstr "E93: %s täsmää useampaan kuin yhteen puskuriin" -#: ../buffer.c:1800 #, c-format msgid "E94: No matching buffer for %s" -msgstr "E94: %s ei täsmää yhteenkään puskuriin" +msgstr "E94: %s ei täsmää yhteenkään puskuriin" -#: ../buffer.c:2161 -#, c-format -msgid "line %<PRId64>" -msgstr "rivi %<PRId64>" +#, fuzzy, c-format +#~ msgid "line %<PRId64>" +#~ msgstr "rivi %ld" -#: ../buffer.c:2233 msgid "E95: Buffer with this name already exists" msgstr "E95: Samanniminen puskuri on jo olemassa" -#: ../buffer.c:2498 msgid " [Modified]" msgstr " [Muokattu]" -#: ../buffer.c:2501 msgid "[Not edited]" msgstr "[Muokkaamaton]" -#: ../buffer.c:2504 msgid "[New file]" msgstr "[Uusi tiedosto]" -#: ../buffer.c:2505 msgid "[Read errors]" -msgstr "[Lukuvirheitä]" +msgstr "[Lukuvirheitä]" -#: ../buffer.c:2506 ../buffer.c:3217 ../fileio.c:1807 ../screen.c:4895 msgid "[RO]" msgstr "[Luku]" -#: ../buffer.c:2507 ../fileio.c:1807 msgid "[readonly]" msgstr "[kirjoitussuojattu]" -#: ../buffer.c:2524 #, c-format msgid "1 line --%d%%--" msgstr "1 rivi --%d %%--" -#: ../buffer.c:2526 -#, c-format -msgid "%<PRId64> lines --%d%%--" -msgstr "%<PRId64> riviä --%d %%--" +#, fuzzy, c-format +#~ msgid "%<PRId64> lines --%d%%--" +#~ msgstr "%ld riviä --%d %%--" -#: ../buffer.c:2530 -#, c-format -msgid "line %<PRId64> of %<PRId64> --%d%%-- col " -msgstr "rivi %<PRId64>/%<PRId64> --%d %%-- sarake " +#, fuzzy, c-format +#~ msgid "line %<PRId64> of %<PRId64> --%d%%-- col " +#~ msgstr "rivi %ld/%ld --%d %%-- sarake " -#: ../buffer.c:2632 ../buffer.c:4292 ../memline.c:1554 msgid "[No Name]" -msgstr "[Nimetön]" +msgstr "[Nimetön]" #. must be a help buffer -#: ../buffer.c:2667 msgid "help" msgstr "ohje" -#: ../buffer.c:3225 ../screen.c:4883 msgid "[Help]" msgstr "[Ohje]" -#: ../buffer.c:3254 ../screen.c:4887 msgid "[Preview]" msgstr "[Esikatselu]" # sijainti tiedostossa -indikaattoreja: -# 4 merkkiä sais riittää -#: ../buffer.c:3528 +# 4 merkkiä sais riittää msgid "All" msgstr "Kaik" -#: ../buffer.c:3528 msgid "Bot" msgstr "Loppu" -#: ../buffer.c:3531 msgid "Top" msgstr "Alku" -#: ../buffer.c:4244 -msgid "" -"\n" -"# Buffer list:\n" -msgstr "" -"\n" -"# Puskuriluettelo:\n" - -#: ../buffer.c:4289 msgid "[Scratch]" msgstr "[Raapust]" -#: ../buffer.c:4529 msgid "" "\n" "--- Signs ---" @@ -249,795 +421,669 @@ msgstr "" "\n" "--- Merkit ---" -#: ../buffer.c:4538 #, c-format msgid "Signs for %s:" msgstr "Merkit kohteelle %s:" -#: ../buffer.c:4543 -#, c-format -msgid " line=%<PRId64> id=%d name=%s" -msgstr " rivi=%<PRId64> id=%d nimi=%s" +#, fuzzy, c-format +#~ msgid " line=%<PRId64> id=%d name=%s" +#~ msgstr " rivi=%ld id=%d nimi=%s" -#: ../cursor_shape.c:68 msgid "E545: Missing colon" msgstr "E545: Kaksoispiste puuttuu" -#: ../cursor_shape.c:70 ../cursor_shape.c:94 msgid "E546: Illegal mode" msgstr "E546: Virheellinen tila" -#: ../cursor_shape.c:134 msgid "E548: digit expected" -msgstr "E548: pitää olla numero" +msgstr "E548: pitää olla numero" -#: ../cursor_shape.c:138 msgid "E549: Illegal percentage" msgstr "E549: Virheellinen prosenttiluku" -#: ../diff.c:146 -#, c-format -msgid "E96: Can not diff more than %<PRId64> buffers" -msgstr "E96: Ei voi diffata enempää kuin %<PRId64> puskuria" +#, fuzzy, c-format +#~ msgid "E96: Cannot diff more than %<PRId64> buffers" +#~ msgstr "E96: Ei voi diffata enempää kuin %ld puskuria" -#: ../diff.c:753 msgid "E810: Cannot read or write temp files" -msgstr "E810: Ei voi lukea tai kirjoittaa väliaikaistiedostoja" +msgstr "E810: Ei voi lukea tai kirjoittaa väliaikaistiedostoja" -#: ../diff.c:755 msgid "E97: Cannot create diffs" -msgstr "E97: Ei voi luoda diffejä" +msgstr "E97: Ei voi luoda diffejä" -#: ../diff.c:966 msgid "E816: Cannot read patch output" msgstr "E816: Ei voi lukea patchin tulostetta" -#: ../diff.c:1220 msgid "E98: Cannot read diff output" msgstr "E98: Ei voi lukea diffin tulostetta" -#: ../diff.c:2081 msgid "E99: Current buffer is not in diff mode" -msgstr "E99: Tämä puskuri ei ole diff-tilassa" +msgstr "E99: Tämä puskuri ei ole diff-tilassa" -#: ../diff.c:2100 msgid "E793: No other buffer in diff mode is modifiable" -msgstr "E793: Yksikään muu diff-tilan puskurit ei ole muokattavissa" +msgstr "E793: Yksikään muu diff-tilan puskurit ei ole muokattavissa" -#: ../diff.c:2102 msgid "E100: No other buffer in diff mode" -msgstr "E100: Yksikään muu puskuri ei ole diff-tilassa" +msgstr "E100: Yksikään muu puskuri ei ole diff-tilassa" -#: ../diff.c:2112 msgid "E101: More than two buffers in diff mode, don't know which one to use" -msgstr "E101: Monta puskuria on diff-tilassa, käytettävän valinta ei onnistu" +msgstr "E101: Monta puskuria on diff-tilassa, käytettävän valinta ei onnistu" -#: ../diff.c:2141 #, c-format msgid "E102: Can't find buffer \"%s\"" -msgstr "E102: Puskuria %s ei löydy" +msgstr "E102: Puskuria %s ei löydy" -#: ../diff.c:2152 #, c-format msgid "E103: Buffer \"%s\" is not in diff mode" msgstr "E103: Puskuri %s ei ole diff-tilassa" -#: ../diff.c:2193 msgid "E787: Buffer changed unexpectedly" msgstr "E787: Puskuri vaihtui odottamatta" -#: ../digraph.c:1598 msgid "E104: Escape not allowed in digraph" -msgstr "E104: Escapea ei voi käyttää digraafissa" +msgstr "E104: Escapea ei voi käyttää digraafissa" -#: ../digraph.c:1760 msgid "E544: Keymap file not found" -msgstr "E544: Näppäinkarttaa ei löydy" +msgstr "E544: Näppäinkarttaa ei löydy" -#: ../digraph.c:1785 msgid "E105: Using :loadkeymap not in a sourced file" -msgstr "E105: Käytetään :loadkeymapia ladatun tiedoston ulkopuolella" +msgstr "E105: Käytetään :loadkeymapia ladatun tiedoston ulkopuolella" -#: ../digraph.c:1821 msgid "E791: Empty keymap entry" -msgstr "E791: Tyhjä keymap-kenttä" +msgstr "E791: Tyhjä keymap-kenttä" -#: ../edit.c:82 msgid " Keyword completion (^N^P)" -msgstr " Avainsanatäydennys (^N^P)" +msgstr " Avainsanatäydennys (^N^P)" #. ctrl_x_mode == 0, ^P/^N compl. -#: ../edit.c:83 msgid " ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" msgstr " ^X-tila (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" -#: ../edit.c:85 msgid " Whole line completion (^L^N^P)" -msgstr " Täysrivitäydennys (^L^N^P)" +msgstr " Täysrivitäydennys (^L^N^P)" -#: ../edit.c:86 msgid " File name completion (^F^N^P)" -msgstr " Tiedostonimitäydennys (^F^N^P)" +msgstr " Tiedostonimitäydennys (^F^N^P)" -#: ../edit.c:87 msgid " Tag completion (^]^N^P)" -msgstr " Tägitäydennys (^]^N^P)" +msgstr " Tägitäydennys (^]^N^P)" -#: ../edit.c:88 msgid " Path pattern completion (^N^P)" -msgstr " Polkukuviotäydennys (^N^P)" +msgstr " Polkukuviotäydennys (^N^P)" -#: ../edit.c:89 msgid " Definition completion (^D^N^P)" -msgstr " Määritelmätäydennys (^D^N^P)" +msgstr " Määritelmätäydennys (^D^N^P)" -#: ../edit.c:91 msgid " Dictionary completion (^K^N^P)" -msgstr " Sanakirjatäydennys (^K^N^P)" +msgstr " Sanakirjatäydennys (^K^N^P)" -#: ../edit.c:92 msgid " Thesaurus completion (^T^N^P)" -msgstr " Thesaurus-täydennys (^T^N^P)" +msgstr " Thesaurus-täydennys (^T^N^P)" -#: ../edit.c:93 msgid " Command-line completion (^V^N^P)" -msgstr " Komentorivitäydennys (^V^N^P)" +msgstr " Komentorivitäydennys (^V^N^P)" -#: ../edit.c:94 msgid " User defined completion (^U^N^P)" -msgstr " Käyttäjän määrittelemä täydennys (^U^N^P)" +msgstr " Käyttäjän määrittelemä täydennys (^U^N^P)" -#: ../edit.c:95 msgid " Omni completion (^O^N^P)" -msgstr " Omnitäydennys (^O^N^P)" +msgstr " Omnitäydennys (^O^N^P)" -#: ../edit.c:96 msgid " Spelling suggestion (s^N^P)" msgstr " Oikaisulukuehdotus (s^N^P)" -#: ../edit.c:97 msgid " Keyword Local completion (^N^P)" -msgstr " Avainsanan paikallinen täydennys (^N^P)" +msgstr " Avainsanan paikallinen täydennys (^N^P)" -#: ../edit.c:100 msgid "Hit end of paragraph" msgstr "Kappaleen loppu tuli vastaan" -#: ../edit.c:101 -#, fuzzy msgid "E839: Completion function changed window" -msgstr "E813: Ei voi sulkea autocmd-ikkunaa" +msgstr "E839: Täydennys vaihtoi ikkunaa" -#: ../edit.c:102 msgid "E840: Completion function deleted text" -msgstr "" +msgstr "E840: Täydennys poisti tekstiä" -#: ../edit.c:1847 msgid "'dictionary' option is empty" -msgstr "dictionary-asetus on tyhjä" +msgstr "dictionary-asetus on tyhjä" -#: ../edit.c:1848 msgid "'thesaurus' option is empty" -msgstr "thesaurus-asetus on tyhjä" +msgstr "thesaurus-asetus on tyhjä" -#: ../edit.c:2655 #, c-format msgid "Scanning dictionary: %s" msgstr "Luetaan sanakirjaa: %s" -#: ../edit.c:3079 msgid " (insert) Scroll (^E/^Y)" -msgstr " (syöttö) Vieritys (^E/^Y)" +msgstr " (syöttö) Vieritys (^E/^Y)" -#: ../edit.c:3081 msgid " (replace) Scroll (^E/^Y)" msgstr " (korvaus) Vieritys (^E/^Y)" -#: ../edit.c:3587 #, c-format msgid "Scanning: %s" msgstr "Luetaan: %s" -#: ../edit.c:3614 msgid "Scanning tags." -msgstr "Luetaan tägejä." +msgstr "Luetaan tägejä." -#: ../edit.c:4519 msgid " Adding" -msgstr " Lisätään" +msgstr " Lisätään" #. showmode might reset the internal line pointers, so it must #. * be called before line = ml_get(), or when this address is no #. * longer needed. -- Acevedo. #. -#: ../edit.c:4562 msgid "-- Searching..." msgstr "-- Haetaan..." -#: ../edit.c:4618 msgid "Back at original" -msgstr "Takaisin lähtöpisteessä" +msgstr "Takaisin lähtöpisteessä" -#: ../edit.c:4621 msgid "Word from other line" -msgstr "Sana toisella rivillä" +msgstr "Sana toisella rivillä" -#: ../edit.c:4624 msgid "The only match" -msgstr "Ainoa täsmäys" +msgstr "Ainoa täsmäys" -#: ../edit.c:4680 #, c-format msgid "match %d of %d" -msgstr "täsmäys %d/%d" +msgstr "täsmäys %d/%d" -#: ../edit.c:4684 #, c-format msgid "match %d" -msgstr "täsmäys %d" +msgstr "täsmäys %d" -#: ../eval.c:137 msgid "E18: Unexpected characters in :let" -msgstr "E18: Odottamattomia merkkejä komennossa :let" - -#: ../eval.c:138 -#, c-format -msgid "E684: list index out of range: %<PRId64>" -msgstr "E684: Indeksi %<PRId64> luettelon rajojen ulkopuolella" +msgstr "E18: Odottamattomia merkkejä komennossa :let" -#: ../eval.c:139 -#, c-format -msgid "E121: Undefined variable: %s" -msgstr "E121: Määrittelemätön muuttuja: %s" - -#: ../eval.c:140 msgid "E111: Missing ']'" msgstr "E111: ] puuttuu" -#: ../eval.c:141 #, c-format msgid "E686: Argument of %s must be a List" -msgstr "E686: Argumentin %s pitää olla lista" +msgstr "E686: Argumentin %s pitää olla lista" # datarakenteita -#: ../eval.c:143 #, c-format msgid "E712: Argument of %s must be a List or Dictionary" -msgstr "E712: Argumentin %s pitää olla lista tai sanakirja" - -#: ../eval.c:144 -msgid "E713: Cannot use empty key for Dictionary" -msgstr "E713: Sanakirjassa ei voi olla tyhjiä avaimia" +msgstr "E712: Argumentin %s pitää olla lista tai sanakirja" -#: ../eval.c:145 msgid "E714: List required" msgstr "E714: Lista tarvitaan" -#: ../eval.c:146 msgid "E715: Dictionary required" msgstr "E715: Sanakirja tarvitaan" -#: ../eval.c:147 +msgid "E928: String required" +msgstr "E928: Merkkijono puuttuu" + #, c-format msgid "E118: Too many arguments for function: %s" msgstr "E118: Liikaa argumentteja funktiolle: %s" -#: ../eval.c:148 #, c-format msgid "E716: Key not present in Dictionary: %s" msgstr "E716: Avainta %s ei ole sanakirjassa" -#: ../eval.c:150 #, c-format msgid "E122: Function %s already exists, add ! to replace it" -msgstr "E122: Funktio %s on jo olemassa, lisää ! korvataksesi" +msgstr "E122: Funktio %s on jo olemassa, lisää ! korvataksesi" -#: ../eval.c:151 msgid "E717: Dictionary entry already exists" msgstr "E717: Sanakirja-alkio on jo olemassa" -#: ../eval.c:152 msgid "E718: Funcref required" msgstr "E718: Funcref tarvitaan" -#: ../eval.c:153 msgid "E719: Cannot use [:] with a Dictionary" -msgstr "E719: Sanakirjassa ei voi käyttää merkintää [:]" +msgstr "E719: Sanakirjassa ei voi käyttää merkintää [:]" -#: ../eval.c:154 -#, c-format -msgid "E734: Wrong variable type for %s=" -msgstr "E734: Väärä muuttujatyyppi muuttujalle %s=" - -#: ../eval.c:155 #, c-format msgid "E130: Unknown function: %s" msgstr "E130: Tuntematon funktio: %s" -#: ../eval.c:156 #, c-format msgid "E461: Illegal variable name: %s" msgstr "E461: Virheellinen muuttujanimi: %s" -#: ../eval.c:157 -msgid "E806: using Float as a String" -msgstr "E806: Float ei käy merkkijonosta" +#, fuzzy, c-format +#~ msgid "E46: Cannot change read-only variable \"%.*s\"" +#~ msgstr "E46: Kirjoitussuojattua muuttujaa %s ei voi muuttaa" + +#. TODO(ZyX-I): move to eval/executor +#, c-format +msgid "E734: Wrong variable type for %s=" +msgstr "E734: Väärä muuttujatyyppi muuttujalle %s=" -#: ../eval.c:1830 msgid "E687: Less targets than List items" -msgstr "E687: Kohteita on vähemmän kuin listan alkioita" +msgstr "E687: Kohteita on vähemmän kuin listan alkioita" -#: ../eval.c:1834 msgid "E688: More targets than List items" -msgstr "E688: Kohteita on enemmän kuin listan alkioita" +msgstr "E688: Kohteita on enemmän kuin listan alkioita" -#: ../eval.c:1906 msgid "Double ; in list of variables" -msgstr "Kaksi ;:ttä listan muuttujissa" +msgstr "Kaksi ;:ttä listan muuttujissa" -#: ../eval.c:2078 #, c-format msgid "E738: Can't list variables for %s" msgstr "E738: Kohteen %s muuttujia ei voi listata" -#: ../eval.c:2391 +#, fuzzy, c-format +#~ msgid "E121: Undefined variable: %.*s" +#~ msgstr "E121: Määrittelemätön muuttuja: %s" + msgid "E689: Can only index a List or Dictionary" -msgstr "E689: Vain listalla ja sanakirjalla voi olla indeksejä" +msgstr "E689: Vain listalla ja sanakirjalla voi olla indeksejä" -#: ../eval.c:2396 msgid "E708: [:] must come last" -msgstr "E708: [:]:n pitää olla viimeisenä" +msgstr "E708: [:]:n pitää olla viimeisenä" + +#, fuzzy +#~ msgid "E713: Cannot use empty key after ." +#~ msgstr "E713: Sanakirjassa ei voi olla tyhjiä avaimia" -#: ../eval.c:2439 msgid "E709: [:] requires a List value" msgstr "E709: [:] toimii vain listalla" -#: ../eval.c:2674 msgid "E710: List value has more items than target" -msgstr "E710: Listalla on enemmän alkioita kuin kohteella" +msgstr "E710: Listalla on enemmän alkioita kuin kohteella" -#: ../eval.c:2678 msgid "E711: List value has not enough items" msgstr "E711: Listalla ei ole tarpeeksi alkioita" -#: ../eval.c:2867 msgid "E690: Missing \"in\" after :for" msgstr "E690: :for-kommenolta puuttuu in" -#: ../eval.c:3063 #, c-format msgid "E107: Missing parentheses: %s" msgstr "E107: Sulkeita puuttuu: %s" -#: ../eval.c:3263 #, c-format msgid "E108: No such variable: \"%s\"" msgstr "E108: Muuttujaa %s ei ole" -#: ../eval.c:3333 -msgid "E743: variable nested too deep for (un)lock" -msgstr "E743: muuttujassa liian monta tasoa lukituksen käsittelyyn" +#. For historical reasons this error is not given for Lists and +#. Dictionaries. E.g. b: dictionary may be locked/unlocked. +#, fuzzy, c-format +#~ msgid "E940: Cannot lock or unlock variable %s" +#~ msgstr "E46: Kirjoitussuojattua muuttujaa %s ei voi muuttaa" -#: ../eval.c:3630 msgid "E109: Missing ':' after '?'" -msgstr "E109: ?:n jälkeen puuttuu :" +msgstr "E109: ?:n jälkeen puuttuu :" -#: ../eval.c:3893 msgid "E691: Can only compare List with List" msgstr "E691: Listaa voi verrata vain listaan" -#: ../eval.c:3895 -msgid "E692: Invalid operation for Lists" +msgid "E692: Invalid operation for List" msgstr "E692: Virheellinen toiminto listalle" -#: ../eval.c:3915 msgid "E735: Can only compare Dictionary with Dictionary" msgstr "E735: Sanakirjaa voi verrata vain sanakirjaan" -#: ../eval.c:3917 msgid "E736: Invalid operation for Dictionary" msgstr "E736: Virheellinen toiminto sanakirjalle" -#: ../eval.c:3932 -msgid "E693: Can only compare Funcref with Funcref" -msgstr "E693: Funcrefiä voi verrata vain funcrefiin" - -#: ../eval.c:3934 msgid "E694: Invalid operation for Funcrefs" msgstr "E694: Virheellinen toiminto funcrefille" -#: ../eval.c:4277 msgid "E804: Cannot use '%' with Float" -msgstr "E804: Ei voi käyttää '%':a Floatin kanssa" +msgstr "E804: Ei voi käyttää '%':a Floatin kanssa" -#: ../eval.c:4478 msgid "E110: Missing ')'" msgstr "E110: ) puuttuu" -#: ../eval.c:4609 msgid "E695: Cannot index a Funcref" -msgstr "E695: Funcrefiä ei voi indeksoida" +msgstr "E695: Funcrefiä ei voi indeksoida" + +msgid "E909: Cannot index a special variable" +msgstr "E909: erikoismuuttujaa ei voi indeksoida" -#: ../eval.c:4839 #, c-format msgid "E112: Option name missing: %s" msgstr "E112: Asetuksen nimi puuttuu: %s" -#: ../eval.c:4855 #, c-format msgid "E113: Unknown option: %s" msgstr "E113: Tuntematon asetus: %s" -#: ../eval.c:4904 #, c-format msgid "E114: Missing quote: %s" msgstr "E114: Puuttuva lainausmerkki: %s" -#: ../eval.c:5020 #, c-format msgid "E115: Missing quote: %s" msgstr "E115: Puuttuva lainausmerkki: %s" -#: ../eval.c:5084 #, c-format msgid "E696: Missing comma in List: %s" msgstr "E696: Listasta puuttuu pilkku: %s" -#: ../eval.c:5091 #, c-format msgid "E697: Missing end of List ']': %s" msgstr "E697: Listan lopusta puuttuu ]: %s" -#: ../eval.c:6475 +msgid "Not enough memory to set references, garbage collection aborted!" +msgstr "" +"Ei tarpeeksi muistia viitteiden asettamista varten, roskiekeruu peruttiin." + #, c-format msgid "E720: Missing colon in Dictionary: %s" msgstr "E720: Sanakirjasta puuttuu kaksoispiste: %s" -#: ../eval.c:6499 #, c-format msgid "E721: Duplicate key in Dictionary: \"%s\"" msgstr "E721: Kaksi samaa avainta sanakirjassa: %s" -#: ../eval.c:6517 #, c-format msgid "E722: Missing comma in Dictionary: %s" msgstr "E722: Sanakirjasta puuttuu pilkku: %s" -#: ../eval.c:6524 #, c-format msgid "E723: Missing end of Dictionary '}': %s" msgstr "E723: Sanakirjan lopusta puuttuu }: %s" -#: ../eval.c:6555 -msgid "E724: variable nested too deep for displaying" -msgstr "E724: muuttuja on upotettu liian syvälle näytettäväksi" +#, c-format +msgid "E125: Illegal argument: %s" +msgstr "E125: Virheellinen argumentti: %s" + +#, c-format +msgid "E853: Duplicate argument name: %s" +msgstr "E853: Kaksoiskappale argumentin nimestä: %s" -#: ../eval.c:7188 #, c-format msgid "E740: Too many arguments for function %s" msgstr "E740: Liikaa argumentteja funktiolle %s" -#: ../eval.c:7190 #, c-format msgid "E116: Invalid arguments for function %s" -msgstr "E116: Vääriä argumentteja funktiolle %s" +msgstr "E116: Vääriä argumentteja funktiolle %s" -#: ../eval.c:7377 #, c-format msgid "E117: Unknown function: %s" msgstr "E117: Tuntematon funktio: %s" -#: ../eval.c:7383 +#, c-format +msgid "E933: Function was deleted: %s" +msgstr "E933: Funktion nimi poistettu: %s" + #, c-format msgid "E119: Not enough arguments for function: %s" msgstr "E119: Liikaa argumentteja funktiolle %s" -#: ../eval.c:7387 #, c-format msgid "E120: Using <SID> not in a script context: %s" msgstr "E120: <SID> skriptin ulkopuolella: %s" -#: ../eval.c:7391 #, c-format msgid "E725: Calling dict function without Dictionary: %s" msgstr "E725: dict-funktio ilman sanakirjaa: %s" -#: ../eval.c:7453 -msgid "E808: Number or Float required" -msgstr "E808: Number tai Float vaaditaan" +#, fuzzy, c-format +#~ msgid "Error converting the call result: %s" +#~ msgstr "virhe Schemestä Vimiin konversiossa" -#: ../eval.c:7503 -#, fuzzy msgid "add() argument" -msgstr "-c-argumentti" +msgstr "add()-argumentti" -#: ../eval.c:7907 msgid "E699: Too many arguments" msgstr "E699: Liikaa argumentteja" -#: ../eval.c:8073 msgid "E785: complete() can only be used in Insert mode" -msgstr "E785: complete() toimii vain syöttötilassa" +msgstr "E785: complete() toimii vain syöttötilassa" -#: ../eval.c:8156 msgid "&Ok" msgstr "&Ok" -#: ../eval.c:8676 -#, c-format -msgid "E737: Key already exists: %s" -msgstr "E737: Avain on jo olemassa: %s" - -#: ../eval.c:8692 #, fuzzy +#~ msgid "dictwatcheradd() argument" +#~ msgstr "add()-argumentti" + msgid "extend() argument" -msgstr "--cmd-argumentti" +msgstr "extend()-argumentti" -#: ../eval.c:8915 -#, fuzzy msgid "map() argument" -msgstr "-c-argumentti" +msgstr "map()-argumentti" -#: ../eval.c:8916 -#, fuzzy msgid "filter() argument" -msgstr "-c-argumentti" +msgstr "filter()-argumentti" -#: ../eval.c:9229 -#, c-format -msgid "+-%s%3ld lines: " -msgstr "+-%s%3ld riviä: " +#, fuzzy, c-format +#~ msgid "+-%s%3ld lines: " +#~ msgstr "+-%s%3ld rivi: " -#: ../eval.c:9291 #, c-format msgid "E700: Unknown function: %s" msgstr "E700: Tuntematon funktio: %s" -#: ../eval.c:10729 +msgid "E922: expected a dict" +msgstr "E922: odotettiin dictiä" + +# datarakenteita +msgid "E923: Second argument of function() must be a list or a dict" +msgstr "E923: toisen function()-argumentin pitää olla lista tai sanakirja" + +#, fuzzy +#~ msgid "E5000: Cannot find tab number." +#~ msgstr "E695: Funcrefiä ei voi indeksoida" + +#~ msgid "E5001: Higher scope cannot be -1 if lower scope is >= 0." +#~ msgstr "" + +#, fuzzy +#~ msgid "E5002: Cannot find window number." +#~ msgstr "E671: Ikkunan otsikkoa ei löydy %s" + msgid "called inputrestore() more often than inputsave()" msgstr "inputrestore() suoritettu useammin kuin inputsave()" -#: ../eval.c:10771 -#, fuzzy msgid "insert() argument" -msgstr "-c-argumentti" +msgstr "insert()-argumentti" -#: ../eval.c:10841 msgid "E786: Range not allowed" -msgstr "E786: Aluetta ei voi käyttää" +msgstr "E786: Aluetta ei voi käyttää" + +#~ msgid "Invalid stream on rpc job, use jobclose(id, 'rpc')" +#~ msgstr "" + +#~ msgid "Invalid job stream: Not an rpc job" +#~ msgstr "" + +#, c-format +#~ msgid "Invalid job stream \"%s\"" +#~ msgstr "" + +#~ msgid "Can't send data to the job: stdin is closed" +#~ msgstr "" + +#~ msgid "Can't send raw data to rpc channel" +#~ msgstr "" + +#, fuzzy +#~ msgid "E474: Failed to convert list to string" +#~ msgstr "ei voitu konvertoida tyypistä %s vim-listaksi" + +#, fuzzy, c-format +#~ msgid "E474: Failed to parse %.*s" +#~ msgstr "E241: Kohteeseen %s lähettäminen ei onnistunut" -#: ../eval.c:11140 msgid "E701: Invalid type for len()" msgstr "E701: Virheellinen tyyppi funktiolle len()" -#: ../eval.c:11980 +#, fuzzy, c-format +#~ msgid "msgpackdump() argument, index %i" +#~ msgstr "map()-argumentti" + +#, fuzzy +#~ msgid "E5070: Character number must not be less than zero" +#~ msgstr "luvun on oltava nollaa suurempi" + +#, fuzzy, c-format +#~ msgid "E5071: Character number must not be greater than INT_MAX (%i)" +#~ msgstr "luvun on oltava nollaa suurempi" + msgid "E726: Stride is zero" msgstr "E726: Stride on nolla" -#: ../eval.c:11982 msgid "E727: Start past end" -msgstr "E727: Alku on lopun jälkeen" +msgstr "E727: Alku on lopun jälkeen" -#: ../eval.c:12024 ../eval.c:15297 msgid "<empty>" -msgstr "<tyhjä>" +msgstr "<tyhjä>" -#: ../eval.c:12282 -#, fuzzy msgid "remove() argument" -msgstr "--cmd-argumentti" +msgstr "remove()-argumentti" -#: ../eval.c:12466 msgid "E655: Too many symbolic links (cycle?)" -msgstr "E655: Liikaa symbolisia linkkejä (mahdollinen sykli)" +msgstr "E655: Liikaa symbolisia linkkejä (mahdollinen sykli)" -#: ../eval.c:12593 -#, fuzzy msgid "reverse() argument" -msgstr "-c-argumentti" +msgstr "reverse()-argumentti" + +#, c-format +msgid "E927: Invalid action: '%s'" +msgstr "E927: Viallinen toiminto: %s" -#: ../eval.c:13721 -#, fuzzy msgid "sort() argument" -msgstr "-c-argumentti" +msgstr "sort()-argumentti" -#: ../eval.c:13721 -#, fuzzy msgid "uniq() argument" -msgstr "-c-argumentti" +msgstr "uniq()-argumentti" -#: ../eval.c:13776 msgid "E702: Sort compare function failed" msgstr "E702: Lajittelun vertausfunktio ei onnistunut" -#: ../eval.c:13806 -#, fuzzy msgid "E882: Uniq compare function failed" -msgstr "E702: Lajittelun vertausfunktio ei onnistunut" +msgstr "E882: Uniqin vertausfunktio ei onnistunut" -#: ../eval.c:14085 msgid "(Invalid)" msgstr "(Virheellinen)" -#: ../eval.c:14590 -msgid "E677: Error writing temp file" -msgstr "E677: Väliaikaistiedostoon kirjoittaminen ei onnistunut" +#, c-format +msgid "E935: invalid submatch number: %d" +msgstr "E935: Virheellinen alitäsmäyksen numero: %d" -#: ../eval.c:16159 -msgid "E805: Using a Float as a Number" -msgstr "E805: Float ei käy Numberista" +#~ msgid "Can only call this function in an unmodified buffer" +#~ msgstr "" -#: ../eval.c:16162 -msgid "E703: Using a Funcref as a Number" -msgstr "E703: Funcref ei käy Numberista" +msgid "E921: Invalid callback argument" +msgstr "E921: Virheellinen callback-argumentti" -#: ../eval.c:16170 -msgid "E745: Using a List as a Number" -msgstr "E745: Lista ei käy Numberista" +#, fuzzy, c-format +#~ msgid "E80: Error while writing: %s" +#~ msgstr "E80: Kirjoitusvirhe" -#: ../eval.c:16173 -msgid "E728: Using a Dictionary as a Number" -msgstr "E728: Sanakirja ei käy Numberista" +#. Using %s, p and not %c, *p to preserve multibyte characters +#, fuzzy, c-format +#~ msgid "E5060: Unknown flag: %s" +#~ msgstr "E235: Tuntematon fontti: %s" -#: ../eval.c:16259 -msgid "E729: using Funcref as a String" -msgstr "E729: Funcref ei käy merkkijonosta" +#, fuzzy +#~ msgid "E482: Can't open file with an empty name" +#~ msgstr "E212: Tiedoston avaus kirjoittamista varten ei onnistu" -#: ../eval.c:16262 -msgid "E730: using List as a String" -msgstr "E730: Lista ei käy merkkijonosta" +#, fuzzy, c-format +#~ msgid "E482: Can't open file %s for writing: %s" +#~ msgstr "E212: Tiedoston avaus kirjoittamista varten ei onnistu" -#: ../eval.c:16265 -msgid "E731: using Dictionary as a String" -msgstr "E731: Sanakirja ei käy merkkijonosta" +#, fuzzy, c-format +#~ msgid "E80: Error when closing file %s: %s" +#~ msgstr "E209: Virhe suljettaessa tiedostoa %s" -#: ../eval.c:16619 -#, c-format -msgid "E706: Variable type mismatch for: %s" -msgstr "E706: Muuttujatyyppi ei täsmää: %s" +#, fuzzy, c-format +#~ msgid "E794: Cannot set variable in the sandbox: \"%.*s\"" +#~ msgstr "E794: Muuttujaa ei voi asettaa hiekkalaatikossa: %s" -#: ../eval.c:16705 -#, c-format -msgid "E795: Cannot delete variable %s" -msgstr "E795: Muuttujaa %s ei voi poistaa" +#, fuzzy, c-format +#~ msgid "E795: Cannot delete variable %.*s" +#~ msgstr "E795: Muuttujaa %s ei voi poistaa" -#: ../eval.c:16724 #, c-format msgid "E704: Funcref variable name must start with a capital: %s" -msgstr "E704: Funcrefin muuttujanimen pitää alkaa suuraakkosella: %s" +msgstr "E704: Funcrefin muuttujanimen pitää alkaa suuraakkosella: %s" -#: ../eval.c:16732 #, c-format msgid "E705: Variable name conflicts with existing function: %s" msgstr "E705: Muuttujanimi on sama kuin olemassaolevan funktion: %s" -#: ../eval.c:16763 -#, c-format -msgid "E741: Value is locked: %s" -msgstr "E741: Arvo on lukittu: %s" - -#: ../eval.c:16764 ../eval.c:16769 ../message.c:1839 -msgid "Unknown" -msgstr "Tuntematon" - -#: ../eval.c:16768 -#, c-format -msgid "E742: Cannot change value of %s" -msgstr "E742: Ei voi muuttaa muuttujan %s arvoa" - -#: ../eval.c:16838 msgid "E698: variable nested too deep for making a copy" -msgstr "E698: muuttuja on upotettu liian syvälle kopioitavaksi" +msgstr "E698: muuttuja on upotettu liian syvälle kopioitavaksi" -#: ../eval.c:17249 #, c-format msgid "E123: Undefined function: %s" msgstr "E123: Tuntematon funktio: %s" -#: ../eval.c:17260 #, c-format msgid "E124: Missing '(': %s" msgstr "E124: ( puuttuu: %s" -#: ../eval.c:17293 -#, fuzzy msgid "E862: Cannot use g: here" -msgstr "E284: Ei voi asettaa IC-arvoja" +msgstr "E862: g: ei toimi täällä" -#: ../eval.c:17312 -#, c-format -msgid "E125: Illegal argument: %s" -msgstr "E125: Virheellinen argumentti: %s" - -#: ../eval.c:17323 #, fuzzy, c-format -msgid "E853: Duplicate argument name: %s" -msgstr "Kaksoiskappale kentän nimestä: %s" +#~ msgid "E932: Closure function should not be at top level: %s" +#~ msgstr "E932 Sulkeumafunktio ei voi olla uloimmalla tasolla: %s" -#: ../eval.c:17416 msgid "E126: Missing :endfunction" msgstr "E126: :endfunction puuttuu" -#: ../eval.c:17537 #, c-format msgid "E707: Function name conflicts with variable: %s" msgstr "E707: Funktion nimi on ristiriidassa muuttujan kanssa: %s" -#: ../eval.c:17549 #, c-format msgid "E127: Cannot redefine function %s: It is in use" -msgstr "E127: Funktiota %s ei voi määritellä uudestaan, koska se on käytössä" +msgstr "E127: Funktiota %s ei voi määritellä uudestaan, koska se on käytössä" -#: ../eval.c:17604 #, c-format msgid "E746: Function name does not match script file name: %s" msgstr "E746: Funktion nimi ei ole sama kuin skriptin tiedostonnimi: %s" -#: ../eval.c:17716 msgid "E129: Function name required" msgstr "E129: Funktion nimi puuttuu" -#: ../eval.c:17824 -#, fuzzy, c-format +#, c-format msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "" -"E128: Funktion nimen pitää alkaa suuraakkosella tai sisältää kaksoispisteen: " -"%s" +msgstr "E128: Funktion nimen pitää alkaa suuraakkosella tai merkeillä ’s:’: %s" -#: ../eval.c:17833 -#, fuzzy, c-format +#, c-format msgid "E884: Function name cannot contain a colon: %s" -msgstr "" -"E128: Funktion nimen pitää alkaa suuraakkosella tai sisältää kaksoispisteen: " -"%s" +msgstr "E884: Funktion nimessä ei saa olla kaksoispistettä: %s" -#: ../eval.c:18336 #, c-format msgid "E131: Cannot delete function %s: It is in use" msgstr "E131: Funktiota %s ei voi poistaa" -#: ../eval.c:18441 +#, fuzzy, c-format +#~ msgid "Cannot delete function %s: It is being used internally" +#~ msgstr "E131: Funktiota %s ei voi poistaa" + msgid "E132: Function call depth is higher than 'maxfuncdepth'" -msgstr "E132: Funktiokutsujen syvyys on enemmän kuin maxfuncdepth" +msgstr "E132: Funktiokutsujen syvyys on enemmän kuin maxfuncdepth" -#: ../eval.c:18568 #, c-format msgid "calling %s" msgstr "kutsutaan funktiota %s" -#: ../eval.c:18651 #, c-format msgid "%s aborted" msgstr "%s keskeytettiin" -#: ../eval.c:18653 -#, c-format -msgid "%s returning #%<PRId64>" -msgstr "%s palaa kohdassa #%<PRId64>" +#, fuzzy, c-format +#~ msgid "%s returning #%<PRId64>" +#~ msgstr "%s palaa kohdassa #%ld" -#: ../eval.c:18670 #, c-format msgid "%s returning %s" msgstr "%s palaa kohdassa %s" -#: ../eval.c:18691 ../ex_cmds2.c:2695 #, c-format msgid "continuing in %s" msgstr "jatkaa kohdassa %s" -#: ../eval.c:18795 msgid "E133: :return not inside a function" -msgstr "E133: :return ei ole funktion sisällä" +msgstr "E133: :return ei ole funktion sisällä" -#: ../eval.c:19159 -msgid "" -"\n" -"# global variables:\n" -msgstr "" -"\n" -"# globaalit muuttujat:\n" - -#: ../eval.c:19254 msgid "" "\n" "\tLast set from " @@ -1045,154 +1091,396 @@ msgstr "" "\n" "\tViimeksi asetettu kohteesta " -#: ../eval.c:19272 msgid "No old files" msgstr "Ei vanhoja tiedostoja" -# puhutaan merkin ulkoasusta snprintf(..., c, c, c, c) -#: ../ex_cmds.c:122 #, c-format -msgid "<%s>%s%s %d, Hex %02x, Octal %03o" -msgstr "<%s>%s%s %d, heksana %02x, oktaalina %03o" +#~ msgid "E474: Expected comma before list item: %s" +#~ msgstr "" -#: ../ex_cmds.c:145 #, c-format -msgid "> %d, Hex %04x, Octal %o" -msgstr "> %d, heksana %04x, oktaalina %o" +#~ msgid "E474: Expected colon before dictionary value: %s" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "E474: Expected string key: %s" +#~ msgstr "E415: odotuksenvastainen =-merkki: %s" + +#, fuzzy, c-format +#~ msgid "E474: Expected comma before dictionary key: %s" +#~ msgstr "E722: Sanakirjasta puuttuu pilkku: %s" + +#, fuzzy, c-format +#~ msgid "E474: Unfinished escape sequence: %.*s" +#~ msgstr "E540: Sulkematon lausekesarja" -#: ../ex_cmds.c:146 #, c-format -msgid "> %d, Hex %08x, Octal %o" -msgstr "> %d, hekdana %08x, oktaalina %o" +#~ msgid "E474: Unfinished unicode escape sequence: %.*s" +#~ msgstr "" -#: ../ex_cmds.c:684 -msgid "E134: Move lines into themselves" -msgstr "E134: Rivien siirto itsejensä päälle" +#, c-format +#~ msgid "E474: Expected four hex digits after \\u: %.*s" +#~ msgstr "" -#: ../ex_cmds.c:747 -msgid "1 line moved" -msgstr "1 rivi siirretty" +#, fuzzy, c-format +#~ msgid "E474: Unknown escape sequence: %.*s" +#~ msgstr "E409: Tuntematon ryhmän nimi: %s" -#: ../ex_cmds.c:749 #, c-format -msgid "%<PRId64> lines moved" -msgstr "%<PRId64> riviä siirretty" +#~ msgid "E474: ASCII control characters cannot be present inside string: %.*s" +#~ msgstr "" -#: ../ex_cmds.c:1175 #, c-format -msgid "%<PRId64> lines filtered" -msgstr "%<PRId64> riviä suodatettu" +#~ msgid "E474: Only UTF-8 strings allowed: %.*s" +#~ msgstr "" -#: ../ex_cmds.c:1194 -msgid "E135: *Filter* Autocommands must not change current buffer" -msgstr "E135: *Filter*-autocommand ei voi vaihtaa puskuria" +#, c-format +#~ msgid "" +#~ "E474: Only UTF-8 code points up to U+10FFFF are allowed to appear unescaped: " +#~ "%.*s" +#~ msgstr "" -#: ../ex_cmds.c:1244 -msgid "[No write since last change]\n" -msgstr "[Viimeisintä muutosta ei ole kirjoitettu]\n" +#, fuzzy, c-format +#~ msgid "E474: Expected string end: %.*s" +#~ msgstr "E415: odotuksenvastainen =-merkki: %s" + +#, fuzzy, c-format +#~ msgid "E474: Leading zeroes are not allowed: %.*s" +#~ msgstr "E786: Aluetta ei voi käyttää" + +#, fuzzy, c-format +#~ msgid "E474: Missing number after minus sign: %.*s" +#~ msgstr "E526: Lukuarvo puuttuu merkkijonon <%s> jälkeen" + +#, fuzzy, c-format +#~ msgid "E474: Missing number after decimal dot: %.*s" +#~ msgstr "E526: Lukuarvo puuttuu merkkijonon <%s> jälkeen" + +#, fuzzy, c-format +#~ msgid "E474: Missing exponent: %.*s" +#~ msgstr "E114: Puuttuva lainausmerkki: %s" -#: ../ex_cmds.c:1424 #, c-format -msgid "%sviminfo: %s in line: " -msgstr "%sviminfo: %s rivillä: " +#~ msgid "" +#~ "E685: internal error: while converting number \"%.*s\" to float string2float " +#~ "consumed %zu bytes in place of %zu" +#~ msgstr "" -#: ../ex_cmds.c:1431 -msgid "E136: viminfo: Too many errors, skipping rest of file" -msgstr "E136: viminfo: liikaa virheitä, ohitetaan lopputiedosto" +#, c-format +#~ msgid "" +#~ "E685: internal error: while converting number \"%.*s\" to integer vim_str2nr " +#~ "consumed %i bytes in place of %zu" +#~ msgstr "" + +#~ msgid "E474: Attempt to decode a blank string" +#~ msgstr "" -#: ../ex_cmds.c:1458 #, c-format -msgid "Reading viminfo file \"%s\"%s%s%s" -msgstr "Luetaan viminfo-tiedostoa \"%s\"%s%s%s" +#~ msgid "E474: No container to close: %.*s" +#~ msgstr "" -#: ../ex_cmds.c:1460 -msgid " info" -msgstr " info" +#, c-format +#~ msgid "E474: Closing list with curly bracket: %.*s" +#~ msgstr "" -#: ../ex_cmds.c:1461 -msgid " marks" -msgstr " merkit" +#, fuzzy, c-format +#~ msgid "E474: Closing dictionary with square bracket: %.*s" +#~ msgstr "E725: dict-funktio ilman sanakirjaa: %s" -#: ../ex_cmds.c:1462 -msgid " oldfiles" -msgstr " vanhaatiedostoa" +#, fuzzy, c-format +#~ msgid "E474: Trailing comma: %.*s" +#~ msgstr "E488: Ylimääräisiä merkkejä perässä" -#: ../ex_cmds.c:1463 -msgid " FAILED" -msgstr " EPÄONNISTUI" +#, c-format +#~ msgid "E474: Expected value after colon: %.*s" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "E474: Expected value: %.*s" +#~ msgstr "E415: odotuksenvastainen =-merkki: %s" -#. avoid a wait_return for this message, it's annoying -#: ../ex_cmds.c:1541 #, c-format -msgid "E137: Viminfo file is not writable: %s" -msgstr "E137: Viminfo-tiedostoon ei voitu kirjoittaa: %s" +#~ msgid "E474: Comma not inside container: %.*s" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "E474: Duplicate comma: %.*s" +#~ msgstr "E721: Kaksi samaa avainta sanakirjassa: %s" + +#, fuzzy, c-format +#~ msgid "E474: Comma after colon: %.*s" +#~ msgstr "E254: Väriä %s ei voi määritellä" + +#, fuzzy, c-format +#~ msgid "E474: Using comma in place of colon: %.*s" +#~ msgstr "E722: Sanakirjasta puuttuu pilkku: %s" -#: ../ex_cmds.c:1626 #, c-format -msgid "E138: Can't write viminfo file %s!" -msgstr "E138: Viminfo-tiedoston kirjoittaminen ei onnistu %s" +#~ msgid "E474: Leading comma: %.*s" +#~ msgstr "" -#: ../ex_cmds.c:1635 #, c-format -msgid "Writing viminfo file \"%s\"" -msgstr "Kirjoitetaan viminfo-tiedostoa %s" +#~ msgid "E474: Colon not inside container: %.*s" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "E474: Using colon not in dictionary: %.*s" +#~ msgstr "E720: Sanakirjasta puuttuu kaksoispiste: %s" + +#, fuzzy, c-format +#~ msgid "E474: Unexpected colon: %.*s" +#~ msgstr "E415: odotuksenvastainen =-merkki: %s" -#. Write the info: -#: ../ex_cmds.c:1720 #, c-format -msgid "# This viminfo file was generated by Vim %s.\n" -msgstr "# Vimin %s generoima viminfo-tiedosto.\n" +#~ msgid "E474: Colon after comma: %.*s" +#~ msgstr "" -#: ../ex_cmds.c:1722 -msgid "" -"# You may edit it if you're careful!\n" -"\n" -msgstr "" -"# Muokkaa varovasti!\n" -"\n" +#, fuzzy, c-format +#~ msgid "E474: Duplicate colon: %.*s" +#~ msgstr "E721: Kaksi samaa avainta sanakirjassa: %s" + +#, fuzzy, c-format +#~ msgid "E474: Expected null: %.*s" +#~ msgstr "E415: odotuksenvastainen =-merkki: %s" + +#, fuzzy, c-format +#~ msgid "E474: Expected true: %.*s" +#~ msgstr "E270: odotuksenvastainen redo" + +#, fuzzy, c-format +#~ msgid "E474: Expected false: %.*s" +#~ msgstr "E415: odotuksenvastainen =-merkki: %s" -#: ../ex_cmds.c:1723 -msgid "# Value of 'encoding' when this file was written\n" -msgstr "# encoding-muuttujan arvo tiedostoa kirjoitettaessa\n" +#, fuzzy, c-format +#~ msgid "E474: Unidentified byte: %.*s" +#~ msgstr "E121: Määrittelemätön muuttuja: %s" -#: ../ex_cmds.c:1800 -msgid "Illegal starting char" -msgstr "Virheellinen aloitusmerkki" +#, fuzzy, c-format +#~ msgid "E474: Trailing characters: %.*s" +#~ msgstr "E488: Ylimääräisiä merkkejä perässä" + +#, fuzzy, c-format +#~ msgid "E474: Unexpected end of input: %.*s" +#~ msgstr "E415: odotuksenvastainen =-merkki: %s" + +#, c-format +#~ msgid "key %s" +#~ msgstr "" + +#, c-format +#~ msgid "key %s at index %i from special map" +#~ msgstr "" + +#, c-format +#~ msgid "index %i" +#~ msgstr "" + +#~ msgid "partial" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "argument %i" +#~ msgstr "-c-argumentti" + +#, fuzzy +#~ msgid "partial self dictionary" +#~ msgstr "ei voida muuttaa kiinnitettyä sanakirjaa" + +#~ msgid "itself" +#~ msgstr "" + +#. Only give this message once for a recursive call to avoid +#. flooding the user with errors. +#~ msgid "E724: unable to correctly dump variable with self-referencing container" +#~ msgstr "" + +#~ msgid "E474: Unable to represent NaN value in JSON" +#~ msgstr "" + +#~ msgid "E474: Unable to represent infinity in JSON" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "E474: String \"%.*s\" contains byte that does not start any UTF-8 character" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "E474: UTF-8 string contains code point which belongs to a surrogate pair: " +#~ "%.*s" +#~ msgstr "" + +#, fuzzy +#~ msgid "E474: Unable to convert EXT string to JSON" +#~ msgstr "E620: Tulostuskoodaukseen %s muunto ei onnistu" + +#, c-format +#~ msgid "E474: Error while dumping %s, %s: attempt to dump function reference" +#~ msgstr "" + +#, fuzzy +#~ msgid "E474: Invalid key in special dictionary" +#~ msgstr "E736: Virheellinen toiminto sanakirjalle" + +#, c-format +#~ msgid "E5004: Error while dumping %s, %s: attempt to dump function reference" +#~ msgstr "" + +#, c-format +#~ msgid "E5005: Unable to dump %s: container references itself in %s" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "E684: list index out of range: %<PRId64>" +#~ msgstr "E684: Indeksi %ld luettelon rajojen ulkopuolella" + +#~ msgid "E6000: Argument is not a function or function name" +#~ msgstr "" + +#, c-format +msgid "E737: Key already exists: %s" +msgstr "E737: Avain on jo olemassa: %s" + +#, fuzzy +#~ msgid "tv_clear() argument" +#~ msgstr "filter()-argumentti" + +msgid "E743: variable nested too deep for (un)lock" +msgstr "E743: muuttujassa liian monta tasoa lukituksen käsittelyyn" + +#, fuzzy, c-format +#~ msgid "E741: Value is locked: %.*s" +#~ msgstr "E741: Arvo on lukittu: %s" + +#, fuzzy, c-format +#~ msgid "E742: Cannot change value of %.*s" +#~ msgstr "E742: Ei voi muuttaa muuttujan %s arvoa" + +msgid "Unknown" +msgstr "Tuntematon" + +#, fuzzy +#~ msgid "E805: Expected a Number or a String, Float found" +#~ msgstr "E807: Odotettiin Float-argumenttia printf():lle" + +#~ msgid "E703: Expected a Number or a String, Funcref found" +#~ msgstr "" + +#, fuzzy +#~ msgid "E745: Expected a Number or a String, List found" +#~ msgstr "E807: Odotettiin Float-argumenttia printf():lle" + +#~ msgid "E728: Expected a Number or a String, Dictionary found" +#~ msgstr "" + +#, fuzzy +#~ msgid "E5300: Expected a Number or a String" +#~ msgstr "E807: Odotettiin Float-argumenttia printf():lle" + +msgid "E745: Using a List as a Number" +msgstr "E745: Lista ei käy Numberista" + +msgid "E728: Using a Dictionary as a Number" +msgstr "E728: Sanakirja ei käy Numberista" + +msgid "E805: Using a Float as a Number" +msgstr "E805: Float ei käy Numberista" + +#, fuzzy +#~ msgid "E685: using an invalid value as a Number" +#~ msgstr "E908: huono arvo merkkijonolle" + +msgid "E730: using List as a String" +msgstr "E730: Lista ei käy merkkijonosta" + +msgid "E731: using Dictionary as a String" +msgstr "E731: Sanakirja ei käy merkkijonosta" + +msgid "E908: using an invalid value as a String" +msgstr "E908: huono arvo merkkijonolle" + +msgid "E891: Using a Funcref as a Float" +msgstr "E891: Funcref ei käy Floatista" + +msgid "E892: Using a String as a Float" +msgstr "E892: String ei käy Floatista" + +msgid "E893: Using a List as a Float" +msgstr "E893: Lista ei käy Floatista" + +msgid "E894: Using a Dictionary as a Float" +msgstr "E894: Sanakirja ei käy Floatista" + +msgid "E907: Using a special value as a Float" +msgstr "E907: Käytettiin erikoisarvoa Floattina" + +msgid "E808: Number or Float required" +msgstr "E808: Number tai Float vaaditaan" + +# puhutaan merkin ulkoasusta snprintf(..., c, c, c, c) +#, c-format +msgid "<%s>%s%s %d, Hex %02x, Octal %03o" +msgstr "<%s>%s%s %d, heksana %02x, oktaalina %03o" + +#, c-format +msgid "> %d, Hex %04x, Octal %o" +msgstr "> %d, heksana %04x, oktaalina %o" + +#, c-format +msgid "> %d, Hex %08x, Octal %o" +msgstr "> %d, hekdana %08x, oktaalina %o" + +msgid "E134: Move lines into themselves" +msgstr "E134: Rivien siirto itsejensä päälle" + +msgid "1 line moved" +msgstr "1 rivi siirretty" + +#, fuzzy, c-format +#~ msgid "%<PRId64> lines moved" +#~ msgstr "%ld riviä siirretty" + +#, c-format +msgid "E482: Can't create file %s" +msgstr "E482: Tiedostoa %s ei voi luoda" + +#, fuzzy, c-format +#~ msgid "%<PRId64> lines filtered" +#~ msgstr "%ld riviä suodatettu" + +msgid "E135: *Filter* Autocommands must not change current buffer" +msgstr "E135: *Filter*-autocommand ei voi vaihtaa puskuria" + +msgid "[No write since last change]\n" +msgstr "[Viimeisintä muutosta ei ole kirjoitettu]\n" -#: ../ex_cmds.c:2162 msgid "Write partial file?" msgstr "Kirjoita osittainen tiedosto" -#: ../ex_cmds.c:2166 msgid "E140: Use ! to write partial buffer" -msgstr "E140: Käytä !-komentoa osittaisen puskurin kirjoittamiseen" +msgstr "E140: Käytä !-komentoa osittaisen puskurin kirjoittamiseen" -#: ../ex_cmds.c:2281 #, c-format msgid "Overwrite existing file \"%s\"?" msgstr "Ylikirjoitetaanko olemassaoleva tiedosto %s?" -#: ../ex_cmds.c:2317 #, c-format msgid "Swap file \"%s\" exists, overwrite anyway?" msgstr "Swap-tiedosto %s on olemassa, ylikirjoitetaanko?" -#: ../ex_cmds.c:2326 #, c-format msgid "E768: Swap file exists: %s (:silent! overrides)" msgstr "E768: Swap-tiedosto on jo olemassa: %s (komento :silent! ohittaa)" -#: ../ex_cmds.c:2381 -#, c-format -msgid "E141: No file name for buffer %<PRId64>" -msgstr "E141: Ei tiedostonimeä puskurille %<PRId64>" +#, fuzzy, c-format +#~ msgid "E141: No file name for buffer %<PRId64>" +#~ msgstr "E141: Ei tiedostonimeä puskurille %ld" -#: ../ex_cmds.c:2412 msgid "E142: File not written: Writing is disabled by 'write' option" msgstr "" -"E142: Tiedostoa ei kirjoitettu; write-asetus poistaa kirjoituksen käytöstä" +"E142: Tiedostoa ei kirjoitettu; write-asetus poistaa kirjoituksen käytöstä" -#: ../ex_cmds.c:2434 #, c-format msgid "" "'readonly' option is set for \"%s\".\n" @@ -1201,7 +1489,6 @@ msgstr "" "readonly asetettu tiedostolle \"%s\".\n" "Kirjoitetaanko?" -#: ../ex_cmds.c:2439 #, c-format msgid "" "File permissions of \"%s\" are read-only.\n" @@ -1210,799 +1497,599 @@ msgid "" msgstr "" "Tiedosto %s on kirjoitussuojattu.\n" "Siihen saattaa voida silti kirjoittaa.\n" -"Yritetäänkö?" +"Yritetäänkö?" -#: ../ex_cmds.c:2451 #, c-format msgid "E505: \"%s\" is read-only (add ! to override)" -msgstr "E505: %s on kirjoitussuojattu (lisää komentoon ! ohittaaksesi)" +msgstr "E505: %s on kirjoitussuojattu (lisää komentoon ! ohittaaksesi)" -#: ../ex_cmds.c:3120 #, c-format msgid "E143: Autocommands unexpectedly deleted new buffer %s" msgstr "E143: Autocommand poisti uuden puskurin odotuksen vastaisesti %s" -#: ../ex_cmds.c:3313 msgid "E144: non-numeric argument to :z" msgstr "E144: :z:n argumentti ei ole numero" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: Kuoren komennot eivät toimi rvimissä" +#, fuzzy +#~ msgid "E145: Shell commands not allowed in restricted mode" +#~ msgstr "E145: Kuoren komennot eivät toimi rvimissä" -#: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" -msgstr "E146: Säännöllistä ilmausta ei voi rajata kirjaimilla" +msgstr "E146: Säännöllistä ilmausta ei voi rajata kirjaimilla" -#: ../ex_cmds.c:3964 #, c-format msgid "replace with %s (y/n/a/q/l/^E/^Y)?" msgstr "korvaa kohteella %s (y/n/a/q/l/^E/^Y)?" -#: ../ex_cmds.c:4379 msgid "(Interrupted) " msgstr "(Keskeytetty)" -#: ../ex_cmds.c:4384 msgid "1 match" -msgstr "1 täsmäys" +msgstr "1 täsmäys" -#: ../ex_cmds.c:4384 msgid "1 substitution" msgstr "1 korvaus" -#: ../ex_cmds.c:4387 -#, c-format -msgid "%<PRId64> matches" -msgstr "%<PRId64> täsmäystä" +#, fuzzy, c-format +#~ msgid "%<PRId64> matches" +#~ msgstr "%ld täsmäystä" -#: ../ex_cmds.c:4388 -#, c-format -msgid "%<PRId64> substitutions" -msgstr "%<PRId64> korvausta" +#, fuzzy, c-format +#~ msgid "%<PRId64> substitutions" +#~ msgstr "%ld korvausta" -#: ../ex_cmds.c:4392 msgid " on 1 line" -msgstr " 1 rivillä" +msgstr " 1 rivillä" -#: ../ex_cmds.c:4395 -#, c-format -msgid " on %<PRId64> lines" -msgstr " %<PRId64> rivillä" +#, fuzzy, c-format +#~ msgid " on %<PRId64> lines" +#~ msgstr " %ld rivillä" -#: ../ex_cmds.c:4438 msgid "E147: Cannot do :global recursive" msgstr "E147: :globalia ei voi suorittaa rekursiivisesti" -#: ../ex_cmds.c:4467 msgid "E148: Regular expression missing from global" -msgstr "E148: Säännöllinen ilmaus puuttuu globaalista" +msgstr "E148: Säännöllinen ilmaus puuttuu globaalista" -#: ../ex_cmds.c:4508 #, c-format msgid "Pattern found in every line: %s" -msgstr "Kuvio löytyi joka riviltä: %s" +msgstr "Kuvio löytyi joka riviltä: %s" -#: ../ex_cmds.c:4510 -#, fuzzy, c-format +#, c-format msgid "Pattern not found: %s" -msgstr "Kuviota ei löydy" - -#: ../ex_cmds.c:4587 -msgid "" -"\n" -"# Last Substitute String:\n" -"$" -msgstr "" -"\n" -"# Viimeisin korvausmerkkijono:\n" -"$" +msgstr "Kuviota ei löydy: %s" -#: ../ex_cmds.c:4679 msgid "E478: Don't panic!" -msgstr "E478: Älä panikoi." +msgstr "E478: Älä panikoi." -#: ../ex_cmds.c:4717 #, c-format msgid "E661: Sorry, no '%s' help for %s" -msgstr "E661: Sori, ei löydy %s-ohjetta kohteelle %s" +msgstr "E661: ei löydy %s-ohjetta kohteelle %s" -#: ../ex_cmds.c:4719 #, c-format msgid "E149: Sorry, no help for %s" -msgstr "E149: Sori, ei löydy ohjetta kohteelle %s" +msgstr "E149: ei löydy ohjetta kohteelle %s" -#: ../ex_cmds.c:4751 #, c-format msgid "Sorry, help file \"%s\" not found" -msgstr "Sori, ohjetiedostoa %s ei löydy" +msgstr "ohjetiedostoa %s ei löydy" -#: ../ex_cmds.c:5323 -#, c-format -msgid "E150: Not a directory: %s" -msgstr "E150: Ei ole hakemisto: %s" - -#: ../ex_cmds.c:5446 #, c-format msgid "E152: Cannot open %s for writing" msgstr "E152: Ei voi avata tiedostoa %s kirjoittamista varten" -#: ../ex_cmds.c:5471 #, c-format msgid "E153: Unable to open %s for reading" msgstr "E153: Ei voi avata tiedostoa %s lukemista varten" -#: ../ex_cmds.c:5500 #, c-format msgid "E670: Mix of help file encodings within a language: %s" -msgstr "E670: Monia ohjetiedostokoodauksia kielessä: %s" +msgstr "E670: Monia ohjetiedostokoodauksia kielessä: %s" -#: ../ex_cmds.c:5565 #, c-format msgid "E154: Duplicate tag \"%s\" in file %s/%s" -msgstr "E154: Kaksoiskappale tägistä %s tiedostossa %s/%s" +msgstr "E154: Kaksoiskappale tägistä %s tiedostossa %s/%s" + +#, c-format +msgid "E150: Not a directory: %s" +msgstr "E150: Ei ole hakemisto: %s" -#: ../ex_cmds.c:5687 #, c-format msgid "E160: Unknown sign command: %s" msgstr "E160: Tuntematon merkkikomento: %s" -#: ../ex_cmds.c:5704 msgid "E156: Missing sign name" msgstr "E156: Merkki puuttuu" -#: ../ex_cmds.c:5746 msgid "E612: Too many signs defined" -msgstr "E612: Liikaa merkkejä määritelty" +msgstr "E612: Liikaa merkkejä määritelty" -#: ../ex_cmds.c:5813 #, c-format msgid "E239: Invalid sign text: %s" msgstr "E239: Virheellinen merkkiteksti: %s" -#: ../ex_cmds.c:5844 ../ex_cmds.c:6035 #, c-format msgid "E155: Unknown sign: %s" msgstr "E155: Tuntematon merkki: %s" -#: ../ex_cmds.c:5877 msgid "E159: Missing sign number" msgstr "E159: Merkin numero puuttuu" -#: ../ex_cmds.c:5971 #, c-format msgid "E158: Invalid buffer name: %s" msgstr "E158: Virheellinen puskurin nimi: %s" -#: ../ex_cmds.c:6008 +msgid "E934: Cannot jump to a buffer that does not have a name" +msgstr "E934: Ei voida hypätä puskuriin jolla ei ole nimeä" + +#, fuzzy, c-format +#~ msgid "E157: Invalid sign ID: %<PRId64>" +#~ msgstr "E157: Virheellinen merkin tunnus: %ld" + #, c-format -msgid "E157: Invalid sign ID: %<PRId64>" -msgstr "E157: Virheellinen merkin tunnus: %<PRId64>" +msgid "E885: Not possible to change sign %s" +msgstr "E885: Ei voida muuttaa merkkiä %s" -#: ../ex_cmds.c:6066 msgid " (not supported)" msgstr " (ei tuettu)" -#: ../ex_cmds.c:6169 msgid "[Deleted]" msgstr "[Poistettu]" -#: ../ex_cmds2.c:139 msgid "Entering Debug mode. Type \"cont\" to continue." -msgstr "Siirrytään vianetsintätilaan, kirjoita cont jatkaaksesi." +msgstr "Siirrytään vianetsintätilaan, kirjoita cont jatkaaksesi." -#: ../ex_cmds2.c:143 ../ex_docmd.c:759 -#, c-format -msgid "line %<PRId64>: %s" -msgstr "rivi %<PRId64>: %s" +#, fuzzy, c-format +#~ msgid "line %<PRId64>: %s" +#~ msgstr "rivi %ld: %s" -#: ../ex_cmds2.c:145 #, c-format msgid "cmd: %s" msgstr "kmnt: %s" -#: ../ex_cmds2.c:322 +msgid "frame is zero" +msgstr "kehys on nolla" + #, c-format -msgid "Breakpoint in \"%s%s\" line %<PRId64>" -msgstr "Katkaisukohta %s%s rivillä %<PRId64>" +msgid "frame at highest level: %d" +msgstr "kehys ylimmällä tasolla: %d" + +#, fuzzy, c-format +#~ msgid "Breakpoint in \"%s%s\" line %<PRId64>" +#~ msgstr "Katkaisukohta %s%s rivillä %ld" -#: ../ex_cmds2.c:581 #, c-format msgid "E161: Breakpoint not found: %s" msgstr "E161: Katkaisukohta puuttuu: %s" -#: ../ex_cmds2.c:611 msgid "No breakpoints defined" msgstr "Ei katkaisukohtia" -#: ../ex_cmds2.c:617 -#, c-format -msgid "%3d %s %s line %<PRId64>" -msgstr "%3d %s %s rivi %<PRId64>" +#, fuzzy, c-format +#~ msgid "%3d %s %s line %<PRId64>" +#~ msgstr "%3d %s %s rivi %ld" -#: ../ex_cmds2.c:942 msgid "E750: First use \":profile start {fname}\"" -msgstr "E750: Aloita käskyllä :profile start {fname}" +msgstr "E750: Aloita käskyllä :profile start {fname}" -#: ../ex_cmds2.c:1269 #, c-format msgid "Save changes to \"%s\"?" msgstr "Tallennetaanko muutokset tiedostoon %s?" -#: ../ex_cmds2.c:1271 ../ex_docmd.c:8851 msgid "Untitled" -msgstr "Nimetön" +msgstr "Nimetön" -#: ../ex_cmds2.c:1421 #, c-format msgid "E162: No write since last change for buffer \"%s\"" -msgstr "E162: Muutoksia ei ole kirjoitettu puskurin %s viime muutoksen jälkeen" +msgstr "E162: Muutoksia ei ole kirjoitettu puskurin %s viime muutoksen jälkeen" -#: ../ex_cmds2.c:1480 msgid "Warning: Entered other buffer unexpectedly (check autocommands)" msgstr "Varoitus: Puskuri vaihtui odottamatta (tarkista autocommands)" -#: ../ex_cmds2.c:1826 msgid "E163: There is only one file to edit" msgstr "E163: Vain yksi tiedosto muokattavana" -#: ../ex_cmds2.c:1828 msgid "E164: Cannot go before first file" -msgstr "E164: Ensimmäisen tiedoston ohi ei voi mennä" +msgstr "E164: Ensimmäisen tiedoston ohi ei voi mennä" -#: ../ex_cmds2.c:1830 msgid "E165: Cannot go beyond last file" -msgstr "E165: Viimeisen tiedoston ohi ei voi mennä" +msgstr "E165: Viimeisen tiedoston ohi ei voi mennä" -#: ../ex_cmds2.c:2175 #, c-format msgid "E666: compiler not supported: %s" -msgstr "E666: kääntäjää ei tueta: %s" +msgstr "E666: kääntäjää ei tueta: %s" -#: ../ex_cmds2.c:2257 #, c-format msgid "Searching for \"%s\" in \"%s\"" -msgstr "Etsitään ilmausta %s kohteesta %s" +msgstr "Etsitään ilmausta %s kohteesta %s" -#: ../ex_cmds2.c:2284 #, c-format msgid "Searching for \"%s\"" -msgstr "Etsitään ilmausta %s" +msgstr "Etsitään ilmausta %s" -#: ../ex_cmds2.c:2307 #, c-format -msgid "not found in 'runtimepath': \"%s\"" -msgstr "ei löydy runtimepathista: %s" +msgid "not found in '%s': \"%s\"" +msgstr "'%s' ei löydy kohteesta: %s" -#: ../ex_cmds2.c:2472 #, c-format msgid "Cannot source a directory: \"%s\"" msgstr "Hakemistoa ei voi ladata: %s" -#: ../ex_cmds2.c:2518 #, c-format msgid "could not source \"%s\"" msgstr "ei voitu ladata %s" -#: ../ex_cmds2.c:2520 -#, c-format -msgid "line %<PRId64>: could not source \"%s\"" -msgstr "rivi %<PRId64>: ei voitu ladata %s" +#, fuzzy, c-format +#~ msgid "line %<PRId64>: could not source \"%s\"" +#~ msgstr "rivi %ld: ei voitu ladata %s" -#: ../ex_cmds2.c:2535 #, c-format msgid "sourcing \"%s\"" msgstr "ladataan %s" -#: ../ex_cmds2.c:2537 -#, c-format -msgid "line %<PRId64>: sourcing \"%s\"" -msgstr "rivi %<PRId64>: ladataan %s" +#, fuzzy, c-format +#~ msgid "line %<PRId64>: sourcing \"%s\"" +#~ msgstr "rivi %ld: ladataan %s" -#: ../ex_cmds2.c:2693 #, c-format msgid "finished sourcing %s" msgstr "ladattu %s" -#: ../ex_cmds2.c:2765 msgid "modeline" msgstr "mode-rivi" -#: ../ex_cmds2.c:2767 msgid "--cmd argument" msgstr "--cmd-argumentti" -#: ../ex_cmds2.c:2769 msgid "-c argument" msgstr "-c-argumentti" -#: ../ex_cmds2.c:2771 msgid "environment variable" -msgstr "ympäristömuuttuja" +msgstr "ympäristömuuttuja" -#: ../ex_cmds2.c:2773 msgid "error handler" -msgstr "virhekäsittelin" +msgstr "virhekäsittelin" -#: ../ex_cmds2.c:3020 msgid "W15: Warning: Wrong line separator, ^M may be missing" -msgstr "W15: Varoitus: Väärä rivierotin, ^M saattaa puuttua" +msgstr "W15: Varoitus: Väärä rivierotin, ^M saattaa puuttua" -#: ../ex_cmds2.c:3139 msgid "E167: :scriptencoding used outside of a sourced file" msgstr "E167: :scriptencoding ladatun tiedoston ulkopuolella" -#: ../ex_cmds2.c:3166 msgid "E168: :finish used outside of a sourced file" msgstr "E168: :finish ladatun tiedoston ulkopuolella" -#: ../ex_cmds2.c:3389 #, c-format msgid "Current %slanguage: \"%s\"" -msgstr "Käytössä oleva %skieli: %s" +msgstr "Käytössä oleva %skieli: %s" -#: ../ex_cmds2.c:3404 #, c-format msgid "E197: Cannot set language to \"%s\"" -msgstr "E197: Kieleksi ei voitu asettaa kieltä %s" +msgstr "E197: Kieleksi ei voitu asettaa kieltä %s" #. don't redisplay the window #. don't wait for return -#: ../ex_docmd.c:387 msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." -msgstr "Siirrytään Ex-tilaan, kirjoita visual palataksesi normaaliin tilaan." +msgstr "Siirrytään Ex-tilaan, kirjoita visual palataksesi normaaliin tilaan." -#: ../ex_docmd.c:428 msgid "E501: At end-of-file" msgstr "E501: Tiedoston lopussa" -#: ../ex_docmd.c:513 msgid "E169: Command too recursive" msgstr "E169: Liian rekursiivinen komento" -#: ../ex_docmd.c:1006 +#, fuzzy +#~ msgid "line %" +#~ msgstr "rivi %ld" + #, c-format msgid "E605: Exception not caught: %s" msgstr "E605: Kiinniottamaton poikkeus: %s" -#: ../ex_docmd.c:1085 msgid "End of sourced file" msgstr "Ladatun tiedoston loppu" -#: ../ex_docmd.c:1086 msgid "End of function" msgstr "Funktion loppu" -#: ../ex_docmd.c:1628 msgid "E464: Ambiguous use of user-defined command" -msgstr "E464: Käyttäjän määrittelemän komennon monimerkityksinen käyttö" +msgstr "E464: Käyttäjän määrittelemän komennon monimerkityksinen käyttö" -#: ../ex_docmd.c:1638 msgid "E492: Not an editor command" msgstr "E492: Ei ole editorikomento" -#: ../ex_docmd.c:1729 msgid "E493: Backwards range given" msgstr "E493: Takaperoinen arvoalue annettu" -#: ../ex_docmd.c:1733 msgid "Backwards range given, OK to swap" -msgstr "Takaperoinen arvoalue annettu, OK kääntää" +msgstr "Takaperoinen arvoalue annettu, OK kääntää" #. append #. typed wrong -#: ../ex_docmd.c:1787 msgid "E494: Use w or w>>" -msgstr "E494: Käytä w:tä tai w>>:aa" - -#: ../ex_docmd.c:3454 -msgid "E319: The command is not available in this version" -msgstr "E319: Komento ei ole käytettävissä tässä versiossa" +msgstr "E494: Käytä w:tä tai w>>:aa" -#: ../ex_docmd.c:3752 -msgid "E172: Only one file name allowed" -msgstr "E172: Vain yksi tiedostonimi sallitaan" +#, fuzzy +#~ msgid "E319: The command is not available in this version" +#~ msgstr "E319: Komento ei ole käytettävissä tässä versiossa" -#: ../ex_docmd.c:4238 msgid "1 more file to edit. Quit anyway?" -msgstr "vielä 1 tiedosto muokattavana, lopetaanko silti?" +msgstr "vielä 1 tiedosto muokattavana, lopetaanko silti?" -#: ../ex_docmd.c:4242 #, c-format msgid "%d more files to edit. Quit anyway?" -msgstr "vielä %d tiedostoa muokattavana, lopetetaanko silti?" +msgstr "vielä %d tiedostoa muokattavana, lopetetaanko silti?" -#: ../ex_docmd.c:4248 msgid "E173: 1 more file to edit" -msgstr "E173: vielä 1 tiedosto muokattavana" +msgstr "E173: vielä 1 tiedosto muokattavana" -#: ../ex_docmd.c:4250 -#, c-format -msgid "E173: %<PRId64> more files to edit" -msgstr "E173: vielä %<PRId64> tiedostoa muokattavana" +#, fuzzy, c-format +#~ msgid "E173: %<PRId64> more files to edit" +#~ msgstr "E173: vielä %ld tiedostoa muokattavana" -#: ../ex_docmd.c:4320 msgid "E174: Command already exists: add ! to replace it" -msgstr "E174: Komento on jo olemassa, käytä !:ä korvataksesi" +msgstr "E174: Komento on jo olemassa, käytä !:ä korvataksesi" -#: ../ex_docmd.c:4432 msgid "" "\n" -" Name Args Range Complete Definition" +" Name Args Address Complete Definition" msgstr "" "\n" -" Nimi Arg Arvot Valmis Määritelmä" +" Nimi Argumentit Osoite Valmis Määritelmä" -#: ../ex_docmd.c:4516 msgid "No user-defined commands found" -msgstr "Ei käyttäjän määrittelemiä komentoja" +msgstr "Ei käyttäjän määrittelemiä komentoja" -#: ../ex_docmd.c:4538 msgid "E175: No attribute specified" -msgstr "E175: Ei attribuutteja määriteltynä" +msgstr "E175: Ei attribuutteja määriteltynä" -#: ../ex_docmd.c:4583 msgid "E176: Invalid number of arguments" -msgstr "E176: Väärä määrä attribuutteja" +msgstr "E176: Väärä määrä attribuutteja" -#: ../ex_docmd.c:4594 msgid "E177: Count cannot be specified twice" -msgstr "E177: Lukumäärää ei voi määritellä kahdesti" +msgstr "E177: Lukumäärää ei voi määritellä kahdesti" -#: ../ex_docmd.c:4603 msgid "E178: Invalid default value for count" -msgstr "E178: Lukumäärän oletusarvo on väärä" +msgstr "E178: Lukumäärän oletusarvo on väärä" -#: ../ex_docmd.c:4625 msgid "E179: argument required for -complete" msgstr "E179: -complete vaatii argumentin" -#: ../ex_docmd.c:4635 +msgid "E179: argument required for -addr" +msgstr "E179: -addr vaatii argumentin" + #, c-format msgid "E181: Invalid attribute: %s" msgstr "E181: Virheellinen attribuutti: %s" -#: ../ex_docmd.c:4678 msgid "E182: Invalid command name" msgstr "E182: Virheellinen komennon nimi" -#: ../ex_docmd.c:4691 msgid "E183: User defined commands must start with an uppercase letter" -msgstr "E183: Käyttäjän määrittelemän komennon pitää alkaa suuraakkosella" +msgstr "E183: Käyttäjän määrittelemän komennon pitää alkaa suuraakkosella" -#: ../ex_docmd.c:4696 -#, fuzzy msgid "E841: Reserved name, cannot be used for user defined command" -msgstr "E464: Käyttäjän määrittelemän komennon monimerkityksinen käyttö" +msgstr "E841: Varattua nimeä ei voi käyttää käyttäjän määrittelemänä komentona" -#: ../ex_docmd.c:4751 #, c-format msgid "E184: No such user-defined command: %s" -msgstr "E184: Käyttäjän komentoa ei ole olemassa: %s" +msgstr "E184: Käyttäjän komentoa ei ole olemassa: %s" + +#, c-format +msgid "E180: Invalid address type value: %s" +msgstr "E180: Virheellinen osoitetyyppiarvo: %s" -#: ../ex_docmd.c:5219 #, c-format msgid "E180: Invalid complete value: %s" -msgstr "E180: Virheellinen täydennysarvo: %s" +msgstr "E180: Virheellinen täydennysarvo: %s" -#: ../ex_docmd.c:5225 msgid "E468: Completion argument only allowed for custom completion" -msgstr "E468: Täydennysargumentti sopii vain itse määriteltyyn täydennykseen" +msgstr "E468: Täydennysargumentti sopii vain itse määriteltyyn täydennykseen" -#: ../ex_docmd.c:5231 msgid "E467: Custom completion requires a function argument" -msgstr "E467: Itse määritelty täydennys vaatii funktioargumentin" +msgstr "E467: Itse määritelty täydennys vaatii funktioargumentin" -#: ../ex_docmd.c:5257 -#, fuzzy, c-format +#, c-format msgid "E185: Cannot find color scheme '%s'" -msgstr "E185: Väriteemaa %s ei löydy" +msgstr "E185: Väriteemaa %s ei löydy" -#: ../ex_docmd.c:5263 msgid "Greetings, Vim user!" -msgstr "Tervehdys, Vimin käyttäjä." +msgstr "Tervehdys, Vimin käyttäjä." -#: ../ex_docmd.c:5431 msgid "E784: Cannot close last tab page" -msgstr "E784: Viimeistä välilehteä ei voi sulkea" +msgstr "E784: Viimeistä välilehteä ei voi sulkea" -#: ../ex_docmd.c:5462 msgid "Already only one tab page" -msgstr "Vain yksi välilehti jäljellä enää" +msgstr "Vain yksi välilehti jäljellä enää" -#: ../ex_docmd.c:6004 #, c-format msgid "Tab page %d" msgstr "Tabisivu %d" -#: ../ex_docmd.c:6295 msgid "No swap file" msgstr "Ei swap-tiedostoa" -#: ../ex_docmd.c:6478 -msgid "E747: Cannot change directory, buffer is modified (add ! to override)" -msgstr "" -"E747: Hakemistoa ei voida muuttaa, puskuria on muokattu (lisää komentoon ! " -"ohittaaksesi" - -#: ../ex_docmd.c:6485 msgid "E186: No previous directory" -msgstr "E186: Ei edellistä hakemistoa" +msgstr "E186: Ei edellistä hakemistoa" -#: ../ex_docmd.c:6530 msgid "E187: Unknown" msgstr "E187: Tuntematon" -#: ../ex_docmd.c:6610 msgid "E465: :winsize requires two number arguments" msgstr "E465: :winsize vaatii kaksi numeroargumenttia" -#: ../ex_docmd.c:6655 -msgid "E188: Obtaining window position not implemented for this platform" -msgstr "E188: Ikkunan sijainnin selvitys ei toimi tällä alustalla" - -#: ../ex_docmd.c:6662 -msgid "E466: :winpos requires two number arguments" -msgstr "E466: :winpos vaatii kaksi lukuargumenttia" - -#: ../ex_docmd.c:7241 -#, c-format -msgid "E739: Cannot create directory: %s" -msgstr "E739: hakemistoa ei voi luoda: %s" - -#: ../ex_docmd.c:7268 #, c-format msgid "E189: \"%s\" exists (add ! to override)" -msgstr "E189: %s on jo olemassa (lisää komentoon ! ohittaaksesi)" +msgstr "E189: %s on jo olemassa (lisää komentoon ! ohittaaksesi)" -#: ../ex_docmd.c:7273 #, c-format msgid "E190: Cannot open \"%s\" for writing" msgstr "E190: Tiedostoa %s ei voitu avata kirjoittamista varten" #. set mark -#: ../ex_docmd.c:7294 msgid "E191: Argument must be a letter or forward/backward quote" -msgstr "E191: Argumentin eteen- tai taaksepäin lainaukseen pitää olla kirjain" +msgstr "E191: Argumentin eteen- tai taaksepäin lainaukseen pitää olla kirjain" -#: ../ex_docmd.c:7333 msgid "E192: Recursive use of :normal too deep" -msgstr "E192: :normalin liian syvä rekursio" +msgstr "E192: :normalin liian syvä rekursio" -#: ../ex_docmd.c:7807 msgid "E194: No alternate file name to substitute for '#'" -msgstr "E194: Ei vaihtoehtoista tiedostonimeä #:lle" +msgstr "E194: Ei vaihtoehtoista tiedostonimeä #:lle" -#: ../ex_docmd.c:7841 msgid "E495: no autocommand file name to substitute for \"<afile>\"" msgstr "E495: ei autocommand-tiedostoa kohteelle <afile>" -#: ../ex_docmd.c:7850 msgid "E496: no autocommand buffer number to substitute for \"<abuf>\"" msgstr "E496: ei autocommand-puskurinumeroa kohteelle <abuf>" -#: ../ex_docmd.c:7861 msgid "E497: no autocommand match name to substitute for \"<amatch>\"" -msgstr "E497: ei autocommand-täsmäysnimeä kohteella <amatch>" +msgstr "E497: ei autocommand-täsmäysnimeä kohteella <amatch>" -#: ../ex_docmd.c:7870 msgid "E498: no :source file name to substitute for \"<sfile>\"" -msgstr "E498: ei :source-tiedostonimeä kohteelle <sfile>" +msgstr "E498: ei :source-tiedostonimeä kohteelle <sfile>" -#: ../ex_docmd.c:7876 -#, fuzzy msgid "E842: no line number to use for \"<slnum>\"" -msgstr "E498: ei :source-tiedostonimeä kohteelle <sfile>" +msgstr "E842: ei rivinumeroa kohteelle <slnum>" -#: ../ex_docmd.c:7903 #, fuzzy, c-format -msgid "E499: Empty file name for '%' or '#', only works with \":p:h\"" -msgstr "E499: Tyhjä tiedostonimi kohteissa % tai # toimii vain :p:h" +#~ msgid "E499: Empty file name for '%' or '#', only works with \":p:h\"" +#~ msgstr "E499: Tyhjä tiedostonimi kohteissa % tai # toimii vain :p:h" -#: ../ex_docmd.c:7905 msgid "E500: Evaluates to an empty string" -msgstr "E500: Loppuarvo on tyhjä merkkijono" - -#: ../ex_docmd.c:8838 -msgid "E195: Cannot open viminfo file for reading" -msgstr "E195: Viminfoa ei voi avata lukemista varten" +msgstr "E500: Loppuarvo on tyhjä merkkijono" -#: ../ex_eval.c:464 msgid "E608: Cannot :throw exceptions with 'Vim' prefix" -msgstr "E608: Vim-alkuisia poikkeuksia ei voi heittää :throw-komennolla" +msgstr "E608: Vim-alkuisia poikkeuksia ei voi heittää :throw-komennolla" #. always scroll up, don't overwrite -#: ../ex_eval.c:496 #, c-format msgid "Exception thrown: %s" msgstr "Poikkeus heitetty: %s" -#: ../ex_eval.c:545 +#. always scroll up, don't overwrite #, c-format msgid "Exception finished: %s" msgstr "Poikkeus lopeteltu: %s" -#: ../ex_eval.c:546 #, c-format msgid "Exception discarded: %s" msgstr "Poikkeus poistettu: %s" -#: ../ex_eval.c:588 ../ex_eval.c:634 -#, c-format -msgid "%s, line %<PRId64>" -msgstr "%s, rivi %<PRId64>" +#, fuzzy, c-format +#~ msgid "%s, line %<PRId64>" +#~ msgstr "%s, rivi %ld" #. always scroll up, don't overwrite -#: ../ex_eval.c:608 #, c-format msgid "Exception caught: %s" msgstr "Poikkeus otettu kiinni: %s" -#: ../ex_eval.c:676 #, c-format msgid "%s made pending" msgstr "%s odotutettu" -#: ../ex_eval.c:679 #, c-format msgid "%s resumed" msgstr "%s palautettu" -#: ../ex_eval.c:683 #, c-format msgid "%s discarded" msgstr "%s poistettu" -#: ../ex_eval.c:708 msgid "Exception" msgstr "Poikkeus" -#: ../ex_eval.c:713 msgid "Error and interrupt" msgstr "Virhe ja keskeytys" -#: ../ex_eval.c:715 msgid "Error" msgstr "Virhe" #. if (pending & CSTP_INTERRUPT) -#: ../ex_eval.c:717 msgid "Interrupt" msgstr "Keskeytys" -#: ../ex_eval.c:795 msgid "E579: :if nesting too deep" msgstr "E579: liian monta kerrosta :if-komennossa" -#: ../ex_eval.c:830 msgid "E580: :endif without :if" msgstr "E580: :endif ilman komentoa :if" -#: ../ex_eval.c:873 msgid "E581: :else without :if" msgstr "E581: :else ilman komentoa :if" -#: ../ex_eval.c:876 msgid "E582: :elseif without :if" msgstr "E582: :elseif ilman komentoa :if" -#: ../ex_eval.c:880 msgid "E583: multiple :else" msgstr "E583: :else monta kertaa" -#: ../ex_eval.c:883 msgid "E584: :elseif after :else" -msgstr "E584: :elseif komennon :else jälkeen" +msgstr "E584: :elseif komennon :else jälkeen" -#: ../ex_eval.c:941 msgid "E585: :while/:for nesting too deep" msgstr "E585: liian monta tasoa :while- tai :for-komennoissa" -#: ../ex_eval.c:1028 msgid "E586: :continue without :while or :for" msgstr "E586: :continue ilman komentoa :while tai :for" -#: ../ex_eval.c:1061 msgid "E587: :break without :while or :for" msgstr "E587: :break ilman komentoa :while tai :for" -#: ../ex_eval.c:1102 msgid "E732: Using :endfor with :while" msgstr "E732: :endfor ilman komentoa :while" -#: ../ex_eval.c:1104 msgid "E733: Using :endwhile with :for" msgstr "E733: :endwhile ilman komentoa :for" -#: ../ex_eval.c:1247 msgid "E601: :try nesting too deep" msgstr "E601: liian monta tasoa :try-komennossa" -#: ../ex_eval.c:1317 msgid "E603: :catch without :try" msgstr "E603: :catch ilman komentoa :try" #. Give up for a ":catch" after ":finally" and ignore it. #. * Just parse. -#: ../ex_eval.c:1332 msgid "E604: :catch after :finally" msgstr "E604: :catch ilman komentoa :finally" -#: ../ex_eval.c:1451 msgid "E606: :finally without :try" msgstr "E606: :finally ilman komentoa :try" #. Give up for a multiple ":finally" and ignore it. -#: ../ex_eval.c:1467 msgid "E607: multiple :finally" msgstr "E607: :finally monta kertaa" -#: ../ex_eval.c:1571 msgid "E602: :endtry without :try" msgstr "E602: :endtry ilman komentoa :try" -#: ../ex_eval.c:2026 msgid "E193: :endfunction not inside a function" msgstr "E193: :endfunction funktion ulkopuolella" -#: ../ex_getln.c:1643 msgid "E788: Not allowed to edit another buffer now" msgstr "E788: Puskuria ei voi muokata nyt" -#: ../ex_getln.c:1656 msgid "E811: Not allowed to change buffer information now" msgstr "E811: Puskuria ei voi vaihtaa nyt" -#: ../ex_getln.c:3178 msgid "tagname" -msgstr "täginimi" +msgstr "täginimi" -#: ../ex_getln.c:3181 msgid " kind file\n" msgstr " -tiedostotyyppi\n" -#: ../ex_getln.c:4799 msgid "'history' option is zero" msgstr "history-asetus on nolla" -#: ../ex_getln.c:5046 -#, c-format -msgid "" -"\n" -"# %s History (newest to oldest):\n" -msgstr "" -"\n" -"# %s Historia (uusimmasta alkaen):\n" - -#: ../ex_getln.c:5047 -msgid "Command Line" -msgstr "Komentorivi" - -#: ../ex_getln.c:5048 -msgid "Search String" -msgstr "Hakujono" - -#: ../ex_getln.c:5049 -msgid "Expression" -msgstr "Ilmaus" - -#: ../ex_getln.c:5050 -msgid "Input Line" -msgstr "Syöterivi" - -#: ../ex_getln.c:5117 msgid "E198: cmd_pchar beyond the command length" msgstr "E198: cmd_pchar komennon pituuden ulkopuolella" -#: ../ex_getln.c:5279 msgid "E199: Active window or buffer deleted" msgstr "E199: Aktiivinen ikkuna tai puskuri poistettu" -#: ../file_search.c:203 msgid "E854: path too long for completion" -msgstr "" +msgstr "E854: polku on liian pitkä täydennykseen" -#: ../file_search.c:446 #, c-format msgid "" "E343: Invalid path: '**[number]' must be at the end of the path or be " @@ -2011,376 +2098,296 @@ msgstr "" "E343: Virheellinen polku: '**[numero]' kuuluu polun loppuun tai ennen kohtaa " "%s." -#: ../file_search.c:1505 #, c-format msgid "E344: Can't find directory \"%s\" in cdpath" -msgstr "E344: Hakemistoa %s ei löydy cdpathista" +msgstr "E344: Hakemistoa %s ei löydy cdpathista" -#: ../file_search.c:1508 #, c-format msgid "E345: Can't find file \"%s\" in path" -msgstr "E345: Tiedostoa %s ei löydy polulta" +msgstr "E345: Tiedostoa %s ei löydy polulta" -#: ../file_search.c:1512 #, c-format msgid "E346: No more directory \"%s\" found in cdpath" -msgstr "E346: Hakemisto %s ei ole enää cdpathissa" +msgstr "E346: Hakemisto %s ei ole enää cdpathissa" -#: ../file_search.c:1515 #, c-format msgid "E347: No more file \"%s\" found in path" -msgstr "E347: Tiedosto %s ei ole enää polulla" +msgstr "E347: Tiedosto %s ei ole enää polulla" -#: ../fileio.c:137 msgid "E812: Autocommands changed buffer or buffer name" msgstr "E812: Autocommands muutti puskurin tai sen nimen" -#: ../fileio.c:368 msgid "Illegal file name" msgstr "Virheellinen tiedostonimi" -#: ../fileio.c:395 ../fileio.c:476 ../fileio.c:2543 ../fileio.c:2578 msgid "is a directory" msgstr "on hakemisto" -#: ../fileio.c:397 msgid "is not a file" msgstr "ei ole tiedosto" -#: ../fileio.c:508 ../fileio.c:3522 msgid "[New File]" msgstr "[Uusi tiedosto]" -#: ../fileio.c:511 msgid "[New DIRECTORY]" msgstr "[uusi HAKEMISTO]" -#: ../fileio.c:529 ../fileio.c:532 +#. libuv only returns -errno in Unix and in Windows open() does not +#. set EOVERFLOW msgid "[File too big]" msgstr "[Liian iso tiedosto]" -#: ../fileio.c:534 msgid "[Permission Denied]" msgstr "[Lupa kielletty]" -#: ../fileio.c:653 msgid "E200: *ReadPre autocommands made the file unreadable" msgstr "" -"E200: *ReadPre-autocommand-komennot tekivät tiedostosta lukukelvottoman" +"E200: *ReadPre-autocommand-komennot tekivät tiedostosta lukukelvottoman" -#: ../fileio.c:655 msgid "E201: *ReadPre autocommands must not change current buffer" -msgstr "E201: *ReadPre-autocommand-komennot eivät saa muuttaa puskuria" - -#: ../fileio.c:672 -msgid "Nvim: Reading from stdin...\n" -msgstr "Vim: Luetaan vakiosyötteestä...\n" +msgstr "E201: *ReadPre-autocommand-komennot eivät saa muuttaa puskuria" #. Re-opening the original file failed! -#: ../fileio.c:909 msgid "E202: Conversion made file unreadable!" msgstr "E202: Muunnos teki tiedostosta lukukelvottoman." #. fifo or socket -#: ../fileio.c:1782 msgid "[fifo/socket]" msgstr "[fifo t. soketti]" #. fifo -#: ../fileio.c:1788 msgid "[fifo]" msgstr "[fifo]" #. or socket -#: ../fileio.c:1794 msgid "[socket]" msgstr "[soketti]" #. or character special -#: ../fileio.c:1801 msgid "[character special]" msgstr "[merkki erikoinen]" -# Carriage Return elikkä rivinvaihtomerkin eräs muoto/osa (vrt. LF) -#: ../fileio.c:1815 +# Carriage Return elikkä rivinvaihtomerkin eräs muoto/osa (vrt. LF) msgid "[CR missing]" msgstr "[CR puuttuu]" -#: ../fileio.c:1819 msgid "[long lines split]" -msgstr "[pitkät rivit hajotettu]" +msgstr "[pitkät rivit hajotettu]" -#: ../fileio.c:1823 ../fileio.c:3512 msgid "[NOT converted]" msgstr "[EI muunnettu]" -#: ../fileio.c:1826 ../fileio.c:3515 msgid "[converted]" msgstr "[muunnettu]" -#: ../fileio.c:1831 -#, c-format -msgid "[CONVERSION ERROR in line %<PRId64>]" -msgstr "[MUUNNOSVIRHE rivillä %<PRId64>]" +#, fuzzy, c-format +#~ msgid "[CONVERSION ERROR in line %<PRId64>]" +#~ msgstr "[MUUNNOSVIRHE rivillä %ld]" -#: ../fileio.c:1835 -#, c-format -msgid "[ILLEGAL BYTE in line %<PRId64>]" -msgstr "[VIRHEELLINEN OKTETTI rivillä %<PRId64>]" +#, fuzzy, c-format +#~ msgid "[ILLEGAL BYTE in line %<PRId64>]" +#~ msgstr "[VIRHEELLINEN OKTETTI rivillä %ld]" -#: ../fileio.c:1838 msgid "[READ ERRORS]" -msgstr "[LUKUVIRHEITÄ]" +msgstr "[LUKUVIRHEITÄ]" -#: ../fileio.c:2104 msgid "Can't find temp file for conversion" -msgstr "Ei voi löytää väliaikaistiedstoa muuntamiseksi" +msgstr "Ei voi löytää väliaikaistiedstoa muuntamiseksi" -#: ../fileio.c:2110 msgid "Conversion with 'charconvert' failed" -msgstr "Muunnos charconvert epäonnistui" +msgstr "Muunnos charconvert epäonnistui" -#: ../fileio.c:2113 msgid "can't read output of 'charconvert'" msgstr "charconvertin tulostetta ei voida lukea" -#: ../fileio.c:2437 msgid "E676: No matching autocommands for acwrite buffer" msgstr "E676: Ei autocommand-komentoa acwrite-puskurille" -#: ../fileio.c:2466 msgid "E203: Autocommands deleted or unloaded buffer to be written" msgstr "" "E203: Autocommand-komennot poistivat tai vapauttivat puskurin, johon piti " "kirjoittaa" -#: ../fileio.c:2486 msgid "E204: Autocommand changed number of lines in unexpected way" -msgstr "E204: Autocommand-komento muutti rivien määrä odottamatta" +msgstr "E204: Autocommand-komento muutti rivien määrä odottamatta" -#: ../fileio.c:2548 ../fileio.c:2565 msgid "is not a file or writable device" msgstr "ei ole tiedosto tai kirjoitettava laite" -#: ../fileio.c:2601 msgid "is read-only (add ! to override)" -msgstr "on kirjoitussuojattu (lisää komentoon ! ohittaaksesi)" +msgstr "on kirjoitussuojattu (lisää komentoon ! ohittaaksesi)" -#: ../fileio.c:2886 msgid "E506: Can't write to backup file (add ! to override)" msgstr "" -"E506: Ei voi kirjoittaa varmuuskopiotiedostoon (lisää komentoon ! " +"E506: Ei voi kirjoittaa varmuuskopiotiedostoon (lisää komentoon ! " "ohittaaksesi)" -#: ../fileio.c:2898 -msgid "E507: Close error for backup file (add ! to override)" -msgstr "" -"E507: Varmuuskopiotiedoston sulkeminen ei onnistu (lisää komentoon ! " -"ohittaaksesi)" +#, fuzzy, c-format +#~ msgid "E507: Close error for backup file (add ! to override): %s" +#~ msgstr "" +#~ "E507: Varmuuskopiotiedoston sulkeminen ei onnistu (lisää komentoon ! " +#~ "ohittaaksesi)" -#: ../fileio.c:2901 msgid "E508: Can't read file for backup (add ! to override)" msgstr "" -"E508: Varmuuskopiotiedostoa ei voi lukea (lisää komentoon ! ohittaaksesi)" +"E508: Varmuuskopiotiedostoa ei voi lukea (lisää komentoon ! ohittaaksesi)" -#: ../fileio.c:2923 msgid "E509: Cannot create backup file (add ! to override)" msgstr "" -"E509: Ei voi luoda varmuuskopiotiedostoa (lisää komentoon ! ohittaaksesi)" +"E509: Ei voi luoda varmuuskopiotiedostoa (lisää komentoon ! ohittaaksesi)" -#: ../fileio.c:3008 msgid "E510: Can't make backup file (add ! to override)" msgstr "" -"E510: Ei voi tehdä varmuuskopiotiedostoa (lisää komentoon ! ohittaaksesi)" +"E510: Ei voi tehdä varmuuskopiotiedostoa (lisää komentoon ! ohittaaksesi)" #. Can't write without a tempfile! -#: ../fileio.c:3121 msgid "E214: Can't find temp file for writing" -msgstr "E214: Ei voi löytää väliaikaistiedostoa kirjoitettavaksi" +msgstr "E214: Ei voi löytää väliaikaistiedostoa kirjoitettavaksi" -#: ../fileio.c:3134 msgid "E213: Cannot convert (add ! to write without conversion)" msgstr "" -"E213: Muunnos ei onnistu (lisää komentoon ! kirjoittaaksesi muuntamatta)" +"E213: Muunnos ei onnistu (lisää komentoon ! kirjoittaaksesi muuntamatta)" -#: ../fileio.c:3169 msgid "E166: Can't open linked file for writing" msgstr "E166: Linkitetyn tiedoston avaus kirjoittamista varten ei onnistu" -#: ../fileio.c:3173 -msgid "E212: Can't open file for writing" -msgstr "E212: Tiedoston avaus kirjoittamista varten ei onnistu" +#, fuzzy, c-format +#~ msgid "E212: Can't open file for writing: %s" +#~ msgstr "E212: Tiedoston avaus kirjoittamista varten ei onnistu" -#: ../fileio.c:3363 -msgid "E667: Fsync failed" -msgstr "E667: Fsync ei onnistunut" +#, fuzzy, c-format +#~ msgid "E667: Fsync failed: %s" +#~ msgstr "E667: Fsync ei onnistunut" -#: ../fileio.c:3398 -msgid "E512: Close failed" -msgstr "E512: Sulkeminen ei onnistunut" +#, fuzzy, c-format +#~ msgid "E512: Close failed: %s" +#~ msgstr "E512: Sulkeminen ei onnistunut" -#: ../fileio.c:3436 msgid "E513: write error, conversion failed (make 'fenc' empty to override)" -msgstr "E513: kirjoitusvirhe, muunnos epäonnistui (tyhjää fenc ohittaaksesi)" +msgstr "E513: kirjoitusvirhe, muunnos epäonnistui (tyhjää fenc ohittaaksesi)" -#: ../fileio.c:3441 -#, c-format -msgid "" -"E513: write error, conversion failed in line %<PRId64> (make 'fenc' empty to " -"override)" -msgstr "" -"E513: kirjoitusvirhe, muunnos epäonnistui rivillä %<PRId64>(tyhjää fenc " -"ohittaaksesi)" +#, fuzzy +#~ msgid "E513: write error, conversion failed in line %" +#~ msgstr "" +#~ "E513: kirjoitusvirhe, muunnos epäonnistui rivillä %ld(tyhjää fenc " +#~ "ohittaaksesi)" -#: ../fileio.c:3448 msgid "E514: write error (file system full?)" -msgstr "E514: kirjoitusvirhe (tiedostojärjestelmä täysi)" +msgstr "E514: kirjoitusvirhe (tiedostojärjestelmä täysi)" -#: ../fileio.c:3506 msgid " CONVERSION ERROR" msgstr " MUUNNOSVIRHE" -#: ../fileio.c:3509 -#, c-format -msgid " in line %<PRId64>;" -msgstr " rivillä %<PRId64>" +#, fuzzy, c-format +#~ msgid " in line %<PRId64>;" +#~ msgstr " rivillä %ld" -#: ../fileio.c:3519 msgid "[Device]" msgstr "[Laite]" -#: ../fileio.c:3522 msgid "[New]" msgstr "[Uusi]" -#: ../fileio.c:3535 msgid " [a]" msgstr " [a]" -#: ../fileio.c:3535 msgid " appended" -msgstr " lisätty" +msgstr " lisätty" -#: ../fileio.c:3537 msgid " [w]" msgstr " [w]" -#: ../fileio.c:3537 msgid " written" msgstr " kirjoitettu" -#: ../fileio.c:3579 msgid "E205: Patchmode: can't save original file" -msgstr "E205: Patch-tilassa ei voi tallentaa alkuperäistiedostoa" +msgstr "E205: Patch-tilassa ei voi tallentaa alkuperäistiedostoa" -#: ../fileio.c:3602 msgid "E206: patchmode: can't touch empty original file" -msgstr "E206: patch-tilassa ei voi muuttaa tyhjää alkuperäistiedostoa" +msgstr "E206: patch-tilassa ei voi muuttaa tyhjää alkuperäistiedostoa" -#: ../fileio.c:3616 msgid "E207: Can't delete backup file" msgstr "E207: Ei voi poistaa varmuuskopiota" -#: ../fileio.c:3672 +#. Set highlight for error messages. msgid "" "\n" "WARNING: Original file may be lost or damaged\n" msgstr "" "\n" -"VAROITUS: Alkuperäistiedosto voi hävitä tai vahingoittua\n" +"VAROITUS: Alkuperäistiedosto voi hävitä tai vahingoittua\n" -#: ../fileio.c:3675 msgid "don't quit the editor until the file is successfully written!" -msgstr "älä lopeta editoria kesken tallentamisen." +msgstr "älä lopeta editoria kesken tallentamisen." -#: ../fileio.c:3795 -msgid "[dos]" -msgstr "[dos]" - -#: ../fileio.c:3795 msgid "[dos format]" msgstr "[dos-muoto]" -#: ../fileio.c:3801 -msgid "[mac]" -msgstr "[mac]" +msgid "[dos]" +msgstr "[dos]" -#: ../fileio.c:3801 msgid "[mac format]" msgstr "[mac-muoto]" -#: ../fileio.c:3807 -msgid "[unix]" -msgstr "[unix]" +msgid "[mac]" +msgstr "[mac]" -#: ../fileio.c:3807 msgid "[unix format]" msgstr "[unix-muoto]" -#: ../fileio.c:3831 +msgid "[unix]" +msgstr "[unix]" + msgid "1 line, " msgstr "1 rivi, " -#: ../fileio.c:3833 -#, c-format -msgid "%<PRId64> lines, " -msgstr "%<PRId64> riviä, " +#, fuzzy, c-format +#~ msgid "%<PRId64> lines, " +#~ msgstr "%ld riviä, " -#: ../fileio.c:3836 msgid "1 character" msgstr "1 merkki" -#: ../fileio.c:3838 -#, c-format -msgid "%<PRId64> characters" -msgstr "%<PRId64> merkkiä" +#, fuzzy, c-format +#~ msgid "%<PRId64> characters" +#~ msgstr "%lld merkkiä" + +msgid "[Incomplete last line]" +msgstr "[Vajaa viimeinen rivi]" # ei rivinvaihtoja -#: ../fileio.c:3849 msgid "[noeol]" msgstr "[eiriviv.]" -#: ../fileio.c:3849 -msgid "[Incomplete last line]" -msgstr "[Vajaa viimeinen rivi]" - -# Jos aukiolevaa tiedostoa sörkkii toisella ohjelmalla -#. don't overwrite messages here -#. must give this prompt -#. don't use emsg() here, don't want to flush the buffers -#: ../fileio.c:3865 +# Jos aukiolevaa tiedostoa sörkkii toisella ohjelmalla +#. Don't overwrite messages here. +#. Must give this prompt. +#. Don't use emsg() here, don't want to flush the buffers. msgid "WARNING: The file has been changed since reading it!!!" -msgstr "VAROITUS: tiedosto on muuttunut viime lukukerran jälkeen!" +msgstr "VAROITUS: tiedosto on muuttunut viime lukukerran jälkeen!" -#: ../fileio.c:3867 msgid "Do you really want to write to it" msgstr "Kirjoitetaanko" -#: ../fileio.c:4648 #, c-format msgid "E208: Error writing to \"%s\"" msgstr "E208: Virhe kirjoitettaessa tiedostoon %s" -#: ../fileio.c:4655 #, c-format msgid "E209: Error closing \"%s\"" msgstr "E209: Virhe suljettaessa tiedostoa %s" -#: ../fileio.c:4657 #, c-format msgid "E210: Error reading \"%s\"" msgstr "E210: Virhe luettaessa tiedostoa %s" -#: ../fileio.c:4883 msgid "E246: FileChangedShell autocommand deleted buffer" msgstr "E246: FileChangedShell-autocommand poisti puskurin" -#: ../fileio.c:4894 #, c-format msgid "E211: File \"%s\" no longer available" -msgstr "E211: Tiedostoa %s ei ole enää" +msgstr "E211: Tiedostoa %s ei ole enää" -#: ../fileio.c:4906 #, c-format msgid "" "W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as " @@ -2389,41 +2396,33 @@ msgstr "" "W12: Varoitus: Tiedostoa %s on muutettu ja Vimin puskurissa on muutoksia " "tiedostoon" -#: ../fileio.c:4907 msgid "See \":help W12\" for more info." -msgstr ":help W12 kertoo lisätietoja." +msgstr ":help W12 kertoo lisätietoja." -#: ../fileio.c:4910 #, c-format msgid "W11: Warning: File \"%s\" has changed since editing started" -msgstr "W11: Varoitus: Tiedostoa %s on muutettu muokkauksen aloituksen jälkeen" +msgstr "W11: Varoitus: Tiedostoa %s on muutettu muokkauksen aloituksen jälkeen" -#: ../fileio.c:4911 msgid "See \":help W11\" for more info." -msgstr ":help W11 kertoo lisätietoja." +msgstr ":help W11 kertoo lisätietoja." -#: ../fileio.c:4914 #, c-format msgid "W16: Warning: Mode of file \"%s\" has changed since editing started" msgstr "" "W16: Varoitus: Tiedoston %s oikeuksia on muutettu muokkauksen aloituksen " -"jälkeen" +"jälkeen" -#: ../fileio.c:4915 msgid "See \":help W16\" for more info." -msgstr ":help W16 kertoo lisätietoja." +msgstr ":help W16 kertoo lisätietoja." -#: ../fileio.c:4927 #, c-format msgid "W13: Warning: File \"%s\" has been created after editing started" -msgstr "W13: Varoitus: Tiedosto %s on luotu muokkauksen aloituksen jälkeen" +msgstr "W13: Varoitus: Tiedosto %s on luotu muokkauksen aloituksen jälkeen" -#: ../fileio.c:4947 msgid "Warning" msgstr "Varoitus" -# yllä olevien varoitusten ratkaisut -#: ../fileio.c:4948 +# yllä olevien varoitusten ratkaisut msgid "" "&OK\n" "&Load File" @@ -2431,48 +2430,46 @@ msgstr "" "&OK\n" "&Avaa tiedosto uudelleen" -#: ../fileio.c:5065 #, c-format msgid "E462: Could not prepare for reloading \"%s\"" msgstr "E462: Ei voitu valmistella uudelleen avausta %s" -#: ../fileio.c:5078 #, c-format msgid "E321: Could not reload \"%s\"" msgstr "E321: Ei voitu uudelleenavata %s" -#: ../fileio.c:5601 msgid "--Deleted--" msgstr "--Poistettu--" -#: ../fileio.c:5732 #, c-format msgid "auto-removing autocommand: %s <buffer=%d>" msgstr "poistetaan autocommand automaattisesti: %s <puskuri=%d>" #. the group doesn't exist -#: ../fileio.c:5772 #, c-format msgid "E367: No such group: \"%s\"" -msgstr "E367: Ryhmää ei ole: %s" +msgstr "E367: Ryhmää ei ole: %s" + +#, fuzzy +#~ msgid "E936: Cannot delete the current group" +#~ msgstr "E351: Taitosta ei voi poistaa tällä foldmethodilla" + +msgid "W19: Deleting augroup that is still in use" +msgstr "W19: käytössä oleva augroup poistetaan" -#: ../fileio.c:5897 #, c-format msgid "E215: Illegal character after *: %s" -msgstr "E215: Virheellinen merkki *:n jälkeen: %s" +msgstr "E215: Virheellinen merkki *:n jälkeen: %s" -#: ../fileio.c:5905 #, c-format msgid "E216: No such event: %s" -msgstr "E216: Eventtiä ei ole: %s" +msgstr "E216: Eventtiä ei ole: %s" -#: ../fileio.c:5907 #, c-format msgid "E216: No such group or event: %s" -msgstr "E216: Ryhmää tai eventtiä ei ole: %s" +msgstr "E216: Ryhmää tai eventtiä ei ole: %s" #. Highlight title -#: ../fileio.c:6090 msgid "" "\n" "--- Auto-Commands ---" @@ -2480,762 +2477,611 @@ msgstr "" "\n" "--- Autocommandit ---" -#: ../fileio.c:6293 #, c-format msgid "E680: <buffer=%d>: invalid buffer number " msgstr "E680: <puskuri=%d>: virheellinen puskurinumero" -#: ../fileio.c:6370 msgid "E217: Can't execute autocommands for ALL events" msgstr "E217: Ei voi suorittaa autocommandsia kaikille eventeille" -#: ../fileio.c:6393 msgid "No matching autocommands" -msgstr "Ei täsmääviä autocommandsia" +msgstr "Ei täsmääviä autocommandsia" -#: ../fileio.c:6831 msgid "E218: autocommand nesting too deep" msgstr "E218: liian monta tasoa autocommandissa" -#: ../fileio.c:7143 #, c-format msgid "%s Auto commands for \"%s\"" msgstr "%s Autocommands kohteelle %s" -#: ../fileio.c:7149 #, c-format msgid "Executing %s" msgstr "Suoritetaan %s" -#: ../fileio.c:7211 #, c-format msgid "autocommand %s" msgstr "autocommand %s" -#: ../fileio.c:7795 msgid "E219: Missing {." msgstr "E219: { puuttuu." -#: ../fileio.c:7797 msgid "E220: Missing }." msgstr "E220: } puuttuu." -#: ../fold.c:93 msgid "E490: No fold found" msgstr "E490: taitos puuttuu" -#: ../fold.c:544 msgid "E350: Cannot create fold with current 'foldmethod'" -msgstr "E350: Taitoksia ei voi tehdä tällä foldmethodilla" +msgstr "E350: Taitoksia ei voi tehdä tällä foldmethodilla" -#: ../fold.c:546 msgid "E351: Cannot delete fold with current 'foldmethod'" -msgstr "E351: Taitosta ei voi poistaa tällä foldmethodilla" +msgstr "E351: Taitosta ei voi poistaa tällä foldmethodilla" -#: ../fold.c:1784 -#, c-format -msgid "+--%3ld lines folded " -msgstr "+--%3ld riviä taitettu pois " +#, fuzzy, c-format +#~ msgid "+--%3ld lines folded " +#~ msgstr "+--%3ld rivi taitettu pois " #. buffer has already been read -#: ../getchar.c:273 msgid "E222: Add to read buffer" -msgstr "E222: Lisää lukupuskuriin" +msgstr "E222: Lisää lukupuskuriin" -#: ../getchar.c:2040 msgid "E223: recursive mapping" msgstr "E223: rekursiivinen kuvaus" -#: ../getchar.c:2849 #, c-format msgid "E224: global abbreviation already exists for %s" -msgstr "E224: globaali lyhenne merkinnälle %s on jo olemassa" +msgstr "E224: globaali lyhenne merkinnälle %s on jo olemassa" -#: ../getchar.c:2852 #, c-format msgid "E225: global mapping already exists for %s" -msgstr "E225: globaali kuvaus merkinnälle %s on jo olemassa" +msgstr "E225: globaali kuvaus merkinnälle %s on jo olemassa" -#: ../getchar.c:2952 #, c-format msgid "E226: abbreviation already exists for %s" msgstr "E226: lyhenne on jo olemassa %s" -#: ../getchar.c:2955 #, c-format msgid "E227: mapping already exists for %s" msgstr "E227: kuvaus on jo olemassa %s" -#: ../getchar.c:3008 msgid "No abbreviation found" -msgstr "Lyhennettä ei löydy" +msgstr "Lyhennettä ei löydy" -#: ../getchar.c:3010 msgid "No mapping found" -msgstr "Kuvausta ei löydy" +msgstr "Kuvausta ei löydy" -#: ../getchar.c:3974 msgid "E228: makemap: Illegal mode" msgstr "E228: makemap: Virheellinen tila" #. key value of 'cedit' option #. type of cmdline window or 0 #. result of cmdline window or 0 -#: ../globals.h:924 msgid "--No lines in buffer--" -msgstr "--Ei rivejä puskurissa--" +msgstr "--Ei rivejä puskurissa--" #. #. * The error messages that can be shared are included here. #. * Excluded are errors that are only used once and debugging messages. #. -#: ../globals.h:996 msgid "E470: Command aborted" msgstr "E470: Komento peruttu" -#: ../globals.h:997 +#, fuzzy +#~ msgid "E905: Cannot set this option after startup" +#~ msgstr "E529: Termiä ei voi asettaa tyhjäksi merkkijonoksi" + +#, fuzzy +#~ msgid "E903: Could not spawn API job" +#~ msgstr "E623: Cscope-prosessin luonti epäonnistui" + msgid "E471: Argument required" msgstr "E471: Argumentti puuttuu" -#: ../globals.h:998 msgid "E10: \\ should be followed by /, ? or &" -msgstr "E10: \\:n jälkeen pitää tulla /, ? tai &" +msgstr "E10: \\:n jälkeen pitää tulla /, ? tai &" -#: ../globals.h:1000 msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" msgstr "E11: Virheellinen komentorivi-ikkuna, <CR> suorittaa, Ctrl C lopettaa" -#: ../globals.h:1002 msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" msgstr "" -"E12: Komentoa ei tueta exrc:ssä tai vimrc:ssä tässä hakemistossa tai " -"tägihaussa" +"E12: Komentoa ei tueta exrc:ssä tai vimrc:ssä tässä hakemistossa tai " +"tägihaussa" -#: ../globals.h:1003 msgid "E171: Missing :endif" msgstr "E171: :endif puuttuu" -#: ../globals.h:1004 msgid "E600: Missing :endtry" msgstr "E600: :endtry puuttuu" -#: ../globals.h:1005 msgid "E170: Missing :endwhile" msgstr "E170: :endwhile puuttuu" -#: ../globals.h:1006 msgid "E170: Missing :endfor" msgstr "E170: :endfor puuttuu" -#: ../globals.h:1007 msgid "E588: :endwhile without :while" msgstr "E588: :endwhile ilman komentoa :while" -#: ../globals.h:1008 msgid "E588: :endfor without :for" msgstr "E588: :endfor ilman komentoa :for" -#: ../globals.h:1009 msgid "E13: File exists (add ! to override)" -msgstr "E13: Tiedosto on jo olemassa (lisää ! ohittaaksesi)" +msgstr "E13: Tiedosto on jo olemassa (lisää ! ohittaaksesi)" -#: ../globals.h:1010 msgid "E472: Command failed" -msgstr "E472: Komento epäonnistui" +msgstr "E472: Komento epäonnistui" -#: ../globals.h:1011 msgid "E473: Internal error" -msgstr "E473: Sisäinen virhe" +msgstr "E473: Sisäinen virhe" -#: ../globals.h:1012 msgid "Interrupted" msgstr "Keskeytetty" -#: ../globals.h:1013 msgid "E14: Invalid address" msgstr "E14: Virheellinen osoite" -#: ../globals.h:1014 msgid "E474: Invalid argument" msgstr "E474: Virheellinen argumentti" -#: ../globals.h:1015 #, c-format msgid "E475: Invalid argument: %s" msgstr "E475: Virheellinen argumentti: %s" -#: ../globals.h:1016 #, c-format msgid "E15: Invalid expression: %s" msgstr "E15: Virheellinen ilmaus: %s" -#: ../globals.h:1017 msgid "E16: Invalid range" msgstr "E16: Virheellinen arvoalue" -#: ../globals.h:1018 msgid "E476: Invalid command" msgstr "E476: Virheellinen komento" -#: ../globals.h:1019 #, c-format msgid "E17: \"%s\" is a directory" msgstr "E17: %s on hakemisto" -#: ../globals.h:1020 #, fuzzy -msgid "E900: Invalid job id" -msgstr "E49: Virheellinen vierityskoko" +#~ msgid "E900: Invalid job id" +#~ msgstr "E916: ei ole job" -#: ../globals.h:1021 -msgid "E901: Job table is full" -msgstr "" +#~ msgid "E901: Job table is full" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "E903: Process failed to start: %s: \"%s\"" +#~ msgstr "E852: Lapsiprosesi ei voinut käynnistää käyttöliittymää" + +#, fuzzy +#~ msgid "E904: Job is not connected to a pty" +#~ msgstr "E902: Ei voi yhdistää porttiin" -#: ../globals.h:1024 #, c-format msgid "E364: Library call failed for \"%s()\"" -msgstr "E364: Kirjastukutsu %s() epäonnistui" +msgstr "E364: Kirjastukutsu %s() epäonnistui" + +#, fuzzy, c-format +#~ msgid "E739: Cannot create directory %s: %s" +#~ msgstr "E739: hakemistoa ei voi luoda: %s" -#: ../globals.h:1026 msgid "E19: Mark has invalid line number" -msgstr "E19: Merkillä on virheellinen rivinumero" +msgstr "E19: Merkillä on virheellinen rivinumero" -#: ../globals.h:1027 msgid "E20: Mark not set" -msgstr "E20: Merkkiä ei asetettu" +msgstr "E20: Merkkiä ei asetettu" -#: ../globals.h:1029 msgid "E21: Cannot make changes, 'modifiable' is off" -msgstr "E21: Ei voi tehdä muutoksia, modifiable on pois päältä" +msgstr "E21: Ei voi tehdä muutoksia, modifiable on pois päältä" -#: ../globals.h:1030 msgid "E22: Scripts nested too deep" -msgstr "E22: Liian monta tasoa skripteissä" +msgstr "E22: Liian monta tasoa skripteissä" -#: ../globals.h:1031 msgid "E23: No alternate file" msgstr "E23: Eo vaihtoehtoista tiedostoa" -#: ../globals.h:1032 msgid "E24: No such abbreviation" -msgstr "E24: Lyhennettä ei ole" +msgstr "E24: Lyhennettä ei ole" -#: ../globals.h:1033 msgid "E477: No ! allowed" msgstr "E477: ! ei sallittu" -#: ../globals.h:1035 -msgid "E25: Nvim does not have a built-in GUI" -msgstr "E25: GUIta ei voi käyttää, koska sitä ei käännetty mukaan" +#~ msgid "E25: Nvim does not have a built-in GUI" +#~ msgstr "" -#: ../globals.h:1036 #, c-format msgid "E28: No such highlight group name: %s" -msgstr "E28: Korostusryhmää ei ole nimellä: %s" +msgstr "E28: Korostusryhmää ei ole nimellä: %s" -#: ../globals.h:1037 msgid "E29: No inserted text yet" -msgstr "E29: Tekstiä ei ole syötetty vielä" +msgstr "E29: Tekstiä ei ole syötetty vielä" -#: ../globals.h:1038 msgid "E30: No previous command line" -msgstr "E30: Ei edellistä komentoriviä" +msgstr "E30: Ei edellistä komentoriviä" -#: ../globals.h:1039 msgid "E31: No such mapping" msgstr "E31: Kuvausta ei ole" -#: ../globals.h:1040 msgid "E479: No match" -msgstr "E479: Ei täsmää" +msgstr "E479: Ei täsmää" -#: ../globals.h:1041 #, c-format msgid "E480: No match: %s" -msgstr "E480: Ei tsämää: %s" +msgstr "E480: Ei tsämää: %s" -#: ../globals.h:1042 msgid "E32: No file name" -msgstr "E32: Ei tiedostonimeä" +msgstr "E32: Ei tiedostonimeä" -#: ../globals.h:1044 msgid "E33: No previous substitute regular expression" -msgstr "E33: Ei edellistä korvausta säännölliselle ilmaukselle" +msgstr "E33: Ei edellistä korvausta säännölliselle ilmaukselle" -#: ../globals.h:1045 msgid "E34: No previous command" -msgstr "E34: Ei edellistä komentoa" +msgstr "E34: Ei edellistä komentoa" -#: ../globals.h:1046 msgid "E35: No previous regular expression" -msgstr "E35: Ei edellistä säännöllistä ilmausta" +msgstr "E35: Ei edellistä säännöllistä ilmausta" -#: ../globals.h:1047 msgid "E481: No range allowed" msgstr "E481: Arvoalue ei sallittu" -#: ../globals.h:1048 msgid "E36: Not enough room" -msgstr "E36: Tila ei riitä" +msgstr "E36: Tila ei riitä" -#: ../globals.h:1049 -#, c-format -msgid "E482: Can't create file %s" -msgstr "E482: Tiedostoa %s ei voi luoda" - -#: ../globals.h:1050 msgid "E483: Can't get temp file name" -msgstr "E483: väliaikaistiedoston nimeä ei saada selville" +msgstr "E483: väliaikaistiedoston nimeä ei saada selville" -#: ../globals.h:1051 #, c-format msgid "E484: Can't open file %s" msgstr "E484: Ei voi avata tiedostoa %s" -#: ../globals.h:1052 #, c-format msgid "E485: Can't read file %s" msgstr "E485: Ei voi lukea tiedostoa %s" -#: ../globals.h:1054 msgid "E37: No write since last change (add ! to override)" msgstr "" -"E37: Viimeisen muutoksen jälkeen ei ole kirjoitettu (lisää ! ohittaaksesi)" +"E37: Viimeisen muutoksen jälkeen ei ole kirjoitettu (lisää ! ohittaaksesi)" -#: ../globals.h:1055 -#, fuzzy msgid "E37: No write since last change" -msgstr "[Viimeisintä muutosta ei ole kirjoitettu]\n" +msgstr "E37: Viimeisimmän muutoksen jälkeen ei ole kirjoitettu mitään" -#: ../globals.h:1056 msgid "E38: Null argument" msgstr "E38: Null-argumentti" -#: ../globals.h:1057 msgid "E39: Number expected" -msgstr "E39: Pitää olla numero" +msgstr "E39: Pitää olla numero" -#: ../globals.h:1058 #, c-format msgid "E40: Can't open errorfile %s" msgstr "E40: virhetiedostoa %s ei voi avata" -#: ../globals.h:1059 msgid "E41: Out of memory!" msgstr "E41: Muisti loppui" -#: ../globals.h:1060 msgid "Pattern not found" -msgstr "Kuviota ei löydy" +msgstr "Kuviota ei löydy" -#: ../globals.h:1061 #, c-format msgid "E486: Pattern not found: %s" -msgstr "E486: Kuviota ei löydy: %s" +msgstr "E486: Kuviota ei löydy: %s" -#: ../globals.h:1062 msgid "E487: Argument must be positive" -msgstr "E487: Argumentin pitää olla positiivinen" +msgstr "E487: Argumentin pitää olla positiivinen" -#: ../globals.h:1064 msgid "E459: Cannot go back to previous directory" -msgstr "E459: Ei voi siirtyä edelliseen hakemistoon" +msgstr "E459: Ei voi siirtyä edelliseen hakemistoon" # ;-) -#: ../globals.h:1066 msgid "E42: No Errors" -msgstr "E42: Ei virheitä" +msgstr "E42: Ei virheitä" -#: ../globals.h:1067 msgid "E776: No location list" msgstr "E776: Ei sijaintilistaa" -#: ../globals.h:1068 msgid "E43: Damaged match string" -msgstr "E43: Viallinen täsmäysmerkkijono" +msgstr "E43: Viallinen täsmäysmerkkijono" -#: ../globals.h:1069 msgid "E44: Corrupted regexp program" msgstr "E44: Viallinen regexp-ohjelma" -#: ../globals.h:1071 msgid "E45: 'readonly' option is set (add ! to override)" -msgstr "E45: readonly asetettu (lisää ! ohittaaksesi)" - -#: ../globals.h:1073 -#, c-format -msgid "E46: Cannot change read-only variable \"%s\"" -msgstr "E46: Kirjoitussuojattua muuttujaa %s ei voi muuttaa" - -#: ../globals.h:1075 -#, c-format -msgid "E794: Cannot set variable in the sandbox: \"%s\"" -msgstr "E794: Muuttujaa ei voi asettaa hiekkalaatikossa: %s" +msgstr "E45: readonly asetettu (lisää ! ohittaaksesi)" -#: ../globals.h:1076 msgid "E47: Error while reading errorfile" msgstr "E47: Virhe virhetiedostoa luettaessa" -#: ../globals.h:1078 msgid "E48: Not allowed in sandbox" msgstr "E48: Ei sallittu hiekkalaatikossa" -#: ../globals.h:1080 msgid "E523: Not allowed here" -msgstr "E523: Ei sallittu täällä" +msgstr "E523: Ei sallittu täällä" -#: ../globals.h:1082 msgid "E359: Screen mode setting not supported" -msgstr "E359: Näyttötila-asetus ei tuettu" +msgstr "E359: Näyttötila-asetus ei tuettu" -#: ../globals.h:1083 msgid "E49: Invalid scroll size" msgstr "E49: Virheellinen vierityskoko" -#: ../globals.h:1084 msgid "E91: 'shell' option is empty" -msgstr "E91: shell-asetus on tyhjä" +msgstr "E91: shell-asetus on tyhjä" -#: ../globals.h:1085 msgid "E255: Couldn't read in sign data!" msgstr "E255: Merkkidatan luku ei onnistu" -#: ../globals.h:1086 msgid "E72: Close error on swap file" msgstr "E72: Swap-tiedoston sulkemisvirhe" -#: ../globals.h:1087 msgid "E73: tag stack empty" -msgstr "E73: tägipino tyhjä" +msgstr "E73: tägipino tyhjä" -#: ../globals.h:1088 msgid "E74: Command too complex" msgstr "E74: Liian monimutkainen komento" -#: ../globals.h:1089 msgid "E75: Name too long" -msgstr "E75: Liian pitkä nimi" +msgstr "E75: Liian pitkä nimi" -#: ../globals.h:1090 msgid "E76: Too many [" msgstr "E76: Liian monta [:a" -#: ../globals.h:1091 msgid "E77: Too many file names" -msgstr "E77: Liikaa tiedostonimiä" +msgstr "E77: Liikaa tiedostonimiä" -#: ../globals.h:1092 msgid "E488: Trailing characters" -msgstr "E488: Ylimääräisiä merkkejä perässä" +msgstr "E488: Ylimääräisiä merkkejä perässä" -#: ../globals.h:1093 msgid "E78: Unknown mark" msgstr "E78: Tuntematon merkki" -#: ../globals.h:1094 msgid "E79: Cannot expand wildcards" msgstr "E79: Jokerimerkkien avaus ei onnistu" -#: ../globals.h:1096 msgid "E591: 'winheight' cannot be smaller than 'winminheight'" msgstr "E591: winheight ei voi olla pienempi kuin winminheight" -#: ../globals.h:1098 msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" msgstr "E592: winwidth ei voi olla pienempi kuin winminwidth" -#: ../globals.h:1099 msgid "E80: Error while writing" msgstr "E80: Kirjoitusvirhe" -#: ../globals.h:1100 msgid "Zero count" msgstr "Nollalaskuri" -#: ../globals.h:1101 msgid "E81: Using <SID> not in a script context" msgstr "E81: <SID> skriptin ulkopuolella" -#: ../globals.h:1102 #, c-format msgid "E685: Internal error: %s" -msgstr "E685: Sisäinen virhe: %s" +msgstr "E685: Sisäinen virhe: %s" -#: ../globals.h:1104 msgid "E363: pattern uses more memory than 'maxmempattern'" -msgstr "E363: kuvio käyttää enemmän muistia kuin maxmempattern on" +msgstr "E363: kuvio käyttää enemmän muistia kuin maxmempattern on" -#: ../globals.h:1105 msgid "E749: empty buffer" -msgstr "E749: tyhjä puskuri" +msgstr "E749: tyhjä puskuri" + +#, fuzzy, c-format +#~ msgid "E86: Buffer %<PRId64> does not exist" +#~ msgstr "E86: Puskuria %ld ei ole" -#: ../globals.h:1108 msgid "E682: Invalid search pattern or delimiter" msgstr "E682: Virheellinen hakulauseke tai erotin" -#: ../globals.h:1109 msgid "E139: File is loaded in another buffer" msgstr "E139: Tiedosto on ladattu toiseen puskuriin" -#: ../globals.h:1110 #, c-format msgid "E764: Option '%s' is not set" msgstr "E764: Asetus %s on asettamatta" -#: ../globals.h:1111 -#, fuzzy msgid "E850: Invalid register name" -msgstr "E354: Virheellinen rekisterin nimi: %s" +msgstr "E850: Virheellinen rekisterin nimi" + +#, c-format +msgid "E919: Directory not found in '%s': \"%s\"" +msgstr "E919: Hakemisto puuttuu kohteesta %s: %s" + +msgid "E519: Option not supported" +msgstr "E519: Asetusta ei tueta" + +#, fuzzy +#~ msgid "E856: Filename too long" +#~ msgstr "E75: Liian pitkä nimi" + +msgid "E806: using Float as a String" +msgstr "E806: Float ei käy merkkijonosta" -#: ../globals.h:1114 msgid "search hit TOP, continuing at BOTTOM" -msgstr "haku pääsi ALKUUN, jatketaan LOPUSTA" +msgstr "haku pääsi ALKUUN, jatketaan LOPUSTA" -#: ../globals.h:1115 msgid "search hit BOTTOM, continuing at TOP" -msgstr "haku pääsi LOPPUUN, jatketaan ALUSTA" +msgstr "haku pääsi LOPPUUN, jatketaan ALUSTA" -#: ../hardcopy.c:240 msgid "E550: Missing colon" msgstr "E550: kaksoispiste puuttuu" -#: ../hardcopy.c:252 msgid "E551: Illegal component" msgstr "E551: Virheellinen komponentti" -#: ../hardcopy.c:259 msgid "E552: digit expected" -msgstr "E552: pitäisi olla numero" +msgstr "E552: pitäisi olla numero" -#: ../hardcopy.c:473 #, c-format msgid "Page %d" msgstr "Sivu %d" -#: ../hardcopy.c:597 msgid "No text to be printed" -msgstr "Ei tekstiä tulostettavaksi" +msgstr "Ei tekstiä tulostettavaksi" -#: ../hardcopy.c:668 -#, c-format -msgid "Printing page %d (%d%%)" -msgstr "Tulostetaan sivua %d (%d %%)" +#, fuzzy, c-format +#~ msgid "Printing page %d (%zu%%)" +#~ msgstr "Tulostetaan sivua %d (%d %%)" -#: ../hardcopy.c:680 #, c-format msgid " Copy %d of %d" msgstr " Kopio %d/%d" -#: ../hardcopy.c:733 #, c-format msgid "Printed: %s" msgstr "Tulostettu: %s" -#: ../hardcopy.c:740 msgid "Printing aborted" msgstr "Tulostus peruttu" -#: ../hardcopy.c:1365 msgid "E455: Error writing to PostScript output file" -msgstr "E455: Virhe kirjoitettaessa PostScriptiä tiedostoon" +msgstr "E455: Virhe kirjoitettaessa PostScriptiä tiedostoon" -#: ../hardcopy.c:1747 #, c-format msgid "E624: Can't open file \"%s\"" msgstr "E624: Ei voi avata tiedostoa %s" -#: ../hardcopy.c:1756 ../hardcopy.c:2470 #, c-format msgid "E457: Can't read PostScript resource file \"%s\"" msgstr "E457: Ei voi lukea PostScript-resurssitiedostoa %s" -#: ../hardcopy.c:1772 #, c-format msgid "E618: file \"%s\" is not a PostScript resource file" msgstr "E618: tiedosto %s ei ole PostScript-resurssitiedosto" -#: ../hardcopy.c:1788 ../hardcopy.c:1805 ../hardcopy.c:1844 #, c-format msgid "E619: file \"%s\" is not a supported PostScript resource file" msgstr "E619: tiedosto %s ei ole tuettu PostScript-resurssitiedosto" -#: ../hardcopy.c:1856 #, c-format msgid "E621: \"%s\" resource file has wrong version" -msgstr "E621: resurssitiedoston %s versio on väärä" +msgstr "E621: resurssitiedoston %s versio on väärä" -#: ../hardcopy.c:2225 msgid "E673: Incompatible multi-byte encoding and character set." -msgstr "E673: Tukematon monitvauinen merkistökoodaus ja merkistö." +msgstr "E673: Tukematon monitvauinen merkistökoodaus ja merkistö." -#: ../hardcopy.c:2238 msgid "E674: printmbcharset cannot be empty with multi-byte encoding." -msgstr "E674: printmbcharset ei voi olla tyhjä monitavuiselle koodaukselle." +msgstr "E674: printmbcharset ei voi olla tyhjä monitavuiselle koodaukselle." -#: ../hardcopy.c:2254 msgid "E675: No default font specified for multi-byte printing." msgstr "E675: Ei oletusfonttia monitavuiseen tulostukseen" -#: ../hardcopy.c:2426 msgid "E324: Can't open PostScript output file" msgstr "E324: PostScript-tulostetiedoston avaus ei onnistu" -#: ../hardcopy.c:2458 #, c-format msgid "E456: Can't open file \"%s\"" msgstr "E456: Tiedoston %s avaus ei onnistu" -#: ../hardcopy.c:2583 msgid "E456: Can't find PostScript resource file \"prolog.ps\"" -msgstr "E456: PostScript-resurssitiedostoa prolog.ps ei löydy" +msgstr "E456: PostScript-resurssitiedostoa prolog.ps ei löydy" -#: ../hardcopy.c:2593 msgid "E456: Can't find PostScript resource file \"cidfont.ps\"" -msgstr "E456: PostScript-resurssitiedostoa cidfont.ps ei löydy" +msgstr "E456: PostScript-resurssitiedostoa cidfont.ps ei löydy" -#: ../hardcopy.c:2622 ../hardcopy.c:2639 ../hardcopy.c:2665 #, c-format msgid "E456: Can't find PostScript resource file \"%s.ps\"" -msgstr "E456: Postscript-resurssitiedosta %s.ps ei löydy" +msgstr "E456: Postscript-resurssitiedosta %s.ps ei löydy" -#: ../hardcopy.c:2654 #, c-format msgid "E620: Unable to convert to print encoding \"%s\"" msgstr "E620: Tulostuskoodaukseen %s muunto ei onnistu" -#: ../hardcopy.c:2877 msgid "Sending to printer..." -msgstr "Lähetetään tulostimelle..." +msgstr "Lähetetään tulostimelle..." -#: ../hardcopy.c:2881 msgid "E365: Failed to print PostScript file" -msgstr "E365: PostScript-tiedoston tulostus epäonnistui" +msgstr "E365: PostScript-tiedoston tulostus epäonnistui" -#: ../hardcopy.c:2883 msgid "Print job sent." -msgstr "Tulostustyö lähetetty." +msgstr "Tulostustyö lähetetty." -#: ../if_cscope.c:85 msgid "Add a new database" -msgstr "Lisää uusi tietokanta" +msgstr "Lisää uusi tietokanta" -#: ../if_cscope.c:87 msgid "Query for a pattern" msgstr "Hae kuviota" -#: ../if_cscope.c:89 msgid "Show this message" -msgstr "Näytä tämä viesti" +msgstr "Näytä tämä viesti" -#: ../if_cscope.c:91 msgid "Kill a connection" msgstr "Tapa yhteys" -#: ../if_cscope.c:93 msgid "Reinit all connections" msgstr "Alusta uudelleen yhteydet" -#: ../if_cscope.c:95 msgid "Show connections" -msgstr "Näytä yhteydet" +msgstr "Näytä yhteydet" -#: ../if_cscope.c:101 #, c-format msgid "E560: Usage: cs[cope] %s" -msgstr "E560: Käyttö: cs[cope] %s" +msgstr "E560: Käyttö: cs[cope] %s" -#: ../if_cscope.c:225 msgid "This cscope command does not support splitting the window.\n" -msgstr "Tämä cscope-komento ei tue ikkunan jakamista.\n" +msgstr "Tämä cscope-komento ei tue ikkunan jakamista.\n" -#: ../if_cscope.c:266 msgid "E562: Usage: cstag <ident>" -msgstr "E562: Käyttö: cstag <ident>" +msgstr "E562: Käyttö: cstag <ident>" -#: ../if_cscope.c:313 msgid "E257: cstag: tag not found" -msgstr "E257: cstag: tägia ei löydy" +msgstr "E257: cstag: tägia ei löydy" -#: ../if_cscope.c:461 #, c-format msgid "E563: stat(%s) error: %d" msgstr "E563: stat(%s)-virhe: %d" -#: ../if_cscope.c:551 #, c-format msgid "E564: %s is not a directory or a valid cscope database" -msgstr "E564: %s ei ole hakemisto eikä cscope-tietokanta" +msgstr "E564: %s ei ole hakemisto eikä cscope-tietokanta" -#: ../if_cscope.c:566 #, c-format msgid "Added cscope database %s" -msgstr "Lisätty cscope-tietokanta %s" +msgstr "Lisätty cscope-tietokanta %s" -#: ../if_cscope.c:616 -#, c-format -msgid "E262: error reading cscope connection %<PRId64>" -msgstr "E262: Virhe luettaessa cscope-yhteyttä %<PRId64>" +#, fuzzy, c-format +#~ msgid "E262: error reading cscope connection %<PRIu64>" +#~ msgstr "E262: Virhe luettaessa cscope-yhteyttä %ld" -#: ../if_cscope.c:711 msgid "E561: unknown cscope search type" msgstr "E561: tuntematon cscope-hakutyyppi" -#: ../if_cscope.c:752 ../if_cscope.c:789 msgid "E566: Could not create cscope pipes" msgstr "E566: Ei voitu luoda cscope-putkia" -#: ../if_cscope.c:767 msgid "E622: Could not fork for cscope" msgstr "E622: Ei voitu haarauttaa cscopea" -#: ../if_cscope.c:849 -#, fuzzy msgid "cs_create_connection setpgid failed" -msgstr "cs_create_connection epäonnistui" +msgstr "cs_create_connection setpgid epäonnistui" -#: ../if_cscope.c:853 ../if_cscope.c:889 msgid "cs_create_connection exec failed" -msgstr "cs_create_connection epäonnistui" +msgstr "cs_create_connection epäonnistui" -#: ../if_cscope.c:863 ../if_cscope.c:902 msgid "cs_create_connection: fdopen for to_fp failed" -msgstr "cs_create_connection: fdopen to_fp epäonnistui" +msgstr "cs_create_connection: fdopen to_fp epäonnistui" -#: ../if_cscope.c:865 ../if_cscope.c:906 msgid "cs_create_connection: fdopen for fr_fp failed" -msgstr "cs_create_connection: fdopen fr_fp epäonnistui" +msgstr "cs_create_connection: fdopen fr_fp epäonnistui" -#: ../if_cscope.c:890 msgid "E623: Could not spawn cscope process" -msgstr "E623: Cscope-prosessin luonti epäonnistui" +msgstr "E623: Cscope-prosessin luonti epäonnistui" -#: ../if_cscope.c:932 msgid "E567: no cscope connections" -msgstr "E567: ei cscope-yhteyksiä" +msgstr "E567: ei cscope-yhteyksiä" -#: ../if_cscope.c:1009 #, c-format msgid "E469: invalid cscopequickfix flag %c for %c" msgstr "E469: virheellinen cscopequickfix-asetus %c kohteelle %c" -#: ../if_cscope.c:1058 #, c-format msgid "E259: no matches found for cscope query %s of %s" -msgstr "E259: ei täsmäyksiä cscope-hakuun %s/%s" +msgstr "E259: ei täsmäyksiä cscope-hakuun %s/%s" -#: ../if_cscope.c:1142 msgid "cscope commands:\n" msgstr "cscope-komennot:\n" -#: ../if_cscope.c:1150 #, c-format msgid "%-5s: %s%*s (Usage: %s)" -msgstr "%-5s: %s%*s (Käyttö: %s)" +msgstr "%-5s: %s%*s (Käyttö: %s)" -#: ../if_cscope.c:1155 -#, fuzzy msgid "" "\n" +" a: Find assignments to this symbol\n" " c: Find functions calling this function\n" " d: Find functions called by this function\n" " e: Find this egrep pattern\n" @@ -3246,40 +3092,36 @@ msgid "" " t: Find this text string\n" msgstr "" "\n" -" c: Etsi tätä funktiota kutsuvat funktiot\n" -" d: Etsi tämän funktion kutsumat funktiot\n" -" e: Etsi tämä egrep-lauseke\n" -" f: Find tämä tiedosto\n" -" g: Etsi tämä määritys\n" -" i: Etsi tiedostoja jotka #inkluudaavat tämän\n" -" s: Etsi tämä C-symboli\n" +" a: Etsi sijotukset tähän symboliin\n" +" c: Etsi tätä funktiota kutsuvat funktiot\n" +" d: Etsi tämän funktion kutsumat funktiot\n" +" e: Etsi tämä egrep-lauseke\n" +" f: Etsi tämä tiedosto\n" +" g: Etsi tämä määritys\n" +" i: Etsi tiedostoja jotka #inkluudaavat tämän\n" +" s: Etsi tämä C-symboli\n" " t: Etsi sijoitukset muuttujaan \n" -#: ../if_cscope.c:1226 msgid "E568: duplicate cscope database not added" -msgstr "E568: kaksoiskappaletta cscope-tietokannasta ei lisätty" +msgstr "E568: kaksoiskappaletta cscope-tietokannasta ei lisätty" -#: ../if_cscope.c:1335 #, c-format msgid "E261: cscope connection %s not found" msgstr "E261: cscope-yhteys %s puuttuu" -#: ../if_cscope.c:1364 #, c-format msgid "cscope connection %s closed" msgstr "cscope-yhteys %s on katkaistu" #. should not reach here -#: ../if_cscope.c:1486 msgid "E570: fatal error in cs_manage_matches" msgstr "E570: kriittinen virhe cs_manage_matches-funktiossa" -#: ../if_cscope.c:1693 #, c-format msgid "Cscope tag: %s" -msgstr "Cscope-tägi: %s" +msgstr "Cscope-tägi: %s" -#: ../if_cscope.c:1711 +#. Column headers for match number, line number and filename. msgid "" "\n" " # line" @@ -3287,326 +3129,272 @@ msgstr "" "\n" " # rivi" -#: ../if_cscope.c:1713 msgid "filename / context / line\n" msgstr "tiedosto / konteksti / rivi\n" -#: ../if_cscope.c:1809 #, c-format msgid "E609: Cscope error: %s" msgstr "E609: Cscope-virhe: %s" -#: ../if_cscope.c:2053 msgid "All cscope databases reset" msgstr "Kaikki cscope-tietokannat nollattu" -#: ../if_cscope.c:2123 msgid "no cscope connections\n" -msgstr "ei cscope-yhteyksiä\n" +msgstr "ei cscope-yhteyksiä\n" -#: ../if_cscope.c:2126 msgid " # pid database name prepend path\n" -msgstr " # pid tietokanta lisäyspolku\n" +msgstr " # pid tietokanta lisäyspolku\n" + +#. Error messages +msgid "Argument missing after" +msgstr "Argumentti puuttuu kohdasta" + +msgid "Garbage after option argument" +msgstr "Roskaa argumentin perässä" -#: ../main.c:144 msgid "Unknown option argument" msgstr "Tuntematon asetusargumentti" -#: ../main.c:146 msgid "Too many edit arguments" msgstr "Liikaa muokkausargumentteja" -#: ../main.c:148 -msgid "Argument missing after" -msgstr "Argumentti puuttuu kohdasta" - -#: ../main.c:150 -msgid "Garbage after option argument" -msgstr "Roskaa argumentin perässä" - -#: ../main.c:152 msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments" msgstr "Liikaa +komentoja, -c-komentoja tai --cmd-komentoja" -#: ../main.c:154 -msgid "Invalid argument for" -msgstr "Väärä argumentti valitsimelle" - -#: ../main.c:294 -#, c-format -msgid "%d files to edit\n" -msgstr "%d tiedostoa muokattavana\n" - -#: ../main.c:1342 msgid "Attempt to open script file again: \"" msgstr "Yritettiin avata skriptitiedostoa uudestaan:" -#: ../main.c:1350 msgid "Cannot open for reading: \"" msgstr "Ei voi avata luettavaksi: " -#: ../main.c:1393 msgid "Cannot open for script output: \"" msgstr "Ei voi avata skriptin tulostetta varten: " -#: ../main.c:1622 msgid "Vim: Warning: Output is not to a terminal\n" msgstr "Vim: Varoitus: Tuloste ei mene terminaalille\n" -#: ../main.c:1624 msgid "Vim: Warning: Input is not from a terminal\n" -msgstr "Vim: Varoitus: Syöte ei tule terminaalilta\n" +msgstr "Vim: Varoitus: Syöte ei tule terminaalilta\n" #. just in case.. -#: ../main.c:1891 msgid "pre-vimrc command line" msgstr "esi-vimrc-komentorivi" -#: ../main.c:1964 #, c-format msgid "E282: Cannot read from \"%s\"" msgstr "E282: Ei voida lukea kohteesta %s" -#: ../main.c:2149 +#, fuzzy msgid "" "\n" -"More info with: \"vim -h\"\n" +"More info with \"" msgstr "" "\n" -"Lisätietoja: \"vim -h\"\n" - -#: ../main.c:2178 -msgid "[file ..] edit specified file(s)" -msgstr "[tiedosto ..] muokkaa tiedostoja" - -#: ../main.c:2179 -msgid "- read text from stdin" -msgstr "- lue vakiosyötteestä" +"Lisätietoja: \"vim -h\"\n" -#: ../main.c:2180 -msgid "-t tag edit file where tag is defined" -msgstr "-t tägi muokkaa tiedostoa tägistä" +#. kill us with CTRL-C here, if you like +#, fuzzy +#~ msgid "Usage:\n" +#~ msgstr "" +#~ "\n" +#~ "\n" +#~ "käyttö:" -#: ../main.c:2181 -msgid "-q [errorfile] edit file with first error" -msgstr "-q [virhetiedosto] muokkaa tiedostoa ensimmäisestä virheestä" +#, fuzzy +#~ msgid " nvim [arguments] [file ...] Edit specified file(s)\n" +#~ msgstr "[tiedosto ..] muokkaa tiedostoja" -#: ../main.c:2187 -msgid "" -"\n" -"\n" -"usage:" -msgstr "" -"\n" -"\n" -"käyttö:" +#, fuzzy +#~ msgid " nvim [arguments] - Read text from stdin\n" +#~ msgstr "- lue vakiosyötteestä" -#: ../main.c:2189 -msgid " vim [arguments] " -msgstr " vim [argumentit] " +#, fuzzy +#~ msgid " nvim [arguments] -t <tag> Edit file where tag is defined\n" +#~ msgstr "-t tägi muokkaa tiedostoa tägistä" -#: ../main.c:2193 -msgid "" -"\n" -" or:" -msgstr "" -"\n" -" tai:" +#, fuzzy +#~ msgid " nvim [arguments] -q [errorfile] Edit file with first error\n" +#~ msgstr "-q [virhetiedosto] muokkaa tiedostoa ensimmäisestä virheestä" -#: ../main.c:2196 +#, fuzzy msgid "" "\n" -"\n" "Arguments:\n" msgstr "" "\n" "\n" "Argumentit:\n" -#: ../main.c:2197 -msgid "--\t\t\tOnly file names after this" -msgstr "--\t\t\tvain tiedostonimiä tämän jälkeen" - -#: ../main.c:2199 -msgid "--literal\t\tDon't expand wildcards" -msgstr "--literal\t\tÄlä käsittele jokerimerkkejä " - -#: ../main.c:2201 -msgid "-v\t\t\tVi mode (like \"vi\")" -msgstr "-v\t\t\tVi-tila (kuten villä)" +#, fuzzy +#~ msgid " -- Only file names after this\n" +#~ msgstr "--\t\t\tvain tiedostonimiä tämän jälkeen" -#: ../main.c:2202 -msgid "-e\t\t\tEx mode (like \"ex\")" -msgstr "-e\t\t\tEx-tila (kute exillä)" +#, fuzzy +#~ msgid " --literal Don't expand wildcards\n" +#~ msgstr "--literal\t\tÄlä käsittele jokerimerkkejä " -#: ../main.c:2203 -msgid "-E\t\t\tImproved Ex mode" -msgstr "" +#, fuzzy +#~ msgid " -e Ex mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2204 -msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")" -msgstr "-s\t\t\tHiljainen (eräajo)tila (vain exillä)" +#, fuzzy +#~ msgid " -E Improved Ex mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2205 -msgid "-d\t\t\tDiff mode (like \"vimdiff\")" -msgstr "-d\t\t\tDiff-tila (kuten vimdiffillä)" +#, fuzzy +#~ msgid " -s Silent (batch) mode (only for ex mode)\n" +#~ msgstr "-s\t\t\tHiljainen (eräajo)tila (vain exillä)" -#: ../main.c:2206 -msgid "-y\t\t\tEasy mode (like \"evim\", modeless)" -msgstr "-y\t\t\tHelppokäyttötila (kuten evimissä, ilman tiloja)" +#, fuzzy +#~ msgid " -d Diff mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2207 -msgid "-R\t\t\tReadonly mode (like \"view\")" -msgstr "-R\t\t\tKirjoitussuojattu tila (kuten view'lla)" +#, fuzzy +#~ msgid " -R Read-only mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2208 -msgid "-Z\t\t\tRestricted mode (like \"rvim\")" -msgstr "-Z\t\t\tRajoitettu tila (kuten rvimillä)" +#, fuzzy +#~ msgid " -Z Restricted mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2209 -msgid "-m\t\t\tModifications (writing files) not allowed" -msgstr "-m\t\t\tMuokkaukset (kirjoittaminen tiedostoon) pois käytöstä" +#, fuzzy +#~ msgid " -m Modifications (writing files) not allowed\n" +#~ msgstr "-m\t\t\tMuokkaukset (kirjoittaminen tiedostoon) pois käytöstä" -#: ../main.c:2210 -msgid "-M\t\t\tModifications in text not allowed" -msgstr "-M\t\t\tTekstin muokkaus pois käytöstä" +#, fuzzy +#~ msgid " -M Modifications in text not allowed\n" +#~ msgstr "-M\t\t\tTekstin muokkaus pois käytöstä" -#: ../main.c:2211 -msgid "-b\t\t\tBinary mode" -msgstr "-b\t\t\tBinääritila" +#, fuzzy +#~ msgid " -b Binary mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2212 -msgid "-l\t\t\tLisp mode" -msgstr "-l\t\t\tLisp-tila" +#, fuzzy +#~ msgid " -l Lisp mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2213 -msgid "-C\t\t\tCompatible with Vi: 'compatible'" -msgstr "-C\t\t\tVi-yhteensopivuustila: compatible" +#, fuzzy +#~ msgid " -A Arabic mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2214 -msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'" -msgstr "-N\t\t\tEi Vi-yhteensopivuutta: nocompatible" +#, fuzzy +#~ msgid " -F Farsi mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2215 -msgid "-V[N][fname]\t\tBe verbose [level N] [log messages to fname]" -msgstr "" -"-V[N][tnimi]\t\tMonisanainen tuloste [Taso N] [kirjoita tuloste tnimeen] " +#, fuzzy +#~ msgid " -H Hebrew mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2216 -msgid "-D\t\t\tDebugging mode" -msgstr "-D\t\t\tVianetsintätila" +#, fuzzy +#~ msgid " -V[N][file] Be verbose [level N][log messages to file]\n" +#~ msgstr "" +#~ "-V[N][tnimi]\t\tMonisanainen tuloste [Taso N] [kirjoita tuloste tnimeen] " -#: ../main.c:2217 -msgid "-n\t\t\tNo swap file, use memory only" -msgstr "-n\t\t\tEi swap-tiedostoja, käytä muistia" +#, fuzzy +#~ msgid " -D Debugging mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2218 -msgid "-r\t\t\tList swap files and exit" -msgstr "-r\t\t\tLuetteloi swap-tiedostot ja poistu" +#, fuzzy +#~ msgid " -n No swap file, use memory only\n" +#~ msgstr "-n\t\t\tEi swap-tiedostoja, käytä muistia" -#: ../main.c:2219 -msgid "-r (with file name)\tRecover crashed session" -msgstr "-r (tiedostonimi)\tPalauta kaatunut sessio" +#, fuzzy +#~ msgid " -r, -L List swap files and exit\n" +#~ msgstr "-r\t\t\tLuetteloi swap-tiedostot ja poistu" -#: ../main.c:2220 -msgid "-L\t\t\tSame as -r" -msgstr "-L\t\t\tkuten -r" +#, fuzzy +#~ msgid " -r <file> Recover crashed session\n" +#~ msgstr "-r (tiedostonimi)\tPalauta kaatunut sessio" -#: ../main.c:2221 -msgid "-A\t\t\tstart in Arabic mode" -msgstr "-A\t\t\tkäynnistä arabia-tilassa" +#, fuzzy +#~ msgid " -u <vimrc> Use <vimrc> instead of the default\n" +#~ msgstr "-u <vimrc>\t\tKäytä <vimrc>-tiedostoa .vimrc:iden sijasta" -#: ../main.c:2222 -msgid "-H\t\t\tStart in Hebrew mode" -msgstr "-H\t\t\tkäynnistä heprea-tilassa" +#~ msgid " -i <shada> Use <shada> instead of the default\n" +#~ msgstr "" -#: ../main.c:2223 -msgid "-F\t\t\tStart in Farsi mode" -msgstr "-F\t\t\tkäynnistä farsi-tilassa" +#, fuzzy +#~ msgid " --noplugin Don't load plugin scripts\n" +#~ msgstr "--noplugin\t\tÄlä lataa liitännäisiä" -#: ../main.c:2224 -msgid "-T <terminal>\tSet terminal type to <terminal>" -msgstr "-T <terminaali>\tAseta terminaalin tyypiksi <terminaali>" +#, fuzzy +#~ msgid " -o[N] Open N windows (default: one for each file)\n" +#~ msgstr "-o[N]\t\tAvaa N ikkunaa (oletus: yksi per tiedosto)" -#: ../main.c:2225 -msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc" -msgstr "-u <vimrc>\t\tKäytä <vimrc>-tiedostoa .vimrc:iden sijasta" +#, fuzzy +#~ msgid " -O[N] Like -o but split vertically\n" +#~ msgstr "-O[N]\t\tKuten -o, mutta jaa pystysuunnassa" -#: ../main.c:2226 -msgid "--noplugin\t\tDon't load plugin scripts" -msgstr "--noplugin\t\tÄlä lataa liitännäisiä" +#, fuzzy +#~ msgid " -p[N] Open N tab pages (default: one for each file)\n" +#~ msgstr "-p[N]\t\tAvaa N välilehteä (oletus: yksi per tiedosto)" -#: ../main.c:2227 -msgid "-p[N]\t\tOpen N tab pages (default: one for each file)" -msgstr "-p[N]\t\tAvaa N välilehteä (oletus: yksi per tiedosto)" +#, fuzzy +#~ msgid " + Start at end of file\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2228 -msgid "-o[N]\t\tOpen N windows (default: one for each file)" -msgstr "-o[N]\t\tAvaa N ikkunaa (oletus: yksi per tiedosto)" +#, fuzzy +#~ msgid " +<linenum> Start at line <linenum>\n" +#~ msgstr "+<rivi>\t\t\tAloita riviltä <rivi>" -#: ../main.c:2229 -msgid "-O[N]\t\tLike -o but split vertically" -msgstr "-O[N]\t\tKuten -o, mutta jaa pystysuunnassa" +#~ msgid " +/<pattern> Start at first occurrence of <pattern>\n" +#~ msgstr "" -#: ../main.c:2230 -msgid "+\t\t\tStart at end of file" -msgstr "+\t\t\tAloita tiedoston lopusta" +#, fuzzy +#~ msgid " --cmd <command> Execute <command> before loading any vimrc\n" +#~ msgstr "--cmd <komento>\tSuorita <komento> ennen vimrc:iden latausta" -#: ../main.c:2231 -msgid "+<lnum>\t\tStart at line <lnum>" -msgstr "+<rivi>\t\t\tAloita riviltä <rivi>" +#, fuzzy +msgid "" +" -c <command> Execute <command> after loading the first file\n" +msgstr "-c <komento>\t\tSuorita <komento> ensimmäisen tiedoston latauduttua" -#: ../main.c:2232 -msgid "--cmd <command>\tExecute <command> before loading any vimrc file" -msgstr "--cmd <komento>\tSuorita <komento> ennen vimrc:iden latausta" +#, fuzzy +#~ msgid " -S <session> Source <session> after loading the first file\n" +#~ msgstr "-S <sessio>\t\tLataa <sessio> ensimmäisen tiedoston latauduttua" -#: ../main.c:2233 -msgid "-c <command>\t\tExecute <command> after loading the first file" -msgstr "-c <komento>\t\tSuorita <komento> ensimmäisen tiedoston latauduttua" +#, fuzzy +#~ msgid " -s <scriptin> Read Normal mode commands from <scriptin>\n" +#~ msgstr "-s <skripti>\tLue normaalitilan komentoja <skripti>-tiedostosta" -#: ../main.c:2235 -msgid "-S <session>\t\tSource file <session> after loading the first file" -msgstr "-S <sessio>\t\tLataa <sessio> ensimmäisen tiedoston latauduttua" +#, fuzzy +#~ msgid " -w <scriptout> Append all typed characters to <scriptout>\n" +#~ msgstr "-w <skripti>\tLisää kirjoitetut komennot <skripti>-tiedostoon" -#: ../main.c:2236 -msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>" -msgstr "-s <skripti>\tLue normaalitilan komentoja <skripti>-tiedostosta" +#, fuzzy +#~ msgid " -W <scriptout> Write all typed characters to <scriptout>\n" +#~ msgstr "-W <skripti>\tKirjoita komennot <skripti>-tiedostoon" -#: ../main.c:2237 -msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>" -msgstr "-w <skripti>\tLisää kirjoitetut komennot <skripti>-tiedostoon" +#, fuzzy +#~ msgid " --startuptime <file> Write startup timing messages to <file>\n" +#~ msgstr "--startuptime <file>\tKirjoita käynnistysaikaviestit tiedostoon <file>" -#: ../main.c:2238 -msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>" -msgstr "-W <skripti>\tKirjoita komennot <skripti>-tiedostoon" +#~ msgid "" +#~ " --api-info Dump API metadata serialized to msgpack and exit\n" +#~ msgstr "" -#: ../main.c:2240 -msgid "--startuptime <file>\tWrite startup timing messages to <file>" -msgstr "--startuptime <file>\tKirjoita käynnistysaikaviestit tiedostoon <file>" +#~ msgid " --embed Use stdin/stdout as a msgpack-rpc channel\n" +#~ msgstr "" -#: ../main.c:2242 -msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo" -msgstr "-i <viminfo>\t\tKäytä <viminfo>-tiedostoa .viminfon sijaan" +#~ msgid " --headless Don't start a user interface\n" +#~ msgstr "" -#: ../main.c:2243 -msgid "-h or --help\tPrint Help (this message) and exit" -msgstr "-h tai --help\tTulosta ohje (tämä viesti) ja lopeta" +#, fuzzy +#~ msgid " -v, --version Print version information and exit\n" +#~ msgstr "--version\t\t\tTulosta versiotiedot ja lopeta" -#: ../main.c:2244 -msgid "--version\t\tPrint version information and exit" -msgstr "--version\t\t\tTulosta versiotiedot ja lopeta" +#, fuzzy +#~ msgid " -h, --help Print this help message and exit\n" +#~ msgstr "-h tai --help\tTulosta ohje (tämä viesti) ja lopeta" -#: ../mark.c:676 msgid "No marks set" -msgstr "Ei asetettuja merkkejä" +msgstr "Ei asetettuja merkkejä" -#: ../mark.c:678 #, c-format msgid "E283: No marks matching \"%s\"" -msgstr "E283: Mikään merkki ei täsmää ilmaukseen \"%s\"" +msgstr "E283: Mikään merkki ei täsmää ilmaukseen \"%s\"" #. Highlight title -#: ../mark.c:687 msgid "" "\n" "mark line col file/text" @@ -3615,7 +3403,6 @@ msgstr "" "merkki rivi sarake tiedosto/teksti" #. Highlight title -#: ../mark.c:789 msgid "" "\n" " jump line col file/text" @@ -3624,7 +3411,6 @@ msgstr "" "hyppy rivi sarake tiedosto/teksti" #. Highlight title -#: ../mark.c:831 msgid "" "\n" "change line col text" @@ -3632,138 +3418,85 @@ msgstr "" "\n" "muutos rivi sarake teksti" -#: ../mark.c:1238 -msgid "" -"\n" -"# File marks:\n" -msgstr "" -"\n" -"# Tiedoston merkit:\n" - -#. Write the jumplist with -' -#: ../mark.c:1271 -msgid "" -"\n" -"# Jumplist (newest first):\n" -msgstr "" -"\n" -"# Hyppylista (uusin ensiksi):\n" - -#: ../mark.c:1352 -msgid "" -"\n" -"# History of marks within files (newest to oldest):\n" -msgstr "" -"\n" -"# Tiedostojen merkkien historia (uusimmasta vanhimpaan):\n" - -#: ../mark.c:1431 -msgid "Missing '>'" -msgstr "> puuttuu" - -#: ../memfile.c:426 msgid "E293: block was not locked" msgstr "E293: lohkoa ei ole lukittu" -#: ../memfile.c:799 msgid "E294: Seek error in swap file read" msgstr "E294: Hakuvirhe swap-tiedostoa luettaessa" -#: ../memfile.c:803 msgid "E295: Read error in swap file" msgstr "E295: Lukuvirhe swap-tiedostossa" -#: ../memfile.c:849 msgid "E296: Seek error in swap file write" msgstr "E296: Hakuvirhe swap-tiedostoa kirjoitettaessa" -#: ../memfile.c:865 msgid "E297: Write error in swap file" msgstr "E297: Kirjoitusvirhe swap-tiedostossa" -#: ../memfile.c:1036 msgid "E300: Swap file already exists (symlink attack?)" -msgstr "E300: Swaptiedosto on jo olemassa (symlink-hyökkäys?)" +msgstr "E300: Swaptiedosto on jo olemassa (symlink-hyökkäys?)" -#: ../memline.c:318 msgid "E298: Didn't get block nr 0?" msgstr "E298: Lohko 0:aa ei saatu?" -#: ../memline.c:361 msgid "E298: Didn't get block nr 1?" -msgstr "E298: Lohko 1:tä ei saatu?" +msgstr "E298: Lohko 1:tä ei saatu?" -#: ../memline.c:377 msgid "E298: Didn't get block nr 2?" msgstr "E298: Lohko 2:ta ei saatu?" #. could not (re)open the swap file, what can we do???? -#: ../memline.c:465 msgid "E301: Oops, lost the swap file!!!" -msgstr "E301: Hups, swap-tiedosto hävisi!" +msgstr "E301: Hups, swap-tiedosto hävisi!" -#: ../memline.c:477 msgid "E302: Could not rename swap file" msgstr "E302: Swap-tiedoston uudellennimeys ei onnistu" -#: ../memline.c:554 #, c-format msgid "E303: Unable to open swap file for \"%s\", recovery impossible" msgstr "E303: Swap-tiedostoa %s ei voi avata, palautus ei onnistu" -#: ../memline.c:666 msgid "E304: ml_upd_block0(): Didn't get block 0??" msgstr "E304: ml_upd_block0(): Lohko 0:aa ei saatu?" #. no swap files found -#: ../memline.c:830 #, c-format msgid "E305: No swap file found for %s" msgstr "E305: Ei swap-tiedostoa tiedostolle %s" -#: ../memline.c:839 msgid "Enter number of swap file to use (0 to quit): " msgstr "Anna swap-tiedoston numero tai 0 lopettaaksesi: " -#: ../memline.c:879 #, c-format msgid "E306: Cannot open %s" msgstr "E306: Ei voi avata tiedostoa %s" -#: ../memline.c:897 msgid "Unable to read block 0 from " msgstr "Ei voi lukea lohkoa 0 kohteesta " -#: ../memline.c:900 msgid "" "\n" "Maybe no changes were made or Vim did not update the swap file." msgstr "" "\n" -"Muutoksia ei tehty, tai Vim ei päivittänyt swap-tiedostoa." +"Muutoksia ei tehty, tai Vim ei päivittänyt swap-tiedostoa." -#: ../memline.c:909 msgid " cannot be used with this version of Vim.\n" -msgstr " ei toimi tämän version Vimin kanssa.\n" +msgstr " ei toimi tämän version Vimin kanssa.\n" -#: ../memline.c:911 msgid "Use Vim version 3.0.\n" -msgstr "Käytä Vimin versiota 3.0\n" +msgstr "Käytä Vimin versiota 3.0\n" -#: ../memline.c:916 #, c-format msgid "E307: %s does not look like a Vim swap file" msgstr "E307: %s ei ole Vimin swap-tiedosto" -#: ../memline.c:922 msgid " cannot be used on this computer.\n" -msgstr " ei toimi tällä koneella.\n" +msgstr " ei toimi tällä koneella.\n" -#: ../memline.c:924 msgid "The file was created on " msgstr "Tiedosto luotiin " -#: ../memline.c:928 msgid "" ",\n" "or the file has been damaged." @@ -3771,100 +3504,78 @@ msgstr "" ",\n" "tai tiedosto on vahingoittunut." -#: ../memline.c:945 msgid " has been damaged (page size is smaller than minimum value).\n" -msgstr " on vioittunut (sivun koko on vähimmäisarvoa pienempi).\n" +msgstr " on vioittunut (sivun koko on vähimmäisarvoa pienempi).\n" -#: ../memline.c:974 #, c-format msgid "Using swap file \"%s\"" -msgstr "Käytetään swap-tiedostoa %s" +msgstr "Käytetään swap-tiedostoa %s" -#: ../memline.c:980 #, c-format msgid "Original file \"%s\"" -msgstr "Alkuperäinen tiedosto %s" +msgstr "Alkuperäinen tiedosto %s" -#: ../memline.c:995 msgid "E308: Warning: Original file may have been changed" -msgstr "E308: Varoitus: Alkuperäistä tiedostoa saattaa olla muutettu" +msgstr "E308: Varoitus: Alkuperäistä tiedostoa saattaa olla muutettu" -#: ../memline.c:1061 #, c-format msgid "E309: Unable to read block 1 from %s" msgstr "E309: Ei voitu lukea lohkoa 1 tiedostosta %s" -#: ../memline.c:1065 msgid "???MANY LINES MISSING" -msgstr "???PALJON RIVEJÄ PUUTTUU" +msgstr "???PALJON RIVEJÄ PUUTTUU" -#: ../memline.c:1076 msgid "???LINE COUNT WRONG" -msgstr "???RIVIMÄÄRÄ PIELESSÄ" +msgstr "???RIVIMÄÄRÄ PIELESSÄ" -#: ../memline.c:1082 msgid "???EMPTY BLOCK" -msgstr "???TYHJÄ LOHKO" +msgstr "???TYHJÄ LOHKO" -#: ../memline.c:1103 msgid "???LINES MISSING" -msgstr "???RIVEJÄ PUUTTUU" +msgstr "???RIVEJÄ PUUTTUU" -#: ../memline.c:1128 #, c-format msgid "E310: Block 1 ID wrong (%s not a .swp file?)" -msgstr "E310: Lohon 1 tunniste väärä (%s ei ole .swp-tiedosto?)" +msgstr "E310: Lohon 1 tunniste väärä (%s ei ole .swp-tiedosto?)" -#: ../memline.c:1133 msgid "???BLOCK MISSING" msgstr "???LOHKO PUUTTUU" -#: ../memline.c:1147 msgid "??? from here until ???END lines may be messed up" -msgstr "??? tästä kohtaan ???LOPPU rivejä sekaisin" +msgstr "??? tästä kohtaan ???LOPPU rivejä sekaisin" -#: ../memline.c:1164 msgid "??? from here until ???END lines may have been inserted/deleted" -msgstr "??? tästä kohtaan ???LOPPU rivejä saattaa olla lisätty tai poistettu" +msgstr "??? tästä kohtaan ???LOPPU rivejä saattaa olla lisätty tai poistettu" -#: ../memline.c:1181 msgid "???END" msgstr "???LOPPU" -#: ../memline.c:1238 msgid "E311: Recovery Interrupted" msgstr "E311: Palautus keskeytetty" -#: ../memline.c:1243 msgid "" "E312: Errors detected while recovering; look for lines starting with ???" -msgstr "E312: Palautuksessa oli virheitä, etsi rivejä, jotka alkavat ???" +msgstr "E312: Palautuksessa oli virheitä, etsi rivejä, jotka alkavat ???" -#: ../memline.c:1245 msgid "See \":help E312\" for more information." -msgstr ":help E312 kertoo lisätietoja" +msgstr ":help E312 kertoo lisätietoja" -#: ../memline.c:1249 msgid "Recovery completed. You should check if everything is OK." -msgstr "Palautus onnistui. Tarkista, että kaikki on kunnossa." +msgstr "Palautus onnistui. Tarkista, että kaikki on kunnossa." -#: ../memline.c:1251 msgid "" "\n" "(You might want to write out this file under another name\n" msgstr "" "\n" -"(Saattaa kannattaa kirjoittaa tämä tiedosto toisella nimellä\n" +"(Saattaa kannattaa kirjoittaa tämä tiedosto toisella nimellä\n" -#: ../memline.c:1252 msgid "and run diff with the original file to check for changes)" -msgstr "ja katso diffillä muutokset alkuperäiseen tiedostoon)" +msgstr "ja katso diffillä muutokset alkuperäiseen tiedostoon)" -#: ../memline.c:1254 msgid "Recovery completed. Buffer contents equals file contents." -msgstr "Palautus onnistui. Puskurin ja tiedoston sisällöt täsmäävät." +msgstr "Palautus onnistui. Puskurin ja tiedoston sisällöt täsmäävät." -#: ../memline.c:1255 msgid "" "\n" "You may want to delete the .swp file now.\n" @@ -3875,51 +3586,42 @@ msgstr "" "\n" #. use msg() to start the scrolling properly -#: ../memline.c:1327 msgid "Swap files found:" -msgstr "Swap-tiedostoja löytyi:" +msgstr "Swap-tiedostoja löytyi:" -#: ../memline.c:1446 msgid " In current directory:\n" -msgstr " Tässä hakemistossa:\n" +msgstr " Tässä hakemistossa:\n" -#: ../memline.c:1448 msgid " Using specified name:\n" -msgstr " Määritellyllä nimellä:\n" +msgstr " Määritellyllä nimellä:\n" -#: ../memline.c:1450 msgid " In directory " msgstr " Hakemistossa " -#: ../memline.c:1465 msgid " -- none --\n" -msgstr " -- ei mitään --\n" +msgstr " -- ei mitään --\n" -#: ../memline.c:1527 msgid " owned by: " msgstr " omistaja: " -#: ../memline.c:1529 msgid " dated: " msgstr " ajalta: " -#: ../memline.c:1532 ../memline.c:3231 msgid " dated: " msgstr " ajalta:" -#: ../memline.c:1548 msgid " [from Vim version 3.0]" msgstr " [Vimin 3.0-versiosta]" -#: ../memline.c:1550 msgid " [does not look like a Vim swap file]" -msgstr " [ei näytä Vimin swap-tiedostolta]" +msgstr " [ei näytä Vimin swap-tiedostolta]" + +#~ msgid " [garbled strings (not nul terminated)]" +#~ msgstr "" -#: ../memline.c:1552 msgid " file name: " msgstr " tiedostonimi: " -#: ../memline.c:1558 msgid "" "\n" " modified: " @@ -3927,27 +3629,22 @@ msgstr "" "\n" " muokattu: " -#: ../memline.c:1559 msgid "YES" -msgstr "KYLLÄ" +msgstr "KYLLÄ" -#: ../memline.c:1559 msgid "no" msgstr "ei" -#: ../memline.c:1562 msgid "" "\n" " user name: " msgstr "" "\n" -" käyttäjänimi: " +" käyttäjänimi: " -#: ../memline.c:1568 msgid " host name: " msgstr " laitenimi: " -#: ../memline.c:1570 msgid "" "\n" " host name: " @@ -3955,7 +3652,6 @@ msgstr "" "\n" " laitenimi: " -#: ../memline.c:1575 msgid "" "\n" " process ID: " @@ -3963,190 +3659,143 @@ msgstr "" "\n" " prosessin tunniste: " -#: ../memline.c:1579 msgid " (still running)" -msgstr " (käynnissä)" +msgstr " (käynnissä)" -#: ../memline.c:1586 msgid "" "\n" " [not usable on this computer]" msgstr "" "\n" -" [ei toimi tällä koneella]" +" [ei toimi tällä koneella]" -#: ../memline.c:1590 msgid " [cannot be read]" msgstr " [ei voi lukea]" -#: ../memline.c:1593 msgid " [cannot be opened]" msgstr " [ei voi avata]" -#: ../memline.c:1698 msgid "E313: Cannot preserve, there is no swap file" -msgstr "E313: Ei voi säilyttää, swap-tiedostoa ei ole" +msgstr "E313: Ei voi säilyttää, swap-tiedostoa ei ole" -#: ../memline.c:1747 msgid "File preserved" -msgstr "Tiedosto säilytetty" +msgstr "Tiedosto säilytetty" -#: ../memline.c:1749 msgid "E314: Preserve failed" -msgstr "E314: Säilyttäminen epäonnistui" +msgstr "E314: Säilyttäminen epäonnistui" -#: ../memline.c:1819 -#, c-format -msgid "E315: ml_get: invalid lnum: %<PRId64>" -msgstr "E315: ml_get: virheellinen lnum: %<PRId64>" +#, fuzzy, c-format +#~ msgid "E315: ml_get: invalid lnum: %<PRId64>" +#~ msgstr "E315: ml_get: virheellinen lnum: %ld" -#: ../memline.c:1851 -#, c-format -msgid "E316: ml_get: cannot find line %<PRId64>" -msgstr "E316: ml_get: riviä %<PRId64> ei löydy" +#, fuzzy, c-format +#~ msgid "E316: ml_get: cannot find line %<PRId64>" +#~ msgstr "E316: ml_get: riviä %ld ei löydy" -#: ../memline.c:2236 msgid "E317: pointer block id wrong 3" -msgstr "E317: osoitinlohkon tunnus väärä 3" +msgstr "E317: osoitinlohkon tunnus väärä 3" -#: ../memline.c:2311 msgid "stack_idx should be 0" -msgstr "stack_idx pitää olla 0" +msgstr "stack_idx pitää olla 0" -#: ../memline.c:2369 msgid "E318: Updated too many blocks?" -msgstr "E318: Päivitetty liikaa lohkoja" +msgstr "E318: Päivitetty liikaa lohkoja" -#: ../memline.c:2511 msgid "E317: pointer block id wrong 4" -msgstr "E317: osoitinlohkon tunnus väärä 4" +msgstr "E317: osoitinlohkon tunnus väärä 4" -#: ../memline.c:2536 msgid "deleted block 1?" msgstr "poistettu lohko 1?" -#: ../memline.c:2707 -#, c-format -msgid "E320: Cannot find line %<PRId64>" -msgstr "E320: Riviä %<PRId64> ei löydy" +#, fuzzy, c-format +#~ msgid "E320: Cannot find line %<PRId64>" +#~ msgstr "E320: Riviä %ld ei löydy" -#: ../memline.c:2916 msgid "E317: pointer block id wrong" -msgstr "E317: osoitinlohkon tunnus väärä" +msgstr "E317: osoitinlohkon tunnus väärä" -#: ../memline.c:2930 msgid "pe_line_count is zero" msgstr "pe_line_count on nolla" -#: ../memline.c:2955 -#, c-format -msgid "E322: line number out of range: %<PRId64> past the end" -msgstr "E322: rivinumero arvoalueen ulkopuoleta: %<PRId64> on loppua suurempi" +#, fuzzy, c-format +#~ msgid "E322: line number out of range: %<PRId64> past the end" +#~ msgstr "E322: rivinumero arvoalueen ulkopuoleta: %ld on loppua suurempi" -#: ../memline.c:2959 -#, c-format -msgid "E323: line count wrong in block %<PRId64>" -msgstr "E323: rivimäärä väärin lohkossa %<PRId64>" +#, fuzzy, c-format +#~ msgid "E323: line count wrong in block %<PRId64>" +#~ msgstr "E323: rivimäärä väärin lohkossa %ld" -#: ../memline.c:2999 msgid "Stack size increases" msgstr "Pinon koko kasvaa" -#: ../memline.c:3038 msgid "E317: pointer block id wrong 2" -msgstr "E317: osoitinlohon tunnus väärä 2" +msgstr "E317: osoitinlohon tunnus väärä 2" -#: ../memline.c:3070 #, c-format msgid "E773: Symlink loop for \"%s\"" msgstr "E773: Symlinkkisilmukka kohteelle %s" -#: ../memline.c:3221 msgid "E325: ATTENTION" msgstr "E325: HUOMAA" -#: ../memline.c:3222 msgid "" "\n" "Found a swap file by the name \"" msgstr "" "\n" -"Swap-tiedosto löytyi: \"" +"Swap-tiedosto löytyi: \"" -#: ../memline.c:3226 msgid "While opening file \"" msgstr "Avattaessa tiedostoa " -#: ../memline.c:3239 msgid " NEWER than swap file!\n" msgstr " joka on UUDEMPI kuin swap-tiedosto!\n" -#: ../memline.c:3244 -#, fuzzy +#. Some of these messages are long to allow translation to +#. * other languages. msgid "" "\n" "(1) Another program may be editing the same file. If this is the case,\n" " be careful not to end up with two different instances of the same\n" -" file when making changes." +" file when making changes. Quit, or continue with caution.\n" msgstr "" "\n" -"(1) Toinen ohjelma saattaa käyttää samaa tiedostoa.\n" -" Jos näin on, varo, ettet muokkaa saman tiedoston\n" -" kahta instanssia yhtä aikaa.\n" - -#: ../memline.c:3245 -#, fuzzy -msgid " Quit, or continue with caution.\n" -msgstr " Lopeta, tai jatka.\n" +"(1) Toinen ohjelma saattaa käyttää samaa tiedostoa.\n" +" Jos näin on, varo, ettet muokkaa saman tiedoston\n" +" kahta instanssia yhtä aikaa. Lopeta tai jatka varoen.\n" -#: ../memline.c:3246 -#, fuzzy msgid "(2) An edit session for this file crashed.\n" -msgstr "" -"\n" -"(2) Ohjelma on kaatunut muokatessa tiedostoa.\n" +msgstr "(2) Tiedostonmuokkausistunto on kaatunut.\n" -#: ../memline.c:3247 msgid " If this is the case, use \":recover\" or \"vim -r " -msgstr " Jos näin on, käytä komentoa :recover tai vim -r " +msgstr " Jos näin on, käytä komentoa :recover tai vim -r " -#: ../memline.c:3249 msgid "" "\"\n" " to recover the changes (see \":help recovery\").\n" msgstr "" "\"\n" -" palauttaaksesi muutokset (lisätietoja: \":help recovery\").\n" +" palauttaaksesi muutokset (lisätietoja: \":help recovery\").\n" -#: ../memline.c:3250 msgid " If you did this already, delete the swap file \"" -msgstr " Jos teit jo näin, poista swap-tiedosto " +msgstr " Jos teit jo näin, poista swap-tiedosto " -#: ../memline.c:3252 msgid "" "\"\n" " to avoid this message.\n" msgstr "" "\"\n" -" välttääksesi tämän viestin.\n" +" välttääksesi tämän viestin.\n" -#: ../memline.c:3450 ../memline.c:3452 msgid "Swap file \"" msgstr "Swap-tiedosto " -#: ../memline.c:3451 ../memline.c:3455 msgid "\" already exists!" msgstr " on jo olemassa" -#: ../memline.c:3457 msgid "VIM - ATTENTION" msgstr "VIM - HUOMAUTUS" -#: ../memline.c:3459 -msgid "Swap file already exists!" -msgstr "Swap-tiedosto on jo olemassa" - -#: ../memline.c:3464 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4160,7 +3809,6 @@ msgstr "" "&Lopeta\n" "P&eru" -#: ../memline.c:3467 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4184,48 +3832,48 @@ msgstr "" #. #. ".s?a" #. ".saa": tried enough, give up -#: ../memline.c:3528 msgid "E326: Too many swap files found" msgstr "E326: Liian monta swap-tiedostoa" -#: ../memory.c:227 -#, c-format -msgid "E342: Out of memory! (allocating %<PRIu64> bytes)" -msgstr "E342: Muisti loppui! (varattaessa %<PRIu64> tavua)" +#, fuzzy, c-format +msgid "" +"E303: Unable to create directory \"%s\" for swap file, recovery impossible: " +"%s" +msgstr "E303: Swap-tiedostoa %s ei voi avata, palautus ei onnistu" + +#, fuzzy +#~ msgid "Vim: Data too large to fit into virtual memory space\n" +#~ msgstr "arvo on liian suuri mahtumaan C:n int-tyyppiin" + +#, fuzzy, c-format +#~ msgid "E342: Out of memory! (allocating %<PRIu64> bytes)" +#~ msgstr "E342: Muisti loppui! (varattaessa %lu tavua)" -#: ../menu.c:62 msgid "E327: Part of menu-item path is not sub-menu" msgstr "E327: Valikkokohtapolun osa ei ole alivalikko" -#: ../menu.c:63 msgid "E328: Menu only exists in another mode" msgstr "E328: Valikko on olemassa vain toisessa tilassa" -#: ../menu.c:64 #, c-format msgid "E329: No menu \"%s\"" msgstr "E329: Ei valikkoa %s" #. Only a mnemonic or accelerator is not valid. -#: ../menu.c:329 msgid "E792: Empty menu name" -msgstr "E792: tyhjä valikkonimi" +msgstr "E792: tyhjä valikkonimi" -#: ../menu.c:340 msgid "E330: Menu path must not lead to a sub-menu" msgstr "E330: Valikkopolku ei saa johtaa alivalikkoon" -#: ../menu.c:365 msgid "E331: Must not add menu items directly to menu bar" -msgstr "E331: Valikkokohtia ei saa lisätä suoraan valikkopalkkiin" +msgstr "E331: Valikkokohtia ei saa lisätä suoraan valikkopalkkiin" -#: ../menu.c:370 msgid "E332: Separator cannot be part of a menu path" msgstr "E332: Erotin ei voi olla valikkopolun osa" #. Now we have found the matching menu, and we list the mappings #. Highlight title -#: ../menu.c:762 msgid "" "\n" "--- Menus ---" @@ -4233,87 +3881,64 @@ msgstr "" "\n" "--- Valikot ---" -#: ../menu.c:1313 msgid "E333: Menu path must lead to a menu item" msgstr "E333: Valikkopolun on johdettava valikkokohtaan" -#: ../menu.c:1330 #, c-format msgid "E334: Menu not found: %s" -msgstr "E334: Valikkoa ei löydy: %s" +msgstr "E334: Valikkoa ei löydy: %s" -#: ../menu.c:1396 #, c-format msgid "E335: Menu not defined for %s mode" -msgstr "E335: Valikkoa ei ole määritelty %s-tilassa" - -#: ../menu.c:1426 -msgid "E336: Menu path must lead to a sub-menu" -msgstr "E336: Valikkopolun pitää johtaa alivalikkoon" +msgstr "E335: Valikkoa ei ole määritelty %s-tilassa" -#: ../menu.c:1447 -msgid "E337: Menu not found - check menu names" -msgstr "E337: Valikkoa ei löytynyt - tarkista valikkojen nimet" - -#: ../message.c:423 #, c-format msgid "Error detected while processing %s:" msgstr "Virhe suoritettaessa komentoja %s:" -#: ../message.c:445 #, c-format msgid "line %4ld:" msgstr "rivi %4ld:" -#: ../message.c:617 #, c-format msgid "E354: Invalid register name: '%s'" msgstr "E354: Virheellinen rekisterin nimi: %s" -#: ../message.c:986 msgid "Interrupt: " msgstr "Keskeytys: " -#: ../message.c:988 msgid "Press ENTER or type command to continue" -msgstr "Paina enteriä tai kirjoita komento aloittaaksesi " +msgstr "Paina enteriä tai kirjoita komento aloittaaksesi " -#: ../message.c:1843 -#, c-format -msgid "%s line %<PRId64>" -msgstr "%s rivi %<PRId64>" +#, fuzzy, c-format +#~ msgid "%s line %<PRId64>" +#~ msgstr "%s rivi %ld" -#: ../message.c:2392 msgid "-- More --" -msgstr "-- Lisää --" +msgstr "-- Lisää --" -#: ../message.c:2398 msgid " SPACE/d/j: screen/page/line down, b/u/k: up, q: quit " -msgstr " SPACE/d/j: ruutu/sivu/rivi alas, b/u/k: ylös, q: lopeta " +msgstr " SPACE/d/j: ruutu/sivu/rivi alas, b/u/k: ylös, q: lopeta " -#: ../message.c:3021 ../message.c:3031 msgid "Question" msgstr "Kysymys" -#: ../message.c:3023 msgid "" "&Yes\n" "&No" msgstr "" -"&Kyllä\n" +"&Kyllä\n" "&Ei" -#: ../message.c:3033 msgid "" "&Yes\n" "&No\n" "&Cancel" msgstr "" -"&Kyllä\n" +"&Kyllä\n" "&Ei\n" "&Peru" -#: ../message.c:3045 msgid "" "&Yes\n" "&No\n" @@ -4321,180 +3946,165 @@ msgid "" "&Discard All\n" "&Cancel" msgstr "" -"&Kyllä\n" +"&Kyllä\n" "&Ei\n" "&Tallenna kaikki\n" "T&uhoa kaikki\n" "&Peru" -#: ../message.c:3058 -msgid "E766: Insufficient arguments for printf()" -msgstr "E766: printf():lle ei annettu tarpeeksi argumentteja" - -#: ../message.c:3119 -msgid "E807: Expected Float argument for printf()" -msgstr "E807: Odotettiin Float-argumenttia printf():lle" - -#: ../message.c:3873 -msgid "E767: Too many arguments to printf()" -msgstr "E767: printf():lle annettiin liikaa argumentteja" - -#: ../misc1.c:2256 msgid "W10: Warning: Changing a readonly file" msgstr "W10: Varoitus: Muutetaan kirjoitussuojattua tiedostoa" -#: ../misc1.c:2537 msgid "Type number and <Enter> or click with mouse (empty cancels): " -msgstr "Kirjoita numero ja <Enter> tai valitse hiirellä (tyhjä peruu): " +msgstr "Kirjoita numero ja <Enter> tai valitse hiirellä (tyhjä peruu): " -#: ../misc1.c:2539 msgid "Type number and <Enter> (empty cancels): " -msgstr "Valitse numero ja <Enter> (tyhjä peruu): " +msgstr "Valitse numero ja <Enter> (tyhjä peruu): " -#: ../misc1.c:2585 msgid "1 more line" -msgstr "1 rivi lisää" +msgstr "1 rivi lisää" -#: ../misc1.c:2588 msgid "1 line less" -msgstr "1 rivi vähemmän" +msgstr "1 rivi vähemmän" -#: ../misc1.c:2593 -#, c-format -msgid "%<PRId64> more lines" -msgstr "%<PRId64> riviä lisää" +#, fuzzy, c-format +#~ msgid "%<PRId64> more lines" +#~ msgstr "%ld riviä lisää" -#: ../misc1.c:2596 -#, c-format -msgid "%<PRId64> fewer lines" -msgstr "%<PRId64> riviä vähemmän" +#, fuzzy, c-format +#~ msgid "%<PRId64> fewer lines" +#~ msgstr "%ld riviä vähemmän" -#: ../misc1.c:2599 msgid " (Interrupted)" msgstr " (Keskeytetty)" -#: ../misc1.c:2635 msgid "Beep!" msgstr "Piip!" -#: ../misc2.c:738 #, c-format msgid "Calling shell to execute: \"%s\"" msgstr "Kutsutaan kuorta suorittamaan: %s" -#: ../normal.c:183 +#, c-format +#~ msgid "Invalid channel: %<PRIu64>" +#~ msgstr "" + +#~ msgid "Message is not an array" +#~ msgstr "" + +#, fuzzy +#~ msgid "Message is empty" +#~ msgstr "Viesti" + +#~ msgid "Message type must be an integer" +#~ msgstr "" + +#, fuzzy +#~ msgid "Unknown message type" +#~ msgstr "E574: Tuntematon rekisterityyppi %d" + +#~ msgid "Request array size must be 4 (request) or 3 (notification)" +#~ msgstr "" + +#~ msgid "ID must be a positive integer" +#~ msgstr "" + +#~ msgid "Method must be a string" +#~ msgstr "" + +#, fuzzy +#~ msgid "Parameters must be an array" +#~ msgstr "merkin nimen pitää olla yksi merkki" + +#. +#. * nv_*(): functions called to handle Normal and Visual mode commands. +#. * n_*(): functions called to handle Normal mode commands. +#. * v_*(): functions called to handle Visual mode commands. +#. msgid "E349: No identifier under cursor" msgstr "E349: Ei tunnistetta osoittimen alla" -#: ../normal.c:1866 msgid "E774: 'operatorfunc' is empty" -msgstr "E774: operatorfunc on tyhjä" +msgstr "E774: operatorfunc on tyhjä" -#: ../normal.c:2637 msgid "Warning: terminal cannot highlight" msgstr "Varoitus: terminaalista puuttuu korostus" -#: ../normal.c:2807 msgid "E348: No string under cursor" msgstr "E348: Ei merkkijonoa kursorin alla" -#: ../normal.c:3937 msgid "E352: Cannot erase folds with current 'foldmethod'" -msgstr "E352: taitoksia ei voi poistaa tällä foldmethodilla" +msgstr "E352: taitoksia ei voi poistaa tällä foldmethodilla" -#: ../normal.c:5897 msgid "E664: changelist is empty" -msgstr "E664: muutoslista on tyhjä" +msgstr "E664: muutoslista on tyhjä" -#: ../normal.c:5899 msgid "E662: At start of changelist" msgstr "E662: Muutoslistan alussa" -#: ../normal.c:5901 msgid "E663: At end of changelist" msgstr "E663: Muutoslistan lopussa" -#: ../normal.c:7053 -msgid "Type :quit<Enter> to exit Nvim" -msgstr "Komento :quit<Enter> lopettaa Vimin" +#, fuzzy +#~ msgid "Type :quit<Enter> to exit Nvim" +#~ msgstr "Komento :quit<Enter> lopettaa Vimin" -#: ../ops.c:248 #, c-format msgid "1 line %sed 1 time" -msgstr "1 riviä %s kerran" +msgstr "1 riviä %s kerran" -#: ../ops.c:250 #, c-format msgid "1 line %sed %d times" -msgstr "1 riviä %s %d kertaa" +msgstr "1 riviä %s %d kertaa" -#: ../ops.c:253 -#, c-format -msgid "%<PRId64> lines %sed 1 time" -msgstr "%<PRId64> riviä %s kerran" +#, fuzzy, c-format +#~ msgid "%<PRId64> lines %sed 1 time" +#~ msgstr "%ld riviä %s kerran" -#: ../ops.c:256 -#, c-format -msgid "%<PRId64> lines %sed %d times" -msgstr "%<PRId64> riviä %s %d kertaa" +#, fuzzy, c-format +#~ msgid "%<PRId64> lines %sed %d times" +#~ msgstr "%ld riviä %s %d kertaa" -#: ../ops.c:592 -#, c-format -msgid "%<PRId64> lines to indent... " -msgstr "%<PRId64> riviä sisennettävänä..." +#, fuzzy, c-format +#~ msgid "%<PRId64> lines to indent... " +#~ msgstr "%ld riviä sisennettävänä..." -#: ../ops.c:634 msgid "1 line indented " msgstr "1 rivi sisennetty " -#: ../ops.c:636 -#, c-format -msgid "%<PRId64> lines indented " -msgstr "%<PRId64> riviä sisennetty " +#, fuzzy, c-format +#~ msgid "%<PRId64> lines indented " +#~ msgstr "%ld riviä sisennetty " -#: ../ops.c:938 msgid "E748: No previously used register" -msgstr "E748: Ei aiemmin käytettyjä rekisterejä" +msgstr "E748: Ei aiemmin käytettyjä rekisterejä" -#. must display the prompt -#: ../ops.c:1433 -msgid "cannot yank; delete anyway" -msgstr "Ei voi kopioida; poista joka tapauksessa" - -#: ../ops.c:1929 msgid "1 line changed" msgstr "1 rivi muuttui" -#: ../ops.c:1931 -#, c-format -msgid "%<PRId64> lines changed" -msgstr "%<PRId64> riviä muuttui" +#, fuzzy, c-format +#~ msgid "%<PRId64> lines changed" +#~ msgstr "%ld riviä muuttui" -#: ../ops.c:2521 msgid "block of 1 line yanked" msgstr "1 rivin lohko kopioitu" -#: ../ops.c:2523 msgid "1 line yanked" msgstr "1 rivi kopioitu" -#: ../ops.c:2525 -#, c-format -msgid "block of %<PRId64> lines yanked" -msgstr "lohko %<PRId64> riviltä kopioitu" +#, fuzzy, c-format +#~ msgid "block of %<PRId64> lines yanked" +#~ msgstr "lohko %ld riviltä kopioitu" -#: ../ops.c:2528 -#, c-format -msgid "%<PRId64> lines yanked" -msgstr "%<PRId64> riviä kopioitu" +#, fuzzy, c-format +#~ msgid "%<PRId64> lines yanked" +#~ msgstr "%ld riviä kopioitu" -#: ../ops.c:2710 #, c-format msgid "E353: Nothing in register %s" -msgstr "E353: Rekisterissä %s ei ole mitään" +msgstr "E353: Rekisterissä %s ei ole mitään" #. Highlight title -#: ../ops.c:3185 msgid "" "\n" "--- Registers ---" @@ -4502,207 +4112,142 @@ msgstr "" "\n" "--- Rekisterit ---" -#: ../ops.c:4455 -msgid "Illegal register name" -msgstr "Virheellinen rekisterin nimi" - -#: ../ops.c:4533 msgid "" -"\n" -"# Registers:\n" +"E883: search pattern and expression register may not contain two or more " +"lines" msgstr "" -"\n" -"# Rekisterit:\n" +"E883: hakulauseke- ja -ilmausrekisteri ei voi sisältää kahta tai useampaa " +"riviä" -#: ../ops.c:4575 -#, c-format -msgid "E574: Unknown register type %d" -msgstr "E574: Tuntematon rekisterityyppi %d" - -#: ../ops.c:5089 -#, c-format -msgid "%<PRId64> Cols; " -msgstr "%<PRId64> saraketta, " +#, fuzzy, c-format +#~ msgid "%<PRId64> Cols; " +#~ msgstr "%ld saraketta, " -#: ../ops.c:5097 -#, c-format +#, fuzzy, c-format msgid "" "Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " "%<PRId64> of %<PRId64> Bytes" -msgstr "" -"Valittu %s%<PRId64>/%<PRId64> riviä, %<PRId64>/%<PRId64> sanaa, %<PRId64>/" -"%<PRId64> tavua" +msgstr "Valittu %s%ld/%ld riviä, %lld/%lld sanaa, %lld/%lld tavua" -#: ../ops.c:5105 -#, c-format +#, fuzzy, c-format msgid "" "Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " "%<PRId64> of %<PRId64> Chars; %<PRId64> of %<PRId64> Bytes" msgstr "" -"Valittu %s%<PRId64>/%<PRId64> riviä, %<PRId64>/%<PRId64> sanaa, %<PRId64>/" -"%<PRId64> merkkiä, %<PRId64>/%<PRId64> tavua" +"Valittu %s%ld/%ld riviä, %lld/%lld sanaa, %lld/%lld merkkiä, %lld/%lld tavua" -#: ../ops.c:5123 -#, c-format +#, fuzzy, c-format msgid "" "Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Byte " "%<PRId64> of %<PRId64>" -msgstr "" -"Sarake %s/%s, Rivi %<PRId64>/%<PRId64>, sana %<PRId64>/%<PRId64>, tavu " -"%<PRId64>/%<PRId64>" +msgstr "Sarake %s/%s, Rivi %ld/%ld, sana %lld/%lld, tavu %lld/%lld" -#: ../ops.c:5133 -#, c-format +#, fuzzy, c-format msgid "" "Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Char " "%<PRId64> of %<PRId64>; Byte %<PRId64> of %<PRId64>" msgstr "" -"Sarake %s/%s, rivi %<PRId64>/%<PRId64>, sana %<PRId64>/%<PRId64>, merkki " -"%<PRId64>/%<PRId64>, tavu %<PRId64>/%<PRId64>" +"Sarake %s/%s, rivi %ld/%ld, sana %lld/%lld, merkki %lld/%lld, tavu %lld/%lld" # Unicode Byte Order Mark -#: ../ops.c:5146 -#, c-format -msgid "(+%<PRId64> for BOM)" -msgstr "(+%<PRId64> BOMista)" - -#: ../option.c:1238 -msgid "%<%f%h%m%=Page %N" -msgstr "%<%f%h%m%=Sivu %N" - -#: ../option.c:1574 -msgid "Thanks for flying Vim" -msgstr "Kiitos että ajoit Vimiä" +#, fuzzy, c-format +#~ msgid "(+%<PRId64> for BOM)" +#~ msgstr "(+%ld BOMista)" #. found a mismatch: skip -#: ../option.c:2698 msgid "E518: Unknown option" msgstr "E518: Tuntematon asetus" -#: ../option.c:2709 -msgid "E519: Option not supported" -msgstr "E519: Asetusta ei tueta" - -#: ../option.c:2740 msgid "E520: Not allowed in a modeline" -msgstr "E520: Ei sallitu modeline-rivillä" +msgstr "E520: Ei sallitu modeline-rivillä" -#: ../option.c:2815 msgid "E846: Key code not set" -msgstr "" +msgstr "E846: Avainkoodi puuttuu" -#: ../option.c:2924 msgid "E521: Number required after =" -msgstr "E521: =:n jälkeen tarvitaan luku" - -#: ../option.c:3226 ../option.c:3864 -msgid "E522: Not found in termcap" -msgstr "E522: Puuttuu termcapista" +msgstr "E521: =:n jälkeen tarvitaan luku" -#: ../option.c:3335 #, c-format msgid "E539: Illegal character <%s>" msgstr "E539: Virheellinen merkki <%s>" -#: ../option.c:3862 -msgid "E529: Cannot set 'term' to empty string" -msgstr "E529: Termiä ei voi asettaa tyhjäksi merkkijonoksi" +#, c-format +msgid "For option %s" +msgstr "Asetukselle %s" -#: ../option.c:3885 msgid "E589: 'backupext' and 'patchmode' are equal" msgstr "E589: backupext ja patchmod ovat samat" -#: ../option.c:3964 msgid "E834: Conflicts with value of 'listchars'" msgstr "E834: listcharsin arvoissa on ristiriitoja" -#: ../option.c:3966 msgid "E835: Conflicts with value of 'fillchars'" msgstr "E835: fillcharsin arvossa on ristiriitoja" -#: ../option.c:4163 msgid "E524: Missing colon" msgstr "E524: Kaksoispiste puuttuu" -#: ../option.c:4165 msgid "E525: Zero length string" msgstr "E525: Nollan pituinen merkkijono" -#: ../option.c:4220 #, c-format msgid "E526: Missing number after <%s>" -msgstr "E526: Lukuarvo puuttuu merkkijonon <%s> jälkeen" +msgstr "E526: Lukuarvo puuttuu merkkijonon <%s> jälkeen" -#: ../option.c:4232 msgid "E527: Missing comma" msgstr "E527: Pilkku puuttuu" -#: ../option.c:4239 msgid "E528: Must specify a ' value" -msgstr "E528: '-arvo pitää antaa" +msgstr "E528: '-arvo pitää antaa" -#: ../option.c:4271 msgid "E595: contains unprintable or wide character" -msgstr "E595: Sisältää tulostumattomia tai leveitä merkkejä" +msgstr "E595: Sisältää tulostumattomia tai leveitä merkkejä" -#: ../option.c:4469 #, c-format msgid "E535: Illegal character after <%c>" -msgstr "E535: Virheellinen merkki merkin <%c> jälkeen" +msgstr "E535: Virheellinen merkki merkin <%c> jälkeen" -#: ../option.c:4534 msgid "E536: comma required" msgstr "E536: pilkku puuttuu" -#: ../option.c:4543 #, c-format msgid "E537: 'commentstring' must be empty or contain %s" -msgstr "E537: commentstringin pitää olla tyhjä tai sisältää %s" +msgstr "E537: commentstringin pitää olla tyhjä tai sisältää %s" -#: ../option.c:4928 msgid "E540: Unclosed expression sequence" msgstr "E540: Sulkematon lausekesarja" -#: ../option.c:4932 msgid "E541: too many items" msgstr "E541: liikaa kohteita" -#: ../option.c:4934 msgid "E542: unbalanced groups" -msgstr "E542: epätasapainoisia ryhmiä" +msgstr "E542: epätasapainoisia ryhmiä" -#: ../option.c:5148 msgid "E590: A preview window already exists" msgstr "E590: Esikatseluikkuna on jo olemassa" -#: ../option.c:5311 msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'" -msgstr "W17: Arabialle pitää olla UTF-8:aa, aseta :set encoding=utf-8" +msgstr "W17: Arabialle pitää olla UTF-8:aa, aseta :set encoding=utf-8" -#: ../option.c:5623 #, c-format msgid "E593: Need at least %d lines" -msgstr "E593: Tarvitaan ainakin %d riviä" +msgstr "E593: Tarvitaan ainakin %d riviä" -#: ../option.c:5631 #, c-format msgid "E594: Need at least %d columns" msgstr "E594: Tarvitaan ainakin %d saraketta" -#: ../option.c:6011 #, c-format msgid "E355: Unknown option: %s" msgstr "E355: Tuntematon asetus: %s" #. 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. -#: ../option.c:6037 +#. is empty. In both cases, we are trying to set a +#. num option using a string. #, c-format msgid "E521: Number required: &%s = '%s'" msgstr "E521: tarvitaan luku: &%s = '%s'" -#: ../option.c:6149 msgid "" "\n" "--- Terminal codes ---" @@ -4710,7 +4255,6 @@ msgstr "" "\n" "--- Terminaalikoodit ---" -#: ../option.c:6151 msgid "" "\n" "--- Global option values ---" @@ -4718,7 +4262,6 @@ msgstr "" "\n" "--- Globaalit asetukset ---" -#: ../option.c:6153 msgid "" "\n" "--- Local option values ---" @@ -4726,7 +4269,6 @@ msgstr "" "\n" "--- Paikalliset asetukset ---" -#: ../option.c:6155 msgid "" "\n" "--- Options ---" @@ -4734,29 +4276,24 @@ msgstr "" "\n" "--- Asetukset ---" -#: ../option.c:6816 msgid "E356: get_varp ERROR" msgstr "E356: get_varp-virhe" -#: ../option.c:7696 #, c-format msgid "E357: 'langmap': Matching character missing for %s" -msgstr "E357: langmap: Merkkiin %s täsmäävä merkki puuttuu" +msgstr "E357: langmap: Merkkiin %s täsmäävä merkki puuttuu" -#: ../option.c:7715 #, c-format msgid "E358: 'langmap': Extra characters after semicolon: %s" -msgstr "E358: langmap: ylimääräisiä merkkejä puolipisteen jälkeen: %s" +msgstr "E358: langmap: ylimääräisiä merkkejä puolipisteen jälkeen: %s" -#: ../os/shell.c:194 -msgid "" -"\n" -"Cannot execute shell " -msgstr "" -"\n" -"Kuoren suoritus ei onnistu " +#, c-format +msgid "dlerror = \"%s\"" +msgstr "dlerror = %s" + +msgid "Vim: Error reading input, exiting...\n" +msgstr "Vim: Virhe luettaessa syötettä, poistutaan...\n" -#: ../os/shell.c:439 msgid "" "\n" "shell returned " @@ -4764,8 +4301,18 @@ msgstr "" "\n" "kuoren palautusarvo " -# mikä security context? -#: ../os_unix.c:465 ../os_unix.c:471 +#~ msgid "" +#~ "\n" +#~ "shell failed to start: " +#~ msgstr "" + +#. Can happen if system() tries to send input to a shell command that was +#. backgrounded (:call system("cat - &", "foo")). #3529 #5241 +#, fuzzy, c-format +#~ msgid "E5677: Error writing input to shell-command: %s" +#~ msgstr "E677: Väliaikaistiedostoon kirjoittaminen ei onnistunut" + +# mikä security context? msgid "" "\n" "Could not get security context for " @@ -4773,7 +4320,6 @@ msgstr "" "\n" "Ei saatu turvallisuuskontekstia kohteelle " -#: ../os_unix.c:479 msgid "" "\n" "Could not set security context for " @@ -4781,947 +4327,897 @@ msgstr "" "\n" "Ei voitu asettaa turvallisuuskontekstia kohteelle " -#: ../os_unix.c:1558 ../os_unix.c:1647 -#, c-format -msgid "dlerror = \"%s\"" -msgstr "dlerror = %s" - -#: ../path.c:1449 #, c-format msgid "E447: Can't find file \"%s\" in path" -msgstr "E447: Tiedosto %s ei löydy polulta" +msgstr "E447: Tiedosto %s ei löydy polulta" -#: ../quickfix.c:359 #, c-format msgid "E372: Too many %%%c in format string" msgstr "E372: Liikaa %%%c-juttuja muotoilumerkkijonossa" -#: ../quickfix.c:371 #, c-format msgid "E373: Unexpected %%%c in format string" msgstr "E373: Odottamaton %%%c muotoilumerkkijonossa" -#: ../quickfix.c:420 msgid "E374: Missing ] in format string" msgstr "E374: ] puuttuu muotoilemerkkijonosta" -#: ../quickfix.c:431 #, c-format msgid "E375: Unsupported %%%c in format string" msgstr "E375: Tukematon %%%c muotoilumerkkijonossa" -#: ../quickfix.c:448 #, c-format msgid "E376: Invalid %%%c in format string prefix" msgstr "E376: Virheellinen %%%c muotoilumerkkijonon alussa" -#: ../quickfix.c:454 #, c-format msgid "E377: Invalid %%%c in format string" msgstr "E377: Virheellinen %%%c muotoilumerkkijonossa" #. nothing found -#: ../quickfix.c:477 msgid "E378: 'errorformat' contains no pattern" msgstr "E378: errorformatissa ei ole kuvioita" -#: ../quickfix.c:695 msgid "E379: Missing or empty directory name" -msgstr "E379: Puuttuva tai tyhjä hakemiston nimi" +msgstr "E379: Puuttuva tai tyhjä hakemiston nimi" -#: ../quickfix.c:1305 msgid "E553: No more items" -msgstr "E553: Ei enää kohteita" +msgstr "E553: Ei enää kohteita" + +msgid "E924: Current window was closed" +msgstr "E924: Nykyinen ikkuna on suljettu" + +msgid "E925: Current quickfix was changed" +msgstr "E925: Nykyinen quickfix on muuttunut" + +msgid "E926: Current location list was changed" +msgstr "E926: Nykyinen sijaintiluettelo on muuttunut" -#: ../quickfix.c:1674 #, c-format msgid "(%d of %d)%s%s: " msgstr "(%d/%d)%s%s: " -#: ../quickfix.c:1676 msgid " (line deleted)" msgstr " (rivi poistettu)" -#: ../quickfix.c:1863 +#, c-format +msgid "%serror list %d of %d; %d errors " +msgstr "%svirhelista %d/%d, %d virhettä" + msgid "E380: At bottom of quickfix stack" msgstr "E380: quickfix-pinon pohjalla" -#: ../quickfix.c:1869 msgid "E381: At top of quickfix stack" msgstr "E381: quickfix-pinon huipulla" -#: ../quickfix.c:1880 -#, c-format -msgid "error list %d of %d; %d errors" -msgstr "virhelista %d/%d, %d virhettä" +msgid "No entries" +msgstr "Ei kenttiä" -#: ../quickfix.c:2427 msgid "E382: Cannot write, 'buftype' option is set" msgstr "E382: Ei voi kirjoittaa, buftype asetettu" -#: ../quickfix.c:2812 msgid "E683: File name missing or invalid pattern" msgstr "E683: Tiedostonimi puuttuu tai kuvio on viallinen" -#: ../quickfix.c:2911 #, c-format msgid "Cannot open file \"%s\"" msgstr "Tiedostoa %s ei voi avata" -#: ../quickfix.c:3429 msgid "E681: Buffer is not loaded" msgstr "E681: Puskuria ei ole ladattu" -#: ../quickfix.c:3487 msgid "E777: String or List expected" -msgstr "E777: Pitää olla merkkijono tai lista" +msgstr "E777: Pitää olla merkkijono tai lista" -#: ../regexp.c:359 #, c-format msgid "E369: invalid item in %s%%[]" msgstr "E369: virheellinen olio kohdassa %s%%[]" -#: ../regexp.c:374 #, c-format msgid "E769: Missing ] after %s[" -msgstr "E769: ] puuttuu merkinnän %s[ jäljestä" +msgstr "E769: ] puuttuu merkinnän %s[ jäljestä" -#: ../regexp.c:375 #, c-format msgid "E53: Unmatched %s%%(" msgstr "E53: Pariton %s%%(" -#: ../regexp.c:376 #, c-format msgid "E54: Unmatched %s(" msgstr "E54: Pariton %s(" -#: ../regexp.c:377 #, c-format msgid "E55: Unmatched %s)" msgstr "E55: Pariton %s)" -#: ../regexp.c:378 msgid "E66: \\z( not allowed here" -msgstr "E66: \\z( ei ole sallittu tässä" +msgstr "E66: \\z( ei ole sallittu tässä" -#: ../regexp.c:379 msgid "E67: \\z1 et al. not allowed here" -msgstr "E67: \\z1 jne. ei ole sallittu tässä" +msgstr "E67: \\z1 jne. ei ole sallittu tässä" -#: ../regexp.c:380 #, c-format msgid "E69: Missing ] after %s%%[" -msgstr "E69: ] puuttuu merkinnän %s%%[ jäljestä" +msgstr "E69: ] puuttuu merkinnän %s%%[ jäljestä" -#: ../regexp.c:381 #, c-format msgid "E70: Empty %s%%[]" -msgstr "E70: Tyhjä %s%%[]" +msgstr "E70: Tyhjä %s%%[]" -#: ../regexp.c:1209 ../regexp.c:1224 msgid "E339: Pattern too long" -msgstr "E339: Liian pitkä kuvio" +msgstr "E339: Liian pitkä kuvio" -#: ../regexp.c:1371 msgid "E50: Too many \\z(" -msgstr "E50: Liikaa merkkejä \\z(" +msgstr "E50: Liikaa merkkejä \\z(" -#: ../regexp.c:1378 #, c-format msgid "E51: Too many %s(" -msgstr "E51: Liikaa merkkejä %s(" +msgstr "E51: Liikaa merkkejä %s(" -#: ../regexp.c:1427 msgid "E52: Unmatched \\z(" msgstr "E52: Pariton \\z(" -#: ../regexp.c:1637 #, c-format msgid "E59: invalid character after %s@" -msgstr "E59: virheellinen merkki kohdan %s@ jälkeen" +msgstr "E59: virheellinen merkki kohdan %s@ jälkeen" -#: ../regexp.c:1672 #, c-format msgid "E60: Too many complex %s{...}s" msgstr "E60: Liikaa monimutkaisia ilmauksia %s{...}s" -#: ../regexp.c:1687 #, c-format msgid "E61: Nested %s*" -msgstr "E61: Sisäkkäistetty %s*" +msgstr "E61: Sisäkkäistetty %s*" -#: ../regexp.c:1690 #, c-format msgid "E62: Nested %s%c" -msgstr "E62: Sisäkkäistetty %s%c" +msgstr "E62: Sisäkkäistetty %s%c" -#: ../regexp.c:1800 msgid "E63: invalid use of \\_" -msgstr "E63: väärinkäytetty \\_" +msgstr "E63: väärinkäytetty \\_" -#: ../regexp.c:1850 #, c-format msgid "E64: %s%c follows nothing" -msgstr "E64: %s%c jälkeen ei minkään" +msgstr "E64: %s%c jälkeen ei minkään" -#: ../regexp.c:1902 msgid "E65: Illegal back reference" -msgstr "E65: Virheellinen täsmäysviittaus" +msgstr "E65: Virheellinen täsmäysviittaus" -#: ../regexp.c:1943 msgid "E68: Invalid character after \\z" -msgstr "E68: Virheellinen merkki ilmauksen \\z jälkeen" +msgstr "E68: Virheellinen merkki ilmauksen \\z jälkeen" -#: ../regexp.c:2049 ../regexp_nfa.c:1296 #, c-format msgid "E678: Invalid character after %s%%[dxouU]" -msgstr "E678: Virheellinen merkki merkinnän %s%%[dxouU] jäljessä" +msgstr "E678: Virheellinen merkki merkinnän %s%%[dxouU] jäljessä" -#: ../regexp.c:2107 #, c-format msgid "E71: Invalid character after %s%%" -msgstr "E71: Virheellinen merkki merkinnän %s%% jäljessä" +msgstr "E71: Virheellinen merkki merkinnän %s%% jäljessä" + +#, c-format +msgid "E888: (NFA regexp) cannot repeat %s" +msgstr "E888: (NFA-säänn. ilmaus) ei voi toistaa kohdetta %s" -#: ../regexp.c:3017 #, c-format msgid "E554: Syntax error in %s{...}" msgstr "E554: Syntaksivirhe ilmauksessa %s{...}" -#: ../regexp.c:3805 msgid "External submatches:\n" -msgstr "Ulkoisia alitäsmäyksiä:\n" +msgstr "Ulkoisia alitäsmäyksiä:\n" -#: ../regexp.c:7022 msgid "" "E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be " "used " msgstr "" +"E864: \\%#=-merkkien perään voi tulla vain 0, 1 tai 2. Käytetään " +"automaattista engineä " -#: ../regexp_nfa.c:239 -msgid "E865: (NFA) Regexp end encountered prematurely" -msgstr "" - -#: ../regexp_nfa.c:240 -#, c-format -msgid "E866: (NFA regexp) Misplaced %c" -msgstr "" - -#: ../regexp_nfa.c:242 -#, c-format -msgid "E877: (NFA regexp) Invalid character class: %<PRId64>" -msgstr "" - -#: ../regexp_nfa.c:1261 -#, c-format -msgid "E867: (NFA) Unknown operator '\\z%c'" -msgstr "" - -#: ../regexp_nfa.c:1387 -#, c-format -msgid "E867: (NFA) Unknown operator '\\%%%c'" -msgstr "" - -#: ../regexp_nfa.c:1802 -#, c-format -msgid "E869: (NFA) Unknown operator '\\@%c'" -msgstr "" - -#: ../regexp_nfa.c:1831 -msgid "E870: (NFA regexp) Error reading repetition limits" -msgstr "" - -#. Can't have a multi follow a multi. -#: ../regexp_nfa.c:1895 -msgid "E871: (NFA regexp) Can't have a multi follow a multi !" -msgstr "" - -#. Too many `(' -#: ../regexp_nfa.c:2037 -msgid "E872: (NFA regexp) Too many '('" -msgstr "" - -#: ../regexp_nfa.c:2042 -#, fuzzy -msgid "E879: (NFA regexp) Too many \\z(" -msgstr "E50: Liikaa merkkejä \\z(" - -#: ../regexp_nfa.c:2066 -msgid "E873: (NFA regexp) proper termination error" -msgstr "" - -#: ../regexp_nfa.c:2599 -msgid "E874: (NFA) Could not pop the stack !" -msgstr "" - -#: ../regexp_nfa.c:3298 -msgid "" -"E875: (NFA regexp) (While converting from postfix to NFA), too many states " -"left on stack" -msgstr "" - -#: ../regexp_nfa.c:3302 -msgid "E876: (NFA regexp) Not enough space to store the whole NFA " -msgstr "" - -#: ../regexp_nfa.c:4571 ../regexp_nfa.c:4869 -msgid "" -"Could not open temporary log file for writing, displaying on stderr ... " -msgstr "" +msgid "Switching to backtracking RE engine for pattern: " +msgstr "Vaihdetaan käyttämään backtrackkaavaa RE-engineä ilmaukselle: " -#: ../regexp_nfa.c:4840 -#, c-format -msgid "(NFA) COULD NOT OPEN %s !" -msgstr "" - -#: ../regexp_nfa.c:6049 -#, fuzzy -msgid "Could not open temporary log file for writing " -msgstr "E828: Kumoustiedoston avaus kirjoittamista varten ei onnistu: %s" +#~ msgid " TERMINAL" +#~ msgstr "" # tiloja -#: ../screen.c:7435 msgid " VREPLACE" msgstr " VKORVAUS" -#: ../screen.c:7437 msgid " REPLACE" msgstr " KORVAUS" -#: ../screen.c:7440 msgid " REVERSE" -msgstr " KÄÄNTEIS" +msgstr " KÄÄNTEIS" -#: ../screen.c:7441 msgid " INSERT" -msgstr " SYÖTTÖ" +msgstr " SYÖTTÖ" -#: ../screen.c:7443 msgid " (insert)" -msgstr " (syöttö)" +msgstr " (syöttö)" -#: ../screen.c:7445 msgid " (replace)" msgstr " (korvaus)" -#: ../screen.c:7447 msgid " (vreplace)" msgstr " (vkorvaus)" -#: ../screen.c:7449 msgid " Hebrew" msgstr " Heprea" -#: ../screen.c:7454 msgid " Arabic" msgstr " Arabia" -#: ../screen.c:7456 -msgid " (lang)" -msgstr " (kieli)" - -#: ../screen.c:7459 msgid " (paste)" msgstr " (liitos)" -#: ../screen.c:7469 msgid " VISUAL" msgstr " VALINTA" -#: ../screen.c:7470 msgid " VISUAL LINE" msgstr " VALINTARIVI" -#: ../screen.c:7471 msgid " VISUAL BLOCK" msgstr " VALINTALOHKO" -#: ../screen.c:7472 msgid " SELECT" msgstr " WALINTA" -#: ../screen.c:7473 msgid " SELECT LINE" msgstr " WALINTARIVI" -#: ../screen.c:7474 msgid " SELECT BLOCK" msgstr " WALINTALOHKO" -#: ../screen.c:7486 ../screen.c:7541 msgid "recording" msgstr "tallennetaan" -#: ../search.c:487 #, c-format msgid "E383: Invalid search string: %s" msgstr "E383: Viallinen hakujono: %s" -#: ../search.c:832 #, c-format msgid "E384: search hit TOP without match for: %s" -msgstr "E384: Haku pääsi alkuun löytämättä jonoa: %s" +msgstr "E384: Haku pääsi alkuun löytämättä jonoa: %s" -#: ../search.c:835 #, c-format msgid "E385: search hit BOTTOM without match for: %s" -msgstr "E385: Haku pääsi loppuun löytämättä jonoa: %s" +msgstr "E385: Haku pääsi loppuun löytämättä jonoa: %s" -#: ../search.c:1200 msgid "E386: Expected '?' or '/' after ';'" -msgstr "E386: ;:n jälkeen pitää olla ? tai /" +msgstr "E386: ;:n jälkeen pitää olla ? tai /" -#: ../search.c:4085 msgid " (includes previously listed match)" -msgstr " (sisältää viimeksi luetellun täsmäyksen)" +msgstr " (sisältää viimeksi luetellun täsmäyksen)" #. cursor at status line -#: ../search.c:4104 msgid "--- Included files " -msgstr "--- Sisällytetyt tiedostot " +msgstr "--- Sisällytetyt tiedostot " -#: ../search.c:4106 msgid "not found " -msgstr "ei löytynyt " +msgstr "ei löytynyt " -#: ../search.c:4107 msgid "in path ---\n" msgstr "polusta ---\n" -#: ../search.c:4168 msgid " (Already listed)" msgstr " (Jo lueteltu)" -#: ../search.c:4170 msgid " NOT FOUND" -msgstr " EI LÖYTYNYT" +msgstr " EI LÖYTYNYT" -#: ../search.c:4211 #, c-format msgid "Scanning included file: %s" -msgstr "Haku sisälsi tiedoston: %s" +msgstr "Haku sisälsi tiedoston: %s" -#: ../search.c:4216 #, c-format msgid "Searching included file %s" -msgstr "Haku sisälsi tiedoston %s" +msgstr "Haku sisälsi tiedoston %s" -#: ../search.c:4405 msgid "E387: Match is on current line" -msgstr "E387: Täsmäys tällä rivillä" +msgstr "E387: Täsmäys tällä rivillä" -#: ../search.c:4517 msgid "All included files were found" -msgstr "Kaikki sisällytetyt rivit löytyivät" +msgstr "Kaikki sisällytetyt rivit löytyivät" -#: ../search.c:4519 msgid "No included files" -msgstr "Ei sisällytettyjä tiedostoja" +msgstr "Ei sisällytettyjä tiedostoja" -#: ../search.c:4527 msgid "E388: Couldn't find definition" -msgstr "E388: Määritelmä ei löydy" +msgstr "E388: Määritelmä ei löydy" -#: ../search.c:4529 msgid "E389: Couldn't find pattern" -msgstr "E389: kuvio ei löydy" +msgstr "E389: kuvio ei löydy" + +#~ msgid "too few bytes read" +#~ msgstr "" -#: ../search.c:4668 -msgid "Substitute " -msgstr "Korvaa " +#, fuzzy, c-format +#~ msgid "System error while skipping in ShaDa file: %s" +#~ msgstr "E782: virhe luettaessa .sug-tiedostoa: %s" -#: ../search.c:4681 #, c-format -msgid "" -"\n" -"# Last %sSearch Pattern:\n" -"~" -msgstr "" -"\n" -"# Edellinen %sHakulauseke:\n" -"~" +#~ msgid "" +#~ "Error while reading ShaDa file: last entry specified that it occupies " +#~ "%<PRIu64> bytes, but file ended earlier" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "System error while closing ShaDa file: %s" +#~ msgstr "E782: virhe luettaessa .sug-tiedostoa: %s" + +#, fuzzy, c-format +#~ msgid "System error while writing ShaDa file: %s" +#~ msgstr "E782: virhe luettaessa .sug-tiedostoa: %s" + +#, fuzzy, c-format +#~ msgid "Reading ShaDa file \"%s\"%s%s%s" +#~ msgstr "Luetaan viminfo-tiedostoa \"%s\"%s%s%s" + +msgid " info" +msgstr " info" + +msgid " marks" +msgstr " merkit" + +msgid " oldfiles" +msgstr " vanhaatiedostoa" + +msgid " FAILED" +msgstr " EPÄONNISTUI" + +#, c-format +#~ msgid "System error while opening ShaDa file %s for reading: %s" +#~ msgstr "" + +#~ msgid "additional elements of ShaDa " +#~ msgstr "" + +#~ msgid "additional data of ShaDa " +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "Failed to write variable %s" +#~ msgstr "ei voitu vaihtaa puskuriin %d" + +#, c-format +#~ msgid "" +#~ "Failed to parse ShaDa file due to a msgpack parser error at position " +#~ "%<PRIu64>" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "Failed to parse ShaDa file: incomplete msgpack string at position %<PRIu64>" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "Failed to parse ShaDa file: extra bytes in msgpack string at position " +#~ "%<PRIu64>" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "System error while opening ShaDa file %s for reading to merge before writing " +#~ "it: %s" +#~ msgstr "" + +#. Tried names from .tmp.a to .tmp.z, all failed. Something must be +#. wrong then. +#, c-format +#~ msgid "E138: All %s.tmp.X files exist, cannot write ShaDa file!" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "System error while opening temporary ShaDa file %s for writing: %s" +#~ msgstr "Väliaikaislokitiedoston avaus kirjoittamista varten ei onnistu" + +#, c-format +#~ msgid "Failed to create directory %s for writing ShaDa file: %s" +#~ msgstr "" + +#, c-format +#~ msgid "System error while opening ShaDa file %s for writing: %s" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "Writing ShaDa file \"%s\"" +#~ msgstr "Kirjoitetaan viminfo-tiedostoa %s" + +#, fuzzy, c-format +#~ msgid "Failed setting uid and gid for file %s: %s" +#~ msgstr "Ladattu kumoustiedoto %s" + +#, fuzzy, c-format +#~ msgid "E137: ShaDa file is not writable: %s" +#~ msgstr "E137: Viminfo-tiedostoon ei voitu kirjoittaa: %s" + +#, fuzzy, c-format +#~ msgid "Can't rename ShaDa file from %s to %s!" +#~ msgstr "E886: Viminfo-tiedostoa ei voit uudelleennimetä nimelle %s" + +#, fuzzy, c-format +#~ msgid "Did not rename %s because %s does not looks like a ShaDa file" +#~ msgstr " [ei näytä Vimin swap-tiedostolta]" + +#, c-format +#~ msgid "Did not rename %s to %s because there were errors during writing it" +#~ msgstr "" + +#, c-format +#~ msgid "Do not forget to remove %s or rename it manually to %s." +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "System error while reading ShaDa file: %s" +#~ msgstr "E782: virhe luettaessa .sug-tiedostoa: %s" + +#, fuzzy, c-format +#~ msgid "System error while reading integer from ShaDa file: %s" +#~ msgstr "E782: virhe luettaessa .sug-tiedostoa: %s" + +#, c-format +#~ msgid "" +#~ "Error while reading ShaDa file: expected positive integer at position " +#~ "%<PRIu64>, but got nothing" +#~ msgstr "" -#: ../spell.c:951 -msgid "E759: Format error in spell file" -msgstr "E759: Muotoiluvirhe oikolukutiedostossa" +#, c-format +#~ msgid "" +#~ "Error while reading ShaDa file: expected positive integer at position " +#~ "%<PRIu64>" +#~ msgstr "" + +#. kSDItemUnknown cannot possibly pass that far because it is -1 and that +#. will fail in msgpack_read_uint64. But kSDItemMissing may and it will +#. otherwise be skipped because (1 << 0) will never appear in flags. +#, c-format +#~ msgid "" +#~ "Error while reading ShaDa file: there is an item at position %<PRIu64> that " +#~ "must not be there: Missing items are for internal uses only" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "Error while reading ShaDa file: buffer list at position %<PRIu64> contains " +#~ "entry that is not a dictionary" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "Error while reading ShaDa file: buffer list at position %<PRIu64> contains " +#~ "entry with invalid line number" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "Error while reading ShaDa file: buffer list at position %<PRIu64> contains " +#~ "entry with invalid column number" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "Error while reading ShaDa file: buffer list at position %<PRIu64> contains " +#~ "entry that does not have a file name" +#~ msgstr "" + +#. values for ts_isdiff +#. no different byte (yet) +#. different byte found +#. inserting character +#. values for ts_flags +#. already checked that prefix is OK +#. tried split at this point +#. did a delete, "ts_delidx" has index +#. special values ts_prefixdepth +#. not using prefixes +#. walking through the prefix tree +#. highest value that's not special +#. mode values for find_word +#. find word case-folded +#. find keep-case word +#. find word after prefix +#. find case-folded compound word +#. find keep-case compound word +#, fuzzy +#~ msgid "E759: Format error in spell file" +#~ msgstr "E297: Kirjoitusvirhe swap-tiedostossa" + +msgid "E756: Spell checking is not enabled" +msgstr "E756: Oikaisuluku ei ole päällä" + +#, c-format +msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" +msgstr "Varoitus: Ei löydetty sanalistaa %s.%s.spl tai %s.ascii.spl" + +#. This is probably an error. Give a warning and +#. accept the words anyway. +#, c-format +msgid "Warning: region %s not supported" +msgstr "Varoitus: osaa %s ei tueta" + +msgid "Sorry, no suggestions" +msgstr "ei ehdotuksia" + +#, fuzzy, c-format +#~ msgid "Sorry, only %<PRId64> suggestions" +#~ msgstr "vain %ld ehdotusta" + +#. for when 'cmdheight' > 1 +#. avoid more prompt +#, c-format +msgid "Change \"%.*s\" to:" +msgstr "Muuta %.*s:" + +#, c-format +msgid " < \"%.*s\"" +msgstr " < %.*s" + +msgid "E752: No previous spell replacement" +msgstr "E752: Ei edellistä oikaisulukukorjausta" + +#, c-format +msgid "E753: Not found: %s" +msgstr "E753: Ei löytynyt: %s" -#: ../spell.c:952 msgid "E758: Truncated spell file" msgstr "E758: Oikolukutiedosto katkaistu" -#: ../spell.c:953 #, c-format msgid "Trailing text in %s line %d: %s" -msgstr "Tekstiä rivin perässä tiedostossa %s rivillä %d: %s" +msgstr "Tekstiä rivin perässä tiedostossa %s rivillä %d: %s" -#: ../spell.c:954 #, c-format msgid "Affix name too long in %s line %d: %s" -msgstr "Affiksin nimi on liian pitkä tiedostossa %s rivillä %d: %s" +msgstr "Affiksin nimi on liian pitkä tiedostossa %s rivillä %d: %s" -#: ../spell.c:955 msgid "E761: Format error in affix file FOL, LOW or UPP" msgstr "E761: Affiksitiedoston FOL-, LOW- tai UPP-muotovirhe " -#: ../spell.c:957 msgid "E762: Character in FOL, LOW or UPP is out of range" -msgstr "E762: Merkki FOL:ssä, LOW:ssä tai UPP:ssä ei kuulu arvoalueeseen" +msgstr "E762: Merkki FOL:ssä, LOW:ssä tai UPP:ssä ei kuulu arvoalueeseen" -#: ../spell.c:958 msgid "Compressing word tree..." -msgstr "Tiivistetään sanapuuta..." - -#: ../spell.c:1951 -msgid "E756: Spell checking is not enabled" -msgstr "E756: Oikaisuluku ei ole päällä" - -#: ../spell.c:2249 -#, c-format -msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" -msgstr "Varoitus: Ei löydetty sanalistaa %s.%s.spl tai %s.ascii.spl" +msgstr "Tiivistetään sanapuuta..." -#: ../spell.c:2473 #, c-format msgid "Reading spell file \"%s\"" msgstr "Luetaan oikaisulukutiedosta %s" -#: ../spell.c:2496 msgid "E757: This does not look like a spell file" msgstr "E757: Ei vaikuta oikaisulukutiedostolta" -#: ../spell.c:2501 +#, fuzzy, c-format +#~ msgid "E5042: Failed to read spell file %s: %s" +#~ msgstr "E482: Tiedostoa %s ei voi luoda" + msgid "E771: Old spell file, needs to be updated" -msgstr "E771: Vanha oikaisulukutiedosto vaatii päivittämistä" +msgstr "E771: Vanha oikaisulukutiedosto vaatii päivittämistä" -#: ../spell.c:2504 msgid "E772: Spell file is for newer version of Vim" msgstr "E772: Oikaisulukutiedosto on uudemmalle Vimille" -#: ../spell.c:2602 msgid "E770: Unsupported section in spell file" msgstr "E770: Tukematon osio oikaisulukutiedostossa" -#: ../spell.c:3762 #, c-format -msgid "Warning: region %s not supported" -msgstr "Varoitus: osaa %s ei tueta" +msgid "E778: This does not look like a .sug file: %s" +msgstr "E778: Ei vaikuta .sug-tiedostolta: %s" + +#, c-format +msgid "E779: Old .sug file, needs to be updated: %s" +msgstr "E779: Vanha .sug-tiedosto pitää päivittää: %s" + +#, c-format +msgid "E780: .sug file is for newer version of Vim: %s" +msgstr "E780: .sug-tiedosto on uudemmalle Vimille: %s" + +#, c-format +msgid "E781: .sug file doesn't match .spl file: %s" +msgstr "E781: .sug-tiedosto ei täsmää .spl-tiedostoon: %s" + +#, c-format +msgid "E782: error while reading .sug file: %s" +msgstr "E782: virhe luettaessa .sug-tiedostoa: %s" -#: ../spell.c:4550 #, c-format msgid "Reading affix file %s ..." msgstr "Luetaan affiksitiedostoa %s..." -#: ../spell.c:4589 ../spell.c:5635 ../spell.c:6140 #, c-format msgid "Conversion failure for word in %s line %d: %s" -msgstr "Muunnosvirhe sanalle %s rivillä %d: %s" +msgstr "Muunnosvirhe sanalle %s rivillä %d: %s" -#: ../spell.c:4630 ../spell.c:6170 #, c-format msgid "Conversion in %s not supported: from %s to %s" msgstr "Muunnosta kohteessa %s ei tueta: kohteesta %s kohteeseen %s" -#: ../spell.c:4642 #, c-format msgid "Invalid value for FLAG in %s line %d: %s" -msgstr "Tuntematon FLAG kohteessa %s rivillä %d: %s" +msgstr "Tuntematon FLAG kohteessa %s rivillä %d: %s" -#: ../spell.c:4655 #, c-format msgid "FLAG after using flags in %s line %d: %s" -msgstr "FLAG kohteessa %s lippujen jälkeen rivillä %d: %s" +msgstr "FLAG kohteessa %s lippujen jälkeen rivillä %d: %s" -#: ../spell.c:4723 #, c-format msgid "" "Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line " "%d" msgstr "" -"COMPOUNDFORBIDFLAG PFX:n jälkeen voi antaa vääriä tuloksia kohteessa %s " -"rivillä %d" +"COMPOUNDFORBIDFLAG PFX:n jälkeen voi antaa vääriä tuloksia kohteessa %s " +"rivillä %d" -#: ../spell.c:4731 #, c-format msgid "" "Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line " "%d" msgstr "" -"COMPOUNDPERMITFLAG PFX:n jälkeen voi antaa vääriä tuloksia kohteessa %s " -"rivillä %d" +"COMPOUNDPERMITFLAG PFX:n jälkeen voi antaa vääriä tuloksia kohteessa %s " +"rivillä %d" -#: ../spell.c:4747 #, c-format msgid "Wrong COMPOUNDRULES value in %s line %d: %s" -msgstr "Väärä COMPOUNDRULES-arvo kohteessa %s rivillä %d: %s" +msgstr "Väärä COMPOUNDRULES-arvo kohteessa %s rivillä %d: %s" -#: ../spell.c:4771 #, c-format msgid "Wrong COMPOUNDWORDMAX value in %s line %d: %s" -msgstr "Väärä COMPOUNDWORDMAX-arvo kohteessa %s rivillä %d: %s" +msgstr "Väärä COMPOUNDWORDMAX-arvo kohteessa %s rivillä %d: %s" -#: ../spell.c:4777 #, c-format msgid "Wrong COMPOUNDMIN value in %s line %d: %s" -msgstr "Väärä COMPOUNDMIN-arvo kohteessa %s rivillä %d: %s" +msgstr "Väärä COMPOUNDMIN-arvo kohteessa %s rivillä %d: %s" -#: ../spell.c:4783 #, c-format msgid "Wrong COMPOUNDSYLMAX value in %s line %d: %s" -msgstr "Väärä COMPOUNDSYLMAX-arvo kohteessa %s rivillä %d: %s" +msgstr "Väärä COMPOUNDSYLMAX-arvo kohteessa %s rivillä %d: %s" -#: ../spell.c:4795 #, c-format msgid "Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s" -msgstr "Väärä CHECKCOMPOUNDPATTERN-arvo kohteessa %s rivillä %d: %s" +msgstr "Väärä CHECKCOMPOUNDPATTERN-arvo kohteessa %s rivillä %d: %s" -#: ../spell.c:4847 #, c-format msgid "Different combining flag in continued affix block in %s line %d: %s" msgstr "" -"Eri yhdistelmälippu jatketussa affiksilohkossa kohteessa %s rivillä %d: %s" +"Eri yhdistelmälippu jatketussa affiksilohkossa kohteessa %s rivillä %d: %s" -#: ../spell.c:4850 #, c-format msgid "Duplicate affix in %s line %d: %s" -msgstr "Kaksoiskappale affiksista kohteessa %s rivillä %d: %s" +msgstr "Kaksoiskappale affiksista kohteessa %s rivillä %d: %s" -#: ../spell.c:4871 -#, c-format +#, fuzzy, c-format msgid "" -"Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in %s " +"Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGESTin %s " "line %d: %s" msgstr "" -"Affiksia käytetty myös BAD-, RARE-, KEEPCASE-, NEEDAFFIX-, NEEDCOMPOUND- tai " -"NOSUGGEST-arvossa kohteessa %s rivillä %d: %s" +"Affiksia käytetty myös BAD-, RARE-, KEEPCASE-, NEEDAFFIX-, NEEDCOMPOUND- tai " +"NOSUGGEST-arvossa kohteessa %s rivillä %d: %s" -#: ../spell.c:4893 #, c-format msgid "Expected Y or N in %s line %d: %s" -msgstr "Odotettiin Y:tä tai N:ää kohteessa %s rivillä %d: %s" +msgstr "Odotettiin Y:tä tai N:ää kohteessa %s rivillä %d: %s" -#: ../spell.c:4968 #, c-format msgid "Broken condition in %s line %d: %s" -msgstr "Viallinen ehto kohteessa %s rivillä %d: %s" +msgstr "Viallinen ehto kohteessa %s rivillä %d: %s" -#: ../spell.c:5091 #, c-format msgid "Expected REP(SAL) count in %s line %d" -msgstr "Odotettiin REP(SAL)-arvoa kohteessa %s rivillä %d" +msgstr "Odotettiin REP(SAL)-arvoa kohteessa %s rivillä %d" -#: ../spell.c:5120 #, c-format msgid "Expected MAP count in %s line %d" -msgstr "Odotettiin MAP-arvoa kohteessa %s rivillä %d" +msgstr "Odotettiin MAP-arvoa kohteessa %s rivillä %d" -#: ../spell.c:5132 #, c-format msgid "Duplicate character in MAP in %s line %d" -msgstr "Kaksoiskappale merkistä MAP:ssä kohteessa %s rivillä %d" +msgstr "Kaksoiskappale merkistä MAP:ssä kohteessa %s rivillä %d" -#: ../spell.c:5176 #, c-format msgid "Unrecognized or duplicate item in %s line %d: %s" -msgstr "Tunnistamaton tai kaksoiskappale arvosta kohteessa %s rivillä %d: %s" +msgstr "Tunnistamaton tai kaksoiskappale arvosta kohteessa %s rivillä %d: %s" -#: ../spell.c:5197 #, c-format msgid "Missing FOL/LOW/UPP line in %s" msgstr "Puuttuva FOL, LOW tai UPP rivi kohteessa %s" -#: ../spell.c:5220 msgid "COMPOUNDSYLMAX used without SYLLABLE" msgstr "COMPOUNDSYLMAX ilman SYLLABLEa" -#: ../spell.c:5236 msgid "Too many postponed prefixes" -msgstr "Liikaa jälkikäteistettyjä prefiksejä" +msgstr "Liikaa jälkikäteistettyjä prefiksejä" -#: ../spell.c:5238 msgid "Too many compound flags" msgstr "Liikaa yhdyssanalippuja" -#: ../spell.c:5240 msgid "Too many postponed prefixes and/or compound flags" -msgstr "Liikaa jälkikäteistettyjä prefiksejä tai yhdyssanalippuja" +msgstr "Liikaa jälkikäteistettyjä prefiksejä tai yhdyssanalippuja" -#: ../spell.c:5250 #, c-format msgid "Missing SOFO%s line in %s" msgstr "Puuttuva SOFO%s-rivi kohteessa %s" -#: ../spell.c:5253 #, c-format msgid "Both SAL and SOFO lines in %s" msgstr "SAL- ja SOFO-rivit kohteessa %s" -#: ../spell.c:5331 #, c-format msgid "Flag is not a number in %s line %d: %s" -msgstr "Lippu ei ole lukuarvo kohteessa %s rivillä %d: %s" +msgstr "Lippu ei ole lukuarvo kohteessa %s rivillä %d: %s" -#: ../spell.c:5334 #, c-format msgid "Illegal flag in %s line %d: %s" -msgstr "Tuntematon lippu kohteessa %s rivillä %d: %s" +msgstr "Tuntematon lippu kohteessa %s rivillä %d: %s" -#: ../spell.c:5493 ../spell.c:5501 #, c-format msgid "%s value differs from what is used in another .aff file" msgstr "%s-arvo eroaa toisessa .aff-tiedostossa olevasta" -#: ../spell.c:5602 #, c-format msgid "Reading dictionary file %s ..." msgstr "Luetaan sanakirjatiedostoa %s" -#: ../spell.c:5611 #, c-format msgid "E760: No word count in %s" msgstr "E760: Ei sanalaskuria kohteessa %s" -#: ../spell.c:5669 #, c-format msgid "line %6d, word %6d - %s" msgstr "rivi %6d, sana %6d - %s" -#: ../spell.c:5691 #, c-format msgid "Duplicate word in %s line %d: %s" -msgstr "Toistettu sana kohteessa %s rivillä %d: %s" +msgstr "Toistettu sana kohteessa %s rivillä %d: %s" -#: ../spell.c:5694 #, c-format msgid "First duplicate word in %s line %d: %s" -msgstr "Ensimmäinen kappale kohteessa %s rivillä %d: %s" +msgstr "Ensimmäinen kappale kohteessa %s rivillä %d: %s" -#: ../spell.c:5746 #, c-format msgid "%d duplicate word(s) in %s" msgstr "toistettuja sanoja %d kohteessa %s" -#: ../spell.c:5748 #, c-format msgid "Ignored %d word(s) with non-ASCII characters in %s" msgstr "Ei-ASCII-merkkien takia ohitettuja sanoja %d kohteessa %s" -#: ../spell.c:6115 #, c-format msgid "Reading word file %s ..." msgstr "Luetaan sanatiedostoa %s..." -#: ../spell.c:6155 #, c-format msgid "Duplicate /encoding= line ignored in %s line %d: %s" -msgstr "Toistettu /encoding= ohitettu kohteessa %s rivillä %d: %s" +msgstr "Toistettu /encoding= ohitettu kohteessa %s rivillä %d: %s" -#: ../spell.c:6159 #, c-format msgid "/encoding= line after word ignored in %s line %d: %s" -msgstr "/encoding= sanojen jälkeen ohitettu kohteessa %s rivillä %d: %s" +msgstr "/encoding= sanojen jälkeen ohitettu kohteessa %s rivillä %d: %s" -#: ../spell.c:6180 #, c-format msgid "Duplicate /regions= line ignored in %s line %d: %s" -msgstr "Toistettu /regions= ohitettu kohteessa %s rivillä %d: %s" +msgstr "Toistettu /regions= ohitettu kohteessa %s rivillä %d: %s" -#: ../spell.c:6185 #, c-format msgid "Too many regions in %s line %d: %s" -msgstr "Liikaa regionseja kohteessa %s rivillä %d: %s" +msgstr "Liikaa regionseja kohteessa %s rivillä %d: %s" -#: ../spell.c:6198 #, c-format msgid "/ line ignored in %s line %d: %s" -msgstr "/ ohitettu kohteessa %s rivillä %d: %s" +msgstr "/ ohitettu kohteessa %s rivillä %d: %s" -#: ../spell.c:6224 #, c-format msgid "Invalid region nr in %s line %d: %s" -msgstr "Virheellinen region-luku kohteessa %s rivillä %d: %s" +msgstr "Virheellinen region-luku kohteessa %s rivillä %d: %s" -#: ../spell.c:6230 #, c-format msgid "Unrecognized flags in %s line %d: %s" -msgstr "Tunnistamaton lippu kohteessa %s rivillä %d: %s" +msgstr "Tunnistamaton lippu kohteessa %s rivillä %d: %s" -#: ../spell.c:6257 #, c-format msgid "Ignored %d words with non-ASCII characters" msgstr "Ei-ASCIIn takia ohitettuja sanoja %d" -#: ../spell.c:6656 #, c-format msgid "Compressed %d of %d nodes; %d (%d%%) remaining" -msgstr "Tiivistetty %d/%d noodia. %d (%d %%) jäljellä" +msgstr "Tiivistetty %d/%d noodia. %d (%d %%) jäljellä" -#: ../spell.c:7340 msgid "Reading back spell file..." msgstr "Luetaan taas oikaisulukutiedostoa..." #. Go through the trie of good words, soundfold each word and add it to #. the soundfold trie. -#: ../spell.c:7357 msgid "Performing soundfolding..." -msgstr "Ääntämyksen mukaan yhdistellään..." +msgstr "Ääntämyksen mukaan yhdistellään..." -#: ../spell.c:7368 -#, c-format -msgid "Number of words after soundfolding: %<PRId64>" -msgstr "Sanoja ääntämysyhdistelyn jälkeen: %<PRId64>" +#, fuzzy, c-format +#~ msgid "Number of words after soundfolding: %<PRId64>" +#~ msgstr "Sanoja ääntämysyhdistelyn jälkeen: %ld" -#: ../spell.c:7476 #, c-format msgid "Total number of words: %d" -msgstr "Sanoja yhteensä: %d" +msgstr "Sanoja yhteensä: %d" -#: ../spell.c:7655 #, c-format msgid "Writing suggestion file %s ..." msgstr "Kirjoitetaan ehdotustiedostoa %s..." -#: ../spell.c:7707 ../spell.c:7927 #, c-format msgid "Estimated runtime memory use: %d bytes" -msgstr "Arvioitu käyttömuisti: %d tavua" +msgstr "Arvioitu käyttömuisti: %d tavua" -#: ../spell.c:7820 msgid "E751: Output file name must not have region name" -msgstr "E751: Tulostetiedostonimessä ei saa olla alueen nimeä" +msgstr "E751: Tulostetiedostonimessä ei saa olla alueen nimeä" -#: ../spell.c:7822 msgid "E754: Only up to 8 regions supported" -msgstr "E754: Enintään 8 aluetta tuetaan" +msgstr "E754: Enintään 8 aluetta tuetaan" -#: ../spell.c:7846 #, c-format msgid "E755: Invalid region in %s" msgstr "E755: Virheellinen alue kohteelle %s" -#: ../spell.c:7907 msgid "Warning: both compounding and NOBREAK specified" -msgstr "Varoitus: sekä yhdyssanamuodostus että NOBREAK käytössä" +msgstr "Varoitus: sekä yhdyssanamuodostus että NOBREAK käytössä" -#: ../spell.c:7920 #, c-format msgid "Writing spell file %s ..." msgstr "Kirjoitetaan oikaisulukutiedostoa %s..." -#: ../spell.c:7925 msgid "Done!" msgstr "Valmista." -#: ../spell.c:8034 -#, c-format -msgid "E765: 'spellfile' does not have %<PRId64> entries" -msgstr "E765: spellfile ei sisällä %<PRId64> kohtaa" - -#: ../spell.c:8074 #, fuzzy, c-format -msgid "Word '%.*s' removed from %s" -msgstr "Sana poistettu kohteesta %s" +#~ msgid "E765: 'spellfile' does not have %<PRId64> entries" +#~ msgstr "E765: spellfile ei sisällä %ld kohtaa" -#: ../spell.c:8117 -#, fuzzy, c-format -msgid "Word '%.*s' added to %s" -msgstr "Sana lisätty kohteeseen %s" - -#: ../spell.c:8381 -msgid "E763: Word characters differ between spell files" -msgstr "E763: Sanan merkit muuttuvat oikaisulukutiedostojen välillä" - -#: ../spell.c:8684 -msgid "Sorry, no suggestions" -msgstr "Sori, ei ehdotuksia" - -#: ../spell.c:8687 -#, c-format -msgid "Sorry, only %<PRId64> suggestions" -msgstr "Sori, vain %<PRId64> ehdotusta" - -#. for when 'cmdheight' > 1 -#. avoid more prompt -#: ../spell.c:8704 -#, c-format -msgid "Change \"%.*s\" to:" -msgstr "Muuta %.*s:" - -#: ../spell.c:8737 -#, c-format -msgid " < \"%.*s\"" -msgstr " < %.*s" - -#: ../spell.c:8882 -msgid "E752: No previous spell replacement" -msgstr "E752: Ei edellistä oikaisulukukorjausta" - -#: ../spell.c:8925 -#, c-format -msgid "E753: Not found: %s" -msgstr "E753: Ei löytynyt: %s" - -#: ../spell.c:9276 -#, c-format -msgid "E778: This does not look like a .sug file: %s" -msgstr "E778: Ei vaikuta .sug-tiedostolta: %s" - -#: ../spell.c:9282 -#, c-format -msgid "E779: Old .sug file, needs to be updated: %s" -msgstr "E779: Vanha .sug-tiedosto pitää päivittää: %s" - -#: ../spell.c:9286 #, c-format -msgid "E780: .sug file is for newer version of Vim: %s" -msgstr "E780: .sug-tiedosto on uudemmalle Vimille: %s" +msgid "Word '%.*s' removed from %s" +msgstr "Sana %.*s poistettu kohteesta %s" -#: ../spell.c:9295 #, c-format -msgid "E781: .sug file doesn't match .spl file: %s" -msgstr "E781: .sug-tiedosto ei täsmää .spl-tiedostoon: %s" +msgid "Word '%.*s' added to %s" +msgstr "Sana %.*s lisätty kohteeseen %s" -#: ../spell.c:9305 -#, c-format -msgid "E782: error while reading .sug file: %s" -msgstr "E782: virhe luettaessa .sug-tiedostoa: %s" +msgid "E763: Word characters differ between spell files" +msgstr "E763: Sanan merkit muuttuvat oikaisulukutiedostojen välillä" #. This should have been checked when generating the .spl #. file. -#: ../spell.c:11575 msgid "E783: duplicate char in MAP entry" -msgstr "E783: kaksoiskappale merkistä MAP-kohdassa" +msgstr "E783: kaksoiskappale merkistä MAP-kohdassa" + +msgid "E766: Insufficient arguments for printf()" +msgstr "E766: printf():lle ei annettu tarpeeksi argumentteja" + +msgid "E807: Expected Float argument for printf()" +msgstr "E807: Odotettiin Float-argumenttia printf():lle" + +msgid "E767: Too many arguments to printf()" +msgstr "E767: printf():lle annettiin liikaa argumentteja" -#: ../syntax.c:266 msgid "No Syntax items defined for this buffer" -msgstr "Ei syntaksikohteita tälle puskurille" +msgstr "Ei syntaksikohteita tälle puskurille" -#: ../syntax.c:3083 ../syntax.c:3104 ../syntax.c:3127 #, c-format msgid "E390: Illegal argument: %s" msgstr "E390: Virheellinen argumentti: %s" -#: ../syntax.c:3299 +msgid "syntax iskeyword " +msgstr "syntax iskeyword " + #, c-format msgid "E391: No such syntax cluster: %s" msgstr "E391: Syntaksiklusteri puuttuu: %s" -#: ../syntax.c:3433 msgid "syncing on C-style comments" msgstr "synkkaa C-tyylin kommentteihin" -#: ../syntax.c:3439 msgid "no syncing" msgstr "ei synkkausta" -#: ../syntax.c:3441 msgid "syncing starts " msgstr "synkkaus aloitettu " -#: ../syntax.c:3443 ../syntax.c:3506 msgid " lines before top line" -msgstr " riviä ennen alkua" +msgstr " riviä ennen alkua" -#: ../syntax.c:3448 msgid "" "\n" "--- Syntax sync items ---" @@ -5729,7 +5225,6 @@ msgstr "" "\n" "--- Syntax sync -kohteet ---" -#: ../syntax.c:3452 msgid "" "\n" "syncing on items" @@ -5737,7 +5232,6 @@ msgstr "" "\n" "synkataan kohteisiin" -#: ../syntax.c:3457 msgid "" "\n" "--- Syntax items ---" @@ -5745,2314 +5239,2499 @@ msgstr "" "\n" "--- Syntax-kohteet ---" -#: ../syntax.c:3475 #, c-format msgid "E392: No such syntax cluster: %s" msgstr "E392: syntaksiklusteria ei ole: %s" -#: ../syntax.c:3497 msgid "minimal " -msgstr "vähintään " +msgstr "vähintään " -#: ../syntax.c:3503 msgid "maximal " -msgstr "enitntään " +msgstr "enitntään " -#: ../syntax.c:3513 msgid "; match " -msgstr "; täsmää " +msgstr "; täsmää " -#: ../syntax.c:3515 msgid " line breaks" msgstr " rivinvaihdot" -#: ../syntax.c:4076 msgid "E395: contains argument not accepted here" -msgstr "E395: contains ei sovi tähän" +msgstr "E395: contains ei sovi tähän" -#: ../syntax.c:4096 -#, fuzzy msgid "E844: invalid cchar value" -msgstr "E474: Virheellinen argumentti" +msgstr "E844: Virheellinen cchar-arvo" -#: ../syntax.c:4107 msgid "E393: group[t]here not accepted here" -msgstr "E393: group[t]here ei sovi tähän" +msgstr "E393: group[t]here ei sovi tähän" -#: ../syntax.c:4126 #, c-format msgid "E394: Didn't find region item for %s" -msgstr "E394: Aluetta nimelle %s ei löydy" +msgstr "E394: Aluetta nimelle %s ei löydy" -#: ../syntax.c:4188 msgid "E397: Filename required" msgstr "E397: Tiedostonimi puuttuu" -#: ../syntax.c:4221 -#, fuzzy msgid "E847: Too many syntax includes" -msgstr "E77: Liikaa tiedostonimiä" +msgstr "E847: Liikaa syntax includeja" -#: ../syntax.c:4303 #, c-format msgid "E789: Missing ']': %s" msgstr "E789: ] puuttuu: %s" -#: ../syntax.c:4531 +#, c-format +msgid "E890: trailing char after ']': %s]%s" +msgstr "E890: Ylimääräisiä merkkejä merkin ] perässä: %s]%s" + #, c-format msgid "E398: Missing '=': %s" msgstr "E398: = puuttuu: %s" -#: ../syntax.c:4666 #, c-format msgid "E399: Not enough arguments: syntax region %s" msgstr "E399: Argumentteja puuttuu: syntaksialue %s" -#: ../syntax.c:4870 -#, fuzzy msgid "E848: Too many syntax clusters" -msgstr "E391: Syntaksiklusteri puuttuu: %s" +msgstr "E848: Liikaa syntaksiklustereita" -#: ../syntax.c:4954 msgid "E400: No cluster specified" -msgstr "E400: klusteri määrittelemättä" +msgstr "E400: klusteri määrittelemättä" #. end delimiter not found -#: ../syntax.c:4986 #, c-format msgid "E401: Pattern delimiter not found: %s" msgstr "E401: Kuvoin erotin puuttuu: %s" -#: ../syntax.c:5049 #, c-format msgid "E402: Garbage after pattern: %s" -msgstr "E402: Roskia kuvion jäljessä: %s" +msgstr "E402: Roskia kuvion jäljessä: %s" -#: ../syntax.c:5120 msgid "E403: syntax sync: line continuations pattern specified twice" -msgstr "E403: syntax sync: rivinjatkamiskuvio määritelty kahdesti" +msgstr "E403: syntax sync: rivinjatkamiskuvio määritelty kahdesti" -#: ../syntax.c:5169 #, c-format msgid "E404: Illegal arguments: %s" msgstr "E404: Virheelliset argumentit: %s" -#: ../syntax.c:5217 #, c-format msgid "E405: Missing equal sign: %s" msgstr "E405: = puuttuu: %s" -#: ../syntax.c:5222 #, c-format msgid "E406: Empty argument: %s" -msgstr "E406: Tyhjä argumentti: %s" +msgstr "E406: Tyhjä argumentti: %s" -#: ../syntax.c:5240 #, c-format msgid "E407: %s not allowed here" -msgstr "E407: %s ei sovi tähän" +msgstr "E407: %s ei sovi tähän" -#: ../syntax.c:5246 #, c-format msgid "E408: %s must be first in contains list" msgstr "E408: %s kuuluu contains-listan alkuun" -#: ../syntax.c:5304 #, c-format msgid "E409: Unknown group name: %s" -msgstr "E409: Tuntematon ryhmän nimi: %s" +msgstr "E409: Tuntematon ryhmän nimi: %s" -#: ../syntax.c:5512 #, c-format msgid "E410: Invalid :syntax subcommand: %s" msgstr "E410: Virheelluinen :syntax-osakomento: %s" -#: ../syntax.c:5854 msgid "" " TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN" msgstr "" +" KAIKKI MÄÄRÄ TÄSMÄYS HITAIN KEKSIARVO NIMI ILMAUS" -#: ../syntax.c:6146 msgid "E679: recursive loop loading syncolor.vim" -msgstr "E679: rekursiivinen silmukka syncolor.vimissä" +msgstr "E679: rekursiivinen silmukka syncolor.vimissä" -#: ../syntax.c:6256 #, c-format msgid "E411: highlight group not found: %s" -msgstr "E411: korostusryhmää ei löytynyt: %s" +msgstr "E411: korostusryhmää ei löytynyt: %s" -#: ../syntax.c:6278 #, c-format msgid "E412: Not enough arguments: \":highlight link %s\"" msgstr "E412: Argumentteja puuttuu: :highlight link %s" -#: ../syntax.c:6284 #, c-format msgid "E413: Too many arguments: \":highlight link %s\"" msgstr "E413: Liikaa argumentteja: :highlight link %s" -#: ../syntax.c:6302 msgid "E414: group has settings, highlight link ignored" -msgstr "E414: ryhmällä on asetuksia, highlight link -komento ohitetaan" +msgstr "E414: ryhmällä on asetuksia, highlight link -komento ohitetaan" -#: ../syntax.c:6367 #, c-format msgid "E415: unexpected equal sign: %s" msgstr "E415: odotuksenvastainen =-merkki: %s" -#: ../syntax.c:6395 #, c-format msgid "E416: missing equal sign: %s" msgstr "E416: puuttuva =-merkki: %s" -#: ../syntax.c:6418 #, c-format msgid "E417: missing argument: %s" msgstr "E417: puuttuva argumentti: %s" -#: ../syntax.c:6446 #, c-format msgid "E418: Illegal value: %s" msgstr "E418: Viallinen arvo: %s" -#: ../syntax.c:6496 msgid "E419: FG color unknown" -msgstr "E419: edustaväri tuntematon" +msgstr "E419: edustaväri tuntematon" -#: ../syntax.c:6504 msgid "E420: BG color unknown" -msgstr "E420: taustaväri tuntematon" +msgstr "E420: taustaväri tuntematon" -#: ../syntax.c:6564 #, c-format msgid "E421: Color name or number not recognized: %s" -msgstr "E421: Värin nimi tai numero tuntematon: %s" - -#: ../syntax.c:6714 -#, c-format -msgid "E422: terminal code too long: %s" -msgstr "E422: terminaalikoodi liian pitkä: %s" +msgstr "E421: Värin nimi tai numero tuntematon: %s" -#: ../syntax.c:6753 #, c-format msgid "E423: Illegal argument: %s" msgstr "E423: Virheellinen argumentti: %s" -#: ../syntax.c:6925 msgid "E424: Too many different highlighting attributes in use" msgstr "E424: Liikaa eri korostusattribuutteja" -#: ../syntax.c:7427 msgid "E669: Unprintable character in group name" -msgstr "E669: Tulostuskelvoton merkki ryhmän nimessä" +msgstr "E669: Tulostuskelvoton merkki ryhmän nimessä" -#: ../syntax.c:7434 msgid "W18: Invalid character in group name" -msgstr "W18: Virheellinen merkki ryhmän nimessä" +msgstr "W18: Virheellinen merkki ryhmän nimessä" -#: ../syntax.c:7448 msgid "E849: Too many highlight and syntax groups" -msgstr "" +msgstr "E849: Liikaa korostuksia ja syntaksiryhmiä" -#: ../tag.c:104 msgid "E555: at bottom of tag stack" -msgstr "E555: tägipinon pohja" +msgstr "E555: tägipinon pohja" -#: ../tag.c:105 msgid "E556: at top of tag stack" -msgstr "E556: tägipinon huippu" +msgstr "E556: tägipinon huippu" -#: ../tag.c:380 msgid "E425: Cannot go before first matching tag" -msgstr "E425: Ei voida mennä ensimmäistä täsmäävää tägiä alummaksi" +msgstr "E425: Ei voida mennä ensimmäistä täsmäävää tägiä alummaksi" -#: ../tag.c:504 #, c-format msgid "E426: tag not found: %s" -msgstr "E426: tägi puuttuu: %s" +msgstr "E426: tägi puuttuu: %s" -#: ../tag.c:528 msgid " # pri kind tag" -msgstr " # arvo tyyppi tägi" +msgstr " # arvo tyyppi tägi" -#: ../tag.c:531 msgid "file\n" msgstr "tiedosto\n" -#: ../tag.c:829 msgid "E427: There is only one matching tag" -msgstr "E427: Vain yksi tägi täsmää" +msgstr "E427: Vain yksi tägi täsmää" -#: ../tag.c:831 msgid "E428: Cannot go beyond last matching tag" -msgstr "E428: Ei voida edetä viimeisen täsmäävän tägin ohi" +msgstr "E428: Ei voida edetä viimeisen täsmäävän tägin ohi" -#: ../tag.c:850 #, c-format msgid "File \"%s\" does not exist" msgstr "Tiedostoa %s ei ole" #. Give an indication of the number of matching tags -#: ../tag.c:859 #, c-format msgid "tag %d of %d%s" -msgstr "tägi %d/%d%s" +msgstr "tägi %d/%d%s" -#: ../tag.c:862 msgid " or more" msgstr " tai useammasta" -#: ../tag.c:864 msgid " Using tag with different case!" -msgstr " Tägissä eri kirjaintaso" +msgstr " Tägissä eri kirjaintaso" -#: ../tag.c:909 #, c-format msgid "E429: File \"%s\" does not exist" msgstr "E429: Tiedostoa %s ei ole" #. Highlight title -#: ../tag.c:960 msgid "" "\n" " # TO tag FROM line in file/text" msgstr "" "\n" -" # TILL tagg FRÅN LINJE i fil/text" +" # TILL tagg FRÃ…N LINJE i fil/text" -#: ../tag.c:1303 #, c-format msgid "Searching tags file %s" -msgstr "Etsitään tägitiedostoa %s" +msgstr "Etsitään tägitiedostoa %s" -#: ../tag.c:1545 msgid "Ignoring long line in tags file" -msgstr "Ohitetaan pitkä rivi tägitiedostossa" +msgstr "Ohitetaan pitkä rivi tägitiedostossa" -#: ../tag.c:1915 #, c-format msgid "E431: Format error in tags file \"%s\"" -msgstr "E431: Muotovirh tägitiedostossa %s" +msgstr "E431: Muotovirh tägitiedostossa %s" -#: ../tag.c:1917 -#, c-format -msgid "Before byte %<PRId64>" -msgstr "Ennen tavua %<PRId64>" +#, fuzzy, c-format +#~ msgid "Before byte %<PRId64>" +#~ msgstr "Ennen tavua %ld" -#: ../tag.c:1929 #, c-format msgid "E432: Tags file not sorted: %s" -msgstr "E432: Tägitiedosto ei ole järjestetty: %s" +msgstr "E432: Tägitiedosto ei ole järjestetty: %s" #. never opened any tags file -#: ../tag.c:1960 msgid "E433: No tags file" -msgstr "E433: Ei tägitiedostoja" +msgstr "E433: Ei tägitiedostoja" -#: ../tag.c:2536 msgid "E434: Can't find tag pattern" -msgstr "E434: Tägikuviota ei löydy" +msgstr "E434: Tägikuviota ei löydy" -#: ../tag.c:2544 msgid "E435: Couldn't find tag, just guessing!" -msgstr "E435: Tägiä ei löydy, arvataan." +msgstr "E435: Tägiä ei löydy, arvataan." -#: ../tag.c:2797 #, c-format msgid "Duplicate field name: %s" -msgstr "Kaksoiskappale kentän nimestä: %s" - -#: ../term.c:1442 -msgid "' not known. Available builtin terminals are:" -msgstr " ei tunnettu. Tuetut terminaalit:" - -#: ../term.c:1463 -msgid "defaulting to '" -msgstr "oletusarvona " - -#: ../term.c:1731 -msgid "E557: Cannot open termcap file" -msgstr "E557: Ei voi avata termcap-tiedostoa" - -#: ../term.c:1735 -msgid "E558: Terminal entry not found in terminfo" -msgstr "E558: Terminaalia ei löytynyt terminfosta" - -#: ../term.c:1737 -msgid "E559: Terminal entry not found in termcap" -msgstr "E559: Terminaalia ei löytynyt termcapista" - -#: ../term.c:1878 -#, c-format -msgid "E436: No \"%s\" entry in termcap" -msgstr "E436: %s ei löytynyt termcapista" - -#: ../term.c:2249 -msgid "E437: terminal capability \"cm\" required" -msgstr "E437: terminaalilla pitää olla cm kyvyissään" - -#. Highlight title -#: ../term.c:4376 -msgid "" -"\n" -"--- Terminal keys ---" -msgstr "" -"\n" -"--- Terminaalinäppäimet ---" - -#: ../ui.c:481 -msgid "Vim: Error reading input, exiting...\n" -msgstr "Vim: Virhe luettaessa syötettä, poistutaan...\n" +msgstr "Kaksoiskappale kentän nimestä: %s" #. This happens when the FileChangedRO autocommand changes the #. * file in a way it becomes shorter. -#: ../undo.c:379 -#, fuzzy msgid "E881: Line count changed unexpectedly" -msgstr "E834: Rivimäärä vaihtui odottamatta" +msgstr "E881: Rivimäärä vaihtui odottamatta" -#: ../undo.c:627 #, c-format msgid "E828: Cannot open undo file for writing: %s" msgstr "E828: Kumoustiedoston avaus kirjoittamista varten ei onnistu: %s" -#: ../undo.c:717 +#, fuzzy, c-format +#~ msgid "E5003: Unable to create directory \"%s\" for undo file: %s" +#~ msgstr "E346: Hakemisto %s ei ole enää cdpathissa" + #, c-format msgid "E825: Corrupted undo file (%s): %s" msgstr "E825: Pilaanntunut kumoustiedosto (%s): %s" -#: ../undo.c:1039 msgid "Cannot write undo file in any directory in 'undodir'" -msgstr "Ei voitu lukea kumoustiedostoa mistään undodir-muuttujan hakemistosta" +msgstr "Ei voitu lukea kumoustiedostoa mistään undodir-muuttujan hakemistosta" -#: ../undo.c:1074 #, c-format msgid "Will not overwrite with undo file, cannot read: %s" msgstr "Ei ylikirjoitetat kumoustiedostolla, koska ei voida lukea: %s" -#: ../undo.c:1092 #, c-format msgid "Will not overwrite, this is not an undo file: %s" -msgstr "Ei ylikirjoiteta, koska tämä ei ole kumoustiedosto: %s" +msgstr "Ei ylikirjoiteta, koska tämä ei ole kumoustiedosto: %s" -#: ../undo.c:1108 msgid "Skipping undo file write, nothing to undo" msgstr "Ohitetaan kumoustiedoston kirjoitus, koska ei ole peruutettavia" -#: ../undo.c:1121 #, c-format msgid "Writing undo file: %s" msgstr "Kirjoitetaan kumoustiedostoa: %s" -#: ../undo.c:1213 #, c-format msgid "E829: write error in undo file: %s" msgstr "E829: Kirjoitusvirhe kumoustiedostossa: %s" -#: ../undo.c:1280 #, c-format msgid "Not reading undo file, owner differs: %s" msgstr "Ei lueta kumoustiedosto jonka omistaja on eri: %s" -#: ../undo.c:1292 #, c-format msgid "Reading undo file: %s" msgstr "Luetaan kumoustiedostoa: %s" -#: ../undo.c:1299 #, c-format msgid "E822: Cannot open undo file for reading: %s" msgstr "E822: Kumoustiedostoa ei voi avata lukemista varten: %s" -#: ../undo.c:1308 #, c-format msgid "E823: Not an undo file: %s" msgstr "E823: Ei ole kumoustiedosto: %s" -#: ../undo.c:1313 #, c-format msgid "E824: Incompatible undo file: %s" -msgstr "E824: Epäyhteensopiva kumoustiedosto: %s" +msgstr "E824: Epäyhteensopiva kumoustiedosto: %s" -#: ../undo.c:1328 msgid "File contents changed, cannot use undo info" msgstr "" -"Tiedoston sisältö on muuttunut, joen kumoustiedot ovat käyttökelvottomia" +"Tiedoston sisältö on muuttunut, joen kumoustiedot ovat käyttökelvottomia" -#: ../undo.c:1497 #, c-format msgid "Finished reading undo file %s" msgstr "Ladattu kumoustiedoto %s" -#: ../undo.c:1586 ../undo.c:1812 msgid "Already at oldest change" msgstr "Vanhimmassa muutoksessa" -#: ../undo.c:1597 ../undo.c:1814 msgid "Already at newest change" msgstr "Nuorimmassa muutoksessa" -#: ../undo.c:1806 -#, c-format -msgid "E830: Undo number %<PRId64> not found" -msgstr "E830: Kumouslukua %<PRId64> ei löydy" +#, fuzzy, c-format +#~ msgid "E830: Undo number %<PRId64> not found" +#~ msgstr "E830: Kumouslukua %ld ei löydy" -#: ../undo.c:1979 msgid "E438: u_undo: line numbers wrong" -msgstr "E438: u_undo: väärät rivinumerot" +msgstr "E438: u_undo: väärät rivinumerot" -#: ../undo.c:2183 msgid "more line" -msgstr "rivi lisää" +msgstr "rivi lisää" -#: ../undo.c:2185 msgid "more lines" -msgstr "riviä lisää" +msgstr "riviä lisää" -#: ../undo.c:2187 msgid "line less" -msgstr "rivi vähemmän" +msgstr "rivi vähemmän" -#: ../undo.c:2189 msgid "fewer lines" -msgstr "riviä vähemmän" +msgstr "riviä vähemmän" -#: ../undo.c:2193 msgid "change" msgstr "muutos" -#: ../undo.c:2195 msgid "changes" msgstr "muutosta" -# eka %s yläpuolelta, toka %s alapuolelta, kolmas %s aika -#: ../undo.c:2225 -#, c-format -msgid "%<PRId64> %s; %s #%<PRId64> %s" -msgstr "%<PRId64> %s, %s #%<PRId64> %s" +# eka %s yläpuolelta, toka %s alapuolelta, kolmas %s aika +#, fuzzy, c-format +#~ msgid "%<PRId64> %s; %s #%<PRId64> %s" +#~ msgstr "%ld %s, %s #%ld %s" + +msgid "after" +msgstr "jälkeen muutoksen" -#: ../undo.c:2228 msgid "before" msgstr "ennen muutosta" -#: ../undo.c:2228 -msgid "after" -msgstr "jälkeen muutoksen" - -#: ../undo.c:2325 msgid "Nothing to undo" msgstr "Ei kumottavaa" -#: ../undo.c:2330 -#, fuzzy msgid "number changes when saved" -msgstr "muutoksia aika tallennettu" +msgstr "numero muutoksia aika tallennettu" -#: ../undo.c:2360 -#, c-format -msgid "%<PRId64> seconds ago" -msgstr "%<PRId64> sekuntia sitten" +#, fuzzy, c-format +#~ msgid "%<PRId64> seconds ago" +#~ msgstr "%ld sekuntia sitten" -#: ../undo.c:2372 msgid "E790: undojoin is not allowed after undo" -msgstr "E790: undojoin ei toimi undon jälkeen" +msgstr "E790: undojoin ei toimi undon jälkeen" -#: ../undo.c:2466 msgid "E439: undo list corrupt" msgstr "E439: kumouslista rikki" -#: ../undo.c:2495 msgid "E440: undo line missing" msgstr "E440: kumousrivi puuttuu" -#: ../version.c:600 -msgid "" -"\n" -"Included patches: " -msgstr "" -"\n" -"Pätsit: " - -#: ../version.c:627 msgid "" "\n" "Extra patches: " msgstr "" "\n" -"Muita pätsejä: " - -#: ../version.c:639 ../version.c:864 -msgid "Modified by " -msgstr "Muokannut " +"Muita pätsejä: " -#: ../version.c:646 msgid "" "\n" "Compiled " msgstr "" "\n" -"Kääntänyt " +"Kääntänyt " -#: ../version.c:649 msgid "by " msgstr ": " -#: ../version.c:660 +#, fuzzy msgid "" "\n" -"Huge version " -msgstr "" "\n" -"Huge-versio " - -#: ../version.c:661 -msgid "without GUI." -msgstr "ilman GUIta." - -#: ../version.c:662 -msgid " Features included (+) or not (-):\n" +"Optional features included (+) or not (-): " msgstr " Ominaisuudet mukana (+) ja poissa (-):\n" -#: ../version.c:667 msgid " system vimrc file: \"" -msgstr " järjestelmän vimrc: \"" - -#: ../version.c:672 -msgid " user vimrc file: \"" -msgstr " käyttäjän vimrc: \"" - -#: ../version.c:677 -msgid " 2nd user vimrc file: \"" -msgstr " 2. käyttäjän vimrc: \"" +msgstr " järjestelmän vimrc: \"" -#: ../version.c:682 -msgid " 3rd user vimrc file: \"" -msgstr " 3. käyttäjän vimrc: \"" - -#: ../version.c:687 -msgid " user exrc file: \"" -msgstr " käyttäjän exrc: \"" - -#: ../version.c:692 -msgid " 2nd user exrc file: \"" -msgstr " 2. käyttäjän exrc: \"" - -#: ../version.c:699 msgid " fall-back for $VIM: \"" msgstr " $VIMin fallback: \"" -#: ../version.c:705 msgid " f-b for $VIMRUNTIME: \"" msgstr " $VIMRUNTIMEn f-b: \"" -#: ../version.c:709 -msgid "Compilation: " -msgstr "Käännös: " - -#: ../version.c:712 -msgid "Linking: " -msgstr "Linkitys: " - -#: ../version.c:717 -msgid " DEBUG BUILD" -msgstr " DEBUG-versio" - -#: ../version.c:767 -msgid "VIM - Vi IMproved" -msgstr "VIM - Vi IMproved" - -#: ../version.c:769 -msgid "version " -msgstr "versio " - -#: ../version.c:770 msgid "by Bram Moolenaar et al." -msgstr "tekijät Bram Moolenaar et al." +msgstr "tekijät Bram Moolenaar et al." -#: ../version.c:774 -msgid "Vim is open source and freely distributable" -msgstr "Vim on avointa lähdekoodia ja vapaasti jaossa" +#, fuzzy +#~ msgid "Nvim is open source and freely distributable" +#~ msgstr "Vim on avointa lähdekoodia ja vapaasti jaossa" -#: ../version.c:776 -msgid "Help poor children in Uganda!" -msgstr "Auta Ugandan köyhiä lapsia" +#~ msgid "https://neovim.io/community" +#~ msgstr "" -#: ../version.c:777 -msgid "type :help iccf<Enter> for information " -msgstr "kirjoita :help iccf<Enter> lisätietoa varten " +#, fuzzy +#~ msgid "type :help nvim<Enter> if you are new! " +#~ msgstr "kirjoita :help iccf<Enter> lisätietoa varten " + +#, fuzzy +#~ msgid "type :CheckHealth<Enter> to optimize Nvim" +#~ msgstr "kirjoita :help iccf<Enter> lisätietoa varten " -#: ../version.c:779 msgid "type :q<Enter> to exit " msgstr "kirjoita :q<Enter> lopettaaksesi " -#: ../version.c:780 -msgid "type :help<Enter> or <F1> for on-line help" -msgstr "kirjoita :help<Enter> tai <F1> ohjetta varten " - -#: ../version.c:781 -msgid "type :help version7<Enter> for version info" -msgstr "kirjoita :help version7<Enter> versiotietoja varten " - -#: ../version.c:784 -msgid "Running in Vi compatible mode" -msgstr "Suoritetaan Vi-yhteensopivuustilaa" +#, fuzzy +#~ msgid "type :help<Enter> for help " +#~ msgstr "kirjoita :q<Enter> lopettaaksesi " -#: ../version.c:785 -msgid "type :set nocp<Enter> for Vim defaults" -msgstr "kirjoita :set nocp<Enter> Vimin oletuksiin " +msgid "Help poor children in Uganda!" +msgstr "Auta Ugandan köyhiä lapsia" -#: ../version.c:786 -msgid "type :help cp-default<Enter> for info on this" -msgstr "kirjoita :help cp-default<Enter> ohjetta oletuksista varten" +msgid "type :help iccf<Enter> for information " +msgstr "kirjoita :help iccf<Enter> lisätietoa varten " -#: ../version.c:827 msgid "Sponsor Vim development!" -msgstr "Tue Vimin kehitystä" +msgstr "Tue Vimin kehitystä" -#: ../version.c:828 msgid "Become a registered Vim user!" -msgstr "Rekisteröidy Vim-käyttäjäksi." +msgstr "Rekisteröidy Vim-käyttäjäksi." -#: ../version.c:831 msgid "type :help sponsor<Enter> for information " -msgstr "kirjoita :help sponsor<Enter> lisätietoja varten" +msgstr "kirjoita :help sponsor<Enter> lisätietoja varten" -#: ../version.c:832 msgid "type :help register<Enter> for information " -msgstr "kirjoita :help register<Enter> lisätietoja varten" +msgstr "kirjoita :help register<Enter> lisätietoja varten" -#: ../version.c:834 msgid "menu Help->Sponsor/Register for information " -msgstr "valikko Ohje->Sponsoroi/Rekisteröi lisätietoja varten" +msgstr "valikko Ohje->Sponsoroi/Rekisteröi lisätietoja varten" -#: ../window.c:119 msgid "Already only one window" -msgstr "Enää yksi ikkuna jäljellä" +msgstr "Enää yksi ikkuna jäljellä" -#: ../window.c:224 msgid "E441: There is no preview window" msgstr "E441: Ei esikatseluikkunaa" -#: ../window.c:559 msgid "E442: Can't split topleft and botright at the same time" -msgstr "E442: Ei voi jakaa vasenta ylänurkkaa ja oikeaa alanurkkaa yhtäaikaa" +msgstr "E442: Ei voi jakaa vasenta ylänurkkaa ja oikeaa alanurkkaa yhtäaikaa" -#: ../window.c:1228 msgid "E443: Cannot rotate when another window is split" -msgstr "E443: Ei voi kiertää kun toinen ikkuna on jaettu" +msgstr "E443: Ei voi kiertää kun toinen ikkuna on jaettu" -#: ../window.c:1803 msgid "E444: Cannot close last window" -msgstr "E444: Ei voi sulkea viimeistä ikkunaa" +msgstr "E444: Ei voi sulkea viimeistä ikkunaa" -#: ../window.c:1810 msgid "E813: Cannot close autocmd window" msgstr "E813: Ei voi sulkea autocmd-ikkunaa" -#: ../window.c:1814 msgid "E814: Cannot close window, only autocmd window would remain" -msgstr "E814: Ei voi sulkea viimeistä ikkunaa, joka ei ole autocmd-ikkuna" +msgstr "E814: Ei voi sulkea viimeistä ikkunaa, joka ei ole autocmd-ikkuna" -#: ../window.c:2717 msgid "E445: Other window contains changes" -msgstr "E445: Toinen ikkuna sisältää muutoksia" +msgstr "E445: Toinen ikkuna sisältää muutoksia" -#: ../window.c:4805 msgid "E446: No file name under cursor" -msgstr "E446: Ei tiedostonimeä kursorin alla" +msgstr "E446: Ei tiedostonimeä kursorin alla" -#~ msgid "E831: bf_key_init() called with empty password" -#~ msgstr "E831: bf_key_init() tyhjällä salasanalla" +msgid "List or number required" +msgstr "Lista tai luku tarvitaan" -#~ msgid "E820: sizeof(uint32_t) != 4" -#~ msgstr "E820: sizeof(uint32_t) != 4" +#~ msgid "" +#~ "Failed to set path: sys.path is not a list\n" +#~ "You should now append vim.VIM_SPECIAL_PATH to sys.path" +#~ msgstr "" +#~ "Ei onnistuttu asettaman polkua: sys.path ei ole list\n" +#~ "Lisää vim.VIM_SPECIAL_PATH muuttujaan sys.path" -#~ msgid "E817: Blowfish big/little endian use wrong" -#~ msgstr "E817: Blowfishin tavujärjestys väärä" +#~ msgid "" +#~ "Failed to set path hook: sys.path_hooks is not a list\n" +#~ "You should now do the following:\n" +#~ "- append vim.path_hook to sys.path_hooks\n" +#~ "- append vim.VIM_SPECIAL_PATH to sys.path\n" +#~ msgstr "" +#~ "Ei voitu asettaa polkukoukkua: sys.path_hooks ei ole lista\n" +#~ "Koeta seuraavaa:\n" +#~ "- lisää vim.path_hook muuttujaan sys.path_hooks\n" +#~ "- lisää vim.VIM_SPECIAL_PATH muuttujaan sys.path\n" -#~ msgid "E818: sha256 test failed" -#~ msgstr "E818: sha256-testi epäonnistui failed" +#~ msgid "internal error: invalid value type" +#~ msgstr "sisäinen virhe: huono arvotyyppi" -#~ msgid "E819: Blowfish test failed" -#~ msgstr "E819: Blowfish-testi epäonnistui" +#~ msgid "internal error: NULL reference passed" +#~ msgstr "sisäinen virhe: NULL-viite annettu" -#~ msgid "Patch file" -#~ msgstr "Patch-tiedosto" +#~ msgid "unable to convert %s to vim structure" +#~ msgstr "ei voi konvertoida oliota %s vim-tietorakenteeksi" -#~ msgid "" -#~ "&OK\n" -#~ "&Cancel" -#~ msgstr "" -#~ "&OK\n" -#~ "&Peru" +#~ msgid "unable to convert %s to vim dictionary" +#~ msgstr "ei voitu konvertoida oliota %s vim-sanakirjaksi" -#~ msgid "E240: No connection to Vim server" -#~ msgstr "E240: Ei yhteyttä vim-palvelimeen" +#~ msgid "E859: Failed to convert returned python object to vim value" +#~ msgstr "E859: Ei voitu konvertoida python-oliota vim-arvoksi" -#~ msgid "E241: Unable to send to %s" -#~ msgstr "E241: Kohteeseen %s lähettäminen ei onnistunut" +#~ msgid "E858: Eval did not return a valid python object" +#~ msgstr "E858: Eval ei palauttanut python-oliota" -#~ msgid "E277: Unable to read a server reply" -#~ msgstr "E277: Palvelimen vastauksen lukeminen ei onnistunut" +#~ msgid "failed to run the code" +#~ msgstr "ei voitu suorittaa koodia" -#~ msgid "E258: Unable to send to client" -#~ msgstr "E258: Asiakkaalle lähetys ei onnistunut" +#~ msgid "did not switch to the specified tab page" +#~ msgstr "ei voitu vaihtaa annetulle välilehtisivulle" -#~ msgid "Save As" -#~ msgstr "Tallenna nimellä" +#~ msgid "expected vim.TabPage object, but got %s" +#~ msgstr "odotettiin vim.TabPage-oliota, saatiin %s" -#~ msgid "Source Vim script" -#~ msgstr "Lataa vim-skripti" +#~ msgid "did not switch to the specified window" +#~ msgstr "ei vaihdettu annettuun ikkunaan" -#~ msgid "Edit File" -#~ msgstr "Muokkaa tiedostoa" +#~ msgid "failed to find window in the current tab page" +#~ msgstr "ei voitu löytää ikkunaa nykyiselle välilehtisivulle" -#~ msgid " (NOT FOUND)" -#~ msgstr " (EI LÖYTYNYT)" +#~ msgid "expected vim.Window object, but got %s" +#~ msgstr "odotettiin vim.Window-oliota, saatiin %s" -#~ msgid "unknown" -#~ msgstr "tuntematon" +#~ msgid "expected vim.Buffer object, but got %s" +#~ msgstr "odotettiin vim.Buffer-oliota, ei %s" -#~ msgid "Edit File in new window" -#~ msgstr "Muokkaa uudessa ikkunassa" +#~ msgid "attempt to refer to deleted buffer" +#~ msgstr "yritettiin viitata poistettuun puskuriin" -#~ msgid "Append File" -#~ msgstr "Lisää tiedostoon" +#~ msgid "no such window" +#~ msgstr "ikkunaa ei ole" -#~ msgid "Window position: X %d, Y %d" -#~ msgstr "Ikkunan sijainti: X %d, Y %d" +#~ msgid "readonly attribute: buffer" +#~ msgstr "kirjoitussuojausattribuutti: puskuri" -#~ msgid "Save Redirection" -#~ msgstr "Tallenna uudelleenosoitus" +#~ msgid "attempt to refer to deleted window" +#~ msgstr "yritettiin viitata poistettuun ikkunaan" -#~ msgid "Save View" -#~ msgstr "Tallenna näkymä" +#~ msgid "no such tab page" +#~ msgstr "välilehteä ei ole" -#~ msgid "Save Session" -#~ msgstr "Tallenna sessio" +#~ msgid "attempt to refer to deleted tab page" +#~ msgstr "yritettiin viitata poistettuun välilehteen" -#~ msgid "Save Setup" -#~ msgstr "Tallenna asetukset" +#~ msgid "internal error: unknown option type" +#~ msgstr "sisäinen virhe: tuntematon asetustyyppi" -#~ msgid "E809: #< is not available without the +eval feature" -#~ msgstr "E809: #< ei ole käytössä jollei +eval ole päällä" +#~ msgid "unable to get option value" +#~ msgstr "ei voitu hakea asetuksen arvoa" -#~ msgid "E196: No digraphs in this version" -#~ msgstr "E196: Digraafeja ei ole tässä versiossa" +#~ msgid "failed to run function %s" +#~ msgstr "ei voitu suorittaa funktiota %s" -#~ msgid "is a device (disabled with 'opendevice' option)" -#~ msgstr "on laite (ei käytössä opendevice-asetuksen takia)" +#~ msgid "function %s does not exist" +#~ msgstr "funktiota %s ei ole" -#~ msgid "Reading from stdin..." -#~ msgstr "Luetaan vakiosyötteestä" +#~ msgid "unnamed function %s does not exist" +#~ msgstr "nimetöntä funktiota %s ei ole" -#~ msgid "[crypted]" -#~ msgstr "[salattu]" +#~ msgid "cannot modify fixed list" +#~ msgstr "ei voida muokata kiinitettyä listaa" -#~ msgid "E821: File is encrypted with unknown method" -#~ msgstr "E821: Tiedoston salaus on tuntematon" +#~ msgid "cannot delete vim.List attributes" +#~ msgstr "ei voi poistaa vim.List-attribuutteja" -#~ msgid "NetBeans disallows writes of unmodified buffers" -#~ msgstr "NetBeans ei salli kirjoittaa muokkaamattomiin puskureihin" +#~ msgid "failed to add item to list" +#~ msgstr "ei voitu lisätä kohtaa listaan" -#~ msgid "Partial writes disallowed for NetBeans buffers" -#~ msgstr "Osittaiset kirjoitukset kielletty NetBeans-puskureissa" +#~ msgid "attempt to assign sequence of size %d to extended slice of size %d" +#~ msgstr "" +#~ "yritettiin asettaa sekvenssiä jonka koko on %d sliceen jonka koko on %d" -#~ msgid "writing to device disabled with 'opendevice' option" -#~ msgstr "laitteeseen kirjoittaminen pois käytöstä opendevice-asetuksella" +#~ msgid "internal error: failed to add item to list" +#~ msgstr "sisäinen virhe: ei voitu lisätä kohtaa listaan" -# tietääkseni resurssiforkki on applen tiedostojärjestelmän tunnistejuttujuttu -#~ msgid "E460: The resource fork would be lost (add ! to override)" -#~ msgstr "E460: resurssiosa häviäisi (lisää komentoon ! ohittaaksesi)" +#~ msgid "internal error: not enough list items" +#~ msgstr "sisäinen virhe: ei tarpeeksi listan kohtia" -#~ msgid "<cannot open> " -#~ msgstr "<ei voi avata> " - -#~ msgid "E616: vim_SelFile: can't get font %s" -#~ msgstr "E616: vim_SelFile: ei saada fonttia %s" +#~ msgid "internal error: no vim list item %d" +#~ msgstr "sisäinen virhe: ei vim-listan indeksiä %d" -#~ msgid "E614: vim_SelFile: can't return to current directory" -#~ msgstr "E614: vim_SelFile: nykyiseen hakemistoon ei voi palata" +#~ msgid "attempt to assign sequence of size greater than %d to extended slice" +#~ msgstr "" +#~ "yritettiin sijoittaa sekvenssiä jonka koko on enemmän kuin %d sliceen" -#~ msgid "Pathname:" -#~ msgstr "Polku:" +#~ msgid "slice step cannot be zero" +#~ msgstr "slicen askel ei voi olla nolla" -#~ msgid "E615: vim_SelFile: can't get current directory" -#~ msgstr "E615: vim_SelFile: nykyistä hakemistoa ei saada selville" +#~ msgid "internal error: failed to get vim list item %d" +#~ msgstr "sisäinen virhe: ei pystytty hakea vimin listan indeksiä %d" -#~ msgid "OK" -#~ msgstr "OK" +#~ msgid "list index out of range" +#~ msgstr "listaindeksi arvoalueen ulkopuolelta" -#~ msgid "Cancel" -#~ msgstr "Peru" +#~ msgid "list constructor does not accept keyword arguments" +#~ msgstr "listakonstruktori ei tue avainsanaparametrejä" -#~ msgid "Vim dialog" -#~ msgstr "Vim-ikkuna" +#~ msgid "expected sequence element of size 2, but got sequence of size %d" +#~ msgstr "sekvenssin elementin koon pitäisi olla 2, ei %d" -#~ msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." -#~ msgstr "Vierityspalkki: Pixmapin geometria ei selviä" +#~ msgid "hashtab changed during iteration" +#~ msgstr "hashtab muuttui kesken iteraation" -#~ msgid "E232: Cannot create BalloonEval with both message and callback" -#~ msgstr "E232: Ei voi luoda BalloonEvalia viestille ja callbackille" +#~ msgid "cannot set attribute %s" +#~ msgstr "ei voi asettaa attribuuttia %s" -#~ msgid "E229: Cannot start the GUI" -#~ msgstr "E229: GUIn käynnistys ei onnistu" +#~ msgid "cannot delete vim.Dictionary attributes" +#~ msgstr "ei voi poistaa vim.Dictionary-attribuutteja" -#~ msgid "E230: Cannot read from \"%s\"" -#~ msgstr "E230: Ei voi lukea kohteesta %s" +#~ msgid "internal error: imp.find_module returned tuple with NULL" +#~ msgstr "" +#~ "sisäinen virhe: imp.find_module palautti tuplen joka sisältää nullin" -#~ msgid "E665: Cannot start GUI, no valid font found" -#~ msgstr "E665: Ei voi avata GUIta, sopivaa fonttia ei löydy" +#~ msgid "" +#~ "expected 3-tuple as imp.find_module() result, but got tuple of size %d" +#~ msgstr "" +#~ "odotettiin 3-tuple tuloksnea imp.find_module()-kutsulle, mutta tuplen " +#~ "koko onkin %d" -#~ msgid "E231: 'guifontwide' invalid" -#~ msgstr "E231: guifontwide virheellinen" +#~ msgid "expected 3-tuple as imp.find_module() result, but got %s" +#~ msgstr "odotettiin 3-tuplea tuloksena imp.find_module()-kutsulle, ei %s" -#~ msgid "E599: Value of 'imactivatekey' is invalid" -#~ msgstr "E599: imactivatekeyn arvo on virheellinen" +#~ msgid "E264: Python: Error initialising I/O objects" +#~ msgstr "E264: Python: Virhe IO-olioiden alustuksessa" -#~ msgid "E254: Cannot allocate color %s" -#~ msgstr "E254: Väriä %s ei voi määritellä" +#~ msgid "invalid attribute: %s" +#~ msgstr "virheellinen attribuutti: %s" -#~ msgid "No match at cursor, finding next" -#~ msgstr "Ei täsmäystä kursorin alla, etsitään seuraava" +#~ msgid "can't delete OutputObject attributes" +#~ msgstr "ei voi poistaa OutputObject-attribuutteja" -#~ msgid "Input _Methods" -#~ msgstr "Syöte_menetelmät" +#~ msgid "number must be greater or equal to zero" +#~ msgstr "luvun on oltava yhtä suuri tai suurempi kuin nolla" -#~ msgid "VIM - Search and Replace..." -#~ msgstr "VIM - Etsi ja korvaa..." +#~ msgid "value is too small to fit into C int type" +#~ msgstr "arvo on liian pieni mahtumaan C:n int-tyyppiin" -#~ msgid "VIM - Search..." -#~ msgstr "VIM - Etsi..." +#~ msgid "expected int() or something supporting coercing to int(), but got %s" +#~ msgstr "" +#~ "odotettiin tyyppiä int() tai jotain joka muuntuu tyyppiin int(), ei %s" -#~ msgid "Find what:" -#~ msgstr "Etsi:" +#~ msgid "" +#~ "expected int(), long() or something supporting coercing to long(), but " +#~ "got %s" +#~ msgstr "" +#~ "odotettiin instanssia tyypeistä int(), long() tai mitä tahansa joka " +#~ "muuntuisi tyyppiin long(), ei %s" -#~ msgid "Replace with:" -#~ msgstr "Korvaa:" +#~ msgid "expected bytes() or str() instance, but got %s" +#~ msgstr "odotettiin instanssia tyypeistä bytes() tai str(), ei %s" -#~ msgid "Match whole word only" -#~ msgstr "Korvaa kokonaisia sanoja" +#~ msgid "expected str() or unicode() instance, but got %s" +#~ msgstr "odottettiin insanssia tyypeistä str() tai unicode(), ei %s" -#~ msgid "Match case" -#~ msgstr "Kirjaintaso" +#~ msgid "index must be int or slice, not %s" +#~ msgstr "indeksin pitää olla int tai slice, ei %s" -#~ msgid "Direction" -#~ msgstr "Suunta" +#~ msgid "failed to add key '%s' to dictionary" +#~ msgstr "avaimen %s lisääminen sanakirjaan ei onnistu" -#~ msgid "Up" -#~ msgstr "Ylös" +#~ msgid "list is locked" +#~ msgstr "luettelo on lukittu" -#~ msgid "Down" -#~ msgstr "Alas" +#~ msgid "Need encryption key for \"%s\"" +#~ msgstr "Tarvitaan salausavain kohteelle %s " -#~ msgid "Find Next" -#~ msgstr "Etsi seuraava" +#~ msgid "E744: NetBeans does not allow changes in read-only files" +#~ msgstr "E744: NetBeans ei tue muutoksia kirjoitussuojattuihin tiedostoihin" -#~ msgid "Replace" -#~ msgstr "Korvaa" +#~ msgid "E463: Region is guarded, cannot modify" +#~ msgstr "E463: Alue on suojattu, muuttaminen ei onnistu" -#~ msgid "Replace All" -#~ msgstr "Korvaa kaikki" +#~ msgid "E449: Invalid expression received" +#~ msgstr "E449: Virheellinen ilmaus saatu" -#~ msgid "Vim: Received \"die\" request from session manager\n" -#~ msgstr "Vim: sessiomanageri lähetti die-pyynnön\n" +#~ msgid "E233: cannot open display" +#~ msgstr "E233: näyttöä ei voi avata" -#~ msgid "Close" -#~ msgstr "Sulje" +#~ msgid "E247: no registered server named \"%s\"" +#~ msgstr "E247: palvelinta %s ei ole rekisteröitynä" -#~ msgid "New tab" -#~ msgstr "Uusi välilehti" +#~ msgid "E800: Arabic cannot be used: Not enabled at compile time\n" +#~ msgstr "E800: Arabiaa ei voi käyttää, koska sitä ei käännetty mukaan\n" -#~ msgid "Open Tab..." -#~ msgstr "Avaa välilehti..." +#~ msgid "E27: Farsi cannot be used: Not enabled at compile time\n" +#~ msgstr "E27: Farsia ei voi käyttää, koska sitä ei käännetty mukaan\n" -#~ msgid "Vim: Main window unexpectedly destroyed\n" -#~ msgstr "Vim: Pääikkuna tuhoutui odottamatta\n" +#~ msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" +#~ msgstr "E26: Hepreaa ei voi käyttää, koska sitä ei käännetty mukaan\n" -#~ msgid "&Filter" -#~ msgstr "&Suodata" +#~ msgid "E25: GUI cannot be used: Not enabled at compile time" +#~ msgstr "E25: GUIta ei voi käyttää, koska sitä ei käännetty mukaan" -#~ msgid "&Cancel" -#~ msgstr "&Peru" +#~ msgid "E448: Could not load library function %s" +#~ msgstr "E448: Ei voitu ladta kirjastofunktiota %s" -#~ msgid "Directories" -#~ msgstr "Hakemistot" +#~ msgid "E236: Font \"%s\" is not fixed-width" +#~ msgstr "E236: Fontti %s ei ole tasavälinen" -#~ msgid "Filter" -#~ msgstr "Suodatus" +#~ msgid "E234: Unknown fontset: %s" +#~ msgstr "E234: Tuntematon fontset: %s" -#~ msgid "&Help" -#~ msgstr "O&hje" +#~ msgid "gvimext.dll error" +#~ msgstr "gvimext.dll-virhe" -#~ msgid "Files" -#~ msgstr "Tiedostot" +#~ msgid "Error creating process: Check if gvim is in your path!" +#~ msgstr "Virhe prosessin käynnistämisessä, varmista että gvim on polulla" -#~ msgid "&OK" -#~ msgstr "&Ok" +#~ msgid "Edits the selected file(s) with Vim" +#~ msgstr "Muokkaa valittuja tiedostoja Vimillä" -#~ msgid "Selection" -#~ msgstr "Valinta" +#~ msgid "Edit with existing Vim - " +#~ msgstr "Muokkaa olemassaolevalla Vimillä - " -#~ msgid "Find &Next" -#~ msgstr "Hae &seuraava" +#~ msgid "Edit with &Vim" +#~ msgstr "Muokkaa &Vimillä" -#~ msgid "&Replace" -#~ msgstr "Ko&rvaa" +#~ msgid "Diff with Vim" +#~ msgstr "Diffi Vimillä" -#~ msgid "Replace &All" -#~ msgstr "Korvaa k&aikki" +#~ msgid "Edit with single &Vim" +#~ msgstr "Muokkaa yhdellä &Vimillä" -#~ msgid "&Undo" -#~ msgstr "&Kumoa" +#~ msgid "Edit with &multiple Vims" +#~ msgstr "&Muokkaa usealla Vimillä" -#~ msgid "E671: Cannot find window title \"%s\"" -#~ msgstr "E671: Ikkunan otsikkoa ei löydy %s" +#~ msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" +#~ msgstr "E299: Perl-suoritus kielletty hiekkalaatikossa ilman Safe-moduulia" -# OLE on object linking and embedding på windowska -#~ msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." -#~ msgstr "E243: Argumenttia ei tueta: -%s, käytä OLE-versiota" +#~ msgid "" +#~ "Sorry, this command is disabled: the Perl library could not be loaded." +#~ msgstr "komento ei toimi, Perl kirjastoa ei voinut ladata." -# MDI eli windowsin moni-ikkunasovellus -#~ msgid "E672: Unable to open window inside MDI application" -#~ msgstr "E672: Ikkunaa ei voitu avata MDI-sovellukseen" +#~ msgid "E370: Could not load library %s" +#~ msgstr "E370: Kirjaston %s lataaminen ei onnistu" -#~ msgid "Close tab" -#~ msgstr "Sulje välilehti" +#~ msgid "type :help windows95<Enter> for info on this" +#~ msgstr "kirjoita :help windows95<Enter> lisätietoja varten" -#~ msgid "Open tab..." -#~ msgstr "Avaa välilehti..." +#~ msgid "WARNING: Windows 95/98/ME detected" +#~ msgstr "VAROITUS: Window 95/98/ME havaittu" -#~ msgid "Find string (use '\\\\' to find a '\\')" -#~ msgstr "Etsi merkkijonoa (\\\\:llä löytää \\:t)" +#~ msgid " for Vim defaults " +#~ msgstr " Vim-oletuksia varten" -#~ msgid "Find & Replace (use '\\\\' to find a '\\')" -#~ msgstr "Etsi ja korvaa (\\\\:llä löytää \\:t)" +#~ msgid "menu Edit->Global Settings->Toggle Vi Compatible" +#~ msgstr "valikko Muokkaa->Yleiset asetukset->Vaihda Vi-yhteensopivuutta" -#~ msgid "Not Used" -#~ msgstr "Ei käytössä" +#~ msgid "menu Edit->Global Settings->Toggle Insert Mode " +#~ msgstr "valikko Muokkaa->Yleiset asetukset->Vaihda syötetilaa" -#~ msgid "Directory\t*.nothing\n" -#~ msgstr "Hakemisto\t*.nothing\n" +#~ msgid "Running modeless, typed text is inserted" +#~ msgstr "Suoritetaan tilattomana, kirjoitettu teksti syötetään" -#~ msgid "" -#~ "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" -#~ msgstr "" -#~ "Vim E458: Ei voi varata värikartan alkiota, värit voivat mennä väärin" +#~ msgid "menu Help->Orphans for information " +#~ msgstr "valikko Ohje->Orvot lisätietoja varten " -#~ msgid "E250: Fonts for the following charsets are missing in fontset %s:" -#~ msgstr "E250: Seuraavien merkistöjoukkojen fontit puuttuvat fontsetistä %s:" +#~ msgid "type :help cp-default<Enter> for info on this" +#~ msgstr "kirjoita :help cp-default<Enter> ohjetta oletuksista varten" -#~ msgid "E252: Fontset name: %s" -#~ msgstr "E252: Fontsetin nimi: %s" +#~ msgid "type :set nocp<Enter> for Vim defaults" +#~ msgstr "kirjoita :set nocp<Enter> Vimin oletuksiin " -#~ msgid "Font '%s' is not fixed-width" -#~ msgstr "Fontti %s ei ole tasavälinen" +#~ msgid "Running in Vi compatible mode" +#~ msgstr "Suoritetaan Vi-yhteensopivuustilaa" -#~ msgid "E253: Fontset name: %s\n" -#~ msgstr "E253: Fontsetin nimi: %s\n" +#~ msgid "type :help version8<Enter> for version info" +#~ msgstr "kirjoita :help version8<Enter> versiotietoja varten " -#~ msgid "Font0: %s\n" -#~ msgstr "Fontti0: %s\n" +#~ msgid "type :help<Enter> or <F1> for on-line help" +#~ msgstr "kirjoita :help<Enter> tai <F1> ohjetta varten " -#~ msgid "Font1: %s\n" -#~ msgstr "Fontti1: %s\n" +#~ msgid "version " +#~ msgstr "versio " -#~ msgid "Font%<PRId64> width is not twice that of font0\n" -#~ msgstr "Fontti%<PRId64>:n leveys ei ole kaksi kertaa fontti0:n\n" +#~ msgid "VIM - Vi IMproved" +#~ msgstr "VIM - Vi IMproved" -#~ msgid "Font0 width: %<PRId64>\n" -#~ msgstr "Fontti0:n leveys: %<PRId64>\n" +#~ msgid " DEBUG BUILD" +#~ msgstr " DEBUG-versio" -#~ msgid "" -#~ "Font1 width: %<PRId64>\n" -#~ "\n" -#~ msgstr "" -#~ "Fontti1:n leveys: %<PRId64>\n" -#~ "\n" +#~ msgid "Linking: " +#~ msgstr "Linkitys: " -#~ msgid "Invalid font specification" -#~ msgstr "Virheellinen fonttimääritys" +#~ msgid "Compiler: " +#~ msgstr "Käännin: " -#~ msgid "&Dismiss" -#~ msgstr "&Ohita" +#~ msgid "Compilation: " +#~ msgstr "Käännös: " -#~ msgid "no specific match" -#~ msgstr "ei tarkkaa täsmäystä" +#~ msgid " system menu file: \"" +#~ msgstr " järjestelmävalikko: \"" -#~ msgid "Vim - Font Selector" -#~ msgstr "Vim - fonttivalitsin" +#~ msgid " defaults file: \"" +#~ msgstr " defaults-tiedosto: \"" -#~ msgid "Name:" -#~ msgstr "Nimi:" +#~ msgid "3rd user gvimrc file: \"" +#~ msgstr "3. käyttäjän gvimrc: \"" -#~ msgid "Show size in Points" -#~ msgstr "Näytä koko pisteinä" +#~ msgid "2nd user gvimrc file: \"" +#~ msgstr "2. käyttäjän gvimrc: \"" -#~ msgid "Encoding:" -#~ msgstr "Koodaus:" +#~ msgid " user gvimrc file: \"" +#~ msgstr " käyttäjän gvimrc: \"" -#~ msgid "Font:" -#~ msgstr "Fontti:" +#~ msgid " system gvimrc file: \"" +#~ msgstr " järjestelmän gvimrc: \"" -#~ msgid "Style:" -#~ msgstr "Tyyli:" +#~ msgid " 2nd user exrc file: \"" +#~ msgstr " 2. käyttäjän exrc: \"" -#~ msgid "Size:" -#~ msgstr "Koko:" +#~ msgid " user exrc file: \"" +#~ msgstr " käyttäjän exrc: \"" -#~ msgid "E256: Hangul automata ERROR" -#~ msgstr "E256: Hangu-automaattivirhe" +#~ msgid " 3rd user vimrc file: \"" +#~ msgstr " 3. käyttäjän vimrc: \"" -#~ msgid "E563: stat error" -#~ msgstr "E563: stat-virhe" +#~ msgid " 2nd user vimrc file: \"" +#~ msgstr " 2. käyttäjän vimrc: \"" -#~ msgid "E625: cannot open cscope database: %s" -#~ msgstr "E625: ei voi avata cscope-tietokantaa: %s" +#~ msgid " user vimrc file: \"" +#~ msgstr " käyttäjän vimrc: \"" -#~ msgid "E626: cannot get cscope database information" -#~ msgstr "E626: ei voi hakea cscope-tietokannan tietoja" +#~ msgid "with (classic) GUI." +#~ msgstr "perinteisellä GUIlla." -#~ msgid "Lua library cannot be loaded." -#~ msgstr "Luan kirjastoa ei voitu ladata." +#~ msgid "with Cocoa GUI." +#~ msgstr "Cocoa-GUIlla." -#~ msgid "cannot save undo information" -#~ msgstr "ei voitu tallentaa kumoustietoja" +#~ msgid "with Carbon GUI." +#~ msgstr "Carbon-GUIlla." -#~ msgid "" -#~ "E815: Sorry, this command is disabled, the MzScheme libraries could not " -#~ "be loaded." -#~ msgstr "E815: Sori, komento ei toimi, MzScheme-kirjastoa ei voitu ladata." +#~ msgid "with GUI." +#~ msgstr "GUIlla." -#~ msgid "invalid expression" -#~ msgstr "virheellinen ilmaus" +#~ msgid "with Photon GUI." +#~ msgstr "Photon-GUIlla." -#~ msgid "expressions disabled at compile time" -#~ msgstr "ilmaukset poistettu käytöstä käännösaikana" +#~ msgid "with X11-Athena GUI." +#~ msgstr "X11-Athena-GUIlla." -#~ msgid "hidden option" -#~ msgstr "piilotettu asetus" +#~ msgid "with X11-neXtaw GUI." +#~ msgstr "X11-neXtaw-GUIlla." -#~ msgid "unknown option" -#~ msgstr "tuntematon asetus" +#~ msgid "with X11-Motif GUI." +#~ msgstr "X11-Motif-GUIlla." -#~ msgid "window index is out of range" -#~ msgstr "ikkunan indeksi alueen ulkopuolella" +#~ msgid "with GTK2 GUI." +#~ msgstr "GTK2-GUIlla." -#~ msgid "couldn't open buffer" -#~ msgstr "ei voitu avata puskuria" +#~ msgid "with GTK2-GNOME GUI." +#~ msgstr "GTK2-Gnome-GUIlla." -#~ msgid "cannot delete line" -#~ msgstr "ei voitu poistaa riviä" +#~ msgid "with GTK3 GUI." +#~ msgstr "GTK3-GUIlla." -#~ msgid "cannot replace line" -#~ msgstr "ei voitu korvata riviä" +#~ msgid "without GUI." +#~ msgstr "ilman GUIta." -#~ msgid "cannot insert line" -#~ msgstr "ei voitu lisätä riviä" +#~ msgid "" +#~ "\n" +#~ "Tiny version " +#~ msgstr "" +#~ "\n" +#~ "Tiny-versio " -#~ msgid "string cannot contain newlines" -#~ msgstr "merkkijono ei saa sisältää rivinvaihtoja" +#~ msgid "" +#~ "\n" +#~ "Small version " +#~ msgstr "" +#~ "\n" +#~ "Small-versio " -#~ msgid "Vim error: ~a" -#~ msgstr "Vim-virhe: ~a" +#~ msgid "" +#~ "\n" +#~ "Normal version " +#~ msgstr "" +#~ "\n" +#~ "Normal-versio " -#~ msgid "Vim error" -#~ msgstr "Vim-virhe" +#~ msgid "" +#~ "\n" +#~ "Big version " +#~ msgstr "" +#~ "\n" +#~ "Big-version " -#~ msgid "buffer is invalid" -#~ msgstr "puskuri on virheellinen" +#~ msgid "" +#~ "\n" +#~ "Huge version " +#~ msgstr "" +#~ "\n" +#~ "Huge-versio " -#~ msgid "window is invalid" -#~ msgstr "ikkuna on virheellinen" +#~ msgid "Modified by " +#~ msgstr "Muokannut " -#~ msgid "linenr out of range" -#~ msgstr "rivinumero arvoalueen ulkopuolelta" +#~ msgid "" +#~ "\n" +#~ "Included patches: " +#~ msgstr "" +#~ "\n" +#~ "Pätsit: " -#~ msgid "not allowed in the Vim sandbox" -#~ msgstr "ei sallittu Vimin hiekkalaatikossa" +#~ msgid "" +#~ "\n" +#~ "OpenVMS version" +#~ msgstr "" +#~ "\n" +#~ "OpenVMS-version" -#~ msgid "E836: This Vim cannot execute :python after using :py3" +#~ msgid "" +#~ "\n" +#~ "MacOS version" #~ msgstr "" -#~ "E836: Python: Ei voi käyttää komentoja :py ja :py3 samassa istunnossa" +#~ "\n" +#~ "MacOS-version" -#~ msgid "E837: This Vim cannot execute :py3 after using :python" +#~ msgid "" +#~ "\n" +#~ "MacOS X version" #~ msgstr "" -#~ "E837: Python: Ei voi käyttää komentoja :py ja :py3 samassa istunnossa" +#~ "\n" +#~ "MacOS X-version" #~ msgid "" -#~ "E263: Sorry, this command is disabled, the Python library could not be " -#~ "loaded." +#~ "\n" +#~ "MacOS X (unix) version" #~ msgstr "" -#~ "E263: Sori, komento ei toimi, Python-kirjaston lataaminen ei onnistunut." +#~ "\n" +#~ "MacOS X-version (unix)" -#~ msgid "can't delete OutputObject attributes" -#~ msgstr "ei voi poistaa OutputObject-attribuutteja" +#~ msgid "" +#~ "\n" +#~ "MS-Windows 32-bit console version" +#~ msgstr "" +#~ "\n" +#~ "MS-Windows 32-bittinen konsoliversio" -#~ msgid "softspace must be an integer" -#~ msgstr "softspacen pitää olla kokonaisluku" +#~ msgid "" +#~ "\n" +#~ "MS-Windows 64-bit console version" +#~ msgstr "" +#~ "\n" +#~ "MS-Windows 32-bittinen konsoliversio" -#~ msgid "invalid attribute" -#~ msgstr "virheellinen attribuutti" +#~ msgid " with OLE support" +#~ msgstr " OLE-tuella" -#~ msgid "<buffer object (deleted) at %p>" -#~ msgstr "<puskuriolio (poistettu) kohdassa %p>" +#~ msgid " in Win32s mode" +#~ msgstr " Win32s-tilassa" -#~ msgid "E659: Cannot invoke Python recursively" -#~ msgstr "E659: Pythonia ei voi kutsua rekursiivisesti" +#~ msgid "" +#~ "\n" +#~ "MS-Windows 32-bit GUI version" +#~ msgstr "" +#~ "\n" +#~ "MS-Windows 32-bittinen GUI-version" -#~ msgid "E265: $_ must be an instance of String" -#~ msgstr "E265: muuttujan $_ pitää olla Stringin instanssi" +#~ msgid "" +#~ "\n" +#~ "MS-Windows 64-bit GUI version" +#~ msgstr "" +#~ "\n" +#~ "MS-Windows 64-bittinen GUI-versio" #~ msgid "" -#~ "E266: Sorry, this command is disabled, the Ruby library could not be " -#~ "loaded." -#~ msgstr "E266: Sori, komento ei toimi, Ruby-kirjastoa ei voitu ladata." +#~ "\n" +#~ "MS-Windows 16/32-bit GUI version" +#~ msgstr "" +#~ "\n" +#~ "MS-Windows 16- t. 32-bittinen GUI-versio" -#~ msgid "E267: unexpected return" -#~ msgstr "E267: odotuksenvastainen return" +#~ msgid "E827: Undo file is encrypted: %s" +#~ msgstr "E827: Kumoustiedosto on salattu: %s" -#~ msgid "E268: unexpected next" -#~ msgstr "E268: Odotuksenvastainen next" +#~ msgid "E826: Undo file decryption failed: %s" +#~ msgstr "E826: Kumoustiedoston purku epäonnistui: %s" -#~ msgid "E269: unexpected break" -#~ msgstr "E269: Odotuksenvastainen break" +#~ msgid "E832: Non-encrypted file has encrypted undo file: %s" +#~ msgstr "E832: Salaamattomalla tiedostolla on salattu kumoustiedosto: %s" -#~ msgid "E270: unexpected redo" -#~ msgstr "E270: odotuksenvastainen redo" +#~ msgid "No undo possible; continue anyway" +#~ msgstr "Ei voi kumota, jatketaan silti" -#~ msgid "E271: retry outside of rescue clause" -#~ msgstr "E271: retry rescuen ulkopuolella" +#~ msgid "Used CUT_BUFFER0 instead of empty selection" +#~ msgstr "Käytettiin CUT_BUFFER0:aa tyhjän valinnan sijaan" -#~ msgid "E272: unhandled exception" -#~ msgstr "E272: käsittelemätön poikkeus" +#~ msgid "new shell started\n" +#~ msgstr "uusi kuori avattu\n" -#~ msgid "E273: unknown longjmp status %d" -#~ msgstr "E273: tuntematon longjmp-tila %d" +#~ msgid "Cannot open $VIMRUNTIME/rgb.txt" +#~ msgstr "Ei voida avata tiedostoa $VIMRUNTIME/rgb.txt" -#~ msgid "Toggle implementation/definition" -#~ msgstr "Vaihda toteutuksen ja määritelmän välillä" +#~ msgid "" +#~ "\n" +#~ "--- Terminal keys ---" +#~ msgstr "" +#~ "\n" +#~ "--- Terminaalinäppäimet ---" -#~ msgid "Show base class of" -#~ msgstr "Näytä kantaluokka kohteelle" +#~ msgid "E437: terminal capability \"cm\" required" +#~ msgstr "E437: terminaalilla pitää olla cm kyvyissään" -#~ msgid "Show overridden member function" -#~ msgstr "Näytä korvattu jäsenfunktio" +#~ msgid "E436: No \"%s\" entry in termcap" +#~ msgstr "E436: %s ei löytynyt termcapista" -#~ msgid "Retrieve from file" -#~ msgstr "Jäljitä tiedostosta" +#~ msgid "E559: Terminal entry not found in termcap" +#~ msgstr "E559: Terminaalia ei löytynyt termcapista" -#~ msgid "Retrieve from project" -#~ msgstr "Jäljitä projektista" +#~ msgid "E558: Terminal entry not found in terminfo" +#~ msgstr "E558: Terminaalia ei löytynyt terminfosta" -#~ msgid "Retrieve from all projects" -#~ msgstr "Jäljitä kaikista projekteista" +#~ msgid "E557: Cannot open termcap file" +#~ msgstr "E557: Ei voi avata termcap-tiedostoa" -#~ msgid "Retrieve" -#~ msgstr "Jäljitä" +#~ msgid "defaulting to '" +#~ msgstr "oletusarvona " -#~ msgid "Show source of" -#~ msgstr "Näytä lähdekoodi kohteelle" +#~ msgid "' not known. Available builtin terminals are:" +#~ msgstr " ei tunnettu. Tuetut terminaalit:" -#~ msgid "Find symbol" -#~ msgstr "Etsi symboli" +#~ msgid "E430: Tag file path truncated for %s\n" +#~ msgstr "E430: Tägitiedoston polku katkaistu kohdassa %s\n" -#~ msgid "Browse class" -#~ msgstr "Selaa luokkaa" +#~ msgid "E422: terminal code too long: %s" +#~ msgstr "E422: terminaalikoodi liian pitkä: %s" -#~ msgid "Show class in hierarchy" -#~ msgstr "Näytä luokka hierarkiassa" +#~ msgid "E845: Insufficient memory, word list will be incomplete" +#~ msgstr "E845: Muisti ei riitä, sanalista jää keskeneräiseksi" + +#~ msgid "Conversion in %s not supported" +#~ msgstr "Muutosta kohteessa %s ei tueta" -#~ msgid "Show class in restricted hierarchy" -#~ msgstr "Näytä luokka rajoitetussa hierarkiassa" +#~ msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" +#~ msgstr "Varoitus: Ei löydetty sanalistaa %s_%s.spl tai %s_ascii.spl" -#~ msgid "Xref refers to" -#~ msgstr "Xref viittaa kohteeseen" +#~ msgid "" +#~ "\n" +#~ "# Last %sSearch Pattern:\n" +#~ "~" +#~ msgstr "" +#~ "\n" +#~ "# Edellinen %sHakulauseke:\n" +#~ "~" -#~ msgid "Xref referred by" -#~ msgstr "Xref viitattu kohteesta" +#~ msgid "Substitute " +#~ msgstr "Korvaa " -#~ msgid "Xref has a" -#~ msgstr "Xref sisältää kohteen" +#~ msgid "(NFA) COULD NOT OPEN %s !" +#~ msgstr "(NFA) EI VOI AVATA KOHDETTA %s" -#~ msgid "Xref used by" -#~ msgstr "Xrefiä käyttää" +#~ msgid "" +#~ "Could not open temporary log file for writing, displaying on stderr ... " +#~ msgstr "" +#~ "Ei voitu avata väliaikaislokitiedosta kirjoittamista varten, joten " +#~ "virheet näytetään vakiovirhevirrassa. " -#~ msgid "Show docu of" -#~ msgstr "Näytä dokumentti kohteelle" +#~ msgid "E878: (NFA) Could not allocate memory for branch traversal!" +#~ msgstr "E878: (NFA) Ei voitu allokoida muistia polkujen läpikäyntiin" -#~ msgid "Generate docu for" -#~ msgstr "Luo dokumentti kohteelle" +#~ msgid "E876: (NFA regexp) Not enough space to store the whole NFA " +#~ msgstr "E876: (NFA regexp) Tila ei riitä NFA:n tallentamiseen" #~ msgid "" -#~ "Cannot connect to SNiFF+. Check environment (sniffemacs must be found in " -#~ "$PATH).\n" +#~ "E875: (NFA regexp) (While converting from postfix to NFA), too many " +#~ "states left on stack" #~ msgstr "" -#~ "Ei voida yhdistää SNiFF+:aan. Tarkista ympäristömuuttujat (sniffemacsin " -#~ "löytyä polkumuuttujasta $PATH).\n" +#~ "E875: (NFA regexp) (Muunnettaessa postfixistä NFA:ksi), liikaa tiloja " +#~ "jäljellä pinossa" -#~ msgid "E274: Sniff: Error during read. Disconnected" -#~ msgstr "E274: Sniff: Virhe luettaessa, yhteys katkaistu" +#~ msgid "E874: (NFA) Could not pop the stack !" +#~ msgstr "E874: (NFA) Ei voida poistaa pinosta" -#~ msgid "SNiFF+ is currently " -#~ msgstr "SNiFF+ " +#~ msgid "E873: (NFA regexp) proper termination error" +#~ msgstr "E873: (NFA regexp) oikea lopetusvirhe" -#~ msgid "not " -#~ msgstr "ei ole " +#~ msgid "E879: (NFA regexp) Too many \\z(" +#~ msgstr "E879: (NFA regexp) Liikaa merkkejä \\z(" -#~ msgid "connected" -#~ msgstr "yhdistetty" +#~ msgid "E872: (NFA regexp) Too many '('" +#~ msgstr "E872: (NFA regexp) Liian monta suljetta '('" -#~ msgid "E275: Unknown SNiFF+ request: %s" -#~ msgstr "E275: Tuntematon SNiFF+-pyyntö: %s" +#~ msgid "E871: (NFA regexp) Can't have a multi follow a multi !" +#~ msgstr "E871: (NFA regexp) Multi ei voi seurata multia" -#~ msgid "E276: Error connecting to SNiFF+" -#~ msgstr "E276: Virhe yhdistettäessä SNiFF+:aan" +#~ msgid "E870: (NFA regexp) Error reading repetition limits" +#~ msgstr "E870: (NFA regexp) Virhe luettaessa toiston määriä" -#~ msgid "E278: SNiFF+ not connected" -#~ msgstr "E278: SNiFF+ ei ole yhdistetty" +#~ msgid "E869: (NFA) Unknown operator '\\@%c'" +#~ msgstr "E869: (NFA) Tuntematon operaattori '\\@%c'" -#~ msgid "E279: Not a SNiFF+ buffer" -#~ msgstr "E279: Ei ole SNiFF+-puskuri" +#~ msgid "E868: Error building NFA with equivalence class!" +#~ msgstr "E868: Virhe NFA:n ekvivalenssiluokkia tekemisessä" -#~ msgid "Sniff: Error during write. Disconnected" -#~ msgstr "Sniff: Virhe kirjoituksessa, yhteys katkaistu" +#~ msgid "E867: (NFA) Unknown operator '\\%%%c'" +#~ msgstr "E867: (NFA) Tuntematon operaattori '\\%%%c'" -#~ msgid "invalid buffer number" -#~ msgstr "virheellinen puskurinumero" +#~ msgid "E867: (NFA) Unknown operator '\\z%c'" +#~ msgstr "E867: (NFA) Tuntematon operaattori '\\z%c'" -#~ msgid "not implemented yet" -#~ msgstr "ei toteutettu" +#~ msgid "E877: (NFA regexp) Invalid character class: %ld" +#~ msgstr "E877: (NFA regexp) Virheellinen merkkiluokka: %ld" -#~ msgid "cannot set line(s)" -#~ msgstr "ei voi asettaa rivejä" +#~ msgid "E866: (NFA regexp) Misplaced %c" +#~ msgstr "E866: (NFA-regexp) %c väärässä paikassa" -#~ msgid "invalid mark name" -#~ msgstr "virheellinen merkin nimi" +#~ msgid "E865: (NFA) Regexp end encountered prematurely" +#~ msgstr "E865: (NFA) Säännöllisen ilmauksen ennenaikainen loppu" -#~ msgid "mark not set" -#~ msgstr "merkko ei ole asetettu" +#~ msgid "Error file" +#~ msgstr "Virhetiedosto" -#~ msgid "row %d column %d" -#~ msgstr "rivi %d sarake %d" +#~ msgid "shell returned %d" +#~ msgstr "kuori palautti arvon %d" -#~ msgid "cannot insert/append line" -#~ msgstr "rivin lisäys ei onnistu" +#~ msgid "Vim Warning" +#~ msgstr "Vim-varoitus" -#~ msgid "line number out of range" -#~ msgstr "rivinumero arvoalueen ulkopuolella" +#~ msgid "" +#~ "VIMRUN.EXE not found in your $PATH.\n" +#~ "External commands will not pause after completion.\n" +#~ "See :help win32-vimrun for more information." +#~ msgstr "" +#~ "VIMRUN.EXEä ei löydy muuttujasta $PATH.\n" +#~ "Ulkoiset komennot eivät pysähdy suorituksen lopussa.\n" +#~ "Lisätietoja komennolla :help win32-vimrun" -#~ msgid "unknown flag: " -#~ msgstr "tuntematon asetus: " +#~ msgid "E371: Command not found" +#~ msgstr "E371: Komentoa ei löydy" -#~ msgid "unknown vimOption" -#~ msgstr "tuntematon vimOption" +#~ msgid "shutdown" +#~ msgstr "sammutus" -#~ msgid "keyboard interrupt" -#~ msgstr "näppäimistökeskeytys" +#~ msgid "logoff" +#~ msgstr "uloskirjautuminen" -#~ msgid "vim error" -#~ msgstr "vim-virhe" +#~ msgid "close" +#~ msgstr "sulkeminen" -#~ msgid "cannot create buffer/window command: object is being deleted" -#~ msgstr "ei voi luoda puskuri- tai ikkunakomentoa, olio on poistumassa" +#~ msgid "Vim: Caught %s event\n" +#~ msgstr "Vim: Napattiin %s\n" + +#~ msgid "Could not fix up function pointers to the DLL!" +#~ msgstr "Ei voitu korjata funktio-osoittimia DLL:ssä" + +#~ msgid "VIM Error" +#~ msgstr "VIM-virhe" + +#~ msgid "Could not load vim32.dll!" +#~ msgstr "Vim32.dll:ää ei voitu ladata" + +#~ msgid "At line" +#~ msgstr "Rivillä" + +#~ msgid "XSMP SmcOpenConnection failed: %s" +#~ msgstr "XSMP SmcOpenConnection epäonnistui: %s" + +#~ msgid "XSMP ICE connection watch failed" +#~ msgstr "XSMP:n ICE-yhteyden tarkkailu epäonnistui" + +#~ msgid "XSMP opening connection" +#~ msgstr "XSMP avaa yhteyttä" + +#~ msgid "XSMP handling save-yourself request" +#~ msgstr "XSMP käsittelee save-yourself-pyyntöä" + +#~ msgid "Opening the X display failed" +#~ msgstr "X-näytön avaus epäonnistui" + +#~ msgid "XSMP lost ICE connection" +#~ msgstr "XSMP kadotti ICE-yhteyden" #~ msgid "" -#~ "cannot register callback command: buffer/window is already being deleted" -#~ msgstr "callbackia ei voi rekisteröidä: puskuri tai ikkuna on poistettu" +#~ "\n" +#~ "Command terminated\n" +#~ msgstr "" +#~ "\n" +#~ "Komento loppui\n" #~ msgid "" -#~ "E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-" -#~ "dev@vim.org" +#~ "\n" +#~ "Cannot execute shell " #~ msgstr "" -#~ "E280: kriittinen TCL-virhe: reflist hajalla? Ilmoita asiasta " -#~ "postituslistalle vim-dev@vim.org" +#~ "\n" +#~ "Kuoren suoritus ei onnistu " -#~ msgid "cannot register callback command: buffer/window reference not found" +#~ msgid "" +#~ "\n" +#~ "Cannot fork\n" #~ msgstr "" -#~ "callbackia ei voi rekisteröidä: puskurin tai ikkunan viitettä ei löydy" +#~ "\n" +#~ "Ei voi haarauttaa\n" #~ msgid "" -#~ "E571: Sorry, this command is disabled: the Tcl library could not be " -#~ "loaded." -#~ msgstr "E571: Sori, komento ei toimi, Tcl-kirjastoa ei voitu ladata." +#~ "\n" +#~ "Cannot create pipes\n" +#~ msgstr "" +#~ "\n" +#~ "Putkia ei voi tehdä\n" #~ msgid "" -#~ "E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim." -#~ "org" +#~ "\n" +#~ "Cannot execute shell sh\n" #~ msgstr "" -#~ "E281: TCL-virhe: lopetuskoodi ei ole kokonaisluku? Ilmoita asiasta " -#~ "postituslistalle vim-dev@vim.org" +#~ "\n" +#~ "Kuoren sh suoritus ei onnistu\n" -#~ msgid "E572: exit code %d" -#~ msgstr "E572: palautusarvo %d" +# mikä security context? +#~ msgid "Could not get security context %s for %s. Removing it!" +#~ msgstr "Ei saatu turvallisuuskontekstia %s kohteelle %s ja se poistetaan" -#~ msgid "cannot get line" -#~ msgstr "ei voida hakea riviä" +#~ msgid "Could not set security context %s for %s" +#~ msgstr "Ei voitu asettaa turvallisuuskontekstia %s kohteelle %s" -#~ msgid "Unable to register a command server name" -#~ msgstr "Komentopalvelimen nimen rekisteröinti ei onnistu" +#~ msgid "Opening the X display timed out" +#~ msgstr "X-näytön avaus aikakatkaistiin" -#~ msgid "E248: Failed to send command to the destination program" -#~ msgstr "E248: Komennon lähetys kohdeohjelmalle ei onnistu" +#~ msgid "Testing the X display failed" +#~ msgstr "X-näytön testaus epäonnistui" -#~ msgid "E573: Invalid server id used: %s" -#~ msgstr "E573: Virheellinen palvelimen tunniste: %s" +#~ msgid "" +#~ "\n" +#~ "Vim: Got X error\n" +#~ msgstr "" +#~ "\n" +#~ "Vim: X-virhe\n" -#~ msgid "E251: VIM instance registry property is badly formed. Deleted!" -#~ msgstr "E251: VIMin instanssin rekisteriarvo on virheellinen, poistettiin." +#~ msgid "Opening the X display took %ld msec" +#~ msgstr "X-näytön avaus vei %ld millisekuntia" -#~ msgid "netbeans is not supported with this GUI\n" -#~ msgstr "netbeans ei toimi tässä käyttöliittymässä\n" +#~ msgid "E245: Illegal char '%c' in font name \"%s\"" +#~ msgstr "E245: Virheellinen merkki %c fontin nimessä %s" -#~ msgid "This Vim was not compiled with the diff feature." -#~ msgstr "Tähän Vimiin ei ole käännetty diff-toimintoja mukaan." +#~ msgid "E244: Illegal quality name \"%s\" in font name \"%s\"" +#~ msgstr "E244: Virheellinen laatunimi %s fontin nimessä %s" -#~ msgid "'-nb' cannot be used: not enabled at compile time\n" -#~ msgstr "-nb:tä ei voi käyttää, koska sitä ei käännetty mukaan\n" +#~ msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" +#~ msgstr "E244: Virheellinen merkistön nimi %s fontin nimessä %s" -#~ msgid "Vim: Error: Failure to start gvim from NetBeans\n" -#~ msgstr "Vim: Virhe: Gvimin käynnistys NetBeansistä ei onnistu\n" +#~ msgid "Printing '%s'" +#~ msgstr "Tulostetaan %s" + +#~ msgid "E238: Print error: %s" +#~ msgstr "E238: Tulostinvirhe: %s" + +#~ msgid "E613: Unknown printer font: %s" +#~ msgstr "E613: Tuntematon tulostimen fontti: %s" + +#~ msgid "to %s on %s" +#~ msgstr "tulostimelle %s kohteessa %s" + +#~ msgid "E237: Printer selection failed" +#~ msgstr "E237: Tulostimen valinta epäonnistui" + +#~ msgid "'columns' is not 80, cannot execute external commands" +#~ msgstr "columns ei ole 80, ei voi suorittaa ulkoista komentoa" + +#~ msgid "I/O ERROR" +#~ msgstr "IO-virhe" + +#~ msgid "ANCHOR_BUF_SIZE too small." +#~ msgstr "ANCHOR_BUF_SIZE liian pieni." + +#~ msgid " returned\n" +#~ msgstr " palautti\n" + +#~ msgid "shell " +#~ msgstr "kuori " + +#~ msgid "Cannot execute " +#~ msgstr "Ei voi suorittaa " + +#~ msgid "E360: Cannot execute shell with -f option" +#~ msgstr "E360: Kuorta ei voi avata asetuksella -f" + +#~ msgid "mch_get_shellsize: not a console??\n" +#~ msgstr "mch_get_shellsize: ei ole konsoli?\n" + +#~ msgid "cannot change console mode ?!\n" +#~ msgstr "ei voi vaihtaa konsolitilaa?\n" + +#~ msgid "Vim exiting with %d\n" +#~ msgstr "Vim sulkeutuu koodilla %d\n" + +#~ msgid "Cannot create " +#~ msgstr "Ei voi luoda " + +#~ msgid "Cannot open NIL:\n" +#~ msgstr "Ei voi avata NILiä:\n" + +#~ msgid "Need %s version %ld\n" +#~ msgstr "Tarvitaan %s versio %ld\n" + +#~ msgid "Need Amigados version 2.04 or later\n" +#~ msgstr "Amigados 2.04 tai uudempi tarvitaan\n" + +#~ msgid "VIM: Can't open window!\n" +#~ msgstr "VIM: Ei voi avata ikkunaa\n" + +#~ msgid "cannot open " +#~ msgstr "ei voi avata " + +#~ msgid "E538: No mouse support" +#~ msgstr "E538: Hiirtä ei tueta" + +#~ msgid "E533: can't select wide font" +#~ msgstr "E533: Leveän fontin valinta ei onnistu" + +#~ msgid "E598: Invalid fontset" +#~ msgstr "E598: Viallinen fontset" + +#~ msgid "E597: can't select fontset" +#~ msgstr "E597: Fontsetin valinta ei onnistu" + +#~ msgid "E596: Invalid font(s)" +#~ msgstr "E596: Viallisia fontteja" + +#~ msgid "E617: Cannot be changed in the GTK+ 2 GUI" +#~ msgstr "E617: Ei voi muuttaa GTK+2-GUIssa" + +#~ msgid "E531: Use \":gui\" to start the GUI" +#~ msgstr "E531: Käytä komentoa :gui GUIn käynnistämiseen" + +#~ msgid "E530: Cannot change term in GUI" +#~ msgstr "E530: Ei voi vaihtaa termiä GUIssa" + +#~ msgid "E522: Not found in termcap" +#~ msgstr "E522: Puuttuu termcapista" + +#~ msgid "Thanks for flying Vim" +#~ msgstr "Kiitos että ajoit Vimiä" + +#~ msgid "%<%f%h%m%=Page %N" +#~ msgstr "%<%f%h%m%=Sivu %N" #~ msgid "" #~ "\n" -#~ "Where case is ignored prepend / to make flag upper case" +#~ "# Registers:\n" #~ msgstr "" #~ "\n" -#~ "Jos aakkoslaji on ohitettu, lisää alkuun / tehdäksesi asetuksesta " -#~ "suuraakkosia" +#~ "# Rekisterit:\n" -#~ msgid "-register\t\tRegister this gvim for OLE" -#~ msgstr "-register\t\trekisteröi gvim OLEa varten" +#~ msgid "Illegal register name" +#~ msgstr "Virheellinen rekisterin nimi" -#~ msgid "-unregister\t\tUnregister gvim for OLE" -#~ msgstr "-unregister\t\tPoista gvim OLE-rekisteristä" +#~ msgid "freeing %ld lines" +#~ msgstr "vapautetaan %ld riviä" -#~ msgid "-g\t\t\tRun using GUI (like \"gvim\")" -#~ msgstr "-g\t\t\tAvaa GUI (kuten gvimillä)" +#~ msgid "cannot yank; delete anyway" +#~ msgstr "Ei voi kopioida; poista joka tapauksessa" -#~ msgid "-f or --nofork\tForeground: Don't fork when starting GUI" -#~ msgstr "-f tai --nofork\tEdustalle: Älä haarauta GUIn käynnistyksessä" +#~ msgid "E775: Eval feature not available" +#~ msgstr "E775: Eval ei ole käytettävissä" -#~ msgid "-f\t\t\tDon't use newcli to open window" -#~ msgstr "-f\t\t\tÄlä käytä newcli:tä ikkunan avaamiseen" +#~ msgid "E505: %s is read-only (add ! to override)" +#~ msgstr "E505: %s on kirjoitussuojattu (lisää komentoon ! ohittaaksesi)" -#~ msgid "-dev <device>\t\tUse <device> for I/O" -#~ msgstr "-dev <laite>\t\tKäytä <laitetta> IO:hon" +#~ msgid "E511: netbeans already connected" +#~ msgstr "E511: netbeans on yhdistetty jo" -#~ msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" -#~ msgstr "-U <gvimrc>\t\tKäytä <gvimrc>-tiedostoa .gvimrc:iden sijasta" +#~ msgid "E838: netbeans is not supported with this GUI" +#~ msgstr "E838: netbeans ei toimi tässä käyttöliittymässä" -#~ msgid "-x\t\t\tEdit encrypted files" -#~ msgstr "-x\t\t\tMuokkaa salattua tiedostoa" +#~ msgid "E658: NetBeans connection lost for buffer %ld" +#~ msgstr "E658: NetBeans-yhteys katkesi puskurille %ld" -#~ msgid "-display <display>\tConnect vim to this particular X-server" -#~ msgstr "-display <näyttö>\tYhdistä vim tiettyyn X-palvelimeen" +#~ msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" +#~ msgstr "E668: Väärä avaustila NetBeans-yhteyden infotiedostolle: %s" -#~ msgid "-X\t\t\tDo not connect to X server" -#~ msgstr "-X\t\t\tÄlä yhdistä X-palvelimeen" +#~ msgid "E547: Illegal mouseshape" +#~ msgstr "E547: Virheellinen hiiren muoto" -#~ msgid "--remote <files>\tEdit <files> in a Vim server if possible" -#~ msgstr "" -#~ "--remote <tiedostoja>\tMuokkaa <tiedostoja> Vim-palvelimessa, jos " -#~ "mahdollista" +#~ msgid "E341: Internal error: lalloc(%ld, )" +#~ msgstr "E341: Sisäinen virhe: lalloc(%ld, )" -#~ msgid "--remote-silent <files> Same, don't complain if there is no server" -#~ msgstr "" -#~ "--remote-silent <tiedostoja>\tSama, mutta älä ilmoita puuttuvasta " -#~ "palvelimesta" +#~ msgid "E340: Line is becoming too long" +#~ msgstr "E340: Rivistä tulee liian pitkä" #~ msgid "" -#~ "--remote-wait <files> As --remote but wait for files to have been edited" +#~ "[calls] total re/malloc()'s %lu, total free()'s %lu\n" +#~ "\n" #~ msgstr "" -#~ "--remote-wait <tiedostoja> kuten --remote, mutta odota tiedostojen " -#~ "muokkaamista" +#~ "[kutsut] yht. re/malloc() %lu, yht. free() %lu\n" +#~ "\n" #~ msgid "" -#~ "--remote-wait-silent <files> Same, don't complain if there is no server" +#~ "\n" +#~ "[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n" #~ msgstr "" -#~ "--remote-wait-silent <tiedostoja> sama, mutta älä ilmoita puuttuvasta " -#~ "palvelimesta" +#~ "\n" +#~ "[tavua] yht. alloc-free %lu-%lu, käytössä %lu, käyttöhuippu %lu\n" -#~ msgid "" -#~ "--remote-tab[-wait][-silent] <files> As --remote but use tab page per " -#~ "file" -#~ msgstr "" -#~ "--remote-tab[-wait][-silent] <tiedostoja> kuten --remote, mutta avaa " -#~ "välilehti joka tiedostolle" +#~ msgid "ERROR: " +#~ msgstr "VIRHE: " -#~ msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" -#~ msgstr "" -#~ "--remote-send <näppäimiä>\tLähetä <näppäimiä> painalluksina Vimille ja " -#~ "lopeta" +#~ msgid "E338: Sorry, no file browser in console mode" +#~ msgstr "E338: tiedostonselain puuttuu konsolitilasta" -#~ msgid "" -#~ "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" -#~ msgstr "" -#~ "--remote-expr <ilmaus>\tKäsittele <ilmaus> Vim-palvelimella ja tulosta " -#~ "tulos" +#~ msgid "Open File dialog" +#~ msgstr "Avausikkuna" -#~ msgid "--serverlist\t\tList available Vim server names and exit" -#~ msgstr "--serverlist\t\tLuettele Vim-palvelinten nimet ja lopeta" +#~ msgid "Save File dialog" +#~ msgstr "Tallennusikkuna" -#~ msgid "--servername <name>\tSend to/become the Vim server <name>" -#~ msgstr "--servername <nimi>\tLähetä Vim-palvelimelle <nimi> tai luo se" +#~ msgid "Select Directory dialog" +#~ msgstr "Hakemiston valintaikkuna" + +#~ msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>" +#~ msgstr "Käännöksen ylläpitäjä: Flammie Pirinen <flammie@iki.fi>" + +#~ msgid "E337: Menu not found - check menu names" +#~ msgstr "E337: Valikkoa ei löytynyt - tarkista valikkojen nimet" + +#~ msgid "E336: Menu path must lead to a sub-menu" +#~ msgstr "E336: Valikkopolun pitää johtaa alivalikkoon" + +#~ msgid "Tear off this menu" +#~ msgstr "Repäise valikko irti" + +#~ msgid "Swap file already exists!" +#~ msgstr "Swap-tiedosto on jo olemassa" #~ msgid "" #~ "\n" -#~ "Arguments recognised by gvim (Motif version):\n" +#~ " [not usable with this version of Vim]" #~ msgstr "" #~ "\n" -#~ "Gvimin (Motif-version) tuntemat argumentit:\n" +#~ " [ei toimi tämän Vim-version kanssa]" + +#~ msgid "Using crypt key from swap file for the text file.\n" +#~ msgstr "Käytetään swäpin salausavainta tekstitiedostolle\n" #~ msgid "" #~ "\n" -#~ "Arguments recognised by gvim (neXtaw version):\n" +#~ "to use the same key for text file and swap file" #~ msgstr "" #~ "\n" -#~ "Gvimin (neXtaw-version) tuntemat argumentit:\n" +#~ "käyttääksesi samaa avainta teksti- ja swäppitiedostoille" #~ msgid "" #~ "\n" -#~ "Arguments recognised by gvim (Athena version):\n" +#~ "If you wrote the text file after changing the crypt key press enter" #~ msgstr "" #~ "\n" -#~ "Gvimin (Athena-version) tuntemat argumentit:\n" +#~ "Jos kirjoitit tekstitiedoston salausavaimen vaihdon jälkeen paina enteriä" -#~ msgid "-display <display>\tRun vim on <display>" -#~ msgstr "-display <näyttö>\tSuorita vim <näytössä>" +#~ msgid "" +#~ "\n" +#~ "enter the new crypt key." +#~ msgstr "" +#~ "\n" +#~ "anna uusi salausavain." -#~ msgid "-iconic\t\tStart vim iconified" -#~ msgstr "-iconic\t\tKäynnistä pienennettynä" +#~ msgid "" +#~ "\n" +#~ "If you entered a new crypt key but did not write the text file," +#~ msgstr "" +#~ "\n" +#~ "Jos käytit uutta salausavainta muttet kirjoittanut tekstitiedostoa," -#~ msgid "-background <color>\tUse <color> for the background (also: -bg)" -#~ msgstr "-background <väri>\tKäytä <väriä> taustavärinä (myös: -bg)" +#~ msgid "Swap file is encrypted: \"%s\"" +#~ msgstr "Swap-tiedosto on salattu: %s" -#~ msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" -#~ msgstr "-foreground <väri>\tKäytä <väriä> tekstin värinä (myös: -fg)" +#~ msgid "" +#~ "E833: %s is encrypted and this version of Vim does not support encryption" +#~ msgstr "E833: %s on salattu eikä tämä Vim tue salausta" -#~ msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" -#~ msgstr "-font <fontti>\t\tKäytä <fonttia> tekstissä (myös: -fn)" +#~ msgid "E843: Error while updating swap file crypt" +#~ msgstr "E843: Virhe päivitettäessä swapin kryptausta" -#~ msgid "-boldfont <font>\tUse <font> for bold text" -#~ msgstr "-boldfont <fontti>\tKäytä <fonttia> lihavoidussa tekstissä" +#~ msgid "E289: input method doesn't support my preedit type" +#~ msgstr "E289: syötemetodi ei tue tätä preedit-tyyppiä" -#~ msgid "-italicfont <font>\tUse <font> for italic text" -#~ msgstr "-italicfont <fontti>\tKäytä <fonttia> kursivoidussa tekstissä" +#~ msgid "E288: input method doesn't support any style" +#~ msgstr "E288: syötemetodi ei tue tyylejä" -#~ msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" +#~ msgid "E287: Warning: Could not set destroy callback to IM" #~ msgstr "" -#~ "-geometry <geom>\tKäytä mittoja <geom> ikkunan asetteluun (myös: -geom)" +#~ "E287: Varoitus: Ei voitu asettaa destroy-kutsua syötemetodipalvelimelle" -#~ msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" -#~ msgstr "-borderwidt <leveys>\tKäytä <leveyttä> reunuksissa (myös: -bw) " - -#~ msgid "" -#~ "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" -#~ msgstr "" -#~ "-scrollbarwidth <leveys> Käytä <leveyttä> vierityspalkissa (myös: -sw)" +#~ msgid "E286: Failed to open input method" +#~ msgstr "E286: Syötemetodin avaus ei onnistu" -#~ msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" -#~ msgstr "-menuheight <korkeus>\tKäytä <korkeutta> valikossa (myös: -mh)" +#~ msgid "E285: Failed to create input context" +#~ msgstr "E285: Syötekontekstin luonti ei onnistu" -#~ msgid "-reverse\t\tUse reverse video (also: -rv)" -#~ msgstr "-reverse\t\tKäytä käänteisvärejä (myös: -rv) " +#~ msgid "E284: Cannot set IC values" +#~ msgstr "E284: Ei voi asettaa IC-arvoja" -#~ msgid "+reverse\t\tDon't use reverse video (also: +rv)" -#~ msgstr "+reverse\t\tÄlä käytä käänteisvärejä (myös: +rv)" +#~ msgid "E543: Not a valid codepage" +#~ msgstr "E543: Koodisivu ei ole käypä" -#~ msgid "-xrm <resource>\tSet the specified resource" -#~ msgstr "-xrm <resurssi>\tAseta resurssi" +#~ msgid "Missing '>'" +#~ msgstr "> puuttuu" #~ msgid "" #~ "\n" -#~ "Arguments recognised by gvim (RISC OS version):\n" +#~ "# History of marks within files (newest to oldest):\n" #~ msgstr "" #~ "\n" -#~ "Gvimin (RISC OS -version) tuntemat argumentit:\n" - -#~ msgid "--columns <number>\tInitial width of window in columns" -#~ msgstr "--columns <luku>\tIkkunan alkuleveys sarakkeina" +#~ "# Tiedostojen merkkien historia (uusimmasta vanhimpaan):\n" -#~ msgid "--rows <number>\tInitial height of window in rows" -#~ msgstr "--rows <luku>\tIkkunan alkukorkeus riveinä" +#~ msgid "" +#~ "\n" +#~ "# Jumplist (newest first):\n" +#~ msgstr "" +#~ "\n" +#~ "# Hyppylista (uusin ensiksi):\n" #~ msgid "" #~ "\n" -#~ "Arguments recognised by gvim (GTK+ version):\n" +#~ "# File marks:\n" #~ msgstr "" #~ "\n" -#~ "Gvimin (GTK+-version) tuntemat argumentit:\n" +#~ "# Tiedoston merkit:\n" -#~ msgid "-display <display>\tRun vim on <display> (also: --display)" -#~ msgstr "-display <näyttö>\tSuorita vim näytöllä <näyttö> (myös: --display)" +#~ msgid ": Send expression failed.\n" +#~ msgstr ": Ilmauksen lähetys epäonnistui.\n" -# X-ikkunointijärjestelmässä saman sovelluksen saman luokan ikkunat -# tunnistetaan rooliresursseista -#~ msgid "--role <role>\tSet a unique role to identify the main window" -#~ msgstr "" -#~ "--role <rooli>\tAseta pääikkunalle ainutlaatuinen rooli tunnisteeksi" +#~ msgid "No display: Send expression failed.\n" +#~ msgstr "Ei näyttöä: Ilmauksen lähetys epäonnistui.\n" -#~ msgid "--socketid <xid>\tOpen Vim inside another GTK widget" -#~ msgstr "--socketid <xid>\tAvaa Vim annettuun GTK-olioon " +#~ msgid "%d of %d edited" +#~ msgstr "%d/%d muokattu" -#~ msgid "-P <parent title>\tOpen Vim inside parent application" -#~ msgstr "-P <otsikko>\tAvaa Vim isäntäohjelman sisään" +#~ msgid ": Send failed. Trying to execute locally\n" +#~ msgstr ": Lähetys epäonnistui. Yritetään suorittaa paikallisena\n" + +#~ msgid ": Send failed.\n" +#~ msgstr ": Lähetys epäonnistui.\n" + +#~ msgid "No display" +#~ msgstr "Ei näyttöä" #~ msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" #~ msgstr "--windowid <HWND>\tAvaa Vim annettuun win32-olioon " -#~ msgid "No display" -#~ msgstr "Ei näyttöä" +#~ msgid "-P <parent title>\tOpen Vim inside parent application" +#~ msgstr "-P <otsikko>\tAvaa Vim isäntäohjelman sisään" -#~ msgid ": Send failed.\n" -#~ msgstr ": Lähetys epäonnistui.\n" +#~ msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" +#~ msgstr "--echo-wid\t\tTulosta gvimin Window ID vakiotulosteeseen" -#~ msgid ": Send failed. Trying to execute locally\n" -#~ msgstr ": Lähetys epäonnistui. Yritetään suorittaa paikallisena\n" +#~ msgid "--socketid <xid>\tOpen Vim inside another GTK widget" +#~ msgstr "--socketid <xid>\tAvaa Vim annettuun GTK-olioon " -#~ msgid "%d of %d edited" -#~ msgstr "%d/%d muokattu" +# X-ikkunointijärjestelmässä saman sovelluksen saman luokan ikkunat +# tunnistetaan rooliresursseista +#~ msgid "--role <role>\tSet a unique role to identify the main window" +#~ msgstr "" +#~ "--role <rooli>\tAseta pääikkunalle ainutlaatuinen rooli tunnisteeksi" -#~ msgid "No display: Send expression failed.\n" -#~ msgstr "Ei näyttöä: Ilmauksen lähetys epäonnistui.\n" +#~ msgid "-display <display>\tRun vim on <display> (also: --display)" +#~ msgstr "-display <näyttö>\tSuorita vim näytöllä <näyttö> (myös: --display)" -#~ msgid ": Send expression failed.\n" -#~ msgstr ": Ilmauksen lähetys epäonnistui.\n" +#~ msgid "" +#~ "\n" +#~ "Arguments recognised by gvim (GTK+ version):\n" +#~ msgstr "" +#~ "\n" +#~ "Gvimin (GTK+-version) tuntemat argumentit:\n" -#~ msgid "E543: Not a valid codepage" -#~ msgstr "E543: Koodisivu ei ole käypä" +#~ msgid "-xrm <resource>\tSet the specified resource" +#~ msgstr "-xrm <resurssi>\tAseta resurssi" -#~ msgid "E285: Failed to create input context" -#~ msgstr "E285: Syötekontekstin luonti ei onnistu" +#~ msgid "+reverse\t\tDon't use reverse video (also: +rv)" +#~ msgstr "+reverse\t\tÄlä käytä käänteisvärejä (myös: +rv)" -#~ msgid "E286: Failed to open input method" -#~ msgstr "E286: Syötemetodin avaus ei onnistu" +#~ msgid "-reverse\t\tUse reverse video (also: -rv)" +#~ msgstr "-reverse\t\tKäytä käänteisvärejä (myös: -rv) " -#~ msgid "E287: Warning: Could not set destroy callback to IM" +#~ msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" +#~ msgstr "-menuheight <korkeus>\tKäytä <korkeutta> valikossa (myös: -mh)" + +#~ msgid "" +#~ "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" #~ msgstr "" -#~ "E287: Varoitus: Ei voitu asettaa destroy-kutsua syötemetodipalvelimelle" +#~ "-scrollbarwidth <leveys> Käytä <leveyttä> vierityspalkissa (myös: -sw)" -#~ msgid "E288: input method doesn't support any style" -#~ msgstr "E288: syötemetodi ei tue tyylejä" +#~ msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" +#~ msgstr "-borderwidt <leveys>\tKäytä <leveyttä> reunuksissa (myös: -bw) " -#~ msgid "E289: input method doesn't support my preedit type" -#~ msgstr "E289: syötemetodi ei tue tätä preedit-tyyppiä" +#~ msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" +#~ msgstr "" +#~ "-geometry <geom>\tKäytä mittoja <geom> ikkunan asetteluun (myös: -geom)" -#~ msgid "" -#~ "E833: %s is encrypted and this version of Vim does not support encryption" -#~ msgstr "E833: %s on salattu eikä tämä Vim tue salausta" +#~ msgid "-italicfont <font>\tUse <font> for italic text" +#~ msgstr "-italicfont <fontti>\tKäytä <fonttia> kursivoidussa tekstissä" -#~ msgid "Swap file is encrypted: \"%s\"" -#~ msgstr "Swap-tiedosto on salattu: %s" +#~ msgid "-boldfont <font>\tUse <font> for bold text" +#~ msgstr "-boldfont <fontti>\tKäytä <fonttia> lihavoidussa tekstissä" + +#~ msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" +#~ msgstr "-font <fontti>\t\tKäytä <fonttia> tekstissä (myös: -fn)" + +#~ msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" +#~ msgstr "-foreground <väri>\tKäytä <väriä> tekstin värinä (myös: -fg)" + +#~ msgid "-background <color>\tUse <color> for the background (also: -bg)" +#~ msgstr "-background <väri>\tKäytä <väriä> taustavärinä (myös: -bg)" + +#~ msgid "-iconic\t\tStart vim iconified" +#~ msgstr "-iconic\t\tKäynnistä pienennettynä" + +#~ msgid "-display <display>\tRun vim on <display>" +#~ msgstr "-display <näyttö>\tSuorita vim <näytössä>" #~ msgid "" #~ "\n" -#~ "If you entered a new crypt key but did not write the text file," +#~ "Arguments recognised by gvim (Athena version):\n" #~ msgstr "" #~ "\n" -#~ "Jos käytit uutta salausavainta muttet kirjoittanut tekstitiedostoa," +#~ "Gvimin (Athena-version) tuntemat argumentit:\n" #~ msgid "" #~ "\n" -#~ "enter the new crypt key." +#~ "Arguments recognised by gvim (neXtaw version):\n" #~ msgstr "" #~ "\n" -#~ "anna uusi salausavain." +#~ "Gvimin (neXtaw-version) tuntemat argumentit:\n" #~ msgid "" #~ "\n" -#~ "If you wrote the text file after changing the crypt key press enter" +#~ "Arguments recognised by gvim (Motif version):\n" #~ msgstr "" #~ "\n" -#~ "Jos kirjoitit tekstitiedoston salausavaimen vaihdon jälkeen paina enteriä" +#~ "Gvimin (Motif-version) tuntemat argumentit:\n" + +#~ msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo" +#~ msgstr "-i <viminfo>\t\tKäytä <viminfo>-tiedostoa .viminfon sijaan" + +#~ msgid "--servername <name>\tSend to/become the Vim server <name>" +#~ msgstr "--servername <nimi>\tLähetä Vim-palvelimelle <nimi> tai luo se" + +#~ msgid "--serverlist\t\tList available Vim server names and exit" +#~ msgstr "--serverlist\t\tLuettele Vim-palvelinten nimet ja lopeta" #~ msgid "" -#~ "\n" -#~ "to use the same key for text file and swap file" +#~ "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" #~ msgstr "" -#~ "\n" -#~ "käyttääksesi samaa avainta teksti- ja swäppitiedostoille" +#~ "--remote-expr <ilmaus>\tKäsittele <ilmaus> Vim-palvelimella ja tulosta " +#~ "tulos" -#~ msgid "Using crypt key from swap file for the text file.\n" -#~ msgstr "Käytetään swäpin salausavainta tekstitiedostolle\n" +#~ msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" +#~ msgstr "" +#~ "--remote-send <näppäimiä>\tLähetä <näppäimiä> painalluksina Vimille ja " +#~ "lopeta" #~ msgid "" -#~ "\n" -#~ " [not usable with this version of Vim]" +#~ "--remote-tab[-wait][-silent] <files> As --remote but use tab page per " +#~ "file" #~ msgstr "" -#~ "\n" -#~ " [ei toimi tämän Vim-version kanssa]" +#~ "--remote-tab[-wait][-silent] <tiedostoja> kuten --remote, mutta avaa " +#~ "välilehti joka tiedostolle" -#~ msgid "Tear off this menu" -#~ msgstr "Repäise valikko irti" +#~ msgid "" +#~ "--remote-wait-silent <files> Same, don't complain if there is no server" +#~ msgstr "" +#~ "--remote-wait-silent <tiedostoja> sama, mutta älä ilmoita puuttuvasta " +#~ "palvelimesta" -#~ msgid "Select Directory dialog" -#~ msgstr "Hakemiston valintaikkuna" +#~ msgid "" +#~ "--remote-wait <files> As --remote but wait for files to have been edited" +#~ msgstr "" +#~ "--remote-wait <tiedostoja> kuten --remote, mutta odota tiedostojen " +#~ "muokkaamista" -#~ msgid "Save File dialog" -#~ msgstr "Tallennusikkuna" +#~ msgid "--remote-silent <files> Same, don't complain if there is no server" +#~ msgstr "" +#~ "--remote-silent <tiedostoja>\tSama, mutta älä ilmoita puuttuvasta " +#~ "palvelimesta" -#~ msgid "Open File dialog" -#~ msgstr "Avausikkuna" +#~ msgid "--remote <files>\tEdit <files> in a Vim server if possible" +#~ msgstr "" +#~ "--remote <tiedostoja>\tMuokkaa <tiedostoja> Vim-palvelimessa, jos " +#~ "mahdollista" -#~ msgid "E338: Sorry, no file browser in console mode" -#~ msgstr "E338: Sori, tiedostonselain puuttuu konsolitilasta" +#~ msgid "-X\t\t\tDo not connect to X server" +#~ msgstr "-X\t\t\tÄlä yhdistä X-palvelimeen" -#~ msgid "Vim: preserving files...\n" -#~ msgstr "Vim: säästetään tiedostoja...\n" +#~ msgid "-display <display>\tConnect vim to this particular X-server" +#~ msgstr "-display <näyttö>\tYhdistä vim tiettyyn X-palvelimeen" -#~ msgid "Vim: Finished.\n" -#~ msgstr "Vim: Valmis.\n" +#~ msgid "-x\t\t\tEdit encrypted files" +#~ msgstr "-x\t\t\tMuokkaa salattua tiedostoa" -#~ msgid "ERROR: " -#~ msgstr "VIRHE: " +#~ msgid "+\t\t\tStart at end of file" +#~ msgstr "+\t\t\tAloita tiedoston lopusta" -#~ msgid "" -#~ "\n" -#~ "[bytes] total alloc-freed %<PRIu64>-%<PRIu64>, in use %<PRIu64>, peak use " -#~ "%<PRIu64>\n" -#~ msgstr "" -#~ "\n" -#~ "[tavua] yht. alloc-free %<PRIu64>-%<PRIu64>, käytössä %<PRIu64>, " -#~ "käyttöhuippu %<PRIu64>\n" +#~ msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" +#~ msgstr "-U <gvimrc>\t\tKäytä <gvimrc>-tiedostoa .gvimrc:iden sijasta" -#~ msgid "" -#~ "[calls] total re/malloc()'s %<PRIu64>, total free()'s %<PRIu64>\n" -#~ "\n" -#~ msgstr "" -#~ "[kutsut] yht. re/malloc() %<PRIu64>, yht. free() %<PRIu64>\n" -#~ "\n" +#~ msgid "--not-a-term\t\tSkip warning for input/output not being a terminal" +#~ msgstr "--not-a-term\t\tOhita varoitus siitä että i/o ei ole terminaali" -#~ msgid "E340: Line is becoming too long" -#~ msgstr "E340: Rivistä tulee liian pitkä" +#~ msgid "-T <terminal>\tSet terminal type to <terminal>" +#~ msgstr "-T <terminaali>\tAseta terminaalin tyypiksi <terminaali>" -#~ msgid "E341: Internal error: lalloc(%<PRId64>, )" -#~ msgstr "E341: Sisäinen virhe: lalloc(%<PRId64>, )" +#~ msgid "-F\t\t\tStart in Farsi mode" +#~ msgstr "-F\t\t\tkäynnistä farsi-tilassa" -#~ msgid "E547: Illegal mouseshape" -#~ msgstr "E547: Virheellinen hiiren muoto" +#~ msgid "-H\t\t\tStart in Hebrew mode" +#~ msgstr "-H\t\t\tkäynnistä heprea-tilassa" -#~ msgid "Enter encryption key: " -#~ msgstr "Anna salausavain: " +#~ msgid "-A\t\t\tstart in Arabic mode" +#~ msgstr "-A\t\t\tkäynnistä arabia-tilassa" -#~ msgid "Enter same key again: " -#~ msgstr "Anna sama avain uudestaan: " +#~ msgid "-dev <device>\t\tUse <device> for I/O" +#~ msgstr "-dev <laite>\t\tKäytä <laitetta> IO:hon" -#~ msgid "Keys don't match!" -#~ msgstr "Avaimet eivät täsmää!" +#~ msgid "-f\t\t\tDon't use newcli to open window" +#~ msgstr "-f\t\t\tÄlä käytä newcli:tä ikkunan avaamiseen" -#~ msgid "Cannot connect to Netbeans #2" -#~ msgstr "Ei voi yhdistää Netbeans #2:een" +#~ msgid "-L\t\t\tSame as -r" +#~ msgstr "-L\t\t\tkuten -r" -#~ msgid "Cannot connect to Netbeans" -#~ msgstr "Ei voi yhdistää Netbeansiin" +#~ msgid "-D\t\t\tDebugging mode" +#~ msgstr "-D\t\t\tVianetsintätila" -#~ msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" -#~ msgstr "E668: Väärä avaustila NetBeans-yhteyden infotiedostolle: %s" +#~ msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'" +#~ msgstr "-N\t\t\tEi Vi-yhteensopivuutta: nocompatible" -#~ msgid "read from Netbeans socket" -#~ msgstr "luettu Netbeans-soketista" +#~ msgid "-C\t\t\tCompatible with Vi: 'compatible'" +#~ msgstr "-C\t\t\tVi-yhteensopivuustila: compatible" -#~ msgid "E658: NetBeans connection lost for buffer %<PRId64>" -#~ msgstr "E658: NetBeans-yhteys katkesi puskurille %<PRId64>" +#~ msgid "-l\t\t\tLisp mode" +#~ msgstr "-l\t\t\tLisp-tila" -#~ msgid "E511: netbeans already connected" -#~ msgstr "E511: netbeans on yhdistetty jo" +#~ msgid "-b\t\t\tBinary mode" +#~ msgstr "-b\t\t\tBinääritila" -#~ msgid "E505: " -#~ msgstr "E505: " +#~ msgid "-Z\t\t\tRestricted mode (like \"rvim\")" +#~ msgstr "-Z\t\t\tRajoitettu tila (kuten rvimillä)" -#~ msgid "E775: Eval feature not available" -#~ msgstr "E775: Eval ei ole käytettävissä" +#~ msgid "-R\t\t\tReadonly mode (like \"view\")" +#~ msgstr "-R\t\t\tKirjoitussuojattu tila (kuten view'lla)" -#~ msgid "freeing %<PRId64> lines" -#~ msgstr "vapautetaan %<PRId64> riviä" +#~ msgid "-y\t\t\tEasy mode (like \"evim\", modeless)" +#~ msgstr "-y\t\t\tHelppokäyttötila (kuten evimissä, ilman tiloja)" -#~ msgid "E530: Cannot change term in GUI" -#~ msgstr "E530: Ei voi vaihtaa termiä GUIssa" +#~ msgid "-d\t\t\tDiff mode (like \"vimdiff\")" +#~ msgstr "-d\t\t\tDiff-tila (kuten vimdiffillä)" -#~ msgid "E531: Use \":gui\" to start the GUI" -#~ msgstr "E531: Käytä komentoa :gui GUIn käynnistämiseen" +#~ msgid "-E\t\t\tImproved Ex mode" +#~ msgstr "-E\t\t\tParanneltu Ex-tila" -#~ msgid "E617: Cannot be changed in the GTK+ 2 GUI" -#~ msgstr "E617: Ei voi muuttaa GTK+2-GUIssa" +#~ msgid "-e\t\t\tEx mode (like \"ex\")" +#~ msgstr "-e\t\t\tEx-tila (kute exillä)" -#~ msgid "E596: Invalid font(s)" -#~ msgstr "E596: Viallisia fontteja" +#~ msgid "-v\t\t\tVi mode (like \"vi\")" +#~ msgstr "-v\t\t\tVi-tila (kuten villä)" -#~ msgid "E597: can't select fontset" -#~ msgstr "E597: Fontsetin valinta ei onnistu" +#~ msgid "-f or --nofork\tForeground: Don't fork when starting GUI" +#~ msgstr "-f tai --nofork\tEdustalle: Älä haarauta GUIn käynnistyksessä" -#~ msgid "E598: Invalid fontset" -#~ msgstr "E598: Viallinen fontset" +#~ msgid "-g\t\t\tRun using GUI (like \"gvim\")" +#~ msgstr "-g\t\t\tAvaa GUI (kuten gvimillä)" -#~ msgid "E533: can't select wide font" -#~ msgstr "E533: Leveän fontin valinta ei onnistu" +#~ msgid "-unregister\t\tUnregister gvim for OLE" +#~ msgstr "-unregister\t\tPoista gvim OLE-rekisteristä" -#~ msgid "E534: Invalid wide font" -#~ msgstr "E534: Viallinen leveä fontti" +#~ msgid "-register\t\tRegister this gvim for OLE" +#~ msgstr "-register\t\trekisteröi gvim OLEa varten" -#~ msgid "E538: No mouse support" -#~ msgstr "E538: Hiirtä ei tueta" +#~ msgid "" +#~ "\n" +#~ "Where case is ignored prepend / to make flag upper case" +#~ msgstr "" +#~ "\n" +#~ "Jos aakkoslaji on ohitettu, lisää alkuun / tehdäksesi asetuksesta " +#~ "suuraakkosia" -#~ msgid "cannot open " -#~ msgstr "ei voi avata " +#~ msgid "" +#~ "\n" +#~ " or:" +#~ msgstr "" +#~ "\n" +#~ " tai:" -#~ msgid "VIM: Can't open window!\n" -#~ msgstr "VIM: Ei voi avata ikkunaa\n" +#~ msgid " vim [arguments] " +#~ msgstr " vim [argumentit] " -#~ msgid "Need Amigados version 2.04 or later\n" -#~ msgstr "Amigados 2.04 tai uudempi tarvitaan\n" +#~ msgid "Vim: Error: This version of Vim does not run in a Cygwin terminal\n" +#~ msgstr "Vim: Virhe: Tämä versio Vimistä ei toimi Cygwinin terminaalissa\n" -#~ msgid "Need %s version %<PRId64>\n" -#~ msgstr "Tarvitaan %s versio %<PRId64>\n" +#~ msgid "Vim: Error: Failure to start gvim from NetBeans\n" +#~ msgstr "Vim: Virhe: Gvimin käynnistys NetBeansistä ei onnistu\n" -#~ msgid "Cannot open NIL:\n" -#~ msgstr "Ei voi avata NILiä:\n" +#~ msgid "This Vim was not compiled with the diff feature." +#~ msgstr "Tähän Vimiin ei ole käännetty diff-toimintoja mukaan." -#~ msgid "Cannot create " -#~ msgstr "Ei voi luoda " +#~ msgid "'-nb' cannot be used: not enabled at compile time\n" +#~ msgstr "-nb:tä ei voi käyttää, koska sitä ei käännetty mukaan\n" -#~ msgid "Vim exiting with %d\n" -#~ msgstr "Vim sulkeutuu koodilla %d\n" +#~ msgid "netbeans is not supported with this GUI\n" +#~ msgstr "netbeans ei toimi tässä käyttöliittymässä\n" -#~ msgid "cannot change console mode ?!\n" -#~ msgstr "ei voi vaihtaa konsolitilaa?\n" +#~ msgid "%d files to edit\n" +#~ msgstr "%d tiedostoa muokattavana\n" -#~ msgid "mch_get_shellsize: not a console??\n" -#~ msgstr "mch_get_shellsize: ei ole konsoli?\n" +#~ msgid "E251: VIM instance registry property is badly formed. Deleted!" +#~ msgstr "E251: VIMin instanssin rekisteriarvo on virheellinen, poistettiin." -#~ msgid "E360: Cannot execute shell with -f option" -#~ msgstr "E360: Kuorta ei voi avata asetuksella -f" +#~ msgid "E573: Invalid server id used: %s" +#~ msgstr "E573: Virheellinen palvelimen tunniste: %s" -#~ msgid "Cannot execute " -#~ msgstr "Ei voi suorittaa " +#~ msgid "E248: Failed to send command to the destination program" +#~ msgstr "E248: Komennon lähetys kohdeohjelmalle ei onnistu" -#~ msgid "shell " -#~ msgstr "kuori " +#~ msgid "Unable to register a command server name" +#~ msgstr "Komentopalvelimen nimen rekisteröinti ei onnistu" -#~ msgid " returned\n" -#~ msgstr " palautti\n" +#~ msgid "cannot get line" +#~ msgstr "ei voida hakea riviä" -#~ msgid "ANCHOR_BUF_SIZE too small." -#~ msgstr "ANCHOR_BUF_SIZE liian pieni." +#~ msgid "E572: exit code %d" +#~ msgstr "E572: palautusarvo %d" -#~ msgid "I/O ERROR" -#~ msgstr "IO-virhe" +#~ msgid "" +#~ "E571: Sorry, this command is disabled: the Tcl library could not be " +#~ "loaded." +#~ msgstr "E571: komento ei toimi, Tcl-kirjastoa ei voitu ladata." -#~ msgid "Message" -#~ msgstr "Viesti" +#~ msgid "cannot register callback command: buffer/window reference not found" +#~ msgstr "" +#~ "callbackia ei voi rekisteröidä: puskurin tai ikkunan viitettä ei löydy" -#~ msgid "'columns' is not 80, cannot execute external commands" -#~ msgstr "columns ei ole 80, ei voi suorittaa ulkoista komentoa" +#~ msgid "" +#~ "E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-" +#~ "dev@vim.org" +#~ msgstr "" +#~ "E280: kriittinen TCL-virhe: reflist hajalla? Ilmoita asiasta " +#~ "postituslistalle vim-dev@vim.org" -#~ msgid "E237: Printer selection failed" -#~ msgstr "E237: Tulostimen valinta epäonnistui" +#~ msgid "" +#~ "cannot register callback command: buffer/window is already being deleted" +#~ msgstr "callbackia ei voi rekisteröidä: puskuri tai ikkuna on poistettu" -#~ msgid "to %s on %s" -#~ msgstr "tulostimelle %s kohteessa %s" +#~ msgid "cannot create buffer/window command: object is being deleted" +#~ msgstr "ei voi luoda puskuri- tai ikkunakomentoa, olio on poistumassa" -#~ msgid "E613: Unknown printer font: %s" -#~ msgstr "E613: Tuntematon tulostimen fontti: %s" +#~ msgid "vim error" +#~ msgstr "vim-virhe" -#~ msgid "E238: Print error: %s" -#~ msgstr "E238: Tulostinvirhe: %s" +#~ msgid "unknown vimOption" +#~ msgstr "tuntematon vimOption" -#~ msgid "Printing '%s'" -#~ msgstr "Tulostetaan %s" +#~ msgid "unknown flag: " +#~ msgstr "tuntematon asetus: " -#~ msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" -#~ msgstr "E244: Virheellinen merkistön nimi %s fontin nimessä %s" +#~ msgid "cannot insert/append line" +#~ msgstr "rivin lisäys ei onnistu" -#~ msgid "E245: Illegal char '%c' in font name \"%s\"" -#~ msgstr "E245: Virheellinen merkki %c fontin nimessä %s" +#~ msgid "row %d column %d" +#~ msgstr "rivi %d sarake %d" + +#~ msgid "mark not set" +#~ msgstr "merkko ei ole asetettu" + +#~ msgid "cannot set line(s)" +#~ msgstr "ei voi asettaa rivejä" -#~ msgid "Vim: Double signal, exiting\n" -#~ msgstr "Vim: Kaksoissignaali, lopetetaan\n" +#~ msgid "not implemented yet" +#~ msgstr "ei toteutettu" -#~ msgid "Vim: Caught deadly signal %s\n" -#~ msgstr "Vim: Tappava signaali %s\n" +#~ msgid "E273: unknown longjmp status %d" +#~ msgstr "E273: tuntematon longjmp-tila %d" -#~ msgid "Vim: Caught deadly signal\n" -#~ msgstr "Vim: Tappava signaali\n" +#~ msgid "E272: unhandled exception" +#~ msgstr "E272: käsittelemätön poikkeus" -#~ msgid "Opening the X display took %<PRId64> msec" -#~ msgstr "X-näytön avaus vei %<PRId64> millisekuntia" +#~ msgid "E271: retry outside of rescue clause" +#~ msgstr "E271: retry rescuen ulkopuolella" -#~ msgid "" -#~ "\n" -#~ "Vim: Got X error\n" -#~ msgstr "" -#~ "\n" -#~ "Vim: X-virhe\n" +#~ msgid "E269: unexpected break" +#~ msgstr "E269: Odotuksenvastainen break" -#~ msgid "Testing the X display failed" -#~ msgstr "X-näytön testaus epäonnistui" +#~ msgid "E268: unexpected next" +#~ msgstr "E268: Odotuksenvastainen next" -#~ msgid "Opening the X display timed out" -#~ msgstr "X-näytön avaus aikakatkaistiin" +#~ msgid "E267: unexpected return" +#~ msgstr "E267: odotuksenvastainen return" #~ msgid "" -#~ "\n" -#~ "Cannot execute shell sh\n" +#~ "E266: Sorry, this command is disabled, the Ruby library could not be " +#~ "loaded." +#~ msgstr "E266: komento ei toimi, Ruby-kirjastoa ei voitu ladata." + +#~ msgid "E265: $_ must be an instance of String" +#~ msgstr "E265: muuttujan $_ pitää olla Stringin instanssi" + +#~ msgid "E837: This Vim cannot execute :py3 after using :python" #~ msgstr "" -#~ "\n" -#~ "Kuoren sh suoritus ei onnistu\n" +#~ "E837: Python: Ei voi käyttää komentoja :py ja :py3 samassa istunnossa" + +#~ msgid "E659: Cannot invoke Python recursively" +#~ msgstr "E659: Pythonia ei voi kutsua rekursiivisesti" #~ msgid "" -#~ "\n" -#~ "Cannot create pipes\n" +#~ "E887: Sorry, this command is disabled, the Python's site module could not " +#~ "be loaded." #~ msgstr "" -#~ "\n" -#~ "Putkia ei voi tehdä\n" +#~ "E887: Komento ei toimi, Pythonin site-moduulien lataaminen ei onnistunut." #~ msgid "" -#~ "\n" -#~ "Cannot fork\n" +#~ "E263: Sorry, this command is disabled, the Python library could not be " +#~ "loaded." +#~ msgstr "E263: komento ei toimi, Python-kirjaston lataaminen ei onnistunut." + +#~ msgid "E836: This Vim cannot execute :python after using :py3" #~ msgstr "" -#~ "\n" -#~ "Ei voi haarauttaa\n" +#~ "E836: Python: Ei voi käyttää komentoja :py ja :py3 samassa istunnossa" + +#~ msgid "not allowed in the Vim sandbox" +#~ msgstr "ei sallittu Vimin hiekkalaatikossa" + +#~ msgid "linenr out of range" +#~ msgstr "rivinumero arvoalueen ulkopuolelta" + +#~ msgid "window is invalid" +#~ msgstr "ikkuna on virheellinen" + +#~ msgid "buffer is invalid" +#~ msgstr "puskuri on virheellinen" + +#~ msgid "Vim error" +#~ msgstr "Vim-virhe" + +#~ msgid "Vim error: ~a" +#~ msgstr "Vim-virhe: ~a" + +#~ msgid "couldn't open buffer" +#~ msgstr "ei voitu avata puskuria" + +#~ msgid "unknown option" +#~ msgstr "tuntematon asetus" + +#~ msgid "hidden option" +#~ msgstr "piilotettu asetus" + +#~ msgid "expressions disabled at compile time" +#~ msgstr "ilmaukset poistettu käytöstä käännösaikana" + +#~ msgid "invalid expression" +#~ msgstr "virheellinen ilmaus" #~ msgid "" -#~ "\n" -#~ "Command terminated\n" +#~ "E895: Sorry, this command is disabled, the MzScheme's racket/base module " +#~ "could not be loaded." #~ msgstr "" -#~ "\n" -#~ "Komento loppui\n" +#~ "E895: Komento ei toimi, MzScheme-moduulia racket/base ei voitu ladata." -#~ msgid "XSMP lost ICE connection" -#~ msgstr "XSMP kadotti ICE-yhteyden" +#~ msgid "" +#~ "E815: Sorry, this command is disabled, the MzScheme libraries could not " +#~ "be loaded." +#~ msgstr "E815: komento ei toimi, MzScheme-kirjastoa ei voitu ladata." -#~ msgid "Opening the X display failed" -#~ msgstr "X-näytön avaus epäonnistui" +#~ msgid "Lua library cannot be loaded." +#~ msgstr "Luan kirjastoa ei voitu ladata." -#~ msgid "XSMP handling save-yourself request" -#~ msgstr "XSMP käsittelee save-yourself-pyyntöä" +#~ msgid "E626: cannot get cscope database information" +#~ msgstr "E626: ei voi hakea cscope-tietokannan tietoja" -#~ msgid "XSMP opening connection" -#~ msgstr "XSMP avaa yhteyttä" +#~ msgid "E625: cannot open cscope database: %s" +#~ msgstr "E625: ei voi avata cscope-tietokantaa: %s" -#~ msgid "XSMP ICE connection watch failed" -#~ msgstr "XSMP:n ICE-yhteyden tarkkailu epäonnistui" +#~ msgid "E563: stat error" +#~ msgstr "E563: stat-virhe" -#~ msgid "XSMP SmcOpenConnection failed: %s" -#~ msgstr "XSMP SmcOpenConnection epäonnistui: %s" +#~ msgid "E256: Hangul automata ERROR" +#~ msgstr "E256: Hangu-automaattivirhe" -#~ msgid "At line" -#~ msgstr "Rivillä" +#~ msgid "Size:" +#~ msgstr "Koko:" -#~ msgid "Could not load vim32.dll!" -#~ msgstr "Vim32.dll:ää ei voitu ladata" +#~ msgid "Style:" +#~ msgstr "Tyyli:" -#~ msgid "VIM Error" -#~ msgstr "VIM-virhe" +#~ msgid "Font:" +#~ msgstr "Fontti:" -#~ msgid "Could not fix up function pointers to the DLL!" -#~ msgstr "Ei voitu korjata funktio-osoittimia DLL:ssä" +#~ msgid "Encoding:" +#~ msgstr "Koodaus:" -#~ msgid "shell returned %d" -#~ msgstr "kuori palautti arvon %d" +#~ msgid "Show size in Points" +#~ msgstr "Näytä koko pisteinä" -#~ msgid "Vim: Caught %s event\n" -#~ msgstr "Vim: Napattiin %s\n" +#~ msgid "Name:" +#~ msgstr "Nimi:" -#~ msgid "close" -#~ msgstr "sulkeminen" +#~ msgid "Vim - Font Selector" +#~ msgstr "Vim - fonttivalitsin" -#~ msgid "logoff" -#~ msgstr "uloskirjautuminen" +#~ msgid "no specific match" +#~ msgstr "ei tarkkaa täsmäystä" -#~ msgid "shutdown" -#~ msgstr "sammutus" +#~ msgid "&Dismiss" +#~ msgstr "&Ohita" -#~ msgid "E371: Command not found" -#~ msgstr "E371: Komentoa ei löydy" +#~ msgid "Invalid font specification" +#~ msgstr "Virheellinen fonttimääritys" + +#~ msgid "Font1 width: %ld" +#~ msgstr "Fontti1:n leveys: %ld" + +#~ msgid "Font0 width: %ld" +#~ msgstr "Fontti0:n leveys: %ld" + +#~ msgid "Font%ld width is not twice that of font0" +#~ msgstr "Fontti%ld:n leveys ei ole kaksi kertaa fontti0:n" + +#~ msgid "Font1: %s" +#~ msgstr "Fontti1: %s" + +#~ msgid "Font0: %s" +#~ msgstr "Fontti0: %s" + +#~ msgid "E253: Fontset name: %s" +#~ msgstr "E253: Fontsetin nimi: %s" + +#~ msgid "Font '%s' is not fixed-width" +#~ msgstr "Fontti %s ei ole tasavälinen" + +#~ msgid "E252: Fontset name: %s" +#~ msgstr "E252: Fontsetin nimi: %s" + +#~ msgid "E250: Fonts for the following charsets are missing in fontset %s:" +#~ msgstr "E250: Seuraavien merkistöjoukkojen fontit puuttuvat fontsetistä %s:" #~ msgid "" -#~ "VIMRUN.EXE not found in your $PATH.\n" -#~ "External commands will not pause after completion.\n" -#~ "See :help win32-vimrun for more information." +#~ "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" #~ msgstr "" -#~ "VIMRUN.EXEä ei löydy muuttujasta $PATH.\n" -#~ "Ulkoiset komennot eivät pysähdy suorituksen lopussa.\n" -#~ "Lisätietoja komennolla :help win32-vimrun" +#~ "Vim E458: Ei voi varata värikartan alkiota, värit voivat mennä väärin" -#~ msgid "Vim Warning" -#~ msgstr "Vim-varoitus" +# MDI eli windowsin moni-ikkunasovellus +#~ msgid "E672: Unable to open window inside MDI application" +#~ msgstr "E672: Ikkunaa ei voitu avata MDI-sovellukseen" -#~ msgid "Error file" -#~ msgstr "Virhetiedosto" +# OLE on object linking and embedding pÃ¥ windowska +#~ msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." +#~ msgstr "E243: Argumenttia ei tueta: -%s, käytä OLE-versiota" -#~ msgid "Conversion in %s not supported" -#~ msgstr "Muutosta kohteessa %s ei tueta" +#~ msgid "Directory\t*.nothing\n" +#~ msgstr "Hakemisto\t*.nothing\n" -#~ msgid "E430: Tag file path truncated for %s\n" -#~ msgstr "E430: Tägitiedoston polku katkaistu kohdassa %s\n" +#~ msgid "Not Used" +#~ msgstr "Ei käytössä" -#~ msgid "new shell started\n" -#~ msgstr "uusi kuori avattu\n" +#~ msgid "Find & Replace (use '\\\\' to find a '\\')" +#~ msgstr "Etsi ja korvaa (\\\\:llä löytää \\:t)" -#~ msgid "Used CUT_BUFFER0 instead of empty selection" -#~ msgstr "Käytettiin CUT_BUFFER0:aa tyhjän valinnan sijaan" +#~ msgid "Find string (use '\\\\' to find a '\\')" +#~ msgstr "Etsi merkkijonoa (\\\\:llä löytää \\:t)" -#~ msgid "No undo possible; continue anyway" -#~ msgstr "Ei voi kumota, jatketaan silti" +#~ msgid "Open tab..." +#~ msgstr "Avaa välilehti..." -#~ msgid "E832: Non-encrypted file has encrypted undo file: %s" -#~ msgstr "E832: Salaamattomalla tiedostolla on salattu kumoustiedosto: %s" +#~ msgid "&Undo" +#~ msgstr "&Kumoa" -#~ msgid "E826: Undo file decryption failed: %s" -#~ msgstr "E826: Kumoustiedoston purku epäonnistui: %s" +#~ msgid "Replace &All" +#~ msgstr "Korvaa k&aikki" -#~ msgid "E827: Undo file is encrypted: %s" -#~ msgstr "E827: Kumoustiedosto on salattu: %s" +#~ msgid "&Replace" +#~ msgstr "Ko&rvaa" -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16/32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 16- t. 32-bittinen GUI-versio" +#~ msgid "Find &Next" +#~ msgstr "Hae &seuraava" -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 64-bittinen GUI-versio" +#~ msgid "Selection" +#~ msgstr "Valinta" -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 32-bittinen GUI-version" +#~ msgid "&OK" +#~ msgstr "&Ok" -#~ msgid " in Win32s mode" -#~ msgstr " Win32s-tilassa" +#~ msgid "Files" +#~ msgstr "Tiedostot" -#~ msgid " with OLE support" -#~ msgstr " OLE-tuella" +#~ msgid "&Help" +#~ msgstr "O&hje" -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit console version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 32-bittinen konsoliversio" +#~ msgid "Filter" +#~ msgstr "Suodatus" -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit console version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 32-bittinen konsoliversio" +#~ msgid "Directories" +#~ msgstr "Hakemistot" -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16-bit version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 16-bittinen versio" +#~ msgid "&Cancel" +#~ msgstr "&Peru" -#~ msgid "" -#~ "\n" -#~ "32-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "32-bittinen MS-DOS-versio" +#~ msgid "&Filter" +#~ msgstr "&Suodata" -#~ msgid "" -#~ "\n" -#~ "16-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "16-bittinen MS-DOS-versio" +#~ msgid "Vim: Main window unexpectedly destroyed\n" +#~ msgstr "Vim: Pääikkuna tuhoutui odottamatta\n" -#~ msgid "" -#~ "\n" -#~ "MacOS X (unix) version" -#~ msgstr "" -#~ "\n" -#~ "MacOS X-version (unix)" +#~ msgid "Open Tab..." +#~ msgstr "Avaa välilehti..." -#~ msgid "" -#~ "\n" -#~ "MacOS X version" -#~ msgstr "" -#~ "\n" -#~ "MacOS X-version" +#~ msgid "New tab" +#~ msgstr "Uusi välilehti" -#~ msgid "" -#~ "\n" -#~ "MacOS version" -#~ msgstr "" -#~ "\n" -#~ "MacOS-version" +#~ msgid "Close tab" +#~ msgstr "Sulje välilehti" -#~ msgid "" -#~ "\n" -#~ "RISC OS version" -#~ msgstr "" -#~ "\n" -#~ "RISC OS-version" +#~ msgid "Vim: Received \"die\" request from session manager\n" +#~ msgstr "Vim: sessiomanageri lähetti die-pyynnön\n" -#~ msgid "" -#~ "\n" -#~ "OpenVMS version" -#~ msgstr "" -#~ "\n" -#~ "OpenVMS-version" +#~ msgid "_Close" +#~ msgstr "_Sulje" -#~ msgid "" -#~ "\n" -#~ "Big version " -#~ msgstr "" -#~ "\n" -#~ "Big-version " +#~ msgid "Replace All" +#~ msgstr "Korvaa kaikki" -#~ msgid "" -#~ "\n" -#~ "Normal version " -#~ msgstr "" -#~ "\n" -#~ "Normal-versio " +#~ msgid "Replace" +#~ msgstr "Korvaa" -#~ msgid "" -#~ "\n" -#~ "Small version " -#~ msgstr "" -#~ "\n" -#~ "Small-versio " +#~ msgid "Find Next" +#~ msgstr "Etsi seuraava" -#~ msgid "" -#~ "\n" -#~ "Tiny version " -#~ msgstr "" -#~ "\n" -#~ "Tiny-versio " +#~ msgid "Down" +#~ msgstr "Alas" -#~ msgid "with GTK2-GNOME GUI." -#~ msgstr "GTK2-Gnome-GUIlla." +#~ msgid "Up" +#~ msgstr "Ylös" -#~ msgid "with GTK2 GUI." -#~ msgstr "GTK2-GUIlla." +#~ msgid "Direction" +#~ msgstr "Suunta" -#~ msgid "with X11-Motif GUI." -#~ msgstr "X11-Motif-GUIlla." +#~ msgid "Match case" +#~ msgstr "Kirjaintaso" -#~ msgid "with X11-neXtaw GUI." -#~ msgstr "X11-neXtaw-GUIlla." +#~ msgid "Match whole word only" +#~ msgstr "Korvaa kokonaisia sanoja" -#~ msgid "with X11-Athena GUI." -#~ msgstr "X11-Athena-GUIlla." +#~ msgid "Replace with:" +#~ msgstr "Korvaa:" -#~ msgid "with Photon GUI." -#~ msgstr "Photon-GUIlla." +#~ msgid "Find what:" +#~ msgstr "Etsi:" -#~ msgid "with GUI." -#~ msgstr "GUIlla." +#~ msgid "VIM - Search..." +#~ msgstr "VIM - Etsi..." -#~ msgid "with Carbon GUI." -#~ msgstr "Carbon-GUIlla." +#~ msgid "VIM - Search and Replace..." +#~ msgstr "VIM - Etsi ja korvaa..." -#~ msgid "with Cocoa GUI." -#~ msgstr "Cocoa-GUIlla." +#~ msgid "Input _Methods" +#~ msgstr "Syöte_menetelmät" -#~ msgid "with (classic) GUI." -#~ msgstr "perinteisellä GUIlla." +#~ msgid "No" +#~ msgstr "Ei" -#~ msgid " system gvimrc file: \"" -#~ msgstr " järjestelmän gvimrc: \"" +#~ msgid "Yes" +#~ msgstr "Kyllä" -#~ msgid " user gvimrc file: \"" -#~ msgstr " käyttäjän gvimrc: \"" +#~ msgid "_OK" +#~ msgstr "_OK" -#~ msgid "2nd user gvimrc file: \"" -#~ msgstr "2. käyttäjän gvimrc: \"" +#~ msgid "_Open" +#~ msgstr "_Avaa" -#~ msgid "3rd user gvimrc file: \"" -#~ msgstr "3. käyttäjän gvimrc: \"" +#~ msgid "_Save" +#~ msgstr "_Tallenna" -#~ msgid " system menu file: \"" -#~ msgstr " järjestelmävalikko: \"" +#~ msgid "_Cancel" +#~ msgstr "_Peru" -#~ msgid "Compiler: " -#~ msgstr "Käännin: " +#~ msgid "E232: Cannot create BalloonEval with both message and callback" +#~ msgstr "E232: Ei voi luoda BalloonEvalia viestille ja callbackille" -#~ msgid "menu Help->Orphans for information " -#~ msgstr "valikko Ohje->Orvot lisätietoja varten " +#~ msgid "Vim dialog" +#~ msgstr "Vim-ikkuna" -#~ msgid "Running modeless, typed text is inserted" -#~ msgstr "Suoritetaan tilattomana, kirjoitettu teksti syötetään" +#~ msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." +#~ msgstr "Vierityspalkki: Pixmapin geometria ei selviä" -#~ msgid "menu Edit->Global Settings->Toggle Insert Mode " -#~ msgstr "valikko Muokkaa->Yleiset asetukset->Vaihda syötetilaa" +#~ msgid "Cancel" +#~ msgstr "Peru" -#~ msgid " for two modes " -#~ msgstr " kahta tilaa varten " +#~ msgid "OK" +#~ msgstr "OK" -#~ msgid "menu Edit->Global Settings->Toggle Vi Compatible" -#~ msgstr "valikko Muokkaa->Yleiset asetukset->Vaihda Vi-yhteensopivuutta" +#~ msgid "E615: vim_SelFile: can't get current directory" +#~ msgstr "E615: vim_SelFile: nykyistä hakemistoa ei saada selville" -#~ msgid " for Vim defaults " -#~ msgstr " Vim-oletuksia varten" +#~ msgid "Pathname:" +#~ msgstr "Polku:" -#~ msgid "WARNING: Windows 95/98/ME detected" -#~ msgstr "VAROITUS: Window 95/98/ME havaittu" +#~ msgid "E614: vim_SelFile: can't return to current directory" +#~ msgstr "E614: vim_SelFile: nykyiseen hakemistoon ei voi palata" -#~ msgid "type :help windows95<Enter> for info on this" -#~ msgstr "kirjoita :help windows95<Enter> lisätietoja varten" +#~ msgid "E616: vim_SelFile: can't get font %s" +#~ msgstr "E616: vim_SelFile: ei saada fonttia %s" -#~ msgid "E370: Could not load library %s" -#~ msgstr "E370: Kirjaston %s lataaminen ei onnistu" +#~ msgid "<cannot open> " +#~ msgstr "<ei voi avata> " + +#~ msgid "No match at cursor, finding next" +#~ msgstr "Ei täsmäystä kursorin alla, etsitään seuraava" + +#~ msgid "E599: Value of 'imactivatekey' is invalid" +#~ msgstr "E599: imactivatekeyn arvo on virheellinen" + +#~ msgid "E231: 'guifontwide' invalid" +#~ msgstr "E231: guifontwide virheellinen" + +#~ msgid "E665: Cannot start GUI, no valid font found" +#~ msgstr "E665: Ei voi avata GUIta, sopivaa fonttia ei löydy" + +#~ msgid "E230: Cannot read from \"%s\"" +#~ msgstr "E230: Ei voi lukea kohteesta %s" + +#~ msgid "E229: Cannot start the GUI" +#~ msgstr "E229: GUIn käynnistys ei onnistu" + +#~ msgid "E851: Failed to create a new process for the GUI" +#~ msgstr "E851: Ei voitu luoda uutta prosessia käyttöliittymälle" + +# tietääkseni resurssiforkki on applen tiedostojärjestelmän tunnistejuttujuttu +#~ msgid "E460: The resource fork would be lost (add ! to override)" +#~ msgstr "E460: resurssiosa häviäisi (lisää komentoon ! ohittaaksesi)" + +#~ msgid "writing to device disabled with 'opendevice' option" +#~ msgstr "laitteeseen kirjoittaminen pois käytöstä opendevice-asetuksella" + +#~ msgid "Partial writes disallowed for NetBeans buffers" +#~ msgstr "Osittaiset kirjoitukset kielletty NetBeans-puskureissa" + +#~ msgid "NetBeans disallows writes of unmodified buffers" +#~ msgstr "NetBeans ei salli kirjoittaa muokkaamattomiin puskureihin" + +#~ msgid "Reading from stdin..." +#~ msgstr "Luetaan vakiosyötteestä" + +#~ msgid "Vim: Reading from stdin...\n" +#~ msgstr "Vim: Luetaan vakiosyötteestä...\n" + +#~ msgid "is a device (disabled with 'opendevice' option)" +#~ msgstr "on laite (ei käytössä opendevice-asetuksen takia)" + +#~ msgid "Debug Line" +#~ msgstr "Vianetsintärivi" + +#~ msgid "Input Line" +#~ msgstr "Syöterivi" + +#~ msgid "Expression" +#~ msgstr "Ilmaus" + +#~ msgid "Search String" +#~ msgstr "Hakujono" + +#~ msgid "Command Line" +#~ msgstr "Komentorivi" #~ msgid "" -#~ "Sorry, this command is disabled: the Perl library could not be loaded." -#~ msgstr "Sori, komento ei toimi, Perl kirjastoa ei voinut ladata." +#~ "\n" +#~ "# %s History (newest to oldest):\n" +#~ msgstr "" +#~ "\n" +#~ "# %s Historia (uusimmasta alkaen):\n" -#~ msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" -#~ msgstr "E299: Perl-suoritus kielletty hiekkalaatikossa ilman Safe-moduulia" +#~ msgid "E196: No digraphs in this version" +#~ msgstr "E196: Digraafeja ei ole tässä versiossa" -#~ msgid "Edit with &multiple Vims" -#~ msgstr "&Muokkaa usealla Vimillä" +#~ msgid "E195: Cannot open viminfo file for reading" +#~ msgstr "E195: Viminfoa ei voi avata lukemista varten" -#~ msgid "Edit with single &Vim" -#~ msgstr "Muokkaa yhdellä &Vimillä" +#~ msgid "E809: #< is not available without the +eval feature" +#~ msgstr "E809: #< ei ole käytössä jollei +eval ole päällä" -#~ msgid "Diff with Vim" -#~ msgstr "Diffi Vimillä" +#~ msgid "Save Setup" +#~ msgstr "Tallenna asetukset" -#~ msgid "Edit with &Vim" -#~ msgstr "Muokkaa &Vimillä" +#~ msgid "Save Session" +#~ msgstr "Tallenna sessio" -#~ msgid "Edit with existing Vim - " -#~ msgstr "Muokkaa olemassaolevalla Vimillä - " +#~ msgid "Save View" +#~ msgstr "Tallenna näkymä" -#~ msgid "Edits the selected file(s) with Vim" -#~ msgstr "Muokkaa valittuja tiedostoja Vimillä" +#~ msgid "Save Redirection" +#~ msgstr "Tallenna uudelleenosoitus" -#~ msgid "Error creating process: Check if gvim is in your path!" -#~ msgstr "Virhe prosessin käynnistämisessä, varmista että gvim on polulla" +#~ msgid "E930: Cannot use :redir inside execute()" +#~ msgstr "E930: Komentoa :redir ei voi käyttää funktion execute() sisällä" -#~ msgid "gvimext.dll error" -#~ msgstr "gvimext.dll-virhe" +#~ msgid "E466: :winpos requires two number arguments" +#~ msgstr "E466: :winpos vaatii kaksi lukuargumenttia" -#~ msgid "Path length too long!" -#~ msgstr "Liian pitkä polku" +#~ msgid "E188: Obtaining window position not implemented for this platform" +#~ msgstr "E188: Ikkunan sijainnin selvitys ei toimi tällä alustalla" -#~ msgid "E234: Unknown fontset: %s" -#~ msgstr "E234: Tuntematon fontset: %s" +#~ msgid "Window position: X %d, Y %d" +#~ msgstr "Ikkunan sijainti: X %d, Y %d" -#~ msgid "E235: Unknown font: %s" -#~ msgstr "E235: Tuntematon fontti: %s" +#~ msgid "" +#~ "E747: Cannot change directory, buffer is modified (add ! to override)" +#~ msgstr "" +#~ "E747: Hakemistoa ei voida muuttaa, puskuria on muokattu (lisää " +#~ "komentoon ! ohittaaksesi" -#~ msgid "E236: Font \"%s\" is not fixed-width" -#~ msgstr "E236: Fontti %s ei ole tasavälinen" +#~ msgid "Append File" +#~ msgstr "Lisää tiedostoon" -#~ msgid "E448: Could not load library function %s" -#~ msgstr "E448: Ei voitu ladta kirjastofunktiota %s" +#~ msgid "Edit File in new window" +#~ msgstr "Muokkaa uudessa ikkunassa" -#~ msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" -#~ msgstr "E26: Hepreaa ei voi käyttää, koska sitä ei käännetty mukaan\n" +#~ msgid "unknown" +#~ msgstr "tuntematon" -#~ msgid "E27: Farsi cannot be used: Not enabled at compile time\n" -#~ msgstr "E27: Farsia ei voi käyttää, koska sitä ei käännetty mukaan\n" +#~ msgid "E172: Only one file name allowed" +#~ msgstr "E172: Vain yksi tiedostonimi sallitaan" -#~ msgid "E800: Arabic cannot be used: Not enabled at compile time\n" -#~ msgstr "E800: Arabiaa ei voi käyttää, koska sitä ei käännetty mukaan\n" +#~ msgid "Source Vim script" +#~ msgstr "Lataa vim-skripti" -#~ msgid "E247: no registered server named \"%s\"" -#~ msgstr "E247: palvelinta %s ei ole rekisteröitynä" +#~ msgid " (NOT FOUND)" +#~ msgstr " (EI LÖYTYNYT)" -#~ msgid "E233: cannot open display" -#~ msgstr "E233: näyttöä ei voi avata" +#~ msgid "" +#~ "\n" +#~ "# Last Substitute String:\n" +#~ "$" +#~ msgstr "" +#~ "\n" +#~ "# Viimeisin korvausmerkkijono:\n" +#~ "$" -#~ msgid "E449: Invalid expression received" -#~ msgstr "E449: Virheellinen ilmaus saatu" +#~ msgid "Edit File" +#~ msgstr "Muokkaa tiedostoa" -#~ msgid "E463: Region is guarded, cannot modify" -#~ msgstr "E463: Alue on suojattu, muuttaminen ei onnistu" +#~ msgid "Save As" +#~ msgstr "Tallenna nimellä" -#~ msgid "E744: NetBeans does not allow changes in read-only files" -#~ msgstr "E744: NetBeans ei tue muutoksia kirjoitussuojattuihin tiedostoihin" +#~ msgid "" +#~ "\n" +#~ "# Bar lines, copied verbatim:\n" +#~ msgstr "" +#~ "\n" +#~ "# Bar-rivit, kopiotu sellaisenaan:\n" -#~ msgid "Need encryption key for \"%s\"" -#~ msgstr "Tarvitaan salausavain kohteelle %s " +#~ msgid "Illegal starting char" +#~ msgstr "Virheellinen aloitusmerkki" -#~ msgid "writelines() requires list of strings" -#~ msgstr "writelines()-komennolle pitää antaa merkkijonolista" +#~ msgid "# Value of 'encoding' when this file was written\n" +#~ msgstr "# encoding-muuttujan arvo tiedostoa kirjoitettaessa\n" -#~ msgid "E264: Python: Error initialising I/O objects" -#~ msgstr "E264: Python: Virhe IO-olioiden alustuksessa" +#~ msgid "" +#~ "# You may edit it if you're careful!\n" +#~ "\n" +#~ msgstr "" +#~ "# Muokkaa varovasti!\n" +#~ "\n" -#~ msgid "no such buffer" -#~ msgstr "puskuria ei ole" +#~ msgid "# This viminfo file was generated by Vim %s.\n" +#~ msgstr "# Vimin %s generoima viminfo-tiedosto.\n" -#~ msgid "attempt to refer to deleted window" -#~ msgstr "yritettiin viitata poistettuun ikkunaan" +#~ msgid "E138: Can't write viminfo file %s!" +#~ msgstr "E138: Viminfo-tiedoston kirjoittaminen ei onnistu %s" -#~ msgid "readonly attribute" -#~ msgstr "kirjoitussuojattu attribuutti" +#~ msgid "E929: Too many viminfo temp files, like %s!" +#~ msgstr "E929: liikaa viminfo-väliaikaistiedostoja, kuten %s." -#~ msgid "cursor position outside buffer" -#~ msgstr "kursorin sijainti puskurin ulkopuolella" +#~ msgid "E136: viminfo: Too many errors, skipping rest of file" +#~ msgstr "E136: viminfo: liikaa virheitä, ohitetaan lopputiedosto" -#~ msgid "<window object (deleted) at %p>" -#~ msgstr "<ikkunaolio (poistettu) kohdassa %p>" +#~ msgid "%sviminfo: %s in line: " +#~ msgstr "%sviminfo: %s rivillä: " -#~ msgid "<window object (unknown) at %p>" -#~ msgstr "<ikkunaolio (tuntematon) kohdassa %p>" +#~ msgid "E258: Unable to send to client" +#~ msgstr "E258: Asiakkaalle lähetys ei onnistunut" -#~ msgid "<window %d>" -#~ msgstr "<ikkuna %d>" +#~ msgid "E277: Unable to read a server reply" +#~ msgstr "E277: Palvelimen vastauksen lukeminen ei onnistunut" -#~ msgid "no such window" -#~ msgstr "ikkunaa ei ole" +#~ msgid "E240: No connection to Vim server" +#~ msgstr "E240: Ei yhteyttä vim-palvelimeen" -#~ msgid "attempt to refer to deleted buffer" -#~ msgstr "yritettiin viitata poistettuun puskuriin" +#~ msgid "" +#~ "&OK\n" +#~ "&Cancel" +#~ msgstr "" +#~ "&OK\n" +#~ "&Peru" + +#~ msgid "" +#~ "\n" +#~ "# global variables:\n" +#~ msgstr "" +#~ "\n" +#~ "# globaalit muuttujat:\n" + +#~ msgid "E729: using Funcref as a String" +#~ msgstr "E729: Funcref ei käy merkkijonosta" + +#~ msgid "E914: Using a Channel as a Float" +#~ msgstr "E914: Käytettiin Channelia Floattina" + +#~ msgid "E911: Using a Job as a Float" +#~ msgstr "E911: Job ei käy Floatista" + +#~ msgid "E913: Using a Channel as a Number" +#~ msgstr "E913: Channel ei käy Numberista" + +#~ msgid "E910: Using a Job as a Number" +#~ msgstr "E910: Job ei käy Numberista" + +#~ msgid "E703: Using a Funcref as a Number" +#~ msgstr "E703: Funcref ei käy Numberista" + +#~ msgid "E724: variable nested too deep for displaying" +#~ msgstr "E724: muuttuja on upotettu liian syvälle näytettäväksi" + +#~ msgid "Patch file" +#~ msgstr "Patch-tiedosto" + +#~ msgid "[crypted]" +#~ msgstr "[salattu]" + +#~ msgid "Keys don't match!" +#~ msgstr "Avaimet eivät täsmää!" -# New Line eli uusi rivinvaihtomerkki (ei CR, LF tai CR LF) -#~ msgid "[NL found]" -#~ msgstr "[NL puuttuu]" +#~ msgid "Enter same key again: " +#~ msgstr "Anna sama avain uudestaan: " -#~ msgid "Vim dialog..." -#~ msgstr "Vim-ikkuna..." +#~ msgid "Enter encryption key: " +#~ msgstr "Anna salausavain: " -#~ msgid "Font Selection" -#~ msgstr "Fontin valinta" +#~ msgid "Warning: Using a weak encryption method; see :help 'cm'" +#~ msgstr "Varoitus: Käytetään heikkoa salausmenetelmää, ks. :help 'cm'" -#~ msgid "E569: maximum number of cscope connections reached" -#~ msgstr "E569: enimmäismäärä cscope-yhteyksiä otettu" +#~ msgid "E821: File is encrypted with unknown method" +#~ msgstr "E821: Tiedoston salaus on tuntematon" + +#~ msgid "E918: buffer must be loaded: %s" +#~ msgstr "E918: puskuria ei voi ladata: %s" + +#~ msgid "E915: in_io buffer requires in_buf or in_name to be set" +#~ msgstr "E915: in_io-puskurilla pitää olla in_buf tai in_name asetettu" -#~ msgid "-name <name>\t\tUse resource as if vim was <name>" -#~ msgstr "-name <nimi>\t\tKäytä resurssia vim <nimenä>" +#~ msgid "E920: _io file requires _name to be set" +#~ msgstr "E920: _io-tiedostolla pitää olla _name asetettu" -#~ msgid "\t\t\t (Unimplemented)\n" -#~ msgstr "\t\t\t (toteuttamatta)\n" +#~ msgid "E906: not an open channel" +#~ msgstr "E906: ei ole avoin kanava" + +#~ msgid "" +#~ "E912: cannot use ch_evalexpr()/ch_sendexpr() with a raw or nl channel" +#~ msgstr "" +#~ "E912: ei voida käyttää funktioita ch_evalexpr(), ch_sendexpr() raa'an tai " +#~ "nl-kanavan kanssa" -#~ msgid "E290: over-the-spot style requires fontset" -#~ msgstr "E290: over-the-spot-tyylissä pitää olla fontset" +#~ msgid "E917: Cannot use a callback with %s()" +#~ msgstr "E917: Ei voitu käyttää callbackia %s()" -#~ msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled" -#~ msgstr "E291: GTK+-versio vanhempi kuin 1.2.3: Tila-alue poistettu käytöstä" +#~ msgid "" +#~ "\n" +#~ "# Buffer list:\n" +#~ msgstr "" +#~ "\n" +#~ "# Puskuriluettelo:\n" -#~ msgid "E292: Input Method Server is not running" -#~ msgstr "E292: Syötemetodipalvelin ei ole käynnissä" +#~ msgid "E931: Buffer cannot be registered" +#~ msgstr "E931: Puskuria ei voi rekisteröidä" -#~ msgid "E396: containedin argument not accepted here" -#~ msgstr "E396: containedin ei sovi tähän" +#~ msgid "E819: Blowfish test failed" +#~ msgstr "E819: Blowfish-testi epäonnistui" -#~ msgid "with GTK-GNOME GUI." -#~ msgstr "GTK-Gnome-GUIlla." +#~ msgid "E818: sha256 test failed" +#~ msgstr "E818: sha256-testi epäonnistui failed" -#~ msgid "with GTK GUI." -#~ msgstr "GTK-GUIlla." +#~ msgid "E817: Blowfish big/little endian use wrong" +#~ msgstr "E817: Blowfishin tavujärjestys väärä" -#~ msgid "-V[N]\t\tVerbose level" -#~ msgstr "-V[N]\t\tMonisanaisuustaso" +#~ msgid "E820: sizeof(uint32_t) != 4" +#~ msgstr "E820: sizeof(uint32_t) != 4" -#~ msgid "...(truncated)" -#~ msgstr "...(katkaistu)" +#~ msgid "E831: bf_key_init() called with empty password" +#~ msgstr "E831: bf_key_init() tyhjällä salasanalla" diff --git a/src/nvim/po/fr.po b/src/nvim/po/fr.po index bf0610de02..c0df5f2170 100644 --- a/src/nvim/po/fr.po +++ b/src/nvim/po/fr.po @@ -1,3 +1,4 @@ + # French Translation for Vim # # Do ":help uganda" in Vim to read copying and usage conditions. @@ -6,7 +7,7 @@ # FIRST AUTHOR DindinX <David.Odin@bigfoot.com> 2000. # SECOND AUTHOR Adrien Beau <version.francaise@free.fr> 2002, 2003. # THIRD AUTHOR David Blanchet <david.blanchet@free.fr> 2006, 2008. -# FOURTH AUTHOR Dominique Pellé <dominique.pelle@gmail.com> 2008, 2015. +# FOURTH AUTHOR Dominique Pellé <dominique.pelle@gmail.com> 2008, 2017. # # Latest translation available at: # http://dominique.pelle.free.fr/vim-fr.php @@ -15,8 +16,8 @@ msgid "" msgstr "" "Project-Id-Version: Vim(Français)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-07-30 17:54+0200\n" -"PO-Revision-Date: 2015-07-30 18:00+0200\n" +"POT-Creation-Date: 2017-01-16 00:30+0100\n" +"PO-Revision-Date: 2017-01-16 00:51+0100\n" "Last-Translator: Dominique Pellé <dominique.pelle@gmail.com>\n" "Language-Team: \n" "Language: fr\n" @@ -24,201 +25,172 @@ msgstr "" "Content-Type: text/plain; charset=ISO_8859-15\n" "Content-Transfer-Encoding: 8bit\n" -#: ../api/private/helpers.c:201 -#, fuzzy -msgid "Unable to get option value" -msgstr "impossible d'obtenir la valeur d'une option" +msgid "E831: bf_key_init() called with empty password" +msgstr "E831: bf_key_init() appelée avec un mot de passe vide" -#: ../api/private/helpers.c:204 -#, fuzzy -msgid "internal error: unknown option type" -msgstr "erreur interne : pas d'élément de liste vim" +msgid "E820: sizeof(uint32_t) != 4" +msgstr "E820: sizeof(uint32_t) != 4" + +msgid "E817: Blowfish big/little endian use wrong" +msgstr "E817: petit/gros boutisme incorrect dans blowfish" + +msgid "E818: sha256 test failed" +msgstr "E818: le test de sha256 a échoué" + +msgid "E819: Blowfish test failed" +msgstr "E819: le test de blowfish a échoué" # DB - TODO : Trouver une traduction valable et attestée pour "location". -#: ../buffer.c:92 msgid "[Location List]" msgstr "[Liste des emplacements]" -#: ../buffer.c:93 msgid "[Quickfix List]" msgstr "[Liste Quickfix]" -#: ../buffer.c:94 msgid "E855: Autocommands caused command to abort" msgstr "E855: Des autocommandes ont causé la terminaison de la commande" # AB - Il faut respecter l'esprit plus que la lettre. -#: ../buffer.c:135 msgid "E82: Cannot allocate any buffer, exiting..." msgstr "E82: Aucun tampon ne peut être alloué, Vim doit s'arrêter" # AB - La situation est probablement plus grave que la version anglaise ne le # laisse entendre (voir l'aide en ligne). La version française est plus # explicite. -#: ../buffer.c:138 msgid "E83: Cannot allocate buffer, using other one..." msgstr "" "E83: L'allocation du tampon a échoué : arrêtez Vim, libérez de la mémoire" -#: ../buffer.c:763 +msgid "E931: Buffer cannot be registered" +msgstr "E931: Le tampon ne peut pas être enregistré" + +msgid "E937: Attempt to delete a buffer that is in use" +msgstr "E937: Tentative de suppression d'un tampon en cours d'utilisation" + msgid "E515: No buffers were unloaded" msgstr "E515: Aucun tampon n'a été déchargé" -#: ../buffer.c:765 msgid "E516: No buffers were deleted" msgstr "E516: Aucun tampon n'a été effacé" -#: ../buffer.c:767 msgid "E517: No buffers were wiped out" msgstr "E517: Aucun tampon n'a été détruit" -#: ../buffer.c:772 msgid "1 buffer unloaded" msgstr "1 tampon a été déchargé" -#: ../buffer.c:774 #, c-format msgid "%d buffers unloaded" msgstr "%d tampons ont été déchargés" -#: ../buffer.c:777 msgid "1 buffer deleted" msgstr "1 tampon a été effacé" -#: ../buffer.c:779 #, c-format msgid "%d buffers deleted" msgstr "%d tampons ont été effacés" -#: ../buffer.c:782 msgid "1 buffer wiped out" msgstr "1 tampon a été détruit" -#: ../buffer.c:784 #, c-format msgid "%d buffers wiped out" msgstr "%d tampons ont été détruits" -#: ../buffer.c:806 msgid "E90: Cannot unload last buffer" msgstr "E90: Impossible de décharger le dernier tampon" # AB - La version française est meilleure que la version anglaise. -#: ../buffer.c:874 msgid "E84: No modified buffer found" msgstr "E84: Aucun tampon n'est modifié" #. back where we started, didn't find anything. -#: ../buffer.c:903 msgid "E85: There is no listed buffer" msgstr "E85: Aucun tampon n'est listé" # AB - Je ne suis pas sûr que l'on puisse obtenir ce message. -#: ../buffer.c:915 msgid "E87: Cannot go beyond last buffer" msgstr "E87: Impossible d'aller après le dernier tampon" # AB - Je ne suis pas sûr que l'on puisse obtenir ce message. -#: ../buffer.c:917 msgid "E88: Cannot go before first buffer" msgstr "E88: Impossible d'aller avant le premier tampon" -#: ../buffer.c:945 #, c-format -msgid "" -"E89: No write since last change for buffer %<PRId64> (add ! to override)" +msgid "E89: No write since last change for buffer %ld (add ! to override)" msgstr "" -"E89: Le tampon %<PRId64> n'a pas été enregistré (ajoutez ! pour passer outre)" +"E89: Le tampon %ld n'a pas été enregistré (ajoutez ! pour passer outre)" -#. wrap around (may cause duplicates) -#: ../buffer.c:1423 msgid "W14: Warning: List of file names overflow" msgstr "W14: Alerte : La liste des noms de fichier déborde" # AB - Vu le code source, la version française est meilleure que la # version anglaise. Ce message est similaire au message E86. -#: ../buffer.c:1555 ../quickfix.c:3361 #, c-format -msgid "E92: Buffer %<PRId64> not found" -msgstr "E92: Le tampon %<PRId64> n'existe pas" +msgid "E92: Buffer %ld not found" +msgstr "E92: Le tampon %ld n'existe pas" # AB - Il faut respecter l'esprit plus que la lettre. -#: ../buffer.c:1798 #, c-format msgid "E93: More than one match for %s" msgstr "E93: Plusieurs tampons correspondent à %s" -#: ../buffer.c:1800 #, c-format msgid "E94: No matching buffer for %s" msgstr "E94: Aucun tampon ne correspond à %s" -#: ../buffer.c:2161 #, c-format -msgid "line %<PRId64>" -msgstr "ligne %<PRId64>" +msgid "line %ld" +msgstr "ligne %ld" -#: ../buffer.c:2233 msgid "E95: Buffer with this name already exists" msgstr "E95: Un tampon porte déjà ce nom" -#: ../buffer.c:2498 msgid " [Modified]" msgstr "[Modifié]" # AB - "[Inédité]" est plus correct, mais sonne faux. -#: ../buffer.c:2501 msgid "[Not edited]" msgstr "[Non édité]" -#: ../buffer.c:2504 msgid "[New file]" msgstr "[Nouveau fichier]" -#: ../buffer.c:2505 msgid "[Read errors]" msgstr "[Erreurs de lecture]" -#: ../buffer.c:2506 ../buffer.c:3217 ../fileio.c:1807 ../screen.c:4895 msgid "[RO]" msgstr "[RO]" # AB - La version courte, "[RO]", devrait-elle être traduite par "[LS]" ? # Il faudrait faire un sondage auprès des utilisateurs francophones. -#: ../buffer.c:2507 ../fileio.c:1807 msgid "[readonly]" msgstr "[lecture-seule]" -#: ../buffer.c:2524 #, c-format msgid "1 line --%d%%--" msgstr "1 ligne --%d%%--" -#: ../buffer.c:2526 #, c-format -msgid "%<PRId64> lines --%d%%--" -msgstr "%<PRId64> lignes --%d%%--" +msgid "%ld lines --%d%%--" +msgstr "%ld lignes --%d%%--" # AB - Faut-il remplacer "sur" par "de" ? # DB - Mon avis : oui. -#: ../buffer.c:2530 #, c-format -msgid "line %<PRId64> of %<PRId64> --%d%%-- col " -msgstr "ligne %<PRId64> sur %<PRId64> --%d%%-- col " +msgid "line %ld of %ld --%d%%-- col " +msgstr "ligne %ld sur %ld --%d%%-- col " # DB - Je trouvais [Aucun fichier] (VO : [No file]) plus naturel # lors du lancement de Vim en mode graphique (ce message # apparaît notamment dans le titre de la fenêtre). -#: ../buffer.c:2632 ../buffer.c:4292 ../memline.c:1554 msgid "[No Name]" msgstr "[Aucun nom]" #. must be a help buffer -#: ../buffer.c:2667 msgid "help" msgstr "aide" -#: ../buffer.c:3225 ../screen.c:4883 msgid "[Help]" msgstr "[Aide]" @@ -226,24 +198,19 @@ msgstr "[Aide]" # traduction littérale et brève, mais qui risque fort d'être mal comprise. # J'ai finalement choisi d'utiliser une abréviation, mais cela ne me # satisfait pas. -#: ../buffer.c:3254 ../screen.c:4887 msgid "[Preview]" msgstr "[Prévisu]" -#: ../buffer.c:3528 msgid "All" msgstr "Tout" -#: ../buffer.c:3528 msgid "Bot" msgstr "Bas" # AB - Attention, on passe de trois à quatre lettres. -#: ../buffer.c:3531 msgid "Top" msgstr "Haut" -#: ../buffer.c:4244 msgid "" "\n" "# Buffer list:\n" @@ -251,11 +218,9 @@ msgstr "" "\n" "# Liste des tampons :\n" -#: ../buffer.c:4289 msgid "[Scratch]" msgstr "[Brouillon]" -#: ../buffer.c:4529 msgid "" "\n" "--- Signs ---" @@ -263,175 +228,220 @@ msgstr "" "\n" "--- Symboles ---" -#: ../buffer.c:4538 #, c-format msgid "Signs for %s:" msgstr "Symboles dans %s :" -#: ../buffer.c:4543 #, c-format -msgid " line=%<PRId64> id=%d name=%s" -msgstr " ligne=%<PRId64> id=%d nom=%s" +msgid " line=%ld id=%d name=%s" +msgstr " ligne=%ld id=%d nom=%s" -#: ../cursor_shape.c:68 -msgid "E545: Missing colon" -msgstr "E545: ':' manquant" +msgid "E902: Cannot connect to port" +msgstr "E902: Impossible de se connecter au port" -#: ../cursor_shape.c:70 ../cursor_shape.c:94 -msgid "E546: Illegal mode" -msgstr "E546: Mode non autorisé" +msgid "E901: gethostbyname() in channel_open()" +msgstr "E901: gethostbyname() dans channel_open()" -#: ../cursor_shape.c:134 -msgid "E548: digit expected" -msgstr "E548: chiffre attendu" +msgid "E898: socket() in channel_open()" +msgstr "E898: socket() dans channel_open()" -#: ../cursor_shape.c:138 -msgid "E549: Illegal percentage" -msgstr "E549: Pourcentage non autorisé" +msgid "E903: received command with non-string argument" +msgstr "E903: commande reçue avec un argument qui n'est pas une chaîne" + +msgid "E904: last argument for expr/call must be a number" +msgstr "E904: le dernier argument de expr/call doit être un nombre" + +msgid "E904: third argument for call must be a list" +msgstr "E904: le troisième argument de \"call\" doit être une liste" + +#, c-format +msgid "E905: received unknown command: %s" +msgstr "E905: commande inconnue reçue : %s" + +#, c-format +msgid "E630: %s(): write while not connected" +msgstr "E630: %s() : écriture sans être connecté" + +#, c-format +msgid "E631: %s(): write failed" +msgstr "E631: %s() : erreur d'écriture" + +#, c-format +msgid "E917: Cannot use a callback with %s()" +msgstr "E917: Impossible d'utiliser un callback avec %s()" + +msgid "E912: cannot use ch_evalexpr()/ch_sendexpr() with a raw or nl channel" +msgstr "" +"E912: Impossible d'utiliser ch_evalexpr()/ch_sendexpr() avec un canal brut " +"ou nl" + +msgid "E906: not an open channel" +msgstr "E906: pas un canal ouvert" + +msgid "E920: _io file requires _name to be set" +msgstr "E920: fichier _io nécessite _name" + +msgid "E915: in_io buffer requires in_buf or in_name to be set" +msgstr "E915: tampon in_io nécessite in_buf ou in_name " + +#, c-format +msgid "E918: buffer must be loaded: %s" +msgstr "E918: le tampon doit être chargé : %s" + +msgid "E821: File is encrypted with unknown method" +msgstr "E821: Le fichier est chiffré avec une méthode inconnue" + +msgid "Warning: Using a weak encryption method; see :help 'cm'" +msgstr "" +"Alerte : utilisation d'une méthode de chiffrage faible ; consultez :help 'cm'" + +msgid "Enter encryption key: " +msgstr "Tapez la clé de chiffrement : " + +msgid "Enter same key again: " +msgstr "Tapez la clé à nouveau : " + +msgid "Keys don't match!" +msgstr "Les clés ne correspondent pas !" + +msgid "[crypted]" +msgstr "[chiffré]" -# AB - Je n'ai pas trouvé de traduction satisfaisante au verbe "diff". Comme -# Vim fait en pratique appel au programme "diff" pour evaluer les -# différences entre fichiers, "to diff" a été traduit par "utiliser diff" -# et d'autres expressions appropriées. -#: ../diff.c:146 #, c-format -msgid "E96: Can not diff more than %<PRId64> buffers" -msgstr "E96: Impossible d'utiliser diff sur plus de %<PRId64> tampons" +msgid "E720: Missing colon in Dictionary: %s" +msgstr "E720: Il manque ':' dans le Dictionnaire %s" + +#, c-format +msgid "E721: Duplicate key in Dictionary: \"%s\"" +msgstr "E721: Clé dupliquée dans le Dictionnaire : %s" + +#, c-format +msgid "E722: Missing comma in Dictionary: %s" +msgstr "E722: Il manque une virgule dans le Dictionnaire : %s" + +#, c-format +msgid "E723: Missing end of Dictionary '}': %s" +msgstr "E723: Il manque '}' à la fin du Dictionnaire : %s" + +msgid "extend() argument" +msgstr "argument de extend()" + +#, c-format +msgid "E737: Key already exists: %s" +msgstr "E737: La clé existe déjà : %s" + +#, c-format +msgid "E96: Cannot diff more than %ld buffers" +msgstr "E96: Impossible d'utiliser diff sur plus de %ld tampons" -#: ../diff.c:753 msgid "E810: Cannot read or write temp files" msgstr "E810: Impossible de lire ou écrire des fichiers temporaires" # AB - La version française est meilleure que la version anglaise. -#: ../diff.c:755 msgid "E97: Cannot create diffs" msgstr "E97: diff ne fonctionne pas" -#: ../diff.c:966 +msgid "Patch file" +msgstr "Fichier rustine" + msgid "E816: Cannot read patch output" msgstr "E816: Le fichier intermédiaire produit par patch n'a pu être lu" -#: ../diff.c:1220 msgid "E98: Cannot read diff output" msgstr "E98: Le fichier intermédiaire produit par diff n'a pu être lu" -#: ../diff.c:2081 msgid "E99: Current buffer is not in diff mode" msgstr "E99: Le tampon courant n'est pas en mode diff" -#: ../diff.c:2100 msgid "E793: No other buffer in diff mode is modifiable" msgstr "E793: Aucun autre tampon en mode diff n'est modifiable" -#: ../diff.c:2102 msgid "E100: No other buffer in diff mode" msgstr "E100: Aucun autre tampon n'est en mode diff" # AB - La version française est meilleure que la version anglaise, mais elle # peut être améliorée. -#: ../diff.c:2112 msgid "E101: More than two buffers in diff mode, don't know which one to use" msgstr "E101: Plus de deux tampons sont en mode diff, soyez plus précis" -#: ../diff.c:2141 #, c-format msgid "E102: Can't find buffer \"%s\"" msgstr "E102: Le tampon %s est introuvable" -#: ../diff.c:2152 #, c-format msgid "E103: Buffer \"%s\" is not in diff mode" msgstr "E103: Le tampon %s n'est pas en mode diff" -#: ../diff.c:2193 msgid "E787: Buffer changed unexpectedly" msgstr "E787: Le tampon a été modifié inopinément" # AB - Je cherche une traduction plus concise pour "escape". -#: ../digraph.c:1598 msgid "E104: Escape not allowed in digraph" msgstr "E104: Un digraphe ne peut contenir le caractère d'échappement" # AB - La version française est trop verbeuse. -#: ../digraph.c:1760 msgid "E544: Keymap file not found" msgstr "E544: Le fichier descripteur de clavier est introuvable" # AB - La version française est meilleure que la version anglaise. -#: ../digraph.c:1785 msgid "E105: Using :loadkeymap not in a sourced file" msgstr "E105: :loadkeymap ne peut être utilisé que dans un script Vim" -#: ../digraph.c:1821 msgid "E791: Empty keymap entry" msgstr "E791: Entrée du descripteur de clavier (keymap) vide" # AB - Remplacer "complétion" par "complètement" ? Voir l'éthymologie # d'"accrétion". -#: ../edit.c:82 msgid " Keyword completion (^N^P)" msgstr " Complètement de mot-clé (^N^P)" # DB - todo : Faut-il une majuscule à "mode" ? #. ctrl_x_mode == 0, ^P/^N compl. -#: ../edit.c:83 msgid " ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" msgstr " mode ^X (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" -#: ../edit.c:85 msgid " Whole line completion (^L^N^P)" msgstr " Complètement de ligne entière (^L^N^P)" -#: ../edit.c:86 msgid " File name completion (^F^N^P)" msgstr " Complètement de nom de fichier (^F^N^P)" -#: ../edit.c:87 msgid " Tag completion (^]^N^P)" msgstr " Complètement de marqueur (^]^N^P)" # AB - J'ai dû avoir une bonne raison de faire une version française aussi # différente de la version anglaise. Il me faut la retrouver. # DB - TODO -#: ../edit.c:88 msgid " Path pattern completion (^N^P)" msgstr " Complètement global de mot-clé (^N^P)" -#: ../edit.c:89 msgid " Definition completion (^D^N^P)" msgstr " Complètement de définition (^D^N^P)" # AB - Trouver une meilleure formulation que "selon le". # DB : proposition : "avec" -#: ../edit.c:91 msgid " Dictionary completion (^K^N^P)" msgstr " Complètement avec le dictionnaire (^K^N^P)" # AB - Trouver une meilleure formulation que "selon le". -#: ../edit.c:92 msgid " Thesaurus completion (^T^N^P)" msgstr " Complètement avec le thésaurus (^T^N^P)" # AB - La version française est meilleure que la version anglaise. # DB : Suggestion. -#: ../edit.c:93 msgid " Command-line completion (^V^N^P)" msgstr " Complètement de ligne de commande (^V^N^P)" -#: ../edit.c:94 msgid " User defined completion (^U^N^P)" msgstr " Complètement défini par l'utilisateur (^U^N^P)" # DB : On doit pouvoir trouver nettement mieux que ça. -#: ../edit.c:95 msgid " Omni completion (^O^N^P)" msgstr " Complètement selon le type de fichier (Omni) (^O^N^P)" -#: ../edit.c:96 msgid " Spelling suggestion (s^N^P)" msgstr " Suggestion d'orthographe (s^N^P)" -#: ../edit.c:97 msgid " Keyword Local completion (^N^P)" msgstr " Complètement local de mot-clé (^N/^P)" @@ -439,45 +449,35 @@ msgstr " Complètement local de mot-clé (^N/^P)" # Il faut éviter de le faire trop long. Je pense que la version française # est suffisamment compréhensible dans le contexte dans lequel elle est # affichée. -#: ../edit.c:100 msgid "Hit end of paragraph" msgstr "Fin du paragraphe" -#: ../edit.c:101 msgid "E839: Completion function changed window" msgstr "E839: La fonction de complètement a changé la fenêtre" -#: ../edit.c:102 msgid "E840: Completion function deleted text" msgstr "E840: La fonction de complètement a effacé du texte" -#: ../edit.c:1847 msgid "'dictionary' option is empty" msgstr "L'option 'dictionary' est vide" -#: ../edit.c:1848 msgid "'thesaurus' option is empty" msgstr "L'option 'thesaurus' est vide" -#: ../edit.c:2655 #, c-format msgid "Scanning dictionary: %s" msgstr "Examen du dictionnaire : %s" -#: ../edit.c:3079 msgid " (insert) Scroll (^E/^Y)" msgstr " (insertion) Défilement (^E/^Y)" -#: ../edit.c:3081 msgid " (replace) Scroll (^E/^Y)" msgstr " (remplacement) Défilement (^E/^Y)" -#: ../edit.c:3587 #, c-format msgid "Scanning: %s" msgstr "Examen : %s" -#: ../edit.c:3614 msgid "Scanning tags." msgstr "Examen des marqueurs." @@ -485,7 +485,6 @@ msgstr "Examen des marqueurs." # opération de complétion est répétée (typiquement avec CTRL-X CTRL-N). # Que ce soit en anglais ou en français, il y a un problème de majuscules. # Bien qu'insatisfaisante, cette traduction semble optimale. -#: ../edit.c:4519 msgid " Adding" msgstr " Ajout" @@ -493,236 +492,138 @@ msgstr " Ajout" #. * be called before line = ml_get(), or when this address is no #. * longer needed. -- Acevedo. #. -#: ../edit.c:4562 msgid "-- Searching..." msgstr "-- Recherche en cours..." # AB - Ce texte s'ajoute à la fin d'un des messages de complétion ci-dessus. # AB - Faut-il utiliser "origine" ou "originel" au lieu d'"original" ? # DB : Suggestion. -#: ../edit.c:4618 msgid "Back at original" msgstr "Retour au point de départ" # AB - Ce texte s'ajoute à la fin d'un des messages de complétion ci-dessus. -#: ../edit.c:4621 msgid "Word from other line" msgstr "Mot d'une autre ligne" # AB - Ce texte s'ajoute à la fin d'un des messages de complétion ci-dessus. -#: ../edit.c:4624 msgid "The only match" msgstr "La seule correspondance" # AB - Ce texte s'ajoute à la fin d'un des messages de complétion ci-dessus. # AB - Faut-il remplacer "sur" par "de" ? # DB : Pour moi, non. -#: ../edit.c:4680 #, c-format msgid "match %d of %d" msgstr "Correspondance %d sur %d" # AB - Ce texte s'ajoute à la fin d'un des messages de complétion ci-dessus. # DB - todo : la VO n'a pas de majuscule. -#: ../edit.c:4684 #, c-format msgid "match %d" msgstr "Correspondance %d" -#: ../eval.c:137 +#. maximum nesting of lists and dicts msgid "E18: Unexpected characters in :let" msgstr "E18: Caractères inattendus avant '='" -#: ../eval.c:138 -#, c-format -msgid "E684: list index out of range: %<PRId64>" -msgstr "E684: index de Liste hors limites : %<PRId64> au-delà de la fin" - -#: ../eval.c:139 #, c-format msgid "E121: Undefined variable: %s" msgstr "E121: Variable non définie : %s" -#: ../eval.c:140 msgid "E111: Missing ']'" msgstr "E111: ']' manquant" -#: ../eval.c:141 -#, c-format -msgid "E686: Argument of %s must be a List" -msgstr "E686: L'argument de %s doit être une Liste" - -#: ../eval.c:143 -#, c-format -msgid "E712: Argument of %s must be a List or Dictionary" -msgstr "E712: L'argument de %s doit être une Liste ou un Dictionnaire" - -#: ../eval.c:144 -msgid "E713: Cannot use empty key for Dictionary" -msgstr "E713: Impossible d'utiliser une clé vide dans un Dictionnaire" - -#: ../eval.c:145 -msgid "E714: List required" -msgstr "E714: Liste requise" - -#: ../eval.c:146 -msgid "E715: Dictionary required" -msgstr "E715: Dictionnaire requis" - -# DB : Suggestion -#: ../eval.c:147 -#, c-format -msgid "E118: Too many arguments for function: %s" -msgstr "E118: La fonction %s a reçu trop d'arguments" - -#: ../eval.c:148 -#, c-format -msgid "E716: Key not present in Dictionary: %s" -msgstr "E716: La clé %s n'existe pas dans le Dictionnaire" - -#: ../eval.c:150 -#, c-format -msgid "E122: Function %s already exists, add ! to replace it" -msgstr "E122: La fonction %s existe déjà (ajoutez ! pour la remplacer)" - -#: ../eval.c:151 -msgid "E717: Dictionary entry already exists" -msgstr "E717: Une entrée du Dictionnaire porte déjà ce nom" - -#: ../eval.c:152 -msgid "E718: Funcref required" -msgstr "E718: Référence de fonction (Funcref) requise" - -#: ../eval.c:153 msgid "E719: Cannot use [:] with a Dictionary" msgstr "E719: Utilisation de [:] impossible avec un Dictionnaire" -#: ../eval.c:154 #, c-format msgid "E734: Wrong variable type for %s=" msgstr "E734: Type de variable erroné avec %s=" -#: ../eval.c:155 -#, c-format -msgid "E130: Unknown function: %s" -msgstr "E130: Fonction inconnue : %s" - -#: ../eval.c:156 #, c-format msgid "E461: Illegal variable name: %s" msgstr "E461: Nom de variable invalide : %s" -#: ../eval.c:157 msgid "E806: using Float as a String" msgstr "E806: Utilisation d'un Flottant comme une Chaîne" # DB - todo : trouver mieux que "destinations". -#: ../eval.c:1830 msgid "E687: Less targets than List items" msgstr "E687: Moins de destinations que d'éléments dans la Liste" # DB - todo : trouver mieux que "destinations". -#: ../eval.c:1834 msgid "E688: More targets than List items" msgstr "E688: Plus de destinations que d'éléments dans la Liste" -#: ../eval.c:1906 msgid "Double ; in list of variables" msgstr "Double ; dans une liste de variables" -#: ../eval.c:2078 #, c-format msgid "E738: Can't list variables for %s" msgstr "E738: Impossible de lister les variables de %s" -#: ../eval.c:2391 msgid "E689: Can only index a List or Dictionary" msgstr "E689: Seul une Liste ou un Dictionnaire peut être indexé" -#: ../eval.c:2396 msgid "E708: [:] must come last" msgstr "E708: [:] ne peut être spécifié qu'en dernier" -#: ../eval.c:2439 msgid "E709: [:] requires a List value" -msgstr "E709: [:] n?cessite une Liste" +msgstr "E709: [:] nécessite une Liste" -#: ../eval.c:2674 msgid "E710: List value has more items than target" msgstr "E710: La Liste a plus d'éléments que la destination" -#: ../eval.c:2678 msgid "E711: List value has not enough items" msgstr "E711: La Liste n'a pas assez d'éléments" -#: ../eval.c:2867 msgid "E690: Missing \"in\" after :for" msgstr "E690: \"in\" manquant après :for" -#: ../eval.c:3063 -#, c-format -msgid "E107: Missing parentheses: %s" -msgstr "E107: Parenthèses manquantes : %s" - -#: ../eval.c:3263 #, c-format msgid "E108: No such variable: \"%s\"" msgstr "E108: Variable inexistante : %s" -#: ../eval.c:3333 msgid "E743: variable nested too deep for (un)lock" msgstr "E743: variable trop imbriquée pour la (dé)verrouiller" # AB - Je suis partagé entre la concision d'une traduction assez littérale et # la lourdeur d'une traduction plus correcte. -#: ../eval.c:3630 msgid "E109: Missing ':' after '?'" msgstr "E109: Il manque ':' après '?'" -#: ../eval.c:3893 msgid "E691: Can only compare List with List" msgstr "E691: Une Liste ne peut être comparée qu'avec une Liste" -#: ../eval.c:3895 -msgid "E692: Invalid operation for Lists" -msgstr "E692: Opération invalide avec les Listes" +msgid "E692: Invalid operation for List" +msgstr "E692: Opération invalide avec les Liste" -#: ../eval.c:3915 msgid "E735: Can only compare Dictionary with Dictionary" msgstr "E735: Un Dictionnaire ne peut être comparé qu'avec un Dictionnaire" -#: ../eval.c:3917 msgid "E736: Invalid operation for Dictionary" msgstr "E736: Opération invalide avec les Dictionnaires" -# DB - todo : Traduction valable (et courte) pour Funcref ? -#: ../eval.c:3932 -msgid "E693: Can only compare Funcref with Funcref" -msgstr "E693: Une Funcref ne peut être comparée qu'à une Funcref" - -#: ../eval.c:3934 msgid "E694: Invalid operation for Funcrefs" msgstr "E694: Opération invalide avec les Funcrefs" -#: ../eval.c:4277 msgid "E804: Cannot use '%' with Float" msgstr "E804: Impossible d'utiliser '%' avec un Flottant" -#: ../eval.c:4478 msgid "E110: Missing ')'" msgstr "E110: ')' manquant" -#: ../eval.c:4609 msgid "E695: Cannot index a Funcref" msgstr "E695: Impossible d'indexer une Funcref" +msgid "E909: Cannot index a special variable" +msgstr "E909: Impossible d'indexer une variable spéciale" + # AB - La version française est meilleure que la version anglaise. -#: ../eval.c:4839 #, c-format msgid "E112: Option name missing: %s" msgstr "E112: Il manque un nom d'option après %s" -#: ../eval.c:4855 #, c-format msgid "E113: Unknown option: %s" msgstr "E113: Option inconnue : %s" @@ -730,464 +631,307 @@ msgstr "E113: Option inconnue : %s" # AB - La version française est meilleure que la version anglaise, qui est # erronée, d'ailleurs : il s'agit d'une "double quote" et non d'une # "quote". -#: ../eval.c:4904 #, c-format msgid "E114: Missing quote: %s" msgstr "E114: Il manque \" à la fin de %s" # AB - La version française est meilleure que la version anglaise. -#: ../eval.c:5020 #, c-format msgid "E115: Missing quote: %s" msgstr "E115: Il manque ' à la fin de %s" -#: ../eval.c:5084 -#, c-format -msgid "E696: Missing comma in List: %s" -msgstr "E696: Il manque une virgule dans la Liste %s" - -#: ../eval.c:5091 -#, c-format -msgid "E697: Missing end of List ']': %s" -msgstr "E697: Il manque ']' à la fin de la Liste %s" - -#: ../eval.c:5750 msgid "Not enough memory to set references, garbage collection aborted!" msgstr "" "Pas assez de mémoire pour les références, arrêt du ramassage de miètes !" -#: ../eval.c:6475 -#, c-format -msgid "E720: Missing colon in Dictionary: %s" -msgstr "E720: Il manque ':' dans le Dictionnaire %s" +msgid "E724: variable nested too deep for displaying" +msgstr "E724: variable trop imbriquée pour être affichée" -#: ../eval.c:6499 -#, c-format -msgid "E721: Duplicate key in Dictionary: \"%s\"" -msgstr "E721: Clé \"%s\" dupliquée dans le Dictionnaire" +msgid "E805: Using a Float as a Number" +msgstr "E805: Utilisation d'un Flottant comme un Nombre" -#: ../eval.c:6517 -#, c-format -msgid "E722: Missing comma in Dictionary: %s" -msgstr "E722: Il manque une virgule dans le Dictionnaire %s" +msgid "E703: Using a Funcref as a Number" +msgstr "E703: Utilisation d'une Funcref comme un Nombre" -#: ../eval.c:6524 -#, c-format -msgid "E723: Missing end of Dictionary '}': %s" -msgstr "E723: Il manque '}' à la fin du Dictionnaire %s" +msgid "E745: Using a List as a Number" +msgstr "E745: Utilisation d'une Liste comme un Nombre" -#: ../eval.c:6555 -msgid "E724: variable nested too deep for displaying" -msgstr "E724: variable trop imbriquée pour être affichée" +msgid "E728: Using a Dictionary as a Number" +msgstr "E728: Utilisation d'un Dictionnaire comme un Nombre" + +msgid "E910: Using a Job as a Number" +msgstr "E910: Utilisation d'une Tâche comme un Nombre" + +msgid "E913: Using a Channel as a Number" +msgstr "E913: Utilisation d'un Canal comme un Nombre" + +msgid "E891: Using a Funcref as a Float" +msgstr "E891: Utilisation d'une Funcref comme un Flottant" + +msgid "E892: Using a String as a Float" +msgstr "E892: Utilisation d'une Chaîne comme un Flottant" + +msgid "E893: Using a List as a Float" +msgstr "E893: Utilisation d'une Liste comme un Flottant" + +msgid "E894: Using a Dictionary as a Float" +msgstr "E894: Utilisation d'un Dictionnaire comme un Flottant" + +msgid "E907: Using a special value as a Float" +msgstr "E907: Utilisation d'une valeur spéciale comme un Flottant" + +msgid "E911: Using a Job as a Float" +msgstr "E911: Utilisation d'une Tâche comme un Flottant" + +msgid "E914: Using a Channel as a Float" +msgstr "E914: Utilisation d'un Canal comme un Flottant" + +msgid "E729: using Funcref as a String" +msgstr "E729: Utilisation d'une Funcref comme une Chaîne" + +msgid "E730: using List as a String" +msgstr "E730: Utilisation d'une Liste comme une Chaîne" + +msgid "E731: using Dictionary as a String" +msgstr "E731: Utilisation d'un Dictionnaire comme une Chaîne" + +msgid "E908: using an invalid value as a String" +msgstr "E908: Utilisation d'une valeur invalide comme une Chaîne" -#: ../eval.c:7188 #, c-format -msgid "E740: Too many arguments for function %s" -msgstr "E740: Trop d'arguments pour la fonction %s" +msgid "E795: Cannot delete variable %s" +msgstr "E795: Impossible de supprimer la variable %s" -#: ../eval.c:7190 #, c-format -msgid "E116: Invalid arguments for function %s" -msgstr "E116: Arguments invalides pour la fonction %s" +msgid "E704: Funcref variable name must start with a capital: %s" +msgstr "E704: Le nom d'une Funcref doit commencer par une majuscule : %s" -#: ../eval.c:7377 #, c-format -msgid "E117: Unknown function: %s" -msgstr "E117: Fonction inconnue : %s" +msgid "E705: Variable name conflicts with existing function: %s" +msgstr "E705: Le nom d'une variable entre en conflit avec la fonction %s" -#: ../eval.c:7383 #, c-format -msgid "E119: Not enough arguments for function: %s" -msgstr "E119: La fonction %s n'a pas reçu assez d'arguments" +msgid "E741: Value is locked: %s" +msgstr "E741: La valeur de %s est verrouillée" + +msgid "Unknown" +msgstr "Inconnu" -#: ../eval.c:7387 #, c-format -msgid "E120: Using <SID> not in a script context: %s" -msgstr "E120: <SID> utilisé en dehors d'un script : %s" +msgid "E742: Cannot change value of %s" +msgstr "E742: Impossible de modifier la valeur de %s" + +msgid "E698: variable nested too deep for making a copy" +msgstr "E698: variable trop imbriquée pour en faire une copie" + +# AB - La version française est capitalisée pour être en accord avec les autres +# commentaires enregistrés dans le fichier viminfo. +msgid "" +"\n" +"# global variables:\n" +msgstr "" +"\n" +"# Variables globales:\n" + +# DB - Plus précis ("la dernière fois") ? +msgid "" +"\n" +"\tLast set from " +msgstr "" +"\n" +"\tModifié la dernière fois dans " + +msgid "map() argument" +msgstr "argument de map()" + +msgid "filter() argument" +msgstr "argument de filter()" -#: ../eval.c:7391 #, c-format -msgid "E725: Calling dict function without Dictionary: %s" -msgstr "E725: Appel d'une fonction « dict » sans Dictionnaire : %s" +msgid "E686: Argument of %s must be a List" +msgstr "E686: L'argument de %s doit être une Liste" + +msgid "E928: String required" +msgstr "E928: Chaîne requis" -#: ../eval.c:7453 msgid "E808: Number or Float required" msgstr "E808: Nombre ou Flottant requis" -#: ../eval.c:7503 msgid "add() argument" msgstr "argument de add()" -#: ../eval.c:7907 -msgid "E699: Too many arguments" -msgstr "E699: Trop d'arguments" - -#: ../eval.c:8073 msgid "E785: complete() can only be used in Insert mode" msgstr "E785: complete() n'est utilisable que dans le mode Insertion" # AB - Texte par défaut du bouton de la boîte de dialogue affichée par la # fonction confirm(). -#: ../eval.c:8156 +#. +#. * Yes this is ugly, I don't particularly like it either. But doing it +#. * this way has the compelling advantage that translations need not to +#. * be touched at all. See below what 'ok' and 'ync' are used for. +#. msgid "&Ok" msgstr "&Ok" -#: ../eval.c:8692 -msgid "extend() argument" -msgstr "argument de extend()" - -#: ../eval.c:9345 -#, c-format -msgid "E737: Key already exists: %s" -msgstr "E737: un mappage existe déjà pour %s" - -#: ../eval.c:8915 -msgid "map() argument" -msgstr "argument de map()" - -#: ../eval.c:8916 -msgid "filter() argument" -msgstr "argument de filter()" - -#: ../eval.c:9229 #, c-format -msgid "+-%s%3ld lines: " -msgstr "+-%s%3ld lignes : " +msgid "+-%s%3ld line: " +msgid_plural "+-%s%3ld lines: " +msgstr[0] "+-%s%3ld ligne : " +msgstr[1] "+-%s%3ld lignes : " -#: ../eval.c:9291 #, c-format msgid "E700: Unknown function: %s" msgstr "E700: Fonction inconnue : %s" +msgid "E922: expected a dict" +msgstr "E922: dictionnaire attendu" + +msgid "E923: Second argument of function() must be a list or a dict" +msgstr "" +"E923: Le second argument de function() doit être une liste ou un dictionnaire" + +# AB - Textes des boutons de la boîte de dialogue affichée par inputdialog(). +msgid "" +"&OK\n" +"&Cancel" +msgstr "" +"&Ok\n" +"&Annuler" + # AB - La version française est meilleure que la version anglaise. -#: ../eval.c:10729 msgid "called inputrestore() more often than inputsave()" msgstr "inputrestore() a été appelé plus de fois qu'inputsave()" -#: ../eval.c:10771 msgid "insert() argument" msgstr "argument de insert()" -#: ../eval.c:10841 msgid "E786: Range not allowed" msgstr "E786: Les plages ne sont pas autorisées" -#: ../eval.c:11140 +msgid "E916: not a valid job" +msgstr "E916: tâche invalide" + msgid "E701: Invalid type for len()" msgstr "E701: Type invalide avec len()" -#: ../eval.c:11980 +#, c-format +msgid "E798: ID is reserved for \":match\": %ld" +msgstr "E798: ID est réservé pour \":match\": %ld" + msgid "E726: Stride is zero" msgstr "E726: Le pas est nul" -#: ../eval.c:11982 msgid "E727: Start past end" msgstr "E727: Début au-delà de la fin" -#: ../eval.c:12024 ../eval.c:15297 msgid "<empty>" msgstr "<vide>" -#: ../eval.c:12282 +# AB - À mon avis, la version anglaise est erronée. +# DB : Vérifier +msgid "E240: No connection to Vim server" +msgstr "E240: Pas de connexion au serveur X" + +# AB - La version française est meilleure que la version anglaise. +#, c-format +msgid "E241: Unable to send to %s" +msgstr "E241: L'envoi au serveur %s a échoué" + +msgid "E277: Unable to read a server reply" +msgstr "E277: Impossible de lire la réponse du serveur" + msgid "remove() argument" msgstr "argument de remove()" -#: ../eval.c:12466 msgid "E655: Too many symbolic links (cycle?)" msgstr "E655: Trop de liens symboliques (cycle ?)" -#: ../eval.c:12593 msgid "reverse() argument" msgstr "argument de reverse()" -#: ../eval.c:13721 +# AB - La version française est meilleure que la version anglaise. +msgid "E258: Unable to send to client" +msgstr "E258: La réponse n'a pas pu être envoyée au client" + +#, c-format +msgid "E927: Invalid action: '%s'" +msgstr "E927: Action invalide : « %s »" + msgid "sort() argument" msgstr "argument de sort()" -#: ../eval.c:13721 -#, fuzzy msgid "uniq() argument" -msgstr "argument de add()" +msgstr "argument de uniq()" -#: ../eval.c:13776 msgid "E702: Sort compare function failed" msgstr "E702: La fonction de comparaison de sort() a échoué" -#: ../eval.c:13806 -#, fuzzy msgid "E882: Uniq compare function failed" -msgstr "E702: La fonction de comparaison de sort() a échoué" +msgstr "E882: La fonction de comparaison de uniq() a échoué" -#: ../eval.c:14085 msgid "(Invalid)" msgstr "(Invalide)" -#: ../eval.c:14590 -msgid "E677: Error writing temp file" -msgstr "E677: Erreur lors de l'écriture du fichier temporaire" - -#: ../eval.c:16159 -msgid "E805: Using a Float as a Number" -msgstr "E805: Utilisation d'un Flottant comme un Nombre" - -#: ../eval.c:16162 -msgid "E703: Using a Funcref as a Number" -msgstr "E703: Utilisation d'une Funcref comme un Nombre" - -#: ../eval.c:16170 -msgid "E745: Using a List as a Number" -msgstr "E745: Utilisation d'une Liste comme un Nombre" - -#: ../eval.c:16173 -msgid "E728: Using a Dictionary as a Number" -msgstr "E728: Utilisation d'un Dictionnaire comme un Nombre" - -#: ../eval.c:16259 -msgid "E729: using Funcref as a String" -msgstr "E729: Utilisation d'une Funcref comme une Chaîne" - -#: ../eval.c:16262 -msgid "E730: using List as a String" -msgstr "E730: Utilisation d'une Liste comme une Chaîne" - -#: ../eval.c:16265 -msgid "E731: using Dictionary as a String" -msgstr "E731: Utilisation d'un Dictionnaire comme une Chaîne" - -# DB : On doit pouvoir trouver nettement mieux que ça. -#: ../eval.c:16619 -#, c-format -msgid "E706: Variable type mismatch for: %s" -msgstr "E706: Type de variable incohérent pour %s" - -#: ../eval.c:16705 -#, c-format -msgid "E795: Cannot delete variable %s" -msgstr "E795: Impossible de supprimer la variable %s" - -#: ../eval.c:16724 -#, c-format -msgid "E704: Funcref variable name must start with a capital: %s" -msgstr "E704: Le nom d'une Funcref doit commencer par une majuscule : %s" - -#: ../eval.c:16732 -#, c-format -msgid "E705: Variable name conflicts with existing function: %s" -msgstr "E705: Le nom d'une variable entre en conflit avec la fonction %s" - -#: ../eval.c:16763 -#, c-format -msgid "E741: Value is locked: %s" -msgstr "E741: La valeur de %s est verrouillée" - -#: ../eval.c:16764 ../eval.c:16769 ../message.c:1839 -msgid "Unknown" -msgstr "Inconnu" - -#: ../eval.c:16768 -#, c-format -msgid "E742: Cannot change value of %s" -msgstr "E742: Impossible de modifier la valeur de %s" - -#: ../eval.c:16838 -msgid "E698: variable nested too deep for making a copy" -msgstr "E698: variable trop imbriquée pour en faire une copie" - -#: ../eval.c:17249 -#, c-format -msgid "E123: Undefined function: %s" -msgstr "E123: Fonction non définie : %s" - -# AB - La version française est plus consistante que la version anglaise. -# AB - Je suis partagé entre la concision d'une traduction assez littérale et -# la lourdeur d'une traduction plus correcte. -#: ../eval.c:17260 -#, c-format -msgid "E124: Missing '(': %s" -msgstr "E124: Il manque '(' après %s" - -#: ../eval.c:17293 -msgid "E862: Cannot use g: here" -msgstr "E862: Impossible d'utiliser g: ici" - -#: ../eval.c:17312 -#, c-format -msgid "E125: Illegal argument: %s" -msgstr "E125: Argument invalide : %s" - -#: ../eval.c:17323 -#, c-format -msgid "E853: Duplicate argument name: %s" -msgstr "E853: Nom d'argument dupliqué : %s" - -#: ../eval.c:17416 -msgid "E126: Missing :endfunction" -msgstr "E126: Il manque :endfunction" - -#: ../eval.c:17537 -#, c-format -msgid "E707: Function name conflicts with variable: %s" -msgstr "E707: Le nom de fonction entre en conflit avec la variable : %s" - -#: ../eval.c:17549 -#, c-format -msgid "E127: Cannot redefine function %s: It is in use" -msgstr "E127: Impossible de redéfinir fonction %s : déjà utilisée" - -# DB - Le contenu du "c-format" est le nom de la fonction. -#: ../eval.c:17604 -#, c-format -msgid "E746: Function name does not match script file name: %s" -msgstr "E746: Le nom de la fonction %s ne correspond pas le nom du script" - -#: ../eval.c:17716 -msgid "E129: Function name required" -msgstr "E129: Nom de fonction requis" - -#: ../eval.c:17824 -#, fuzzy, c-format -msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "E128: La fonction %s ne commence pas par une majuscule ou contient ':'" - -#: ../eval.c:17833 -#, fuzzy, c-format -msgid "E884: Function name cannot contain a colon: %s" -msgstr "E128: La fonction %s ne commence pas par une majuscule ou contient ':'" - -# AB - Il est difficile de créer une version française qui fasse moins de 80 -# caractères de long, nom de la fonction compris : "It is in use" est une -# expression très dense. Traductions possibles : "elle est utilisée", -# "elle s'exécute" ou "elle est occupée". -#: ../eval.c:18336 -#, c-format -msgid "E131: Cannot delete function %s: It is in use" -msgstr "E131: Impossible d'effacer %s : cette fonction est utilisée" - -# AB - Vérifier dans la littérature technique s'il n'existe pas une meilleure -# traduction pour "function call depth". -#: ../eval.c:18441 -msgid "E132: Function call depth is higher than 'maxfuncdepth'" -msgstr "" -"E132: La profondeur d'appel de fonction est supérieure à 'maxfuncdepth'" - -# AB - Ce texte fait partie d'un message de débogage. -#: ../eval.c:18568 #, c-format -msgid "calling %s" -msgstr "appel de %s" +msgid "E935: invalid submatch number: %d" +msgstr "E935: numéro de submatch invalide : %d" -# AB - Vérifier. -#: ../eval.c:18651 -#, c-format -msgid "%s aborted" -msgstr "%s annulée" - -# AB - Ce texte fait partie d'un message de débogage. -#: ../eval.c:18653 -#, c-format -msgid "%s returning #%<PRId64>" -msgstr "%s a retourné #%<PRId64>" - -# AB - Ce texte fait partie d'un message de débogage. -#: ../eval.c:18670 -#, c-format -msgid "%s returning %s" -msgstr "%s a retourné \"%s\"" - -# AB - Ce texte fait partie d'un message de débogage. -#: ../eval.c:18691 ../ex_cmds2.c:2695 -#, c-format -msgid "continuing in %s" -msgstr "de retour dans %s" - -#: ../eval.c:18795 -msgid "E133: :return not inside a function" -msgstr "E133: :return en dehors d'une fonction" - -# AB - La version française est capitalisée pour être en accord avec les autres -# commentaires enregistrés dans le fichier viminfo. -#: ../eval.c:19159 -msgid "" -"\n" -"# global variables:\n" -msgstr "" -"\n" -"# Variables globales:\n" - -# DB - Plus précis ("la dernière fois") ? -#: ../eval.c:19254 -msgid "" -"\n" -"\tLast set from " -msgstr "" -"\n" -"\tModifié la dernière fois dans " +msgid "E677: Error writing temp file" +msgstr "E677: Erreur lors de l'écriture du fichier temporaire" -#: ../eval.c:19272 -msgid "No old files" -msgstr "Aucun vieux fichier" +msgid "E921: Invalid callback argument" +msgstr "E921: Argument de callback invalide" -#: ../ex_cmds.c:122 #, c-format msgid "<%s>%s%s %d, Hex %02x, Octal %03o" msgstr "<%s>%s%s %d, Hexa %02x, Octal %03o" -#: ../ex_cmds.c:145 #, c-format msgid "> %d, Hex %04x, Octal %o" msgstr "> %d, Hexa %04x, Octal %o" -#: ../ex_cmds.c:146 #, c-format msgid "> %d, Hex %08x, Octal %o" msgstr "> %d, Hexa %08x, Octal %o" # AB - La version anglaise est très mauvaise, ce qui m'oblige a inventer une # version française. -#: ../ex_cmds.c:684 msgid "E134: Move lines into themselves" msgstr "E134: La destination est dans la plage d'origine" -#: ../ex_cmds.c:747 msgid "1 line moved" msgstr "1 ligne déplacée" -#: ../ex_cmds.c:749 #, c-format -msgid "%<PRId64> lines moved" -msgstr "%<PRId64> lignes déplacées" +msgid "%ld lines moved" +msgstr "%ld lignes déplacées" -#: ../ex_cmds.c:1175 #, c-format -msgid "%<PRId64> lines filtered" -msgstr "%<PRId64> lignes filtrées" +msgid "%ld lines filtered" +msgstr "%ld lignes filtrées" # AB - J'ai volontairement omis l'astérisque initiale car je pense que le # motif "Filter*" décrit plus clairement les quatre autocommandes liées # au filtrage (FilterReadPre, FilterReadPost, FilterWritePre et # FilterWritePost) que "*Filter*" que l'on confond avec une tentative de # mise en valeur. -#: ../ex_cmds.c:1194 msgid "E135: *Filter* Autocommands must not change current buffer" msgstr "" "E135: Les autocommandes Filter* ne doivent pas changer le tampon courant" # AB - Il faut respecter l'esprit plus que la lettre. Dans le cas présent, # nettement plus. -#: ../ex_cmds.c:1244 msgid "[No write since last change]\n" msgstr "[Attention : tout n'est pas enregistré]\n" # AB - Le numéro et le message d'erreur (%s ci-dessous) et le "numéro" de ligne # sont des chaînes de caractères dont le contenu est à la discrétion de # l'appelant de la fonction viminfo_error(). -#: ../ex_cmds.c:1424 #, c-format msgid "%sviminfo: %s in line: " msgstr "%sviminfo : %s à la ligne " # AB - La version française est meilleure que la version anglaise. -#: ../ex_cmds.c:1431 msgid "E136: viminfo: Too many errors, skipping rest of file" msgstr "" "E136: Il y a trop d'erreurs ; interruption de la lecture du fichier viminfo" @@ -1195,30 +939,25 @@ msgstr "" # AB - Ce texte fait partie d'un message de débogage. # DB - ... dont les valeurs possibles sont les messages # qui suivent. -#: ../ex_cmds.c:1458 #, c-format msgid "Reading viminfo file \"%s\"%s%s%s" msgstr "Lecture du fichier viminfo \"%s\"%s%s%s" # AB - Ce texte fait partie d'un message de débogage. # DB - Voir ci-dessus. -#: ../ex_cmds.c:1460 msgid " info" msgstr " info" # AB - Ce texte fait partie d'un message de débogage. # DB - Voir ci-dessus. -#: ../ex_cmds.c:1461 msgid " marks" msgstr " marques" -#: ../ex_cmds.c:1462 msgid " oldfiles" msgstr " vieux fichiers" # AB - Ce texte fait partie d'un message de débogage. # DB - Voir ci-dessus. -#: ../ex_cmds.c:1463 msgid " FAILED" msgstr " ÉCHEC" @@ -1227,33 +966,36 @@ msgstr " ÉCHEC" # AB - Le mot "viminfo" a été retiré pour que le message ne dépasse pas 80 # caractères dans le cas courant où %s = /home/12345678/.viminfo #. avoid a wait_return for this message, it's annoying -#: ../ex_cmds.c:1541 #, c-format msgid "E137: Viminfo file is not writable: %s" msgstr "E137: L'écriture dans le fichier %s est interdite" +#, c-format +msgid "E929: Too many viminfo temp files, like %s!" +msgstr "E929: Trop de fichiers temporaires viminfo, comme %s!" + # AB - Le point d'exclamation est superflu. # AB - Le mot "viminfo" a été retiré pour que le message ne dépasse pas 80 # caractères dans le cas courant où %s = /home/12345678/.viminfo -#: ../ex_cmds.c:1626 #, c-format msgid "E138: Can't write viminfo file %s!" msgstr "E138: Impossible d'écrire le fichier %s" # AB - Ce texte est un message de débogage. -#: ../ex_cmds.c:1635 #, c-format msgid "Writing viminfo file \"%s\"" msgstr "Écriture du fichier viminfo \"%s\"" +#, c-format +msgid "E886: Can't rename viminfo file to %s!" +msgstr "E886: Impossible de renommer viminfo en %s" + #. Write the info: -#: ../ex_cmds.c:1720 #, c-format msgid "# This viminfo file was generated by Vim %s.\n" msgstr "# Ce fichier viminfo a été généré par Vim %s.\n" # AB - Les deux versions, bien que différentes, se valent. -#: ../ex_cmds.c:1722 msgid "" "# You may edit it if you're careful!\n" "\n" @@ -1261,58 +1003,61 @@ msgstr "" "# Vous pouvez l'éditer, mais soyez prudent.\n" "\n" -#: ../ex_cmds.c:1723 msgid "# Value of 'encoding' when this file was written\n" msgstr "# 'encoding' dans lequel ce fichier a été écrit\n" # AB - Ce texte est passé en argument à la fonction viminfo_error(). # AB - "illégal" est un terme trop fort à mon goût. -#: ../ex_cmds.c:1800 msgid "Illegal starting char" msgstr "Caractère initial non valide" +msgid "" +"\n" +"# Bar lines, copied verbatim:\n" +msgstr "" +"\n" +"# Lignes commençant par |, copiées littéralement :\n" + +# AB - Ceci est un titre de boîte de dialogue. Vérifier que la version +# française est correcte pour les trois références ; j'ai un doute quant +# à la troisième. +msgid "Save As" +msgstr "Enregistrer sous - Vim" + # AB - Ceci est un contenu de boîte de dialogue (éventuellement en mode texte). # AB - La version française est meilleure que la version anglaise. -#: ../ex_cmds.c:2162 msgid "Write partial file?" msgstr "Perdre une partie du fichier ?" # AB - La version française est nettement meilleure que la version anglaise. -#: ../ex_cmds.c:2166 msgid "E140: Use ! to write partial buffer" msgstr "" "E140: Une partie du fichier serait perdue (ajoutez ! pour passer outre)" -#: ../ex_cmds.c:2281 #, c-format msgid "Overwrite existing file \"%s\"?" msgstr "Écraser le fichier %s existant ?" -#: ../ex_cmds.c:2317 #, c-format msgid "Swap file \"%s\" exists, overwrite anyway?" msgstr "Le fichier d'échange \"%s\" existe déjà, l'écraser ?" # DB - Un peu long à mon avis. -#: ../ex_cmds.c:2326 #, c-format msgid "E768: Swap file exists: %s (:silent! overrides)" msgstr "E768: Le fichier d'échange %s existe déjà (:silent! pour passer outre)" -#: ../ex_cmds.c:2381 #, c-format -msgid "E141: No file name for buffer %<PRId64>" -msgstr "E141: Pas de nom de fichier pour le tampon %<PRId64>" +msgid "E141: No file name for buffer %ld" +msgstr "E141: Pas de nom de fichier pour le tampon %ld" # AB - Il faut respecter l'esprit plus que la lettre. -#: ../ex_cmds.c:2412 msgid "E142: File not written: Writing is disabled by 'write' option" msgstr "" "E142: L'option 'nowrite' est activée et empêche toute écriture du fichier" # AB - Ceci est un contenu de boîte de dialogue (éventuellement en mode texte). # AB - "activée pour" n'est pas une formulation très heureuse. -#: ../ex_cmds.c:2434 #, c-format msgid "" "'readonly' option is set for \"%s\".\n" @@ -1321,7 +1066,6 @@ msgstr "" "L'option 'readonly' est activée pour \"%s\".\n" "Voulez-vous tout de même enregistrer ?" -#: ../ex_cmds.c:2439 #, c-format msgid "" "File permissions of \"%s\" are read-only.\n" @@ -1332,94 +1076,81 @@ msgstr "" "Il peut être possible de l'écrire tout de même.\n" "Tenter ?" -#: ../ex_cmds.c:2451 #, c-format msgid "E505: \"%s\" is read-only (add ! to override)" msgstr "E505: \"%s\" est en lecture seule (ajoutez ! pour passer outre)" +# AB - Ceci est un titre de boîte de dialogue. +msgid "Edit File" +msgstr "Ouvrir un fichier - Vim" + # AB - Il faut respecter l'esprit plus que la lettre. # AB - J'hésite à ajouter "à sa création" après le nom du tampon. Ce message # devrait n'être affiché qu'après une tentative d'ouverture de fichier, # la version actuelle devrait donc suffire. # DB - Suggestion : "nouveau tampon" ? -#: ../ex_cmds.c:3120 #, c-format msgid "E143: Autocommands unexpectedly deleted new buffer %s" msgstr "E143: Une autocommande a effacé le nouveau tampon %s" -#: ../ex_cmds.c:3313 msgid "E144: non-numeric argument to :z" msgstr "E144: L'argument de :z n'est pas numérique" # AB - La version française fera peut-être mieux passer l'amère pilule. # La consultation de l'aide donnera l'explication complète à ceux qui # ne comprendraient pas à quoi ce message est dû. -#: ../ex_cmds.c:3404 msgid "E145: Shell commands not allowed in rvim" msgstr "E145: Les commandes externes sont indisponibles dans rvim" -#: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "" "E146: Les expressions régulières ne peuvent pas être délimitées par des " "lettres" -#: ../ex_cmds.c:3964 #, c-format msgid "replace with %s (y/n/a/q/l/^E/^Y)?" msgstr "remplacer par %s (y/n/a/q/l/^E/^Y)?" -#: ../ex_cmds.c:4379 msgid "(Interrupted) " msgstr "(Interrompu) " -#: ../ex_cmds.c:4384 msgid "1 match" msgstr "1 correspondance" -#: ../ex_cmds.c:4384 msgid "1 substitution" msgstr "1 substitution" -#: ../ex_cmds.c:4387 #, c-format -msgid "%<PRId64> matches" -msgstr "%<PRId64> correspondances" +msgid "%ld matches" +msgstr "%ld correspondances" -#: ../ex_cmds.c:4388 #, c-format -msgid "%<PRId64> substitutions" -msgstr "%<PRId64> substitutions" +msgid "%ld substitutions" +msgstr "%ld substitutions" -#: ../ex_cmds.c:4392 msgid " on 1 line" msgstr " sur 1 ligne" -#: ../ex_cmds.c:4395 #, c-format -msgid " on %<PRId64> lines" -msgstr " sur %<PRId64> lignes" +msgid " on %ld lines" +msgstr " sur %ld lignes" # AB - Il faut respecter l'esprit plus que la lettre. # AB - Ce message devrait contenir une référence à :vglobal. -#: ../ex_cmds.c:4438 msgid "E147: Cannot do :global recursive" msgstr "E147: :global ne peut pas exécuter :global" # AB - Ce message devrait contenir une référence à :vglobal. -#: ../ex_cmds.c:4467 msgid "E148: Regular expression missing from global" msgstr "E148: :global doit être suivi par une expression régulière" # AB - Ce message est utilisé lorsque :vglobal ne trouve rien. Lorsque :global # ne trouve rien, c'est "Pattern not found: %s" / "Motif introuvable: %s" # qui est utilisé. -#: ../ex_cmds.c:4508 #, c-format msgid "Pattern found in every line: %s" msgstr "Motif trouvé dans toutes les lignes : %s" -#: ../ex_cmds.c:4510 #, c-format msgid "Pattern not found: %s" msgstr "Motif introuvable: %s" @@ -1430,7 +1161,6 @@ msgstr "Motif introuvable: %s" # à internationalisation. J'attends que les deux autres messages soient # traduisibles pour traduire celui-ci. # DB - TODO : Qu'en est-il à présent ? -#: ../ex_cmds.c:4587 msgid "" "\n" "# Last Substitute String:\n" @@ -1441,43 +1171,33 @@ msgstr "" "$" # This message should *so* be E42! -#: ../ex_cmds.c:4679 msgid "E478: Don't panic!" msgstr "E478: Pas de panique !" -#: ../ex_cmds.c:4717 #, c-format msgid "E661: Sorry, no '%s' help for %s" msgstr "E661: Désolé, aucune aide en langue '%s' pour %s" -#: ../ex_cmds.c:4719 #, c-format msgid "E149: Sorry, no help for %s" msgstr "E149: Désolé, aucune aide pour %s" -#: ../ex_cmds.c:4751 #, c-format msgid "Sorry, help file \"%s\" not found" msgstr "Désolé, le fichier d'aide \"%s\" est introuvable" -#: ../ex_cmds.c:5323 #, c-format -msgid "E150: Not a directory: %s" -msgstr "E150: %s n'est pas un répertoire" +msgid "E151: No match: %s" +msgstr "E151: Aucune correspondance : %s" -# AB - La version anglaise est plus précise, mais trop technique. -#: ../ex_cmds.c:5446 #, c-format msgid "E152: Cannot open %s for writing" -msgstr "E152: Impossible d'écrire %s" +msgstr "E152: Impossible d'ouvrir %s en écriture" -# AB - La version anglaise est plus précise, mais trop technique. -#: ../ex_cmds.c:5471 #, c-format msgid "E153: Unable to open %s for reading" -msgstr "E153: Impossible de lire %s" +msgstr "E153: Impossible d'ouvrir %s en lecture" -#: ../ex_cmds.c:5500 #, c-format msgid "E670: Mix of help file encodings within a language: %s" msgstr "E670: Encodages différents dans les fichiers d'aide en langue %s" @@ -1487,315 +1207,279 @@ msgstr "E670: Encodages différents dans les fichiers d'aide en langue %s" # traduction de 40 caractères ou moins. Ce qui est loin d'être le cas # présent. # DB - Suggestion. -#: ../ex_cmds.c:5565 #, c-format msgid "E154: Duplicate tag \"%s\" in file %s/%s" msgstr "E154: Marqueur \"%s\" dupliqué dans le fichier %s/%s" +#, c-format +msgid "E150: Not a directory: %s" +msgstr "E150: %s n'est pas un répertoire" + # AB - Il faut respecter l'esprit plus que la lettre. -#: ../ex_cmds.c:5687 #, c-format msgid "E160: Unknown sign command: %s" msgstr "E160: Commande inconnue : :sign %s" # AB - La version française est meilleure que la version anglaise. -#: ../ex_cmds.c:5704 msgid "E156: Missing sign name" msgstr "E156: Il manque le nom du symbole" -#: ../ex_cmds.c:5746 msgid "E612: Too many signs defined" msgstr "E612: Trop de symboles sont définis" # AB - Cette traduction ne me satisfait pas. # DB - Suggestion. -#: ../ex_cmds.c:5813 #, c-format msgid "E239: Invalid sign text: %s" msgstr "E239: Le texte du symbole est invalide : %s" -#: ../ex_cmds.c:5844 ../ex_cmds.c:6035 #, c-format msgid "E155: Unknown sign: %s" msgstr "E155: Symbole inconnu : %s" # AB - La version française est meilleure que la version anglaise. -#: ../ex_cmds.c:5877 msgid "E159: Missing sign number" msgstr "E159: Il manque l'ID du symbole" # AB - Vu le code source, la version française est meilleure que la # version anglaise. Ce message est similaire au message E102. -#: ../ex_cmds.c:5971 #, c-format msgid "E158: Invalid buffer name: %s" msgstr "E158: Le tampon %s est introuvable" +msgid "E934: Cannot jump to a buffer that does not have a name" +msgstr "E934: Impossible de sauter à un tampon sans nom" + # AB - Vu le code source, la version française est meilleure que la # version anglaise. -#: ../ex_cmds.c:6008 #, c-format -msgid "E157: Invalid sign ID: %<PRId64>" -msgstr "E157: Le symbole %<PRId64> est introuvable" +msgid "E157: Invalid sign ID: %ld" +msgstr "E157: Le symbole %ld est introuvable" + +#, c-format +msgid "E885: Not possible to change sign %s" +msgstr "E885: Impossible de changer le symbole %s" + +msgid " (NOT FOUND)" +msgstr " (INTROUVABLE)" -#: ../ex_cmds.c:6066 msgid " (not supported)" msgstr " (non supporté)" -#: ../ex_cmds.c:6169 msgid "[Deleted]" msgstr "[Effacé]" +msgid "No old files" +msgstr "Aucun vieux fichier" + # AB - La version française de la première phrase ne me satisfait pas. # DB - Suggestion. -#: ../ex_cmds2.c:139 msgid "Entering Debug mode. Type \"cont\" to continue." msgstr "Mode débogage activé. Tapez \"cont\" pour continuer." -#: ../ex_cmds2.c:143 ../ex_docmd.c:759 #, c-format -msgid "line %<PRId64>: %s" -msgstr "ligne %<PRId64> : %s" +msgid "line %ld: %s" +msgstr "ligne %ld : %s" -#: ../ex_cmds2.c:145 #, c-format msgid "cmd: %s" msgstr "cmde : %s" -#: ../ex_cmds2.c:322 +msgid "frame is zero" +msgstr "le cadre de pile est zéro" + +#, c-format +msgid "frame at highest level: %d" +msgstr "cadre de pile au niveau le plus haut : %d" + #, c-format -msgid "Breakpoint in \"%s%s\" line %<PRId64>" -msgstr "Point d'arrêt dans %s%s ligne %<PRId64>" +msgid "Breakpoint in \"%s%s\" line %ld" +msgstr "Point d'arrêt dans %s%s ligne %ld" -#: ../ex_cmds2.c:581 #, c-format msgid "E161: Breakpoint not found: %s" msgstr "E161: Le point d'arrêt %s est introuvable" -#: ../ex_cmds2.c:611 msgid "No breakpoints defined" msgstr "Aucun point d'arrêt n'est défini" # AB - Le deuxième %s est remplacé par "func" ou "file" sans que l'on puisse # traduire ces mots. -#: ../ex_cmds2.c:617 #, c-format -msgid "%3d %s %s line %<PRId64>" -msgstr "%3d %s %s ligne %<PRId64>" +msgid "%3d %s %s line %ld" +msgstr "%3d %s %s ligne %ld" -#: ../ex_cmds2.c:942 msgid "E750: First use \":profile start {fname}\"" msgstr "E750: Utilisez d'abord \":profile start {nomfichier}\"" # AB - "changes to" est redondant et a été omis de la version française. -#: ../ex_cmds2.c:1269 #, c-format msgid "Save changes to \"%s\"?" msgstr "Enregistrer \"%s\" ?" # AB - Si les parenthèses posent problème, il faudra remettre les guillemets # ci-dessus. -#: ../ex_cmds2.c:1271 ../ex_docmd.c:8851 msgid "Untitled" msgstr "(sans titre)" # AB - Il faut respecter l'esprit plus que la lettre. # AB - Ce message est similaire au message E89. -#: ../ex_cmds2.c:1421 #, c-format msgid "E162: No write since last change for buffer \"%s\"" msgstr "E162: Le tampon %s n'a pas été enregistré" -#: ../ex_cmds2.c:1480 msgid "Warning: Entered other buffer unexpectedly (check autocommands)" -msgstr "Alerte : Entrée inattendue dans un autre tampon (vérifier autocmdes)" +msgstr "" +"Alerte : Entrée inattendue dans un autre tampon (vérifier autocommandes)" -#: ../ex_cmds2.c:1826 msgid "E163: There is only one file to edit" msgstr "E163: Il n'y a qu'un seul fichier à éditer" -#: ../ex_cmds2.c:1828 msgid "E164: Cannot go before first file" msgstr "E164: Impossible d'aller avant le premier fichier" -#: ../ex_cmds2.c:1830 msgid "E165: Cannot go beyond last file" msgstr "E165: Impossible d'aller au-delà du dernier fichier" -#: ../ex_cmds2.c:2175 #, c-format msgid "E666: compiler not supported: %s" msgstr "E666: Compilateur %s non supporté" -#: ../ex_cmds2.c:2257 #, c-format msgid "Searching for \"%s\" in \"%s\"" msgstr "Recherche de \"%s\" dans \"%s\"" -#: ../ex_cmds2.c:2284 #, c-format msgid "Searching for \"%s\"" msgstr "Recherche de \"%s\"" -#: ../ex_cmds2.c:2307 #, c-format msgid "not found in '%s': \"%s\"" msgstr "introuvable dans '%s' : \"%s\"" -#: ../ex_cmds2.c:2472 +msgid "Source Vim script" +msgstr "Sourcer un script - Vim" + #, c-format msgid "Cannot source a directory: \"%s\"" msgstr "Impossible de sourcer un répertoire : \"%s\"" -#: ../ex_cmds2.c:2518 #, c-format msgid "could not source \"%s\"" msgstr "impossible de sourcer \"%s\"" -#: ../ex_cmds2.c:2520 #, c-format -msgid "line %<PRId64>: could not source \"%s\"" -msgstr "ligne %<PRId64> : impossible de sourcer \"%s\"" +msgid "line %ld: could not source \"%s\"" +msgstr "ligne %ld : impossible de sourcer \"%s\"" -#: ../ex_cmds2.c:2535 #, c-format msgid "sourcing \"%s\"" msgstr "sourcement \"%s\"" -#: ../ex_cmds2.c:2537 #, c-format -msgid "line %<PRId64>: sourcing \"%s\"" -msgstr "ligne %<PRId64> : sourcement de \"%s\"" +msgid "line %ld: sourcing \"%s\"" +msgstr "ligne %ld : sourcement de \"%s\"" -#: ../ex_cmds2.c:2693 #, c-format msgid "finished sourcing %s" msgstr "fin du sourcement de %s" -#: ../ex_cmds2.c:2765 +# AB - Ce texte fait partie d'un message de débogage. +#, c-format +msgid "continuing in %s" +msgstr "de retour dans %s" + msgid "modeline" msgstr "ligne de mode" -#: ../ex_cmds2.c:2767 msgid "--cmd argument" msgstr "argument --cmd" -#: ../ex_cmds2.c:2769 msgid "-c argument" msgstr "argument -c" -#: ../ex_cmds2.c:2771 msgid "environment variable" msgstr "variable d'environnement" -#: ../ex_cmds2.c:2773 msgid "error handler" msgstr "gestionnaire d'erreur" -#: ../ex_cmds2.c:3020 msgid "W15: Warning: Wrong line separator, ^M may be missing" msgstr "W15: Alerte : Séparateur de ligne erroné, ^M possiblement manquant" -#: ../ex_cmds2.c:3139 msgid "E167: :scriptencoding used outside of a sourced file" msgstr "E167: :scriptencoding utilisé en dehors d'un fichier sourcé" -#: ../ex_cmds2.c:3166 msgid "E168: :finish used outside of a sourced file" msgstr "E168: :finish utilisé en dehors d'un fichier sourcé" # DB - Le premier %s est, au choix : "time ", "ctype " ou "messages ", # sans qu'il soit possible de les traduire. -#: ../ex_cmds2.c:3389 #, c-format msgid "Current %slanguage: \"%s\"" msgstr "Langue courante pour %s : \"%s\"" -#: ../ex_cmds2.c:3404 #, c-format msgid "E197: Cannot set language to \"%s\"" msgstr "E197: Impossible de choisir la langue \"%s\"" -#. don't redisplay the window -#. don't wait for return -#: ../ex_docmd.c:387 msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." msgstr "Mode Ex activé. Tapez \"visual\" pour passer en mode Normal." -#: ../ex_docmd.c:428 msgid "E501: At end-of-file" msgstr "E501: À la fin du fichier" -#: ../ex_docmd.c:513 msgid "E169: Command too recursive" msgstr "E169: Commande trop récursive" -#: ../ex_docmd.c:1006 #, c-format msgid "E605: Exception not caught: %s" msgstr "E605: Exception non interceptée : %s" -#: ../ex_docmd.c:1085 msgid "End of sourced file" msgstr "Fin du fichier sourcé" -#: ../ex_docmd.c:1086 msgid "End of function" msgstr "Fin de la fonction" -#: ../ex_docmd.c:1628 msgid "E464: Ambiguous use of user-defined command" msgstr "E464: Utilisation ambiguë d'une commande définie par l'utilisateur" -#: ../ex_docmd.c:1638 msgid "E492: Not an editor command" msgstr "E492: Commande inconnue" -#: ../ex_docmd.c:1729 msgid "E493: Backwards range given" msgstr "E493: La plage spécifiée est inversée" -#: ../ex_docmd.c:1733 msgid "Backwards range given, OK to swap" msgstr "La plage spécifiée est inversée, OK pour l'inverser" -#. append -#. typed wrong -#: ../ex_docmd.c:1787 msgid "E494: Use w or w>>" msgstr "E494: Utilisez w ou w>>" -#: ../ex_docmd.c:3454 -msgid "E319: The command is not available in this version" +msgid "E319: Sorry, the command is not available in this version" msgstr "E319: Désolé, cette commande n'est pas disponible dans cette version" -#: ../ex_docmd.c:3752 msgid "E172: Only one file name allowed" msgstr "E172: Un seul nom de fichier autorisé" -#: ../ex_docmd.c:4238 msgid "1 more file to edit. Quit anyway?" msgstr "Encore 1 fichier à éditer. Quitter tout de même ?" -#: ../ex_docmd.c:4242 #, c-format msgid "%d more files to edit. Quit anyway?" msgstr "Encore %d fichiers à éditer. Quitter tout de même ?" -#: ../ex_docmd.c:4248 msgid "E173: 1 more file to edit" msgstr "E173: encore 1 fichier à éditer" -#: ../ex_docmd.c:4250 #, c-format -msgid "E173: %<PRId64> more files to edit" -msgstr "E173: encore %<PRId64> fichiers à éditer" +msgid "E173: %ld more files to edit" +msgstr "E173: encore %ld fichiers à éditer" -#: ../ex_docmd.c:4320 msgid "E174: Command already exists: add ! to replace it" msgstr "E174: La commande existe déjà : ajoutez ! pour la redéfinir" -#: ../ex_docmd.c:4432 msgid "" "\n" " Name Args Address Complete Definition" @@ -1803,356 +1487,311 @@ msgstr "" "\n" " Nom Args Adresse Complet. Définition" -#: ../ex_docmd.c:4516 msgid "No user-defined commands found" msgstr "Aucune commande définie par l'utilisateur trouvée" -#: ../ex_docmd.c:4538 msgid "E175: No attribute specified" msgstr "E175: Pas d'attribut spécifié" -#: ../ex_docmd.c:4583 msgid "E176: Invalid number of arguments" msgstr "E176: Nombre d'arguments invalide" -#: ../ex_docmd.c:4594 msgid "E177: Count cannot be specified twice" msgstr "E177: Le quantificateur ne peut être spécifié deux fois" -#: ../ex_docmd.c:4603 msgid "E178: Invalid default value for count" msgstr "E178: La valeur par défaut du quantificateur est invalide" -#: ../ex_docmd.c:4625 msgid "E179: argument required for -complete" msgstr "E179: argument requis avec -complete" -#: ../ex_docmd.c:4933 msgid "E179: argument required for -addr" msgstr "E179: argument requis avec -addr" -#: ../ex_docmd.c:4635 #, c-format msgid "E181: Invalid attribute: %s" msgstr "E181: Attribut invalide : %s" -#: ../ex_docmd.c:4678 msgid "E182: Invalid command name" msgstr "E182: Nom de commande invalide" -#: ../ex_docmd.c:4691 msgid "E183: User defined commands must start with an uppercase letter" msgstr "E183: Les commandes utilisateur doivent commencer par une majuscule" -#: ../ex_docmd.c:4696 msgid "E841: Reserved name, cannot be used for user defined command" msgstr "" "E841: Nom réservé, ne peux pas être utilisé pour une commande utilisateur" -#: ../ex_docmd.c:4751 #, c-format msgid "E184: No such user-defined command: %s" msgstr "E184: Aucune commande %s définie par l'utilisateur" -#: ../ex_docmd.c:5516 #, c-format msgid "E180: Invalid address type value: %s" msgstr "E180: Valeur de type d'adresse invalide : %s" -#: ../ex_docmd.c:5219 #, c-format msgid "E180: Invalid complete value: %s" msgstr "E180: Valeur invalide pour \"-complete=\" : %s" -#: ../ex_docmd.c:5225 msgid "E468: Completion argument only allowed for custom completion" msgstr "E468: Seul le complètement personnalisé accepte un argument" -#: ../ex_docmd.c:5231 msgid "E467: Custom completion requires a function argument" -msgstr "E467: Le complètement personnalisé requiert une fonction en argument" +msgstr "E467: Le complètement personnalisé nécessite une fonction en argument" + +msgid "unknown" +msgstr "inconnu" -#: ../ex_docmd.c:5257 #, c-format msgid "E185: Cannot find color scheme '%s'" msgstr "E185: Impossible de trouver le jeu de couleurs '%s'" -#: ../ex_docmd.c:5263 msgid "Greetings, Vim user!" msgstr "Bienvenue, utilisateur de Vim !" -#: ../ex_docmd.c:5431 msgid "E784: Cannot close last tab page" msgstr "E784: Impossible de fermer le dernier onglet" -#: ../ex_docmd.c:5462 msgid "Already only one tab page" msgstr "Il ne reste déjà plus qu'un seul onglet" -#: ../ex_docmd.c:6004 +msgid "Edit File in new window" +msgstr "Ouvrir un fichier dans une nouvelle fenêtre - Vim" + #, c-format msgid "Tab page %d" msgstr "Onglet %d" -#: ../ex_docmd.c:6295 msgid "No swap file" msgstr "Pas de fichier d'échange" -#: ../ex_docmd.c:6478 +msgid "Append File" +msgstr "Ajouter fichier" + msgid "E747: Cannot change directory, buffer is modified (add ! to override)" msgstr "" "E747: Tampon modifié : impossible de changer de répertoire (ajoutez ! pour " "passer outre)" -#: ../ex_docmd.c:6485 msgid "E186: No previous directory" msgstr "E186: Pas de répertoire précédent" -#: ../ex_docmd.c:6530 msgid "E187: Unknown" msgstr "E187: Inconnu" -#: ../ex_docmd.c:6610 msgid "E465: :winsize requires two number arguments" -msgstr "E465: :winsize requiert deux arguments numériques" +msgstr "E465: :winsize nécessite deux arguments numériques" + +#, c-format +msgid "Window position: X %d, Y %d" +msgstr "Position de la fenêtre : X %d, Y %d" # DB : Suggestion, sans doute perfectible. -#: ../ex_docmd.c:6655 msgid "E188: Obtaining window position not implemented for this platform" msgstr "" "E188: Récupérer la position de la fenêtre non implémenté dans cette version" -#: ../ex_docmd.c:6662 msgid "E466: :winpos requires two number arguments" -msgstr "E466: :winpos requiert deux arguments numériques" +msgstr "E466: :winpos nécessite deux arguments numériques" + +msgid "E930: Cannot use :redir inside execute()" +msgstr "E930: Impossible d'utiliser :redir dans execute()" + +msgid "Save Redirection" +msgstr "Enregistrer la redirection" + +msgid "Save View" +msgstr "Enregistrer la vue - Vim" + +msgid "Save Session" +msgstr "Enregistrer la session - Vim" + +msgid "Save Setup" +msgstr "Enregistrer les réglages - Vim" -#: ../ex_docmd.c:7241 #, c-format msgid "E739: Cannot create directory: %s" msgstr "E739: Impossible de créer le répertoire \"%s\"" -#: ../ex_docmd.c:7268 #, c-format msgid "E189: \"%s\" exists (add ! to override)" msgstr "E189: \"%s\" existe (ajoutez ! pour passer outre)" -#: ../ex_docmd.c:7273 #, c-format msgid "E190: Cannot open \"%s\" for writing" msgstr "E190: Impossible d'ouvrir \"%s\" pour y écrire" #. set mark -#: ../ex_docmd.c:7294 msgid "E191: Argument must be a letter or forward/backward quote" msgstr "E191: L'argument doit être une lettre ou une (contre-)apostrophe" -#: ../ex_docmd.c:7333 msgid "E192: Recursive use of :normal too deep" msgstr "E192: Appel récursif de :normal trop important" -#: ../ex_docmd.c:7807 +msgid "E809: #< is not available without the +eval feature" +msgstr "E809: #< n'est pas disponible sans la fonctionnalité +eval" + msgid "E194: No alternate file name to substitute for '#'" msgstr "E194: Aucun nom de fichier alternatif à substituer à '#'" -#: ../ex_docmd.c:7841 msgid "E495: no autocommand file name to substitute for \"<afile>\"" msgstr "E495: Aucun nom de ficher d'autocommande à substituer à \"<afile>\"" -#: ../ex_docmd.c:7850 msgid "E496: no autocommand buffer number to substitute for \"<abuf>\"" msgstr "E496: Aucun numéro de tampon d'autocommande à substituer à \"<abuf>\"" -#: ../ex_docmd.c:7861 msgid "E497: no autocommand match name to substitute for \"<amatch>\"" msgstr "E497: Aucune correspondance d'autocommande à substituer à \"<amatch>\"" -#: ../ex_docmd.c:7870 msgid "E498: no :source file name to substitute for \"<sfile>\"" msgstr "E498: Aucun nom de fichier :source à substituer à \"<sfile>\"" -#: ../ex_docmd.c:7876 msgid "E842: no line number to use for \"<slnum>\"" msgstr "E842: aucun numéro de ligne à utiliser pour \"<slnum>\"" -#: ../ex_docmd.c:7903 -#, c-format +#, no-c-format msgid "E499: Empty file name for '%' or '#', only works with \":p:h\"" msgstr "E499: Nom de fichier vide pour '%' ou '#', ne marche qu'avec \":p:h\"" -#: ../ex_docmd.c:7905 msgid "E500: Evaluates to an empty string" msgstr "E500: Évalué en une chaîne vide" -#: ../ex_docmd.c:8838 msgid "E195: Cannot open viminfo file for reading" msgstr "E195: Impossible d'ouvrir le viminfo en lecture" -#: ../ex_eval.c:464 +msgid "E196: No digraphs in this version" +msgstr "E196: Pas de digraphes dans cette version" + msgid "E608: Cannot :throw exceptions with 'Vim' prefix" msgstr "E608: Impossible d'émettre des exceptions avec 'Vim' comme préfixe" #. always scroll up, don't overwrite -#: ../ex_eval.c:496 #, c-format msgid "Exception thrown: %s" msgstr "Exception émise : %s" -#: ../ex_eval.c:545 #, c-format msgid "Exception finished: %s" msgstr "Exception terminée : %s" -#: ../ex_eval.c:546 #, c-format msgid "Exception discarded: %s" msgstr "Exception éliminée : %s" -#: ../ex_eval.c:588 ../ex_eval.c:634 #, c-format -msgid "%s, line %<PRId64>" -msgstr "%s, ligne %<PRId64>" +msgid "%s, line %ld" +msgstr "%s, ligne %ld" #. always scroll up, don't overwrite -#: ../ex_eval.c:608 #, c-format msgid "Exception caught: %s" msgstr "Exception interceptée : %s" # DB - Le c-format est féminin, singulier ou pluriel (cf. 3 messages plus bas). -#: ../ex_eval.c:676 #, c-format msgid "%s made pending" msgstr "%s mise(s) en attente" -#: ../ex_eval.c:679 #, c-format msgid "%s resumed" msgstr "%s ré-émise(s)" -#: ../ex_eval.c:683 #, c-format msgid "%s discarded" msgstr "%s éliminée(s)" -#: ../ex_eval.c:708 msgid "Exception" msgstr "Exception" -#: ../ex_eval.c:713 msgid "Error and interrupt" msgstr "Erreur et interruption" -#: ../ex_eval.c:715 msgid "Error" msgstr "Erreur" #. if (pending & CSTP_INTERRUPT) -#: ../ex_eval.c:717 msgid "Interrupt" msgstr "Interruption" -#: ../ex_eval.c:795 msgid "E579: :if nesting too deep" msgstr "E579: Imbrication de :if trop importante" -#: ../ex_eval.c:830 msgid "E580: :endif without :if" msgstr "E580: :endif sans :if" -#: ../ex_eval.c:873 msgid "E581: :else without :if" msgstr "E581: :else sans :if" -#: ../ex_eval.c:876 msgid "E582: :elseif without :if" msgstr "E582: :elseif sans :if" -#: ../ex_eval.c:880 msgid "E583: multiple :else" msgstr "E583: Il ne peut y avoir qu'un seul :else" -#: ../ex_eval.c:883 msgid "E584: :elseif after :else" msgstr "E584: :elseif après :else" -#: ../ex_eval.c:941 msgid "E585: :while/:for nesting too deep" msgstr "E585: Imbrication de :while ou :for trop importante" -#: ../ex_eval.c:1028 msgid "E586: :continue without :while or :for" msgstr "E586: :continue sans :while ou :for" -#: ../ex_eval.c:1061 msgid "E587: :break without :while or :for" msgstr "E587: :break sans :while ou :for" -#: ../ex_eval.c:1102 msgid "E732: Using :endfor with :while" msgstr "E732: Utilisation de :endfor avec :while" -#: ../ex_eval.c:1104 msgid "E733: Using :endwhile with :for" msgstr "E733: Utilisation de :endwhile avec :for" -#: ../ex_eval.c:1247 msgid "E601: :try nesting too deep" msgstr "E601: Imbrication de :try trop importante" -#: ../ex_eval.c:1317 msgid "E603: :catch without :try" msgstr "E603: :catch sans :try" #. Give up for a ":catch" after ":finally" and ignore it. #. * Just parse. -#: ../ex_eval.c:1332 msgid "E604: :catch after :finally" msgstr "E604: :catch après :finally" -#: ../ex_eval.c:1451 msgid "E606: :finally without :try" msgstr "E606: :finally sans :try" #. Give up for a multiple ":finally" and ignore it. -#: ../ex_eval.c:1467 msgid "E607: multiple :finally" msgstr "E607: Il ne peut y avoir qu'un seul :finally" -#: ../ex_eval.c:1571 msgid "E602: :endtry without :try" msgstr "E602: :endtry sans :try" -#: ../ex_eval.c:2026 msgid "E193: :endfunction not inside a function" msgstr "E193: :endfunction en dehors d'une fonction" -#: ../ex_getln.c:1643 msgid "E788: Not allowed to edit another buffer now" msgstr "E788: L'édition d'un autre tampon n'est plus permise" -#: ../ex_getln.c:1656 msgid "E811: Not allowed to change buffer information now" msgstr "" "E811: Changement des informations du tampon n'est pas permise maintenant" # DB - TODO : Pas compris le message ni comment le déclencher malgré une visite # dans le code. -#: ../ex_getln.c:3178 msgid "tagname" msgstr "nom du marqueur" # DB - TODO : Idem précédent. -#: ../ex_getln.c:3181 msgid " kind file\n" msgstr " type de fichier\n" -#: ../ex_getln.c:4799 msgid "'history' option is zero" msgstr "l'option 'history' vaut zéro" # DB - Messages et les suivants : fichier .viminfo. # Pas de majuscule nécessaire pour les messages d'après. -#: ../ex_getln.c:5046 #, c-format msgid "" "\n" @@ -2161,311 +1800,232 @@ msgstr "" "\n" "# Historique %s (chronologie décroissante) :\n" -#: ../ex_getln.c:5047 msgid "Command Line" msgstr "ligne de commande" -#: ../ex_getln.c:5048 msgid "Search String" msgstr "chaîne de recherche" -#: ../ex_getln.c:5049 msgid "Expression" msgstr "expression" -#: ../ex_getln.c:5050 msgid "Input Line" msgstr "ligne de saisie" -#: ../ex_getln.c:5117 +msgid "Debug Line" +msgstr "Ligne de débogage" + msgid "E198: cmd_pchar beyond the command length" msgstr "E198: cmd_pchar au-delà de la longueur de la commande" -#: ../ex_getln.c:5279 msgid "E199: Active window or buffer deleted" msgstr "E199: Fenêtre ou tampon actif effacé" -#: ../file_search.c:203 -msgid "E854: path too long for completion" -msgstr "E854: chemin trop long pour complètement" - -#: ../file_search.c:446 -#, c-format -msgid "" -"E343: Invalid path: '**[number]' must be at the end of the path or be " -"followed by '%s'." -msgstr "" -"E343: Chemin invalide : '**[nombre]' doit être à la fin du chemin ou être " -"suivi de '%s'." - -#: ../file_search.c:1505 -#, c-format -msgid "E344: Can't find directory \"%s\" in cdpath" -msgstr "E344: Répertoire \"%s\" introuvable dans 'cdpath'" - -#: ../file_search.c:1508 -#, c-format -msgid "E345: Can't find file \"%s\" in path" -msgstr "E345: Fichier \"%s\" introuvable dans 'path'" - -#: ../file_search.c:1512 -#, c-format -msgid "E346: No more directory \"%s\" found in cdpath" -msgstr "E346: Plus de répertoire \"%s\" dans 'cdpath'" - -#: ../file_search.c:1515 -#, c-format -msgid "E347: No more file \"%s\" found in path" -msgstr "E347: Plus de fichier \"%s\" dans 'path'" - -#: ../fileio.c:137 msgid "E812: Autocommands changed buffer or buffer name" msgstr "E812: Des autocommandes ont changé le tampon ou le nom du tampon" -#: ../fileio.c:368 msgid "Illegal file name" msgstr "Nom de fichier invalide" -#: ../fileio.c:395 ../fileio.c:476 ../fileio.c:2543 ../fileio.c:2578 msgid "is a directory" msgstr "est un répertoire" -#: ../fileio.c:397 msgid "is not a file" msgstr "n'est pas un fichier" -#: ../fileio.c:508 ../fileio.c:3522 +msgid "is a device (disabled with 'opendevice' option)" +msgstr "est un périphérique (désactivé par l'option 'opendevice')" + msgid "[New File]" msgstr "[Nouveau fichier]" -#: ../fileio.c:511 msgid "[New DIRECTORY]" msgstr "[Nouveau RÉPERTOIRE]" -#: ../fileio.c:529 ../fileio.c:532 msgid "[File too big]" msgstr "[Fichier trop volumineux]" -#: ../fileio.c:534 msgid "[Permission Denied]" msgstr "[Permission refusée]" -#: ../fileio.c:653 msgid "E200: *ReadPre autocommands made the file unreadable" msgstr "E200: Les autocommandes *ReadPre ont rendu le fichier illisible" -#: ../fileio.c:655 msgid "E201: *ReadPre autocommands must not change current buffer" msgstr "" "E201: Autocommandes *ReadPre ne doivent pas modifier le contenu du tampon " "courant" -#: ../fileio.c:672 -msgid "Nvim: Reading from stdin...\n" +msgid "Vim: Reading from stdin...\n" msgstr "Vim : Lecture de stdin...\n" +msgid "Reading from stdin..." +msgstr "Lecture de stdin..." + #. Re-opening the original file failed! -#: ../fileio.c:909 msgid "E202: Conversion made file unreadable!" msgstr "E202: La conversion a rendu le fichier illisible !" -#. fifo or socket -#: ../fileio.c:1782 msgid "[fifo/socket]" msgstr "[fifo/socket]" -#. fifo -#: ../fileio.c:1788 msgid "[fifo]" msgstr "[fifo]" -#. or socket -#: ../fileio.c:1794 msgid "[socket]" msgstr "[socket]" -#. or character special -#: ../fileio.c:1801 msgid "[character special]" msgstr "[caractère spécial]" -#: ../fileio.c:1815 msgid "[CR missing]" msgstr "[CR manquant]" -#: ../fileio.c:1819 msgid "[long lines split]" msgstr "[lignes longues coupées]" -#: ../fileio.c:1823 ../fileio.c:3512 msgid "[NOT converted]" msgstr "[NON converti]" -#: ../fileio.c:1826 ../fileio.c:3515 msgid "[converted]" msgstr "[converti]" -#: ../fileio.c:1831 #, c-format -msgid "[CONVERSION ERROR in line %<PRId64>]" -msgstr "[ERREUR DE CONVERSION à la ligne %<PRId64>]" +msgid "[CONVERSION ERROR in line %ld]" +msgstr "[ERREUR DE CONVERSION à la ligne %ld]" -#: ../fileio.c:1835 #, c-format -msgid "[ILLEGAL BYTE in line %<PRId64>]" -msgstr "[OCTET INVALIDE à la ligne %<PRId64>]" +msgid "[ILLEGAL BYTE in line %ld]" +msgstr "[OCTET INVALIDE à la ligne %ld]" -#: ../fileio.c:1838 msgid "[READ ERRORS]" msgstr "[ERREURS DE LECTURE]" -#: ../fileio.c:2104 msgid "Can't find temp file for conversion" msgstr "Impossible de générer un fichier temporaire pour la conversion" -#: ../fileio.c:2110 msgid "Conversion with 'charconvert' failed" msgstr "La conversion avec 'charconvert' a échoué" # DB : Pas de majuscule ? -#: ../fileio.c:2113 msgid "can't read output of 'charconvert'" msgstr "Impossible de lire la sortie de 'charconvert'" -#: ../fileio.c:2437 msgid "E676: No matching autocommands for acwrite buffer" msgstr "E676: Pas d'autocommande correspondante pour le tampon acwrite" -#: ../fileio.c:2466 msgid "E203: Autocommands deleted or unloaded buffer to be written" msgstr "E203: Des autocommandes ont effacé ou déchargé le tampon à écrire" -#: ../fileio.c:2486 msgid "E204: Autocommand changed number of lines in unexpected way" msgstr "" "E204: L'autocommande a modifié le nombre de lignes de manière inattendue" -#: ../fileio.c:2548 ../fileio.c:2565 +msgid "NetBeans disallows writes of unmodified buffers" +msgstr "NetBeans interdit l'écriture des tampons non modifiés" + +msgid "Partial writes disallowed for NetBeans buffers" +msgstr "Netbeans interdit l'écriture partielle de ses tampons" + msgid "is not a file or writable device" msgstr "n'est pas un fichier ou un périphérique inscriptible" -#: ../fileio.c:2601 +msgid "writing to device disabled with 'opendevice' option" +msgstr "écriture vers un périphérique désactivé par l'option 'opendevice'" + msgid "is read-only (add ! to override)" msgstr "est en lecture seule (ajoutez ! pour passer outre)" -#: ../fileio.c:2886 msgid "E506: Can't write to backup file (add ! to override)" msgstr "E506: Impossible d'écrire la copie de secours (! pour passer outre)" -#: ../fileio.c:2898 msgid "E507: Close error for backup file (add ! to override)" msgstr "E507: Erreur de fermeture de la copie de secours (! pour passer outre)" -#: ../fileio.c:2901 msgid "E508: Can't read file for backup (add ! to override)" msgstr "" "E508: Impossible de lire le fichier pour la copie de secours (ajoutez ! pour " "passer outre)" -#: ../fileio.c:2923 msgid "E509: Cannot create backup file (add ! to override)" msgstr "" "E509: Impossible de créer la copie de secours (ajoutez ! pour passer outre)" -#: ../fileio.c:3008 msgid "E510: Can't make backup file (add ! to override)" msgstr "" "E510: Impossible de générer la copie de secours (ajoutez ! pour passer outre)" -#. Can't write without a tempfile! -#: ../fileio.c:3121 +msgid "E460: The resource fork would be lost (add ! to override)" +msgstr "" +"E460: Les ressources partagées seraient perdues (ajoutez ! pour passer outre)" + msgid "E214: Can't find temp file for writing" msgstr "E214: Impossible de générer un fichier temporaire pour y écrire" -#: ../fileio.c:3134 msgid "E213: Cannot convert (add ! to write without conversion)" msgstr "E213: Impossible de convertir (ajoutez ! pour écrire sans convertir)" -#: ../fileio.c:3169 msgid "E166: Can't open linked file for writing" msgstr "E166: Impossible d'ouvrir le lien pour y écrire" -#: ../fileio.c:3173 msgid "E212: Can't open file for writing" msgstr "E212: Impossible d'ouvrir le fichier pour y écrire" -#: ../fileio.c:3363 msgid "E667: Fsync failed" msgstr "E667: Fsynch a échoué" -#: ../fileio.c:3398 msgid "E512: Close failed" msgstr "E512: Erreur de fermeture de fichier" -#: ../fileio.c:3436 msgid "E513: write error, conversion failed (make 'fenc' empty to override)" msgstr "" "E513: Erreur d'écriture, échec de conversion (videz 'fenc' pour passer outre)" -#: ../fileio.c:3441 #, c-format msgid "" -"E513: write error, conversion failed in line %<PRId64> (make 'fenc' empty to " +"E513: write error, conversion failed in line %ld (make 'fenc' empty to " "override)" msgstr "" -"E513: Erreur d'écriture, échec de conversion à la ligne %<PRId64> (videz " -"'fenc' pour passer outre)" +"E513: Erreur d'écriture, échec de conversion à la ligne %ld (videz 'fenc' " +"pour passer outre)" -#: ../fileio.c:3448 msgid "E514: write error (file system full?)" msgstr "E514: erreur d'écriture (système de fichiers plein ?)" -#: ../fileio.c:3506 msgid " CONVERSION ERROR" msgstr " ERREUR DE CONVERSION" -#: ../fileio.c:3509 #, c-format -msgid " in line %<PRId64>;" -msgstr " à la ligne %<PRId64>" +msgid " in line %ld;" +msgstr " à la ligne %ld" -#: ../fileio.c:3519 msgid "[Device]" msgstr "[Périph.]" -#: ../fileio.c:3522 msgid "[New]" msgstr "[Nouveau]" -#: ../fileio.c:3535 msgid " [a]" msgstr " [a]" -#: ../fileio.c:3535 msgid " appended" msgstr " ajouté(s)" -#: ../fileio.c:3537 msgid " [w]" msgstr " [e]" -#: ../fileio.c:3537 msgid " written" msgstr " écrit(s)" -#: ../fileio.c:3579 msgid "E205: Patchmode: can't save original file" msgstr "E205: Patchmode : impossible d'enregistrer le fichier original" -#: ../fileio.c:3602 msgid "E206: patchmode: can't touch empty original file" msgstr "E206: patchmode : impossible de créer le fichier original vide" -#: ../fileio.c:3616 msgid "E207: Can't delete backup file" msgstr "E207: Impossible d'effacer la copie de secours" -#: ../fileio.c:3672 msgid "" "\n" "WARNING: Original file may be lost or damaged\n" @@ -2474,99 +2034,78 @@ msgstr "" "ALERTE: Le fichier original est peut-être perdu ou endommagé\n" # DB - todo : un peu long... -#: ../fileio.c:3675 msgid "don't quit the editor until the file is successfully written!" msgstr "" "ne quittez pas l'éditeur tant que le fichier n'est pas correctement " "enregistré !" -#: ../fileio.c:3795 msgid "[dos]" msgstr "[dos]" -#: ../fileio.c:3795 msgid "[dos format]" msgstr "[format dos]" -#: ../fileio.c:3801 msgid "[mac]" msgstr "[mac]" -#: ../fileio.c:3801 msgid "[mac format]" msgstr "[format mac]" -#: ../fileio.c:3807 msgid "[unix]" msgstr "[unix]" -#: ../fileio.c:3807 msgid "[unix format]" msgstr "[format unix]" -#: ../fileio.c:3831 msgid "1 line, " msgstr "1 ligne, " -#: ../fileio.c:3833 #, c-format -msgid "%<PRId64> lines, " -msgstr "%<PRId64> lignes, " +msgid "%ld lines, " +msgstr "%ld lignes, " -#: ../fileio.c:3836 msgid "1 character" msgstr "1 caractère" -#: ../fileio.c:3838 #, c-format -msgid "%<PRId64> characters" -msgstr "%<PRId64> caractères" +msgid "%lld characters" +msgstr "%lld caractères" -#: ../fileio.c:3849 msgid "[noeol]" msgstr "[noeol]" -#: ../fileio.c:3849 msgid "[Incomplete last line]" msgstr "[Dernière ligne incomplète]" #. don't overwrite messages here #. must give this prompt #. don't use emsg() here, don't want to flush the buffers -#: ../fileio.c:3865 msgid "WARNING: The file has been changed since reading it!!!" msgstr "ALERTE : Le fichier a été modifié depuis que Vim l'a lu !" -#: ../fileio.c:3867 msgid "Do you really want to write to it" msgstr "Voulez-vous vraiment écrire dedans" -#: ../fileio.c:4648 #, c-format msgid "E208: Error writing to \"%s\"" msgstr "E208: Erreur lors de l'écriture dans \"%s\"" -#: ../fileio.c:4655 #, c-format msgid "E209: Error closing \"%s\"" msgstr "E209: Erreur lors de la fermeture de \"%s\"" -#: ../fileio.c:4657 #, c-format msgid "E210: Error reading \"%s\"" msgstr "E210: Erreur lors de la lecture de \"%s\"" -#: ../fileio.c:4883 msgid "E246: FileChangedShell autocommand deleted buffer" msgstr "E246: L'autocommande FileChangedShell a effacé le tampon" -#: ../fileio.c:4894 #, c-format msgid "E211: File \"%s\" no longer available" msgstr "E211: Le fichier \"%s\" n'est plus disponible" # DB - todo : Suggestion. Bof bof, à améliorer. -#: ../fileio.c:4906 #, c-format msgid "" "W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as " @@ -2574,40 +2113,32 @@ msgid "" msgstr "" "W12: Alerte : Le fichier \"%s\" a été modifié, ainsi que le tampon dans Vim" -#: ../fileio.c:4907 msgid "See \":help W12\" for more info." msgstr "Consultez \":help W12\" pour plus d'information." -#: ../fileio.c:4910 #, c-format msgid "W11: Warning: File \"%s\" has changed since editing started" msgstr "W11: Alerte : Le fichier \"%s\" a changé depuis le début de l'édition" -#: ../fileio.c:4911 msgid "See \":help W11\" for more info." msgstr "Consultez \":help W11\" pour plus d'information." -#: ../fileio.c:4914 #, c-format msgid "W16: Warning: Mode of file \"%s\" has changed since editing started" msgstr "" "W16: Alerte : Les permissions de \"%s\" ont changé depuis le début de " "l'édition" -#: ../fileio.c:4915 msgid "See \":help W16\" for more info." msgstr "Consultez \":help W16\" pour plus d'information." -#: ../fileio.c:4927 #, c-format msgid "W13: Warning: File \"%s\" has been created after editing started" msgstr "W13: Alerte : Le fichier \"%s\" a été créé après le début de l'édition" -#: ../fileio.c:4947 msgid "Warning" msgstr "Alerte" -#: ../fileio.c:4948 msgid "" "&OK\n" "&Load File" @@ -2615,48 +2146,45 @@ msgstr "" "&Ok\n" "&Charger le fichier" -#: ../fileio.c:5065 #, c-format msgid "E462: Could not prepare for reloading \"%s\"" msgstr "E462: Impossible de préparer le rechargement de \"%s\"" -#: ../fileio.c:5078 #, c-format msgid "E321: Could not reload \"%s\"" msgstr "E321: Impossible de recharger \"%s\"" -#: ../fileio.c:5601 msgid "--Deleted--" msgstr "--Effacé--" -#: ../fileio.c:5732 #, c-format msgid "auto-removing autocommand: %s <buffer=%d>" msgstr "Autocommandes marquées pour auto-suppression : %s <tampon=%d>" #. the group doesn't exist -#: ../fileio.c:5772 #, c-format msgid "E367: No such group: \"%s\"" msgstr "E367: Aucun groupe \"%s\"" -#: ../fileio.c:5897 +msgid "E936: Cannot delete the current group" +msgstr "E936: Impossible de supprimer le groupe courant" + +msgid "W19: Deleting augroup that is still in use" +msgstr "W19: Effacement d'augroup toujours en usage" + #, c-format msgid "E215: Illegal character after *: %s" msgstr "E215: Caractère non valide après * : %s" -#: ../fileio.c:5905 #, c-format msgid "E216: No such event: %s" msgstr "E216: Aucun événement %s" -#: ../fileio.c:5907 #, c-format msgid "E216: No such group or event: %s" msgstr "E216: Aucun événement ou groupe %s" #. Highlight title -#: ../fileio.c:6090 msgid "" "\n" "--- Auto-Commands ---" @@ -2664,776 +2192,580 @@ msgstr "" "\n" "--- Auto-commandes ---" -#: ../fileio.c:6293 #, c-format msgid "E680: <buffer=%d>: invalid buffer number " msgstr "E680: <buffer=%d> : numéro de tampon invalide" -#: ../fileio.c:6370 msgid "E217: Can't execute autocommands for ALL events" msgstr "" "E217: Impossible d'exécuter les autocommandes pour TOUS les événements (ALL)" -#: ../fileio.c:6393 msgid "No matching autocommands" msgstr "Aucune autocommande correspondante" -#: ../fileio.c:6831 msgid "E218: autocommand nesting too deep" msgstr "E218: autocommandes trop imbriquées" -#: ../fileio.c:7143 #, c-format msgid "%s Auto commands for \"%s\"" msgstr "Autocommandes %s pour \"%s\"" -#: ../fileio.c:7149 #, c-format msgid "Executing %s" msgstr "Exécution de %s" -#: ../fileio.c:7211 #, c-format msgid "autocommand %s" msgstr "autocommande %s" -#: ../fileio.c:7795 msgid "E219: Missing {." msgstr "E219: { manquant." -#: ../fileio.c:7797 msgid "E220: Missing }." msgstr "E220: } manquant." -#: ../fold.c:93 msgid "E490: No fold found" msgstr "E490: Aucun repli trouvé" -#: ../fold.c:544 msgid "E350: Cannot create fold with current 'foldmethod'" msgstr "E350: Impossible de créer un repli avec la 'foldmethod'e actuelle" -#: ../fold.c:546 msgid "E351: Cannot delete fold with current 'foldmethod'" msgstr "E351: Impossible de supprimer un repli avec la 'foldmethod'e actuelle" -#: ../fold.c:1784 #, c-format -msgid "+--%3ld lines folded " -msgstr "+--%3ld lignes repliées " +msgid "+--%3ld line folded " +msgid_plural "+--%3ld lines folded " +msgstr[0] "+--%3ld ligne repliée " +msgstr[1] "+--%3ld lignes repliées " -#. buffer has already been read -#: ../getchar.c:273 msgid "E222: Add to read buffer" msgstr "E222: Ajout au tampon de lecture" -#: ../getchar.c:2040 msgid "E223: recursive mapping" msgstr "E223: mappage récursif" -#: ../getchar.c:2849 #, c-format msgid "E224: global abbreviation already exists for %s" msgstr "E224: une abréviation globale existe déjà pour %s" -#: ../getchar.c:2852 #, c-format msgid "E225: global mapping already exists for %s" msgstr "E225: un mappage global existe déjà pour %s" -#: ../getchar.c:2952 #, c-format msgid "E226: abbreviation already exists for %s" msgstr "E226: une abréviation existe déjà pour %s" -#: ../getchar.c:2955 #, c-format msgid "E227: mapping already exists for %s" msgstr "E227: un mappage existe déjà pour %s" -#: ../getchar.c:3008 msgid "No abbreviation found" msgstr "Aucune abréviation trouvée" -#: ../getchar.c:3010 msgid "No mapping found" msgstr "Aucun mappage trouvé" -#: ../getchar.c:3974 msgid "E228: makemap: Illegal mode" msgstr "E228: makemap : mode invalide" -# msgstr "--Pas de lignes dans le tampon--" -# DB - todo : ou encore : msgstr "--Aucune ligne dans le tampon--" -#. key value of 'cedit' option -#. type of cmdline window or 0 -#. result of cmdline window or 0 -#: ../globals.h:924 -msgid "--No lines in buffer--" -msgstr "--Le tampon est vide--" - -#. -#. * The error messages that can be shared are included here. -#. * Excluded are errors that are only used once and debugging messages. -#. -#: ../globals.h:996 -msgid "E470: Command aborted" -msgstr "E470: Commande annulée" - -#: ../globals.h:997 -msgid "E471: Argument required" -msgstr "E471: Argument requis" - -#: ../globals.h:998 -msgid "E10: \\ should be followed by /, ? or &" -msgstr "E10: \\ devrait être suivi de /, ? ou &" - -#: ../globals.h:1000 -msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" +msgid "E851: Failed to create a new process for the GUI" msgstr "" -"E11: Invalide dans la fenêtre ligne-de-commande ; <CR> exécute, CTRL-C quitte" +"E851: Échec lors de la création d'un nouveau processus pour l'interface " +"graphique" -#: ../globals.h:1002 -msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" +msgid "E852: The child process failed to start the GUI" msgstr "" -"E12: commande non autorisée depuis un exrc/vimrc dans répertoire courant ou " -"une recherche de marqueur" - -#: ../globals.h:1003 -msgid "E171: Missing :endif" -msgstr "E171: :endif manquant" +"E852: Le processus fils n'a pas réussi à démarrer l'interface graphique" -#: ../globals.h:1004 -msgid "E600: Missing :endtry" -msgstr "E600: :endtry manquant" +msgid "E229: Cannot start the GUI" +msgstr "E229: Impossible de démarrer l'interface graphique" -#: ../globals.h:1005 -msgid "E170: Missing :endwhile" -msgstr "E170: :endwhile manquant" - -#: ../globals.h:1006 -msgid "E170: Missing :endfor" -msgstr "E170: :endfor manquant" - -#: ../globals.h:1007 -msgid "E588: :endwhile without :while" -msgstr "E588: :endwhile sans :while" - -#: ../globals.h:1008 -msgid "E588: :endfor without :for" -msgstr "E588: :endfor sans :for" - -#: ../globals.h:1009 -msgid "E13: File exists (add ! to override)" -msgstr "E13: Le fichier existe déjà (ajoutez ! pour passer outre)" - -#: ../globals.h:1010 -msgid "E472: Command failed" -msgstr "E472: La commande a échoué" - -#: ../globals.h:1011 -msgid "E473: Internal error" -msgstr "E473: Erreur interne" - -#: ../globals.h:1012 -msgid "Interrupted" -msgstr "Interrompu" +#, c-format +msgid "E230: Cannot read from \"%s\"" +msgstr "E230: Impossible de lire \"%s\"" -#: ../globals.h:1013 -msgid "E14: Invalid address" -msgstr "E14: Adresse invalide" +msgid "E665: Cannot start GUI, no valid font found" +msgstr "" +"E665: Impossible de démarrer l'IHM graphique, aucune police valide trouvée" -#: ../globals.h:1014 -msgid "E474: Invalid argument" -msgstr "E474: Argument invalide" +msgid "E231: 'guifontwide' invalid" +msgstr "E231: 'guifontwide' est invalide" -#: ../globals.h:1015 -#, c-format -msgid "E475: Invalid argument: %s" -msgstr "E475: Argument invalide : %s" +msgid "E599: Value of 'imactivatekey' is invalid" +msgstr "E599: Valeur de 'imactivatekey' invalide" -#: ../globals.h:1016 #, c-format -msgid "E15: Invalid expression: %s" -msgstr "E15: Expression invalide : %s" +msgid "E254: Cannot allocate color %s" +msgstr "E254: Impossible d'allouer la couleur %s" -#: ../globals.h:1017 -msgid "E16: Invalid range" -msgstr "E16: Plage invalide" +msgid "No match at cursor, finding next" +msgstr "Aucune correspondance sous le curseur, recherche de la suivante" -#: ../globals.h:1018 -msgid "E476: Invalid command" -msgstr "E476: Commande invalide" +msgid "<cannot open> " +msgstr "<impossible d'ouvrir> " -#: ../globals.h:1019 #, c-format -msgid "E17: \"%s\" is a directory" -msgstr "E17: \"%s\" est un répertoire" +msgid "E616: vim_SelFile: can't get font %s" +msgstr "E616: vim_SelFile : impossible d'obtenir la police %s" -#: ../globals.h:1020 -#, fuzzy -msgid "E900: Invalid job id" -msgstr "E49: Valeur de défilement invalide" +msgid "E614: vim_SelFile: can't return to current directory" +msgstr "E614: vim_SelFile : impossible de revenir dans le répertoire courant" -#: ../globals.h:1021 -msgid "E901: Job table is full" -msgstr "" +msgid "Pathname:" +msgstr "Chemin :" -#: ../globals.h:1024 -#, c-format -msgid "E364: Library call failed for \"%s()\"" -msgstr "E364: L'appel à la bibliothèque a échoué pour \"%s()\"" +msgid "E615: vim_SelFile: can't get current directory" +msgstr "E615: vim_SelFile : impossible d'obtenir le répertoire courant" -#: ../globals.h:1026 -msgid "E19: Mark has invalid line number" -msgstr "E19: La marque a un numéro de ligne invalide" +msgid "OK" +msgstr "Ok" -#: ../globals.h:1027 -msgid "E20: Mark not set" -msgstr "E20: Marque non positionnée" +msgid "Cancel" +msgstr "Annuler" -#: ../globals.h:1029 -msgid "E21: Cannot make changes, 'modifiable' is off" -msgstr "E21: Impossible de modifier, 'modifiable' est désactivé" +msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." +msgstr "Widget scrollbar : Impossible d'obtenir la géométrie du pixmap 'thumb'" -#: ../globals.h:1030 -msgid "E22: Scripts nested too deep" -msgstr "E22: Trop de récursion dans les scripts" +msgid "Vim dialog" +msgstr "Vim" -#: ../globals.h:1031 -msgid "E23: No alternate file" -msgstr "E23: Pas de fichier alternatif" +msgid "E232: Cannot create BalloonEval with both message and callback" +msgstr "E232: Impossible de créer un BalloonEval avec message ET callback" -#: ../globals.h:1032 -msgid "E24: No such abbreviation" -msgstr "E24: Cette abréviation n'existe pas" +msgid "_Cancel" +msgstr "_Annuler" -#: ../globals.h:1033 -msgid "E477: No ! allowed" -msgstr "E477: Le ! n'est pas autorisé" +msgid "_Save" +msgstr "_Enregistrer" -#: ../globals.h:1035 -msgid "E25: Nvim does not have a built-in GUI" -msgstr "E25: L'interface graphique n'a pas été compilée dans cette version" +msgid "_Open" +msgstr "_Ouvrir" -#: ../globals.h:1036 -#, c-format -msgid "E28: No such highlight group name: %s" -msgstr "E28: Aucun nom de groupe de surbrillance %s" +msgid "_OK" +msgstr "_Ok" -#: ../globals.h:1037 -msgid "E29: No inserted text yet" -msgstr "E29: Pas encore de texte inséré" +msgid "" +"&Yes\n" +"&No\n" +"&Cancel" +msgstr "" +"&Oui\n" +"&Non\n" +"&Annuler" -#: ../globals.h:1038 -msgid "E30: No previous command line" -msgstr "E30: Aucune ligne de commande précédente" +msgid "Yes" +msgstr "Oui" -#: ../globals.h:1039 -msgid "E31: No such mapping" -msgstr "E31: Mappage inexistant" +msgid "No" +msgstr "Non" -#: ../globals.h:1040 -msgid "E479: No match" -msgstr "E479: Aucune correspondance" +# todo '_' is for hotkey, i guess? +msgid "Input _Methods" +msgstr "_Méthodes de saisie" -#: ../globals.h:1041 -#, c-format -msgid "E480: No match: %s" -msgstr "E480: Aucune correspondance : %s" +msgid "VIM - Search and Replace..." +msgstr "Remplacer - Vim" -#: ../globals.h:1042 -msgid "E32: No file name" -msgstr "E32: Aucun nom de fichier" +msgid "VIM - Search..." +msgstr "Rechercher - Vim" -#: ../globals.h:1044 -msgid "E33: No previous substitute regular expression" -msgstr "E33: Aucune expression régulière de substitution précédente" +msgid "Find what:" +msgstr "Rechercher :" -#: ../globals.h:1045 -msgid "E34: No previous command" -msgstr "E34: Aucune commande précédente" +msgid "Replace with:" +msgstr "Remplacer par :" -#: ../globals.h:1046 -msgid "E35: No previous regular expression" -msgstr "E35: Aucune expression régulière précédente" +#. whole word only button +msgid "Match whole word only" +msgstr "Mots entiers seulement" -#: ../globals.h:1047 -msgid "E481: No range allowed" -msgstr "E481: Les plages ne sont pas autorisées" +#. match case button +msgid "Match case" +msgstr "Respecter la casse" -#: ../globals.h:1048 -msgid "E36: Not enough room" -msgstr "E36: Pas assez de place" +msgid "Direction" +msgstr "Direction" -#: ../globals.h:1049 -#, c-format -msgid "E482: Can't create file %s" -msgstr "E482: Impossible de créer le fichier %s" +#. 'Up' and 'Down' buttons +msgid "Up" +msgstr "Haut" -#: ../globals.h:1050 -msgid "E483: Can't get temp file name" -msgstr "E483: Impossible d'obtenir un nom de fichier temporaire" +msgid "Down" +msgstr "Bas" -#: ../globals.h:1051 -#, c-format -msgid "E484: Can't open file %s" -msgstr "E484: Impossible d'ouvrir le fichier \"%s\"" +msgid "Find Next" +msgstr "Suivant" -#: ../globals.h:1052 -#, c-format -msgid "E485: Can't read file %s" -msgstr "E485: Impossible de lire le fichier %s" +msgid "Replace" +msgstr "Remplacer" -#: ../globals.h:1054 -msgid "E37: No write since last change (add ! to override)" -msgstr "E37: Modifications non enregistrées (ajoutez ! pour passer outre)" +msgid "Replace All" +msgstr "Remplacer tout" -# AB - Il faut respecter l'esprit plus que la lettre. Dans le cas présent, -# nettement plus. -#: ../globals.h:1055 -#, fuzzy -msgid "E37: No write since last change" -msgstr "[Attention : tout n'est pas enregistré]\n" +msgid "_Close" +msgstr "_Fermer" -#: ../globals.h:1056 -msgid "E38: Null argument" -msgstr "E38: Argument null" +msgid "Vim: Received \"die\" request from session manager\n" +msgstr "Vim : Une requête \"die\" a été reçue par le gestionnaire de session\n" -#: ../globals.h:1057 -msgid "E39: Number expected" -msgstr "E39: Nombre attendu" +msgid "Close tab" +msgstr "Fermer l'onglet" -#: ../globals.h:1058 -#, c-format -msgid "E40: Can't open errorfile %s" -msgstr "E40: Impossible d'ouvrir le fichier d'erreurs %s" +msgid "New tab" +msgstr "Nouvel onglet" -#: ../globals.h:1059 -msgid "E41: Out of memory!" -msgstr "E41: Mémoire épuisée" +# DB - todo : un peu long. Cet entrée de menu permet d'ouvrir un fichier +# dans un nouvel onglet via le sélecteur de fichiers graphique. +msgid "Open Tab..." +msgstr "Ouvrir dans un onglet..." -#: ../globals.h:1060 -msgid "Pattern not found" -msgstr "Motif introuvable" +msgid "Vim: Main window unexpectedly destroyed\n" +msgstr "Vim : Fenêtre principale détruite inopinément\n" -#: ../globals.h:1061 -#, c-format -msgid "E486: Pattern not found: %s" -msgstr "E486: Motif introuvable : %s" +msgid "&Filter" +msgstr "&Filtrer" -#: ../globals.h:1062 -msgid "E487: Argument must be positive" -msgstr "E487: L'argument doit être positif" +msgid "&Cancel" +msgstr "&Annuler" -#: ../globals.h:1064 -msgid "E459: Cannot go back to previous directory" -msgstr "E459: Impossible de retourner au répertoire précédent" +msgid "Directories" +msgstr "Répertoires" -#: ../globals.h:1066 -msgid "E42: No Errors" -msgstr "E42: Aucune erreur" +msgid "Filter" +msgstr "Filtre" -# DB - TODO : trouver une traduction valable et attestée pour "location". -#: ../globals.h:1067 -msgid "E776: No location list" -msgstr "E776: Aucune liste d'emplacements" +msgid "&Help" +msgstr "&Aide" -#: ../globals.h:1068 -msgid "E43: Damaged match string" -msgstr "E43: La chaîne de recherche est endommagée" +msgid "Files" +msgstr "Fichiers" -#: ../globals.h:1069 -msgid "E44: Corrupted regexp program" -msgstr "E44: L'automate de regexp est corrompu" +msgid "&OK" +msgstr "&Ok" -#: ../globals.h:1071 -msgid "E45: 'readonly' option is set (add ! to override)" -msgstr "E45: L'option 'readonly' est activée (ajoutez ! pour passer outre)" +msgid "Selection" +msgstr "Sélection" -#: ../globals.h:1073 -#, c-format -msgid "E46: Cannot change read-only variable \"%s\"" -msgstr "E46: La variable \"%s\" est en lecture seule" +msgid "Find &Next" +msgstr "Suiva&nt" -#: ../globals.h:1075 -#, c-format -msgid "E794: Cannot set variable in the sandbox: \"%s\"" -msgstr "" -"E794: Impossible de modifier une variable depuis le bac à sable : \"%s\"" +msgid "&Replace" +msgstr "&Remplacer" -#: ../globals.h:1076 -msgid "E47: Error while reading errorfile" -msgstr "E47: Erreur lors de la lecture du fichier d'erreurs" +msgid "Replace &All" +msgstr "Rempl&acer tout" -#: ../globals.h:1078 -msgid "E48: Not allowed in sandbox" -msgstr "E48: Opération interdite dans le bac à sable" +msgid "&Undo" +msgstr "Ann&uler" -#: ../globals.h:1080 -msgid "E523: Not allowed here" -msgstr "E523: Interdit à cet endroit" +msgid "Open tab..." +msgstr "Ouvrir dans un onglet..." -#: ../globals.h:1082 -msgid "E359: Screen mode setting not supported" -msgstr "E359: Choix du mode d'écran non supporté" +msgid "Find string (use '\\\\' to find a '\\')" +msgstr "Chercher une chaîne (utilisez '\\\\' pour chercher un '\\')" -#: ../globals.h:1083 -msgid "E49: Invalid scroll size" -msgstr "E49: Valeur de défilement invalide" +msgid "Find & Replace (use '\\\\' to find a '\\')" +msgstr "Chercher et remplacer (utilisez '\\\\' pour trouver un '\\')" -#: ../globals.h:1084 -msgid "E91: 'shell' option is empty" -msgstr "E91: L'option 'shell' est vide" +# DB - Traduction non indispensable puisque le code indique qu'il s'agit d'un +# paramétrage bidon afin de sélectionner un répertoire plutôt qu'un +# fichier. +#. We fake this: Use a filter that doesn't select anything and a default +#. * file name that won't be used. +msgid "Not Used" +msgstr "Non utilisé" -#: ../globals.h:1085 -msgid "E255: Couldn't read in sign data!" -msgstr "E255: Impossible de lire les données du symbole !" +# DB - Traduction non indispensable puisque le code indique qu'il s'agit d'un +# paramétrage bidon afin de sélectionner un répertoire plutôt qu'un +# fichier. +msgid "Directory\t*.nothing\n" +msgstr "Répertoire\t*.rien\n" -#: ../globals.h:1086 -msgid "E72: Close error on swap file" -msgstr "E72: Erreur lors de la fermeture du fichier d'échange" +#, c-format +msgid "E671: Cannot find window title \"%s\"" +msgstr "E671: Titre de fenêtre \"%s\" introuvable" -#: ../globals.h:1087 -msgid "E73: tag stack empty" -msgstr "E73: La pile des marqueurs est vide" +#, c-format +msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." +msgstr "E243: Argument non supporté : \"-%s\" ; Utilisez la version OLE." -#: ../globals.h:1088 -msgid "E74: Command too complex" -msgstr "E74: Commande trop complexe" +msgid "E672: Unable to open window inside MDI application" +msgstr "E672: Impossible d'ouvrir une fenêtre dans une application MDI" -#: ../globals.h:1089 -msgid "E75: Name too long" -msgstr "E75: Nom trop long" +# DB - todo : perfectible. +msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" +msgstr "" +"Vim E458: Erreur d'allocation de couleurs, couleurs possiblement incorrectes" -#: ../globals.h:1090 -msgid "E76: Too many [" -msgstr "E76: Trop de [" +# DB - todo : La VF est-elle compréhensible ? +#, c-format +msgid "E250: Fonts for the following charsets are missing in fontset %s:" +msgstr "" +"E250: Des polices manquent dans %s pour les jeux de caractères suivants :" -#: ../globals.h:1091 -msgid "E77: Too many file names" -msgstr "E77: Trop de noms de fichiers" +#, c-format +msgid "E252: Fontset name: %s" +msgstr "E252: Nom du jeu de polices : %s" -#: ../globals.h:1092 -msgid "E488: Trailing characters" -msgstr "E488: Caractères surnuméraires" +#, c-format +msgid "Font '%s' is not fixed-width" +msgstr "La police '%s' n'a pas une largeur fixe" -#: ../globals.h:1093 -msgid "E78: Unknown mark" -msgstr "E78: Marque inconnue" +#, c-format +msgid "E253: Fontset name: %s" +msgstr "E253: Nom du jeu de polices : %s" -#: ../globals.h:1094 -msgid "E79: Cannot expand wildcards" -msgstr "E79: Impossible de développer les métacaractères" +#, c-format +msgid "Font0: %s" +msgstr "Font0: %s" -#: ../globals.h:1096 -msgid "E591: 'winheight' cannot be smaller than 'winminheight'" -msgstr "E591: 'winheight' ne peut pas être plus petit que 'winminheight'" +#, c-format +msgid "Font1: %s" +msgstr "Font1: %s" -#: ../globals.h:1098 -msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" -msgstr "E592: 'winwidth' ne peut pas être plus petit que 'winminwidth'" +#, c-format +msgid "Font%ld width is not twice that of font0" +msgstr "La largeur de Font%ld n'est pas le double de celle de Font0" -#: ../globals.h:1099 -msgid "E80: Error while writing" -msgstr "E80: Erreur lors de l'écriture" +#, c-format +msgid "Font0 width: %ld" +msgstr "Largeur de Font0 : %ld" -#: ../globals.h:1100 -msgid "Zero count" -msgstr "Le quantificateur est nul" +#, c-format +msgid "Font1 width: %ld" +msgstr "Largeur de Font1 : %ld" -#: ../globals.h:1101 -msgid "E81: Using <SID> not in a script context" -msgstr "E81: <SID> utilisé en dehors d'un script" +# DB - todo : Pas certain de mon coup, ici... +msgid "Invalid font specification" +msgstr "La spécification de la police est invalide" -#: ../globals.h:1102 -#, c-format -msgid "E685: Internal error: %s" -msgstr "E685: Erreur interne : %s" +msgid "&Dismiss" +msgstr "Aban&donner" -#: ../globals.h:1104 -msgid "E363: pattern uses more memory than 'maxmempattern'" -msgstr "E363: le motif utilise plus de mémoire que 'maxmempattern'" +# DB - todo : Pas certain de mon coup, ici... +msgid "no specific match" +msgstr "aucune correspondance particulière" -#: ../globals.h:1105 -msgid "E749: empty buffer" -msgstr "E749: tampon vide" +msgid "Vim - Font Selector" +msgstr "Choisir une police - Vim" -#: ../buffer.c:1587 -#, c-format -msgid "E86: Buffer %<PRId64> does not exist" -msgstr "E86: Le tampon %<PRId64> n'existe pas" +msgid "Name:" +msgstr "Nom :" -#: ../globals.h:1108 -msgid "E682: Invalid search pattern or delimiter" -msgstr "E682: Délimiteur ou motif de recherche invalide" +#. create toggle button +msgid "Show size in Points" +msgstr "Afficher la taille en Points" -#: ../globals.h:1109 -msgid "E139: File is loaded in another buffer" -msgstr "E139: Le fichier est chargé dans un autre tampon" +msgid "Encoding:" +msgstr "Encodage :" -#: ../globals.h:1110 -#, c-format -msgid "E764: Option '%s' is not set" -msgstr "E764: L'option '%s' n'est pas activée" +msgid "Font:" +msgstr "Police :" -#: ../globals.h:1111 -msgid "E850: Invalid register name" -msgstr "E850: Nom de registre invalide" +msgid "Style:" +msgstr "Style :" -#: ../globals.h:1114 -msgid "search hit TOP, continuing at BOTTOM" -msgstr "La recherche a atteint le HAUT, et continue en BAS" +msgid "Size:" +msgstr "Taille :" -#: ../globals.h:1115 -msgid "search hit BOTTOM, continuing at TOP" -msgstr "La recherche a atteint le BAS, et continue en HAUT" +msgid "E256: Hangul automata ERROR" +msgstr "E256: ERREUR dans l'automate Hangul" -#: ../hardcopy.c:240 msgid "E550: Missing colon" msgstr "E550: ':' manquant" # DB - Il s'agit ici d'un problème lors du parsing d'une option dont le contenu # est une liste d'éléments séparés par des virgules. -#: ../hardcopy.c:252 msgid "E551: Illegal component" msgstr "E551: élément invalide" -#: ../hardcopy.c:259 msgid "E552: digit expected" msgstr "E552: chiffre attendu" -#: ../hardcopy.c:473 #, c-format msgid "Page %d" msgstr "Page %d" -#: ../hardcopy.c:597 msgid "No text to be printed" msgstr "Aucun texte à imprimer" -#: ../hardcopy.c:668 #, c-format msgid "Printing page %d (%d%%)" msgstr "Impression de la page %d (%d%%)" -#: ../hardcopy.c:680 #, c-format msgid " Copy %d of %d" msgstr " Copie %d sur %d" -#: ../hardcopy.c:733 #, c-format msgid "Printed: %s" msgstr "Imprimé : %s" -#: ../hardcopy.c:740 msgid "Printing aborted" msgstr "Impression interrompue" -#: ../hardcopy.c:1365 msgid "E455: Error writing to PostScript output file" msgstr "E455: Erreur lors de l'écriture du fichier PostScript" -#: ../hardcopy.c:1747 #, c-format msgid "E624: Can't open file \"%s\"" msgstr "E624: Impossible d'ouvrir le fichier \"%s\"" -#: ../hardcopy.c:1756 ../hardcopy.c:2470 #, c-format msgid "E457: Can't read PostScript resource file \"%s\"" msgstr "E457: Impossible de lire le fichier de ressource PostScript \"%s\"" -#: ../hardcopy.c:1772 #, c-format msgid "E618: file \"%s\" is not a PostScript resource file" msgstr "E618: \"%s\" n'est pas un fichier de ressource PostScript" -#: ../hardcopy.c:1788 ../hardcopy.c:1805 ../hardcopy.c:1844 #, c-format msgid "E619: file \"%s\" is not a supported PostScript resource file" msgstr "E619: \"%s\" n'est pas un fichier de ressource PostScript supporté" -#: ../hardcopy.c:1856 #, c-format msgid "E621: \"%s\" resource file has wrong version" msgstr "E621: La version du fichier de ressource \"%s\" est erronée" -#: ../hardcopy.c:2225 msgid "E673: Incompatible multi-byte encoding and character set." msgstr "E673: Jeu de caractères et encodage multi-octets incompatibles" -#: ../hardcopy.c:2238 msgid "E674: printmbcharset cannot be empty with multi-byte encoding." msgstr "" "E674: 'printmbcharset' ne peut pas être vide avec un encodage multi-octets" -#: ../hardcopy.c:2254 msgid "E675: No default font specified for multi-byte printing." msgstr "E675: Aucune police par défaut pour l'impression multi-octets" -#: ../hardcopy.c:2426 msgid "E324: Can't open PostScript output file" msgstr "E324: Impossible d'ouvrir le fichier PostScript de sortie" -#: ../hardcopy.c:2458 #, c-format msgid "E456: Can't open file \"%s\"" msgstr "E456: Impossible d'ouvrir le fichier \"%s\"" -#: ../hardcopy.c:2583 msgid "E456: Can't find PostScript resource file \"prolog.ps\"" msgstr "E456: Le fichier de ressource PostScript \"prolog.ps\" est introuvable" -#: ../hardcopy.c:2593 msgid "E456: Can't find PostScript resource file \"cidfont.ps\"" msgstr "" "E456: Le fichier de ressource PostScript \"cidfont.ps\" est introuvable" -#: ../hardcopy.c:2622 ../hardcopy.c:2639 ../hardcopy.c:2665 #, c-format msgid "E456: Can't find PostScript resource file \"%s.ps\"" msgstr "E456: Le fichier de ressource PostScript \"%s.ps\" est introuvable" -#: ../hardcopy.c:2654 #, c-format msgid "E620: Unable to convert to print encoding \"%s\"" msgstr "E620: La conversion pour imprimer dans l'encodage \"%s\" a échoué" -#: ../hardcopy.c:2877 msgid "Sending to printer..." msgstr "Envoi à l'imprimante..." -#: ../hardcopy.c:2881 msgid "E365: Failed to print PostScript file" msgstr "E365: L'impression du fichier PostScript a échoué" -#: ../hardcopy.c:2883 msgid "Print job sent." msgstr "Tâche d'impression envoyée." -#: ../if_cscope.c:85 msgid "Add a new database" msgstr "Ajouter une base de données" -#: ../if_cscope.c:87 msgid "Query for a pattern" msgstr "Rechercher un motif" -#: ../if_cscope.c:89 msgid "Show this message" msgstr "Afficher ce message" -#: ../if_cscope.c:91 msgid "Kill a connection" msgstr "Fermer une connexion" -#: ../if_cscope.c:93 msgid "Reinit all connections" msgstr "Réinitialiser toutes les connexions" -#: ../if_cscope.c:95 msgid "Show connections" msgstr "Afficher les connexions" -#: ../if_cscope.c:101 #, c-format msgid "E560: Usage: cs[cope] %s" msgstr "E560: Utilisation : cs[cope] %s" -#: ../if_cscope.c:225 msgid "This cscope command does not support splitting the window.\n" msgstr "Cette commande cscope ne supporte pas le partage de la fenêtre.\n" -#: ../if_cscope.c:266 msgid "E562: Usage: cstag <ident>" msgstr "E562: Utilisation : cstag <ident>" -#: ../if_cscope.c:313 msgid "E257: cstag: tag not found" msgstr "E257: cstag : marqueur introuvable" -#: ../if_cscope.c:461 #, c-format msgid "E563: stat(%s) error: %d" msgstr "E563: Erreur stat(%s) : %d" -#: ../if_cscope.c:551 +msgid "E563: stat error" +msgstr "E563: Erreur stat" + #, c-format msgid "E564: %s is not a directory or a valid cscope database" msgstr "E564: %s n'est pas un répertoire ou une base de données cscope valide" -#: ../if_cscope.c:566 #, c-format msgid "Added cscope database %s" msgstr "Base de données cscope %s ajoutée" -#: ../if_cscope.c:616 #, c-format -msgid "E262: error reading cscope connection %<PRId64>" -msgstr "E262: erreur lors de la lecture de la connexion cscope %<PRId64>" +msgid "E262: error reading cscope connection %ld" +msgstr "E262: erreur lors de la lecture de la connexion cscope %ld" -#: ../if_cscope.c:711 msgid "E561: unknown cscope search type" msgstr "E561: type de recherche cscope inconnu" -#: ../if_cscope.c:752 ../if_cscope.c:789 msgid "E566: Could not create cscope pipes" msgstr "E566: Impossible de créer les tuyaux (pipes) cscope" -#: ../if_cscope.c:767 msgid "E622: Could not fork for cscope" msgstr "E622: Impossible de forker pour cscope" -#: ../if_cscope.c:849 -#, fuzzy msgid "cs_create_connection setpgid failed" -msgstr "exec de cs_create_connection a échoué" +msgstr "cs_create_connection setpgid a échoué" -#: ../if_cscope.c:853 ../if_cscope.c:889 msgid "cs_create_connection exec failed" msgstr "exec de cs_create_connection a échoué" -#: ../if_cscope.c:863 ../if_cscope.c:902 msgid "cs_create_connection: fdopen for to_fp failed" msgstr "cs_create_connection : fdopen pour to_fp a échoué" -#: ../if_cscope.c:865 ../if_cscope.c:906 msgid "cs_create_connection: fdopen for fr_fp failed" msgstr "cs_create_connection : fdopen pour fr_fp a échoué" -#: ../if_cscope.c:890 msgid "E623: Could not spawn cscope process" msgstr "E623: Impossible d'engendrer le processus cscope" -#: ../if_cscope.c:932 msgid "E567: no cscope connections" msgstr "E567: Aucune connexion cscope" -#: ../if_cscope.c:1009 #, c-format msgid "E469: invalid cscopequickfix flag %c for %c" msgstr "E469: Drapeau cscopequickfix %c invalide pour %c" # DB - todo -#: ../if_cscope.c:1058 #, c-format msgid "E259: no matches found for cscope query %s of %s" msgstr "E259: aucune correspondance trouvée pour la requête cscope %s de %s" -#: ../if_cscope.c:1142 msgid "cscope commands:\n" msgstr "commandes cscope :\n" -#: ../if_cscope.c:1150 #, c-format msgid "%-5s: %s%*s (Usage: %s)" msgstr "%-5s: %s%*s (Utilisation : %s)" -#: ../if_cscope.c:1155 msgid "" "\n" +" a: Find assignments to this symbol\n" " c: Find functions calling this function\n" " d: Find functions called by this function\n" " e: Find this egrep pattern\n" @@ -3444,6 +2776,7 @@ msgid "" " t: Find this text string\n" msgstr "" "\n" +" a: Trouver les affectations à ce symbole\n" " c: Trouver les fonctions appelant cette fonction\n" " d: Trouver les fonctions appelées par cette fonction\n" " e: Trouver ce motif egrep\n" @@ -3453,31 +2786,33 @@ msgstr "" " s: Trouver ce symbole C\n" " t: Trouver cette chaîne\n" -#: ../if_cscope.c:1226 +#, c-format +msgid "E625: cannot open cscope database: %s" +msgstr "E625: impossible d'ouvrir la base de données cscope %s" + +msgid "E626: cannot get cscope database information" +msgstr "" +"E626: impossible d'obtenir des informations sur la base de données cscope" + msgid "E568: duplicate cscope database not added" msgstr "E568: base de données cscope redondante non ajoutée" -#: ../if_cscope.c:1335 #, c-format msgid "E261: cscope connection %s not found" msgstr "E261: Connexion cscope %s introuvable" -#: ../if_cscope.c:1364 #, c-format msgid "cscope connection %s closed" msgstr "connexion cscope %s fermée" #. should not reach here -#: ../if_cscope.c:1486 msgid "E570: fatal error in cs_manage_matches" msgstr "E570: erreur fatale dans cs_manage_matches" -#: ../if_cscope.c:1693 #, c-format msgid "Cscope tag: %s" msgstr "Marqueur cscope : %s" -#: ../if_cscope.c:1711 msgid "" "\n" " # line" @@ -3486,87 +2821,307 @@ msgstr "" " # ligne" # DB - todo : Faut-il respecter l'alignement ici ? -#: ../if_cscope.c:1713 msgid "filename / context / line\n" msgstr "nom / contexte/ ligne\n" -#: ../if_cscope.c:1809 #, c-format msgid "E609: Cscope error: %s" msgstr "E609: Erreur cscope : %s" -#: ../if_cscope.c:2053 msgid "All cscope databases reset" msgstr "Toutes les bases de données cscope ont été réinitialisées" -#: ../if_cscope.c:2123 msgid "no cscope connections\n" msgstr "aucune connexion cscope\n" -#: ../if_cscope.c:2126 msgid " # pid database name prepend path\n" msgstr " # pid nom de la base de données chemin\n" -#: ../main.c:144 +msgid "Lua library cannot be loaded." +msgstr "La bibliothèque Lua n'a pas pu être chargée." + +msgid "cannot save undo information" +msgstr "impossible d'enregistrer les informations d'annulation" + +msgid "" +"E815: Sorry, this command is disabled, the MzScheme libraries could not be " +"loaded." +msgstr "" +"E815: Désolé, cette commande est désactivée : les bibliothèques MzScheme " +"n'ont pas pu être chargées." + +msgid "" +"E895: Sorry, this command is disabled, the MzScheme's racket/base module " +"could not be loaded." +msgstr "" +"E895: Désolé, cette commande est désactivée : le module MzScheme racket/base " +"ne peut pas être chargé." + +msgid "invalid expression" +msgstr "expression invalide" + +msgid "expressions disabled at compile time" +msgstr "expressions désactivées lors de la compilation" + +msgid "hidden option" +msgstr "option cachée" + +msgid "unknown option" +msgstr "option inconnue" + +msgid "window index is out of range" +msgstr "numéro de fenêtre hors limites" + +msgid "couldn't open buffer" +msgstr "impossible d'ouvrir le tampon" + +msgid "cannot delete line" +msgstr "impossible d'effacer la ligne" + +msgid "cannot replace line" +msgstr "impossible de remplacer la ligne" + +msgid "cannot insert line" +msgstr "impossible d'insérer la ligne" + +msgid "string cannot contain newlines" +msgstr "une chaîne ne peut pas contenir de saut-de-ligne" + +msgid "error converting Scheme values to Vim" +msgstr "erreur lors de la conversion d'une valeur de Scheme à Vim" + +msgid "Vim error: ~a" +msgstr "Erreur Vim : ~a" + +msgid "Vim error" +msgstr "Erreur Vim" + +msgid "buffer is invalid" +msgstr "tampon invalide" + +msgid "window is invalid" +msgstr "fenêtre invalide" + +msgid "linenr out of range" +msgstr "numéro de ligne hors limites" + +msgid "not allowed in the Vim sandbox" +msgstr "non autorisé dans le bac à sable" + +msgid "E836: This Vim cannot execute :python after using :py3" +msgstr "E836: Vim ne peut pas exécuter :python après avoir utilisé :py3" + +msgid "" +"E263: Sorry, this command is disabled, the Python library could not be " +"loaded." +msgstr "" +"E263: Désolé, commande désactivée : la bibliothèque Python n'a pas pu être " +"chargée." + +msgid "" +"E887: Sorry, this command is disabled, the Python's site module could not be " +"loaded." +msgstr "" +"E887: Désolé, commande désactivée : la bibliothèque Python n'a pas pu être " +"chargée." + +msgid "E659: Cannot invoke Python recursively" +msgstr "E659: Impossible d'invoquer Python récursivement" + +msgid "E837: This Vim cannot execute :py3 after using :python" +msgstr "E837: Vim ne peut pas exécuter :py3 après avoir utilisé :python" + +msgid "E265: $_ must be an instance of String" +msgstr "E265: $_ doit être une instance de chaîne (String)" + +msgid "" +"E266: Sorry, this command is disabled, the Ruby library could not be loaded." +msgstr "" +"E266: Désolé, commande désactivée : la bibliothèque Ruby n'a pas pu être " +"chargée." + +msgid "E267: unexpected return" +msgstr "E267: « return » inattendu" + +msgid "E268: unexpected next" +msgstr "E268: « next » inattendu" + +msgid "E269: unexpected break" +msgstr "E269: « break » inattendu" + +msgid "E270: unexpected redo" +msgstr "E270: « redo » inattendu" + +msgid "E271: retry outside of rescue clause" +msgstr "E271: « retry » hors d'une clause « rescue »" + +msgid "E272: unhandled exception" +msgstr "E272: Exception non prise en charge" + +# DB - todo +#, c-format +msgid "E273: unknown longjmp status %d" +msgstr "E273: contexte de longjmp inconnu : %d" + +msgid "invalid buffer number" +msgstr "numéro de tampon invalide" + +msgid "not implemented yet" +msgstr "pas encore implémenté" + +# DB - TODO : le contexte est celui d'une annulation. +#. ??? +msgid "cannot set line(s)" +msgstr "Impossible de remettre la/les ligne(s)" + +msgid "invalid mark name" +msgstr "nom de marque invalide" + +msgid "mark not set" +msgstr "marque non positionnée" + +#, c-format +msgid "row %d column %d" +msgstr "ligne %d colonne %d" + +msgid "cannot insert/append line" +msgstr "Impossible d'insérer/ajouter de lignes" + +msgid "line number out of range" +msgstr "numéro de ligne hors limites" + +msgid "unknown flag: " +msgstr "drapeau inconnu : " + +msgid "unknown vimOption" +msgstr "vimOption inconnue" + +msgid "keyboard interrupt" +msgstr "interruption clavier" + +msgid "vim error" +msgstr "erreur Vim" + +msgid "cannot create buffer/window command: object is being deleted" +msgstr "" +"Impossible de créer commande de tampon/fenêtre : objet en cours d'effacement" + +msgid "" +"cannot register callback command: buffer/window is already being deleted" +msgstr "" +"Impossible d'inscrire la commande de rappel : tampon/fenêtre en effacement" + +#. This should never happen. Famous last word? +msgid "" +"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim." +"org" +msgstr "" +"E280: ERREUR FATALE TCL: reflist corrompue ?! Contactez vim-dev@vim.org, SVP." + +msgid "cannot register callback command: buffer/window reference not found" +msgstr "" +"Impossible d'inscrire la commande de rappel : réf. tampon/fenêtre introuvable" + +msgid "" +"E571: Sorry, this command is disabled: the Tcl library could not be loaded." +msgstr "" +"E571: Désolé, commande désactivée: la bibliothèque Tcl n'a pas pu être " +"chargée." + +#, c-format +msgid "E572: exit code %d" +msgstr "E572: code de sortie %d" + +msgid "cannot get line" +msgstr "Impossible d'obtenir la ligne" + +msgid "Unable to register a command server name" +msgstr "Impossible d'inscrire un nom de serveur de commande" + +msgid "E248: Failed to send command to the destination program" +msgstr "E248: Échec de l'envoi de la commande au programme cible" + +#, c-format +msgid "E573: Invalid server id used: %s" +msgstr "E573: Id utilisé pour le serveur invalide : %s" + +msgid "E251: VIM instance registry property is badly formed. Deleted!" +msgstr "E251: Entrée registre de l'instance de Vim mal formatée. Suppression !" + +#, c-format +msgid "E938: Duplicate key in JSON: \"%s\"" +msgstr "E938: Clé dupliquée dans le document JSON : \"%s\"" + +#, c-format +msgid "E696: Missing comma in List: %s" +msgstr "E696: Il manque une virgule dans la Liste %s" + +#, c-format +msgid "E697: Missing end of List ']': %s" +msgstr "E697: Il manque ']' à la fin de la Liste %s" + msgid "Unknown option argument" msgstr "Option inconnue" -#: ../main.c:146 msgid "Too many edit arguments" msgstr "Trop d'arguments d'édition" -#: ../main.c:148 msgid "Argument missing after" msgstr "Argument manquant après" -#: ../main.c:150 msgid "Garbage after option argument" msgstr "arguments en trop après l'option" -#: ../main.c:152 msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments" msgstr "Trop d'arguments \"+command\", \"-c command\" ou \"--cmd command\"" -#: ../main.c:154 msgid "Invalid argument for" msgstr "Argument invalide pour" -#: ../main.c:294 #, c-format msgid "%d files to edit\n" msgstr "%d fichiers à éditer\n" -#: ../main.c:1342 +msgid "netbeans is not supported with this GUI\n" +msgstr "netbeans n'est pas supporté avec cette interface graphique\n" + +msgid "'-nb' cannot be used: not enabled at compile time\n" +msgstr "'-nb' ne peut pas être utilisé : désactivé à la compilation\n" + +msgid "This Vim was not compiled with the diff feature." +msgstr "Ce Vim n'a pas été compilé avec la fonctionnalité diff" + msgid "Attempt to open script file again: \"" msgstr "Nouvelle tentative pour ouvrir le script : \"" -#: ../main.c:1350 msgid "Cannot open for reading: \"" msgstr "Impossible d'ouvrir en lecture : \"" -#: ../main.c:1393 msgid "Cannot open for script output: \"" msgstr "Impossible d'ouvrir pour la sortie script : \"" -#: ../main.c:1622 +msgid "Vim: Error: Failure to start gvim from NetBeans\n" +msgstr "Vim : Erreur : Impossible de démarrer gvim depuis NetBeans\n" + +msgid "Vim: Error: This version of Vim does not run in a Cygwin terminal\n" +msgstr "" +"Vim : Erreur : Cette version de Vim ne fonctionne pas dans un terminal " +"Cygwin\n" + msgid "Vim: Warning: Output is not to a terminal\n" msgstr "Vim : Alerte : La sortie ne s'effectue pas sur un terminal\n" -#: ../main.c:1624 msgid "Vim: Warning: Input is not from a terminal\n" msgstr "Vim : Alerte : L'entrée ne se fait pas sur un terminal\n" #. just in case.. -#: ../main.c:1891 msgid "pre-vimrc command line" msgstr "ligne de commande pre-vimrc" -#: ../main.c:1964 #, c-format msgid "E282: Cannot read from \"%s\"" msgstr "E282: Impossible de lire \"%s\"" -#: ../main.c:2149 msgid "" "\n" "More info with: \"vim -h\"\n" @@ -3574,23 +3129,18 @@ msgstr "" "\n" "Plus d'info avec : \"vim -h\"\n" -#: ../main.c:2178 msgid "[file ..] edit specified file(s)" msgstr "[fichier ...] ouvrir le ou les fichiers spécifiés" -#: ../main.c:2179 msgid "- read text from stdin" msgstr "- lire le texte à partir de stdin" -#: ../main.c:2180 msgid "-t tag edit file where tag is defined" msgstr "-t marqueur ouvrir le fichier qui contient le marqueur" -#: ../main.c:2181 msgid "-q [errorfile] edit file with first error" msgstr "-q [fichErr] ouvrir à l'endroit de la première erreur" -#: ../main.c:2187 msgid "" "\n" "\n" @@ -3600,11 +3150,9 @@ msgstr "" "\n" "utilisation :" -#: ../main.c:2189 msgid " vim [arguments] " msgstr " vim [args] " -#: ../main.c:2193 msgid "" "\n" " or:" @@ -3612,7 +3160,15 @@ msgstr "" "\n" " ou :" -#: ../main.c:2196 +# DB - todo (VMS uniquement). +msgid "" +"\n" +"Where case is ignored prepend / to make flag upper case" +msgstr "" +"\n" +"pour lesquels la casse est indifférente (/ pour que le drapeau soit " +"majuscule)" + msgid "" "\n" "\n" @@ -3622,192 +3178,338 @@ msgstr "" "\n" "Arguments :\n" -#: ../main.c:2197 msgid "--\t\t\tOnly file names after this" msgstr "--\t\tSeuls des noms de fichier sont spécifiés après ceci" -#: ../main.c:2199 msgid "--literal\t\tDon't expand wildcards" msgstr "--literal\tNe pas développer les métacaractères" -#: ../main.c:2201 +msgid "-register\t\tRegister this gvim for OLE" +msgstr "-register\tInscrire ce gvim pour OLE" + +msgid "-unregister\t\tUnregister gvim for OLE" +msgstr "-unregister\tDésinscrire gvim de OLE" + +msgid "-g\t\t\tRun using GUI (like \"gvim\")" +msgstr "-g\t\tLancer l'interface graphique (comme \"gvim\")" + +msgid "-f or --nofork\tForeground: Don't fork when starting GUI" +msgstr "" +"-f, --nofork\tPremier-plan : ne pas détacher l'interface graphique du " +"terminal" + msgid "-v\t\t\tVi mode (like \"vi\")" msgstr "-v\t\tMode Vi (comme \"vi\")" -#: ../main.c:2202 msgid "-e\t\t\tEx mode (like \"ex\")" msgstr "-e\t\tMode Ex (comme \"ex\")" -#: ../main.c:2203 msgid "-E\t\t\tImproved Ex mode" msgstr "-E\t\t\tMode Ex amélioré" -#: ../main.c:2204 msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")" msgstr "-s\t\tMode silencieux (batch) (seulement pour \"ex\")" -#: ../main.c:2205 msgid "-d\t\t\tDiff mode (like \"vimdiff\")" msgstr "-d\t\tMode diff (comme \"vimdiff\")" -#: ../main.c:2206 msgid "-y\t\t\tEasy mode (like \"evim\", modeless)" msgstr "-y\t\tMode facile (comme \"evim\", vim sans modes)" -#: ../main.c:2207 msgid "-R\t\t\tReadonly mode (like \"view\")" msgstr "-R\t\tMode lecture seule (comme \"view\")" -#: ../main.c:2208 msgid "-Z\t\t\tRestricted mode (like \"rvim\")" msgstr "-Z\t\tMode restreint (comme \"rvim\")" -#: ../main.c:2209 msgid "-m\t\t\tModifications (writing files) not allowed" msgstr "-m\t\tInterdire l'enregistrement des fichiers" -#: ../main.c:2210 msgid "-M\t\t\tModifications in text not allowed" msgstr "-M\t\tInterdire toute modification de texte" -#: ../main.c:2211 msgid "-b\t\t\tBinary mode" msgstr "-b\t\tMode binaire" -#: ../main.c:2212 msgid "-l\t\t\tLisp mode" msgstr "-l\t\tMode lisp" -#: ../main.c:2213 msgid "-C\t\t\tCompatible with Vi: 'compatible'" msgstr "-C\t\tCompatible avec Vi : 'compatible'" -#: ../main.c:2214 msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'" msgstr "-N\t\tPas totalement compatible avec Vi : 'nocompatible'" -#: ../main.c:2215 msgid "-V[N][fname]\t\tBe verbose [level N] [log messages to fname]" msgstr "-V[N][<fichier>]\tMode verbeux [niveau N] [dans <fichier>]" -#: ../main.c:2216 msgid "-D\t\t\tDebugging mode" msgstr "-D\t\tMode débogage" -#: ../main.c:2217 msgid "-n\t\t\tNo swap file, use memory only" msgstr "-n\t\tNe pas utiliser de fichier d'échange, seulement la mémoire" -#: ../main.c:2218 msgid "-r\t\t\tList swap files and exit" msgstr "-r\t\tLister les fichiers d'échange et quitter" -#: ../main.c:2219 msgid "-r (with file name)\tRecover crashed session" msgstr "-r <fichier>\tRécupérer une session plantée" -#: ../main.c:2220 msgid "-L\t\t\tSame as -r" msgstr "-L\t\tComme -r" -#: ../main.c:2221 +msgid "-f\t\t\tDon't use newcli to open window" +msgstr "-f\t\tNe pas utiliser newcli pour l'ouverture des fenêtres" + +msgid "-dev <device>\t\tUse <device> for I/O" +msgstr "-dev <périph>\tUtiliser <périphérique> pour les E/S" + msgid "-A\t\t\tstart in Arabic mode" msgstr "-A\t\tDémarrer en mode arabe" -#: ../main.c:2222 msgid "-H\t\t\tStart in Hebrew mode" msgstr "-H\t\tDémarrer en mode hébreu" -#: ../main.c:2223 msgid "-F\t\t\tStart in Farsi mode" msgstr "-F\t\tDémarrer en mode farsi" -#: ../main.c:2224 msgid "-T <terminal>\tSet terminal type to <terminal>" msgstr "-T <term>\tRégler le type du terminal sur <terminal>" -#: ../main.c:2225 +msgid "--not-a-term\t\tSkip warning for input/output not being a terminal" +msgstr "" +"--no-a-term\t\tAucun avertissement si l'entrée/sortie n'est pas un terminal" + +msgid "--ttyfail\t\tExit if input or output is not a terminal" +msgstr "" +"--ttyfail\t\tQuitte si l'entrée ou la sortie ne sont pas un terminal" + msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc" msgstr "-u <vimrc>\tUtiliser <vimrc> au lieu du vimrc habituel" -#: ../main.c:2226 +msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" +msgstr "-U <gvimrc>\tUtiliser <gvimrc> au lieu du gvimrc habituel" + msgid "--noplugin\t\tDon't load plugin scripts" msgstr "--noplugin\tNe charger aucun greffon" -#: ../main.c:2227 msgid "-p[N]\t\tOpen N tab pages (default: one for each file)" msgstr "-p[N]\tOuvrir N onglets (défaut : un pour chaque fichier)" -#: ../main.c:2228 msgid "-o[N]\t\tOpen N windows (default: one for each file)" msgstr "-o[N]\tOuvrir N fenêtres (défaut : une pour chaque fichier)" -#: ../main.c:2229 msgid "-O[N]\t\tLike -o but split vertically" msgstr "-O[N]\tComme -o, mais partager verticalement" -#: ../main.c:2230 msgid "+\t\t\tStart at end of file" msgstr "+\t\tOuvrir à la fin du fichier" -#: ../main.c:2231 msgid "+<lnum>\t\tStart at line <lnum>" msgstr "+<numL>\tOuvrir le fichier à la ligne <numL>" -#: ../main.c:2232 msgid "--cmd <command>\tExecute <command> before loading any vimrc file" msgstr "--cmd <cmde>\tExécuter <commande> avant de charger les fichiers vimrc" -#: ../main.c:2233 msgid "-c <command>\t\tExecute <command> after loading the first file" msgstr "-c <cmde>\tExécuter <commande> une fois le 1er fichier chargé" -#: ../main.c:2235 msgid "-S <session>\t\tSource file <session> after loading the first file" msgstr "" "-S <session>\tSourcer le fichier <session> une fois le 1er fichier chargé" -#: ../main.c:2236 msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>" msgstr "-s <src>\tLire les commandes du mode Normal à partir du fichier <src>" -#: ../main.c:2237 msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>" msgstr "-w <dest>\tAjouter toutes les commandes tapées dans le fichier <dest>" -#: ../main.c:2238 msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>" msgstr "-W <dest>\tÉcrire toutes les commandes tapées dans le fichier <dest>" -#: ../main.c:2240 +msgid "-x\t\t\tEdit encrypted files" +msgstr "-x\t\t\tÉditer des fichiers chiffrés" + +msgid "-display <display>\tConnect vim to this particular X-server" +msgstr "-display <display>\tConnecter Vim au serveur X spécifié" + +msgid "-X\t\t\tDo not connect to X server" +msgstr "-X\t\t\tNe pas se connecter à un serveur X" + +msgid "--remote <files>\tEdit <files> in a Vim server if possible" +msgstr "--remote <fich>\tÉditer les <fichiers> dans un serveur Vim si possible" + +msgid "--remote-silent <files> Same, don't complain if there is no server" +msgstr "" +"--remote-silent ...\tPareil, mais pas d'erreur s'il n'y a aucun serveur" + +msgid "" +"--remote-wait <files> As --remote but wait for files to have been edited" +msgstr "" +"--remote-wait <fich>\tComme --remote mais ne quitter qu'à la fin de l'édition" + +msgid "" +"--remote-wait-silent <files> Same, don't complain if there is no server" +msgstr "" +"--remote-wait-silent\tPareil, mais pas d'erreur s'il n'y a aucun serveur" + +msgid "" +"--remote-tab[-wait][-silent] <files> As --remote but use tab page per file" +msgstr "" +"--remote-tab[-wait][-silent] <fich>\tComme --remote mais ouvrir un onglet " +"pour chaque fichier" + +msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" +msgstr "--remote-send <tche>\tEnvoyer <touches> à un serveur Vim puis quitter" + +msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" +msgstr "" +"--remote-expr <expr>\tÉvaluer <expr> dans un serveur Vim, afficher le " +"résultat" + +msgid "--serverlist\t\tList available Vim server names and exit" +msgstr "" +"--serverlist\t\tLister les noms des serveurs Vim disponibles et quitter" + +msgid "--servername <name>\tSend to/become the Vim server <name>" +msgstr "--servername <nom>\tEnvoyer au/devenir le serveur Vim nommé <nom>" + msgid "--startuptime <file>\tWrite startup timing messages to <file>" msgstr "" "--startuptime <fich>\tÉcrire les messages d'horodatage au démarrage dans " "<fich>" -#: ../main.c:2242 msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo" msgstr "-i <viminfo>\t\tUtiliser <viminfo> au lieu du viminfo habituel" -#: ../main.c:2243 msgid "-h or --help\tPrint Help (this message) and exit" msgstr "-h ou --help\t\tAfficher l'aide (ce message) puis quitter" -#: ../main.c:2244 msgid "--version\t\tPrint version information and exit" msgstr "--version\t\tAfficher les informations de version et quitter" -#: ../mark.c:676 +msgid "" +"\n" +"Arguments recognised by gvim (Motif version):\n" +msgstr "" +"\n" +"Arguments reconnus par gvim (version Motif) :\n" + +msgid "" +"\n" +"Arguments recognised by gvim (neXtaw version):\n" +msgstr "" +"\n" +"Arguments reconnus par gvim (version neXtaw) :\n" + +msgid "" +"\n" +"Arguments recognised by gvim (Athena version):\n" +msgstr "" +"\n" +"Arguments reconnus par gvim (version Athena) :\n" + +msgid "-display <display>\tRun vim on <display>" +msgstr "-display <écran>\tLancer Vim sur ce <display>" + +msgid "-iconic\t\tStart vim iconified" +msgstr "-iconic\t\tIconifier Vim au démarrage" + +msgid "-background <color>\tUse <color> for the background (also: -bg)" +msgstr "" +"-background <coul>\tUtiliser <couleur> pour l'arrière-plan\t (abrv : -bg)" + +msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" +msgstr "" +"-foreground <coul>\tUtiliser <couleur> pour le texte normal\t (abrv : -fg)" + +msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" +msgstr "-font <fonte>\tUtiliser <fonte> pour le texte normal\t (abrv : -fn)" + +msgid "-boldfont <font>\tUse <font> for bold text" +msgstr "-boldfont <fonte>\tUtiliser <fonte> pour le texte gras" + +msgid "-italicfont <font>\tUse <font> for italic text" +msgstr "-italicfont <fonte>\tUtiliser <fonte> pour le texte italique" + +msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" +msgstr "-geometry <géom>\tUtiliser cette <géométrie> initiale\t (abrv : -geom)" + +msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" +msgstr "" +"-borderwidth <épais>\tUtiliser cette <épaisseur> de bordure\t (abrv : -bw)" + +msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" +msgstr "" +"-scrollbarwidth <lg>\tUtiliser cette <largeur> de barre de défil. (abrv: -sw)" + +msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" +msgstr "-menuheight <haut>\tUtiliser cette <hauteur> de menu\t (abrv : -mh)" + +msgid "-reverse\t\tUse reverse video (also: -rv)" +msgstr "-reverse\t\tUtiliser la vidéo inverse\t\t (abrv : -rv)" + +msgid "+reverse\t\tDon't use reverse video (also: +rv)" +msgstr "+reverse\t\tNe pas utiliser de vidéo inverse\t (abrv : +rv)" + +msgid "-xrm <resource>\tSet the specified resource" +msgstr "-xrm <ressource>\tConfigurer la <ressource> spécifiée" + +msgid "" +"\n" +"Arguments recognised by gvim (GTK+ version):\n" +msgstr "" +"\n" +"Arguments reconnus par gvim (version GTK+) :\n" + +msgid "-display <display>\tRun vim on <display> (also: --display)" +msgstr "" +"-display <display>\tLancer Vim sur ce <display>\t(également : --display)" + +msgid "--role <role>\tSet a unique role to identify the main window" +msgstr "--role <rôle>\tDonner un rôle pour identifier la fenêtre principale" + +msgid "--socketid <xid>\tOpen Vim inside another GTK widget" +msgstr "--socketid <xid>\tOuvrir Vim dans un autre widget GTK" + +msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" +msgstr "--echo-wid\t\tGvim affiche l'ID de la fenêtre sur stdout" + +msgid "-P <parent title>\tOpen Vim inside parent application" +msgstr "-P <titre parent>\tOuvrir Vim dans une application parente" + +msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" +msgstr "--windowid <HWND>\tOuvrir Vim dans un autre widget win32" + +msgid "No display" +msgstr "Aucun display" + +#. Failed to send, abort. +msgid ": Send failed.\n" +msgstr " : L'envoi a échoué.\n" + +#. Let vim start normally. +msgid ": Send failed. Trying to execute locally\n" +msgstr " : L'envoi a échoué. Tentative d'exécution locale\n" + +#, c-format +msgid "%d of %d edited" +msgstr "%d édités sur %d" + +msgid "No display: Send expression failed.\n" +msgstr "Aucun display : L'envoi de l'expression a échoué.\n" + +msgid ": Send expression failed.\n" +msgstr " : L'envoi de l'expression a échoué.\n" + msgid "No marks set" msgstr "Aucune marque positionnée" -#: ../mark.c:678 #, c-format msgid "E283: No marks matching \"%s\"" msgstr "E283: Aucune marque ne correspond à \"%s\"" #. Highlight title -#: ../mark.c:687 msgid "" "\n" "mark line col file/text" @@ -3816,7 +3518,6 @@ msgstr "" "marq ligne col fichier/texte" #. Highlight title -#: ../mark.c:789 msgid "" "\n" " jump line col file/text" @@ -3825,7 +3526,6 @@ msgstr "" " saut ligne col fichier/texte" #. Highlight title -#: ../mark.c:831 msgid "" "\n" "change line col text" @@ -3833,7 +3533,6 @@ msgstr "" "\n" "modif ligne col fichier/texte" -#: ../mark.c:1238 msgid "" "\n" "# File marks:\n" @@ -3842,7 +3541,6 @@ msgstr "" "# Marques dans le fichier :\n" #. Write the jumplist with -' -#: ../mark.c:1271 msgid "" "\n" "# Jumplist (newest first):\n" @@ -3850,7 +3548,6 @@ msgstr "" "\n" "# Liste de sauts (le plus récent en premier) :\n" -#: ../mark.c:1352 msgid "" "\n" "# History of marks within files (newest to oldest):\n" @@ -3858,84 +3555,91 @@ msgstr "" "\n" "# Historique des marques dans les fichiers (les plus récentes en premier) :\n" -#: ../mark.c:1431 msgid "Missing '>'" msgstr "'>' manquant" -#: ../memfile.c:426 +msgid "E543: Not a valid codepage" +msgstr "E543: Page de codes non valide" + +msgid "E284: Cannot set IC values" +msgstr "E284: Impossible de régler les valeurs IC" + +msgid "E285: Failed to create input context" +msgstr "E285: Échec de la création du contexte de saisie" + +msgid "E286: Failed to open input method" +msgstr "E286: Échec de l'ouverture de la méthode de saisie" + +msgid "E287: Warning: Could not set destroy callback to IM" +msgstr "" +"E287: Alerte : Impossible d'inscrire le callback de destruction dans la MS" + +msgid "E288: input method doesn't support any style" +msgstr "E288: la méthode de saisie ne supporte aucun style" + +msgid "E289: input method doesn't support my preedit type" +msgstr "" +"E289: le type de préédition de Vim n'est pas supporté par la méthode de " +"saisie" + msgid "E293: block was not locked" msgstr "E293: le bloc n'était pas verrouillé" -#: ../memfile.c:799 msgid "E294: Seek error in swap file read" msgstr "E294: Erreur de positionnement lors de la lecture du fichier d'échange" -#: ../memfile.c:803 msgid "E295: Read error in swap file" msgstr "E295: Erreur de lecture dans le fichier d'échange" -#: ../memfile.c:849 msgid "E296: Seek error in swap file write" msgstr "E296: Erreur de positionnement lors de l'écriture du fichier d'échange" -#: ../memfile.c:865 msgid "E297: Write error in swap file" msgstr "E297: Erreur d'écriture dans le fichier d'échange" -#: ../memfile.c:1036 msgid "E300: Swap file already exists (symlink attack?)" msgstr "E300: Le fichier d'échange existe déjà (attaque par symlink ?)" -#: ../memline.c:318 msgid "E298: Didn't get block nr 0?" msgstr "E298: Bloc n°0 non récupéré ?" -#: ../memline.c:361 msgid "E298: Didn't get block nr 1?" msgstr "E298: Bloc n°1 non récupéré ?" -#: ../memline.c:377 msgid "E298: Didn't get block nr 2?" msgstr "E298: Bloc n°2 non récupéré ?" +msgid "E843: Error while updating swap file crypt" +msgstr "E843: Erreur lors de la mise à jour du fichier d'échange crypté" + #. could not (re)open the swap file, what can we do???? -#: ../memline.c:465 msgid "E301: Oops, lost the swap file!!!" msgstr "E301: Oups, le fichier d'échange a disparu !" -#: ../memline.c:477 msgid "E302: Could not rename swap file" msgstr "E302: Impossible de renommer le fichier d'échange" -#: ../memline.c:554 #, c-format msgid "E303: Unable to open swap file for \"%s\", recovery impossible" msgstr "E303: Impossible d'ouvrir fichier .swp pour \"%s\", récup. impossible" -#: ../memline.c:666 msgid "E304: ml_upd_block0(): Didn't get block 0??" msgstr "E304: ml_upd_block0() : bloc 0 non récupéré ?!" -#. no swap files found -#: ../memline.c:830 #, c-format msgid "E305: No swap file found for %s" msgstr "E305: Aucun fichier d'échange trouvé pour %s" -#: ../memline.c:839 msgid "Enter number of swap file to use (0 to quit): " msgstr "Entrez le numéro du fichier d'échange à utiliser (0 pour quitter) : " -#: ../memline.c:879 #, c-format msgid "E306: Cannot open %s" msgstr "E306: Impossible d'ouvrir %s" -#: ../memline.c:897 msgid "Unable to read block 0 from " msgstr "Impossible de lire le bloc 0 de " -#: ../memline.c:900 msgid "" "\n" "Maybe no changes were made or Vim did not update the swap file." @@ -3944,28 +3648,22 @@ msgstr "" "Il est possible qu'aucune modification n'a été faite ou que Vim n'a pas mis " "à jour le fichier d'échange." -#: ../memline.c:909 msgid " cannot be used with this version of Vim.\n" msgstr " ne peut pas être utilisé avec cette version de Vim.\n" -#: ../memline.c:911 msgid "Use Vim version 3.0.\n" msgstr "Utilisez Vim version 3.0.\n" -#: ../memline.c:916 #, c-format msgid "E307: %s does not look like a Vim swap file" msgstr "E307: %s ne semble pas être un fichier d'échange de Vim" -#: ../memline.c:922 msgid " cannot be used on this computer.\n" msgstr " ne peut pas être utilisé sur cet ordinateur.\n" -#: ../memline.c:924 msgid "The file was created on " msgstr "Le fichier a été créé le " -#: ../memline.c:928 msgid "" ",\n" "or the file has been damaged." @@ -3973,86 +3671,107 @@ msgstr "" ",\n" "ou le fichier a été endommagé." -#: ../memline.c:945 +#, c-format +msgid "" +"E833: %s is encrypted and this version of Vim does not support encryption" +msgstr "" +"E833: %s est chiffré et cette version de Vim ne supporte pas le chiffrement" + msgid " has been damaged (page size is smaller than minimum value).\n" msgstr " a été endommagé (taille de page inférieure à la valeur minimale).\n" -#: ../memline.c:974 #, c-format msgid "Using swap file \"%s\"" msgstr "Utilisation du fichier d'échange \"%s\"" -#: ../memline.c:980 #, c-format msgid "Original file \"%s\"" msgstr "Fichier original \"%s\"" -#: ../memline.c:995 msgid "E308: Warning: Original file may have been changed" msgstr "E308: Alerte : Le fichier original a pu être modifié" -#: ../memline.c:1061 +#, c-format +msgid "Swap file is encrypted: \"%s\"" +msgstr "Fichier d'échange chiffré : \"%s\"" + +msgid "" +"\n" +"If you entered a new crypt key but did not write the text file," +msgstr "" +"\n" +"Si vous avez tapé une nouvelle clé de chiffrement mais n'avez pas enregistré " +"le fichier texte," + +msgid "" +"\n" +"enter the new crypt key." +msgstr "" +"\n" +"tapez la nouvelle clé de chiffrement." + +msgid "" +"\n" +"If you wrote the text file after changing the crypt key press enter" +msgstr "" +"\n" +"Si vous avez écrit le fichier texte après avoir changé la clé de " +"chiffrement, appuyez sur entrée" + +msgid "" +"\n" +"to use the same key for text file and swap file" +msgstr "" +"\n" +"afin d'utiliser la même clé pour le fichier texte et le fichier d'échange" + #, c-format msgid "E309: Unable to read block 1 from %s" msgstr "E309: Impossible de lire le bloc 1 de %s" -#: ../memline.c:1065 msgid "???MANY LINES MISSING" msgstr "???DE NOMBREUSES LIGNES MANQUENT" -#: ../memline.c:1076 msgid "???LINE COUNT WRONG" msgstr "???NOMBRE DE LIGNES ERRONÉ" -#: ../memline.c:1082 msgid "???EMPTY BLOCK" msgstr "???BLOC VIDE" -#: ../memline.c:1103 msgid "???LINES MISSING" msgstr "???LIGNES MANQUANTES" -#: ../memline.c:1128 #, c-format msgid "E310: Block 1 ID wrong (%s not a .swp file?)" msgstr "E310: ID du bloc 1 erroné (%s n'est pas un fichier d'échange ?)" -#: ../memline.c:1133 msgid "???BLOCK MISSING" msgstr "???BLOC MANQUANT" -#: ../memline.c:1147 msgid "??? from here until ???END lines may be messed up" msgstr "??? d'ici jusqu'à ???FIN des lignes peuvent être corrompues" -#: ../memline.c:1164 msgid "??? from here until ???END lines may have been inserted/deleted" msgstr "??? d'ici jusqu'à ???FIN des lignes ont pu être insérées/effacées" -#: ../memline.c:1181 msgid "???END" msgstr "???FIN" -#: ../memline.c:1238 msgid "E311: Recovery Interrupted" msgstr "E311: Récupération interrompue" -#: ../memline.c:1243 msgid "" "E312: Errors detected while recovering; look for lines starting with ???" msgstr "" "E312: Erreurs lors de la récupération ; examinez les lignes commençant " "par ???" -#: ../memline.c:1245 msgid "See \":help E312\" for more information." msgstr "Consultez \":help E312\" pour plus d'information." -#: ../memline.c:1249 msgid "Recovery completed. You should check if everything is OK." msgstr "Récupération achevée. Vérifiez que tout est correct." -#: ../memline.c:1251 msgid "" "\n" "(You might want to write out this file under another name\n" @@ -4060,17 +3779,14 @@ msgstr "" "\n" "(Vous voudrez peut-être enregistrer ce fichier sous un autre nom\n" -#: ../memline.c:1252 msgid "and run diff with the original file to check for changes)" msgstr "et lancer diff avec le fichier original pour repérer les changements)" -#: ../memline.c:1254 msgid "Recovery completed. Buffer contents equals file contents." msgstr "" "Récupération achevée. Le contenu du tampon est identique au contenu du " "fichier." -#: ../memline.c:1255 msgid "" "\n" "You may want to delete the .swp file now.\n" @@ -4080,52 +3796,45 @@ msgstr "" "Il est conseillé d'effacer maintenant le fichier .swp.\n" "\n" +msgid "Using crypt key from swap file for the text file.\n" +msgstr "" +"Utilisation de la clé de chiffrement du fichier d'échange pour le fichier " +"texte.\n" + #. use msg() to start the scrolling properly -#: ../memline.c:1327 msgid "Swap files found:" msgstr "Fichiers d'échange trouvés :" -#: ../memline.c:1446 msgid " In current directory:\n" msgstr " Dans le répertoire courant :\n" -#: ../memline.c:1448 msgid " Using specified name:\n" msgstr "Utilisant le nom indiqué :\n" -#: ../memline.c:1450 msgid " In directory " msgstr " Dans le répertoire " -#: ../memline.c:1465 msgid " -- none --\n" msgstr " -- aucun --\n" -#: ../memline.c:1527 msgid " owned by: " msgstr " propriété de : " -#: ../memline.c:1529 msgid " dated: " msgstr " daté : " -#: ../memline.c:1532 ../memline.c:3231 msgid " dated: " msgstr " daté : " -#: ../memline.c:1548 msgid " [from Vim version 3.0]" msgstr " [de Vim version 3.0]" -#: ../memline.c:1550 msgid " [does not look like a Vim swap file]" msgstr " [ne semble pas être un fichier d'échange Vim]" -#: ../memline.c:1552 msgid " file name: " msgstr " nom de fichier : " -#: ../memline.c:1558 msgid "" "\n" " modified: " @@ -4133,15 +3842,12 @@ msgstr "" "\n" " modifié : " -#: ../memline.c:1559 msgid "YES" msgstr "OUI" -#: ../memline.c:1559 msgid "no" msgstr "non" -#: ../memline.c:1562 msgid "" "\n" " user name: " @@ -4149,11 +3855,9 @@ msgstr "" "\n" " nom d'utilisateur : " -#: ../memline.c:1568 msgid " host name: " msgstr " nom d'hôte : " -#: ../memline.c:1570 msgid "" "\n" " host name: " @@ -4161,7 +3865,6 @@ msgstr "" "\n" " nom d'hôte : " -#: ../memline.c:1575 msgid "" "\n" " process ID: " @@ -4169,11 +3872,16 @@ msgstr "" "\n" " processus n° : " -#: ../memline.c:1579 msgid " (still running)" msgstr " (en cours d'exécution)" -#: ../memline.c:1586 +msgid "" +"\n" +" [not usable with this version of Vim]" +msgstr "" +"\n" +" [inutilisable avec cette version de Vim]" + msgid "" "\n" " [not usable on this computer]" @@ -4181,97 +3889,75 @@ msgstr "" "\n" " [inutilisable sur cet ordinateur]" -#: ../memline.c:1590 msgid " [cannot be read]" msgstr " [ne peut être lu]" -#: ../memline.c:1593 msgid " [cannot be opened]" msgstr " [ne peut être ouvert]" -#: ../memline.c:1698 msgid "E313: Cannot preserve, there is no swap file" msgstr "E313: Préservation impossible, il n'y a pas de fichier d'échange" -#: ../memline.c:1747 msgid "File preserved" msgstr "Fichier préservé" -#: ../memline.c:1749 msgid "E314: Preserve failed" msgstr "E314: Échec de la préservation" -#: ../memline.c:1819 #, c-format -msgid "E315: ml_get: invalid lnum: %<PRId64>" -msgstr "E315: ml_get : numéro de ligne invalide : %<PRId64>" +msgid "E315: ml_get: invalid lnum: %ld" +msgstr "E315: ml_get : numéro de ligne invalide : %ld" -#: ../memline.c:1851 #, c-format -msgid "E316: ml_get: cannot find line %<PRId64>" -msgstr "E316: ml_get : ligne %<PRId64> introuvable" +msgid "E316: ml_get: cannot find line %ld" +msgstr "E316: ml_get : ligne %ld introuvable" -#: ../memline.c:2236 msgid "E317: pointer block id wrong 3" msgstr "E317: mauvais id de pointeur de bloc 3" -#: ../memline.c:2311 msgid "stack_idx should be 0" msgstr "stack_idx devrait être 0" -#: ../memline.c:2369 msgid "E318: Updated too many blocks?" msgstr "E318: Trop de blocs mis à jour ?" -#: ../memline.c:2511 msgid "E317: pointer block id wrong 4" msgstr "E317: mauvais id de pointeur de bloc 4" -#: ../memline.c:2536 msgid "deleted block 1?" msgstr "bloc 1 effacé ?" -#: ../memline.c:2707 #, c-format -msgid "E320: Cannot find line %<PRId64>" -msgstr "E320: Ligne %<PRId64> introuvable" +msgid "E320: Cannot find line %ld" +msgstr "E320: Ligne %ld introuvable" -#: ../memline.c:2916 msgid "E317: pointer block id wrong" msgstr "E317: mauvais id de pointeur de bloc" -#: ../memline.c:2930 msgid "pe_line_count is zero" msgstr "pe_line_count vaut zéro" -#: ../memline.c:2955 #, c-format -msgid "E322: line number out of range: %<PRId64> past the end" -msgstr "E322: numéro de ligne hors limites : %<PRId64> au-delà de la fin" +msgid "E322: line number out of range: %ld past the end" +msgstr "E322: numéro de ligne hors limites : %ld au-delà de la fin" -#: ../memline.c:2959 #, c-format -msgid "E323: line count wrong in block %<PRId64>" -msgstr "E323: nombre de lignes erroné dans le bloc %<PRId64>" +msgid "E323: line count wrong in block %ld" +msgstr "E323: nombre de lignes erroné dans le bloc %ld" -#: ../memline.c:2999 msgid "Stack size increases" msgstr "La taille de la pile s'accroît" -#: ../memline.c:3038 msgid "E317: pointer block id wrong 2" msgstr "E317: mauvais id de pointeur de block 2" -#: ../memline.c:3070 #, c-format msgid "E773: Symlink loop for \"%s\"" msgstr "E773: cycle de liens symboliques avec \"%s\"" -#: ../memline.c:3221 msgid "E325: ATTENTION" msgstr "E325: ATTENTION" -#: ../memline.c:3222 msgid "" "\n" "Found a swap file by the name \"" @@ -4279,39 +3965,32 @@ msgstr "" "\n" "Trouvé un fichier d'échange nommé \"" -#: ../memline.c:3226 msgid "While opening file \"" msgstr "Lors de l'ouverture du fichier \"" -#: ../memline.c:3239 msgid " NEWER than swap file!\n" msgstr " PLUS RÉCENT que le fichier d'échange !\n" -#: ../memline.c:3244 +#. Some of these messages are long to allow translation to +#. * other languages. msgid "" "\n" "(1) Another program may be editing the same file. If this is the case,\n" " be careful not to end up with two different instances of the same\n" -" file when making changes." +" file when making changes. Quit, or continue with caution.\n" msgstr "" "\n" "(1) Un autre programme est peut-être en train d'éditer ce fichier.\n" " Si c'est le cas, faites attention à ne pas vous retrouver avec\n" -" deux versions différentes du même fichier en faisant des modifications." - -#: ../memline.c:3245 -msgid " Quit, or continue with caution.\n" -msgstr " Quittez, ou continuez prudemment.\n" +" deux versions différentes du même fichier en faisant des modifications.\n" +" Quitter ou continuer avec attention.\n" -#: ../memline.c:3246 msgid "(2) An edit session for this file crashed.\n" msgstr "(2) Une session d'édition de ce fichier a planté.\n" -#: ../memline.c:3247 msgid " If this is the case, use \":recover\" or \"vim -r " msgstr " Si c'est le cas, utilisez \":recover\" ou \"vim -r " -#: ../memline.c:3249 msgid "" "\"\n" " to recover the changes (see \":help recovery\").\n" @@ -4319,11 +3998,9 @@ msgstr "" "\"\n" " pour récupérer le fichier (consultez \":help recovery\").\n" -#: ../memline.c:3250 msgid " If you did this already, delete the swap file \"" msgstr " Si vous l'avez déjà fait, effacez le fichier d'échange \"" -#: ../memline.c:3252 msgid "" "\"\n" " to avoid this message.\n" @@ -4331,23 +4008,18 @@ msgstr "" "\"\n" " pour éviter ce message.\n" -#: ../memline.c:3450 ../memline.c:3452 msgid "Swap file \"" msgstr "Le fichier d'échange \"" -#: ../memline.c:3451 ../memline.c:3455 msgid "\" already exists!" msgstr "\" existe déjà !" -#: ../memline.c:3457 msgid "VIM - ATTENTION" msgstr "VIM - ATTENTION" -#: ../memline.c:3459 msgid "Swap file already exists!" msgstr "Un fichier d'échange existe déjà !" -#: ../memline.c:3464 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4361,7 +4033,6 @@ msgstr "" "&Quitter\n" "&Abandonner" -#: ../memline.c:3467 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4377,58 +4048,36 @@ msgstr "" "&Quitter\n" "&Abandonner" -#. -#. * Change the ".swp" extension to find another file that can be used. -#. * First decrement the last char: ".swo", ".swn", etc. -#. * If that still isn't enough decrement the last but one char: ".svz" -#. * Can happen when editing many "No Name" buffers. -#. -#. ".s?a" -#. ".saa": tried enough, give up -#: ../memline.c:3528 msgid "E326: Too many swap files found" msgstr "E326: Trop de fichiers d'échange trouvés" -#: ../memory.c:227 -#, c-format -msgid "E342: Out of memory! (allocating %<PRIu64> bytes)" -msgstr "E342: Mémoire épuisée ! (allocation de %<PRIu64> octets)" - -#: ../menu.c:62 msgid "E327: Part of menu-item path is not sub-menu" msgstr "E327: Une partie du chemin de l'élément de menu n'est pas un sous-menu" # DB - todo : J'hésite avec # msgstr "E328: Le menu n'existe pas dans ce mode" -#: ../menu.c:63 msgid "E328: Menu only exists in another mode" msgstr "E328: Le menu n'existe que dans un autre mode" -#: ../menu.c:64 #, c-format msgid "E329: No menu \"%s\"" msgstr "E329: Aucun menu \"%s\"" #. Only a mnemonic or accelerator is not valid. -#: ../menu.c:329 msgid "E792: Empty menu name" msgstr "E792: Nom de menu vide" -#: ../menu.c:340 msgid "E330: Menu path must not lead to a sub-menu" msgstr "E330: Le chemin de menu ne doit pas conduire à un sous-menu" -#: ../menu.c:365 msgid "E331: Must not add menu items directly to menu bar" msgstr "E331: Ajout d'éléments de menu directement dans barre de menu interdit" -#: ../menu.c:370 msgid "E332: Separator cannot be part of a menu path" msgstr "E332: Un séparateur ne peut faire partie d'un chemin de menu" #. Now we have found the matching menu, and we list the mappings #. Highlight title -#: ../menu.c:762 msgid "" "\n" "--- Menus ---" @@ -4436,71 +4085,62 @@ msgstr "" "\n" "--- Menus ---" -#: ../menu.c:1313 +msgid "Tear off this menu" +msgstr "Détacher ce menu" + msgid "E333: Menu path must lead to a menu item" msgstr "E333: Le chemin du menu doit conduire à un élément de menu" -#: ../menu.c:1330 #, c-format msgid "E334: Menu not found: %s" msgstr "E334: Menu introuvable : %s" -#: ../menu.c:1396 #, c-format msgid "E335: Menu not defined for %s mode" msgstr "E335: Le menu n'est pas défini pour le mode %s" -#: ../menu.c:1426 msgid "E336: Menu path must lead to a sub-menu" msgstr "E336: Le chemin du menu doit conduire à un sous-menu" -#: ../menu.c:1447 msgid "E337: Menu not found - check menu names" msgstr "E337: Menu introuvable - vérifiez les noms des menus" -#: ../message.c:423 #, c-format msgid "Error detected while processing %s:" msgstr "Erreur détectée en traitant %s :" -#: ../message.c:445 #, c-format msgid "line %4ld:" msgstr "ligne %4ld :" -#: ../message.c:617 #, c-format msgid "E354: Invalid register name: '%s'" msgstr "E354: Nom de registre invalide : '%s'" # DB - todo : mettre à jour ? -#: ../message.c:986 +msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>" +msgstr "Maintenance des messages : Dominique Pellé <dominique.pelle@gmail.com>" + msgid "Interrupt: " msgstr "Interruption : " -#: ../message.c:988 msgid "Press ENTER or type command to continue" msgstr "Appuyez sur ENTRÉE ou tapez une commande pour continuer" -#: ../message.c:1843 #, c-format -msgid "%s line %<PRId64>" -msgstr "%s, ligne %<PRId64>" +msgid "%s line %ld" +msgstr "%s, ligne %ld" -#: ../message.c:2392 msgid "-- More --" msgstr "-- Plus --" -#: ../message.c:2398 msgid " SPACE/d/j: screen/page/line down, b/u/k: up, q: quit " msgstr "" "ESPACE/d/j : écran/page/ligne vers le bas, b/u/k : vers le haut, q : quitter" -#: ../message.c:3021 ../message.c:3031 msgid "Question" msgstr "Question" -#: ../message.c:3023 msgid "" "&Yes\n" "&No" @@ -4508,17 +4148,6 @@ msgstr "" "&Oui\n" "&Non" -#: ../message.c:3033 -msgid "" -"&Yes\n" -"&No\n" -"&Cancel" -msgstr "" -"&Oui\n" -"&Non\n" -"&Annuler" - -#: ../message.c:3045 msgid "" "&Yes\n" "&No\n" @@ -4532,176 +4161,251 @@ msgstr "" "Tout aban&donner\n" "&Annuler" -#: ../message.c:3058 +# DB : Les trois messages qui suivent sont des titres de boîtes +# de dialogue par défaut. +msgid "Select Directory dialog" +msgstr "Sélecteur de répertoire" + +msgid "Save File dialog" +msgstr "Enregistrer un fichier" + +msgid "Open File dialog" +msgstr "Ouvrir un fichier" + +#. TODO: non-GUI file selector here +msgid "E338: Sorry, no file browser in console mode" +msgstr "E338: Désolé, pas de sélecteur de fichiers en mode console" + msgid "E766: Insufficient arguments for printf()" msgstr "E766: Pas assez d'arguments pour printf()" -#: ../message.c:3119 msgid "E807: Expected Float argument for printf()" msgstr "E807: printf() attend un argument de type Flottant" -#: ../message.c:3873 msgid "E767: Too many arguments to printf()" msgstr "E767: Trop d'arguments pour printf()" -#: ../misc1.c:2256 msgid "W10: Warning: Changing a readonly file" msgstr "W10: Alerte : Modification d'un fichier en lecture seule" -#: ../misc1.c:2537 msgid "Type number and <Enter> or click with mouse (empty cancels): " msgstr "Tapez un nombre et <Entrée> ou cliquez avec la souris (rien annule) :" -#: ../misc1.c:2539 msgid "Type number and <Enter> (empty cancels): " msgstr "Tapez un nombre et <Entrée> (rien annule) :" -#: ../misc1.c:2585 msgid "1 more line" msgstr "1 ligne en plus" -#: ../misc1.c:2588 msgid "1 line less" msgstr "1 ligne en moins" -#: ../misc1.c:2593 #, c-format -msgid "%<PRId64> more lines" -msgstr "%<PRId64> lignes en plus" +msgid "%ld more lines" +msgstr "%ld lignes en plus" -#: ../misc1.c:2596 #, c-format -msgid "%<PRId64> fewer lines" -msgstr "%<PRId64> lignes en moins" +msgid "%ld fewer lines" +msgstr "%ld lignes en moins" -#: ../misc1.c:2599 msgid " (Interrupted)" msgstr " (Interrompu)" -#: ../misc1.c:2635 msgid "Beep!" msgstr "Bip !" -#: ../misc2.c:738 +msgid "ERROR: " +msgstr "ERREUR : " + +#, c-format +msgid "" +"\n" +"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n" +msgstr "" +"\n" +"[octets] total alloué-libéré %lu-%lu, utilisé %lu, pic %lu\n" + +#, c-format +msgid "" +"[calls] total re/malloc()'s %lu, total free()'s %lu\n" +"\n" +msgstr "" +"[appels] total re/malloc() %lu, total free() %lu\n" +"\n" + +msgid "E340: Line is becoming too long" +msgstr "E340: La ligne devient trop longue" + +#, c-format +msgid "E341: Internal error: lalloc(%ld, )" +msgstr "E341: Erreur interne : lalloc(%ld, )" + +#, c-format +msgid "E342: Out of memory! (allocating %lu bytes)" +msgstr "E342: Mémoire épuisée ! (allocation de %lu octets)" + #, c-format msgid "Calling shell to execute: \"%s\"" msgstr "Appel du shell pour exécuter : \"%s\"" -#: ../normal.c:183 +msgid "E545: Missing colon" +msgstr "E545: ':' manquant" + +msgid "E546: Illegal mode" +msgstr "E546: Mode non autorisé" + +msgid "E547: Illegal mouseshape" +msgstr "E547: Forme de curseur invalide" + +msgid "E548: digit expected" +msgstr "E548: chiffre attendu" + +msgid "E549: Illegal percentage" +msgstr "E549: Pourcentage non autorisé" + +msgid "E854: path too long for completion" +msgstr "E854: chemin trop long pour complètement" + +#, c-format +msgid "" +"E343: Invalid path: '**[number]' must be at the end of the path or be " +"followed by '%s'." +msgstr "" +"E343: Chemin invalide : '**[nombre]' doit être à la fin du chemin ou être " +"suivi de '%s'." + +#, c-format +msgid "E344: Can't find directory \"%s\" in cdpath" +msgstr "E344: Répertoire \"%s\" introuvable dans 'cdpath'" + +#, c-format +msgid "E345: Can't find file \"%s\" in path" +msgstr "E345: Fichier \"%s\" introuvable dans 'path'" + +#, c-format +msgid "E346: No more directory \"%s\" found in cdpath" +msgstr "E346: Plus de répertoire \"%s\" dans 'cdpath'" + +#, c-format +msgid "E347: No more file \"%s\" found in path" +msgstr "E347: Plus de fichier \"%s\" dans 'path'" + +#, c-format +msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" +msgstr "" +"E668: Mode d'accès incorrect au fichier d'infos de connexion NetBeans : \"%s" +"\"" + +#, c-format +msgid "E658: NetBeans connection lost for buffer %ld" +msgstr "E658: Connexion NetBeans perdue pour le tampon %ld" + +msgid "E838: netbeans is not supported with this GUI" +msgstr "E838: netbeans n'est pas supporté avec cette interface graphique" + +msgid "E511: netbeans already connected" +msgstr "E511: netbeans déjà connecté" + +#, c-format +msgid "E505: %s is read-only (add ! to override)" +msgstr "E505: %s est en lecture seule (ajoutez ! pour passer outre)" + msgid "E349: No identifier under cursor" msgstr "E349: Aucun identifiant sous le curseur" -#: ../normal.c:1866 msgid "E774: 'operatorfunc' is empty" msgstr "E774: 'operatorfunc' est vide" +msgid "E775: Eval feature not available" +msgstr "E775: La fonctionnalité d'évaluation n'est pas disponible" + # DB : Il est ici question du mode Visuel. -#: ../normal.c:2637 msgid "Warning: terminal cannot highlight" msgstr "Alerte : le terminal ne peut pas surligner" -#: ../normal.c:2807 msgid "E348: No string under cursor" msgstr "E348: Aucune chaîne sous le curseur" -#: ../normal.c:3937 msgid "E352: Cannot erase folds with current 'foldmethod'" msgstr "E352: Impossible d'effacer des replis avec la 'foldmethod'e actuelle" -#: ../normal.c:5897 msgid "E664: changelist is empty" msgstr "E664: La liste des modifications (changelist) est vide" -#: ../normal.c:5899 msgid "E662: At start of changelist" msgstr "E662: Au début de la liste des modifications" -#: ../normal.c:5901 msgid "E663: At end of changelist" msgstr "E663: À la fin de la liste des modifications" -#: ../normal.c:7053 -msgid "Type :quit<Enter> to exit Nvim" +msgid "Type :quit<Enter> to exit Vim" msgstr "tapez :q<Entrée> pour quitter Vim" -#: ../ops.c:248 #, c-format msgid "1 line %sed 1 time" msgstr "1 ligne %sée 1 fois" -#: ../ops.c:250 #, c-format msgid "1 line %sed %d times" msgstr "1 ligne %sée %d fois" -#: ../ops.c:253 #, c-format -msgid "%<PRId64> lines %sed 1 time" -msgstr "%<PRId64> lignes %sées 1 fois" +msgid "%ld lines %sed 1 time" +msgstr "%ld lignes %sées 1 fois" -#: ../ops.c:256 #, c-format -msgid "%<PRId64> lines %sed %d times" -msgstr "%<PRId64> lignes %sées %d fois" +msgid "%ld lines %sed %d times" +msgstr "%ld lignes %sées %d fois" -#: ../ops.c:592 #, c-format -msgid "%<PRId64> lines to indent... " -msgstr "%<PRId64> lignes à indenter... " +msgid "%ld lines to indent... " +msgstr "%ld lignes à indenter... " -#: ../ops.c:634 msgid "1 line indented " msgstr "1 ligne indentée " -#: ../ops.c:636 #, c-format -msgid "%<PRId64> lines indented " -msgstr "%<PRId64> lignes indentées " +msgid "%ld lines indented " +msgstr "%ld lignes indentées " -#: ../ops.c:938 msgid "E748: No previously used register" msgstr "E748: Aucun registre n'a été précédemment utilisé" # DB - Question O/N. #. must display the prompt -#: ../ops.c:1433 msgid "cannot yank; delete anyway" msgstr "impossible de réaliser une copie ; effacer tout de même" -#: ../ops.c:1929 msgid "1 line changed" msgstr "1 ligne modifiée" -#: ../ops.c:1931 #, c-format -msgid "%<PRId64> lines changed" -msgstr "%<PRId64> lignes modifiées" +msgid "%ld lines changed" +msgstr "%ld lignes modifiées" + +#, c-format +msgid "freeing %ld lines" +msgstr "libération de %ld lignes" -#: ../ops.c:2521 msgid "block of 1 line yanked" msgstr "bloc de 1 ligne copié" -#: ../ops.c:2523 msgid "1 line yanked" msgstr "1 ligne copiée" -#: ../ops.c:2525 #, c-format -msgid "block of %<PRId64> lines yanked" -msgstr "bloc de %<PRId64> lignes copié" +msgid "block of %ld lines yanked" +msgstr "bloc de %ld lignes copié" -#: ../ops.c:2528 #, c-format -msgid "%<PRId64> lines yanked" -msgstr "%<PRId64> lignes copiées" +msgid "%ld lines yanked" +msgstr "%ld lignes copiées" -#: ../ops.c:2710 #, c-format msgid "E353: Nothing in register %s" msgstr "E353: Le registre %s est vide" #. Highlight title -#: ../ops.c:3185 msgid "" "\n" "--- Registers ---" @@ -4709,11 +4413,9 @@ msgstr "" "\n" "--- Registres ---" -#: ../ops.c:4455 msgid "Illegal register name" msgstr "Nom de registre invalide" -#: ../ops.c:4533 msgid "" "\n" "# Registers:\n" @@ -4721,189 +4423,179 @@ msgstr "" "\n" "# Registres :\n" -#: ../ops.c:4575 #, c-format msgid "E574: Unknown register type %d" msgstr "E574: Type de registre %d inconnu" -#: ../ops.c:5089 +msgid "" +"E883: search pattern and expression register may not contain two or more " +"lines" +msgstr "" +"E883: le motif de recherche et le registre d'expression ne peuvent pas " +"contenir deux lignes ou plus" + #, c-format -msgid "%<PRId64> Cols; " -msgstr "%<PRId64> Colonnes ; " +msgid "%ld Cols; " +msgstr "%ld Colonnes ; " -#: ../ops.c:5097 #, c-format -msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Bytes" +msgid "Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Bytes" msgstr "" -"%s%<PRId64> sur %<PRId64> Lignes ; %<PRId64> sur %<PRId64> Mots ; %<PRId64> " -"sur %<PRId64> Octets sélectionnés" +"%s%ld sur %ld Lignes ; %lld sur %lld Mots ; %lld sur %lld Octets sélectionnés" -#: ../ops.c:5105 #, c-format msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Chars; %<PRId64> of %<PRId64> Bytes" +"Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Chars; %lld of " +"%lld Bytes" msgstr "" -"%s%<PRId64> sur %<PRId64> Lignes ; %<PRId64> sur %<PRId64> Mots ; %<PRId64> " -"sur %<PRId64> Caractères ; %<PRId64> sur %<PRId64> octets sélectionnés" +"%s%ld sur %ld Lignes ; %lld sur %lld Mots ; %lld sur %lld Caractères ; %lld " +"sur %lld octets sélectionnés" -#: ../ops.c:5123 #, c-format -msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Byte " -"%<PRId64> of %<PRId64>" +msgid "Col %s of %s; Line %ld of %ld; Word %lld of %lld; Byte %lld of %lld" msgstr "" -"Colonne %s sur %s ; Ligne %<PRId64> sur %<PRId64> ; Mot %<PRId64> sur " -"%<PRId64> ; Octet %<PRId64> sur %<PRId64>" +"Colonne %s sur %s ; Ligne %ld sur %ld ; Mot %lld sur %lld ; Octet %lld sur " +"%lld" -#: ../ops.c:5133 #, c-format msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Char " -"%<PRId64> of %<PRId64>; Byte %<PRId64> of %<PRId64>" +"Col %s of %s; Line %ld of %ld; Word %lld of %lld; Char %lld of %lld; Byte " +"%lld of %lld" msgstr "" -"Colonne %s sur %s ; Ligne %<PRId64> sur %<PRId64> ; Mot %<PRId64> sur " -"%<PRId64> ; Caractère %<PRId64> sur %<PRId64> ; Octet %<PRId64> sur %<PRId64>" +"Colonne %s sur %s ; Ligne %ld sur %ld ; Mot %lld sur %lld ; Caractère %lld " +"sur %lld ; Octet %lld sur %lld" -#: ../ops.c:5146 #, c-format -msgid "(+%<PRId64> for BOM)" -msgstr "(+%<PRId64> pour le BOM)" +msgid "(+%ld for BOM)" +msgstr "(+%ld pour le BOM)" -#: ../option.c:1238 msgid "%<%f%h%m%=Page %N" msgstr "%<%f%h%m%=Page %N" -#: ../option.c:1574 msgid "Thanks for flying Vim" msgstr "Merci d'avoir choisi Vim" -#. found a mismatch: skip -#: ../option.c:2698 msgid "E518: Unknown option" msgstr "E518: Option inconnue" -#: ../option.c:2709 msgid "E519: Option not supported" msgstr "E519: Option non supportée" -#: ../option.c:2740 msgid "E520: Not allowed in a modeline" msgstr "E520: Non autorisé dans une ligne de mode" -#: ../option.c:2815 msgid "E846: Key code not set" msgstr "E846: Le code de touche n'est pas configuré" -#: ../option.c:2924 msgid "E521: Number required after =" msgstr "E521: Nombre requis après =" -#: ../option.c:3226 ../option.c:3864 msgid "E522: Not found in termcap" msgstr "E522: Introuvable dans termcap" -#: ../option.c:3335 #, c-format msgid "E539: Illegal character <%s>" msgstr "E539: Caractère <%s> invalide" -#: ../option.c:2253 #, c-format msgid "For option %s" msgstr "Pour l'option %s" -#: ../option.c:3862 msgid "E529: Cannot set 'term' to empty string" msgstr "E529: 'term' ne doit pas être une chaîne vide" -#: ../option.c:3885 +msgid "E530: Cannot change term in GUI" +msgstr "E530: Impossible de modifier term dans l'interface graphique" + +msgid "E531: Use \":gui\" to start the GUI" +msgstr "E531: Utilisez \":gui\" pour démarrer l'interface graphique" + msgid "E589: 'backupext' and 'patchmode' are equal" msgstr "E589: 'backupext' et 'patchmode' sont égaux" -#: ../option.c:3964 msgid "E834: Conflicts with value of 'listchars'" msgstr "E834: Conflits avec la valeur de 'listchars'" -#: ../option.c:3966 msgid "E835: Conflicts with value of 'fillchars'" msgstr "E835: Conflits avec la valeur de 'fillchars'" -#: ../option.c:4163 +msgid "E617: Cannot be changed in the GTK+ 2 GUI" +msgstr "E617: Non modifiable dans l'interface graphique GTK+ 2" + msgid "E524: Missing colon" msgstr "E524: ':' manquant" -#: ../option.c:4165 msgid "E525: Zero length string" msgstr "E525: Chaîne de longueur nulle" -#: ../option.c:4220 #, c-format msgid "E526: Missing number after <%s>" msgstr "E526: Nombre manquant après <%s>" -#: ../option.c:4232 msgid "E527: Missing comma" msgstr "E527: Virgule manquante" -#: ../option.c:4239 msgid "E528: Must specify a ' value" msgstr "E528: Une valeur ' doit être spécifiée" -#: ../option.c:4271 msgid "E595: contains unprintable or wide character" msgstr "E595: contient des caractères à largeur double non-imprimables" -#: ../option.c:4469 +msgid "E596: Invalid font(s)" +msgstr "E596: Police(s) invalide(s)" + +msgid "E597: can't select fontset" +msgstr "E597: Impossible de sélectionner un jeu de polices" + +msgid "E598: Invalid fontset" +msgstr "E598: Jeu de polices invalide" + +msgid "E533: can't select wide font" +msgstr "E533: Impossible de sélectionner une police à largeur double" + +msgid "E534: Invalid wide font" +msgstr "E534: Police à largeur double invalide" + #, c-format msgid "E535: Illegal character after <%c>" msgstr "E535: Caractère invalide après <%c>" -#: ../option.c:4534 msgid "E536: comma required" msgstr "E536: virgule requise" -#: ../option.c:4543 #, c-format msgid "E537: 'commentstring' must be empty or contain %s" msgstr "E537: 'commentstring' doit être vide ou contenir %s" +msgid "E538: No mouse support" +msgstr "E538: La souris n'est pas supportée" + # DB - Le code est sans ambiguïté sur le caractère manquant. # À défaut d'une traduction valable, au moins comprend-on # ce qui se passe. -#: ../option.c:4928 msgid "E540: Unclosed expression sequence" msgstr "E540: '}' manquant" -#: ../option.c:4932 msgid "E541: too many items" msgstr "E541: trop d'éléments" -#: ../option.c:4934 msgid "E542: unbalanced groups" msgstr "E542: parenthèses non équilibrées" -#: ../option.c:5148 msgid "E590: A preview window already exists" msgstr "E590: Il existe déjà une fenêtre de prévisualisation" -#: ../option.c:5311 msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'" -msgstr "W17: L'arabe requiert l'UTF-8, tapez ':set encoding=utf-8'" +msgstr "W17: L'arabe nécessite l'UTF-8, tapez ':set encoding=utf-8'" -#: ../option.c:5623 #, c-format msgid "E593: Need at least %d lines" msgstr "E593: Au moins %d lignes sont nécessaires" -#: ../option.c:5631 #, c-format msgid "E594: Need at least %d columns" msgstr "E594: Au moins %d colonnes sont nécessaires" -#: ../option.c:6011 #, c-format msgid "E355: Unknown option: %s" msgstr "E355: Option inconnue : %s" @@ -4911,12 +4603,10 @@ msgstr "E355: Option inconnue : %s" #. 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. -#: ../option.c:6037 #, c-format msgid "E521: Number required: &%s = '%s'" msgstr "E521: Nombre requis : &%s = '%s'" -#: ../option.c:6149 msgid "" "\n" "--- Terminal codes ---" @@ -4924,7 +4614,6 @@ msgstr "" "\n" "--- Codes de terminal ---" -#: ../option.c:6151 msgid "" "\n" "--- Global option values ---" @@ -4932,7 +4621,6 @@ msgstr "" "\n" "--- Valeur des options globales ---" -#: ../option.c:6153 msgid "" "\n" "--- Local option values ---" @@ -4940,7 +4628,6 @@ msgstr "" "\n" "--- Valeur des options locales ---" -#: ../option.c:6155 msgid "" "\n" "--- Options ---" @@ -4948,29 +4635,147 @@ msgstr "" "\n" "--- Options ---" -#: ../option.c:6816 msgid "E356: get_varp ERROR" msgstr "E356: ERREUR get_varp" -#: ../option.c:7696 #, c-format msgid "E357: 'langmap': Matching character missing for %s" msgstr "E357: 'langmap' : Aucun caractère correspondant pour %s" -#: ../option.c:7715 #, c-format msgid "E358: 'langmap': Extra characters after semicolon: %s" msgstr "E358: 'langmap' : Caractères surnuméraires après point-virgule : %s" -#: ../os/shell.c:194 +msgid "cannot open " +msgstr "impossible d'ouvrir " + +msgid "VIM: Can't open window!\n" +msgstr "VIM : Impossible d'ouvrir la fenêtre !\n" + +msgid "Need Amigados version 2.04 or later\n" +msgstr "Amigados version 2.04 ou ultérieure est nécessaire\n" + +#, c-format +msgid "Need %s version %ld\n" +msgstr "%s version %ld est nécessaire\n" + +msgid "Cannot open NIL:\n" +msgstr "Impossible d'ouvrir NIL :\n" + +msgid "Cannot create " +msgstr "Impossible de créer " + +#, c-format +msgid "Vim exiting with %d\n" +msgstr "Vim quitte avec %d\n" + +msgid "cannot change console mode ?!\n" +msgstr "Impossible de modifier le mode de la console ?!\n" + +msgid "mch_get_shellsize: not a console??\n" +msgstr "mch_get_shellsize : pas une console ?!\n" + +#. if Vim opened a window: Executing a shell may cause crashes +msgid "E360: Cannot execute shell with -f option" +msgstr "E360: Impossible d'exécuter un shell avec l'option -f" + +msgid "Cannot execute " +msgstr "Impossible d'exécuter " + +msgid "shell " +msgstr "le shell " + +msgid " returned\n" +msgstr " a été retourné\n" + +msgid "ANCHOR_BUF_SIZE too small." +msgstr "ANCHOR_BUF_SIZE trop petit." + +msgid "I/O ERROR" +msgstr "ERREUR d'E/S" + +msgid "Message" +msgstr "Message" + +msgid "E237: Printer selection failed" +msgstr "E237: La sélection de l'imprimante a échoué" + +# DB - Contenu des c-formats : Imprimante puis Port. +#, c-format +msgid "to %s on %s" +msgstr "vers %s sur %s" + +#, c-format +msgid "E613: Unknown printer font: %s" +msgstr "E613: Police d'imprimante inconnue : %s" + +#, c-format +msgid "E238: Print error: %s" +msgstr "E238: Erreur d'impression : %s" + +#, c-format +msgid "Printing '%s'" +msgstr "Impression de '%s'" + +#, c-format +msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" +msgstr "E244: Jeu de caractères \"%s\" invalide dans le nom de fonte \"%s\"" + +#, c-format +msgid "E244: Illegal quality name \"%s\" in font name \"%s\"" +msgstr "E244: Nom de qualité \"%s\" invalide dans le nom de fonte \"%s\"" + +#, c-format +msgid "E245: Illegal char '%c' in font name \"%s\"" +msgstr "E245: Caractère '%c' invalide dans le nom de fonte \"%s\"" + +#, c-format +msgid "Opening the X display took %ld msec" +msgstr "L'ouverture du display X a pris %ld ms" + msgid "" "\n" -"Cannot execute shell " +"Vim: Got X error\n" msgstr "" "\n" -"Impossible d'exécuter le shell " +"Vim : Réception d'une erreur X\n" + +msgid "Testing the X display failed" +msgstr "Le test du display X a échoué" + +msgid "Opening the X display timed out" +msgstr "L'ouverture du display X a dépassé le délai d'attente" + +msgid "" +"\n" +"Could not get security context for " +msgstr "" +"\n" +"Impossible d'obtenir le contexte de sécurité pour " + +msgid "" +"\n" +"Could not set security context for " +msgstr "" +"\n" +"Impossible de modifier le contexte de sécurité pour " + +#, c-format +msgid "Could not set security context %s for %s" +msgstr "Impossible d'initialiser le contexte de sécurité %s pour %s" + +#, c-format +msgid "Could not get security context %s for %s. Removing it!" +msgstr "" +"Impossible d'obtenir le contexte de sécurité %s pour %s. Il sera supprimé !" + +msgid "" +"\n" +"Cannot execute shell sh\n" +msgstr "" +"\n" +"Impossible d'exécuter le shell sh\n" -#: ../os/shell.c:439 msgid "" "\n" "shell returned " @@ -4978,234 +4783,278 @@ msgstr "" "\n" "le shell a retourné " -#: ../os_unix.c:465 ../os_unix.c:471 msgid "" "\n" -"Could not get security context for " +"Cannot create pipes\n" msgstr "" "\n" -"Impossible d'obtenir le contexte de sécurité pour " +"Impossible de créer des tuyaux (pipes)\n" -#: ../os_unix.c:479 msgid "" "\n" -"Could not set security context for " +"Cannot fork\n" msgstr "" "\n" -"Impossible de modifier le contexte de sécurité pour " +"Impossible de forker\n" + +msgid "" +"\n" +"Cannot execute shell " +msgstr "" +"\n" +"Impossible d'exécuter le shell " + +msgid "" +"\n" +"Command terminated\n" +msgstr "" +"\n" +"Commande interrompue\n" + +msgid "XSMP lost ICE connection" +msgstr "XSMP a perdu la connexion ICE" -#: ../os_unix.c:1558 ../os_unix.c:1647 #, c-format msgid "dlerror = \"%s\"" msgstr "dlerror = \"%s\"" -#: ../path.c:1449 +msgid "Opening the X display failed" +msgstr "L'ouverture du display X a échoué" + +msgid "XSMP handling save-yourself request" +msgstr "XSMP : prise en charge d'une requête save-yourself" + +msgid "XSMP opening connection" +msgstr "XSMP : ouverture de la connexion" + +msgid "XSMP ICE connection watch failed" +msgstr "XSMP : échec de la surveillance de connexion ICE" + #, c-format -msgid "E447: Can't find file \"%s\" in path" -msgstr "E447: Le fichier \"%s\" est introuvable dans 'path'" +msgid "XSMP SmcOpenConnection failed: %s" +msgstr "XSMP : SmcOpenConnection a échoué : %s" + +msgid "At line" +msgstr "À la ligne" + +msgid "Could not load vim32.dll!" +msgstr "Impossible de charger vim32.dll !" + +msgid "VIM Error" +msgstr "Erreur VIM" + +msgid "Could not fix up function pointers to the DLL!" +msgstr "Impossible d'initialiser les pointeurs de fonction vers la DLL !" + +# DB - Les événements en question sont ceux des messages qui suivent. +#, c-format +msgid "Vim: Caught %s event\n" +msgstr "Vim : Événement %s intercepté\n" + +msgid "close" +msgstr "de fermeture" + +msgid "logoff" +msgstr "de déconnexion" + +msgid "shutdown" +msgstr "d'arrêt" + +msgid "E371: Command not found" +msgstr "E371: Commande introuvable" + +msgid "" +"VIMRUN.EXE not found in your $PATH.\n" +"External commands will not pause after completion.\n" +"See :help win32-vimrun for more information." +msgstr "" +"VIMRUN.EXE est introuvable votre $PATH.\n" +"Les commandes externes ne feront pas de pause une fois terminées.\n" +"Consultez :help win32-vimrun pour plus d'informations." + +msgid "Vim Warning" +msgstr "Alerte Vim" + +#, c-format +msgid "shell returned %d" +msgstr "le shell a retourné %d" -#: ../quickfix.c:359 #, c-format msgid "E372: Too many %%%c in format string" msgstr "E372: Trop de %%%c dans la chaîne de format" -#: ../quickfix.c:371 #, c-format msgid "E373: Unexpected %%%c in format string" msgstr "E373: %%%c inattendu dans la chaîne de format" -#: ../quickfix.c:420 msgid "E374: Missing ] in format string" msgstr "E374: ] manquant dans la chaîne de format" -#: ../quickfix.c:431 #, c-format msgid "E375: Unsupported %%%c in format string" msgstr "E375: %%%c non supporté dans la chaîne de format" -#: ../quickfix.c:448 #, c-format msgid "E376: Invalid %%%c in format string prefix" msgstr "E376: %%%c invalide dans le préfixe de la chaîne de format" -#: ../quickfix.c:454 #, c-format msgid "E377: Invalid %%%c in format string" msgstr "E377: %%%c invalide dans la chaîne de format" #. nothing found -#: ../quickfix.c:477 msgid "E378: 'errorformat' contains no pattern" msgstr "E378: 'errorformat' ne contient aucun motif" -#: ../quickfix.c:695 msgid "E379: Missing or empty directory name" msgstr "E379: Nom de répertoire vide ou absent" -#: ../quickfix.c:1305 msgid "E553: No more items" msgstr "E553: Plus d'éléments" -#: ../quickfix.c:1674 +msgid "E924: Current window was closed" +msgstr "E924: La fenêtre courante doit être fermée" + +msgid "E925: Current quickfix was changed" +msgstr "E925: Le quickfix courant a changé" + +msgid "E926: Current location list was changed" +msgstr "E926: La liste d'emplacements courante a changé" + #, c-format msgid "(%d of %d)%s%s: " msgstr "(%d sur %d)%s%s : " -#: ../quickfix.c:1676 msgid " (line deleted)" msgstr " (ligne effacée)" -#: ../quickfix.c:1863 +#, c-format +msgid "%serror list %d of %d; %d errors " +msgstr "%sliste d'erreurs %d sur %d ; %d erreurs" + msgid "E380: At bottom of quickfix stack" msgstr "E380: En bas de la pile quickfix" -#: ../quickfix.c:1869 msgid "E381: At top of quickfix stack" msgstr "E381: Au sommet de la pile quickfix" -#: ../quickfix.c:1880 -#, c-format -msgid "error list %d of %d; %d errors" -msgstr "liste d'erreurs %d sur %d ; %d erreurs" +msgid "No entries" +msgstr "Aucune entrée" -#: ../quickfix.c:2427 msgid "E382: Cannot write, 'buftype' option is set" msgstr "E382: Écriture impossible, l'option 'buftype' est activée" -#: ../quickfix.c:2812 +msgid "Error file" +msgstr "Fichier d'erreurs" + msgid "E683: File name missing or invalid pattern" msgstr "E683: Nom de fichier manquant ou motif invalide" -#: ../quickfix.c:2911 #, c-format msgid "Cannot open file \"%s\"" msgstr "Impossible d'ouvrir le fichier \"%s\"" -#: ../quickfix.c:3429 msgid "E681: Buffer is not loaded" msgstr "E681: le tampon n'est pas chargé" -#: ../quickfix.c:3487 msgid "E777: String or List expected" msgstr "E777: Chaîne ou Liste attendue" -#: ../regexp.c:359 #, c-format msgid "E369: invalid item in %s%%[]" msgstr "E369: élément invalide dans %s%%[]" -#: ../regexp.c:374 #, c-format msgid "E769: Missing ] after %s[" msgstr "E769: ']' manquant après %s[" -#: ../regexp.c:375 #, c-format msgid "E53: Unmatched %s%%(" msgstr "E53: Pas de correspondance pour %s%%(" -#: ../regexp.c:376 #, c-format msgid "E54: Unmatched %s(" msgstr "E54: %s( ouvrante non fermée" -#: ../regexp.c:377 #, c-format msgid "E55: Unmatched %s)" msgstr "E55: %s) fermante non ouverte" -#: ../regexp.c:378 msgid "E66: \\z( not allowed here" msgstr "E66: \\z( n'est pas autorisé ici" -#: ../regexp.c:379 msgid "E67: \\z1 et al. not allowed here" msgstr "E67: \\z1 et co. ne sont pas autorisés ici" -#: ../regexp.c:380 #, c-format msgid "E69: Missing ] after %s%%[" msgstr "E69: ']' manquant après %s%%[" -#: ../regexp.c:381 #, c-format msgid "E70: Empty %s%%[]" msgstr "E70: %s%%[] vide" -#: ../regexp.c:1209 ../regexp.c:1224 msgid "E339: Pattern too long" msgstr "E339: Motif trop long" -#: ../regexp.c:1371 msgid "E50: Too many \\z(" msgstr "E50: Trop de \\z(" -#: ../regexp.c:1378 #, c-format msgid "E51: Too many %s(" msgstr "E51: Trop de %s(" -#: ../regexp.c:1427 msgid "E52: Unmatched \\z(" msgstr "E52: Pas de correspondance pour \\z(" -#: ../regexp.c:1637 #, c-format msgid "E59: invalid character after %s@" msgstr "E59: caractère invalide après %s@" -#: ../regexp.c:1672 #, c-format msgid "E60: Too many complex %s{...}s" msgstr "E60: Trop de %s{...}s complexes" -#: ../regexp.c:1687 #, c-format msgid "E61: Nested %s*" msgstr "E61: %s* imbriqués" -#: ../regexp.c:1690 #, c-format msgid "E62: Nested %s%c" msgstr "E62: %s%c imbriqués" -#: ../regexp.c:1800 msgid "E63: invalid use of \\_" msgstr "E63: utilisation invalide de \\_" -#: ../regexp.c:1850 #, c-format msgid "E64: %s%c follows nothing" msgstr "E64: %s%c ne suit aucun atome" -#: ../regexp.c:1902 msgid "E65: Illegal back reference" msgstr "E65: post-référence invalide" -#: ../regexp.c:1943 msgid "E68: Invalid character after \\z" msgstr "E68: Caractère invalide après \\z" -#: ../regexp.c:2049 ../regexp_nfa.c:1296 #, c-format msgid "E678: Invalid character after %s%%[dxouU]" msgstr "E678: Caractère invalide après %s%%[dxouU]" -#: ../regexp.c:2107 #, c-format msgid "E71: Invalid character after %s%%" msgstr "E71: Caractère invalide après %s%%" -#: ../regexp.c:3017 #, c-format msgid "E554: Syntax error in %s{...}" msgstr "E554: Erreur de syntaxe dans %s{...}" -#: ../regexp.c:3805 msgid "External submatches:\n" msgstr "Sous-correspondances externes :\n" -#: ../regexp.c:7022 +#, c-format +msgid "E888: (NFA regexp) cannot repeat %s" +msgstr "E888: (regexp NFA) %s ne peut pas être répété" + msgid "" "E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be " "used " @@ -5213,63 +5062,56 @@ msgstr "" "E864: \\%#= peut être suivi uniquement de 0, 1 ou 2. Le moteur automatique " "sera utilisé " -#: ../regexp_nfa.c:239 +msgid "Switching to backtracking RE engine for pattern: " +msgstr "Moteur RE avec backtracking utilisé pour le motif : " + msgid "E865: (NFA) Regexp end encountered prematurely" msgstr "E865: (NFA) Fin de regexp rencontrée prématurément" -#: ../regexp_nfa.c:240 #, c-format msgid "E866: (NFA regexp) Misplaced %c" msgstr "E866: (regexp NFA) %c au mauvais endroit" -#: ../regexp_nfa.c:242 -#, fuzzy, c-format -msgid "E877: (NFA regexp) Invalid character class: %<PRId64>" -msgstr "E877: (regexp NFA) Classe de caractère invalide " +#, c-format +msgid "E877: (NFA regexp) Invalid character class: %ld" +msgstr "E877: (regexp NFA) Classe de caractère invalide : %ld" -#: ../regexp_nfa.c:1261 #, c-format msgid "E867: (NFA) Unknown operator '\\z%c'" msgstr "E867: (NFA) Opérateur inconnu '\\z%c'" -#: ../regexp_nfa.c:1387 -#, fuzzy, c-format +#, c-format msgid "E867: (NFA) Unknown operator '\\%%%c'" -msgstr "E867: (NFA) Opérateur inconnu '\\z%c'" +msgstr "E867: (NFA) Opérateur inconnu '\\%%%c'" + +#. should never happen +msgid "E868: Error building NFA with equivalence class!" +msgstr "E868: Erreur lors de la construction du NFA avec classe d'équivalence" -#: ../regexp_nfa.c:1802 #, c-format msgid "E869: (NFA) Unknown operator '\\@%c'" msgstr "E869: (NFA) Opérateur inconnu '\\@%c'" -#: ../regexp_nfa.c:1831 msgid "E870: (NFA regexp) Error reading repetition limits" msgstr "E870: (regexp NFA) Erreur à la lecture des limites de répétition" #. Can't have a multi follow a multi. -#: ../regexp_nfa.c:1895 msgid "E871: (NFA regexp) Can't have a multi follow a multi !" msgstr "E871: (regexp NFA) Un multi ne peut pas suivre un multi !" #. Too many `(' -#: ../regexp_nfa.c:2037 msgid "E872: (NFA regexp) Too many '('" msgstr "E872: (regexp NFA) Trop de '('" -#: ../regexp_nfa.c:2042 -#, fuzzy msgid "E879: (NFA regexp) Too many \\z(" -msgstr "E872: (regexp NFA) Trop de '('" +msgstr "E879: (regexp NFA) Trop de \\z(" -#: ../regexp_nfa.c:2066 msgid "E873: (NFA regexp) proper termination error" msgstr "E873: (NFA regexp) erreur de terminaison" -#: ../regexp_nfa.c:2599 msgid "E874: (NFA) Could not pop the stack !" msgstr "E874: (NFA) Impossible de dépiler !" -#: ../regexp_nfa.c:3298 msgid "" "E875: (NFA regexp) (While converting from postfix to NFA), too many states " "left on stack" @@ -5277,178 +5119,138 @@ msgstr "" "E875: (regexp NFA) (lors de la conversion de postfix à NFA), il reste trop " "d'états sur la pile" -#: ../regexp_nfa.c:3302 msgid "E876: (NFA regexp) Not enough space to store the whole NFA " msgstr "E876: (regexp NFA) Pas assez de mémoire pour stocker le NFA" -#: ../regexp_nfa.c:4571 ../regexp_nfa.c:4869 +msgid "E878: (NFA) Could not allocate memory for branch traversal!" +msgstr "" +"E878: (NFA) Impossible d'allouer la mémoire pour parcourir les branches !" + msgid "" "Could not open temporary log file for writing, displaying on stderr ... " msgstr "" "Impossible d'ouvrir le fichier de log temporaire en écriture, affichage sur " "stderr ... " -#: ../regexp_nfa.c:4840 #, c-format msgid "(NFA) COULD NOT OPEN %s !" msgstr "(NFA) IMPOSSIBLE D'OUVRIR %s !" -#: ../regexp_nfa.c:6049 msgid "Could not open temporary log file for writing " msgstr "Impossible d'ouvrir le fichier de log en écriture" -#: ../screen.c:7435 msgid " VREPLACE" msgstr " VREMPLACEMENT" -#: ../screen.c:7437 msgid " REPLACE" msgstr " REMPLACEMENT" # DB - todo -#: ../screen.c:7440 msgid " REVERSE" msgstr " REVERSE" -#: ../screen.c:7441 msgid " INSERT" msgstr " INSERTION" -#: ../screen.c:7443 msgid " (insert)" msgstr " (insertion)" -#: ../screen.c:7445 msgid " (replace)" msgstr " (remplacement)" -#: ../screen.c:7447 msgid " (vreplace)" msgstr " (vremplacement)" -#: ../screen.c:7449 msgid " Hebrew" msgstr " hébreu" -#: ../screen.c:7454 msgid " Arabic" msgstr " arabe" -#: ../screen.c:7456 -msgid " (lang)" -msgstr " (langue)" - -#: ../screen.c:7459 msgid " (paste)" msgstr " (collage)" -#: ../screen.c:7469 msgid " VISUAL" msgstr " VISUEL" -#: ../screen.c:7470 msgid " VISUAL LINE" msgstr " VISUEL LIGNE" -#: ../screen.c:7471 msgid " VISUAL BLOCK" msgstr " VISUEL BLOC" -#: ../screen.c:7472 msgid " SELECT" msgstr " SÉLECTION" -#: ../screen.c:7473 msgid " SELECT LINE" msgstr " SÉLECTION LIGNE" -#: ../screen.c:7474 msgid " SELECT BLOCK" msgstr " SÉLECTION BLOC" -#: ../screen.c:7486 ../screen.c:7541 msgid "recording" msgstr "Enregistrement" -#: ../search.c:487 #, c-format msgid "E383: Invalid search string: %s" msgstr "E383: Chaîne de recherche invalide : %s" -#: ../search.c:832 #, c-format msgid "E384: search hit TOP without match for: %s" msgstr "E384: la recherche a atteint le HAUT sans trouver : %s" -#: ../search.c:835 #, c-format msgid "E385: search hit BOTTOM without match for: %s" msgstr "E385: la recherche a atteint le BAS sans trouver : %s" -#: ../search.c:1200 msgid "E386: Expected '?' or '/' after ';'" msgstr "E386: '?' ou '/' attendu après ';'" -#: ../search.c:4085 msgid " (includes previously listed match)" msgstr " (inclut des correspondances listées précédemment)" #. cursor at status line -#: ../search.c:4104 msgid "--- Included files " msgstr "--- Fichiers inclus " -#: ../search.c:4106 msgid "not found " msgstr "introuvables " -#: ../search.c:4107 msgid "in path ---\n" msgstr "dans le chemin ---\n" -#: ../search.c:4168 msgid " (Already listed)" msgstr " (Déjà listé)" -#: ../search.c:4170 msgid " NOT FOUND" msgstr " INTROUVABLE" -#: ../search.c:4211 #, c-format msgid "Scanning included file: %s" msgstr "Examen des fichiers inclus : %s" -#: ../search.c:4216 #, c-format msgid "Searching included file %s" msgstr "Recherche du fichier inclus %s" -#: ../search.c:4405 msgid "E387: Match is on current line" msgstr "E387: La correspondance est sur la ligne courante" -#: ../search.c:4517 msgid "All included files were found" msgstr "Tous les fichiers inclus ont été trouvés" -#: ../search.c:4519 msgid "No included files" msgstr "Aucun fichier inclus" -#: ../search.c:4527 msgid "E388: Couldn't find definition" msgstr "E388: Impossible de trouver la définition" -#: ../search.c:4529 msgid "E389: Couldn't find pattern" msgstr "E389: Impossible de trouver le motif" -#: ../search.c:4668 msgid "Substitute " msgstr "Substitue " -#: ../search.c:4681 #, c-format msgid "" "\n" @@ -5459,97 +5261,129 @@ msgstr "" "# Dernier motif de recherche %s :\n" "~" -#: ../spell.c:951 -msgid "E759: Format error in spell file" -msgstr "E759: Erreur de format du fichier orthographique" +msgid "E756: Spell checking is not enabled" +msgstr "E756: La vérification orthographique n'est pas activée" + +#, c-format +msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" +msgstr "Alerte : Liste de mots \"%s_%s.spl\" ou \"%s_ascii.spl\" introuvable" + +#, c-format +msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" +msgstr "Alerte : Liste de mots \"%s.%s.spl\" ou \"%s.ascii.spl\" introuvable" + +msgid "E797: SpellFileMissing autocommand deleted buffer" +msgstr "E797: L'autocommande SpellFileMissing a effacé le tampon" + +#, c-format +msgid "Warning: region %s not supported" +msgstr "Alerte : région %s non supportée" + +msgid "Sorry, no suggestions" +msgstr "Désolé, aucune suggestion" + +#, c-format +msgid "Sorry, only %ld suggestions" +msgstr "Désolé, seulement %ld suggestions" + +#. for when 'cmdheight' > 1 +#. avoid more prompt +#, c-format +msgid "Change \"%.*s\" to:" +msgstr "Remplacer \"%.*s\" par :" + +# DB - todo : l'intérêt de traduire ce message m'échappe. +#, c-format +msgid " < \"%.*s\"" +msgstr " < \"%.*s\"" + +msgid "E752: No previous spell replacement" +msgstr "E752: Pas de suggestion orthographique précédente" + +#, c-format +msgid "E753: Not found: %s" +msgstr "E753: Introuvable : %s" -#: ../spell.c:952 msgid "E758: Truncated spell file" msgstr "E758: Fichier orthographique tronqué" -#: ../spell.c:953 #, c-format msgid "Trailing text in %s line %d: %s" msgstr "Texte en trop dans %s ligne %d : %s" -#: ../spell.c:954 #, c-format msgid "Affix name too long in %s line %d: %s" msgstr "Nom d'affixe trop long dans %s ligne %d : %s" -#: ../spell.c:955 msgid "E761: Format error in affix file FOL, LOW or UPP" msgstr "E761: Erreur de format dans le fichier d'affixe FOL, LOW et UPP" -#: ../spell.c:957 msgid "E762: Character in FOL, LOW or UPP is out of range" msgstr "E762: Un caractère dans FOL, LOW ou UPP est hors-limites" -#: ../spell.c:958 msgid "Compressing word tree..." msgstr "Compression de l'arbre des mots" -#: ../spell.c:1951 -msgid "E756: Spell checking is not enabled" -msgstr "E756: La vérification orthographique n'est pas activée" - -#: ../spell.c:2249 -#, c-format -msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" -msgstr "Alerte : Liste de mots \"%s.%s.spl\" ou \"%s.ascii.spl\" introuvable" - -#: ../spell.c:2473 #, c-format msgid "Reading spell file \"%s\"" msgstr "Lecture du fichier orthographique \"%s\"" -#: ../spell.c:2496 msgid "E757: This does not look like a spell file" msgstr "E757: Le fichier ne ressemble pas à un fichier orthographique" -#: ../spell.c:2501 msgid "E771: Old spell file, needs to be updated" msgstr "E771: Fichier orthographique obsolète, sa mise à jour est nécessaire" -#: ../spell.c:2504 msgid "E772: Spell file is for newer version of Vim" msgstr "E772: Le fichier est prévu pour une version de Vim plus récente" -#: ../spell.c:2602 msgid "E770: Unsupported section in spell file" msgstr "E770: Section non supportée dans le fichier orthographique" -#: ../spell.c:3762 #, c-format -msgid "Warning: region %s not supported" -msgstr "Alerte : région %s non supportée" +msgid "E778: This does not look like a .sug file: %s" +msgstr "E778: %s ne semble pas être un fichier .sug" + +#, c-format +msgid "E779: Old .sug file, needs to be updated: %s" +msgstr "E779: Fichier de suggestions obsolète, mise à jour nécessaire : %s" + +#, c-format +msgid "E780: .sug file is for newer version of Vim: %s" +msgstr "E780: Fichier .sug prévu pour une version de Vim plus récente : %s" + +#, c-format +msgid "E781: .sug file doesn't match .spl file: %s" +msgstr "E781: Le fichier .sug ne correspond pas au fichier .spl : %s" + +#, c-format +msgid "E782: error while reading .sug file: %s" +msgstr "E782: Erreur lors de la lecture de fichier de suggestions : %s" -#: ../spell.c:4550 #, c-format msgid "Reading affix file %s ..." msgstr "Lecture du fichier d'affixes %s..." -#: ../spell.c:4589 ../spell.c:5635 ../spell.c:6140 #, c-format msgid "Conversion failure for word in %s line %d: %s" msgstr "Échec de conversion du mot dans %s ligne %d : %s" -#: ../spell.c:4630 ../spell.c:6170 #, c-format msgid "Conversion in %s not supported: from %s to %s" msgstr "La conversion dans %s non supportée : de %s vers %s" -#: ../spell.c:4642 +#, c-format +msgid "Conversion in %s not supported" +msgstr "La conversion dans %s non supportée" + #, c-format msgid "Invalid value for FLAG in %s line %d: %s" msgstr "Valeur de FLAG invalide dans %s ligne %d : %s" -#: ../spell.c:4655 #, c-format msgid "FLAG after using flags in %s line %d: %s" msgstr "FLAG trouvé après des drapeaux dans %s ligne %d : %s" -#: ../spell.c:4723 #, c-format msgid "" "Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line " @@ -5558,7 +5392,6 @@ msgstr "" "Définir COMPOUNDFORBIDFLAG après des PFX peut donner des résultats erronés " "dans %s ligne %d" -#: ../spell.c:4731 #, c-format msgid "" "Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line " @@ -5567,45 +5400,37 @@ msgstr "" "Définir COMPOUNDPERMITFLAG après des PFX peut donner des résultats erronés " "dans %s ligne %d" -#: ../spell.c:4747 #, c-format msgid "Wrong COMPOUNDRULES value in %s line %d: %s" msgstr "Valeur de COMPOUNDRULES erronée dans %s ligne %d : %s" -#: ../spell.c:4771 #, c-format msgid "Wrong COMPOUNDWORDMAX value in %s line %d: %s" msgstr "Valeur de COMPOUNDWORDMAX erronée dans %s ligne %d : %s" -#: ../spell.c:4777 #, c-format msgid "Wrong COMPOUNDMIN value in %s line %d: %s" msgstr "Valeur de COMPOUNDMIN erronée dans %s ligne %d : %s" -#: ../spell.c:4783 #, c-format msgid "Wrong COMPOUNDSYLMAX value in %s line %d: %s" msgstr "Valeur de COMPOUNDSYLMAX erronée dans %s ligne %d : %s" -#: ../spell.c:4795 #, c-format msgid "Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s" msgstr "Valeur de CHECKCOMPOUNDPATTERN erronée dans %s ligne %d : %s" # DB - TODO -#: ../spell.c:4847 #, c-format msgid "Different combining flag in continued affix block in %s line %d: %s" msgstr "" "Drapeaux de composition différents dans un bloc d'affixes continu dans %s " "ligne %d : %s" -#: ../spell.c:4850 #, c-format msgid "Duplicate affix in %s line %d: %s" msgstr "Affixe dupliqué dans %s ligne %d : %s" -#: ../spell.c:4871 #, c-format msgid "" "Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in %s " @@ -5614,339 +5439,233 @@ msgstr "" "Affixe aussi utilisée pour BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/" "NOSUGGEST dans %s ligne %d : %s" -#: ../spell.c:4893 #, c-format msgid "Expected Y or N in %s line %d: %s" msgstr "Y ou N attendu dans %s ligne %d : %s" # DB - todo (regexp impossible à compiler...) -#: ../spell.c:4968 #, c-format msgid "Broken condition in %s line %d: %s" msgstr "Condition non valide dans %s ligne %d : %s" -#: ../spell.c:5091 #, c-format msgid "Expected REP(SAL) count in %s line %d" msgstr "Nombre de REP(SAL) attendu dans %s ligne %d" -#: ../spell.c:5120 #, c-format msgid "Expected MAP count in %s line %d" msgstr "Nombre de MAP attendu dans %s ligne %d" -#: ../spell.c:5132 #, c-format msgid "Duplicate character in MAP in %s line %d" msgstr "Caractère dupliqué dans MAP dans %s ligne %d" -#: ../spell.c:5176 #, c-format msgid "Unrecognized or duplicate item in %s line %d: %s" msgstr "Élément non reconnu ou dupliqué dans %s ligne %d : %s" -#: ../spell.c:5197 #, c-format msgid "Missing FOL/LOW/UPP line in %s" msgstr "Ligne FOL/LOW/UPP manquante dans %s" -#: ../spell.c:5220 msgid "COMPOUNDSYLMAX used without SYLLABLE" msgstr "Utilisation de COMPOUNDSYLMAX sans SYLLABLE" -#: ../spell.c:5236 msgid "Too many postponed prefixes" msgstr "Trop de préfixes reportés (PFXPOSTPONE)" -#: ../spell.c:5238 msgid "Too many compound flags" msgstr "Trop de drapeaux de composition" -#: ../spell.c:5240 msgid "Too many postponed prefixes and/or compound flags" msgstr "Trop de préfixes reportés et/ou de drapeaux de composition" -#: ../spell.c:5250 #, c-format msgid "Missing SOFO%s line in %s" msgstr "Ligne SOFO%s manquante dans %s" -#: ../spell.c:5253 #, c-format msgid "Both SAL and SOFO lines in %s" msgstr "Lignes SAL et lignes SOFO présentes dans %s" -#: ../spell.c:5331 #, c-format msgid "Flag is not a number in %s line %d: %s" msgstr "Le drapeau n'est pas un nombre dans %s ligne %d : %s" -#: ../spell.c:5334 #, c-format msgid "Illegal flag in %s line %d: %s" msgstr "Drapeau non autorisé dans %s ligne %d : %s" -#: ../spell.c:5493 ../spell.c:5501 #, c-format msgid "%s value differs from what is used in another .aff file" msgstr "La valeur de %s est différente de celle d'un autre fichier .aff" -#: ../spell.c:5602 #, c-format msgid "Reading dictionary file %s ..." msgstr "Lecture du fichier orthographique %s..." -#: ../spell.c:5611 #, c-format msgid "E760: No word count in %s" msgstr "E760: Nombre de mots non indiqué dans %s" -#: ../spell.c:5669 #, c-format msgid "line %6d, word %6d - %s" msgstr "ligne %6d, mot %6d - %s" -#: ../spell.c:5691 #, c-format msgid "Duplicate word in %s line %d: %s" msgstr "Mot dupliqué dans %s ligne %d : %s" -#: ../spell.c:5694 #, c-format msgid "First duplicate word in %s line %d: %s" msgstr "Premier mot dupliqué dans %s ligne %d : %s" -#: ../spell.c:5746 #, c-format msgid "%d duplicate word(s) in %s" msgstr "%d mot(s) dupliqué(s) dans %s" -#: ../spell.c:5748 #, c-format msgid "Ignored %d word(s) with non-ASCII characters in %s" msgstr "%d mot(s) ignoré(s) avec des caractères non-ASCII dans %s" -#: ../spell.c:6115 #, c-format msgid "Reading word file %s ..." msgstr "Lecture de la liste de mots %s..." -#: ../spell.c:6155 #, c-format msgid "Duplicate /encoding= line ignored in %s line %d: %s" msgstr "Ligne /encoding= en double ignorée dans %s ligne %d : %s" -#: ../spell.c:6159 #, c-format msgid "/encoding= line after word ignored in %s line %d: %s" msgstr "Ligne /encoding= après des mots ignorée dans %s ligne %d : %s" -#: ../spell.c:6180 #, c-format msgid "Duplicate /regions= line ignored in %s line %d: %s" msgstr "Ligne /regions= en double ignorée dans %s ligne %d : %s" -#: ../spell.c:6185 #, c-format msgid "Too many regions in %s line %d: %s" msgstr "Trop de régions dans %s ligne %d : %s" -#: ../spell.c:6198 #, c-format msgid "/ line ignored in %s line %d: %s" msgstr "Ligne / ignorée dans %s ligne %d : %s" -#: ../spell.c:6224 #, c-format msgid "Invalid region nr in %s line %d: %s" msgstr "Numéro de région invalide dans %s ligne %d : %s" -#: ../spell.c:6230 #, c-format msgid "Unrecognized flags in %s line %d: %s" msgstr "Drapeaux non reconnus dans %s ligne %d : %s" -#: ../spell.c:6257 #, c-format msgid "Ignored %d words with non-ASCII characters" msgstr "%d mot(s) ignoré(s) avec des caractères non-ASCII" -#: ../spell.c:6656 +msgid "E845: Insufficient memory, word list will be incomplete" +msgstr "E845: mémoire insuffisante, liste de mots peut-être incomplète" + #, c-format msgid "Compressed %d of %d nodes; %d (%d%%) remaining" msgstr "%d noeuds compressés sur %d ; %d (%d%%) restants " -#: ../spell.c:7340 msgid "Reading back spell file..." msgstr "Relecture du fichier orthographique" -#. Go through the trie of good words, soundfold each word and add it to -#. the soundfold trie. -#: ../spell.c:7357 +#. +#. * Go through the trie of good words, soundfold each word and add it to +#. * the soundfold trie. +#. msgid "Performing soundfolding..." msgstr "Analyse phonétique en cours..." -#: ../spell.c:7368 #, c-format -msgid "Number of words after soundfolding: %<PRId64>" -msgstr "Nombre de mots après l'analyse phonétique : %<PRId64>" +msgid "Number of words after soundfolding: %ld" +msgstr "Nombre de mots après l'analyse phonétique : %ld" -#: ../spell.c:7476 #, c-format msgid "Total number of words: %d" msgstr "Nombre total de mots : %d" -#: ../spell.c:7655 #, c-format msgid "Writing suggestion file %s ..." msgstr "Écriture du fichier de suggestions %s..." -#: ../spell.c:7707 ../spell.c:7927 #, c-format msgid "Estimated runtime memory use: %d bytes" msgstr "Estimation de mémoire consommée : %d octets" -#: ../spell.c:7820 msgid "E751: Output file name must not have region name" msgstr "E751: Le nom du fichier ne doit pas contenir de nom de région" -#: ../spell.c:7822 msgid "E754: Only up to 8 regions supported" msgstr "E754: 8 régions au maximum sont supportées" -#: ../spell.c:7846 #, c-format msgid "E755: Invalid region in %s" msgstr "E755: Région invalide dans %s" -#: ../spell.c:7907 msgid "Warning: both compounding and NOBREAK specified" msgstr "Alerte : la composition et NOBREAK sont tous les deux spécifiés" -#: ../spell.c:7920 #, c-format msgid "Writing spell file %s ..." msgstr "Écriture du fichier orthographique %s..." -#: ../spell.c:7925 msgid "Done!" msgstr "Terminé !" # DB - todo : perfectible. -#: ../spell.c:8034 #, c-format -msgid "E765: 'spellfile' does not have %<PRId64> entries" -msgstr "E765: 'spellfile' n'a pas %<PRId64> entrées" +msgid "E765: 'spellfile' does not have %ld entries" +msgstr "E765: 'spellfile' n'a pas %ld entrées" -#: ../spell.c:8074 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' removed from %s" -msgstr "Mot retiré de %s" +msgstr "Mot '%.*s' retiré de %s" -#: ../spell.c:8117 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' added to %s" -msgstr "Mot ajouté dans %s" +msgstr "Mot '%.*s' ajouté dans %s" -#: ../spell.c:8381 msgid "E763: Word characters differ between spell files" msgstr "" "E763: Les caractères de mots diffèrent entre les fichiers orthographiques" -#: ../spell.c:8684 -msgid "Sorry, no suggestions" -msgstr "Désolé, aucune suggestion" - -#: ../spell.c:8687 -#, c-format -msgid "Sorry, only %<PRId64> suggestions" -msgstr "Désolé, seulement %<PRId64> suggestions" - -#. for when 'cmdheight' > 1 -#. avoid more prompt -#: ../spell.c:8704 -#, c-format -msgid "Change \"%.*s\" to:" -msgstr "Remplacer \"%.*s\" par :" - -# DB - todo : l'intérêt de traduire ce message m'échappe. -#: ../spell.c:8737 -#, c-format -msgid " < \"%.*s\"" -msgstr " < \"%.*s\"" - -#: ../spell.c:8882 -msgid "E752: No previous spell replacement" -msgstr "E752: Pas de suggestion orthographique précédente" - -#: ../spell.c:8925 -#, c-format -msgid "E753: Not found: %s" -msgstr "E753: Introuvable : %s" - -#: ../spell.c:9276 -#, c-format -msgid "E778: This does not look like a .sug file: %s" -msgstr "E778: %s ne semble pas être un fichier .sug" - -#: ../spell.c:9282 -#, c-format -msgid "E779: Old .sug file, needs to be updated: %s" -msgstr "E779: Fichier de suggestions obsolète, mise à jour nécessaire : %s" - -#: ../spell.c:9286 -#, c-format -msgid "E780: .sug file is for newer version of Vim: %s" -msgstr "E780: Fichier .sug prévu pour une version de Vim plus récente : %s" - -#: ../spell.c:9295 -#, c-format -msgid "E781: .sug file doesn't match .spl file: %s" -msgstr "E781: Le fichier .sug ne correspond pas au fichier .spl : %s" - -#: ../spell.c:9305 -#, c-format -msgid "E782: error while reading .sug file: %s" -msgstr "E782: Erreur lors de la lecture de fichier de suggestions : %s" - #. This should have been checked when generating the .spl -#. file. -#: ../spell.c:11575 +#. * file. msgid "E783: duplicate char in MAP entry" -msgstr "E783: caractères dupliqué dans l'entrée MAP" +msgstr "E783: caractère dupliqué dans l'entrée MAP" -#: ../syntax.c:266 msgid "No Syntax items defined for this buffer" msgstr "Aucun élément de syntaxe défini pour ce tampon" -#: ../syntax.c:3083 ../syntax.c:3104 ../syntax.c:3127 #, c-format msgid "E390: Illegal argument: %s" msgstr "E390: Argument invalide : %s" -#: ../syntax.c:3299 +msgid "syntax iskeyword " +msgstr "syntaxe iskeyword " + #, c-format msgid "E391: No such syntax cluster: %s" msgstr "E391: Aucune grappe de syntaxe %s" -#: ../syntax.c:3433 msgid "syncing on C-style comments" msgstr "synchronisation sur les commentaires de type C" -#: ../syntax.c:3439 msgid "no syncing" msgstr "Aucune synchronisation" # DB - Les deux messages qui suivent vont ensemble. -#: ../syntax.c:3441 msgid "syncing starts " msgstr "La synchronisation débute " -#: ../syntax.c:3443 ../syntax.c:3506 msgid " lines before top line" msgstr " lignes avant la ligne du haut" -#: ../syntax.c:3448 msgid "" "\n" "--- Syntax sync items ---" @@ -5954,7 +5673,6 @@ msgstr "" "\n" "--- Éléments de synchronisation syntaxique ---" -#: ../syntax.c:3452 msgid "" "\n" "syncing on items" @@ -5962,7 +5680,6 @@ msgstr "" "\n" "synchronisation sur éléments" -#: ../syntax.c:3457 msgid "" "\n" "--- Syntax items ---" @@ -5970,275 +5687,220 @@ msgstr "" "\n" "--- Éléments de syntaxe ---" -#: ../syntax.c:3475 #, c-format msgid "E392: No such syntax cluster: %s" msgstr "E392: Aucune grappe de syntaxe %s" -#: ../syntax.c:3497 msgid "minimal " msgstr "minimum " -#: ../syntax.c:3503 msgid "maximal " msgstr "maximum " # DB - todo -#: ../syntax.c:3513 msgid "; match " msgstr "; correspond avec " # DB - todo -#: ../syntax.c:3515 msgid " line breaks" msgstr " coupures de ligne" -#: ../syntax.c:4076 msgid "E395: contains argument not accepted here" msgstr "E395: L'argument « contains » n'est pas accepté ici" -#: ../syntax.c:4096 msgid "E844: invalid cchar value" msgstr "E844: valeur de cchar invalide" -#: ../syntax.c:4107 msgid "E393: group[t]here not accepted here" msgstr "E393: L'argument « group[t]here » n'est pas accepté ici" -#: ../syntax.c:4126 #, c-format msgid "E394: Didn't find region item for %s" msgstr "E394: Aucun élément de type région trouvé pour %s" -#: ../syntax.c:4188 msgid "E397: Filename required" msgstr "E397: Nom de fichier requis" -#: ../syntax.c:4221 msgid "E847: Too many syntax includes" msgstr "E847: Trop d'inclusions de syntaxe" -#: ../syntax.c:4303 #, c-format msgid "E789: Missing ']': %s" msgstr "E789: ']' manquant : %s" -#: ../syntax.c:4531 +#, c-format +msgid "E890: trailing char after ']': %s]%s" +msgstr "E890: Caractère surnuméraire après ']': %s]%s" + #, c-format msgid "E398: Missing '=': %s" msgstr "E398: '=' manquant : %s" -#: ../syntax.c:4666 #, c-format msgid "E399: Not enough arguments: syntax region %s" msgstr "E399: Pas assez d'arguments : syntax region %s" -#: ../syntax.c:4870 msgid "E848: Too many syntax clusters" msgstr "E848: Trop de grappes de syntaxe" -#: ../syntax.c:4954 msgid "E400: No cluster specified" msgstr "E400: Aucune grappe spécifiée" -#. end delimiter not found -#: ../syntax.c:4986 #, c-format msgid "E401: Pattern delimiter not found: %s" msgstr "E401: Délimiteur de motif introuvable : %s" -#: ../syntax.c:5049 #, c-format msgid "E402: Garbage after pattern: %s" msgstr "E402: caractères en trop après le motif : %s" -#: ../syntax.c:5120 msgid "E403: syntax sync: line continuations pattern specified twice" msgstr "" "E403: synchro syntax : motif de continuation de ligne présent deux fois" -#: ../syntax.c:5169 #, c-format msgid "E404: Illegal arguments: %s" msgstr "E404: Arguments invalides : %s" -#: ../syntax.c:5217 #, c-format msgid "E405: Missing equal sign: %s" msgstr "E405: '=' manquant : %s" -#: ../syntax.c:5222 #, c-format msgid "E406: Empty argument: %s" msgstr "E406: Argument vide : %s" -#: ../syntax.c:5240 #, c-format msgid "E407: %s not allowed here" msgstr "E407: %s n'est pas autorisé ici" -#: ../syntax.c:5246 #, c-format msgid "E408: %s must be first in contains list" msgstr "E408: %s doit être le premier élément d'une liste « contains »" -#: ../syntax.c:5304 #, c-format msgid "E409: Unknown group name: %s" msgstr "E409: Nom de groupe inconnu : %s" -#: ../syntax.c:5512 #, c-format msgid "E410: Invalid :syntax subcommand: %s" msgstr "E410: Sous-commande de :syntax invalide : %s" -#: ../syntax.c:5854 msgid "" " TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN" msgstr "" +" TOTAL NOMBRE MATCH PLUS LENT MOYEN NOM MOTIF" -#: ../syntax.c:6146 msgid "E679: recursive loop loading syncolor.vim" msgstr "E679: boucle récursive lors du chargement de syncolor.vim" -#: ../syntax.c:6256 #, c-format msgid "E411: highlight group not found: %s" msgstr "E411: groupe de surbrillance introuvable : %s" -#: ../syntax.c:6278 #, c-format msgid "E412: Not enough arguments: \":highlight link %s\"" msgstr "E412: Trop peu d'arguments : \":highlight link %s\"" -#: ../syntax.c:6284 #, c-format msgid "E413: Too many arguments: \":highlight link %s\"" msgstr "E413: Trop d'arguments : \":highlight link %s\"" -#: ../syntax.c:6302 msgid "E414: group has settings, highlight link ignored" msgstr "E414: le groupe a déjà des attributs, lien de surbrillance ignoré" -#: ../syntax.c:6367 #, c-format msgid "E415: unexpected equal sign: %s" msgstr "E415: signe égal inattendu : %s" -#: ../syntax.c:6395 #, c-format msgid "E416: missing equal sign: %s" msgstr "E416: '=' manquant : %s" -#: ../syntax.c:6418 #, c-format msgid "E417: missing argument: %s" msgstr "E417: argument manquant : %s" -#: ../syntax.c:6446 #, c-format msgid "E418: Illegal value: %s" msgstr "E418: Valeur invalide : %s" -#: ../syntax.c:6496 msgid "E419: FG color unknown" msgstr "E419: Couleur de premier plan inconnue" -#: ../syntax.c:6504 msgid "E420: BG color unknown" msgstr "E420: Couleur d'arrière-plan inconnue" -#: ../syntax.c:6564 #, c-format msgid "E421: Color name or number not recognized: %s" msgstr "E421: Nom ou numéro de couleur non reconnu : %s" -#: ../syntax.c:6714 #, c-format msgid "E422: terminal code too long: %s" msgstr "E422: le code de terminal est trop long : %s" -#: ../syntax.c:6753 #, c-format msgid "E423: Illegal argument: %s" msgstr "E423: Argument invalide : %s" -#: ../syntax.c:6925 msgid "E424: Too many different highlighting attributes in use" msgstr "" "E424: Trop d'attributs de surbrillance différents en cours d'utilisation" -#: ../syntax.c:7427 msgid "E669: Unprintable character in group name" msgstr "E669: Caractère non-imprimable dans un nom de groupe" -#: ../syntax.c:7434 msgid "W18: Invalid character in group name" msgstr "W18: Caractère invalide dans un nom de groupe" -#: ../syntax.c:7448 msgid "E849: Too many highlight and syntax groups" msgstr "E849: Trop de groupes de surbrillance et de syntaxe" -#: ../tag.c:104 msgid "E555: at bottom of tag stack" msgstr "E555: En bas de la pile de marqueurs" -#: ../tag.c:105 msgid "E556: at top of tag stack" msgstr "E556: Au sommet de la pile de marqueurs" -#: ../tag.c:380 msgid "E425: Cannot go before first matching tag" msgstr "E425: Impossible d'aller avant le premier marqueur correspondant" -#: ../tag.c:504 #, c-format msgid "E426: tag not found: %s" msgstr "E426: Marqueur introuvable : %s" -#: ../tag.c:528 msgid " # pri kind tag" msgstr " # pri type marqueur" -#: ../tag.c:531 msgid "file\n" msgstr "fichier\n" -#: ../tag.c:829 msgid "E427: There is only one matching tag" msgstr "E427: Il n'y a qu'un marqueur correspondant" -#: ../tag.c:831 msgid "E428: Cannot go beyond last matching tag" msgstr "E428: Impossible d'aller au-delà du dernier marqueur correspondant" -#: ../tag.c:850 #, c-format msgid "File \"%s\" does not exist" msgstr "Le fichier \"%s\" n'existe pas" #. Give an indication of the number of matching tags -#: ../tag.c:859 #, c-format msgid "tag %d of %d%s" msgstr "marqueur %d sur %d%s" -#: ../tag.c:862 msgid " or more" msgstr " ou plus" -#: ../tag.c:864 msgid " Using tag with different case!" msgstr " Utilisation d'un marqueur avec une casse différente !" -#: ../tag.c:909 #, c-format msgid "E429: File \"%s\" does not exist" msgstr "E429: Le fichier \"%s\" n'existe pas" #. Highlight title -#: ../tag.c:960 msgid "" "\n" " # TO tag FROM line in file/text" @@ -6246,80 +5908,67 @@ msgstr "" "\n" " # VERS marqueur DE ligne dans le fichier/texte" -#: ../tag.c:1303 #, c-format msgid "Searching tags file %s" msgstr "Examen du fichier de marqueurs %s" -#: ../tag.c:1545 +#, c-format +msgid "E430: Tag file path truncated for %s\n" +msgstr "E430: Chemin de fichiers de marqueurs tronqué pour %s\n" + msgid "Ignoring long line in tags file" msgstr "Ignore longue ligne dans le fichier de marqueurs" -#: ../tag.c:1915 #, c-format msgid "E431: Format error in tags file \"%s\"" msgstr "E431: Erreur de format dans le fichier de marqueurs \"%s\"" -#: ../tag.c:1917 #, c-format -msgid "Before byte %<PRId64>" -msgstr "Avant l'octet %<PRId64>" +msgid "Before byte %ld" +msgstr "Avant l'octet %ld" -#: ../tag.c:1929 #, c-format msgid "E432: Tags file not sorted: %s" msgstr "E432: Le fichier de marqueurs %s n'est pas ordonné" #. never opened any tags file -#: ../tag.c:1960 msgid "E433: No tags file" msgstr "E433: Aucun fichier de marqueurs" -#: ../tag.c:2536 msgid "E434: Can't find tag pattern" msgstr "E434: Le motif de marqueur est introuvable" -#: ../tag.c:2544 msgid "E435: Couldn't find tag, just guessing!" msgstr "E435: Marqueur introuvable, tentative pour deviner !" -#: ../tag.c:2797 #, c-format msgid "Duplicate field name: %s" msgstr "Nom de champ dupliqué : %s" -#: ../term.c:1442 msgid "' not known. Available builtin terminals are:" msgstr "' inconnu. Les terminaux intégrés sont :" -#: ../term.c:1463 msgid "defaulting to '" msgstr "utilisation par défaut de '" -#: ../term.c:1731 msgid "E557: Cannot open termcap file" msgstr "E557: Impossible d'ouvrir le fichier termcap" -#: ../term.c:1735 msgid "E558: Terminal entry not found in terminfo" msgstr "E558: La description du terminal est introuvable dans terminfo" -#: ../term.c:1737 msgid "E559: Terminal entry not found in termcap" msgstr "E559: La description du terminal est introuvable dans termcap" -#: ../term.c:1878 #, c-format msgid "E436: No \"%s\" entry in termcap" msgstr "E436: Aucune entrée \"%s\" dans termcap" # DB - todo : Comment améliorer ? -#: ../term.c:2249 msgid "E437: terminal capability \"cm\" required" msgstr "E437: capacité de terminal \"cm\" requise" #. Highlight title -#: ../term.c:4376 msgid "" "\n" "--- Terminal keys ---" @@ -6327,174 +5976,365 @@ msgstr "" "\n" "--- Touches du terminal ---" -#: ../ui.c:481 +msgid "Cannot open $VIMRUNTIME/rgb.txt" +msgstr "Impossible d'ouvrir $VIMRUNTIME/rgb.txt" + +msgid "new shell started\n" +msgstr "nouveau shell démarré\n" + msgid "Vim: Error reading input, exiting...\n" msgstr "Vim : Erreur lors de la lecture de l'entrée, sortie...\n" +# DB - Message de débogage. +msgid "Used CUT_BUFFER0 instead of empty selection" +msgstr "CUT_BUFFER0 utilisé plutôt qu'une sélection vide" + #. This happens when the FileChangedRO autocommand changes the #. * file in a way it becomes shorter. -#: ../undo.c:379 -#, fuzzy msgid "E881: Line count changed unexpectedly" -msgstr "E834: Le nombre de lignes a été changé inopinément" +msgstr "E881: Le nombre de lignes a été changé inopinément" + +# DB - Question O/N. +#. must display the prompt +msgid "No undo possible; continue anyway" +msgstr "Annulation impossible ; continuer" -#: ../undo.c:627 #, c-format msgid "E828: Cannot open undo file for writing: %s" msgstr "E828: Impossible d'ouvrir le fichier d'annulations en écriture : %s" -#: ../undo.c:717 #, c-format msgid "E825: Corrupted undo file (%s): %s" msgstr "E825: Fichier d'annulations corrompu (%s) : %s" -#: ../undo.c:1039 msgid "Cannot write undo file in any directory in 'undodir'" msgstr "" "Impossible d'écrire le fichier d'annulations dans n'importe quel répertoire " "de 'undodir'" -#: ../undo.c:1074 #, c-format msgid "Will not overwrite with undo file, cannot read: %s" msgstr "Le fichier d'annulations ne sera pas écrasé, impossible de lire : %s" -#: ../undo.c:1092 #, c-format msgid "Will not overwrite, this is not an undo file: %s" msgstr "Fichier ne sera pas écrasé, ce n'est pas un fichier d'annulations : %s" -#: ../undo.c:1108 msgid "Skipping undo file write, nothing to undo" msgstr "Le fichier d'annulations n'est pas écrit, rien à annuler" -#: ../undo.c:1121 #, c-format msgid "Writing undo file: %s" msgstr "Écriture du fichier d'annulations : %s" -#: ../undo.c:1213 #, c-format msgid "E829: write error in undo file: %s" msgstr "E829: Erreur d'écriture dans le fichier d'annulations : %s" -#: ../undo.c:1280 #, c-format msgid "Not reading undo file, owner differs: %s" msgstr "Le fichier d'annulations n'est pas lu, propriétaire différent : %s" -#: ../undo.c:1292 #, c-format msgid "Reading undo file: %s" msgstr "Lecture du fichier d'annulations : %s..." -#: ../undo.c:1299 #, c-format msgid "E822: Cannot open undo file for reading: %s" msgstr "E822: Impossible d'ouvrir le fichier d'annulations en lecture : %s" -#: ../undo.c:1308 #, c-format msgid "E823: Not an undo file: %s" msgstr "E823: Ce n'est pas un fichier d'annulations : %s" -#: ../undo.c:1313 +#, c-format +msgid "E832: Non-encrypted file has encrypted undo file: %s" +msgstr "E832: Fichier non-chiffré a un fichier d'annulations chiffré : %s" + +#, c-format +msgid "E826: Undo file decryption failed: %s" +msgstr "E826: Déchiffrage du fichier d'annulation a échoué : %s" + +#, c-format +msgid "E827: Undo file is encrypted: %s" +msgstr "E827: Le fichier d'annulations est chiffré : %s" + #, c-format msgid "E824: Incompatible undo file: %s" msgstr "E824: Fichier d'annulations incompatible : %s" -#: ../undo.c:1328 msgid "File contents changed, cannot use undo info" msgstr "" "Le contenu du fichier a changé, impossible d'utiliser les informations " "d'annulation" -#: ../undo.c:1497 #, c-format msgid "Finished reading undo file %s" msgstr "Fin de lecture du fichier d'annulations %s" -#: ../undo.c:1586 ../undo.c:1812 msgid "Already at oldest change" msgstr "Déjà à la modification la plus ancienne" -#: ../undo.c:1597 ../undo.c:1814 msgid "Already at newest change" msgstr "Déjà à la modification la plus récente" -#: ../undo.c:1806 #, c-format -msgid "E830: Undo number %<PRId64> not found" -msgstr "E830: Annulation n° %<PRId64> introuvable" +msgid "E830: Undo number %ld not found" +msgstr "E830: Annulation n° %ld introuvable" -#: ../undo.c:1979 msgid "E438: u_undo: line numbers wrong" msgstr "E438: u_undo : numéros de ligne erronés" -#: ../undo.c:2183 msgid "more line" msgstr "ligne en plus" -#: ../undo.c:2185 msgid "more lines" msgstr "lignes en plus" -#: ../undo.c:2187 msgid "line less" msgstr "ligne en moins" -#: ../undo.c:2189 msgid "fewer lines" msgstr "lignes en moins" -#: ../undo.c:2193 msgid "change" msgstr "modification" -#: ../undo.c:2195 msgid "changes" msgstr "modifications" -#: ../undo.c:2225 #, c-format -msgid "%<PRId64> %s; %s #%<PRId64> %s" -msgstr "%<PRId64> %s ; %s #%<PRId64> ; %s" +msgid "%ld %s; %s #%ld %s" +msgstr "%ld %s ; %s #%ld ; %s" -#: ../undo.c:2228 msgid "before" msgstr "avant" -#: ../undo.c:2228 msgid "after" msgstr "après" -#: ../undo.c:2325 msgid "Nothing to undo" msgstr "Rien à annuler" # DB - Les deux premières colonnes sont alignées à droite. -#: ../undo.c:2330 msgid "number changes when saved" msgstr "numéro modif. instant enregistré" -#: ../undo.c:2360 #, c-format -msgid "%<PRId64> seconds ago" -msgstr "il y a %<PRId64> secondes" +msgid "%ld seconds ago" +msgstr "il y a %ld secondes" -#: ../undo.c:2372 msgid "E790: undojoin is not allowed after undo" msgstr "E790: undojoin n'est pas autorisé après une annulation" -#: ../undo.c:2466 msgid "E439: undo list corrupt" msgstr "E439: la liste d'annulation est corrompue" -#: ../undo.c:2495 msgid "E440: undo line missing" msgstr "E440: ligne d'annulation manquante" -#: ../version.c:600 +#, c-format +msgid "E122: Function %s already exists, add ! to replace it" +msgstr "E122: La fonction %s existe déjà (ajoutez ! pour la remplacer)" + +msgid "E717: Dictionary entry already exists" +msgstr "E717: Une entrée du Dictionnaire porte déjà ce nom" + +msgid "E718: Funcref required" +msgstr "E718: Référence de fonction (Funcref) requise" + +#, c-format +msgid "E130: Unknown function: %s" +msgstr "E130: Fonction inconnue : %s" + +#, c-format +msgid "E125: Illegal argument: %s" +msgstr "E125: Argument invalide : %s" + +#, c-format +msgid "E853: Duplicate argument name: %s" +msgstr "E853: Nom d'argument dupliqué : %s" + +#, c-format +msgid "E740: Too many arguments for function %s" +msgstr "E740: Trop d'arguments pour la fonction %s" + +#, c-format +msgid "E116: Invalid arguments for function %s" +msgstr "E116: Arguments invalides pour la fonction %s" + +# AB - Vérifier dans la littérature technique s'il n'existe pas une meilleure +# traduction pour "function call depth". +msgid "E132: Function call depth is higher than 'maxfuncdepth'" +msgstr "" +"E132: La profondeur d'appel de fonction est supérieure à 'maxfuncdepth'" + +# AB - Ce texte fait partie d'un message de débogage. +#, c-format +msgid "calling %s" +msgstr "appel de %s" + +# AB - Vérifier. +#, c-format +msgid "%s aborted" +msgstr "%s annulée" + +# AB - Ce texte fait partie d'un message de débogage. +#, c-format +msgid "%s returning #%ld" +msgstr "%s a retourné #%ld" + +# AB - Ce texte fait partie d'un message de débogage. +#, c-format +msgid "%s returning %s" +msgstr "%s a retourné \"%s\"" + +msgid "E699: Too many arguments" +msgstr "E699: Trop d'arguments" + +#, c-format +msgid "E117: Unknown function: %s" +msgstr "E117: Fonction inconnue : %s" + +#, c-format +msgid "E933: Function was deleted: %s" +msgstr "E933: La fonction a été effacée: %s" + +#, c-format +msgid "E119: Not enough arguments for function: %s" +msgstr "E119: La fonction %s n'a pas reçu assez d'arguments" + +#, c-format +msgid "E120: Using <SID> not in a script context: %s" +msgstr "E120: <SID> utilisé en dehors d'un script : %s" + +#, c-format +msgid "E725: Calling dict function without Dictionary: %s" +msgstr "E725: Appel d'une fonction « dict » sans Dictionnaire : %s" + +msgid "E129: Function name required" +msgstr "E129: Nom de fonction requis" + +#, c-format +msgid "E128: Function name must start with a capital or \"s:\": %s" +msgstr "" +"E128: Le nom de la fonction doit commencer par une majuscule ou \"s:\": %s" + +#, c-format +msgid "E884: Function name cannot contain a colon: %s" +msgstr "" +"E884: Le nom de la fonction ne peut pas contenir le caractère deux-points : " +"%s" + +#, c-format +msgid "E123: Undefined function: %s" +msgstr "E123: Fonction non définie : %s" + +# AB - La version française est plus consistante que la version anglaise. +# AB - Je suis partagé entre la concision d'une traduction assez littérale et +# la lourdeur d'une traduction plus correcte. +#, c-format +msgid "E124: Missing '(': %s" +msgstr "E124: Il manque '(' après %s" + +msgid "E862: Cannot use g: here" +msgstr "E862: Impossible d'utiliser g: ici" + +#, c-format +msgid "E932: Closure function should not be at top level: %s" +msgstr "" +"E932: une fonction fermeture ne devrait pas être au niveau principal : %s" + +msgid "E126: Missing :endfunction" +msgstr "E126: Il manque :endfunction" + +#, c-format +msgid "E707: Function name conflicts with variable: %s" +msgstr "E707: Le nom de fonction entre en conflit avec la variable : %s" + +#, c-format +msgid "E127: Cannot redefine function %s: It is in use" +msgstr "E127: Impossible de redéfinir fonction %s : déjà utilisée" + +# DB - Le contenu du "c-format" est le nom de la fonction. +#, c-format +msgid "E746: Function name does not match script file name: %s" +msgstr "E746: Le nom de la fonction %s ne correspond pas le nom du script" + +# AB - Il est difficile de créer une version française qui fasse moins de 80 +# caractères de long, nom de la fonction compris : "It is in use" est une +# expression très dense. Traductions possibles : "elle est utilisée", +# "elle s'exécute" ou "elle est occupée". +#, c-format +msgid "E131: Cannot delete function %s: It is in use" +msgstr "E131: Impossible d'effacer %s : cette fonction est utilisée" + +msgid "E133: :return not inside a function" +msgstr "E133: :return en dehors d'une fonction" + +#, c-format +msgid "E107: Missing parentheses: %s" +msgstr "E107: Parenthèses manquantes : %s" + +msgid "" +"\n" +"MS-Windows 64-bit GUI version" +msgstr "" +"\n" +"Version graphique MS-Windows 64 bits" + +msgid "" +"\n" +"MS-Windows 32-bit GUI version" +msgstr "" +"\n" +"Version graphique MS-Windows 32 bits" + +msgid " with OLE support" +msgstr " supportant l'OLE" + +msgid "" +"\n" +"MS-Windows 64-bit console version" +msgstr "" +"\n" +"Version console MS-Windows 64 bits" + +msgid "" +"\n" +"MS-Windows 32-bit console version" +msgstr "" +"\n" +"Version console MS-Windows 32 bits" + +msgid "" +"\n" +"MacOS X (unix) version" +msgstr "" +"\n" +"Version MaxOS X (unix)" + +msgid "" +"\n" +"MacOS X version" +msgstr "" +"\n" +"Version MacOS X" + +msgid "" +"\n" +"MacOS version" +msgstr "" +"\n" +"Version MacOS" + +msgid "" +"\n" +"OpenVMS version" +msgstr "" +"\n" +"Version OpenVMS" + msgid "" "\n" "Included patches: " @@ -6502,7 +6342,6 @@ msgstr "" "\n" "Rustines incluses : " -#: ../version.c:627 msgid "" "\n" "Extra patches: " @@ -6510,11 +6349,9 @@ msgstr "" "\n" "Rustines extra : " -#: ../version.c:639 ../version.c:864 msgid "Modified by " msgstr "Modifié par " -#: ../version.c:646 msgid "" "\n" "Compiled " @@ -6522,11 +6359,9 @@ msgstr "" "\n" "Compilé " -#: ../version.c:649 msgid "by " msgstr "par " -#: ../version.c:660 msgid "" "\n" "Huge version " @@ -6534,1872 +6369,949 @@ msgstr "" "\n" "Énorme version " -#: ../version.c:661 +msgid "" +"\n" +"Big version " +msgstr "" +"\n" +"Grosse version " + +msgid "" +"\n" +"Normal version " +msgstr "" +"\n" +"Version normale " + +msgid "" +"\n" +"Small version " +msgstr "" +"\n" +"Petite version " + +msgid "" +"\n" +"Tiny version " +msgstr "" +"\n" +"Version minuscule " + msgid "without GUI." msgstr "sans interface graphique." -#: ../version.c:662 +msgid "with GTK3 GUI." +msgstr "avec interface graphique GTK3." + +msgid "with GTK2-GNOME GUI." +msgstr "avec interface graphique GTK2-GNOME." + +msgid "with GTK2 GUI." +msgstr "avec interface graphique GTK2." + +msgid "with X11-Motif GUI." +msgstr "avec interface graphique X11-Motif." + +msgid "with X11-neXtaw GUI." +msgstr "avec interface graphique X11-neXtaw." + +msgid "with X11-Athena GUI." +msgstr "avec interface graphique X11-Athena." + +msgid "with Photon GUI." +msgstr "avec interface graphique Photon." + +msgid "with GUI." +msgstr "avec une interface graphique." + +msgid "with Carbon GUI." +msgstr "avec interface graphique Carbon." + +msgid "with Cocoa GUI." +msgstr "avec interface graphique Cocoa." + +msgid "with (classic) GUI." +msgstr "avec interface graphique (classic)." + msgid " Features included (+) or not (-):\n" msgstr " Fonctionnalités incluses (+) ou non (-) :\n" -#: ../version.c:667 msgid " system vimrc file: \"" msgstr " fichier vimrc système : \"" -#: ../version.c:672 msgid " user vimrc file: \"" msgstr " fichier vimrc utilisateur : \"" -#: ../version.c:677 msgid " 2nd user vimrc file: \"" msgstr " 2me fichier vimrc utilisateur : \"" -#: ../version.c:682 msgid " 3rd user vimrc file: \"" msgstr " 3me fichier vimrc utilisateur : \"" -#: ../version.c:687 msgid " user exrc file: \"" msgstr " fichier exrc utilisateur : \"" -#: ../version.c:692 msgid " 2nd user exrc file: \"" msgstr " 2me fichier exrc utilisateur : \"" -#: ../version.c:699 +msgid " system gvimrc file: \"" +msgstr " fichier gvimrc système : \"" + +msgid " user gvimrc file: \"" +msgstr " fichier gvimrc utilisateur : \"" + +msgid "2nd user gvimrc file: \"" +msgstr "2me fichier gvimrc utilisateur : \"" + +msgid "3rd user gvimrc file: \"" +msgstr "3me fichier gvimrc utilisateur : \"" + +msgid " defaults file: \"" +msgstr " fichier de valeurs par défaut : \"" + +msgid " system menu file: \"" +msgstr " fichier menu système : \"" + msgid " fall-back for $VIM: \"" msgstr " $VIM par défaut : \"" -#: ../version.c:705 msgid " f-b for $VIMRUNTIME: \"" msgstr " $VIMRUNTIME par défaut : \"" -#: ../version.c:709 msgid "Compilation: " msgstr "Compilation : " -#: ../version.c:712 +msgid "Compiler: " +msgstr "Compilateur : " + msgid "Linking: " msgstr "Édition de liens : " -#: ../version.c:717 msgid " DEBUG BUILD" msgstr " VERSION DE DÉBOGAGE" -#: ../version.c:767 msgid "VIM - Vi IMproved" msgstr "VIM - Vi Amélioré" -#: ../version.c:769 msgid "version " msgstr "version " -#: ../version.c:770 msgid "by Bram Moolenaar et al." msgstr "par Bram Moolenaar et al." -#: ../version.c:774 msgid "Vim is open source and freely distributable" msgstr "Vim est un logiciel libre" -#: ../version.c:776 msgid "Help poor children in Uganda!" msgstr "Aidez les enfants pauvres d'Ouganda !" -#: ../version.c:777 msgid "type :help iccf<Enter> for information " msgstr "tapez :help iccf<Entrée> pour plus d'informations " -#: ../version.c:779 msgid "type :q<Enter> to exit " msgstr "tapez :q<Entrée> pour sortir du programme " -#: ../version.c:780 msgid "type :help<Enter> or <F1> for on-line help" msgstr "tapez :help<Entrée> ou <F1> pour accéder à l'aide en ligne " -#: ../version.c:781 -msgid "type :help version7<Enter> for version info" -msgstr "tapez :help version7<Entrée> pour lire les notes de mise à jour" +msgid "type :help version8<Enter> for version info" +msgstr "tapez :help version8<Entrée> pour lire les notes de mise à jour" # DB - Pour les trois messages qui suivent : # :set cp # :intro -#: ../version.c:784 msgid "Running in Vi compatible mode" msgstr "Compatibilité avec Vi activée" -#: ../version.c:785 msgid "type :set nocp<Enter> for Vim defaults" msgstr "tapez :set nocp<Entrée> pour la désactiver" -#: ../version.c:786 msgid "type :help cp-default<Enter> for info on this" msgstr "tapez :help cp-default<Entrée> pour plus d'info" -#: ../version.c:827 +msgid "menu Help->Orphans for information " +msgstr "menu Aide->Orphelins pour plus d'info" + +msgid "Running modeless, typed text is inserted" +msgstr "Les modes sont désactivés, le texte saisi est inséré" + +msgid "menu Edit->Global Settings->Toggle Insert Mode " +msgstr "menu Édition->Réglages Globaux->Insertion Permanente" + +# DB - todo +msgid " for two modes " +msgstr " pour les modes " + +# DB - todo +msgid "menu Edit->Global Settings->Toggle Vi Compatible" +msgstr "menu Édition->Réglages Globaux->Compatibilité Vi" + +# DB - todo +msgid " for Vim defaults " +msgstr " pour déf. de Vim " + msgid "Sponsor Vim development!" msgstr "Sponsorisez le développement de Vim !" -#: ../version.c:828 msgid "Become a registered Vim user!" msgstr "Devenez un utilisateur de Vim enregistré !" -#: ../version.c:831 msgid "type :help sponsor<Enter> for information " msgstr "tapez :help sponsor<Entrée> pour plus d'informations " -#: ../version.c:832 msgid "type :help register<Enter> for information " msgstr "tapez :help register<Entrée> pour plus d'informations " -#: ../version.c:834 msgid "menu Help->Sponsor/Register for information " msgstr "menu Aide->Sponsor/Enregistrement pour plus d'info" -#: ../window.c:119 msgid "Already only one window" msgstr "Il n'y a déjà plus qu'une fenêtre" -#: ../window.c:224 msgid "E441: There is no preview window" msgstr "E441: Il n'y a pas de fenêtre de prévisualisation" -#: ../window.c:559 msgid "E442: Can't split topleft and botright at the same time" msgstr "E442: Impossible de partager topleft et botright en même temps" -#: ../window.c:1228 msgid "E443: Cannot rotate when another window is split" msgstr "E443: Rotation impossible quand une autre fenêtre est partagée" -#: ../window.c:1803 msgid "E444: Cannot close last window" msgstr "E444: Impossible de fermer la dernière fenêtre" -#: ../window.c:1810 msgid "E813: Cannot close autocmd window" msgstr "E813: Impossible de fermer la fenêtre des autocommandes" -#: ../window.c:1814 msgid "E814: Cannot close window, only autocmd window would remain" msgstr "" "E814: Impossible de fermer la fenêtre, seule la fenêtre des autocommandes " "resterait" -#: ../window.c:2717 msgid "E445: Other window contains changes" msgstr "E445: Les modifications de l'autre fenêtre n'ont pas été enregistrées" -#: ../window.c:4805 msgid "E446: No file name under cursor" msgstr "E446: Aucun nom de fichier sous le curseur" -#~ msgid "E831: bf_key_init() called with empty password" -#~ msgstr "E831: bf_key_init() appelée avec un mot de passe vide" - -#~ msgid "E820: sizeof(uint32_t) != 4" -#~ msgstr "E820: sizeof(uint32_t) != 4" - -#~ msgid "E817: Blowfish big/little endian use wrong" -#~ msgstr "E817: petit/gros boutisme incorrect dans blowfish" - -#~ msgid "E818: sha256 test failed" -#~ msgstr "E818: le test de sha256 a échoué" - -#~ msgid "E819: Blowfish test failed" -#~ msgstr "E819: le test de blowfish a échoué" - -#~ msgid "Patch file" -#~ msgstr "Fichier rustine" - -# AB - Textes des boutons de la boîte de dialogue affichée par inputdialog(). -#~ msgid "" -#~ "&OK\n" -#~ "&Cancel" -#~ msgstr "" -#~ "&Ok\n" -#~ "&Annuler" - -# AB - À mon avis, la version anglaise est erronée. -# DB : Vérifier -#~ msgid "E240: No connection to Vim server" -#~ msgstr "E240: Pas de connexion au serveur X" - -# AB - La version française est meilleure que la version anglaise. -#~ msgid "E241: Unable to send to %s" -#~ msgstr "E241: L'envoi au serveur %s à échoué" - -#~ msgid "E277: Unable to read a server reply" -#~ msgstr "E277: Impossible de lire la réponse du serveur" - -# AB - La version française est meilleure que la version anglaise. -#~ msgid "E258: Unable to send to client" -#~ msgstr "E258: La réponse n'a pas pu être envoyée au client" - -# AB - Ceci est un titre de boîte de dialogue. Vérifier que la version -# française est correcte pour les trois références ; j'ai un doute quant -# à la troisième. -#~ msgid "Save As" -#~ msgstr "Enregistrer sous - Vim" - -# AB - Ceci est un titre de boîte de dialogue. -#~ msgid "Edit File" -#~ msgstr "Ouvrir un fichier - Vim" - -#~ msgid " (NOT FOUND)" -#~ msgstr " (INTROUVABLE)" - -#~ msgid "Source Vim script" -#~ msgstr "Sourcer un script - Vim" - -#~ msgid "unknown" -#~ msgstr "inconnu" - -#~ msgid "Edit File in new window" -#~ msgstr "Ouvrir un fichier dans une nouvelle fenêtre - Vim" - -#~ msgid "Append File" -#~ msgstr "Ajouter fichier" - -#~ msgid "Window position: X %d, Y %d" -#~ msgstr "Position de la fenêtre : X %d, Y %d" - -#~ msgid "Save Redirection" -#~ msgstr "Enregistrer la redirection" - -#~ msgid "Save View" -#~ msgstr "Enregistrer la vue - Vim" - -#~ msgid "Save Session" -#~ msgstr "Enregistrer la session - Vim" - -#~ msgid "Save Setup" -#~ msgstr "Enregistrer les réglages - Vim" - -#~ msgid "E809: #< is not available without the +eval feature" -#~ msgstr "E809: #< n'est pas disponible sans la fonctionnalité +eval" - -#~ msgid "E196: No digraphs in this version" -#~ msgstr "E196: Pas de digraphes dans cette version" - -#~ msgid "is a device (disabled with 'opendevice' option)" -#~ msgstr "est un périphérique (désactivé par l'option 'opendevice')" - -#~ msgid "Reading from stdin..." -#~ msgstr "Lecture de stdin..." - -#~ msgid "[crypted]" -#~ msgstr "[chiffré]" - -#~ msgid "E821: File is encrypted with unknown method" -#~ msgstr "E821: Le fichier est chiffré avec une méthode inconnue" - -#~ msgid "NetBeans disallows writes of unmodified buffers" -#~ msgstr "NetBeans interdit l'écriture des tampons non modifiés" - -#~ msgid "Partial writes disallowed for NetBeans buffers" -#~ msgstr "Netbeans interdit l'écriture partielle de ses tampons" - -#~ msgid "writing to device disabled with 'opendevice' option" -#~ msgstr "écriture vers un périphérique désactivé par l'option 'opendevice'" - -#~ msgid "E460: The resource fork would be lost (add ! to override)" -#~ msgstr "" -#~ "E460: Les ressources partagées seraient perdues (ajoutez ! pour passer " -#~ "outre)" - -#~ msgid "E851: Failed to create a new process for the GUI" -#~ msgstr "" -#~ "E851: Échec lors de la création d'un nouveau processus pour l'interface " -#~ "graphique" - -#~ msgid "E852: The child process failed to start the GUI" -#~ msgstr "" -#~ "E852: Le processus fils n'a pas réussi à démarrer l'interface graphique" - -#~ msgid "E229: Cannot start the GUI" -#~ msgstr "E229: Impossible de démarrer l'interface graphique" - -#~ msgid "E230: Cannot read from \"%s\"" -#~ msgstr "E230: Impossible de lire \"%s\"" - -#~ msgid "E665: Cannot start GUI, no valid font found" -#~ msgstr "" -#~ "E665: Impossible de démarrer l'IHM graphique, aucune police valide trouvée" - -#~ msgid "E231: 'guifontwide' invalid" -#~ msgstr "E231: 'guifontwide' est invalide" - -#~ msgid "E599: Value of 'imactivatekey' is invalid" -#~ msgstr "E599: Valeur de 'imactivatekey' invalide" - -#~ msgid "E254: Cannot allocate color %s" -#~ msgstr "E254: Impossible d'allouer la couleur %s" - -#~ msgid "No match at cursor, finding next" -#~ msgstr "Aucune correspondance sous le curseur, recherche de la suivante" - -#~ msgid "<cannot open> " -#~ msgstr "<impossible d'ouvrir> " - -#~ msgid "E616: vim_SelFile: can't get font %s" -#~ msgstr "E616: vim_SelFile : impossible d'obtenir la police %s" - -#~ msgid "E614: vim_SelFile: can't return to current directory" -#~ msgstr "" -#~ "E614: vim_SelFile : impossible de revenir dans le répertoire courant" - -#~ msgid "Pathname:" -#~ msgstr "Chemin :" - -#~ msgid "E615: vim_SelFile: can't get current directory" -#~ msgstr "E615: vim_SelFile : impossible d'obtenir le répertoire courant" - -#~ msgid "OK" -#~ msgstr "Ok" - -#~ msgid "Cancel" -#~ msgstr "Annuler" - -#~ msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." -#~ msgstr "" -#~ "Widget scrollbar : Impossible d'obtenir la géométrie du pixmap 'thumb'" - -#~ msgid "Vim dialog" -#~ msgstr "Vim" - -#~ msgid "E232: Cannot create BalloonEval with both message and callback" -#~ msgstr "E232: Impossible de créer un BalloonEval avec message ET callback" - -msgid "Yes" -msgstr "Oui" - -msgid "No" -msgstr "Non" - -# todo '_' is for hotkey, i guess? -#~ msgid "Input _Methods" -#~ msgstr "_Méthodes de saisie" - -#~ msgid "VIM - Search and Replace..." -#~ msgstr "Remplacer - Vim" - -#~ msgid "VIM - Search..." -#~ msgstr "Rechercher - Vim" - -#~ msgid "Find what:" -#~ msgstr "Rechercher :" - -#~ msgid "Replace with:" -#~ msgstr "Remplacer par :" - -#~ msgid "Match whole word only" -#~ msgstr "Mots entiers seulement" - -#~ msgid "Match case" -#~ msgstr "Respecter la casse" - -#~ msgid "Direction" -#~ msgstr "Direction" - -#~ msgid "Up" -#~ msgstr "Haut" - -#~ msgid "Down" -#~ msgstr "Bas" - -#~ msgid "Find Next" -#~ msgstr "Suivant" - -#~ msgid "Replace" -#~ msgstr "Remplacer" - -#~ msgid "Replace All" -#~ msgstr "Remplacer tout" - -#~ msgid "Vim: Received \"die\" request from session manager\n" -#~ msgstr "" -#~ "Vim : Une requête \"die\" a été reçue par le gestionnaire de session\n" - -#~ msgid "Close tab" -#~ msgstr "Fermer l'onglet" - -#~ msgid "New tab" -#~ msgstr "Nouvel onglet" - -# DB - todo : un peu long. Cet entrée de menu permet d'ouvrir un fichier -# dans un nouvel onglet via le sélecteur de fichiers graphique. -#~ msgid "Open Tab..." -#~ msgstr "Ouvrir dans un onglet..." - -#~ msgid "Vim: Main window unexpectedly destroyed\n" -#~ msgstr "Vim : Fenêtre principale détruite inopinément\n" - -#~ msgid "&Filter" -#~ msgstr "&Filtrer" - -#~ msgid "&Cancel" -#~ msgstr "&Annuler" - -#~ msgid "Directories" -#~ msgstr "Répertoires" - -#~ msgid "Filter" -#~ msgstr "Filtre" - -#~ msgid "&Help" -#~ msgstr "&Aide" - -#~ msgid "Files" -#~ msgstr "Fichiers" - -#~ msgid "&OK" -#~ msgstr "&Ok" - -#~ msgid "Selection" -#~ msgstr "Sélection" - -#~ msgid "Find &Next" -#~ msgstr "Suiva&nt" - -#~ msgid "&Replace" -#~ msgstr "&Remplacer" - -#~ msgid "Replace &All" -#~ msgstr "Rempl&acer tout" - -#~ msgid "&Undo" -#~ msgstr "Ann&uler" - -#~ msgid "E671: Cannot find window title \"%s\"" -#~ msgstr "E671: Titre de fenêtre \"%s\" introuvable" - -#~ msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." -#~ msgstr "E243: Argument non supporté : \"-%s\" ; Utilisez la version OLE." - -#~ msgid "E672: Unable to open window inside MDI application" -#~ msgstr "E672: Impossible d'ouvrir une fenêtre dans une application MDI" - -#~ msgid "Open tab..." -#~ msgstr "Ouvrir dans un onglet..." - -#~ msgid "Find string (use '\\\\' to find a '\\')" -#~ msgstr "Chercher une chaîne (utilisez '\\\\' pour chercher un '\\')" - -#~ msgid "Find & Replace (use '\\\\' to find a '\\')" -#~ msgstr "Chercher et remplacer (utilisez '\\\\' pour trouver un '\\')" - -# DB - Traduction non indispensable puisque le code indique qu'il s'agit d'un -# paramétrage bidon afin de sélectionner un répertoire plutôt qu'un -# fichier. -#~ msgid "Not Used" -#~ msgstr "Non utilisé" - -# DB - Traduction non indispensable puisque le code indique qu'il s'agit d'un -# paramétrage bidon afin de sélectionner un répertoire plutôt qu'un -# fichier. -#~ msgid "Directory\t*.nothing\n" -#~ msgstr "Répertoire\t*.rien\n" - -# DB - todo : perfectible. -#~ msgid "" -#~ "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" -#~ msgstr "" -#~ "Vim E458: Erreur d'allocation de couleurs, couleurs possiblement " -#~ "incorrectes" - -# DB - todo : La VF est-elle compréhensible ? -#~ msgid "E250: Fonts for the following charsets are missing in fontset %s:" -#~ msgstr "" -#~ "E250: Des polices manquent dans %s pour les jeux de caractères suivants :" - -#~ msgid "E252: Fontset name: %s" -#~ msgstr "E252: Nom du jeu de polices : %s" - -#~ msgid "Font '%s' is not fixed-width" -#~ msgstr "La police '%s' n'a pas une largeur fixe" - -#~ msgid "E253: Fontset name: %s\n" -#~ msgstr "E253: Nom du jeu de polices : %s\n" - -#~ msgid "Font0: %s\n" -#~ msgstr "Font0: %s\n" - -#~ msgid "Font1: %s\n" -#~ msgstr "Font1: %s\n" - -#~ msgid "Font%<PRId64> width is not twice that of font0\n" -#~ msgstr "La largeur de Font%<PRId64> n'est pas le double de celle de Font0\n" - -#~ msgid "Font0 width: %<PRId64>\n" -#~ msgstr "Largeur de Font0 : %<PRId64>\n" - -#~ msgid "" -#~ "Font1 width: %<PRId64>\n" -#~ "\n" -#~ msgstr "" -#~ "Largeur de Font1 : %<PRId64>\n" -#~ "\n" - -# DB - todo : Pas certain de mon coup, ici... -#~ msgid "Invalid font specification" -#~ msgstr "La spécification de la police est invalide" - -#~ msgid "&Dismiss" -#~ msgstr "Aban&donner" - -# DB - todo : Pas certain de mon coup, ici... -#~ msgid "no specific match" -#~ msgstr "aucune correspondance particulière" - -#~ msgid "Vim - Font Selector" -#~ msgstr "Choisir une police - Vim" - -#~ msgid "Name:" -#~ msgstr "Nom :" - -#~ msgid "Show size in Points" -#~ msgstr "Afficher la taille en Points" - -#~ msgid "Encoding:" -#~ msgstr "Encodage :" - -#~ msgid "Font:" -#~ msgstr "Police :" - -#~ msgid "Style:" -#~ msgstr "Style :" - -#~ msgid "Size:" -#~ msgstr "Taille :" - -#~ msgid "E256: Hangul automata ERROR" -#~ msgstr "E256: ERREUR dans l'automate Hangul" - -#~ msgid "E563: stat error" -#~ msgstr "E563: Erreur stat" - -#~ msgid "E625: cannot open cscope database: %s" -#~ msgstr "E625: impossible d'ouvrir la base de données cscope %s" - -#~ msgid "E626: cannot get cscope database information" -#~ msgstr "" -#~ "E626: impossible d'obtenir des informations sur la base de données cscope" - -#~ msgid "Lua library cannot be loaded." -#~ msgstr "La bibliothèque Lua n'a pas pu être chargée." - -#~ msgid "cannot save undo information" -#~ msgstr "impossible d'enregistrer les informations d'annulation" - -#~ msgid "" -#~ "E815: Sorry, this command is disabled, the MzScheme libraries could not " -#~ "be loaded." -#~ msgstr "" -#~ "E815: Désolé, cette commande est désactivée : les bibliothèques MzScheme " -#~ "n'ont pas pu être chargées." - -#~ msgid "invalid expression" -#~ msgstr "expression invalide" - -#~ msgid "expressions disabled at compile time" -#~ msgstr "expressions désactivée lors de la compilation" - -#~ msgid "hidden option" -#~ msgstr "option cachée" - -#~ msgid "unknown option" -#~ msgstr "option inconnue" - -#~ msgid "window index is out of range" -#~ msgstr "numéro de fenêtre hors limites" - -#~ msgid "couldn't open buffer" -#~ msgstr "impossible d'ouvrir le tampon" - -#~ msgid "cannot delete line" -#~ msgstr "impossible d'effacer la ligne" - -#~ msgid "cannot replace line" -#~ msgstr "impossible de remplacer la ligne" - -#~ msgid "cannot insert line" -#~ msgstr "impossible d'insérer la ligne" - -#~ msgid "string cannot contain newlines" -#~ msgstr "une chaîne ne peut pas contenir de saut-de-ligne" - -#~ msgid "error converting Scheme values to Vim" -#~ msgstr "erreur lors de la conversion d'une valeur de Scheme à Vim" - -#~ msgid "Vim error: ~a" -#~ msgstr "Erreur Vim : ~a" - -#~ msgid "Vim error" -#~ msgstr "Erreur Vim" - -#~ msgid "buffer is invalid" -#~ msgstr "tampon invalide" - -#~ msgid "window is invalid" -#~ msgstr "fenêtre invalide" - -#~ msgid "linenr out of range" -#~ msgstr "numéro de ligne hors limites" - -#~ msgid "not allowed in the Vim sandbox" -#~ msgstr "non autorisé dans le bac à sable" - -#~ msgid "E836: This Vim cannot execute :python after using :py3" -#~ msgstr "E836: Vim ne peut pas exécuter :python après avoir utilisé :py3" - -#~ msgid "" -#~ "E263: Sorry, this command is disabled, the Python library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E263: Désolé, commande désactivée : la bibliothèque Python n'a pas pu " -#~ "être chargée." - -#~ msgid "E659: Cannot invoke Python recursively" -#~ msgstr "E659: Impossible d'invoquer Python récursivement" - -#~ msgid "E837: This Vim cannot execute :py3 after using :python" -#~ msgstr "E837: Vim ne peut pas exécuter :py3 après avoir utilisé :python" - -#~ msgid "index must be int or slice" -#~ msgstr "index doit être int ou slice" - -#~ msgid "E265: $_ must be an instance of String" -#~ msgstr "E265: $_ doit être une instance de chaîne (String)" - -#~ msgid "" -#~ "E266: Sorry, this command is disabled, the Ruby library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E266: Désolé, commande désactivée : la bibliothèque Ruby n'a pas pu être " -#~ "chargée." - -#~ msgid "E267: unexpected return" -#~ msgstr "E267: « return » inattendu" - -#~ msgid "E268: unexpected next" -#~ msgstr "E268: « next » inattendu" - -#~ msgid "E269: unexpected break" -#~ msgstr "E269: « break » inattendu" - -#~ msgid "E270: unexpected redo" -#~ msgstr "E270: « redo » inattendu" - -#~ msgid "E271: retry outside of rescue clause" -#~ msgstr "E271: « retry » hors d'une clause « rescue »" - -#~ msgid "E272: unhandled exception" -#~ msgstr "E272: Exception non prise en charge" - -# DB - todo -#~ msgid "E273: unknown longjmp status %d" -#~ msgstr "E273: contexte de longjmp inconnu : %d" - -#~ msgid "Toggle implementation/definition" -#~ msgstr "Basculer implémentation/définition" - -#~ msgid "Show base class of" -#~ msgstr "Montrer la classe de base de" - -#~ msgid "Show overridden member function" -#~ msgstr "Montrer les fonctions membres surchargées" - -#~ msgid "Retrieve from file" -#~ msgstr "Récupérer du fichier" - -#~ msgid "Retrieve from project" -#~ msgstr "Récupérer du projet" - -#~ msgid "Retrieve from all projects" -#~ msgstr "Récupérer de tous les projets" - -#~ msgid "Retrieve" -#~ msgstr "Récupérer" - -#~ msgid "Show source of" -#~ msgstr "Montrer source de" - -#~ msgid "Find symbol" -#~ msgstr "Trouver symbole" - -#~ msgid "Browse class" -#~ msgstr "Parcourir classe" - -#~ msgid "Show class in hierarchy" -#~ msgstr "Montrer classe dans hiérarchie" - -#~ msgid "Show class in restricted hierarchy" -#~ msgstr "Montrer classe dans hiérarchie restreinte" - -# todo -#~ msgid "Xref refers to" -#~ msgstr "Xref référence" - -#~ msgid "Xref referred by" -#~ msgstr "Xref est référencé par" - -#~ msgid "Xref has a" -#~ msgstr "Xref a un(e)" - -#~ msgid "Xref used by" -#~ msgstr "Xref utilisée par" - -#~ msgid "Show docu of" -#~ msgstr "Montrer doc de" - -#~ msgid "Generate docu for" -#~ msgstr "Générer la doc de" - -#~ msgid "" -#~ "Cannot connect to SNiFF+. Check environment (sniffemacs must be found in " -#~ "$PATH).\n" -#~ msgstr "" -#~ "Connexion à SNiFF+ impossible. Vérifiez l'environnement (sniffemacs doit " -#~ "être dans le $PATH).\n" - -#~ msgid "E274: Sniff: Error during read. Disconnected" -#~ msgstr "E274: Sniff : Erreur de lecture. Déconnexion" - -# DB - Les trois messages suivants vont ensembles. -#~ msgid "SNiFF+ is currently " -#~ msgstr "SNiFF+ est actuellement " - -#~ msgid "not " -#~ msgstr "dé" - -#~ msgid "connected" -#~ msgstr "connecté" - -#~ msgid "E275: Unknown SNiFF+ request: %s" -#~ msgstr "E275: Requête SNiFF+ inconnue : %s" - -#~ msgid "E276: Error connecting to SNiFF+" -#~ msgstr "E276: Erreur lors de la connexion à SNiFF+" - -#~ msgid "E278: SNiFF+ not connected" -#~ msgstr "E278: SNiFF+ n'est pas connecté" - -#~ msgid "E279: Not a SNiFF+ buffer" -#~ msgstr "E279: Ce tampon n'est pas un tampon SNiFF+" - -#~ msgid "Sniff: Error during write. Disconnected" -#~ msgstr "Sniff : Erreur lors d'une écriture. Déconnexion" - -#~ msgid "invalid buffer number" -#~ msgstr "numéro de tampon invalide" - -#~ msgid "not implemented yet" -#~ msgstr "pas encore implémenté" - -# DB - TODO : le contexte est celui d'une annulation. -#~ msgid "cannot set line(s)" -#~ msgstr "Impossible de remettre la/les ligne(s)" - -#~ msgid "invalid mark name" -#~ msgstr "nom de marque invalide" - -#~ msgid "mark not set" -#~ msgstr "marque non positionnée" - -#~ msgid "row %d column %d" -#~ msgstr "ligne %d colonne %d" - -#~ msgid "cannot insert/append line" -#~ msgstr "Impossible d'insérer/ajouter de lignes" - -#~ msgid "line number out of range" -#~ msgstr "numéro de ligne hors limites" - -#~ msgid "unknown flag: " -#~ msgstr "drapeau inconnu : " - -#~ msgid "unknown vimOption" -#~ msgstr "vimOption inconnue" +#, c-format +msgid "E447: Can't find file \"%s\" in path" +msgstr "E447: Le fichier \"%s\" est introuvable dans 'path'" -#~ msgid "keyboard interrupt" -#~ msgstr "interruption clavier" +#, c-format +msgid "E799: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E799: ID invalide : %ld (doit être plus grand ou égal à 1)" -#~ msgid "vim error" -#~ msgstr "erreur Vim" +#, c-format +msgid "E801: ID already taken: %ld" +msgstr "E801: ID déjà pris: %ld" -#~ msgid "cannot create buffer/window command: object is being deleted" -#~ msgstr "" -#~ "Impossible de créer commande de tampon/fenêtre : objet en cours " -#~ "d'effacement" +msgid "List or number required" +msgstr "Liste ou nombre requis" -#~ msgid "" -#~ "cannot register callback command: buffer/window is already being deleted" -#~ msgstr "" -#~ "Impossible d'inscrire la commande de rappel : tampon/fenêtre en effacement" +#, c-format +msgid "E802: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E802: ID invalide : %ld (doit être plus grand ou égal à 1)" -#~ msgid "" -#~ "E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-" -#~ "dev@vim.org" -#~ msgstr "" -#~ "E280: ERREUR FATALE TCL: reflist corrompue ?! Contactez vim-dev@vim.org, " -#~ "SVP." +#, c-format +msgid "E803: ID not found: %ld" +msgstr "E803: ID introuvable : %ld" -#~ msgid "cannot register callback command: buffer/window reference not found" -#~ msgstr "" -#~ "Impossible d'inscrire la commande de rappel : réf. tampon/fenêtre " -#~ "introuvable" +#, c-format +msgid "E370: Could not load library %s" +msgstr "E370: Impossible de charger la bibliothèque %s" -#~ msgid "" -#~ "E571: Sorry, this command is disabled: the Tcl library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E571: Désolé, commande désactivée: la bibliothèque Tcl n'a pas pu être " -#~ "chargée." +msgid "Sorry, this command is disabled: the Perl library could not be loaded." +msgstr "" +"Désolé, commande désactivée : la bibliothèque Perl n'a pas pu être chargée." -#~ msgid "E572: exit code %d" -#~ msgstr "E572: code de sortie %d" +msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" +msgstr "E299: Évaluation Perl interdite dans bac à sable sans le module Safe" -#~ msgid "cannot get line" -#~ msgstr "Impossible d'obtenir la ligne" +msgid "Edit with &multiple Vims" +msgstr "Éditer dans &plusieurs Vims" -#~ msgid "Unable to register a command server name" -#~ msgstr "Impossible d'inscrire un nom de serveur de commande" +msgid "Edit with single &Vim" +msgstr "Éditer dans un seul &Vim" -#~ msgid "E248: Failed to send command to the destination program" -#~ msgstr "E248: Échec de l'envoi de la commande au programme cible" +msgid "Diff with Vim" +msgstr "&Comparer avec Vim" -#~ msgid "E573: Invalid server id used: %s" -#~ msgstr "E573: Id utilisé pour le serveur invalide : %s" +msgid "Edit with &Vim" +msgstr "Éditer dans &Vim" -#~ msgid "E251: VIM instance registry property is badly formed. Deleted!" -#~ msgstr "" -#~ "E251: Entrée registre de l'instance de Vim mal formatée. Suppression !" +#. Now concatenate +msgid "Edit with existing Vim - " +msgstr "Éditer dans le Vim existant - " -#~ msgid "netbeans is not supported with this GUI\n" -#~ msgstr "netbeans n'est pas supporté avec cette interface graphique\n" +msgid "Edits the selected file(s) with Vim" +msgstr "Édites le(s) fichier(s) sélectionné(s) avec Vim" -#~ msgid "This Vim was not compiled with the diff feature." -#~ msgstr "Ce Vim n'a pas été compilé avec la fonctionnalité diff" +# DB - MessageBox win32, la longueur n'est pas un problème ! +msgid "Error creating process: Check if gvim is in your path!" +msgstr "" +"Erreur de création du processus : vérifiez que gvim est bien dans votre " +"chemin !" -#~ msgid "'-nb' cannot be used: not enabled at compile time\n" -#~ msgstr "'-nb' ne peut pas être utilisé : désactivé à la compilation\n" +msgid "gvimext.dll error" +msgstr "Erreur de gvimext.dll" -#~ msgid "Vim: Error: Failure to start gvim from NetBeans\n" -#~ msgstr "Vim : Erreur : Impossible de démarrer gvim depuis NetBeans\n" +msgid "Path length too long!" +msgstr "Le chemin est trop long !" -# DB - todo (VMS uniquement). -#~ msgid "" -#~ "\n" -#~ "Where case is ignored prepend / to make flag upper case" -#~ msgstr "" -#~ "\n" -#~ "pour lesquels la casse est indifférente (/ pour que le drapeau soit " -#~ "majuscule)" - -#~ msgid "-register\t\tRegister this gvim for OLE" -#~ msgstr "-register\tInscrire ce gvim pour OLE" - -#~ msgid "-unregister\t\tUnregister gvim for OLE" -#~ msgstr "-unregister\tDésinscrire gvim de OLE" - -#~ msgid "-g\t\t\tRun using GUI (like \"gvim\")" -#~ msgstr "-g\t\tLancer l'interface graphique (comme \"gvim\")" - -#~ msgid "-f or --nofork\tForeground: Don't fork when starting GUI" -#~ msgstr "" -#~ "-f, --nofork\tPremier-plan : ne pas détacher l'interface graphique du " -#~ "terminal" - -#~ msgid "-f\t\t\tDon't use newcli to open window" -#~ msgstr "-f\t\tNe pas utiliser newcli pour l'ouverture des fenêtres" - -#~ msgid "-dev <device>\t\tUse <device> for I/O" -#~ msgstr "-dev <périph>\tUtiliser <périphérique> pour les E/S" - -#~ msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" -#~ msgstr "-U <gvimrc>\tUtiliser <gvimrc> au lieu du gvimrc habituel" - -#~ msgid "-x\t\t\tEdit encrypted files" -#~ msgstr "-x\t\t\tÉditer des fichiers chiffrés" - -#~ msgid "-display <display>\tConnect vim to this particular X-server" -#~ msgstr "-display <display>\tConnecter Vim au serveur X spécifié" - -#~ msgid "-X\t\t\tDo not connect to X server" -#~ msgstr "-X\t\t\tNe pas se connecter à un serveur X" - -#~ msgid "--remote <files>\tEdit <files> in a Vim server if possible" -#~ msgstr "" -#~ "--remote <fich>\tÉditer les <fichiers> dans un serveur Vim si possible" - -#~ msgid "--remote-silent <files> Same, don't complain if there is no server" -#~ msgstr "" -#~ "--remote-silent ...\tPareil, mais pas d'erreur s'il n'y a aucun serveur" - -#~ msgid "" -#~ "--remote-wait <files> As --remote but wait for files to have been edited" -#~ msgstr "" -#~ "--remote-wait <fich>\tComme --remote mais ne quitter qu'à la fin de " -#~ "l'édition" - -#~ msgid "" -#~ "--remote-wait-silent <files> Same, don't complain if there is no server" -#~ msgstr "" -#~ "--remote-wait-silent\tPareil, mais pas d'erreur s'il n'y a aucun serveur" - -#~ msgid "" -#~ "--remote-tab[-wait][-silent] <files> As --remote but use tab page per " -#~ "file" -#~ msgstr "" -#~ "--remote-tab[-wait][-silent] <fich>\tComme --remote mais ouvrir un onglet " -#~ "pour chaque fichier" - -#~ msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" -#~ msgstr "" -#~ "--remote-send <tche>\tEnvoyer <touches> à un serveur Vim puis quitter" - -#~ msgid "" -#~ "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" -#~ msgstr "" -#~ "--remote-expr <expr>\tÉvaluer <expr> dans un serveur Vim, afficher le " -#~ "résultat" - -#~ msgid "--serverlist\t\tList available Vim server names and exit" -#~ msgstr "" -#~ "--serverlist\t\tLister les noms des serveurs Vim disponibles et quitter" - -#~ msgid "--servername <name>\tSend to/become the Vim server <name>" -#~ msgstr "--servername <nom>\tEnvoyer au/devenir le serveur Vim nommé <nom>" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (Motif version):\n" -#~ msgstr "" -#~ "\n" -#~ "Arguments reconnus par gvim (version Motif) :\n" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (neXtaw version):\n" -#~ msgstr "" -#~ "\n" -#~ "Arguments reconnus par gvim (version neXtaw) :\n" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (Athena version):\n" -#~ msgstr "" -#~ "\n" -#~ "Arguments reconnus par gvim (version Athena) :\n" +# msgstr "--Pas de lignes dans le tampon--" +# DB - todo : ou encore : msgstr "--Aucune ligne dans le tampon--" +msgid "--No lines in buffer--" +msgstr "--Le tampon est vide--" -#~ msgid "-display <display>\tRun vim on <display>" -#~ msgstr "-display <écran>\tLancer Vim sur ce <display>" +#. +#. * The error messages that can be shared are included here. +#. * Excluded are errors that are only used once and debugging messages. +#. +msgid "E470: Command aborted" +msgstr "E470: Commande annulée" -#~ msgid "-iconic\t\tStart vim iconified" -#~ msgstr "-iconic\t\tIconifier Vim au démarrage" +msgid "E471: Argument required" +msgstr "E471: Argument requis" -#~ msgid "-background <color>\tUse <color> for the background (also: -bg)" -#~ msgstr "" -#~ "-background <coul>\tUtiliser <couleur> pour l'arrière-plan\t (abrv : -" -#~ "bg)" +msgid "E10: \\ should be followed by /, ? or &" +msgstr "E10: \\ devrait être suivi de /, ? ou &" -#~ msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" -#~ msgstr "" -#~ "-foreground <coul>\tUtiliser <couleur> pour le texte normal\t (abrv : -" -#~ "fg)" +msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" +msgstr "" +"E11: Invalide dans la fenêtre ligne-de-commande ; <CR> exécute, CTRL-C quitte" -#~ msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" -#~ msgstr "" -#~ "-font <fonte>\tUtiliser <fonte> pour le texte normal\t (abrv : -fn)" +msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" +msgstr "" +"E12: commande non autorisée depuis un exrc/vimrc dans répertoire courant ou " +"une recherche de marqueur" -#~ msgid "-boldfont <font>\tUse <font> for bold text" -#~ msgstr "-boldfont <fonte>\tUtiliser <fonte> pour le texte gras" +msgid "E171: Missing :endif" +msgstr "E171: :endif manquant" -#~ msgid "-italicfont <font>\tUse <font> for italic text" -#~ msgstr "-italicfont <fonte>\tUtiliser <fonte> pour le texte italique" +msgid "E600: Missing :endtry" +msgstr "E600: :endtry manquant" -#~ msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" -#~ msgstr "" -#~ "-geometry <géom>\tUtiliser cette <géométrie> initiale\t (abrv : -geom)" +msgid "E170: Missing :endwhile" +msgstr "E170: :endwhile manquant" -#~ msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" -#~ msgstr "" -#~ "-borderwidth <épais>\tUtiliser cette <épaisseur> de bordure\t (abrv : -" -#~ "bw)" +msgid "E170: Missing :endfor" +msgstr "E170: :endfor manquant" -#~ msgid "" -#~ "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" -#~ msgstr "" -#~ "-scrollbarwidth <lg>\tUtiliser cette <largeur> de barre de défil. (abrv: -" -#~ "sw)" - -#~ msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" -#~ msgstr "" -#~ "-menuheight <haut>\tUtiliser cette <hauteur> de menu\t (abrv : -mh)" - -#~ msgid "-reverse\t\tUse reverse video (also: -rv)" -#~ msgstr "-reverse\t\tUtiliser la vidéo inverse\t\t (abrv : -rv)" - -#~ msgid "+reverse\t\tDon't use reverse video (also: +rv)" -#~ msgstr "+reverse\t\tNe pas utiliser de vidéo inverse\t (abrv : +rv)" - -#~ msgid "-xrm <resource>\tSet the specified resource" -#~ msgstr "-xrm <ressource>\tConfigurer la <ressource> spécifiée" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (GTK+ version):\n" -#~ msgstr "" -#~ "\n" -#~ "Arguments reconnus par gvim (version GTK+) :\n" - -#~ msgid "-display <display>\tRun vim on <display> (also: --display)" -#~ msgstr "" -#~ "-display <display>\tLancer Vim sur ce <display>\t(également : --display)" - -#~ msgid "--role <role>\tSet a unique role to identify the main window" -#~ msgstr "--role <rôle>\tDonner un rôle pour identifier la fenêtre principale" - -#~ msgid "--socketid <xid>\tOpen Vim inside another GTK widget" -#~ msgstr "--socketid <xid>\tOuvrir Vim dans un autre widget GTK" - -#~ msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" -#~ msgstr "--echo-wid\t\tGvim affiche l'ID de la fenêtre sur stdout" - -#~ msgid "-P <parent title>\tOpen Vim inside parent application" -#~ msgstr "-P <titre parent>\tOuvrir Vim dans une application parente" - -#~ msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" -#~ msgstr "--windowid <HWND>\tOuvrir Vim dans un autre widget win32" - -#~ msgid "No display" -#~ msgstr "Aucun display" - -#~ msgid ": Send failed.\n" -#~ msgstr " : L'envoi a échoué.\n" - -#~ msgid ": Send failed. Trying to execute locally\n" -#~ msgstr " : L'envoi a échoué. Tentative d'exécution locale\n" - -#~ msgid "%d of %d edited" -#~ msgstr "%d édités sur %d" - -#~ msgid "No display: Send expression failed.\n" -#~ msgstr "Aucun display : L'envoi de l'expression a échoué.\n" - -#~ msgid ": Send expression failed.\n" -#~ msgstr " : L'envoi de l'expression a échoué.\n" +msgid "E588: :endwhile without :while" +msgstr "E588: :endwhile sans :while" -#~ msgid "E543: Not a valid codepage" -#~ msgstr "E543: Page de codes non valide" +msgid "E588: :endfor without :for" +msgstr "E588: :endfor sans :for" -#~ msgid "E284: Cannot set IC values" -#~ msgstr "E284: Impossible de régler les valeurs IC" - -#~ msgid "E285: Failed to create input context" -#~ msgstr "E285: Échec de la création du contexte de saisie" - -#~ msgid "E286: Failed to open input method" -#~ msgstr "E286: Échec de l'ouverture de la méthode de saisie" +msgid "E13: File exists (add ! to override)" +msgstr "E13: Le fichier existe déjà (ajoutez ! pour passer outre)" -#~ msgid "E287: Warning: Could not set destroy callback to IM" -#~ msgstr "" -#~ "E287: Alerte : Impossible d'inscrire la callback de destruction dans la MS" +msgid "E472: Command failed" +msgstr "E472: La commande a échoué" -#~ msgid "E288: input method doesn't support any style" -#~ msgstr "E288: la méthode de saisie ne supporte aucun style" +#, c-format +msgid "E234: Unknown fontset: %s" +msgstr "E234: Jeu de police inconnu : %s" -#~ msgid "E289: input method doesn't support my preedit type" -#~ msgstr "" -#~ "E289: le type de préédition de Vim n'est pas supporté par la méthode de " -#~ "saisie" +#, c-format +msgid "E235: Unknown font: %s" +msgstr "E235: Police inconnue : %s" -#~ msgid "E843: Error while updating swap file crypt" -#~ msgstr "E843: Erreur lors de la mise à jour du fichier d'échange crypté" +#, c-format +msgid "E236: Font \"%s\" is not fixed-width" +msgstr "E236: La police \"%s\" n'a pas une chasse (largeur) fixe" -#~ msgid "" -#~ "E833: %s is encrypted and this version of Vim does not support encryption" -#~ msgstr "" -#~ "E833: %s est chiffré et cette version de Vim ne supporte pas le " -#~ "chiffrement" - -#~ msgid "Swap file is encrypted: \"%s\"" -#~ msgstr "Fichier d'échange chiffré : \"%s\"" +msgid "E473: Internal error" +msgstr "E473: Erreur interne" -#~ msgid "" -#~ "\n" -#~ "If you entered a new crypt key but did not write the text file," -#~ msgstr "" -#~ "\n" -#~ "Si vous avez tapé une nouvelle clé de chiffrement mais n'avez pas " -#~ "enregistré le fichier texte," +#, c-format +msgid "E685: Internal error: %s" +msgstr "E685: Erreur interne : %s" -#~ msgid "" -#~ "\n" -#~ "enter the new crypt key." -#~ msgstr "" -#~ "\n" -#~ "tapez la nouvelle clé de chiffrement." +msgid "Interrupted" +msgstr "Interrompu" -#~ msgid "" -#~ "\n" -#~ "If you wrote the text file after changing the crypt key press enter" -#~ msgstr "" -#~ "\n" -#~ "Si vous avez écrit le fichier texte après avoir changé la clé de " -#~ "chiffrement, appuyez sur entrée" +msgid "E14: Invalid address" +msgstr "E14: Adresse invalide" -#~ msgid "" -#~ "\n" -#~ "to use the same key for text file and swap file" -#~ msgstr "" -#~ "\n" -#~ "afin d'utiliser la même clé pour le fichier texte et le fichier d'échange" +msgid "E474: Invalid argument" +msgstr "E474: Argument invalide" -#~ msgid "Using crypt key from swap file for the text file.\n" -#~ msgstr "" -#~ "Utilisation de la clé de chiffrement du fichier d'échange pour le fichier " -#~ "texte.\n" +#, c-format +msgid "E475: Invalid argument: %s" +msgstr "E475: Argument invalide : %s" -#~ msgid "" -#~ "\n" -#~ " [not usable with this version of Vim]" -#~ msgstr "" -#~ "\n" -#~ " [inutilisable avec cette version de Vim]" - -#~ msgid "Tear off this menu" -#~ msgstr "Détacher ce menu" +#, c-format +msgid "E15: Invalid expression: %s" +msgstr "E15: Expression invalide : %s" -# DB : Les trois messages qui suivent sont des titres de boîtes -# de dialogue par défaut. -#~ msgid "Select Directory dialog" -#~ msgstr "Sélecteur de répertoire" +msgid "E16: Invalid range" +msgstr "E16: Plage invalide" -#~ msgid "Save File dialog" -#~ msgstr "Enregistrer un fichier" +msgid "E476: Invalid command" +msgstr "E476: Commande invalide" -#~ msgid "Open File dialog" -#~ msgstr "Ouvrir un fichier" +#, c-format +msgid "E17: \"%s\" is a directory" +msgstr "E17: \"%s\" est un répertoire" -#~ msgid "E338: Sorry, no file browser in console mode" -#~ msgstr "E338: Désolé, pas de sélecteur de fichiers en mode console" +#, c-format +msgid "E364: Library call failed for \"%s()\"" +msgstr "E364: L'appel à la bibliothèque a échoué pour \"%s()\"" -#~ msgid "ERROR: " -#~ msgstr "ERREUR : " +#, c-format +msgid "E448: Could not load library function %s" +msgstr "E448: Impossible de charger la fonction %s de la bibliothèque" -#~ msgid "" -#~ "\n" -#~ "[bytes] total alloc-freed %<PRIu64>-%<PRIu64>, in use %<PRIu64>, peak use " -#~ "%<PRIu64>\n" -#~ msgstr "" -#~ "\n" -#~ "[octets] total alloué-libéré %<PRIu64>-%<PRIu64>, utilisé %<PRIu64>, pic " -#~ "%<PRIu64>\n" +msgid "E19: Mark has invalid line number" +msgstr "E19: La marque a un numéro de ligne invalide" -#~ msgid "" -#~ "[calls] total re/malloc()'s %<PRIu64>, total free()'s %<PRIu64>\n" -#~ "\n" -#~ msgstr "" -#~ "[appels] total re/malloc() %<PRIu64>, total free() %<PRIu64>\n" -#~ "\n" +msgid "E20: Mark not set" +msgstr "E20: Marque non positionnée" -#~ msgid "E340: Line is becoming too long" -#~ msgstr "E340: La ligne devient trop longue" +msgid "E21: Cannot make changes, 'modifiable' is off" +msgstr "E21: Impossible de modifier, 'modifiable' est désactivé" -#~ msgid "E341: Internal error: lalloc(%<PRId64>, )" -#~ msgstr "E341: Erreur interne : lalloc(%<PRId64>, )" +msgid "E22: Scripts nested too deep" +msgstr "E22: Trop de récursion dans les scripts" -#~ msgid "E547: Illegal mouseshape" -#~ msgstr "E547: Forme de curseur invalide" +msgid "E23: No alternate file" +msgstr "E23: Pas de fichier alternatif" -#~ msgid "Warning: Using a weak encryption method; see :help 'cm'" -#~ msgstr "" -#~ "Alerte : utilisation d'une méthode de chiffrage faible ; consultez :help 'cm'" +msgid "E24: No such abbreviation" +msgstr "E24: Cette abréviation n'existe pas" -#~ msgid "Enter encryption key: " -#~ msgstr "Tapez la clé de chiffrement : " +msgid "E477: No ! allowed" +msgstr "E477: Le ! n'est pas autorisé" -#~ msgid "Enter same key again: " -#~ msgstr "Tapez la clé à nouveau : " +msgid "E25: GUI cannot be used: Not enabled at compile time" +msgstr "E25: L'interface graphique n'a pas été compilée dans cette version" -#~ msgid "Keys don't match!" -#~ msgstr "Les clés ne correspondent pas !" +msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" +msgstr "E26: Le support de l'hébreu n'a pas été compilé dans cette version\n" -#~ msgid "Cannot connect to Netbeans #2" -#~ msgstr "Impossible de se connecter à Netbeans n°2" +msgid "E27: Farsi cannot be used: Not enabled at compile time\n" +msgstr "E27: Le support du farsi n'a pas été compilé dans cette version\n" -#~ msgid "Cannot connect to Netbeans" -#~ msgstr "Impossible de se connecter à Netbeans" +msgid "E800: Arabic cannot be used: Not enabled at compile time\n" +msgstr "E800: Le support de l'arabe n'a pas été compilé dans cette version\n" -#~ msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" -#~ msgstr "" -#~ "E668: Mode d'accès incorrect au fichier d'infos de connexion NetBeans : " -#~ "\"%s\"" +#, c-format +msgid "E28: No such highlight group name: %s" +msgstr "E28: Aucun nom de groupe de surbrillance %s" -# DB : message d'un appel à perror(). -#~ msgid "read from Netbeans socket" -#~ msgstr "read sur la socket Netbeans" +msgid "E29: No inserted text yet" +msgstr "E29: Pas encore de texte inséré" -#~ msgid "E658: NetBeans connection lost for buffer %<PRId64>" -#~ msgstr "E658: Connexion NetBeans perdue pour le tampon %<PRId64>" +msgid "E30: No previous command line" +msgstr "E30: Aucune ligne de commande précédente" -#~ msgid "E838: netbeans is not supported with this GUI" -#~ msgstr "E838: netbeans n'est pas supporté avec cette interface graphique" +msgid "E31: No such mapping" +msgstr "E31: Mappage inexistant" -#~ msgid "E511: netbeans already connected" -#~ msgstr "E511: netbeans déjà connecté" +msgid "E479: No match" +msgstr "E479: Aucune correspondance" -#~ msgid "E505: %s is read-only (add ! to override)" -#~ msgstr "E505: %s est en lecture seule (ajoutez ! pour passer outre)" +#, c-format +msgid "E480: No match: %s" +msgstr "E480: Aucune correspondance : %s" -#~ msgid "E775: Eval feature not available" -#~ msgstr "E775: La fonctionnalité d'évaluation n'est pas disponible" +msgid "E32: No file name" +msgstr "E32: Aucun nom de fichier" -#~ msgid "freeing %<PRId64> lines" -#~ msgstr "libération de %<PRId64> lignes" +msgid "E33: No previous substitute regular expression" +msgstr "E33: Aucune expression régulière de substitution précédente" -#~ msgid "E530: Cannot change term in GUI" -#~ msgstr "E530: Impossible de modifier term dans l'interface graphique" +msgid "E34: No previous command" +msgstr "E34: Aucune commande précédente" -#~ msgid "E531: Use \":gui\" to start the GUI" -#~ msgstr "E531: Utilisez \":gui\" pour démarrer l'interface graphique" +msgid "E35: No previous regular expression" +msgstr "E35: Aucune expression régulière précédente" -#~ msgid "E617: Cannot be changed in the GTK+ 2 GUI" -#~ msgstr "E617: Non modifiable dans l'interface graphique GTK+ 2" +msgid "E481: No range allowed" +msgstr "E481: Les plages ne sont pas autorisées" -#~ msgid "E596: Invalid font(s)" -#~ msgstr "E596: Police(s) invalide(s)" +msgid "E36: Not enough room" +msgstr "E36: Pas assez de place" -#~ msgid "E597: can't select fontset" -#~ msgstr "E597: Impossible de sélectionner un jeu de polices" +#, c-format +msgid "E247: no registered server named \"%s\"" +msgstr "E247: aucun serveur nommé \"%s\" n'est enregistré" -#~ msgid "E598: Invalid fontset" -#~ msgstr "E598: Jeu de polices invalide" +#, c-format +msgid "E482: Can't create file %s" +msgstr "E482: Impossible de créer le fichier %s" -#~ msgid "E533: can't select wide font" -#~ msgstr "E533: Impossible de sélectionner une police à largeur double" +msgid "E483: Can't get temp file name" +msgstr "E483: Impossible d'obtenir un nom de fichier temporaire" -#~ msgid "E534: Invalid wide font" -#~ msgstr "E534: Police à largeur double invalide" +#, c-format +msgid "E484: Can't open file %s" +msgstr "E484: Impossible d'ouvrir le fichier \"%s\"" -#~ msgid "E538: No mouse support" -#~ msgstr "E538: La souris n'est pas supportée" +#, c-format +msgid "E485: Can't read file %s" +msgstr "E485: Impossible de lire le fichier %s" -#~ msgid "cannot open " -#~ msgstr "impossible d'ouvrir " +msgid "E37: No write since last change (add ! to override)" +msgstr "E37: Modifications non enregistrées (ajoutez ! pour passer outre)" -#~ msgid "VIM: Can't open window!\n" -#~ msgstr "VIM : Impossible d'ouvrir la fenêtre !\n" +msgid "E37: No write since last change" +msgstr "E37: Modifications non enregistrées" -#~ msgid "Need Amigados version 2.04 or later\n" -#~ msgstr "Amigados version 2.04 ou ultérieure est nécessaire\n" +msgid "E38: Null argument" +msgstr "E38: Argument null" -#~ msgid "Need %s version %<PRId64>\n" -#~ msgstr "%s version %<PRId64> est nécessaire\n" +msgid "E39: Number expected" +msgstr "E39: Nombre attendu" -#~ msgid "Cannot open NIL:\n" -#~ msgstr "Impossible d'ouvrir NIL :\n" +#, c-format +msgid "E40: Can't open errorfile %s" +msgstr "E40: Impossible d'ouvrir le fichier d'erreurs %s" -#~ msgid "Cannot create " -#~ msgstr "Impossible de créer " +msgid "E233: cannot open display" +msgstr "E233: ouverture du display impossible" -#~ msgid "Vim exiting with %d\n" -#~ msgstr "Vim quitte avec %d\n" +msgid "E41: Out of memory!" +msgstr "E41: Mémoire épuisée" -#~ msgid "cannot change console mode ?!\n" -#~ msgstr "Impossible de modifier le mode de la console ?!\n" +msgid "Pattern not found" +msgstr "Motif introuvable" -#~ msgid "mch_get_shellsize: not a console??\n" -#~ msgstr "mch_get_shellsize : pas une console ?!\n" +#, c-format +msgid "E486: Pattern not found: %s" +msgstr "E486: Motif introuvable : %s" -#~ msgid "E360: Cannot execute shell with -f option" -#~ msgstr "E360: Impossible d'exécuter un shell avec l'option -f" +msgid "E487: Argument must be positive" +msgstr "E487: L'argument doit être positif" -#~ msgid "Cannot execute " -#~ msgstr "Impossible d'exécuter " +msgid "E459: Cannot go back to previous directory" +msgstr "E459: Impossible de retourner au répertoire précédent" -#~ msgid "shell " -#~ msgstr "le shell " +msgid "E42: No Errors" +msgstr "E42: Aucune erreur" -#~ msgid " returned\n" -#~ msgstr " a été retourné\n" +# DB - TODO : trouver une traduction valable et attestée pour "location". +msgid "E776: No location list" +msgstr "E776: Aucune liste d'emplacements" -#~ msgid "ANCHOR_BUF_SIZE too small." -#~ msgstr "ANCHOR_BUF_SIZE trop petit." +msgid "E43: Damaged match string" +msgstr "E43: La chaîne de recherche est endommagée" -#~ msgid "I/O ERROR" -#~ msgstr "ERREUR d'E/S" +msgid "E44: Corrupted regexp program" +msgstr "E44: L'automate de regexp est corrompu" -#~ msgid "Message" -#~ msgstr "Message" +msgid "E45: 'readonly' option is set (add ! to override)" +msgstr "E45: L'option 'readonly' est activée (ajoutez ! pour passer outre)" -#~ msgid "'columns' is not 80, cannot execute external commands" -#~ msgstr "" -#~ "'columns' ne vaut pas 80, impossible d'exécuter des commandes externes" +#, c-format +msgid "E46: Cannot change read-only variable \"%s\"" +msgstr "E46: La variable \"%s\" est en lecture seule" -#~ msgid "E237: Printer selection failed" -#~ msgstr "E237: La sélection de l'imprimante a échoué" +#, c-format +msgid "E794: Cannot set variable in the sandbox: \"%s\"" +msgstr "" +"E794: Impossible de modifier une variable depuis le bac à sable : \"%s\"" -# DB - Contenu des c-formats : Imprimante puis Port. -#~ msgid "to %s on %s" -#~ msgstr "vers %s sur %s" +msgid "E713: Cannot use empty key for Dictionary" +msgstr "E713: Impossible d'utiliser une clé vide dans un Dictionnaire" -#~ msgid "E613: Unknown printer font: %s" -#~ msgstr "E613: Police d'imprimante inconnue : %s" +msgid "E715: Dictionary required" +msgstr "E715: Dictionnaire requis" -#~ msgid "E238: Print error: %s" -#~ msgstr "E238: Erreur d'impression : %s" +#, c-format +msgid "E684: list index out of range: %ld" +msgstr "E684: index de Liste hors limites : %ld au-delà de la fin" -#~ msgid "Printing '%s'" -#~ msgstr "Impression de '%s'" +# DB : Suggestion +#, c-format +msgid "E118: Too many arguments for function: %s" +msgstr "E118: La fonction %s a reçu trop d'arguments" -#~ msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" -#~ msgstr "E244: Jeu de caractères \"%s\" invalide dans le nom de fonte \"%s\"" +#, c-format +msgid "E716: Key not present in Dictionary: %s" +msgstr "E716: La clé %s n'existe pas dans le Dictionnaire" -#~ msgid "E245: Illegal char '%c' in font name \"%s\"" -#~ msgstr "E245: Caractère '%c' invalide dans le nom de fonte \"%s\"" +msgid "E714: List required" +msgstr "E714: Liste requise" -#~ msgid "Opening the X display took %<PRId64> msec" -#~ msgstr "L'ouverture du display X a pris %<PRId64> ms" +#, c-format +msgid "E712: Argument of %s must be a List or Dictionary" +msgstr "E712: L'argument de %s doit être une Liste ou un Dictionnaire" -#~ msgid "" -#~ "\n" -#~ "Vim: Got X error\n" -#~ msgstr "" -#~ "\n" -#~ "Vim : Réception d'une erreur X\n" +msgid "E47: Error while reading errorfile" +msgstr "E47: Erreur lors de la lecture du fichier d'erreurs" -#~ msgid "Testing the X display failed" -#~ msgstr "Le test du display X a échoué" +msgid "E48: Not allowed in sandbox" +msgstr "E48: Opération interdite dans le bac à sable" -#~ msgid "Opening the X display timed out" -#~ msgstr "L'ouverture du display X a dépassé le délai d'attente" +msgid "E523: Not allowed here" +msgstr "E523: Interdit à cet endroit" -#~ msgid "" -#~ "\n" -#~ "Cannot execute shell sh\n" -#~ msgstr "" -#~ "\n" -#~ "Impossible d'exécuter le shell sh\n" +msgid "E359: Screen mode setting not supported" +msgstr "E359: Choix du mode d'écran non supporté" -#~ msgid "" -#~ "\n" -#~ "Cannot create pipes\n" -#~ msgstr "" -#~ "\n" -#~ "Impossible de créer des tuyaux (pipes)\n" +msgid "E49: Invalid scroll size" +msgstr "E49: Valeur de défilement invalide" -#~ msgid "" -#~ "\n" -#~ "Cannot fork\n" -#~ msgstr "" -#~ "\n" -#~ "Impossible de forker\n" +msgid "E91: 'shell' option is empty" +msgstr "E91: L'option 'shell' est vide" -#~ msgid "" -#~ "\n" -#~ "Command terminated\n" -#~ msgstr "" -#~ "\n" -#~ "Commande interrompue\n" +msgid "E255: Couldn't read in sign data!" +msgstr "E255: Impossible de lire les données du symbole !" -#~ msgid "XSMP lost ICE connection" -#~ msgstr "XSMP a perdu la connexion ICE" +msgid "E72: Close error on swap file" +msgstr "E72: Erreur lors de la fermeture du fichier d'échange" -#~ msgid "Opening the X display failed" -#~ msgstr "L'ouverture du display X a échoué" +msgid "E73: tag stack empty" +msgstr "E73: La pile des marqueurs est vide" -#~ msgid "XSMP handling save-yourself request" -#~ msgstr "XSMP : prise en charge d'une requête save-yourself" +msgid "E74: Command too complex" +msgstr "E74: Commande trop complexe" -#~ msgid "XSMP opening connection" -#~ msgstr "XSMP : ouverture de la connexion" +msgid "E75: Name too long" +msgstr "E75: Nom trop long" -#~ msgid "XSMP ICE connection watch failed" -#~ msgstr "XSMP : échec de la surveillance de connexion ICE" +msgid "E76: Too many [" +msgstr "E76: Trop de [" -#~ msgid "XSMP SmcOpenConnection failed: %s" -#~ msgstr "XSMP : SmcOpenConnection a échoué : %s" +msgid "E77: Too many file names" +msgstr "E77: Trop de noms de fichiers" -#~ msgid "At line" -#~ msgstr "À la ligne" +msgid "E488: Trailing characters" +msgstr "E488: Caractères surnuméraires" -#~ msgid "Could not load vim32.dll!" -#~ msgstr "Impossible de charger vim32.dll !" +msgid "E78: Unknown mark" +msgstr "E78: Marque inconnue" -#~ msgid "VIM Error" -#~ msgstr "Erreur VIM" +msgid "E79: Cannot expand wildcards" +msgstr "E79: Impossible de développer les métacaractères" -#~ msgid "Could not fix up function pointers to the DLL!" -#~ msgstr "Impossible d'initialiser les pointeurs de fonction vers la DLL !" +msgid "E591: 'winheight' cannot be smaller than 'winminheight'" +msgstr "E591: 'winheight' ne peut pas être plus petit que 'winminheight'" -#~ msgid "shell returned %d" -#~ msgstr "le shell a retourné %d" +msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" +msgstr "E592: 'winwidth' ne peut pas être plus petit que 'winminwidth'" -# DB - Les événements en question sont ceux des messages qui suivent. -#~ msgid "Vim: Caught %s event\n" -#~ msgstr "Vim : Événement %s intercepté\n" +msgid "E80: Error while writing" +msgstr "E80: Erreur lors de l'écriture" -#~ msgid "close" -#~ msgstr "de fermeture" +msgid "Zero count" +msgstr "Le quantificateur est nul" -#~ msgid "logoff" -#~ msgstr "de déconnexion" +msgid "E81: Using <SID> not in a script context" +msgstr "E81: <SID> utilisé en dehors d'un script" -#~ msgid "shutdown" -#~ msgstr "d'arrêt" +msgid "E449: Invalid expression received" +msgstr "E449: Expression invalide reçue" -#~ msgid "E371: Command not found" -#~ msgstr "E371: Commande introuvable" +msgid "E463: Region is guarded, cannot modify" +msgstr "E463: Cette zone est verrouillée et ne peut pas être modifiée" -#~ msgid "" -#~ "VIMRUN.EXE not found in your $PATH.\n" -#~ "External commands will not pause after completion.\n" -#~ "See :help win32-vimrun for more information." -#~ msgstr "" -#~ "VIMRUN.EXE est introuvable votre $PATH.\n" -#~ "Les commandes externes ne feront pas de pause une fois terminées.\n" -#~ "Consultez :help win32-vimrun pour plus d'informations." +msgid "E744: NetBeans does not allow changes in read-only files" +msgstr "" +"E744: NetBeans n'autorise pas la modification des fichiers en lecture seule" -#~ msgid "Vim Warning" -#~ msgstr "Alerte Vim" +msgid "E363: pattern uses more memory than 'maxmempattern'" +msgstr "E363: le motif utilise plus de mémoire que 'maxmempattern'" -#~ msgid "Error file" -#~ msgstr "Fichier d'erreurs" +msgid "E749: empty buffer" +msgstr "E749: tampon vide" -#~ msgid "E868: Error building NFA with equivalence class!" -#~ msgstr "" -#~ "E868: Erreur lors de la construction du NFA avec classe d'équivalence" +#, c-format +msgid "E86: Buffer %ld does not exist" +msgstr "E86: Le tampon %ld n'existe pas" -#~ msgid "E878: (NFA) Could not allocate memory for branch traversal!" -#~ msgstr "" -#~ "E878: (NFA) Impossible d'allouer la mémoire pour parcourir les branches!" +msgid "E682: Invalid search pattern or delimiter" +msgstr "E682: Délimiteur ou motif de recherche invalide" -#~ msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" -#~ msgstr "" -#~ "Alerte : Liste de mots \"%s_%s.spl\" ou \"%s_ascii.spl\" introuvable" +msgid "E139: File is loaded in another buffer" +msgstr "E139: Le fichier est chargé dans un autre tampon" -#~ msgid "Conversion in %s not supported" -#~ msgstr "La conversion dans %s non supportée" +#, c-format +msgid "E764: Option '%s' is not set" +msgstr "E764: L'option '%s' n'est pas activée" -#~ msgid "E845: Insufficient memory, word list will be incomplete" -#~ msgstr "E845: mémoire insuffisante, liste de mots peut-être incomplète" +msgid "E850: Invalid register name" +msgstr "E850: Nom de registre invalide" -#~ msgid "E430: Tag file path truncated for %s\n" -#~ msgstr "E430: Chemin de fichiers de marqueurs tronqué pour %s\n" +#, c-format +msgid "E919: Directory not found in '%s': \"%s\"" +msgstr "E919: Répertoire introuvable dans '%s' : \"%s\"" -#~ msgid "new shell started\n" -#~ msgstr "nouveau shell démarré\n" +msgid "search hit TOP, continuing at BOTTOM" +msgstr "La recherche a atteint le HAUT, et continue en BAS" -# DB - Message de débogage. -#~ msgid "Used CUT_BUFFER0 instead of empty selection" -#~ msgstr "CUT_BUFFER0 utilisé plutôt qu'une sélection vide" +msgid "search hit BOTTOM, continuing at TOP" +msgstr "La recherche a atteint le BAS, et continue en HAUT" -# DB - Question O/N. -#~ msgid "No undo possible; continue anyway" -#~ msgstr "Annulation impossible ; continuer" - -#~ msgid "E832: Non-encrypted file has encrypted undo file: %s" -#~ msgstr "E832: Fichier non-chiffré a un fichier d'annulations chiffré : %s" - -#~ msgid "E826: Undo file decryption failed: %s" -#~ msgstr "E826: Déchiffrage du fichier d'annulation a échoué : %s" - -#~ msgid "E827: Undo file is encrypted: %s" -#~ msgstr "E827: Le fichier d'annulations est chiffré : %s" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16/32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Version graphique MS-Windows 16/32 bits" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Version graphique MS-Windows 64 bits" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Version graphique MS-Windows 32 bits" - -#~ msgid " in Win32s mode" -#~ msgstr " lancée en mode Win32s" - -#~ msgid " with OLE support" -#~ msgstr " supportant l'OLE" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit console version" -#~ msgstr "" -#~ "\n" -#~ "Version console MS-Windows 64 bits" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit console version" -#~ msgstr "" -#~ "\n" -#~ "Version console MS-Windows 32 bits" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16-bit version" -#~ msgstr "" -#~ "\n" -#~ "Version MS-Windows 16 bits" - -#~ msgid "" -#~ "\n" -#~ "32-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "Version MS-DOS 32 bits" - -#~ msgid "" -#~ "\n" -#~ "16-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "Version MS-DOS 16 bits" - -#~ msgid "" -#~ "\n" -#~ "MacOS X (unix) version" -#~ msgstr "" -#~ "\n" -#~ "Version MaxOS X (unix)" - -#~ msgid "" -#~ "\n" -#~ "MacOS X version" -#~ msgstr "" -#~ "\n" -#~ "Version MacOS X" - -#~ msgid "" -#~ "\n" -#~ "MacOS version" -#~ msgstr "" -#~ "\n" -#~ "Version MacOS" - -#~ msgid "" -#~ "\n" -#~ "OpenVMS version" -#~ msgstr "" -#~ "\n" -#~ "Version OpenVMS" - -#~ msgid "" -#~ "\n" -#~ "Big version " -#~ msgstr "" -#~ "\n" -#~ "Grosse version " - -#~ msgid "" -#~ "\n" -#~ "Normal version " -#~ msgstr "" -#~ "\n" -#~ "Version normale " - -#~ msgid "" -#~ "\n" -#~ "Small version " -#~ msgstr "" -#~ "\n" -#~ "Petite version " - -#~ msgid "" -#~ "\n" -#~ "Tiny version " -#~ msgstr "" -#~ "\n" -#~ "Version minuscule " - -#~ msgid "with GTK2-GNOME GUI." -#~ msgstr "avec interface graphique GTK2-GNOME." - -#~ msgid "with GTK2 GUI." -#~ msgstr "avec interface graphique GTK2." - -#~ msgid "with X11-Motif GUI." -#~ msgstr "avec interface graphique X11-Motif." - -#~ msgid "with X11-neXtaw GUI." -#~ msgstr "avec interface graphique X11-neXtaw." - -#~ msgid "with X11-Athena GUI." -#~ msgstr "avec interface graphique X11-Athena." - -#~ msgid "with Photon GUI." -#~ msgstr "avec interface graphique Photon." - -#~ msgid "with GUI." -#~ msgstr "avec une interface graphique." - -#~ msgid "with Carbon GUI." -#~ msgstr "avec interface graphique Carbon." - -#~ msgid "with Cocoa GUI." -#~ msgstr "avec interface graphique Cocoa." - -#~ msgid "with (classic) GUI." -#~ msgstr "avec interface graphique (classic)." - -#~ msgid " system gvimrc file: \"" -#~ msgstr " fichier gvimrc système : \"" - -#~ msgid " user gvimrc file: \"" -#~ msgstr " fichier gvimrc utilisateur : \"" - -#~ msgid "2nd user gvimrc file: \"" -#~ msgstr "2me fichier gvimrc utilisateur : \"" - -#~ msgid "3rd user gvimrc file: \"" -#~ msgstr "3me fichier gvimrc utilisateur : \"" - -#~ msgid " system menu file: \"" -#~ msgstr " fichier menu système : \"" - -#~ msgid "Compiler: " -#~ msgstr "Compilateur : " +#, c-format +msgid "Need encryption key for \"%s\"" +msgstr "Besoin de la clé de chiffrement pour \"%s\"" -#~ msgid "menu Help->Orphans for information " -#~ msgstr "menu Aide->Orphelins pour plus d'info" +msgid "empty keys are not allowed" +msgstr "les clés vides ne sont pas autorisées" -#~ msgid "Running modeless, typed text is inserted" -#~ msgstr "Les modes sont désactivés, le texte saisi est inséré" +msgid "dictionary is locked" +msgstr "dictionnaire est verrouillé" -#~ msgid "menu Edit->Global Settings->Toggle Insert Mode " -#~ msgstr "menu Édition->Réglages Globaux->Insertion Permanente" +msgid "list is locked" +msgstr "liste verrouillée" -# DB - todo -#~ msgid " for two modes " -#~ msgstr " pour les modes " +#, c-format +msgid "failed to add key '%s' to dictionary" +msgstr "l'ajout de clé '%s' au dictionnaire a échoué" -# DB - todo -#~ msgid "menu Edit->Global Settings->Toggle Vi Compatible" -#~ msgstr "menu Édition->Réglages Globaux->Compatibilité Vi" +#, c-format +msgid "index must be int or slice, not %s" +msgstr "index doit être int ou slice, et non %s" -# DB - todo -#~ msgid " for Vim defaults " -#~ msgstr " pour déf. de Vim " +#, c-format +msgid "expected str() or unicode() instance, but got %s" +msgstr "attendu instance de str() ou unicode(), mais reçu %s" -#~ msgid "WARNING: Windows 95/98/ME detected" -#~ msgstr "ALERTE: Windows 95/98/ME détecté" +#, c-format +msgid "expected bytes() or str() instance, but got %s" +msgstr "attendu instance de bytes() ou str(), mais reçu %s" -#~ msgid "type :help windows95<Enter> for info on this" -#~ msgstr "tapez :help windows95<Entrée> pour plus d'information" +#, c-format +msgid "" +"expected int(), long() or something supporting coercing to long(), but got %s" +msgstr "" +"attendu int(), long() ou quelque chose qui peut être transformé en long(), " +"mais reçu %s" -#~ msgid "E370: Could not load library %s" -#~ msgstr "E370: Impossible de charger la bibliothèque %s" +#, c-format +msgid "expected int() or something supporting coercing to int(), but got %s" +msgstr "" +"attendu int() ou quelque chose qui peut être transformé en int(), mais reçu " +"%s" -#~ msgid "" -#~ "Sorry, this command is disabled: the Perl library could not be loaded." -#~ msgstr "" -#~ "Désolé, commande désactivée : la bibliothèque Perl n'a pas pu être " -#~ "chargée." +msgid "value is too large to fit into C int type" +msgstr "valeur trop grande pour être stockée dans le type C int" -#~ msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" -#~ msgstr "" -#~ "E299: Évaluation Perl interdite dans bac à sable sans le module Safe" +msgid "value is too small to fit into C int type" +msgstr "valeur trop petite pour être stockée dans le type C int" -#~ msgid "Edit with &multiple Vims" -#~ msgstr "Éditer dans &plusieurs Vims" +msgid "number must be greater than zero" +msgstr "le nombre doit être plus grand que zéro" -#~ msgid "Edit with single &Vim" -#~ msgstr "Éditer dans un seul &Vim" +msgid "number must be greater or equal to zero" +msgstr "le nombre doit être plus grand ou égal à zéro" -#~ msgid "Diff with Vim" -#~ msgstr "&Comparer avec Vim" +msgid "can't delete OutputObject attributes" +msgstr "impossible d'effacer les attributs d'OutputObject" -#~ msgid "Edit with &Vim" -#~ msgstr "Éditer dans &Vim" +#, c-format +msgid "invalid attribute: %s" +msgstr "attribut invalide : %s" -#~ msgid "Edit with existing Vim - " -#~ msgstr "Éditer dans le Vim existant - " +msgid "E264: Python: Error initialising I/O objects" +msgstr "E264: Python : Erreur d'initialisation des objets d'E/S" -#~ msgid "Edits the selected file(s) with Vim" -#~ msgstr "Édites le(s) fichier(s) sélectionné(s) avec Vim" +msgid "failed to change directory" +msgstr "changement de répertoire a échoué" -# DB - MessageBox win32, la longueur n'est pas un problème ! -#~ msgid "Error creating process: Check if gvim is in your path!" -#~ msgstr "" -#~ "Erreur de création du processus : vérifiez que gvim est bien dans votre " -#~ "chemin !" +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got %s" +msgstr "attendu un 3-tuple comme résultat de imp.find_module(), mais reçu %s" -#~ msgid "gvimext.dll error" -#~ msgstr "Erreur de gvimext.dll" +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got tuple of size %d" +msgstr "" +"attendu un 3-tuple comme résultat de imp.find_module(), mais reçu un tuple " +"de taille %d" -#~ msgid "Path length too long!" -#~ msgstr "Le chemin est trop long !" +msgid "internal error: imp.find_module returned tuple with NULL" +msgstr "erreur interne : imp.find_module a retourné un tuple contenant NULL" -#~ msgid "E234: Unknown fontset: %s" -#~ msgstr "E234: Jeu de police inconnu : %s" +msgid "cannot delete vim.Dictionary attributes" +msgstr "impossible d'effacer les attributs de vim.Dictionary" -#~ msgid "E235: Unknown font: %s" -#~ msgstr "E235: Police inconnue : %s" +msgid "cannot modify fixed dictionary" +msgstr "impossible de modifier un dictionnaire fixe" -#~ msgid "E236: Font \"%s\" is not fixed-width" -#~ msgstr "E236: La police \"%s\" n'a pas une chasse (largeur) fixe" +#, c-format +msgid "cannot set attribute %s" +msgstr "impossible d'initialiser l'attribut %s" -#~ msgid "E448: Could not load library function %s" -#~ msgstr "E448: Impossible de charger la fonction %s de la bibliothèque" +msgid "hashtab changed during iteration" +msgstr "la table de hachage a été changée pendant une itération" -#~ msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" -#~ msgstr "" -#~ "E26: Le support de l'hébreu n'a pas été compilé dans cette version\n" +#, c-format +msgid "expected sequence element of size 2, but got sequence of size %d" +msgstr "" +"attendu une séquence d'éléments de taille 2, mais reçu une séquence de " +"taille %d" -#~ msgid "E27: Farsi cannot be used: Not enabled at compile time\n" -#~ msgstr "E27: Le support du farsi n'a pas été compilé dans cette version\n" +msgid "list constructor does not accept keyword arguments" +msgstr "le constructeur de liste n'accepte pas les arguments nommés" -#~ msgid "E800: Arabic cannot be used: Not enabled at compile time\n" -#~ msgstr "" -#~ "E800: Le support de l'arabe n'a pas été compilé dans cette version\n" +msgid "list index out of range" +msgstr "index de liste hors limites" -#~ msgid "E247: no registered server named \"%s\"" -#~ msgstr "E247: aucun serveur nommé \"%s\" n'est enregistré" +#. No more suitable format specifications in python-2.3 +#, c-format +msgid "internal error: failed to get vim list item %d" +msgstr "erreur interne : accès à un élément %d de liste a échoué" -#~ msgid "E233: cannot open display" -#~ msgstr "E233: ouverture du display impossible" +msgid "slice step cannot be zero" +msgstr "le pas du découpage en tranche ne peut pas être zéro" -#~ msgid "E449: Invalid expression received" -#~ msgstr "E449: Expression invalide reçue" +#, c-format +msgid "attempt to assign sequence of size greater than %d to extended slice" +msgstr "" +"tentative d'assigner une séquence de taille plus grande que %d à un " +"découpage en tranche étendu " -#~ msgid "E463: Region is guarded, cannot modify" -#~ msgstr "E463: Cette zone est verrouillée et ne peut pas être modifiée" +#, c-format +msgid "internal error: no vim list item %d" +msgstr "erreur interne : pas d'élément %d de liste vim" -#~ msgid "E744: NetBeans does not allow changes in read-only files" -#~ msgstr "" -#~ "E744: NetBeans n'autorise pas la modification des fichiers en lecture " -#~ "seule" +msgid "internal error: not enough list items" +msgstr "erreur interne : pas assez d'éléments de liste" -#~ msgid "Need encryption key for \"%s\"" -#~ msgstr "Besoin de la clé de chiffrement pour \"%s\"" +msgid "internal error: failed to add item to list" +msgstr "erreur interne : ajout d'élément à la liste a échoué" -#~ msgid "can't delete OutputObject attributes" -#~ msgstr "impossible d'effacer les attributs d'OutputObject" +#, c-format +msgid "attempt to assign sequence of size %d to extended slice of size %d" +msgstr "" +"tentative d'assigner une séquence de taille %d à un découpage en tranche " +"étendu de taille %d" -#~ msgid "invalid attribute" -#~ msgstr "attribut invalide" +msgid "failed to add item to list" +msgstr "ajout à la liste a échoué" -#~ msgid "E264: Python: Error initialising I/O objects" -#~ msgstr "E264: Python : Erreur d'initialisation des objets d'E/S" +msgid "cannot delete vim.List attributes" +msgstr "impossible d'effacer les attributs de vim.List" -#~ msgid "empty keys are not allowed" -#~ msgstr "les clés vides ne sont pas autorisées" +msgid "cannot modify fixed list" +msgstr "impossible de modifier une liste fixe" -#~ msgid "Cannot modify fixed dictionary" -#~ msgstr "Impossible de modifier un dictionnaire fixe" +#, c-format +msgid "unnamed function %s does not exist" +msgstr "la fonction sans nom %s n'existe pas" -#~ msgid "dict is locked" -#~ msgstr "dictionnaire est verrouillé" +#, c-format +msgid "function %s does not exist" +msgstr "la fonction %s n'existe pas" -#~ msgid "failed to add key to dictionary" -#~ msgstr "l'ajout de clé au dictionnaire a échoué" +#, c-format +msgid "failed to run function %s" +msgstr "exécution de la fonction %s a échoué" -#~ msgid "list index out of range" -#~ msgstr "index de liste hors limites" +msgid "unable to get option value" +msgstr "impossible d'obtenir la valeur d'une option" -#~ msgid "internal error: failed to get vim list item" -#~ msgstr "erreur interne : accès à un élément de liste a échoué" +msgid "internal error: unknown option type" +msgstr "erreur interne : type d'option inconnu" -#~ msgid "list is locked" -#~ msgstr "liste verrouillée" +msgid "problem while switching windows" +msgstr "problème lors du changement de fenêtres" -#~ msgid "Failed to add item to list" -#~ msgstr "Ajout à la liste a échoué" +#, c-format +msgid "unable to unset global option %s" +msgstr "impossible de désactiver une option globale %s" -#~ msgid "internal error: failed to add item to list" -#~ msgstr "erreur interne : ajout d'élément à la liste a échoué" +#, c-format +msgid "unable to unset option %s which does not have global value" +msgstr "impossible de désactiver l'option %s qui n'a pas de valeur globale" -#~ msgid "cannot delete vim.dictionary attributes" -#~ msgstr "impossible d'effacer les attributs de vim.dictionary" +msgid "attempt to refer to deleted tab page" +msgstr "tentative de référencer un onglet effacé" -#~ msgid "cannot modify fixed list" -#~ msgstr "impossible de modifier une liste fixe" +msgid "no such tab page" +msgstr "cet onglet n'existe pas" -#~ msgid "cannot set this attribute" -#~ msgstr "impossible d'initialiser cet attribut" +msgid "attempt to refer to deleted window" +msgstr "tentative de référencer une fenêtre effacée" -#~ msgid "failed to run function" -#~ msgstr "exécution de la fonction a échoué" +msgid "readonly attribute: buffer" +msgstr "attribut en lecture seule : tampon" -#~ msgid "unable to unset global option" -#~ msgstr "impossible de désactiver une option globale" +msgid "cursor position outside buffer" +msgstr "curseur positionné en dehors du tampon" -#~ msgid "unable to unset option without global value" -#~ msgstr "impossible de désactiver une option sans une valeur globale" +msgid "no such window" +msgstr "Cette fenêtre n'existe pas" -#~ msgid "attempt to refer to deleted tab page" -#~ msgstr "tentative de référencer un onglet effacé" +msgid "attempt to refer to deleted buffer" +msgstr "tentative de référencer un tampon effacé" -#~ msgid "no such tab page" -#~ msgstr "cet onglet n'existe pas" +msgid "failed to rename buffer" +msgstr "impossible de renommer le tampon" -#~ msgid "attempt to refer to deleted window" -#~ msgstr "tentative de référencer une fenêtre effacée" +msgid "mark name must be a single character" +msgstr "le nom de marque doit être un seul caractère" -#~ msgid "readonly attribute" -#~ msgstr "attribut en lecture seule" +#, c-format +msgid "expected vim.Buffer object, but got %s" +msgstr "attendu un objet vim.Buffer, mais reçu %s" -#~ msgid "cursor position outside buffer" -#~ msgstr "curseur positionné en dehors du tampon" +#, c-format +msgid "failed to switch to buffer %d" +msgstr "impossible de se déplacer au tampon %d" -#~ msgid "no such window" -#~ msgstr "Cette fenêtre n'existe pas" +#, c-format +msgid "expected vim.Window object, but got %s" +msgstr "attendu un objet vim.Window, mais reçu %s" -#~ msgid "attempt to refer to deleted buffer" -#~ msgstr "tentative de référencer un tampon effacé" +msgid "failed to find window in the current tab page" +msgstr "impossible de trouver une fenêtre dans l'onglet courant" -#~ msgid "expected vim.buffer object" -#~ msgstr "objet vim.buffer attendu" +msgid "did not switch to the specified window" +msgstr "ne s'est pas déplacé à la fenêtre spécifiée" -#~ msgid "failed to switch to given buffer" -#~ msgstr "impossible de se déplacer au tampon donné" +#, c-format +msgid "expected vim.TabPage object, but got %s" +msgstr "attendu un objet vim.TabPage, mais reçu %s" -#~ msgid "expected vim.window object" -#~ msgstr "objet vim.window attendu" +msgid "did not switch to the specified tab page" +msgstr "impossible de se déplacer à l'onglet spécifié" -#~ msgid "failed to find window in the current tab page" -#~ msgstr "impossible de trouver une fenêtre dans l'onglet courant" +msgid "failed to run the code" +msgstr "exécution du code a échoué" -#~ msgid "did not switch to the specified window" -#~ msgstr "ne s'est pas déplacé à la fenêtre spécifiée" +msgid "E858: Eval did not return a valid python object" +msgstr "E858: Eval n'a pas retourné un objet python valide" -#~ msgid "expected vim.tabpage object" -#~ msgstr "objet vim.tabpage attendu" +msgid "E859: Failed to convert returned python object to vim value" +msgstr "E859: Conversion d'objet python à une valeur de vim a échoué" -#~ msgid "did not switch to the specified tab page" -#~ msgstr "impossible de se déplacer à l'onglet spécifié" +#, c-format +msgid "unable to convert %s to vim dictionary" +msgstr "impossible de convertir %s à un dictionnaire vim" -#~ msgid "failed to run the code" -#~ msgstr "exécution du code a échoué" +#, c-format +msgid "unable to convert %s to vim list" +msgstr "impossible de convertir %s à une liste de vim" -#~ msgid "E858: Eval did not return a valid python object" -#~ msgstr "E858: Eval n'a pas retourné un objet python valide" +#, c-format +msgid "unable to convert %s to vim structure" +msgstr "impossible de convertir %s à une structure de vim" -#~ msgid "E859: Failed to convert returned python object to vim value" -#~ msgstr "E859: Conversion d'objet python à une valeur de vim a échoué" +msgid "internal error: NULL reference passed" +msgstr "erreur interne : référence NULL passée" -#~ msgid "unable to convert to vim structure" -#~ msgstr "conversion à une structure vim impossible" +msgid "internal error: invalid value type" +msgstr "erreur interne : type de valeur invalide" -#~ msgid "NULL reference passed" -#~ msgstr "référence NULL passée" +msgid "" +"Failed to set path hook: sys.path_hooks is not a list\n" +"You should now do the following:\n" +"- append vim.path_hook to sys.path_hooks\n" +"- append vim.VIM_SPECIAL_PATH to sys.path\n" +msgstr "" +"Impossible d'initialiser sys.path_hook qui n'est pas un liste\n" +"Vous devez maintenant :\n" +"- ajouter vim.path_hook à sys.path_hooks\n" +"- ajouter vim.VIM_SPECIAL_PATH à sys.path\n" -#~ msgid "internal error: invalid value type" -#~ msgstr "erreur interne : type de valeur invalide" +msgid "" +"Failed to set path: sys.path is not a list\n" +"You should now append vim.VIM_SPECIAL_PATH to sys.path" +msgstr "" +"Impossible d'initialiser le chemin : sys.math n'est pas une liste\n" +"Vous devez maintenant ajouter vim.VIM_SPECIAL_PATH à sys.path" diff --git a/src/nvim/po/ga.po b/src/nvim/po/ga.po index 761539039d..abb3565077 100644 --- a/src/nvim/po/ga.po +++ b/src/nvim/po/ga.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: vim 7.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-05-26 14:21+0200\n" +"POT-Creation-Date: 2016-10-25 09:31-0500\n" "PO-Revision-Date: 2010-04-14 10:01-0500\n" "Last-Translator: Kevin Patrick Scannell <kscanne@gmail.com>\n" "Language-Team: Irish <gaeilge-gnulinux@lists.sourceforge.net>\n" @@ -14,208 +14,171 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=5; plural=n==1 ? 0 : n==2 ? 1 : (n>2 && n<7) ? 2 :" +"(n>6 && n<11) ? 3 : 4;\n" -#: ../api/private/helpers.c:201 -#, fuzzy -msgid "Unable to get option value" -msgstr "Dramhaíl i ndiaidh argóinte rogha" +msgid "E831: bf_key_init() called with empty password" +msgstr "E831: cuireadh glaoch ar bf_key_init() le focal faire folamh" -#: ../api/private/helpers.c:204 -msgid "internal error: unknown option type" -msgstr "" +msgid "E820: sizeof(uint32_t) != 4" +msgstr "E820: sizeof(uint32_t) != 4" + +msgid "E817: Blowfish big/little endian use wrong" +msgstr "E817: Úsáid mhícheart Blowfish mórcheannach/caolcheannach" + +msgid "E818: sha256 test failed" +msgstr "E818: Theip ar thástáil sha256" + +msgid "E819: Blowfish test failed" +msgstr "E819: Theip ar thástáil Blowfish" -#: ../buffer.c:92 msgid "[Location List]" msgstr "[Liosta Suíomh]" -#: ../buffer.c:93 msgid "[Quickfix List]" -msgstr "[Liosta Ceartúchán Tapa]" +msgstr "[Liosta Mearcheartúchán]" -#: ../buffer.c:94 -#, fuzzy msgid "E855: Autocommands caused command to abort" -msgstr "E812: Bhí maolán nó ainm maoláin athraithe ag orduithe uathoibríocha" +msgstr "E855: Tobscoireadh an t-ordú mar gheall ar uathorduithe" -#: ../buffer.c:135 msgid "E82: Cannot allocate any buffer, exiting..." msgstr "E82: Ní féidir maolán a dháileadh, ag scor..." -#: ../buffer.c:138 msgid "E83: Cannot allocate buffer, using other one..." msgstr "E83: Ní féidir maolán a dháileadh, ag úsáid cinn eile..." -#: ../buffer.c:763 +msgid "E931: Buffer cannot be registered" +msgstr "E931: Ní féidir an maolán a chlárú" + +msgid "E937: Attempt to delete a buffer that is in use" +msgstr "E937: Iarracht ar mhaolán in úsáid a scriosadh" + msgid "E515: No buffers were unloaded" msgstr "E515: Ní raibh aon mhaolán díluchtaithe" -#: ../buffer.c:765 msgid "E516: No buffers were deleted" msgstr "E516: Ní raibh aon mhaolán scriosta" -#: ../buffer.c:767 msgid "E517: No buffers were wiped out" msgstr "E517: Ní raibh aon mhaolán bánaithe" -#: ../buffer.c:772 msgid "1 buffer unloaded" msgstr "Bhí maolán amháin díluchtaithe" -#: ../buffer.c:774 #, c-format msgid "%d buffers unloaded" msgstr "%d maolán folmhaithe" -#: ../buffer.c:777 msgid "1 buffer deleted" msgstr "Bhí maolán amháin scriosta" -#: ../buffer.c:779 #, c-format msgid "%d buffers deleted" msgstr "%d maolán scriosta" -#: ../buffer.c:782 msgid "1 buffer wiped out" msgstr "Bhí maolán amháin bánaithe" -#: ../buffer.c:784 #, c-format msgid "%d buffers wiped out" msgstr "%d maolán bánaithe" -#: ../buffer.c:806 msgid "E90: Cannot unload last buffer" msgstr "E90: Ní féidir an maolán deireanach a dhíluchtú" -#: ../buffer.c:874 msgid "E84: No modified buffer found" msgstr "E84: Níor aimsíodh maolán mionathraithe" #. back where we started, didn't find anything. -#: ../buffer.c:903 msgid "E85: There is no listed buffer" msgstr "E85: Níl aon mhaolán liostaithe ann" -#: ../buffer.c:913 -#, c-format -msgid "E86: Buffer %<PRId64> does not exist" -msgstr "E86: Níl a leithéid de mhaolán %<PRId64>" - -#: ../buffer.c:915 msgid "E87: Cannot go beyond last buffer" msgstr "E87: Ní féidir a dhul thar an maolán deireanach" -#: ../buffer.c:917 msgid "E88: Cannot go before first buffer" msgstr "E88: Ní féidir a dhul roimh an chéad mhaolán" -#: ../buffer.c:945 #, c-format -msgid "" -"E89: No write since last change for buffer %<PRId64> (add ! to override)" +msgid "E89: No write since last change for buffer %ld (add ! to override)" msgstr "" -"E89: Athraíodh maolán %<PRId64> ach nach bhfuil sé sábháilte ó shin (cuir ! " -"leis an ordú chun sárú)" +"E89: Athraíodh maolán %ld ach nach bhfuil sé sábháilte ó shin (cuir ! leis " +"an ordú chun sárú)" -#. wrap around (may cause duplicates) -#: ../buffer.c:1423 msgid "W14: Warning: List of file names overflow" msgstr "W14: Rabhadh: Liosta ainmneacha comhaid thar maoil" -#: ../buffer.c:1555 ../quickfix.c:3361 #, c-format -msgid "E92: Buffer %<PRId64> not found" -msgstr "E92: Maolán %<PRId64> gan aimsiú" +msgid "E92: Buffer %ld not found" +msgstr "E92: Maolán %ld gan aimsiú" -#: ../buffer.c:1798 #, c-format msgid "E93: More than one match for %s" msgstr "E93: Níos mó ná teaghrán amháin comhoiriúnaithe le %s" -#: ../buffer.c:1800 #, c-format msgid "E94: No matching buffer for %s" msgstr "E94: Níl aon mhaolán comhoiriúnaithe le %s" -#: ../buffer.c:2161 #, c-format -msgid "line %<PRId64>" -msgstr "líne %<PRId64>:" +msgid "line %ld" +msgstr "líne %ld:" -#: ../buffer.c:2233 msgid "E95: Buffer with this name already exists" msgstr "E95: Tá maolán ann leis an ainm seo cheana" -#: ../buffer.c:2498 msgid " [Modified]" msgstr " [Mionathraithe]" -#: ../buffer.c:2501 msgid "[Not edited]" msgstr "[Gan eagrú]" -#: ../buffer.c:2504 msgid "[New file]" msgstr "[Comhad nua]" -#: ../buffer.c:2505 msgid "[Read errors]" msgstr "[Earráidí léimh]" -#: ../buffer.c:2506 ../buffer.c:3217 ../fileio.c:1807 ../screen.c:4895 msgid "[RO]" msgstr "[L-A]" -#: ../buffer.c:2507 ../fileio.c:1807 msgid "[readonly]" msgstr "[inléite amháin]" -#: ../buffer.c:2524 #, c-format msgid "1 line --%d%%--" msgstr "1 líne --%d%%--" -#: ../buffer.c:2526 #, c-format -msgid "%<PRId64> lines --%d%%--" -msgstr "%<PRId64> líne --%d%%--" +msgid "%ld lines --%d%%--" +msgstr "%ld líne --%d%%--" -#: ../buffer.c:2530 #, c-format -msgid "line %<PRId64> of %<PRId64> --%d%%-- col " -msgstr "líne %<PRId64> de %<PRId64> --%d%%-- col " +msgid "line %ld of %ld --%d%%-- col " +msgstr "líne %ld de %ld --%d%%-- col " -#: ../buffer.c:2632 ../buffer.c:4292 ../memline.c:1554 msgid "[No Name]" msgstr "[Gan Ainm]" #. must be a help buffer -#: ../buffer.c:2667 msgid "help" msgstr "cabhair" -#: ../buffer.c:3225 ../screen.c:4883 msgid "[Help]" msgstr "[Cabhair]" -#: ../buffer.c:3254 ../screen.c:4887 msgid "[Preview]" msgstr "[Réamhamharc]" -#: ../buffer.c:3528 msgid "All" msgstr "Uile" -#: ../buffer.c:3528 msgid "Bot" msgstr "Bun" -#: ../buffer.c:3531 msgid "Top" msgstr "Barr" -#: ../buffer.c:4244 msgid "" "\n" "# Buffer list:\n" @@ -223,11 +186,9 @@ msgstr "" "\n" "# Liosta maoláin:\n" -#: ../buffer.c:4289 msgid "[Scratch]" msgstr "[Sealadach]" -#: ../buffer.c:4529 msgid "" "\n" "--- Signs ---" @@ -235,202 +196,236 @@ msgstr "" "\n" "--- Comharthaí ---" -#: ../buffer.c:4538 #, c-format msgid "Signs for %s:" msgstr "Comharthaí do %s:" -#: ../buffer.c:4543 #, c-format -msgid " line=%<PRId64> id=%d name=%s" -msgstr " líne=%<PRId64> id=%d ainm=%s" +msgid " line=%ld id=%d name=%s" +msgstr " líne=%ld id=%d ainm=%s" -#: ../cursor_shape.c:68 -msgid "E545: Missing colon" -msgstr "E545: Idirstad ar iarraidh" +msgid "E902: Cannot connect to port" +msgstr "E902: Ní féidir ceangal leis an bport" -#: ../cursor_shape.c:70 ../cursor_shape.c:94 -msgid "E546: Illegal mode" -msgstr "E546: Mód neamhcheadaithe" +msgid "E901: gethostbyname() in channel_open()" +msgstr "E901: gethostbyname() in channel_open()" -#: ../cursor_shape.c:134 -msgid "E548: digit expected" -msgstr "E548: ag súil le digit" +msgid "E898: socket() in channel_open()" +msgstr "E898: socket() in channel_open()" -#: ../cursor_shape.c:138 -msgid "E549: Illegal percentage" -msgstr "E549: Céatadán neamhcheadaithe" +msgid "E903: received command with non-string argument" +msgstr "E903: fuarthas ordú le hargóint nach bhfuil ina theaghrán" + +msgid "E904: last argument for expr/call must be a number" +msgstr "E904: ní mór don argóint dheireanach ar expr/call a bheith ina huimhir" + +msgid "E904: third argument for call must be a list" +msgstr "E904: Caithfidh an tríú argóint a bheith ina liosta" + +#, c-format +msgid "E905: received unknown command: %s" +msgstr "E905: fuarthas ordú anaithnid: %s" + +#, c-format +msgid "E630: %s(): write while not connected" +msgstr "E630: %s(): scríobh gan ceangal a bheith ann" + +#, c-format +msgid "E631: %s(): write failed" +msgstr "E631: %s(): theip ar scríobh" + +#, c-format +msgid "E917: Cannot use a callback with %s()" +msgstr "E917: Ní féidir aisghlaoch a úsáid le %s()" + +msgid "E912: cannot use ch_evalexpr()/ch_sendexpr() with a raw or nl channel" +msgstr "E912: ní féidir ch_evalexpr()/ch_sendexpr() a úsáid le cainéal raw nó nl" + +msgid "E906: not an open channel" +msgstr "E906: ní cainéal oscailte é" + +msgid "E920: _io file requires _name to be set" +msgstr "E920: caithfear _name a shocrú chun comhad _io a úsáid" + +msgid "E915: in_io buffer requires in_buf or in_name to be set" +msgstr "E915: caithfear in_buf nó in_name a shocrú chun maolán in_io a úsáid" + +#, c-format +msgid "E918: buffer must be loaded: %s" +msgstr "E918: ní mór an maolán a luchtú: %s" + +msgid "E821: File is encrypted with unknown method" +msgstr "E821: Comhad criptithe le modh anaithnid" + +msgid "Warning: Using a weak encryption method; see :help 'cm'" +msgstr "Rabhadh: Criptiúchán lag; féach :help 'cm'" + +msgid "Enter encryption key: " +msgstr "Iontráil eochair chriptiúcháin: " + +msgid "Enter same key again: " +msgstr "Iontráil an eochair arís: " + +msgid "Keys don't match!" +msgstr "Níl na heochracha comhoiriúnach le chéile!" + +msgid "[crypted]" +msgstr "[criptithe]" -#: ../diff.c:146 #, c-format -msgid "E96: Can not diff more than %<PRId64> buffers" -msgstr "E96: Ní féidir diff a dhéanamh ar níos mó ná %<PRId64> maolán" +msgid "E720: Missing colon in Dictionary: %s" +msgstr "E720: Idirstad ar iarraidh i bhFoclóir: %s" + +#, c-format +msgid "E721: Duplicate key in Dictionary: \"%s\"" +msgstr "E721: Eochair dhúblach i bhFoclóir: \"%s\"" + +#, c-format +msgid "E722: Missing comma in Dictionary: %s" +msgstr "E722: Camóg ar iarraidh i bhFoclóir: %s" + +#, c-format +msgid "E723: Missing end of Dictionary '}': %s" +msgstr "E723: '}' ar iarraidh ag deireadh foclóra: %s" + +msgid "extend() argument" +msgstr "argóint extend()" + +#, c-format +msgid "E737: Key already exists: %s" +msgstr "E737: Tá eochair ann cheana: %s" + +#, c-format +msgid "E96: Cannot diff more than %ld buffers" +msgstr "E96: Ní féidir diff a dhéanamh ar níos mó ná %ld maolán" -#: ../diff.c:753 msgid "E810: Cannot read or write temp files" msgstr "E810: Ní féidir comhaid shealadacha a léamh nó a scríobh" -#: ../diff.c:755 msgid "E97: Cannot create diffs" msgstr "E97: Ní féidir diffeanna a chruthú" -#: ../diff.c:966 +msgid "Patch file" +msgstr "Comhad paiste" + msgid "E816: Cannot read patch output" msgstr "E816: Ní féidir aschur ó 'patch' a léamh" -#: ../diff.c:1220 msgid "E98: Cannot read diff output" msgstr "E98: Ní féidir aschur ó 'diff' a léamh" -#: ../diff.c:2081 msgid "E99: Current buffer is not in diff mode" msgstr "E99: Níl an maolán reatha sa mhód diff" -#: ../diff.c:2100 msgid "E793: No other buffer in diff mode is modifiable" msgstr "E793: Ní féidir aon mhaolán eile a athrú sa mhód diff" -#: ../diff.c:2102 msgid "E100: No other buffer in diff mode" msgstr "E100: Níl aon mhaolán eile sa mhód diff" -#: ../diff.c:2112 msgid "E101: More than two buffers in diff mode, don't know which one to use" msgstr "" "E101: Tá níos mó ná dhá mhaolán sa mhód diff, níl fhios agam cé acu ba chóir " "a úsáid" -#: ../diff.c:2141 #, c-format msgid "E102: Can't find buffer \"%s\"" msgstr "E102: Tá maolán \"%s\" gan aimsiú" -#: ../diff.c:2152 #, c-format msgid "E103: Buffer \"%s\" is not in diff mode" msgstr "E103: Níl maolán \"%s\" i mód diff" -#: ../diff.c:2193 msgid "E787: Buffer changed unexpectedly" msgstr "E787: Athraíodh an maolán gan choinne" -#: ../digraph.c:1598 msgid "E104: Escape not allowed in digraph" msgstr "E104: Ní cheadaítear carachtair éalúcháin i ndéghraf" -#: ../digraph.c:1760 msgid "E544: Keymap file not found" msgstr "E544: Comhad eochairmhapála gan aimsiú" -#: ../digraph.c:1785 msgid "E105: Using :loadkeymap not in a sourced file" msgstr "E105: Ag úsáid :loadkeymap ach ní comhad foinsithe é seo" -#: ../digraph.c:1821 msgid "E791: Empty keymap entry" msgstr "E791: Iontráil fholamh eochairmhapála" -#: ../edit.c:82 msgid " Keyword completion (^N^P)" msgstr " Comhlánú lorgfhocal (^N^P)" #. ctrl_x_mode == 0, ^P/^N compl. -#: ../edit.c:83 msgid " ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" msgstr " mód ^X (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" -#: ../edit.c:85 msgid " Whole line completion (^L^N^P)" msgstr " Comhlánú Línte Ina Iomlán (^L^N^P)" -#: ../edit.c:86 msgid " File name completion (^F^N^P)" msgstr " Comhlánú de na hainmneacha comhaid (^F^N^P)" -#: ../edit.c:87 msgid " Tag completion (^]^N^P)" msgstr " Comhlánú clibeanna (^]/^N/^P)" -#: ../edit.c:88 msgid " Path pattern completion (^N^P)" msgstr " Comhlánú Conaire (^N^P)" -#: ../edit.c:89 msgid " Definition completion (^D^N^P)" msgstr " Comhlánú de na sainmhínithe (^D^N^P)" -#: ../edit.c:91 msgid " Dictionary completion (^K^N^P)" msgstr " Comhlánú foclóra (^K^N^P)" -#: ../edit.c:92 msgid " Thesaurus completion (^T^N^P)" msgstr " Comhlánú teasárais (^T^N^P)" -#: ../edit.c:93 msgid " Command-line completion (^V^N^P)" msgstr " Comhlánú den líne ordaithe (^V^N^P)" -#: ../edit.c:94 msgid " User defined completion (^U^N^P)" msgstr " Comhlánú saincheaptha (^U^N^P)" -#: ../edit.c:95 msgid " Omni completion (^O^N^P)" msgstr " Comhlánú Omni (^O^N^P)" -#: ../edit.c:96 msgid " Spelling suggestion (s^N^P)" msgstr " Moladh litrithe (s^N^P)" -#: ../edit.c:97 msgid " Keyword Local completion (^N^P)" msgstr " Comhlánú logánta lorgfhocal (^N^P)" -#: ../edit.c:100 msgid "Hit end of paragraph" msgstr "Sroicheadh críoch an pharagraif" -#: ../edit.c:101 -#, fuzzy msgid "E839: Completion function changed window" -msgstr "E813: Ní féidir fuinneog autocmd a dhúnadh" +msgstr "E839: D'athraigh an fheidhm chomhlánaithe an fhuinneog" -#: ../edit.c:102 msgid "E840: Completion function deleted text" -msgstr "" +msgstr "E840: Scrios an fheidhm chomhlánaithe roinnt téacs" -#: ../edit.c:1847 msgid "'dictionary' option is empty" msgstr "tá an rogha 'dictionary' folamh" -#: ../edit.c:1848 msgid "'thesaurus' option is empty" msgstr "tá an rogha 'thesaurus' folamh" -#: ../edit.c:2655 #, c-format msgid "Scanning dictionary: %s" msgstr "Foclóir á scanadh: %s" -#: ../edit.c:3079 msgid " (insert) Scroll (^E/^Y)" msgstr " (ionsáigh) Scrollaigh (^E/^Y)" -#: ../edit.c:3081 msgid " (replace) Scroll (^E/^Y)" msgstr " (ionadaigh) Scrollaigh (^E/^Y)" -#: ../edit.c:3587 #, c-format msgid "Scanning: %s" msgstr "%s á scanadh" -#: ../edit.c:3614 msgid "Scanning tags." msgstr "Clibeanna á scanadh." -#: ../edit.c:4519 msgid " Adding" msgstr " Méadú" @@ -438,702 +433,451 @@ msgstr " Méadú" #. * be called before line = ml_get(), or when this address is no #. * longer needed. -- Acevedo. #. -#: ../edit.c:4562 msgid "-- Searching..." msgstr "-- Ag Cuardach..." -#: ../edit.c:4618 msgid "Back at original" msgstr "Ar ais ag an mbunáit" -#: ../edit.c:4621 msgid "Word from other line" msgstr "Focal as líne eile" -#: ../edit.c:4624 msgid "The only match" msgstr "An t-aon teaghrán amháin comhoiriúnaithe" -#: ../edit.c:4680 #, c-format msgid "match %d of %d" msgstr "comhoiriúnú %d as %d" -#: ../edit.c:4684 #, c-format msgid "match %d" msgstr "comhoiriúnú %d" -#: ../eval.c:137 +#. maximum nesting of lists and dicts msgid "E18: Unexpected characters in :let" msgstr "E18: Carachtair gan choinne i :let" -#: ../eval.c:138 -#, c-format -msgid "E684: list index out of range: %<PRId64>" -msgstr "E684: innéacs liosta as raon: %<PRId64>" - -#: ../eval.c:139 #, c-format msgid "E121: Undefined variable: %s" msgstr "E121: Athróg gan sainmhíniú: %s" -#: ../eval.c:140 msgid "E111: Missing ']'" msgstr "E111: `]' ar iarraidh" -#: ../eval.c:141 -#, c-format -msgid "E686: Argument of %s must be a List" -msgstr "E686: Caithfidh argóint de %s a bheith ina Liosta" - -#: ../eval.c:143 -#, c-format -msgid "E712: Argument of %s must be a List or Dictionary" -msgstr "E712: Caithfidh argóint de %s a bheith ina Liosta nó Foclóir" - -#: ../eval.c:144 -msgid "E713: Cannot use empty key for Dictionary" -msgstr "E713: Ní féidir eochair fholamh a úsáid le Foclóir" - -#: ../eval.c:145 -msgid "E714: List required" -msgstr "E714: Tá gá le liosta" - -#: ../eval.c:146 -msgid "E715: Dictionary required" -msgstr "E715: Tá gá le foclóir" - -#: ../eval.c:147 -#, c-format -msgid "E118: Too many arguments for function: %s" -msgstr "E118: An iomarca argóintí d'fheidhm: %s" - -#: ../eval.c:148 -#, c-format -msgid "E716: Key not present in Dictionary: %s" -msgstr "E716: Níl an eochair seo san Fhoclóir: %s" - -#: ../eval.c:150 -#, c-format -msgid "E122: Function %s already exists, add ! to replace it" -msgstr "E122: Tá feidhm %s ann cheana, cuir ! leis an ordú chun é a asáitiú" - -#: ../eval.c:151 -msgid "E717: Dictionary entry already exists" -msgstr "E717: Tá an iontráil foclóra seo ann cheana" - -#: ../eval.c:152 -msgid "E718: Funcref required" -msgstr "E718: Tá gá le Funcref" - -#: ../eval.c:153 msgid "E719: Cannot use [:] with a Dictionary" msgstr "E719: Ní féidir [:] a úsáid le foclóir" -#: ../eval.c:154 #, c-format msgid "E734: Wrong variable type for %s=" msgstr "E734: Cineál mícheart athróige le haghaidh %s=" -#: ../eval.c:155 -#, c-format -msgid "E130: Unknown function: %s" -msgstr "E130: Feidhm anaithnid: %s" - -#: ../eval.c:156 #, c-format msgid "E461: Illegal variable name: %s" msgstr "E461: Ainm athróige neamhcheadaithe: %s" -#: ../eval.c:157 msgid "E806: using Float as a String" msgstr "E806: Snámhphointe á úsáid mar Theaghrán" -#: ../eval.c:1830 msgid "E687: Less targets than List items" msgstr "E687: Níos lú spriocanna ná míreanna Liosta" -#: ../eval.c:1834 msgid "E688: More targets than List items" msgstr "E688: Níos mó spriocanna ná míreanna Liosta" -#: ../eval.c:1906 msgid "Double ; in list of variables" msgstr "; dúblach i liosta na n-athróg" -#: ../eval.c:2078 #, c-format msgid "E738: Can't list variables for %s" msgstr "E738: Ní féidir athróga do %s a thaispeáint" -#: ../eval.c:2391 msgid "E689: Can only index a List or Dictionary" msgstr "E689: Is féidir Liosta nó Foclóir amháin a innéacsú" -#: ../eval.c:2396 msgid "E708: [:] must come last" msgstr "E708: caithfidh [:] a bheith ar deireadh" -#: ../eval.c:2439 msgid "E709: [:] requires a List value" msgstr "E709: ní foláir Liosta a thabhairt le [:]" -#: ../eval.c:2674 msgid "E710: List value has more items than target" msgstr "E710: Tá níos mó míreanna ag an Liosta ná an sprioc" -#: ../eval.c:2678 msgid "E711: List value has not enough items" msgstr "E711: Níl go leor míreanna ag an Liosta" -#: ../eval.c:2867 msgid "E690: Missing \"in\" after :for" msgstr "E690: \"in\" ar iarraidh i ndiaidh :for" -#: ../eval.c:3063 -#, c-format -msgid "E107: Missing parentheses: %s" -msgstr "E107: Lúibíní ar iarraidh: %s" - -#: ../eval.c:3263 #, c-format msgid "E108: No such variable: \"%s\"" msgstr "E108: Níl a leithéid d'athróg: \"%s\"" -#: ../eval.c:3333 msgid "E743: variable nested too deep for (un)lock" msgstr "E743: athróg neadaithe ródhomhain chun í a (dí)ghlasáil" -#: ../eval.c:3630 msgid "E109: Missing ':' after '?'" msgstr "E109: ':' ar iarraidh i ndiaidh '?'" -#: ../eval.c:3893 msgid "E691: Can only compare List with List" msgstr "E691: Is féidir Liosta a chur i gcomparáid le Liosta eile amháin" -#: ../eval.c:3895 -msgid "E692: Invalid operation for Lists" +msgid "E692: Invalid operation for List" msgstr "E692: Oibríocht neamhbhailí ar Liostaí" -#: ../eval.c:3915 msgid "E735: Can only compare Dictionary with Dictionary" msgstr "E735: Is féidir Foclóir a chur i gcomparáid le Foclóir eile amháin" -#: ../eval.c:3917 msgid "E736: Invalid operation for Dictionary" msgstr "E736: Oibríocht neamhbhailí ar Fhoclóir" -#: ../eval.c:3932 -msgid "E693: Can only compare Funcref with Funcref" -msgstr "E693: Is féidir Funcref a chur i gcomparáid le Funcref eile amháin" - -#: ../eval.c:3934 msgid "E694: Invalid operation for Funcrefs" msgstr "E694: Oibríocht neamhbhailí ar Funcref" -#: ../eval.c:4277 msgid "E804: Cannot use '%' with Float" msgstr "E804: Ní féidir '%' a úsáid le Snámhphointe" -#: ../eval.c:4478 msgid "E110: Missing ')'" msgstr "E110: ')' ar iarraidh" -#: ../eval.c:4609 msgid "E695: Cannot index a Funcref" msgstr "E695: Ní féidir Funcref a innéacsú" -#: ../eval.c:4839 +msgid "E909: Cannot index a special variable" +msgstr "E909: Ní féidir athróg speisialta a innéacsú" + #, c-format msgid "E112: Option name missing: %s" msgstr "E112: Ainm rogha ar iarraidh: %s" -#: ../eval.c:4855 #, c-format msgid "E113: Unknown option: %s" msgstr "E113: Rogha anaithnid: %s" -#: ../eval.c:4904 #, c-format msgid "E114: Missing quote: %s" msgstr "E114: Comhartha athfhriotail ar iarraidh: %s" -#: ../eval.c:5020 #, c-format msgid "E115: Missing quote: %s" msgstr "E115: Comhartha athfhriotail ar iarraidh: %s" -#: ../eval.c:5084 -#, c-format -msgid "E696: Missing comma in List: %s" -msgstr "E696: Camóg ar iarraidh i Liosta: %s" - -#: ../eval.c:5091 -#, c-format -msgid "E697: Missing end of List ']': %s" -msgstr "E697: ']' ar iarraidh ag deireadh liosta: %s" - -#: ../eval.c:6475 -#, c-format -msgid "E720: Missing colon in Dictionary: %s" -msgstr "E720: Idirstad ar iarraidh i bhFoclóir: %s" - -#: ../eval.c:6499 -#, c-format -msgid "E721: Duplicate key in Dictionary: \"%s\"" -msgstr "E721: Eochair dhúblach i bhFoclóir: \"%s\"" - -#: ../eval.c:6517 -#, c-format -msgid "E722: Missing comma in Dictionary: %s" -msgstr "E722: Camóg ar iarraidh i bhFoclóir: %s" - -#: ../eval.c:6524 -#, c-format -msgid "E723: Missing end of Dictionary '}': %s" -msgstr "E723: '}' ar iarraidh ag deireadh foclóra: %s" +msgid "Not enough memory to set references, garbage collection aborted!" +msgstr "" +"Níl go leor cuimhne ann le tagairtí a shocrú; bailiú dramhaíola á thobscor!" -#: ../eval.c:6555 msgid "E724: variable nested too deep for displaying" msgstr "E724: athróg neadaithe ródhomhain chun í a thaispeáint" -#: ../eval.c:7188 -#, c-format -msgid "E740: Too many arguments for function %s" -msgstr "E740: An iomarca argóintí d'fheidhm %s" - -#: ../eval.c:7190 -#, c-format -msgid "E116: Invalid arguments for function %s" -msgstr "E116: Argóintí neamhbhailí d'fheidhm %s" - -#: ../eval.c:7377 -#, c-format -msgid "E117: Unknown function: %s" -msgstr "E117: Feidhm anaithnid: %s" - -#: ../eval.c:7383 -#, c-format -msgid "E119: Not enough arguments for function: %s" -msgstr "E119: Níl go leor feidhmeanna d'fheidhm: %s" - -#: ../eval.c:7387 -#, c-format -msgid "E120: Using <SID> not in a script context: %s" -msgstr "E120: <SID> á úsáid ach gan a bheith i gcomhthéacs scripte: %s" - -#: ../eval.c:7391 -#, c-format -msgid "E725: Calling dict function without Dictionary: %s" -msgstr "E725: Feidhm 'dict' á ghlao gan Foclóir: %s" - -#: ../eval.c:7453 -msgid "E808: Number or Float required" -msgstr "E808: Uimhir nó Snámhphointe de dhíth" - -#: ../eval.c:7503 -#, fuzzy -msgid "add() argument" -msgstr "argóint -c" - -#: ../eval.c:7907 -msgid "E699: Too many arguments" -msgstr "E699: An iomarca argóintí" - -#: ../eval.c:8073 -msgid "E785: complete() can only be used in Insert mode" -msgstr "E785: is féidir complete() a úsáid sa mhód Ionsáite amháin" - -#: ../eval.c:8156 -msgid "&Ok" -msgstr "&Ok" - -#: ../eval.c:8676 -#, c-format -msgid "E737: Key already exists: %s" -msgstr "E737: Tá eochair ann cheana: %s" - -#: ../eval.c:8692 -#, fuzzy -msgid "extend() argument" -msgstr "argóint --cmd" - -#: ../eval.c:8915 -#, fuzzy -msgid "map() argument" -msgstr "argóint -c" - -#: ../eval.c:8916 -#, fuzzy -msgid "filter() argument" -msgstr "argóint -c" - -#: ../eval.c:9229 -#, c-format -msgid "+-%s%3ld lines: " -msgstr "+-%s%3ld líne: " - -#: ../eval.c:9291 -#, c-format -msgid "E700: Unknown function: %s" -msgstr "E700: Feidhm anaithnid: %s" - -#: ../eval.c:10729 -msgid "called inputrestore() more often than inputsave()" -msgstr "Glaodh inputrestore() níos minice ná inputsave()" - -#: ../eval.c:10771 -#, fuzzy -msgid "insert() argument" -msgstr "argóint -c" - -#: ../eval.c:10841 -msgid "E786: Range not allowed" -msgstr "E786: Ní cheadaítear an raon" - -#: ../eval.c:11140 -msgid "E701: Invalid type for len()" -msgstr "E701: Cineál neamhbhailí le haghaidh len()" - -#: ../eval.c:11980 -msgid "E726: Stride is zero" -msgstr "E726: Is nialas í an chéim" - -#: ../eval.c:11982 -msgid "E727: Start past end" -msgstr "E727: Tosach thar dheireadh" - -#: ../eval.c:12024 ../eval.c:15297 -msgid "<empty>" -msgstr "<folamh>" - -#: ../eval.c:12282 -#, fuzzy -msgid "remove() argument" -msgstr "argóint --cmd" +msgid "E805: Using a Float as a Number" +msgstr "E805: Snámhphointe á úsáid mar Uimhir" -#: ../eval.c:12466 -msgid "E655: Too many symbolic links (cycle?)" -msgstr "E655: An iomarca naisc shiombalacha (ciogal?)" +msgid "E703: Using a Funcref as a Number" +msgstr "E703: Funcref á úsáid mar Uimhir" -#: ../eval.c:12593 -#, fuzzy -msgid "reverse() argument" -msgstr "argóint -c" +msgid "E745: Using a List as a Number" +msgstr "E745: Liosta á úsáid mar Uimhir" -#: ../eval.c:13721 -#, fuzzy -msgid "sort() argument" -msgstr "argóint -c" +msgid "E728: Using a Dictionary as a Number" +msgstr "E728: Foclóir á úsáid mar Uimhir" -#: ../eval.c:13721 -#, fuzzy -msgid "uniq() argument" -msgstr "argóint -c" +msgid "E910: Using a Job as a Number" +msgstr "E910: Jab á úsáid mar Uimhir" -#: ../eval.c:13776 -msgid "E702: Sort compare function failed" -msgstr "E702: Theip ar fheidhm chomparáide le linn sórtála" +msgid "E913: Using a Channel as a Number" +msgstr "E913: Cainéal á úsáid mar Uimhir" -#: ../eval.c:13806 -#, fuzzy -msgid "E882: Uniq compare function failed" -msgstr "E702: Theip ar fheidhm chomparáide le linn sórtála" +msgid "E891: Using a Funcref as a Float" +msgstr "E891: Funcref á úsáid mar Shnámhphointe" -#: ../eval.c:14085 -msgid "(Invalid)" -msgstr "(Neamhbhailí)" +msgid "E892: Using a String as a Float" +msgstr "E892: Teaghrán á úsáid mar Shnámhphointe" -#: ../eval.c:14590 -msgid "E677: Error writing temp file" -msgstr "E677: Earráid agus comhad sealadach á scríobh" +msgid "E893: Using a List as a Float" +msgstr "E893: Liosta á úsáid mar Shnámhphointe" -#: ../eval.c:16159 -msgid "E805: Using a Float as a Number" -msgstr "E805: Snámhphointe á úsáid mar Uimhir" +msgid "E894: Using a Dictionary as a Float" +msgstr "E894: Foclóir á úsáid mar Shnámhphointe" -#: ../eval.c:16162 -msgid "E703: Using a Funcref as a Number" -msgstr "E703: Funcref á úsáid mar Uimhir" +msgid "E907: Using a special value as a Float" +msgstr "E907: Luach speisialta á úsáid mar Shnámhphointe" -#: ../eval.c:16170 -msgid "E745: Using a List as a Number" -msgstr "E745: Liosta á úsáid mar Uimhir" +msgid "E911: Using a Job as a Float" +msgstr "E911: Jab á úsáid mar Shnámhphointe" -#: ../eval.c:16173 -msgid "E728: Using a Dictionary as a Number" -msgstr "E728: Foclóir á úsáid mar Uimhir" +msgid "E914: Using a Channel as a Float" +msgstr "E914: Cainéal á úsáid mar Shnámhphointe" -#: ../eval.c:16259 msgid "E729: using Funcref as a String" msgstr "E729: Funcref á úsáid mar Theaghrán" -#: ../eval.c:16262 msgid "E730: using List as a String" msgstr "E730: Liosta á úsáid mar Theaghrán" -#: ../eval.c:16265 msgid "E731: using Dictionary as a String" msgstr "E731: Foclóir á úsáid mar Theaghrán" -#: ../eval.c:16619 -#, c-format -msgid "E706: Variable type mismatch for: %s" -msgstr "E706: Mímheaitseáil idir cineálacha athróige: %s" +msgid "E908: using an invalid value as a String" +msgstr "E908: luach neamhbhailí á úsáid mar Theaghrán" -#: ../eval.c:16705 #, c-format msgid "E795: Cannot delete variable %s" msgstr "E795: Ní féidir athróg %s a scriosadh" -#: ../eval.c:16724 #, c-format msgid "E704: Funcref variable name must start with a capital: %s" msgstr "E704: Caithfidh ceannlitir a bheith ar dtús ainm Funcref: %s" -#: ../eval.c:16732 #, c-format msgid "E705: Variable name conflicts with existing function: %s" msgstr "E705: Tagann ainm athróige salach ar fheidhm atá ann cheana: %s" -#: ../eval.c:16763 #, c-format msgid "E741: Value is locked: %s" msgstr "E741: Tá an luach faoi ghlas: %s" -#: ../eval.c:16764 ../eval.c:16769 ../message.c:1839 msgid "Unknown" msgstr "Anaithnid" -#: ../eval.c:16768 #, c-format msgid "E742: Cannot change value of %s" msgstr "E742: Ní féidir an luach de %s a athrú" -#: ../eval.c:16838 msgid "E698: variable nested too deep for making a copy" msgstr "E698: athróg neadaithe ródhomhain chun í a chóipeáil" -#: ../eval.c:17249 -#, c-format -msgid "E123: Undefined function: %s" -msgstr "E123: Feidhm gan sainmhíniú: %s" +msgid "" +"\n" +"# global variables:\n" +msgstr "" +"\n" +"# athróga comhchoiteanna:\n" -#: ../eval.c:17260 -#, c-format -msgid "E124: Missing '(': %s" -msgstr "E124: '(' ar iarraidh: %s" +msgid "" +"\n" +"\tLast set from " +msgstr "" +"\n" +"\tSocraithe is déanaí ó " -#: ../eval.c:17293 -#, fuzzy -msgid "E862: Cannot use g: here" -msgstr "E284: Ní féidir luachanna IC a shocrú" +msgid "map() argument" +msgstr "argóint map()" + +msgid "filter() argument" +msgstr "argóint filter()" -#: ../eval.c:17312 #, c-format -msgid "E125: Illegal argument: %s" -msgstr "E125: Argóint neamhcheadaithe: %s" +msgid "E686: Argument of %s must be a List" +msgstr "E686: Caithfidh argóint de %s a bheith ina Liosta" -#: ../eval.c:17323 -#, fuzzy, c-format -msgid "E853: Duplicate argument name: %s" -msgstr "E125: Argóint neamhcheadaithe: %s" +msgid "E928: String required" +msgstr "E928: Teaghrán de dhíth" -#: ../eval.c:17416 -msgid "E126: Missing :endfunction" -msgstr "E126: :endfunction ar iarraidh" +msgid "E808: Number or Float required" +msgstr "E808: Uimhir nó Snámhphointe de dhíth" -#: ../eval.c:17537 -#, c-format -msgid "E707: Function name conflicts with variable: %s" -msgstr "E707: Tagann ainm na feidhme salach ar athróg: %s" +msgid "add() argument" +msgstr "argóint add()" + +msgid "E785: complete() can only be used in Insert mode" +msgstr "E785: is féidir complete() a úsáid sa mhód Ionsáite amháin" + +#. +#. * Yes this is ugly, I don't particularly like it either. But doing it +#. * this way has the compelling advantage that translations need not to +#. * be touched at all. See below what 'ok' and 'ync' are used for. +#. +msgid "&Ok" +msgstr "&Ok" -#: ../eval.c:17549 #, c-format -msgid "E127: Cannot redefine function %s: It is in use" -msgstr "" -"E127: Ní féidir sainmhíniú nua a dhéanamh ar fheidhm %s: In úsáid cheana" +msgid "+-%s%3ld line: " +msgid_plural "+-%s%3ld lines: " +msgstr[0] "+-%s%3ld líne: " +msgstr[1] "+-%s%3ld líne: " +msgstr[2] "+-%s%3ld líne: " +msgstr[3] "+-%s%3ld líne: " +msgstr[4] "+-%s%3ld líne: " -#: ../eval.c:17604 #, c-format -msgid "E746: Function name does not match script file name: %s" -msgstr "" -"E746: Níl ainm na feidhme comhoiriúnach le hainm comhaid na scripte: %s" +msgid "E700: Unknown function: %s" +msgstr "E700: Feidhm anaithnid: %s" -#: ../eval.c:17716 -msgid "E129: Function name required" -msgstr "E129: Tá gá le hainm feidhme" +msgid "E922: expected a dict" +msgstr "E922: bhíothas ag súil le foclóir" -#: ../eval.c:17824 -#, fuzzy, c-format -msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "" -"E128: Caithfidh ceannlitir a bheith ar dtús ainm feidhme, nó idirstad a " -"bheith ann: %s" +msgid "E923: Second argument of function() must be a list or a dict" +msgstr "E923: Caithfidh an dara hargóint de function() a bheith ina liosta nó ina foclóir" -#: ../eval.c:17833 -#, fuzzy, c-format -msgid "E884: Function name cannot contain a colon: %s" +msgid "" +"&OK\n" +"&Cancel" msgstr "" -"E128: Caithfidh ceannlitir a bheith ar dtús ainm feidhme, nó idirstad a " -"bheith ann: %s" +"&OK\n" +"&Cealaigh" -#: ../eval.c:18336 -#, c-format -msgid "E131: Cannot delete function %s: It is in use" -msgstr "E131: Ní féidir feidhm %s a scriosadh: Tá sé in úsáid faoi láthair" +msgid "called inputrestore() more often than inputsave()" +msgstr "Glaodh inputrestore() níos minice ná inputsave()" -#: ../eval.c:18441 -msgid "E132: Function call depth is higher than 'maxfuncdepth'" -msgstr "E132: Doimhneacht na nglaonna níos mó ná 'maxfuncdepth'" +msgid "insert() argument" +msgstr "argóint insert()" -#: ../eval.c:18568 -#, c-format -msgid "calling %s" -msgstr "%s á glao" +msgid "E786: Range not allowed" +msgstr "E786: Ní cheadaítear an raon" -#: ../eval.c:18651 -#, c-format -msgid "%s aborted" -msgstr "%s tobscortha" +msgid "E916: not a valid job" +msgstr "E916: ní jab bailí é" + +msgid "E701: Invalid type for len()" +msgstr "E701: Cineál neamhbhailí le haghaidh len()" -#: ../eval.c:18653 #, c-format -msgid "%s returning #%<PRId64>" -msgstr "%s ag aisfhilleadh #%<PRId64>" +msgid "E798: ID is reserved for \":match\": %ld" +msgstr "E798: Aitheantas in áirithe do \":match\": %ld" + +msgid "E726: Stride is zero" +msgstr "E726: Is nialas í an chéim" + +msgid "E727: Start past end" +msgstr "E727: Tosach thar dheireadh" + +msgid "<empty>" +msgstr "<folamh>" + +msgid "E240: No connection to Vim server" +msgstr "E240: Níl aon nasc le freastalaí Vim" -#: ../eval.c:18670 #, c-format -msgid "%s returning %s" -msgstr "%s ag aisfhilleadh %s" +msgid "E241: Unable to send to %s" +msgstr "E241: Ní féidir aon rud a sheoladh chuig %s" + +msgid "E277: Unable to read a server reply" +msgstr "E277: Ní féidir freagra ón fhreastalaí a léamh" + +msgid "remove() argument" +msgstr "argóint remove()" + +msgid "E655: Too many symbolic links (cycle?)" +msgstr "E655: An iomarca naisc shiombalacha (ciogal?)" + +msgid "reverse() argument" +msgstr "argóint reverse()" + +msgid "E258: Unable to send to client" +msgstr "E258: Ní féidir aon rud a sheoladh chuig an chliant" -#: ../eval.c:18691 ../ex_cmds2.c:2695 #, c-format -msgid "continuing in %s" -msgstr "ag leanúint i %s" +msgid "E927: Invalid action: '%s'" +msgstr "E927: Gníomh neamhbhailí: '%s'" -#: ../eval.c:18795 -msgid "E133: :return not inside a function" -msgstr "E133: Caithfidh :return a bheith isteach i bhfeidhm" +msgid "sort() argument" +msgstr "argóint sort()" -#: ../eval.c:19159 -msgid "" -"\n" -"# global variables:\n" -msgstr "" -"\n" -"# athróga comhchoiteanna:\n" +msgid "uniq() argument" +msgstr "argóint uniq()" -#: ../eval.c:19254 -msgid "" -"\n" -"\tLast set from " -msgstr "" -"\n" -"\tSocraithe is déanaí ó " +msgid "E702: Sort compare function failed" +msgstr "E702: Theip ar fheidhm chomparáide le linn sórtála" -#: ../eval.c:19272 -msgid "No old files" -msgstr "Gan seanchomhaid" +msgid "E882: Uniq compare function failed" +msgstr "E882: Theip ar fheidhm chomparáide Uniq" + +msgid "(Invalid)" +msgstr "(Neamhbhailí)" + +#, c-format +msgid "E935: invalid submatch number: %d" +msgstr "E935: uimhir fho-mheaitseála neamhbhailí: %d" + +msgid "E677: Error writing temp file" +msgstr "E677: Earráid agus comhad sealadach á scríobh" + +msgid "E921: Invalid callback argument" +msgstr "E921: Argóint neamhbhailí ar aisghlaoch" -#: ../ex_cmds.c:122 #, c-format msgid "<%s>%s%s %d, Hex %02x, Octal %03o" msgstr "<%s>%s%s %d, Heics %02x, Ocht %03o" -#: ../ex_cmds.c:145 #, c-format msgid "> %d, Hex %04x, Octal %o" msgstr "> %d, Heics %04x, Ocht %o" -#: ../ex_cmds.c:146 #, c-format msgid "> %d, Hex %08x, Octal %o" msgstr "> %d, Heics %08x, Ocht %o" -#: ../ex_cmds.c:684 msgid "E134: Move lines into themselves" msgstr "E134: Bog línte isteach iontu féin" -#: ../ex_cmds.c:747 msgid "1 line moved" msgstr "Bogadh líne amháin" -#: ../ex_cmds.c:749 #, c-format -msgid "%<PRId64> lines moved" -msgstr "Bogadh %<PRId64> líne" +msgid "%ld lines moved" +msgstr "Bogadh %ld líne" -#: ../ex_cmds.c:1175 #, c-format -msgid "%<PRId64> lines filtered" -msgstr "Scagadh %<PRId64> líne" +msgid "%ld lines filtered" +msgstr "Scagadh %ld líne" -#: ../ex_cmds.c:1194 msgid "E135: *Filter* Autocommands must not change current buffer" msgstr "" "E135: Ní cheadaítear d'uathorduithe *scagaire* an maolán reatha a athrú" -#: ../ex_cmds.c:1244 msgid "[No write since last change]\n" msgstr "[Athraithe agus nach sábháilte ó shin]\n" -#: ../ex_cmds.c:1424 #, c-format msgid "%sviminfo: %s in line: " msgstr "%sviminfo: %s i líne: " -#: ../ex_cmds.c:1431 msgid "E136: viminfo: Too many errors, skipping rest of file" msgstr "" "E136: viminfo: An iomarca earráidí, ag scipeáil an chuid eile den chomhad" -#: ../ex_cmds.c:1458 #, c-format msgid "Reading viminfo file \"%s\"%s%s%s" msgstr "Comhad viminfo \"%s\"%s%s%s á léamh" -#: ../ex_cmds.c:1460 msgid " info" msgstr " eolas" -#: ../ex_cmds.c:1461 msgid " marks" msgstr " marcanna" -#: ../ex_cmds.c:1462 msgid " oldfiles" msgstr " seanchomhad" -#: ../ex_cmds.c:1463 msgid " FAILED" msgstr " TEIPTHE" #. avoid a wait_return for this message, it's annoying -#: ../ex_cmds.c:1541 #, c-format msgid "E137: Viminfo file is not writable: %s" msgstr "E137: Níl an comhad Viminfo inscríofa: %s" -#: ../ex_cmds.c:1626 +#, c-format +msgid "E929: Too many viminfo temp files, like %s!" +msgstr "E929: An iomarca comhad sealadach viminfo, mar shampla %s!" + #, c-format msgid "E138: Can't write viminfo file %s!" msgstr "E138: Ní féidir comhad viminfo %s a scríobh!" -#: ../ex_cmds.c:1635 #, c-format msgid "Writing viminfo file \"%s\"" msgstr "Comhad viminfo \"%s\" á scríobh" +#, c-format +msgid "E886: Can't rename viminfo file to %s!" +msgstr "E886: Ní féidir ainm %s a chur ar an gcomhad viminfo!" + #. Write the info: -#: ../ex_cmds.c:1720 #, c-format msgid "# This viminfo file was generated by Vim %s.\n" msgstr "# Chruthaigh Vim an comhad viminfo seo %s.\n" -#: ../ex_cmds.c:1722 msgid "" "# You may edit it if you're careful!\n" "\n" @@ -1141,47 +885,47 @@ msgstr "" "# Is féidir leat an comhad seo a chur in eagar ach bí cúramach!\n" "\n" -#: ../ex_cmds.c:1723 msgid "# Value of 'encoding' when this file was written\n" msgstr "# Luach 'encoding' agus an comhad seo á scríobh\n" -#: ../ex_cmds.c:1800 msgid "Illegal starting char" msgstr "Carachtar neamhcheadaithe tosaigh" -#: ../ex_cmds.c:2162 +msgid "" +"\n" +"# Bar lines, copied verbatim:\n" +msgstr "" +"\n" +"# Barralínte, cóipeáilte focal ar fhocal:\n" + +msgid "Save As" +msgstr "Sábháil Mar" + msgid "Write partial file?" msgstr "Scríobh comhad neamhiomlán?" -#: ../ex_cmds.c:2166 msgid "E140: Use ! to write partial buffer" msgstr "E140: Bain úsáid as ! chun maolán neamhiomlán a scríobh" -#: ../ex_cmds.c:2281 #, c-format msgid "Overwrite existing file \"%s\"?" msgstr "Forscríobh comhad \"%s\" atá ann cheana?" -#: ../ex_cmds.c:2317 #, c-format msgid "Swap file \"%s\" exists, overwrite anyway?" msgstr "Tá comhad babhtála \"%s\" ann cheana; forscríobh mar sin féin?" -#: ../ex_cmds.c:2326 #, c-format msgid "E768: Swap file exists: %s (:silent! overrides)" msgstr "E768: Tá comhad babhtála ann cheana: %s (úsáid :silent! chun sárú)" -#: ../ex_cmds.c:2381 #, c-format -msgid "E141: No file name for buffer %<PRId64>" -msgstr "E141: Níl aon ainm ar mhaolán %<PRId64>" +msgid "E141: No file name for buffer %ld" +msgstr "E141: Níl aon ainm ar mhaolán %ld" -#: ../ex_cmds.c:2412 msgid "E142: File not written: Writing is disabled by 'write' option" msgstr "E142: Níor scríobhadh an comhad: díchumasaithe leis an rogha 'write'" -#: ../ex_cmds.c:2434 #, c-format msgid "" "'readonly' option is set for \"%s\".\n" @@ -1190,7 +934,6 @@ msgstr "" "tá an rogha 'readonly' socraithe do \"%s\".\n" "Ar mhaith leat é a scríobh mar sin féin?" -#: ../ex_cmds.c:2439 #, c-format msgid "" "File permissions of \"%s\" are read-only.\n" @@ -1201,85 +944,70 @@ msgstr "" "Seans gurbh fhéidir scríobh ann mar sin féin.\n" "An bhfuil fonn ort triail a bhaint as?" -#: ../ex_cmds.c:2451 #, c-format msgid "E505: \"%s\" is read-only (add ! to override)" msgstr "E505: is inléite amháin é \"%s\" (cuir ! leis an ordú chun sárú)" -#: ../ex_cmds.c:3120 +msgid "Edit File" +msgstr "Cuir Comhad in Eagar" + #, c-format msgid "E143: Autocommands unexpectedly deleted new buffer %s" msgstr "E143: Scrios na huathorduithe maolán nua %s go tobann" -#: ../ex_cmds.c:3313 msgid "E144: non-numeric argument to :z" msgstr "E144: argóint neamhuimhriúil chun :z" -#: ../ex_cmds.c:3404 msgid "E145: Shell commands not allowed in rvim" msgstr "E145: Ní cheadaítear orduithe blaoisce i rvim" -#: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "" "E146: Ní cheadaítear litreacha mar theormharcóirí ar shloinn ionadaíochta" -#: ../ex_cmds.c:3964 #, c-format msgid "replace with %s (y/n/a/q/l/^E/^Y)?" msgstr "cuir %s ina ionad (y/n/a/q/l/^E/^Y)?" -#: ../ex_cmds.c:4379 msgid "(Interrupted) " msgstr "(Idirbhriste) " -#: ../ex_cmds.c:4384 msgid "1 match" msgstr "1 rud comhoiriúnach" -#: ../ex_cmds.c:4384 msgid "1 substitution" msgstr "1 ionadaíocht" -#: ../ex_cmds.c:4387 #, c-format -msgid "%<PRId64> matches" -msgstr "%<PRId64> rud comhoiriúnach" +msgid "%ld matches" +msgstr "%ld rud comhoiriúnach" -#: ../ex_cmds.c:4388 #, c-format -msgid "%<PRId64> substitutions" -msgstr "%<PRId64> ionadaíocht" +msgid "%ld substitutions" +msgstr "%ld ionadaíocht" -#: ../ex_cmds.c:4392 msgid " on 1 line" msgstr " ar líne amháin" -#: ../ex_cmds.c:4395 #, c-format -msgid " on %<PRId64> lines" -msgstr " ar %<PRId64> líne" +msgid " on %ld lines" +msgstr " ar %ld líne" -#: ../ex_cmds.c:4438 msgid "E147: Cannot do :global recursive" msgstr "E147: Ní cheadaítear :global go hathchúrsach" # should have ":" -#: ../ex_cmds.c:4467 msgid "E148: Regular expression missing from global" msgstr "E148: Slonn ionadaíochta ar iarraidh ó :global" -#: ../ex_cmds.c:4508 #, c-format msgid "Pattern found in every line: %s" msgstr "Aimsíodh an patrún i ngach líne: %s" -#: ../ex_cmds.c:4510 -#, fuzzy, c-format +#, c-format msgid "Pattern not found: %s" -msgstr "Patrún gan aimsiú" +msgstr "Patrún gan aimsiú: %s" -#: ../ex_cmds.c:4587 msgid "" "\n" "# Last Substitute String:\n" @@ -1289,682 +1017,599 @@ msgstr "" "# Teaghrán Ionadach Is Déanaí:\n" "$" -#: ../ex_cmds.c:4679 msgid "E478: Don't panic!" msgstr "E478: Ná téigh i scaoll!" -#: ../ex_cmds.c:4717 #, c-format msgid "E661: Sorry, no '%s' help for %s" msgstr "E661: Tá brón orm, ní aon chabhair '%s' do %s" -#: ../ex_cmds.c:4719 #, c-format msgid "E149: Sorry, no help for %s" msgstr "E149: Tá brón orm, níl aon chabhair do %s" -#: ../ex_cmds.c:4751 #, c-format msgid "Sorry, help file \"%s\" not found" msgstr "Tá brón orm, comhad cabhrach \"%s\" gan aimsiú" -#: ../ex_cmds.c:5323 #, c-format -msgid "E150: Not a directory: %s" -msgstr "E150: Ní comhadlann é: %s" +msgid "E151: No match: %s" +msgstr "E151: Gan meaitseáil: %s" -#: ../ex_cmds.c:5446 #, c-format msgid "E152: Cannot open %s for writing" msgstr "E152: Ní féidir %s a oscailt chun scríobh ann" -#: ../ex_cmds.c:5471 #, c-format msgid "E153: Unable to open %s for reading" msgstr "E153: Ní féidir %s a oscailt chun é a léamh" -#: ../ex_cmds.c:5500 #, c-format msgid "E670: Mix of help file encodings within a language: %s" msgstr "E670: Ionchóduithe éagsúla do chomhaid chabhracha i dteanga aonair: %s" -#: ../ex_cmds.c:5565 #, c-format msgid "E154: Duplicate tag \"%s\" in file %s/%s" msgstr "E154: Clib dhúblach \"%s\" i gcomhad %s/%s" -#: ../ex_cmds.c:5687 +#, c-format +msgid "E150: Not a directory: %s" +msgstr "E150: Ní comhadlann é: %s" + #, c-format msgid "E160: Unknown sign command: %s" msgstr "E160: Ordú anaithnid comhartha: %s" -#: ../ex_cmds.c:5704 msgid "E156: Missing sign name" msgstr "E156: Ainm comhartha ar iarraidh" -#: ../ex_cmds.c:5746 msgid "E612: Too many signs defined" msgstr "E612: An iomarca comharthaí sainmhínithe" -#: ../ex_cmds.c:5813 #, c-format msgid "E239: Invalid sign text: %s" msgstr "E239: Téacs neamhbhailí comhartha: %s" -#: ../ex_cmds.c:5844 ../ex_cmds.c:6035 #, c-format msgid "E155: Unknown sign: %s" msgstr "E155: Comhartha anaithnid: %s" -#: ../ex_cmds.c:5877 msgid "E159: Missing sign number" msgstr "E159: Uimhir chomhartha ar iarraidh" -#: ../ex_cmds.c:5971 #, c-format msgid "E158: Invalid buffer name: %s" msgstr "E158: Ainm maoláin neamhbhailí: %s" -#: ../ex_cmds.c:6008 +msgid "E934: Cannot jump to a buffer that does not have a name" +msgstr "E934: Ní féidir léim go maolán gan ainm" + #, c-format -msgid "E157: Invalid sign ID: %<PRId64>" -msgstr "E157: ID neamhbhailí comhartha: %<PRId64>" +msgid "E157: Invalid sign ID: %ld" +msgstr "E157: ID neamhbhailí comhartha: %ld" + +#, c-format +msgid "E885: Not possible to change sign %s" +msgstr "E885: Ní féidir an comhartha a athrú: %s" + +msgid " (NOT FOUND)" +msgstr " (AR IARRAIDH)" -#: ../ex_cmds.c:6066 msgid " (not supported)" msgstr " (níl an rogha seo ar fáil)" -#: ../ex_cmds.c:6169 msgid "[Deleted]" msgstr "[Scriosta]" -#: ../ex_cmds2.c:139 +msgid "No old files" +msgstr "Gan seanchomhaid" + msgid "Entering Debug mode. Type \"cont\" to continue." msgstr "Mód dífhabhtaithe á thosú. Clóscríobh \"cont\" chun leanúint." -#: ../ex_cmds2.c:143 ../ex_docmd.c:759 #, c-format -msgid "line %<PRId64>: %s" -msgstr "líne %<PRId64>: %s" +msgid "line %ld: %s" +msgstr "líne %ld: %s" -#: ../ex_cmds2.c:145 #, c-format msgid "cmd: %s" msgstr "ordú: %s" -#: ../ex_cmds2.c:322 +msgid "frame is zero" +msgstr "is nialas é an fráma" + #, c-format -msgid "Breakpoint in \"%s%s\" line %<PRId64>" -msgstr "Brisphointe i \"%s%s\" líne %<PRId64>" +msgid "frame at highest level: %d" +msgstr "fráma ag an leibhéal is airde: %d" + +#, c-format +msgid "Breakpoint in \"%s%s\" line %ld" +msgstr "Brisphointe i \"%s%s\" líne %ld" -#: ../ex_cmds2.c:581 #, c-format msgid "E161: Breakpoint not found: %s" msgstr "E161: Brisphointe gan aimsiú: %s" -#: ../ex_cmds2.c:611 msgid "No breakpoints defined" msgstr "Níl aon bhrisphointe socraithe" -#: ../ex_cmds2.c:617 #, c-format -msgid "%3d %s %s line %<PRId64>" -msgstr "%3d %s %s líne %<PRId64>" +msgid "%3d %s %s line %ld" +msgstr "%3d %s %s líne %ld" -#: ../ex_cmds2.c:942 msgid "E750: First use \":profile start {fname}\"" msgstr "E750: Úsáid \":profile start {ainm}\" ar dtús" -#: ../ex_cmds2.c:1269 #, c-format msgid "Save changes to \"%s\"?" msgstr "Sábháil athruithe ar \"%s\"?" -#: ../ex_cmds2.c:1271 ../ex_docmd.c:8851 msgid "Untitled" msgstr "Gan Teideal" -#: ../ex_cmds2.c:1421 #, c-format msgid "E162: No write since last change for buffer \"%s\"" msgstr "E162: Athraíodh maolán \"%s\" ach nach bhfuil sé sábháilte ó shin" -#: ../ex_cmds2.c:1480 msgid "Warning: Entered other buffer unexpectedly (check autocommands)" msgstr "Rabhadh: Chuathas i maolán eile go tobann (seiceáil na huathorduithe)" -#: ../ex_cmds2.c:1826 msgid "E163: There is only one file to edit" msgstr "E163: Níl ach aon chomhad amháin le cur in eagar" -#: ../ex_cmds2.c:1828 msgid "E164: Cannot go before first file" msgstr "E164: Ní féidir a dhul roimh an chéad chomhad" -#: ../ex_cmds2.c:1830 msgid "E165: Cannot go beyond last file" msgstr "E165: Ní féidir a dhul thar an gcomhad deireanach" -#: ../ex_cmds2.c:2175 #, c-format msgid "E666: compiler not supported: %s" msgstr "E666: ní ghlactar leis an tiomsaitheoir: %s" -#: ../ex_cmds2.c:2257 #, c-format msgid "Searching for \"%s\" in \"%s\"" msgstr "Ag déanamh cuardach ar \"%s\" i \"%s\"" -#: ../ex_cmds2.c:2284 #, c-format msgid "Searching for \"%s\"" msgstr "Ag déanamh cuardach ar \"%s\"" -#: ../ex_cmds2.c:2307 #, c-format -msgid "not found in 'runtimepath': \"%s\"" -msgstr "gan aimsiú i 'runtimepath': \"%s\"" +msgid "not found in '%s': \"%s\"" +msgstr "gan aimsiú in '%s': \"%s\"" + +msgid "Source Vim script" +msgstr "Foinsigh script Vim" -#: ../ex_cmds2.c:2472 #, c-format msgid "Cannot source a directory: \"%s\"" msgstr "Ní féidir comhadlann a léamh: \"%s\"" -#: ../ex_cmds2.c:2518 #, c-format msgid "could not source \"%s\"" msgstr "níorbh fhéidir \"%s\" a léamh" -#: ../ex_cmds2.c:2520 #, c-format -msgid "line %<PRId64>: could not source \"%s\"" -msgstr "líne %<PRId64>: níorbh fhéidir \"%s\" a fhoinsiú" +msgid "line %ld: could not source \"%s\"" +msgstr "líne %ld: níorbh fhéidir \"%s\" a fhoinsiú" -#: ../ex_cmds2.c:2535 #, c-format msgid "sourcing \"%s\"" msgstr "\"%s\" á fhoinsiú" -#: ../ex_cmds2.c:2537 #, c-format -msgid "line %<PRId64>: sourcing \"%s\"" -msgstr "líne %<PRId64>: \"%s\" á fhoinsiú" +msgid "line %ld: sourcing \"%s\"" +msgstr "líne %ld: \"%s\" á fhoinsiú" -#: ../ex_cmds2.c:2693 #, c-format msgid "finished sourcing %s" msgstr "deireadh ag foinsiú %s" -#: ../ex_cmds2.c:2765 +#, c-format +msgid "continuing in %s" +msgstr "ag leanúint i %s" + msgid "modeline" msgstr "módlíne" -#: ../ex_cmds2.c:2767 msgid "--cmd argument" msgstr "argóint --cmd" -#: ../ex_cmds2.c:2769 msgid "-c argument" msgstr "argóint -c" -#: ../ex_cmds2.c:2771 msgid "environment variable" msgstr "athróg thimpeallachta" -#: ../ex_cmds2.c:2773 msgid "error handler" msgstr "láimhseálaí earráidí" -#: ../ex_cmds2.c:3020 msgid "W15: Warning: Wrong line separator, ^M may be missing" msgstr "" "W15: Rabhadh: Deighilteoir línte mícheart, is féidir go bhfuil ^M ar iarraidh" -#: ../ex_cmds2.c:3139 msgid "E167: :scriptencoding used outside of a sourced file" msgstr "E167: ní úsáidtear :scriptencoding ach i gcomhad foinsithe" -#: ../ex_cmds2.c:3166 msgid "E168: :finish used outside of a sourced file" msgstr "E168: ní úsáidtear :finish ach i gcomhaid foinsithe" -#: ../ex_cmds2.c:3389 #, c-format msgid "Current %slanguage: \"%s\"" msgstr "%sTeanga faoi láthair: \"%s\"" -#: ../ex_cmds2.c:3404 #, c-format msgid "E197: Cannot set language to \"%s\"" msgstr "E197: Ní féidir an teanga a shocrú mar \"%s\"" -#. don't redisplay the window -#. don't wait for return -#: ../ex_docmd.c:387 msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." msgstr "Mód Ex á thosú. Clóscríobh \"visual\" le haghaidh an ghnáthmhód." # in FARF -KPS -#: ../ex_docmd.c:428 msgid "E501: At end-of-file" msgstr "E501: Ag an chomhadchríoch" -#: ../ex_docmd.c:513 msgid "E169: Command too recursive" msgstr "E169: Ordú ró-athchúrsach" -#: ../ex_docmd.c:1006 #, c-format msgid "E605: Exception not caught: %s" msgstr "E605: Eisceacht gan láimhseáil: %s" -#: ../ex_docmd.c:1085 msgid "End of sourced file" msgstr "Críoch chomhaid foinsithe" -#: ../ex_docmd.c:1086 msgid "End of function" msgstr "Críoch fheidhme" -#: ../ex_docmd.c:1628 msgid "E464: Ambiguous use of user-defined command" msgstr "E464: Úsáid athbhríoch d'ordú saincheaptha" -#: ../ex_docmd.c:1638 msgid "E492: Not an editor command" msgstr "E492: Níl ina ordú eagarthóra" -#: ../ex_docmd.c:1729 msgid "E493: Backwards range given" msgstr "E493: Raon droim ar ais" -#: ../ex_docmd.c:1733 msgid "Backwards range given, OK to swap" msgstr "Raon droim ar ais, babhtáil" -#. append -#. typed wrong -#: ../ex_docmd.c:1787 msgid "E494: Use w or w>>" msgstr "E494: Bain úsáid as w nó w>>" -#: ../ex_docmd.c:3454 -msgid "E319: The command is not available in this version" +msgid "E319: Sorry, the command is not available in this version" msgstr "E319: Tá brón orm, níl an t-ordú ar fáil sa leagan seo" -#: ../ex_docmd.c:3752 msgid "E172: Only one file name allowed" msgstr "E172: Ní cheadaítear ach aon ainm comhaid amháin" -#: ../ex_docmd.c:4238 msgid "1 more file to edit. Quit anyway?" msgstr "1 comhad le cur in eagar fós. Scoir mar sin féin?" -#: ../ex_docmd.c:4242 #, c-format msgid "%d more files to edit. Quit anyway?" msgstr "%d comhad le cur in eagar fós. Scoir mar sin féin?" -#: ../ex_docmd.c:4248 msgid "E173: 1 more file to edit" msgstr "E173: 1 chomhad le heagrú fós" -#: ../ex_docmd.c:4250 #, c-format -msgid "E173: %<PRId64> more files to edit" -msgstr "E173: %<PRId64> comhad le cur in eagar" +msgid "E173: %ld more files to edit" +msgstr "E173: %ld comhad le cur in eagar" -#: ../ex_docmd.c:4320 msgid "E174: Command already exists: add ! to replace it" msgstr "E174: Tá an t-ordú ann cheana: cuir ! leis chun sárú" -#: ../ex_docmd.c:4432 msgid "" "\n" -" Name Args Range Complete Definition" +" Name Args Address Complete Definition" msgstr "" "\n" -" Ainm Arg Raon Iomlán Sainmhíniú" +" Ainm Arg Seoladh Iomlán Sainmhíniú" -#: ../ex_docmd.c:4516 msgid "No user-defined commands found" msgstr "Níl aon ordú aimsithe atá sainithe ag an úsáideoir" -#: ../ex_docmd.c:4538 msgid "E175: No attribute specified" msgstr "E175: Níl aon aitreabúid sainithe" -#: ../ex_docmd.c:4583 msgid "E176: Invalid number of arguments" msgstr "E176: Tá líon na n-argóintí mícheart" -#: ../ex_docmd.c:4594 msgid "E177: Count cannot be specified twice" msgstr "E177: Ní cheadaítear an t-áireamh a bheith tugtha faoi dhó" -#: ../ex_docmd.c:4603 msgid "E178: Invalid default value for count" msgstr "E178: Luach réamhshocraithe neamhbhailí ar áireamh" -#: ../ex_docmd.c:4625 msgid "E179: argument required for -complete" msgstr "E179: tá gá le hargóint i ndiaidh -complete" -#: ../ex_docmd.c:4635 +msgid "E179: argument required for -addr" +msgstr "E179: tá gá le hargóint i ndiaidh -addr" + #, c-format msgid "E181: Invalid attribute: %s" msgstr "E181: Aitreabúid neamhbhailí: %s" -#: ../ex_docmd.c:4678 msgid "E182: Invalid command name" msgstr "E182: Ainm neamhbhailí ordaithe" -#: ../ex_docmd.c:4691 msgid "E183: User defined commands must start with an uppercase letter" msgstr "" "E183: Caithfidh ceannlitir a bheith ar dtús orduithe atá sainithe ag an " "úsáideoir" -#: ../ex_docmd.c:4696 -#, fuzzy msgid "E841: Reserved name, cannot be used for user defined command" -msgstr "E464: Úsáid athbhríoch d'ordú saincheaptha" +msgstr "" +"E841: Ainm in áirithe, ní féidir é a chur ar ordú sainithe ag an úsáideoir" -#: ../ex_docmd.c:4751 #, c-format msgid "E184: No such user-defined command: %s" msgstr "E184: Níl a leithéid d'ordú saincheaptha: %s" -#: ../ex_docmd.c:5219 +#, c-format +msgid "E180: Invalid address type value: %s" +msgstr "E180: Cineál neamhbhailí seolta: %s" + #, c-format msgid "E180: Invalid complete value: %s" msgstr "E180: Luach iomlán neamhbhailí: %s" -#: ../ex_docmd.c:5225 msgid "E468: Completion argument only allowed for custom completion" msgstr "" "E468: Ní cheadaítear argóint chomhlánaithe ach le comhlánú saincheaptha" -#: ../ex_docmd.c:5231 msgid "E467: Custom completion requires a function argument" msgstr "E467: Tá gá le hargóint fheidhme le comhlánú saincheaptha" -#: ../ex_docmd.c:5257 -#, fuzzy, c-format +msgid "unknown" +msgstr "anaithnid" + +#, c-format msgid "E185: Cannot find color scheme '%s'" -msgstr "E185: Scéim dathanna %s gan aimsiú" +msgstr "E185: Scéim dathanna '%s' gan aimsiú" -#: ../ex_docmd.c:5263 msgid "Greetings, Vim user!" msgstr "Dia duit, a úsáideoir Vim!" -#: ../ex_docmd.c:5431 msgid "E784: Cannot close last tab page" -msgstr "E784: Ní féidir an leathanach cluaisín deiridh a dhúnadh" +msgstr "E784: Ní féidir an leathanach cluaisíní deiridh a dhúnadh" -#: ../ex_docmd.c:5462 msgid "Already only one tab page" -msgstr "Níl ach leathanach cluaisín amháin cheana féin" +msgstr "Níl ach leathanach cluaisíní amháin cheana féin" + +msgid "Edit File in new window" +msgstr "Cuir comhad in eagar i bhfuinneog nua" -#: ../ex_docmd.c:6004 #, c-format msgid "Tab page %d" msgstr "Leathanach cluaisín %d" -#: ../ex_docmd.c:6295 msgid "No swap file" msgstr "Níl aon chomhad babhtála ann" -#: ../ex_docmd.c:6478 +msgid "Append File" +msgstr "Cuir Comhad i nDeireadh" + msgid "E747: Cannot change directory, buffer is modified (add ! to override)" msgstr "" "E747: Ní féidir an chomhadlann a athrú, mionathraíodh an maolán (cuir ! leis " "an ordú chun sárú)" -#: ../ex_docmd.c:6485 msgid "E186: No previous directory" msgstr "E186: Níl aon chomhadlann roimhe seo" -#: ../ex_docmd.c:6530 msgid "E187: Unknown" msgstr "E187: Anaithnid" -#: ../ex_docmd.c:6610 msgid "E465: :winsize requires two number arguments" msgstr "E465: ní foláir dhá argóint uimhriúla le :winsize" -#: ../ex_docmd.c:6655 +#, c-format +msgid "Window position: X %d, Y %d" +msgstr "Ionad na fuinneoige: X %d, Y %d" + msgid "E188: Obtaining window position not implemented for this platform" msgstr "E188: Ní féidir ionad na fuinneoige a fháil amach ar an chóras seo" -#: ../ex_docmd.c:6662 msgid "E466: :winpos requires two number arguments" msgstr "E466: ní foláir dhá argóint uimhriúla le :winpos" -#: ../ex_docmd.c:7241 +msgid "E930: Cannot use :redir inside execute()" +msgstr "E930: Ní féidir :redir a úsáid laistigh de execute()" + +msgid "Save Redirection" +msgstr "Sábháil Atreorú" + +msgid "Save View" +msgstr "Sábháil an tAmharc" + +msgid "Save Session" +msgstr "Sábháil an Seisiún" + +msgid "Save Setup" +msgstr "Sábháil an Socrú" + #, c-format msgid "E739: Cannot create directory: %s" msgstr "E739: Ní féidir comhadlann a chruthú: %s" -#: ../ex_docmd.c:7268 #, c-format msgid "E189: \"%s\" exists (add ! to override)" msgstr "E189: Tá \"%s\" ann cheana (cuir ! leis an ordú chun sárú)" -#: ../ex_docmd.c:7273 #, c-format msgid "E190: Cannot open \"%s\" for writing" msgstr "E190: Ní féidir \"%s\" a oscailt chun léamh" #. set mark -#: ../ex_docmd.c:7294 msgid "E191: Argument must be a letter or forward/backward quote" msgstr "E191: Caithfidh an argóint a bheith litir nó comhartha athfhriotal" -#: ../ex_docmd.c:7333 msgid "E192: Recursive use of :normal too deep" msgstr "E192: athchúrsáil :normal ródhomhain" -#: ../ex_docmd.c:7807 +msgid "E809: #< is not available without the +eval feature" +msgstr "E809: níl #< ar fáil gan ghné +eval" + msgid "E194: No alternate file name to substitute for '#'" msgstr "E194: Níl aon ainm comhaid a chur in ionad '#'" -#: ../ex_docmd.c:7841 msgid "E495: no autocommand file name to substitute for \"<afile>\"" msgstr "E495: níl aon ainm comhaid uathordaithe le cur in ionad \"<afile>\"" -#: ../ex_docmd.c:7850 msgid "E496: no autocommand buffer number to substitute for \"<abuf>\"" msgstr "E496: níl aon uimhir mhaolán uathordaithe le cur in ionad \"<abuf>\"" -#: ../ex_docmd.c:7861 msgid "E497: no autocommand match name to substitute for \"<amatch>\"" msgstr "" "E497: níl aon ainm meaitseála uathordaithe le cur in ionad \"<amatch>\"" -#: ../ex_docmd.c:7870 msgid "E498: no :source file name to substitute for \"<sfile>\"" msgstr "E498: níl aon ainm comhaid :source le cur in ionad \"<sfile>\"" -#: ../ex_docmd.c:7876 -#, fuzzy msgid "E842: no line number to use for \"<slnum>\"" -msgstr "E498: níl aon ainm comhaid :source le cur in ionad \"<sfile>\"" +msgstr "E842: níl aon líne-uimhir ar fáil le haghaidh \"<slnum>\"" -#: ../ex_docmd.c:7903 -#, fuzzy, c-format +#, no-c-format msgid "E499: Empty file name for '%' or '#', only works with \":p:h\"" msgstr "" "E499: Ainm comhaid folamh le haghaidh '%' nó '#', oibreoidh sé le \":p:h\" " "amháin" -#: ../ex_docmd.c:7905 msgid "E500: Evaluates to an empty string" msgstr "E500: Luacháiltear é seo mar theaghrán folamh" -#: ../ex_docmd.c:8838 msgid "E195: Cannot open viminfo file for reading" msgstr "E195: Ní féidir an comhad viminfo a oscailt chun léamh" -#: ../ex_eval.c:464 +msgid "E196: No digraphs in this version" +msgstr "E196: Ní cheadaítear déghraif sa leagan seo" + msgid "E608: Cannot :throw exceptions with 'Vim' prefix" msgstr "E608: Ní féidir eisceachtaí a :throw le réimír 'Vim'" #. always scroll up, don't overwrite -#: ../ex_eval.c:496 #, c-format msgid "Exception thrown: %s" msgstr "Gineadh eisceacht: %s" -#: ../ex_eval.c:545 #, c-format msgid "Exception finished: %s" msgstr "Eisceacht curtha i gcrích: %s" -#: ../ex_eval.c:546 #, c-format msgid "Exception discarded: %s" msgstr "Eisceacht curtha i leataobh: %s" -#: ../ex_eval.c:588 ../ex_eval.c:634 #, c-format -msgid "%s, line %<PRId64>" -msgstr "%s, líne %<PRId64>" +msgid "%s, line %ld" +msgstr "%s, líne %ld" #. always scroll up, don't overwrite -#: ../ex_eval.c:608 #, c-format msgid "Exception caught: %s" msgstr "Láimhseáladh eisceacht: %s" -#: ../ex_eval.c:676 #, c-format msgid "%s made pending" msgstr "%s ar feitheamh anois" -#: ../ex_eval.c:679 #, c-format msgid "%s resumed" msgstr "atosaíodh %s" -#: ../ex_eval.c:683 #, c-format msgid "%s discarded" msgstr "%s curtha i leataobh" -#: ../ex_eval.c:708 msgid "Exception" msgstr "Eisceacht" -#: ../ex_eval.c:713 msgid "Error and interrupt" msgstr "Earráid agus idirbhriseadh" -#: ../ex_eval.c:715 msgid "Error" msgstr "Earráid" #. if (pending & CSTP_INTERRUPT) -#: ../ex_eval.c:717 msgid "Interrupt" msgstr "Idirbhriseadh" -#: ../ex_eval.c:795 msgid "E579: :if nesting too deep" msgstr "E579: :if neadaithe ródhomhain" -#: ../ex_eval.c:830 msgid "E580: :endif without :if" msgstr "E580: :endif gan :if" -#: ../ex_eval.c:873 msgid "E581: :else without :if" msgstr "E581: :else gan :if" -#: ../ex_eval.c:876 msgid "E582: :elseif without :if" msgstr "E582: :elseif gan :if" -#: ../ex_eval.c:880 msgid "E583: multiple :else" msgstr "E583: :else iomadúla" -#: ../ex_eval.c:883 msgid "E584: :elseif after :else" msgstr "E584: :elseif i ndiaidh :else" -#: ../ex_eval.c:941 msgid "E585: :while/:for nesting too deep" msgstr "E585: :while/:for neadaithe ródhomhain" -#: ../ex_eval.c:1028 msgid "E586: :continue without :while or :for" msgstr "E586: :continue gan :while ná :for" -#: ../ex_eval.c:1061 msgid "E587: :break without :while or :for" msgstr "E587: :break gan :while ná :for" -#: ../ex_eval.c:1102 msgid "E732: Using :endfor with :while" msgstr "E732: :endfor á úsáid le :while" -#: ../ex_eval.c:1104 msgid "E733: Using :endwhile with :for" msgstr "E733: :endwhile á úsáid le :for" -#: ../ex_eval.c:1247 msgid "E601: :try nesting too deep" msgstr "E601: :try neadaithe ródhomhain" -#: ../ex_eval.c:1317 msgid "E603: :catch without :try" msgstr "E603: :catch gan :try" #. Give up for a ":catch" after ":finally" and ignore it. #. * Just parse. -#: ../ex_eval.c:1332 msgid "E604: :catch after :finally" msgstr "E604: :catch i ndiaidh :finally" -#: ../ex_eval.c:1451 msgid "E606: :finally without :try" msgstr "E606: :finally gan :try" #. Give up for a multiple ":finally" and ignore it. -#: ../ex_eval.c:1467 msgid "E607: multiple :finally" msgstr "E607: :finally iomadúla" -#: ../ex_eval.c:1571 msgid "E602: :endtry without :try" msgstr "E602: :endtry gan :try" -#: ../ex_eval.c:2026 msgid "E193: :endfunction not inside a function" msgstr "E193: Caithfidh :endfunction a bheith isteach i bhfeidhm" -#: ../ex_getln.c:1643 msgid "E788: Not allowed to edit another buffer now" msgstr "E788: Níl cead agat maolán eile a chur in eagar anois" -#: ../ex_getln.c:1656 msgid "E811: Not allowed to change buffer information now" msgstr "E811: Níl cead agat faisnéis an mhaoláin a athrú anois" -#: ../ex_getln.c:3178 msgid "tagname" msgstr "clibainm" -#: ../ex_getln.c:3181 msgid " kind file\n" msgstr " cineál comhaid\n" -#: ../ex_getln.c:4799 msgid "'history' option is zero" msgstr "tá an rogha 'history' nialas" -#: ../ex_getln.c:5046 #, c-format msgid "" "\n" @@ -1975,310 +1620,230 @@ msgstr "" # this gets plugged into the %s in the previous string, # hence the colon -#: ../ex_getln.c:5047 msgid "Command Line" msgstr "Líne na nOrduithe:" -#: ../ex_getln.c:5048 msgid "Search String" msgstr "Teaghrán Cuardaigh" -#: ../ex_getln.c:5049 msgid "Expression" msgstr "Sloinn:" -#: ../ex_getln.c:5050 msgid "Input Line" msgstr "Líne an Ionchuir:" -#: ../ex_getln.c:5117 +msgid "Debug Line" +msgstr "Líne Dhífhabhtaithe" + msgid "E198: cmd_pchar beyond the command length" msgstr "E198: cmd_pchar os cionn fad an ordaithe" -#: ../ex_getln.c:5279 msgid "E199: Active window or buffer deleted" msgstr "E199: Scriosadh an fhuinneog reatha nó an maolán reatha" -#: ../file_search.c:203 -msgid "E854: path too long for completion" -msgstr "" - -#: ../file_search.c:446 -#, c-format -msgid "" -"E343: Invalid path: '**[number]' must be at the end of the path or be " -"followed by '%s'." -msgstr "" -"E343: Conair neamhbhailí: ní mór '**[uimhir]' a bheith ag deireadh na " -"conaire, nó le '%s' ina dhiaidh." - -#: ../file_search.c:1505 -#, c-format -msgid "E344: Can't find directory \"%s\" in cdpath" -msgstr "E344: Ní féidir comhadlann \"%s\" a aimsiú sa cdpath" - -#: ../file_search.c:1508 -#, c-format -msgid "E345: Can't find file \"%s\" in path" -msgstr "E345: Ní féidir comhad \"%s\" a aimsiú sa chonair" - -#: ../file_search.c:1512 -#, c-format -msgid "E346: No more directory \"%s\" found in cdpath" -msgstr "E346: Níl comhadlann \"%s\" sa cdpath a thuilleadh" - -#: ../file_search.c:1515 -#, c-format -msgid "E347: No more file \"%s\" found in path" -msgstr "E347: Níl comhad \"%s\" sa chonair a thuilleadh" - -#: ../fileio.c:137 msgid "E812: Autocommands changed buffer or buffer name" msgstr "E812: Bhí maolán nó ainm maoláin athraithe ag orduithe uathoibríocha" -#: ../fileio.c:368 msgid "Illegal file name" msgstr "Ainm comhaid neamhcheadaithe" -#: ../fileio.c:395 ../fileio.c:476 ../fileio.c:2543 ../fileio.c:2578 msgid "is a directory" msgstr "is comhadlann é" -#: ../fileio.c:397 msgid "is not a file" msgstr "ní comhad é" -#: ../fileio.c:508 ../fileio.c:3522 +msgid "is a device (disabled with 'opendevice' option)" +msgstr "is gléas é seo (díchumasaithe le rogha 'opendevice')" + msgid "[New File]" msgstr "[Comhad Nua]" -#: ../fileio.c:511 msgid "[New DIRECTORY]" msgstr "[COMHADLANN nua]" -#: ../fileio.c:529 ../fileio.c:532 msgid "[File too big]" msgstr "[Comhad rómhór]" -#: ../fileio.c:534 msgid "[Permission Denied]" msgstr "[Cead Diúltaithe]" -#: ../fileio.c:653 msgid "E200: *ReadPre autocommands made the file unreadable" msgstr "E200: Rinne uathorduithe *ReadPre praiseach as an chomhad" -#: ../fileio.c:655 msgid "E201: *ReadPre autocommands must not change current buffer" msgstr "E201: Ní cheadaítear d'uathorduithe *ReadPre an maolán reatha a athrú" -#: ../fileio.c:672 -msgid "Nvim: Reading from stdin...\n" +msgid "Vim: Reading from stdin...\n" msgstr "Vim: Ag léamh ón ionchur caighdeánach...\n" +msgid "Reading from stdin..." +msgstr "Ag léamh ón ionchur caighdeánach..." + #. Re-opening the original file failed! -#: ../fileio.c:909 msgid "E202: Conversion made file unreadable!" msgstr "E202: Comhad doléite i ndiaidh an tiontaithe!" -#. fifo or socket -#: ../fileio.c:1782 msgid "[fifo/socket]" msgstr "[fifo/soicéad]" # `TITA' ?! -KPS -#. fifo -#: ../fileio.c:1788 msgid "[fifo]" msgstr "[fifo]" -#. or socket -#: ../fileio.c:1794 msgid "[socket]" msgstr "[soicéad]" -#. or character special -#: ../fileio.c:1801 msgid "[character special]" msgstr "[comhad speisialta den chineál carachtar]" -#: ../fileio.c:1815 msgid "[CR missing]" msgstr "[CR ar iarraidh]" -#: ../fileio.c:1819 msgid "[long lines split]" msgstr "[línte fada deighilte]" -#: ../fileio.c:1823 ../fileio.c:3512 msgid "[NOT converted]" msgstr "[NÍ tiontaithe]" -#: ../fileio.c:1826 ../fileio.c:3515 msgid "[converted]" msgstr "[tiontaithe]" -#: ../fileio.c:1831 #, c-format -msgid "[CONVERSION ERROR in line %<PRId64>]" -msgstr "[EARRÁID TIONTAITHE i líne %<PRId64>]" +msgid "[CONVERSION ERROR in line %ld]" +msgstr "[EARRÁID TIONTAITHE i líne %ld]" -#: ../fileio.c:1835 #, c-format -msgid "[ILLEGAL BYTE in line %<PRId64>]" -msgstr "[BEART NEAMHCHEADAITHE i líne %<PRId64>]" +msgid "[ILLEGAL BYTE in line %ld]" +msgstr "[BEART NEAMHCHEADAITHE i líne %ld]" -#: ../fileio.c:1838 msgid "[READ ERRORS]" msgstr "[EARRÁIDÍ LÉIMH]" -#: ../fileio.c:2104 msgid "Can't find temp file for conversion" msgstr "Ní féidir comhad sealadach a aimsiú le haghaidh tiontaithe" -#: ../fileio.c:2110 msgid "Conversion with 'charconvert' failed" msgstr "Theip ar thiontú le 'charconvert'" -#: ../fileio.c:2113 msgid "can't read output of 'charconvert'" msgstr "ní féidir an t-aschur ó 'charconvert' a léamh" -#: ../fileio.c:2437 msgid "E676: No matching autocommands for acwrite buffer" msgstr "E676: Níl aon uathordú comhoiriúnaithe le haghaidh maoláin acwrite" -#: ../fileio.c:2466 msgid "E203: Autocommands deleted or unloaded buffer to be written" msgstr "E203: Scrios nó dhíluchtaigh uathorduithe an maolán le scríobh" -#: ../fileio.c:2486 msgid "E204: Autocommand changed number of lines in unexpected way" msgstr "E204: D'athraigh uathordú líon na línte gan choinne" -#: ../fileio.c:2548 ../fileio.c:2565 +msgid "NetBeans disallows writes of unmodified buffers" +msgstr "Ní cheadaíonn NetBeans maoláin gan athrú a bheith scríofa" + +msgid "Partial writes disallowed for NetBeans buffers" +msgstr "Ní cheadaítear maoláin NetBeans a bheith scríofa go neamhiomlán" + msgid "is not a file or writable device" msgstr "ní comhad ná gléas inscríofa á" -#: ../fileio.c:2601 +msgid "writing to device disabled with 'opendevice' option" +msgstr "díchumasaíodh scríobh chuig gléas le rogha 'opendevice'" + msgid "is read-only (add ! to override)" msgstr "is inléite amháin é (cuir ! leis an ordú chun sárú)" -#: ../fileio.c:2886 msgid "E506: Can't write to backup file (add ! to override)" msgstr "" "E506: Ní féidir scríobh a dhéanamh sa chomhad cúltaca (úsáid ! chun sárú)" -#: ../fileio.c:2898 msgid "E507: Close error for backup file (add ! to override)" msgstr "" "E507: Earráid agus comhad cúltaca á dhúnadh (cuir ! leis an ordú chun sárú)" -#: ../fileio.c:2901 msgid "E508: Can't read file for backup (add ! to override)" msgstr "" "E508: Ní féidir an comhad cúltaca a léamh (cuir ! leis an ordú chun sárú)" -#: ../fileio.c:2923 msgid "E509: Cannot create backup file (add ! to override)" msgstr "" "E509: Ní féidir comhad cúltaca a chruthú (cuir ! leis an ordú chun sárú)" -#: ../fileio.c:3008 msgid "E510: Can't make backup file (add ! to override)" msgstr "" "E510: Ní féidir comhad cúltaca a chruthú (cuir ! leis an ordú chun sárú)" -#. Can't write without a tempfile! -#: ../fileio.c:3121 +msgid "E460: The resource fork would be lost (add ! to override)" +msgstr "E460: Chaillfí an forc acmhainne (cuir ! leis an ordú chun sárú)" + msgid "E214: Can't find temp file for writing" msgstr "E214: Ní féidir comhad sealadach a aimsiú chun scríobh ann" -#: ../fileio.c:3134 msgid "E213: Cannot convert (add ! to write without conversion)" msgstr "E213: Ní féidir tiontú (cuir ! leis an ordú chun scríobh gan tiontú)" -#: ../fileio.c:3169 msgid "E166: Can't open linked file for writing" msgstr "E166: Ní féidir comhad nasctha a oscailt chun scríobh ann" -#: ../fileio.c:3173 msgid "E212: Can't open file for writing" msgstr "E212: Ní féidir comhad a oscailt chun scríobh ann" -#: ../fileio.c:3363 msgid "E667: Fsync failed" msgstr "E667: Theip ar fsync" -#: ../fileio.c:3398 msgid "E512: Close failed" msgstr "E512: Theip ar dúnadh" -#: ../fileio.c:3436 msgid "E513: write error, conversion failed (make 'fenc' empty to override)" msgstr "" "E513: earráid le linn scríobh, theip ar thiontú (úsáid 'fenc' folamh chun " "sárú)" -#: ../fileio.c:3441 #, c-format msgid "" -"E513: write error, conversion failed in line %<PRId64> (make 'fenc' empty to " +"E513: write error, conversion failed in line %ld (make 'fenc' empty to " "override)" msgstr "" -"E513: earráid le linn scríofa, theip ar thiontú ar líne %<PRId64> (úsáid " -"'fenc' folamh le sárú)" +"E513: earráid le linn scríofa, theip ar thiontú ar líne %ld (úsáid 'fenc' " +"folamh le sárú)" -#: ../fileio.c:3448 msgid "E514: write error (file system full?)" msgstr "E514: earráid le linn scríofa (an bhfuil an córas comhaid lán?)" -#: ../fileio.c:3506 msgid " CONVERSION ERROR" msgstr " EARRÁID TIONTAITHE" -#: ../fileio.c:3509 #, c-format -msgid " in line %<PRId64>;" -msgstr " ar líne %<PRId64>;" +msgid " in line %ld;" +msgstr " ar líne %ld;" -#: ../fileio.c:3519 msgid "[Device]" msgstr "[Gléas]" -#: ../fileio.c:3522 msgid "[New]" msgstr "[Nua]" -#: ../fileio.c:3535 msgid " [a]" msgstr " [a]" -#: ../fileio.c:3535 msgid " appended" msgstr " iarcheangailte" -#: ../fileio.c:3537 msgid " [w]" msgstr " [w]" -#: ../fileio.c:3537 msgid " written" msgstr " scríofa" -#: ../fileio.c:3579 msgid "E205: Patchmode: can't save original file" msgstr "E205: Patchmode: ní féidir an comhad bunúsach a shábháil" -#: ../fileio.c:3602 msgid "E206: patchmode: can't touch empty original file" msgstr "E206: patchmode: ní féidir an comhad bunúsach folamh a theagmháil" -#: ../fileio.c:3616 msgid "E207: Can't delete backup file" msgstr "E207: Ní féidir an comhad cúltaca a scriosadh" -#: ../fileio.c:3672 msgid "" "\n" "WARNING: Original file may be lost or damaged\n" @@ -2286,96 +1851,75 @@ msgstr "" "\n" "RABHADH: Is féidir gur caillte nó loite an comhad bunúsach\n" -#: ../fileio.c:3675 msgid "don't quit the editor until the file is successfully written!" msgstr "ná scoir go dtí go scríobhfaí an comhad!" -#: ../fileio.c:3795 msgid "[dos]" msgstr "[dos]" -#: ../fileio.c:3795 msgid "[dos format]" msgstr "[formáid dos]" -#: ../fileio.c:3801 msgid "[mac]" msgstr "[mac]" -#: ../fileio.c:3801 msgid "[mac format]" msgstr "[formáid mac]" -#: ../fileio.c:3807 msgid "[unix]" msgstr "[unix]" -#: ../fileio.c:3807 msgid "[unix format]" msgstr "[formáid unix]" -#: ../fileio.c:3831 msgid "1 line, " msgstr "1 líne, " -#: ../fileio.c:3833 #, c-format -msgid "%<PRId64> lines, " -msgstr "%<PRId64> líne, " +msgid "%ld lines, " +msgstr "%ld líne, " -#: ../fileio.c:3836 msgid "1 character" msgstr "1 carachtar" -#: ../fileio.c:3838 #, c-format -msgid "%<PRId64> characters" -msgstr "%<PRId64> carachtar" +msgid "%lld characters" +msgstr "%lld carachtar" -#: ../fileio.c:3849 msgid "[noeol]" msgstr "[ganEOL]" -#: ../fileio.c:3849 msgid "[Incomplete last line]" msgstr "[Is neamhiomlán an líne dheireanach]" #. don't overwrite messages here #. must give this prompt #. don't use emsg() here, don't want to flush the buffers -#: ../fileio.c:3865 msgid "WARNING: The file has been changed since reading it!!!" msgstr "RABHADH: Athraíodh an comhad ó léadh é!!!" -#: ../fileio.c:3867 msgid "Do you really want to write to it" msgstr "An bhfuil tú cinnte gur mhaith leat é a scríobh" -#: ../fileio.c:4648 #, c-format msgid "E208: Error writing to \"%s\"" msgstr "E208: Earráid agus \"%s\" á scríobh" -#: ../fileio.c:4655 #, c-format msgid "E209: Error closing \"%s\"" msgstr "E209: Earráid agus \"%s\" á dhúnadh" -#: ../fileio.c:4657 #, c-format msgid "E210: Error reading \"%s\"" msgstr "E210: Earráid agus \"%s\" á léamh" -#: ../fileio.c:4883 msgid "E246: FileChangedShell autocommand deleted buffer" msgstr "E246: Scrios uathordú FileChangedShell an maolán" -#: ../fileio.c:4894 #, c-format msgid "E211: File \"%s\" no longer available" msgstr "E211: Níl comhad \"%s\" ar fáil feasta" -#: ../fileio.c:4906 #, c-format msgid "" "W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as " @@ -2383,39 +1927,31 @@ msgid "" msgstr "" "W12: Rabhadh: Athraíodh comhad \"%s\" agus athraíodh an maolán i Vim fosta" -#: ../fileio.c:4907 msgid "See \":help W12\" for more info." msgstr "Bain triail as \":help W12\" chun tuilleadh eolais a fháil." -#: ../fileio.c:4910 #, c-format msgid "W11: Warning: File \"%s\" has changed since editing started" msgstr "W11: Rabhadh: Athraíodh comhad \"%s\" ó tosaíodh é a chur in eagar" -#: ../fileio.c:4911 msgid "See \":help W11\" for more info." msgstr "Bain triail as \":help W11\" chun tuilleadh eolais a fháil." -#: ../fileio.c:4914 #, c-format msgid "W16: Warning: Mode of file \"%s\" has changed since editing started" msgstr "" "W16: Rabhadh: Athraíodh mód an chomhaid \"%s\" ó tosaíodh é a chur in eagar" -#: ../fileio.c:4915 msgid "See \":help W16\" for more info." msgstr "Bain triail as \":help W16\" chun tuilleadh eolais a fháil." -#: ../fileio.c:4927 #, c-format msgid "W13: Warning: File \"%s\" has been created after editing started" msgstr "W13: Rabhadh: Cruthaíodh comhad \"%s\" ó tosaíodh é a chur in eagar" -#: ../fileio.c:4947 msgid "Warning" msgstr "Rabhadh" -#: ../fileio.c:4948 msgid "" "&OK\n" "&Load File" @@ -2423,48 +1959,45 @@ msgstr "" "&OK\n" "&Luchtaigh Comhad" -#: ../fileio.c:5065 #, c-format msgid "E462: Could not prepare for reloading \"%s\"" msgstr "E462: Ní féidir \"%s\" a ullmhú le haghaidh athluchtaithe" -#: ../fileio.c:5078 #, c-format msgid "E321: Could not reload \"%s\"" msgstr "E321: Ní féidir \"%s\" a athluchtú" -#: ../fileio.c:5601 msgid "--Deleted--" msgstr "--Scriosta--" -#: ../fileio.c:5732 #, c-format msgid "auto-removing autocommand: %s <buffer=%d>" msgstr "uathordú á bhaint go huathoibríoch: %s <maolán=%d>" #. the group doesn't exist -#: ../fileio.c:5772 #, c-format msgid "E367: No such group: \"%s\"" msgstr "E367: Níl a leithéid de ghrúpa: \"%s\"" -#: ../fileio.c:5897 +msgid "E936: Cannot delete the current group" +msgstr "E936: Ní féidir an grúpa reatha a scriosadh" + +msgid "W19: Deleting augroup that is still in use" +msgstr "W19: Iarracht ar augroup atá fós in úsáid a scriosadh" + #, c-format msgid "E215: Illegal character after *: %s" msgstr "E215: Carachtar neamhcheadaithe i ndiaidh *: %s" -#: ../fileio.c:5905 #, c-format msgid "E216: No such event: %s" msgstr "E216: Níl a leithéid de theagmhas: %s" -#: ../fileio.c:5907 #, c-format msgid "E216: No such group or event: %s" msgstr "E216: Níl a leithéid de ghrúpa nó theagmhas: %s" #. Highlight title -#: ../fileio.c:6090 msgid "" "\n" "--- Auto-Commands ---" @@ -2472,765 +2005,567 @@ msgstr "" "\n" "--- Uathorduithe ---" -#: ../fileio.c:6293 #, c-format msgid "E680: <buffer=%d>: invalid buffer number " msgstr "E680: <maolán=%d>: uimhir neamhbhailí mhaoláin " -#: ../fileio.c:6370 msgid "E217: Can't execute autocommands for ALL events" msgstr "E217: Ní féidir uathorduithe a rith i gcomhair teagmhas UILE" -#: ../fileio.c:6393 msgid "No matching autocommands" msgstr "Níl aon uathordú comhoiriúnaithe" -#: ../fileio.c:6831 msgid "E218: autocommand nesting too deep" msgstr "E218: uathordú neadaithe ródhomhain" -#: ../fileio.c:7143 #, c-format msgid "%s Auto commands for \"%s\"" msgstr "%s Uathorduithe do \"%s\"" -#: ../fileio.c:7149 #, c-format msgid "Executing %s" msgstr "%s á rith" -#: ../fileio.c:7211 #, c-format msgid "autocommand %s" msgstr "uathordú %s" -#: ../fileio.c:7795 msgid "E219: Missing {." msgstr "E219: { ar iarraidh." -#: ../fileio.c:7797 msgid "E220: Missing }." msgstr "E220: } ar iarraidh." -#: ../fold.c:93 msgid "E490: No fold found" msgstr "E490: Níor aimsíodh aon fhilleadh" -#: ../fold.c:544 msgid "E350: Cannot create fold with current 'foldmethod'" msgstr "E350: Ní féidir filleadh a chruthú leis an 'foldmethod' reatha" -#: ../fold.c:546 msgid "E351: Cannot delete fold with current 'foldmethod'" msgstr "E351: Ní féidir filleadh a scriosadh leis an 'foldmethod' reatha" -#: ../fold.c:1784 #, c-format -msgid "+--%3ld lines folded " -msgstr "+--%3ld líne fillte " +msgid "+--%3ld line folded " +msgid_plural "+--%3ld lines folded " +msgstr[0] "+--%3ld líne fillte " +msgstr[1] "+--%3ld líne fillte " +msgstr[2] "+--%3ld líne fillte " +msgstr[3] "+--%3ld líne fillte " +msgstr[4] "+--%3ld líne fillte " -#. buffer has already been read -#: ../getchar.c:273 msgid "E222: Add to read buffer" msgstr "E222: Cuir leis an maolán léite" -#: ../getchar.c:2040 msgid "E223: recursive mapping" msgstr "E223: mapáil athchúrsach" -#: ../getchar.c:2849 #, c-format msgid "E224: global abbreviation already exists for %s" msgstr "E224: tá giorrúchán comhchoiteann ann cheana le haghaidh %s" -#: ../getchar.c:2852 #, c-format msgid "E225: global mapping already exists for %s" msgstr "E225: tá mapáil chomhchoiteann ann cheana le haghaidh %s" -#: ../getchar.c:2952 #, c-format msgid "E226: abbreviation already exists for %s" msgstr "E226: tá giorrúchán ann cheana le haghaidh %s" -#: ../getchar.c:2955 #, c-format msgid "E227: mapping already exists for %s" msgstr "E227: tá mapáil ann cheana le haghaidh %s" -#: ../getchar.c:3008 msgid "No abbreviation found" msgstr "Níor aimsíodh aon ghiorrúchán" -#: ../getchar.c:3010 msgid "No mapping found" msgstr "Níor aimsíodh aon mhapáil" -#: ../getchar.c:3974 msgid "E228: makemap: Illegal mode" msgstr "E228: makemap: Mód neamhcheadaithe" -#. key value of 'cedit' option -#. type of cmdline window or 0 -#. result of cmdline window or 0 -#: ../globals.h:924 -msgid "--No lines in buffer--" -msgstr "--Tá an maolán folamh--" - -#. -#. * The error messages that can be shared are included here. -#. * Excluded are errors that are only used once and debugging messages. -#. -#: ../globals.h:996 -msgid "E470: Command aborted" -msgstr "E470: Ordú tobscortha" +msgid "E851: Failed to create a new process for the GUI" +msgstr "E851: Níorbh fhéidir próiseas nua a chruthú don GUI" -#: ../globals.h:997 -msgid "E471: Argument required" -msgstr "E471: Tá gá le hargóint" +msgid "E852: The child process failed to start the GUI" +msgstr "E852: Theip ar an macphróiseas an GUI a thosú" -#: ../globals.h:998 -msgid "E10: \\ should be followed by /, ? or &" -msgstr "E10: Ba chóir /, ? nó & a chur i ndiaidh \\" +msgid "E229: Cannot start the GUI" +msgstr "E229: Ní féidir an GUI a chur ag obair" -#: ../globals.h:1000 -msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" -msgstr "" -"E11: Neamhbhailí i bhfuinneog líne na n-orduithe; <CR>=rith, CTRL-C=scoir" +#, c-format +msgid "E230: Cannot read from \"%s\"" +msgstr "E230: Ní féidir léamh ó \"%s\"" -#: ../globals.h:1002 -msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" +msgid "E665: Cannot start GUI, no valid font found" msgstr "" -"E12: Ní cheadaítear ordú ó exrc/vimrc sa chomhadlann reatha ná ó chuardach " -"clibe" +"E665: Ní féidir an GUI a chur ag obair, níl aon chlófhoireann bhailí ann" -#: ../globals.h:1003 -msgid "E171: Missing :endif" -msgstr "E171: :endif ar iarraidh" +msgid "E231: 'guifontwide' invalid" +msgstr "E231: 'guifontwide' neamhbhailí" -#: ../globals.h:1004 -msgid "E600: Missing :endtry" -msgstr "E600: :endtry ar iarraidh" - -#: ../globals.h:1005 -msgid "E170: Missing :endwhile" -msgstr "E170: :endwhile ar iarraidh" - -#: ../globals.h:1006 -msgid "E170: Missing :endfor" -msgstr "E170: :endfor ar iarraidh" - -#: ../globals.h:1007 -msgid "E588: :endwhile without :while" -msgstr "E588: :endwhile gan :while" - -#: ../globals.h:1008 -msgid "E588: :endfor without :for" -msgstr "E588: :endfor gan :for" +msgid "E599: Value of 'imactivatekey' is invalid" +msgstr "E599: Luach neamhbhailí ar 'imactivatekey'" -#: ../globals.h:1009 -msgid "E13: File exists (add ! to override)" -msgstr "E13: Tá comhad ann cheana (cuir ! leis an ordú chun forscríobh)" - -#: ../globals.h:1010 -msgid "E472: Command failed" -msgstr "E472: Theip ar ordú" - -#: ../globals.h:1011 -msgid "E473: Internal error" -msgstr "E473: Earráid inmheánach" +#, c-format +msgid "E254: Cannot allocate color %s" +msgstr "E254: Ní féidir dath %s a dháileadh" -#: ../globals.h:1012 -msgid "Interrupted" -msgstr "Idirbhriste" +msgid "No match at cursor, finding next" +msgstr "Níl a leithéid ag an chúrsóir, ag cuardach ar an chéad cheann eile" -#: ../globals.h:1013 -msgid "E14: Invalid address" -msgstr "E14: Drochsheoladh" +msgid "<cannot open> " +msgstr "<ní féidir a oscailt> " -#: ../globals.h:1014 -msgid "E474: Invalid argument" -msgstr "E474: Argóint neamhbhailí" - -#: ../globals.h:1015 #, c-format -msgid "E475: Invalid argument: %s" -msgstr "E475: Argóint neamhbhailí: %s" +msgid "E616: vim_SelFile: can't get font %s" +msgstr "E616: vim_SelFile: níl aon fháil ar an chlófhoireann %s" -#: ../globals.h:1016 -#, c-format -msgid "E15: Invalid expression: %s" -msgstr "E15: Slonn neamhbhailí: %s" +msgid "E614: vim_SelFile: can't return to current directory" +msgstr "E614: vim_SelFile: ní féidir dul ar ais go dtí an chomhadlann reatha" -#: ../globals.h:1017 -msgid "E16: Invalid range" -msgstr "E16: Raon neamhbhailí" +msgid "Pathname:" +msgstr "Conair:" -#: ../globals.h:1018 -msgid "E476: Invalid command" -msgstr "E476: Ordú neamhbhailí" +msgid "E615: vim_SelFile: can't get current directory" +msgstr "E615: vim_SelFile: níl an chomhadlann reatha ar fáil" -#: ../globals.h:1019 -#, c-format -msgid "E17: \"%s\" is a directory" -msgstr "E17: is comhadlann \"%s\"" +msgid "OK" +msgstr "OK" -#: ../globals.h:1020 -#, fuzzy -msgid "E900: Invalid job id" -msgstr "E49: Méid neamhbhailí scrollaithe" +msgid "Cancel" +msgstr "Cealaigh" -#: ../globals.h:1021 -msgid "E901: Job table is full" +msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." msgstr "" +"Giuirléid Scrollbharra: Ní féidir céimseata an mhapa picteilíní a fháil." -#: ../globals.h:1024 -#, c-format -msgid "E364: Library call failed for \"%s()\"" -msgstr "E364: Theip ar ghlao leabharlainne \"%s()\"" - -#: ../globals.h:1026 -msgid "E19: Mark has invalid line number" -msgstr "E19: Tá líne-uimhir neamhbhailí ag an mharc" +msgid "Vim dialog" +msgstr "Dialóg Vim" -#: ../globals.h:1027 -msgid "E20: Mark not set" -msgstr "E20: Marc gan socrú" - -#: ../globals.h:1029 -msgid "E21: Cannot make changes, 'modifiable' is off" +msgid "E232: Cannot create BalloonEval with both message and callback" msgstr "" -"E21: Ní féidir athruithe a chur i bhfeidhm, níl an bhratach 'modifiable' " -"socraithe" +"E232: Ní féidir BalloonEval a chruthú le teachtaireacht agus aisghlaoch araon" -#: ../globals.h:1030 -msgid "E22: Scripts nested too deep" -msgstr "E22: scripteanna neadaithe ródhomhain" +msgid "_Cancel" +msgstr "_Cealaigh" -#: ../globals.h:1031 -msgid "E23: No alternate file" -msgstr "E23: Níl aon chomhad malartach" +msgid "_Save" +msgstr "_Sábháil" -#: ../globals.h:1032 -msgid "E24: No such abbreviation" -msgstr "E24: Níl a leithéid de ghiorrúchán ann" +msgid "_Open" +msgstr "_Oscail" -#: ../globals.h:1033 -msgid "E477: No ! allowed" -msgstr "E477: Ní cheadaítear !" +msgid "_OK" +msgstr "_OK" -#: ../globals.h:1035 -msgid "E25: Nvim does not have a built-in GUI" -msgstr "E25: Ní féidir an GUI a úsáid: Níor cumasaíodh é ag am tiomsaithe" +msgid "" +"&Yes\n" +"&No\n" +"&Cancel" +msgstr "" +"&Tá\n" +"&Níl\n" +"&Cealaigh" -#: ../globals.h:1036 -#, c-format -msgid "E28: No such highlight group name: %s" -msgstr "E28: Níl a leithéid d'ainm grúpa aibhsithe: %s" +msgid "Yes" +msgstr "Tá" -#: ../globals.h:1037 -msgid "E29: No inserted text yet" -msgstr "E29: Níl aon téacs ionsáite go dtí seo" +msgid "No" +msgstr "Níl" -#: ../globals.h:1038 -msgid "E30: No previous command line" -msgstr "E30: Níl aon líne na n-orduithe roimhe seo" +msgid "Input _Methods" +msgstr "_Modhanna ionchuir" -#: ../globals.h:1039 -msgid "E31: No such mapping" -msgstr "E31: Níl a leithéid de mhapáil" +# in OLT --KPS +msgid "VIM - Search and Replace..." +msgstr "VIM - Cuardaigh agus Athchuir..." -#: ../globals.h:1040 -msgid "E479: No match" -msgstr "E479: Níl aon rud comhoiriúnach ann" +msgid "VIM - Search..." +msgstr "VIM - Cuardaigh..." -#: ../globals.h:1041 -#, c-format -msgid "E480: No match: %s" -msgstr "E480: Níl aon rud comhoiriúnach ann: %s" +msgid "Find what:" +msgstr "Aimsigh:" -#: ../globals.h:1042 -msgid "E32: No file name" -msgstr "E32: Níl aon ainm comhaid" +msgid "Replace with:" +msgstr "Le cur in ionad:" -#: ../globals.h:1044 -msgid "E33: No previous substitute regular expression" -msgstr "E33: Níl aon slonn ionadaíochta roimhe seo" +#. whole word only button +msgid "Match whole word only" +msgstr "Focal iomlán amháin" -#: ../globals.h:1045 -msgid "E34: No previous command" -msgstr "E34: Níl aon ordú roimhe seo" +#. match case button +msgid "Match case" +msgstr "Meaitseáil an cás" -#: ../globals.h:1046 -msgid "E35: No previous regular expression" -msgstr "E35: Níl aon slonn ionadaíochta roimhe seo" +msgid "Direction" +msgstr "Treo" -#: ../globals.h:1047 -msgid "E481: No range allowed" -msgstr "E481: Ní cheadaítear raon" +#. 'Up' and 'Down' buttons +msgid "Up" +msgstr "Suas" -#: ../globals.h:1048 -msgid "E36: Not enough room" -msgstr "E36: Níl slí a dhóthain ann" +msgid "Down" +msgstr "Síos" -#: ../globals.h:1049 -#, c-format -msgid "E482: Can't create file %s" -msgstr "E482: Ní féidir comhad %s a chruthú" +msgid "Find Next" +msgstr "An Chéad Cheann Eile" -#: ../globals.h:1050 -msgid "E483: Can't get temp file name" -msgstr "E483: Níl aon fháil ar ainm comhaid sealadach" +msgid "Replace" +msgstr "Ionadaigh" -#: ../globals.h:1051 -#, c-format -msgid "E484: Can't open file %s" -msgstr "E484: Ní féidir comhad %s a oscailt" +msgid "Replace All" +msgstr "Ionadaigh Uile" -#: ../globals.h:1052 -#, c-format -msgid "E485: Can't read file %s" -msgstr "E485: Ní féidir comhad %s a léamh" +msgid "_Close" +msgstr "_Dún" -#: ../globals.h:1054 -msgid "E37: No write since last change (add ! to override)" -msgstr "E37: Tá athruithe ann gan sábháil (cuir ! leis an ordú chun sárú)" +msgid "Vim: Received \"die\" request from session manager\n" +msgstr "Vim: Fuarthas iarratas \"die\" ó bhainisteoir an tseisiúin\n" -#: ../globals.h:1055 -#, fuzzy -msgid "E37: No write since last change" -msgstr "[Athraithe agus nach sábháilte ó shin]\n" +msgid "Close tab" +msgstr "Dún cluaisín" -#: ../globals.h:1056 -msgid "E38: Null argument" -msgstr "E38: Argóint nialasach" - -#: ../globals.h:1057 -msgid "E39: Number expected" -msgstr "E39: Ag súil le huimhir" +msgid "New tab" +msgstr "Cluaisín nua" -#: ../globals.h:1058 -#, c-format -msgid "E40: Can't open errorfile %s" -msgstr "E40: Ní féidir an comhad earráide %s a oscailt" +msgid "Open Tab..." +msgstr "Oscail Cluaisín..." -#: ../globals.h:1059 -msgid "E41: Out of memory!" -msgstr "E41: Cuimhne ídithe!" +msgid "Vim: Main window unexpectedly destroyed\n" +msgstr "Vim: Milleadh an príomhfhuinneog gan choinne\n" -#: ../globals.h:1060 -msgid "Pattern not found" -msgstr "Patrún gan aimsiú" +msgid "&Filter" +msgstr "&Scagaire" -#: ../globals.h:1061 -#, c-format -msgid "E486: Pattern not found: %s" -msgstr "E486: Patrún gan aimsiú: %s" +msgid "&Cancel" +msgstr "&Cealaigh" -#: ../globals.h:1062 -msgid "E487: Argument must be positive" -msgstr "E487: Ní foláir argóint dheimhneach" +msgid "Directories" +msgstr "Comhadlanna" -#: ../globals.h:1064 -msgid "E459: Cannot go back to previous directory" -msgstr "E459: Ní féidir a fhilleadh ar an chomhadlann roimhe seo" +msgid "Filter" +msgstr "Scagaire" -#: ../globals.h:1066 -msgid "E42: No Errors" -msgstr "E42: Níl Aon Earráid Ann" +msgid "&Help" +msgstr "&Cabhair" -#: ../globals.h:1067 -msgid "E776: No location list" -msgstr "E776: Gan liosta suíomh" +msgid "Files" +msgstr "Comhaid" -#: ../globals.h:1068 -msgid "E43: Damaged match string" -msgstr "E43: Teaghrán cuardaigh loite" +msgid "&OK" +msgstr "&OK" -#: ../globals.h:1069 -msgid "E44: Corrupted regexp program" -msgstr "E44: Clár na sloinn ionadaíochta truaillithe" +msgid "Selection" +msgstr "Roghnú" -#: ../globals.h:1071 -msgid "E45: 'readonly' option is set (add ! to override)" -msgstr "E45: tá an rogha 'readonly' socraithe (cuir ! leis an ordú chun sárú)" +msgid "Find &Next" +msgstr "An Chéad Chea&nn Eile" -#: ../globals.h:1073 -#, c-format -msgid "E46: Cannot change read-only variable \"%s\"" -msgstr "E46: Ní féidir athróg inléite amháin \"%s\" a athrú" +msgid "&Replace" +msgstr "&Ionadaigh" -#: ../globals.h:1075 -#, c-format -msgid "E794: Cannot set variable in the sandbox: \"%s\"" -msgstr "E794: Ní féidir athróg a shocrú sa bhosca gainimh: \"%s\"" +msgid "Replace &All" +msgstr "Ionadaigh &Uile" -#: ../globals.h:1076 -msgid "E47: Error while reading errorfile" -msgstr "E47: Earráid agus comhad earráide á léamh" +msgid "&Undo" +msgstr "&Cealaigh" -#: ../globals.h:1078 -msgid "E48: Not allowed in sandbox" -msgstr "E48: Ní cheadaítear é seo i mbosca gainimh" +msgid "Open tab..." +msgstr "Oscail cluaisín..." -#: ../globals.h:1080 -msgid "E523: Not allowed here" -msgstr "E523: Ní cheadaítear é anseo" +msgid "Find string (use '\\\\' to find a '\\')" +msgstr "Aimsigh teaghrán (bain úsáid as '\\\\' chun '\\' a aimsiú)" -#: ../globals.h:1082 -msgid "E359: Screen mode setting not supported" -msgstr "E359: Ní féidir an mód scáileáin a shocrú" +msgid "Find & Replace (use '\\\\' to find a '\\')" +msgstr "Aimsigh & Athchuir (úsáid '\\\\' chun '\\' a aimsiú)" -#: ../globals.h:1083 -msgid "E49: Invalid scroll size" -msgstr "E49: Méid neamhbhailí scrollaithe" +#. We fake this: Use a filter that doesn't select anything and a default +#. * file name that won't be used. +msgid "Not Used" +msgstr "Gan Úsáid" -#: ../globals.h:1084 -msgid "E91: 'shell' option is empty" -msgstr "E91: rogha 'shell' folamh" +msgid "Directory\t*.nothing\n" +msgstr "Comhadlann\t*.neamhní\n" -#: ../globals.h:1085 -msgid "E255: Couldn't read in sign data!" -msgstr "E255: Níorbh fhéidir na sonraí comhartha a léamh!" +#, c-format +msgid "E671: Cannot find window title \"%s\"" +msgstr "E671: Ní féidir teideal na fuinneoige \"%s\" a aimsiú" -#: ../globals.h:1086 -msgid "E72: Close error on swap file" -msgstr "E72: Earráid agus comhad babhtála á dhúnadh" +#, c-format +msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." +msgstr "E243: Argóint gan tacaíocht: \"-%s\"; Bain úsáid as an leagan OLE." -#: ../globals.h:1087 -msgid "E73: tag stack empty" -msgstr "E73: tá cruach na gclibeanna folamh" +msgid "E672: Unable to open window inside MDI application" +msgstr "E672: Ní féidir fuinneog a oscailt isteach i bhfeidhmchlár MDI" -#: ../globals.h:1088 -msgid "E74: Command too complex" -msgstr "E74: Ordú róchasta" +msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" +msgstr "" +"Vim E458: Ní féidir iontráil dathmhapála a dháileadh, is féidir go mbeidh " +"dathanna míchearta ann" -#: ../globals.h:1089 -msgid "E75: Name too long" -msgstr "E75: Ainm rófhada" +#, c-format +msgid "E250: Fonts for the following charsets are missing in fontset %s:" +msgstr "" +"E250: Clónna ar iarraidh le haghaidh na dtacar carachtar i dtacar cló %s:" -#: ../globals.h:1090 -msgid "E76: Too many [" -msgstr "E76: an iomarca [" +#, c-format +msgid "E252: Fontset name: %s" +msgstr "E252: Ainm an tacar cló: %s" -#: ../globals.h:1091 -msgid "E77: Too many file names" -msgstr "E77: An iomarca ainmneacha comhaid" +#, c-format +msgid "Font '%s' is not fixed-width" +msgstr "Ní cló aonleithid é '%s'" -#: ../globals.h:1092 -msgid "E488: Trailing characters" -msgstr "E488: Carachtair chun deiridh" +#, c-format +msgid "E253: Fontset name: %s" +msgstr "E253: Ainm an tacar cló: %s" -#: ../globals.h:1093 -msgid "E78: Unknown mark" -msgstr "E78: Marc anaithnid" +#, c-format +msgid "Font0: %s" +msgstr "Cló0: %s" -#: ../globals.h:1094 -msgid "E79: Cannot expand wildcards" -msgstr "E79: Ní féidir saoróga a leathnú" +#, c-format +msgid "Font1: %s" +msgstr "Cló1: %s" -#: ../globals.h:1096 -msgid "E591: 'winheight' cannot be smaller than 'winminheight'" -msgstr "E591: ní cheadaítear 'winheight' a bheith níos lú ná 'winminheight'" +#, c-format +msgid "Font%ld width is not twice that of font0" +msgstr "Níl Cló%ld níos leithne faoi dhó ná cló0" -#: ../globals.h:1098 -msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" -msgstr "E592: ní cheadaítear 'winwidth' a bheith níos lú ná 'winminwidth'" +#, c-format +msgid "Font0 width: %ld" +msgstr "Leithead Cló0: %ld" -#: ../globals.h:1099 -msgid "E80: Error while writing" -msgstr "E80: Earráid agus á scríobh" +#, c-format +msgid "Font1 width: %ld" +msgstr "Leithead cló1: %ld" -#: ../globals.h:1100 -msgid "Zero count" -msgstr "Nialas" +msgid "Invalid font specification" +msgstr "Sonrú neamhbhailí cló" -#: ../globals.h:1101 -msgid "E81: Using <SID> not in a script context" -msgstr "E81: <SID> á úsáid nach i gcomhthéacs scripte" +msgid "&Dismiss" +msgstr "&Ruaig" -#: ../globals.h:1102 -#, c-format -msgid "E685: Internal error: %s" -msgstr "E685: Earráid inmheánach: %s" +msgid "no specific match" +msgstr "níl a leithéid ann" -#: ../globals.h:1104 -msgid "E363: pattern uses more memory than 'maxmempattern'" -msgstr "E363: úsáideann an patrún níos mó cuimhne ná 'maxmempattern'" +msgid "Vim - Font Selector" +msgstr "Vim - Roghnú Cló" -#: ../globals.h:1105 -msgid "E749: empty buffer" -msgstr "E749: maolán folamh" +msgid "Name:" +msgstr "Ainm:" -#: ../globals.h:1108 -msgid "E682: Invalid search pattern or delimiter" -msgstr "E682: Patrún nó teormharcóir neamhbhailí cuardaigh" +#. create toggle button +msgid "Show size in Points" +msgstr "Taispeáin méid (Pointí)" -#: ../globals.h:1109 -msgid "E139: File is loaded in another buffer" -msgstr "E139: Tá an comhad luchtaithe i maolán eile" +msgid "Encoding:" +msgstr "Ionchódú:" -#: ../globals.h:1110 -#, c-format -msgid "E764: Option '%s' is not set" -msgstr "E764: Rogha '%s' gan socrú" +msgid "Font:" +msgstr "Cló:" -#: ../globals.h:1111 -#, fuzzy -msgid "E850: Invalid register name" -msgstr "E354: Ainm neamhbhailí tabhaill: '%s'" +msgid "Style:" +msgstr "Stíl:" -#: ../globals.h:1114 -msgid "search hit TOP, continuing at BOTTOM" -msgstr "Buaileadh an BARR le linn an chuardaigh, ag leanúint ag an CHRÍOCH" +msgid "Size:" +msgstr "Méid:" -#: ../globals.h:1115 -msgid "search hit BOTTOM, continuing at TOP" -msgstr "Buaileadh an BUN le linn an chuardaigh, ag leanúint ag an BHARR" +msgid "E256: Hangul automata ERROR" +msgstr "E256: EARRÁID leis na huathoibreáin Hangul" -#: ../hardcopy.c:240 msgid "E550: Missing colon" msgstr "E550: Idirstad ar iarraidh" -#: ../hardcopy.c:252 msgid "E551: Illegal component" msgstr "E551: Comhpháirt neamhcheadaithe" -#: ../hardcopy.c:259 msgid "E552: digit expected" msgstr "E552: ag súil le digit" -#: ../hardcopy.c:473 #, c-format msgid "Page %d" msgstr "Leathanach %d" -#: ../hardcopy.c:597 msgid "No text to be printed" msgstr "Níl aon téacs le priontáil" -#: ../hardcopy.c:668 #, c-format msgid "Printing page %d (%d%%)" msgstr "Leathanach %d (%d%%) á phriontáil" -#: ../hardcopy.c:680 #, c-format msgid " Copy %d of %d" msgstr " Cóip %d de %d" -#: ../hardcopy.c:733 #, c-format msgid "Printed: %s" msgstr "Priontáilte: %s" -#: ../hardcopy.c:740 msgid "Printing aborted" msgstr "Priontáil tobscortha" -#: ../hardcopy.c:1365 msgid "E455: Error writing to PostScript output file" msgstr "E455: Earráid le linn scríobh chuig aschomhad PostScript" -#: ../hardcopy.c:1747 #, c-format msgid "E624: Can't open file \"%s\"" msgstr "E624: Ní féidir an comhad \"%s\" a oscailt" -#: ../hardcopy.c:1756 ../hardcopy.c:2470 #, c-format msgid "E457: Can't read PostScript resource file \"%s\"" msgstr "E457: Ní féidir comhad acmhainne PostScript \"%s\" a léamh" -#: ../hardcopy.c:1772 #, c-format msgid "E618: file \"%s\" is not a PostScript resource file" msgstr "E618: Níl comhad \"%s\" ina chomhad acmhainne PostScript" -#: ../hardcopy.c:1788 ../hardcopy.c:1805 ../hardcopy.c:1844 #, c-format msgid "E619: file \"%s\" is not a supported PostScript resource file" msgstr "E619: Tá \"%s\" ina chomhad acmhainne PostScript gan tacú" -#: ../hardcopy.c:1856 #, c-format msgid "E621: \"%s\" resource file has wrong version" msgstr "E621: Tá an leagan mícheart ar an gcomhad acmhainne \"%s\"" -#: ../hardcopy.c:2225 msgid "E673: Incompatible multi-byte encoding and character set." msgstr "E673: Ionchódú agus tacar carachtar ilbhirt neamh-chomhoiriúnach." -#: ../hardcopy.c:2238 msgid "E674: printmbcharset cannot be empty with multi-byte encoding." msgstr "" "E674: ní cheadaítear printmbcharset a bheith folamh le hionchódú ilbhirt." -#: ../hardcopy.c:2254 msgid "E675: No default font specified for multi-byte printing." msgstr "E675: Níor réamhshocraíodh cló le haghaidh priontála ilbhirt." -#: ../hardcopy.c:2426 msgid "E324: Can't open PostScript output file" msgstr "E324: Ní féidir aschomhad PostScript a oscailt" -#: ../hardcopy.c:2458 #, c-format msgid "E456: Can't open file \"%s\"" msgstr "E456: Ní féidir an comhad \"%s\" a oscailt" -#: ../hardcopy.c:2583 msgid "E456: Can't find PostScript resource file \"prolog.ps\"" msgstr "E456: Comhad acmhainne PostScript \"prolog.ps\" gan aimsiú" -#: ../hardcopy.c:2593 msgid "E456: Can't find PostScript resource file \"cidfont.ps\"" msgstr "E456: Comhad acmhainne PostScript \"cidfont.ps\" gan aimsiú" -#: ../hardcopy.c:2622 ../hardcopy.c:2639 ../hardcopy.c:2665 #, c-format msgid "E456: Can't find PostScript resource file \"%s.ps\"" msgstr "E456: Comhad acmhainne PostScript \"%s.ps\" gan aimsiú" -#: ../hardcopy.c:2654 #, c-format msgid "E620: Unable to convert to print encoding \"%s\"" msgstr "E620: Ní féidir an t-ionchódú priontála \"%s\" a thiontú" -#: ../hardcopy.c:2877 msgid "Sending to printer..." msgstr "Á sheoladh chuig an phrintéir..." -#: ../hardcopy.c:2881 msgid "E365: Failed to print PostScript file" msgstr "E365: Theip ar phriontáil comhaid PostScript" -#: ../hardcopy.c:2883 msgid "Print job sent." msgstr "Seoladh jab priontála." -#: ../if_cscope.c:85 msgid "Add a new database" msgstr "Bunachar sonraí nua" -#: ../if_cscope.c:87 msgid "Query for a pattern" msgstr "Iarratas ar phatrún" -#: ../if_cscope.c:89 msgid "Show this message" msgstr "Taispeáin an teachtaireacht seo" -#: ../if_cscope.c:91 msgid "Kill a connection" msgstr "Maraigh nasc" -#: ../if_cscope.c:93 msgid "Reinit all connections" msgstr "Atúsaigh gach nasc" -#: ../if_cscope.c:95 msgid "Show connections" msgstr "Taispeáin naisc" -#: ../if_cscope.c:101 #, c-format msgid "E560: Usage: cs[cope] %s" msgstr "E560: Úsáid: cs[cope] %s" -#: ../if_cscope.c:225 msgid "This cscope command does not support splitting the window.\n" msgstr "Ní féidir fuinneoga a scoilteadh leis an ordú seo `cscope'.\n" -#: ../if_cscope.c:266 msgid "E562: Usage: cstag <ident>" msgstr "E562: Úsáid: cstag <ident>" -#: ../if_cscope.c:313 msgid "E257: cstag: tag not found" msgstr "E257: cstag: clib gan aimsiú" -#: ../if_cscope.c:461 #, c-format msgid "E563: stat(%s) error: %d" msgstr "E563: earráid stat(%s): %d" -#: ../if_cscope.c:551 +msgid "E563: stat error" +msgstr "E563: earráid stat" + #, c-format msgid "E564: %s is not a directory or a valid cscope database" msgstr "E564: Níl %s ina comhadlann nó bunachar sonraí cscope bailí" -#: ../if_cscope.c:566 #, c-format msgid "Added cscope database %s" msgstr "Bunachar sonraí nua cscope: %s" -#: ../if_cscope.c:616 #, c-format -msgid "E262: error reading cscope connection %<PRId64>" -msgstr "E262: earráid agus an nasc cscope %<PRId64> á léamh" +msgid "E262: error reading cscope connection %ld" +msgstr "E262: earráid agus an nasc cscope %ld á léamh" -#: ../if_cscope.c:711 msgid "E561: unknown cscope search type" msgstr "E561: cineál anaithnid cuardaigh cscope" -#: ../if_cscope.c:752 ../if_cscope.c:789 msgid "E566: Could not create cscope pipes" msgstr "E566: Níorbh fhéidir píopaí cscope a chruthú" -#: ../if_cscope.c:767 msgid "E622: Could not fork for cscope" msgstr "E622: Níorbh fhéidir forc a dhéanamh le haghaidh cscope" -#: ../if_cscope.c:849 -#, fuzzy msgid "cs_create_connection setpgid failed" -msgstr "theip ar rith cs_create_connection" +msgstr "theip ar setpgid do cs_create_connection" -#: ../if_cscope.c:853 ../if_cscope.c:889 msgid "cs_create_connection exec failed" msgstr "theip ar rith cs_create_connection" -#: ../if_cscope.c:863 ../if_cscope.c:902 msgid "cs_create_connection: fdopen for to_fp failed" msgstr "cs_create_connection: theip ar fdopen le haghaidh to_fp" -#: ../if_cscope.c:865 ../if_cscope.c:906 msgid "cs_create_connection: fdopen for fr_fp failed" msgstr "cs_create_connection: theip ar fdopen le haghaidh fr_fp" -#: ../if_cscope.c:890 msgid "E623: Could not spawn cscope process" msgstr "E623: Níorbh fhéidir próiseas cscope a sceitheadh" -#: ../if_cscope.c:932 msgid "E567: no cscope connections" msgstr "E567: níl aon nasc cscope ann" -#: ../if_cscope.c:1009 #, c-format msgid "E469: invalid cscopequickfix flag %c for %c" msgstr "E469: bratach neamhbhailí cscopequickfix %c le haghaidh %c" -#: ../if_cscope.c:1058 #, c-format msgid "E259: no matches found for cscope query %s of %s" msgstr "" "E259: níor aimsíodh aon rud comhoiriúnach leis an iarratas cscope %s de %s" -#: ../if_cscope.c:1142 msgid "cscope commands:\n" msgstr "Orduithe cscope:\n" -#: ../if_cscope.c:1150 #, c-format msgid "%-5s: %s%*s (Usage: %s)" msgstr "%-5s: %s%*s (Úsáid: %s)" -#: ../if_cscope.c:1155 -#, fuzzy msgid "" "\n" +" a: Find assignments to this symbol\n" " c: Find functions calling this function\n" " d: Find functions called by this function\n" " e: Find this egrep pattern\n" @@ -3241,6 +2576,7 @@ msgid "" " t: Find this text string\n" msgstr "" "\n" +" a: Aimsigh ráitis sannacháin leis an tsiombail seo\n" " c: Aimsigh feidhmeanna a chuireann glaoch ar an bhfeidhm seo\n" " d: Aimsigh feidhmeanna a gcuireann an fheidhm seo glaoch orthu\n" " e: Aimsigh an patrún egrep seo\n" @@ -3248,33 +2584,34 @@ msgstr "" " g: Aimsigh an sainmhíniú seo\n" " i: Aimsigh comhaid a #include-áil an comhad seo\n" " s: Aimsigh an tsiombail C seo\n" -" t: Aimsigh sanntaí do\n" +" t: Aimsigh an teaghrán téacs seo\n" + +#, c-format +msgid "E625: cannot open cscope database: %s" +msgstr "E625: ní féidir bunachar sonraí cscope a oscailt: %s" + +msgid "E626: cannot get cscope database information" +msgstr "E626: ní féidir eolas a fháil faoin bhunachar sonraí cscope" -#: ../if_cscope.c:1226 msgid "E568: duplicate cscope database not added" msgstr "E568: níor cuireadh bunachar sonraí dúblach cscope leis" -#: ../if_cscope.c:1335 #, c-format msgid "E261: cscope connection %s not found" msgstr "E261: nasc cscope %s gan aimsiú" -#: ../if_cscope.c:1364 #, c-format msgid "cscope connection %s closed" msgstr "Dúnadh nasc cscope %s" #. should not reach here -#: ../if_cscope.c:1486 msgid "E570: fatal error in cs_manage_matches" msgstr "E570: earráid mharfach i cs_manage_matches" -#: ../if_cscope.c:1693 #, c-format msgid "Cscope tag: %s" msgstr "Clib cscope: %s" -#: ../if_cscope.c:1711 msgid "" "\n" " # line" @@ -3282,88 +2619,301 @@ msgstr "" "\n" " # líne" -#: ../if_cscope.c:1713 msgid "filename / context / line\n" msgstr "ainm comhaid / comhthéacs / líne\n" -#: ../if_cscope.c:1809 #, c-format msgid "E609: Cscope error: %s" msgstr "E609: Earráid cscope: %s" -#: ../if_cscope.c:2053 msgid "All cscope databases reset" msgstr "Athshocraíodh gach bunachar sonraí cscope" -#: ../if_cscope.c:2123 msgid "no cscope connections\n" msgstr "níl aon nasc cscope\n" -#: ../if_cscope.c:2126 msgid " # pid database name prepend path\n" msgstr " # pid ainm bunachair conair thosaigh\n" -#: ../main.c:144 +msgid "Lua library cannot be loaded." +msgstr "Ní féidir an leabharlann Lua a luchtú." + +msgid "cannot save undo information" +msgstr "ní féidir eolas cealaithe a shábháil" + +msgid "" +"E815: Sorry, this command is disabled, the MzScheme libraries could not be " +"loaded." +msgstr "" +"E815: Tá brón orm, bhí an t-ordú seo díchumasaithe, níorbh fhéidir " +"leabharlanna MzScheme a luchtú." + +msgid "" +"E895: Sorry, this command is disabled, the MzScheme's racket/base module " +"could not be loaded." +msgstr "" +"E895: Ár leithscéal, tá an t-ordú seo díchumasaithe; níorbh fhéidir " +"modúl racket/base MzScheme a luchtú." + +msgid "invalid expression" +msgstr "slonn neamhbhailí" + +msgid "expressions disabled at compile time" +msgstr "díchumasaíodh sloinn ag am an tiomsaithe" + +msgid "hidden option" +msgstr "rogha fholaithe" + +msgid "unknown option" +msgstr "rogha anaithnid" + +msgid "window index is out of range" +msgstr "innéacs fuinneoige as raon" + +msgid "couldn't open buffer" +msgstr "ní féidir maolán a oscailt" + +msgid "cannot delete line" +msgstr "ní féidir an líne a scriosadh" + +msgid "cannot replace line" +msgstr "ní féidir an líne a athchur" + +msgid "cannot insert line" +msgstr "ní féidir líne a ionsá" + +msgid "string cannot contain newlines" +msgstr "ní cheadaítear carachtair líne nua sa teaghrán" + +msgid "error converting Scheme values to Vim" +msgstr "earráid agus luach Scheme á thiontú go Vim" + +msgid "Vim error: ~a" +msgstr "earráid Vim: ~a" + +msgid "Vim error" +msgstr "earráid Vim" + +msgid "buffer is invalid" +msgstr "maolán neamhbhailí" + +msgid "window is invalid" +msgstr "fuinneog neamhbhailí" + +msgid "linenr out of range" +msgstr "líne-uimhir as raon" + +msgid "not allowed in the Vim sandbox" +msgstr "ní cheadaítear é seo i mbosca gainimh Vim" + +msgid "E836: This Vim cannot execute :python after using :py3" +msgstr "" +"E836: Ní féidir leis an leagan seo de Vim :python a rith tar éis :py3 a úsáid" + +msgid "" +"E263: Sorry, this command is disabled, the Python library could not be " +"loaded." +msgstr "" +"E263: Tá brón orm, níl an t-ordú seo le fáil, níorbh fhéidir an leabharlann " +"Python a luchtú." + +msgid "" +"E887: Sorry, this command is disabled, the Python's site module could not be " +"loaded." +msgstr "" +"E887: Ár leithscéal, níl an t-ordú seo le fáil, níorbh fhéidir an modúl " +"Python a luchtú." + +msgid "E659: Cannot invoke Python recursively" +msgstr "E659: Ní féidir Python a rith go hathchúrsach" + +msgid "E837: This Vim cannot execute :py3 after using :python" +msgstr "" +"E837: Ní féidir leis an leagan seo de Vim :py3 a rith tar éis :python a úsáid" + +msgid "E265: $_ must be an instance of String" +msgstr "E265: caithfidh $_ a bheith cineál Teaghráin" + +msgid "" +"E266: Sorry, this command is disabled, the Ruby library could not be loaded." +msgstr "" +"E266: Tá brón orm, níl an t-ordú seo le fáil, níorbh fhéidir an leabharlann " +"Ruby a luchtú." + +msgid "E267: unexpected return" +msgstr "E267: \"return\" gan choinne" + +msgid "E268: unexpected next" +msgstr "E268: \"next\" gan choinne" + +msgid "E269: unexpected break" +msgstr "E269: \"break\" gan choinne" + +msgid "E270: unexpected redo" +msgstr "E270: \"redo\" gan choinne" + +msgid "E271: retry outside of rescue clause" +msgstr "E271: \"retry\" taobh amuigh de chlásal tarrthála" + +msgid "E272: unhandled exception" +msgstr "E272: eisceacht gan láimhseáil" + +#, c-format +msgid "E273: unknown longjmp status %d" +msgstr "E273: stádas anaithnid longjmp %d" + +msgid "invalid buffer number" +msgstr "uimhir neamhbhailí mhaoláin" + +msgid "not implemented yet" +msgstr "níl ar fáil" + +#. ??? +msgid "cannot set line(s)" +msgstr "ní féidir lín(t)e a shocrú" + +msgid "invalid mark name" +msgstr "ainm neamhbhailí mairc" + +msgid "mark not set" +msgstr "marc gan socrú" + +#, c-format +msgid "row %d column %d" +msgstr "líne %d colún %d" + +msgid "cannot insert/append line" +msgstr "ní féidir líne a ionsá/iarcheangal" + +msgid "line number out of range" +msgstr "líne-uimhir as raon" + +msgid "unknown flag: " +msgstr "bratach anaithnid: " + +msgid "unknown vimOption" +msgstr "vimOption anaithnid" + +msgid "keyboard interrupt" +msgstr "idirbhriseadh méarchláir" + +msgid "vim error" +msgstr "earráid vim" + +msgid "cannot create buffer/window command: object is being deleted" +msgstr "ní féidir ordú maoláin/fuinneoige a chruthú: réad á scriosadh" + +msgid "" +"cannot register callback command: buffer/window is already being deleted" +msgstr "ní féidir ordú aisghlaoch a chlárú: maolán/fuinneog á scriosadh cheana" + +#. This should never happen. Famous last word? +msgid "" +"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim." +"org" +msgstr "" +"E280: EARRÁID MHARFACH TCL: liosta truaillithe tagartha!? Seol tuairisc " +"fhabht chuig <vim-dev@vim.org> le do thoil" + +msgid "cannot register callback command: buffer/window reference not found" +msgstr "" +"ní féidir ordú aisghlaoch a chlárú: tagairt mhaolán/fhuinneoige gan aimsiú" + +msgid "" +"E571: Sorry, this command is disabled: the Tcl library could not be loaded." +msgstr "" +"E571: Tá brón orm, níl an t-ordú seo le fáil: níorbh fhéidir an leabharlann " +"Tcl a luchtú." + +#, c-format +msgid "E572: exit code %d" +msgstr "E572: cód scortha %d" + +msgid "cannot get line" +msgstr "ní féidir an líne a fháil" + +msgid "Unable to register a command server name" +msgstr "Ní féidir ainm fhreastalaí ordaithe a chlárú" + +msgid "E248: Failed to send command to the destination program" +msgstr "E248: Theip ar sheoladh ordú chuig an sprioc-chlár" + +#, c-format +msgid "E573: Invalid server id used: %s" +msgstr "E573: Aitheantas neamhbhailí freastalaí in úsáid: %s" + +msgid "E251: VIM instance registry property is badly formed. Deleted!" +msgstr "E251: Airí míchumtha sa chlárlann áisc VIM. Scriosta!" + +#, c-format +msgid "E696: Missing comma in List: %s" +msgstr "E696: Camóg ar iarraidh i Liosta: %s" + +#, c-format +msgid "E697: Missing end of List ']': %s" +msgstr "E697: ']' ar iarraidh ag deireadh liosta: %s" + msgid "Unknown option argument" msgstr "Argóint anaithnid rogha" -#: ../main.c:146 msgid "Too many edit arguments" msgstr "An iomarca argóintí eagarthóireachta" -#: ../main.c:148 msgid "Argument missing after" msgstr "Argóint ar iarraidh i ndiaidh" -#: ../main.c:150 msgid "Garbage after option argument" msgstr "Dramhaíl i ndiaidh argóinte rogha" -#: ../main.c:152 msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments" msgstr "" "An iomarca argóintí den chineál \"+ordú\", \"-c ordú\" nó \"--cmd ordú\"" -#: ../main.c:154 msgid "Invalid argument for" msgstr "Argóint neamhbhailí do" -#: ../main.c:294 #, c-format msgid "%d files to edit\n" msgstr "%d comhad le heagrú\n" -#: ../main.c:1342 +msgid "netbeans is not supported with this GUI\n" +msgstr "Ní thacaítear le netbeans sa GUI seo\n" + +msgid "'-nb' cannot be used: not enabled at compile time\n" +msgstr "Ní féidir '-nb' a úsáid: níor cumasaíodh é ag am tiomsaithe\n" + +msgid "This Vim was not compiled with the diff feature." +msgstr "Níor tiomsaíodh an leagan Vim seo le `diff' ar fáil." + msgid "Attempt to open script file again: \"" msgstr "Déan iarracht ar oscailt na scripte arís: \"" -#: ../main.c:1350 msgid "Cannot open for reading: \"" msgstr "Ní féidir é a oscailt chun léamh: \"" -#: ../main.c:1393 msgid "Cannot open for script output: \"" msgstr "Ní féidir a oscailt le haghaidh an aschuir scripte: \"" -#: ../main.c:1622 +msgid "Vim: Error: Failure to start gvim from NetBeans\n" +msgstr "Vim: Earráid: Theip ar thosú gvim ó NetBeans\n" + +msgid "Vim: Error: This version of Vim does not run in a Cygwin terminal\n" +msgstr "Vim: Earráid: Ní féidir an leagan seo de Vim a rith i dteirminéal Cygwin\n" + msgid "Vim: Warning: Output is not to a terminal\n" msgstr "Vim: Rabhadh: Níl an t-aschur ag dul chuig teirminéal\n" -#: ../main.c:1624 msgid "Vim: Warning: Input is not from a terminal\n" msgstr "Vim: Rabhadh: Níl an t-ionchur ag teacht ó theirminéal\n" #. just in case.. -#: ../main.c:1891 msgid "pre-vimrc command line" msgstr "líne na n-orduithe pre-vimrc" -#: ../main.c:1964 #, c-format msgid "E282: Cannot read from \"%s\"" msgstr "E282: Ní féidir léamh ó \"%s\"" -#: ../main.c:2149 msgid "" "\n" "More info with: \"vim -h\"\n" @@ -3371,23 +2921,18 @@ msgstr "" "\n" "Tuilleadh eolais: \"vim -h\"\n" -#: ../main.c:2178 msgid "[file ..] edit specified file(s)" msgstr "[comhad ..] cuir na comhaid ceaptha in eagar" -#: ../main.c:2179 msgid "- read text from stdin" msgstr "- scríobh téacs ó stdin" -#: ../main.c:2180 msgid "-t tag edit file where tag is defined" msgstr "-t tag cuir an comhad ina bhfuil an chlib in eagar" -#: ../main.c:2181 msgid "-q [errorfile] edit file with first error" msgstr "-q [comhadearr] cuir comhad leis an chéad earráid in eagar" -#: ../main.c:2187 msgid "" "\n" "\n" @@ -3397,11 +2942,9 @@ msgstr "" "\n" "úsáid:" -#: ../main.c:2189 msgid " vim [arguments] " msgstr " vim [argóintí] " -#: ../main.c:2193 msgid "" "\n" " or:" @@ -3409,7 +2952,14 @@ msgstr "" "\n" " nó:" -#: ../main.c:2196 +msgid "" +"\n" +"Where case is ignored prepend / to make flag upper case" +msgstr "" +"\n" +"Nuair nach cásíogair é, cuir '/' ag tosach na brataí chun í a chur sa chás " +"uachtair" + msgid "" "\n" "\n" @@ -3419,194 +2969,338 @@ msgstr "" "\n" "Argóintí:\n" -#: ../main.c:2197 msgid "--\t\t\tOnly file names after this" msgstr "--\t\t\tNí cheadaítear ach ainmneacha comhaid i ndiaidh é seo" -#: ../main.c:2199 msgid "--literal\t\tDon't expand wildcards" msgstr "--literal\t\tNá leathnaigh saoróga" -#: ../main.c:2201 +msgid "-register\t\tRegister this gvim for OLE" +msgstr "-register\t\tCláraigh an gvim seo le haghaidh OLE" + +msgid "-unregister\t\tUnregister gvim for OLE" +msgstr "-unregister\t\tDíchláraigh an gvim seo le haghaidh OLE" + +msgid "-g\t\t\tRun using GUI (like \"gvim\")" +msgstr "-g\t\t\tRith agus úsáid an GUI (mar \"gvim\")" + +msgid "-f or --nofork\tForeground: Don't fork when starting GUI" +msgstr "-f nó --nofork\tTulra: Ná déan forc agus an GUI á thosú" + msgid "-v\t\t\tVi mode (like \"vi\")" msgstr "-v\t\t\tMód Vi (mar \"vi\")" -#: ../main.c:2202 msgid "-e\t\t\tEx mode (like \"ex\")" msgstr "-e\t\t\tMód Ex (mar \"ex\")" -#: ../main.c:2203 msgid "-E\t\t\tImproved Ex mode" -msgstr "" +msgstr "-E\t\t\tMód Ex feabhsaithe" -#: ../main.c:2204 msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")" msgstr "-s\t\t\tMód ciúin (baiscphróiseála) (do \"ex\" amháin)" -#: ../main.c:2205 msgid "-d\t\t\tDiff mode (like \"vimdiff\")" msgstr "-d\t\t\tMód diff (mar \"vimdiff\")" -#: ../main.c:2206 msgid "-y\t\t\tEasy mode (like \"evim\", modeless)" msgstr "-y\t\t\tMód éasca (mar \"evim\", gan mhóid)" -#: ../main.c:2207 msgid "-R\t\t\tReadonly mode (like \"view\")" msgstr "-R\t\t\tMód inléite amháin (mar \"view\")" -#: ../main.c:2208 msgid "-Z\t\t\tRestricted mode (like \"rvim\")" msgstr "-Z\t\t\tMód srianta (mar \"rvim\")" -#: ../main.c:2209 msgid "-m\t\t\tModifications (writing files) not allowed" msgstr "-m\t\t\tNí cheadaítear athruithe (.i. scríobh na gcomhad)" -#: ../main.c:2210 msgid "-M\t\t\tModifications in text not allowed" msgstr "-M\t\t\tNí cheadaítear athruithe sa téacs" -#: ../main.c:2211 msgid "-b\t\t\tBinary mode" msgstr "-b\t\t\tMód dénártha" -#: ../main.c:2212 msgid "-l\t\t\tLisp mode" msgstr "-l\t\t\tMód Lisp" -#: ../main.c:2213 msgid "-C\t\t\tCompatible with Vi: 'compatible'" msgstr "-C\t\t\tComhoiriúnach le Vi: 'compatible'" -#: ../main.c:2214 msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'" msgstr "-N\t\t\tNí comhoiriúnaithe le Vi go hiomlán: 'nocompatible'" -#: ../main.c:2215 msgid "-V[N][fname]\t\tBe verbose [level N] [log messages to fname]" msgstr "" "-V[N][fname]\t\tBí foclach [leibhéal N] [logáil teachtaireachtaí i fname]" -#: ../main.c:2216 msgid "-D\t\t\tDebugging mode" msgstr "-D\t\t\tMód dífhabhtaithe" -#: ../main.c:2217 msgid "-n\t\t\tNo swap file, use memory only" msgstr "-n\t\t\tNá húsáid comhad babhtála .i. ná húsáid ach an chuimhne" -#: ../main.c:2218 msgid "-r\t\t\tList swap files and exit" msgstr "-r\t\t\tTaispeáin comhaid bhabhtála agus scoir" -#: ../main.c:2219 msgid "-r (with file name)\tRecover crashed session" msgstr "-r (le hainm comhaid)\tAthshlánaigh ó chliseadh" -#: ../main.c:2220 msgid "-L\t\t\tSame as -r" msgstr "-L\t\t\tAr comhbhrí le -r" -#: ../main.c:2221 +msgid "-f\t\t\tDon't use newcli to open window" +msgstr "-f\t\t\tNá húsáid newcli chun fuinneog a oscailt" + +msgid "-dev <device>\t\tUse <device> for I/O" +msgstr "-dev <gléas>\t\tBain úsáid as <gléas> do I/A" + msgid "-A\t\t\tstart in Arabic mode" msgstr "-A\t\t\ttosaigh sa mhód Araibise" -#: ../main.c:2222 msgid "-H\t\t\tStart in Hebrew mode" msgstr "-H\t\t\tTosaigh sa mhód Eabhraise" -#: ../main.c:2223 msgid "-F\t\t\tStart in Farsi mode" msgstr "-F\t\t\tTosaigh sa mhód Pheirsise" -#: ../main.c:2224 msgid "-T <terminal>\tSet terminal type to <terminal>" msgstr "-T <teirminéal>\tSocraigh cineál teirminéal" -#: ../main.c:2225 +msgid "--not-a-term\t\tSkip warning for input/output not being a terminal" +msgstr "--not-a-term\t\tNá bac le rabhadh faoi ionchur/aschur gan a bheith ón teirminéal" + msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc" msgstr "-u <vimrc>\t\tÚsáid <vimrc> in ionad aon .vimrc" -#: ../main.c:2226 +msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" +msgstr "-U <gvimrc>\t\tBain úsáid as <gvimrc> in ionad aon .gvimrc" + msgid "--noplugin\t\tDon't load plugin scripts" msgstr "--noplugin\t\tNá luchtaigh breiseáin" -#: ../main.c:2227 msgid "-p[N]\t\tOpen N tab pages (default: one for each file)" -msgstr "-p[N]\t\tOscail N leathanach cluaisín (default: ceann do gach comhad)" +msgstr "-p[N]\t\tOscail N leathanach cluaisíní (default: ceann do gach comhad)" -#: ../main.c:2228 msgid "-o[N]\t\tOpen N windows (default: one for each file)" msgstr "-o[N]\t\tOscail N fuinneog (réamhshocrú: ceann do gach comhad)" -#: ../main.c:2229 msgid "-O[N]\t\tLike -o but split vertically" msgstr "-O[N]\t\tMar -o, ach roinn go hingearach" -#: ../main.c:2230 msgid "+\t\t\tStart at end of file" msgstr "+\t\t\tTosaigh ag an chomhadchríoch" -#: ../main.c:2231 msgid "+<lnum>\t\tStart at line <lnum>" msgstr "+<lnum>\t\tTosaigh ar líne <lnum>" -#: ../main.c:2232 msgid "--cmd <command>\tExecute <command> before loading any vimrc file" msgstr "--cmd <ordú>\tRith <ordú> roimh aon chomhad vimrc a luchtú" -#: ../main.c:2233 msgid "-c <command>\t\tExecute <command> after loading the first file" msgstr "-c <ordú>\t\tRith <ordú> i ndiaidh luchtú an chéad chomhad" -#: ../main.c:2235 msgid "-S <session>\t\tSource file <session> after loading the first file" msgstr "" "-S <seisiún>\t\tLéigh comhad <seisiún> i ndiaidh an chéad chomhad á léamh" -#: ../main.c:2236 msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>" msgstr "-s <script>\tLéigh orduithe gnáthmhóid ón chomhad <script>" -#: ../main.c:2237 msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>" msgstr "" "-w <script>\tIarcheangail gach ordú iontráilte leis an gcomhad <script>" -#: ../main.c:2238 msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>" msgstr "-W <aschur>\tScríobh gach ordú clóscríofa sa chomhad <aschur>" -#: ../main.c:2240 +msgid "-x\t\t\tEdit encrypted files" +msgstr "-x\t\t\tCuir comhaid chriptithe in eagar" + +msgid "-display <display>\tConnect vim to this particular X-server" +msgstr "-display <freastalaí>\tNasc vim leis an bhfreastalaí-X seo" + +msgid "-X\t\t\tDo not connect to X server" +msgstr "-X\t\t\tNá naisc leis an bhfreastalaí X" + +msgid "--remote <files>\tEdit <files> in a Vim server if possible" +msgstr "" +"--remote <comhaid>\tCuir <comhaid> in eagar le freastalaí Vim más féidir" + +msgid "--remote-silent <files> Same, don't complain if there is no server" +msgstr "" +"--remote-silent <comhaid> Mar an gcéanna, ná déan gearán mura bhfuil " +"freastalaí ann" + +msgid "" +"--remote-wait <files> As --remote but wait for files to have been edited" +msgstr "" +"--remote-wait <comhaid> Mar --remote ach fan leis na comhaid a bheith " +"curtha in eagar" + +msgid "" +"--remote-wait-silent <files> Same, don't complain if there is no server" +msgstr "" +"--remote-wait-silent <comhaid> Mar an gcéanna, ná déan gearán mura bhfuil " +"freastalaí ann" + +msgid "" +"--remote-tab[-wait][-silent] <files> As --remote but use tab page per file" +msgstr "" +"--remote-tab[-wait][-silent] <comhaid> Cosúil le --remote ach oscail " +"cluaisín do gach comhad" + +msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" +msgstr "" +"--remote-send <eochracha>\tSeol <eochracha> chuig freastalaí Vim agus scoir" + +msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" +msgstr "" +"--remote-expr <slonn>\tLuacháil <slonn> le freastalaí Vim agus taispeáin an " +"toradh" + +msgid "--serverlist\t\tList available Vim server names and exit" +msgstr "--serverlist\t\tTaispeáin freastalaithe Vim atá ar fáil agus scoir" + +msgid "--servername <name>\tSend to/become the Vim server <name>" +msgstr "--servername <ainm>\tSeol chuig/Téigh i do fhreastalaí Vim <ainm>" + msgid "--startuptime <file>\tWrite startup timing messages to <file>" msgstr "" "--startuptime <comhad>\tScríobh faisnéis maidir le tréimhse tosaithe i " "<comhad>" -#: ../main.c:2242 msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo" msgstr "-i <viminfo>\t\tÚsáid <viminfo> in ionad .viminfo" -#: ../main.c:2243 msgid "-h or --help\tPrint Help (this message) and exit" msgstr "-h nó --help\tTaispeáin an chabhair seo agus scoir" -#: ../main.c:2244 msgid "--version\t\tPrint version information and exit" msgstr "--version\t\tTaispeáin eolas faoin leagan agus scoir" -#: ../mark.c:676 +msgid "" +"\n" +"Arguments recognised by gvim (Motif version):\n" +msgstr "" +"\n" +"Argóintí ar eolas do gvim (leagan Motif):\n" + +msgid "" +"\n" +"Arguments recognised by gvim (neXtaw version):\n" +msgstr "" +"\n" +"Argóintí ar eolas do gvim (leagan neXtaw):\n" + +msgid "" +"\n" +"Arguments recognised by gvim (Athena version):\n" +msgstr "" +"\n" +"Argóintí ar eolas do gvim (leagan Athena):\n" + +msgid "-display <display>\tRun vim on <display>" +msgstr "-display <scáileán>\tRith vim ar <scáileán>" + +msgid "-iconic\t\tStart vim iconified" +msgstr "-iconic\t\tTosaigh vim sa mhód íoslaghdaithe" + +msgid "-background <color>\tUse <color> for the background (also: -bg)" +msgstr "-background <dath>\tBain úsáid as <dath> don chúlra (-bg fosta)" + +msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" +msgstr "-foreground <dath>\tÚsáid <dath> le haghaidh gnáth-théacs (fosta: -fg)" + +msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" +msgstr "-font <cló>\t\tÚsáid <cló> le haghaidh gnáth-théacs (fosta: -fn)" + +msgid "-boldfont <font>\tUse <font> for bold text" +msgstr "-boldfont <cló>\tBain úsáid as <cló> do chló trom" + +msgid "-italicfont <font>\tUse <font> for italic text" +msgstr "-italicfont <cló>\tÚsáid <cló> le haghaidh téacs iodálach" + +msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" +msgstr "" +"-geometry <geoim>\tÚsáid <geoim> le haghaidh na céimseatan tosaigh (fosta: -" +"geom)" + +msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" +msgstr "-borderwidth <leithead>\tSocraigh <leithead> na himlíne (-bw fosta)" + +msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" +msgstr "" +"-scrollbarwidth <leithead> Socraigh leithead na scrollbharraí a bheith " +"<leithead> (fosta: -sw)" + +msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" +msgstr "" +"-menuheight <airde>\tSocraigh airde an bharra roghchláir a bheith <airde> " +"(fosta: -mh)" + +msgid "-reverse\t\tUse reverse video (also: -rv)" +msgstr "-reverse\t\tÚsáid fís aisiompaithe (fosta: -rv)" + +msgid "+reverse\t\tDon't use reverse video (also: +rv)" +msgstr "+reverse\t\tNá húsáid fís aisiompaithe (fosta: +rv)" + +msgid "-xrm <resource>\tSet the specified resource" +msgstr "-xrm <acmhainn>\tSocraigh an acmhainn sainithe" + +msgid "" +"\n" +"Arguments recognised by gvim (GTK+ version):\n" +msgstr "" +"\n" +"Argóintí ar eolas do gvim (leagan GTK+):\n" + +msgid "-display <display>\tRun vim on <display> (also: --display)" +msgstr "-display <scáileán>\tRith vim ar <scáileán> (fosta: --display)" + +msgid "--role <role>\tSet a unique role to identify the main window" +msgstr "--role <ról>\tSocraigh ról sainiúil chun an phríomhfhuinneog a aithint" + +msgid "--socketid <xid>\tOpen Vim inside another GTK widget" +msgstr "--socketid <xid>\tOscail Vim isteach i ngiuirléid GTK eile" + +msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" +msgstr "--echo-wid\t\tTaispeánann gvim aitheantas na fuinneoige ar stdout" + +msgid "-P <parent title>\tOpen Vim inside parent application" +msgstr "-P <máthairchlár>\tOscail Vim isteach sa mháthairchlár" + +msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" +msgstr "--windowid <HWND>\tOscail Vim isteach i ngiuirléid win32 eile" + +msgid "No display" +msgstr "Gan taispeáint" + +#. Failed to send, abort. +msgid ": Send failed.\n" +msgstr ": Theip ar seoladh.\n" + +#. Let vim start normally. +msgid ": Send failed. Trying to execute locally\n" +msgstr ": Theip ar seoladh. Ag baint triail as go logánta\n" + +#, c-format +msgid "%d of %d edited" +msgstr "%d as %d déanta" + +msgid "No display: Send expression failed.\n" +msgstr "Gan taispeáint: Theip ar sheoladh sloinn.\n" + +msgid ": Send expression failed.\n" +msgstr ": Theip ar sheoladh sloinn.\n" + msgid "No marks set" msgstr "Níl aon mharc socraithe" -#: ../mark.c:678 #, c-format msgid "E283: No marks matching \"%s\"" msgstr "E283: Níl aon mharc comhoiriúnaithe le \"%s\"" #. Highlight title -#: ../mark.c:687 msgid "" "\n" "mark line col file/text" @@ -3615,7 +3309,6 @@ msgstr "" "marc líne col comhad/téacs" #. Highlight title -#: ../mark.c:789 msgid "" "\n" " jump line col file/text" @@ -3624,7 +3317,6 @@ msgstr "" " léim líne col comhad/téacs" #. Highlight title -#: ../mark.c:831 msgid "" "\n" "change line col text" @@ -3632,7 +3324,6 @@ msgstr "" "\n" "athrú líne col téacs" -#: ../mark.c:1238 msgid "" "\n" "# File marks:\n" @@ -3641,7 +3332,6 @@ msgstr "" "# Marcanna comhaid:\n" #. Write the jumplist with -' -#: ../mark.c:1271 msgid "" "\n" "# Jumplist (newest first):\n" @@ -3649,7 +3339,6 @@ msgstr "" "\n" "# Liosta léimeanna (is nuaí i dtosach):\n" -#: ../mark.c:1352 msgid "" "\n" "# History of marks within files (newest to oldest):\n" @@ -3657,86 +3346,90 @@ msgstr "" "\n" "# Stair na marcanna i gcomhaid (is nuaí ar dtús):\n" -#: ../mark.c:1431 msgid "Missing '>'" msgstr "`>' ar iarraidh" -#: ../memfile.c:426 +msgid "E543: Not a valid codepage" +msgstr "E543: Ní códleathanach bailí é" + +msgid "E284: Cannot set IC values" +msgstr "E284: Ní féidir luachanna IC a shocrú" + +msgid "E285: Failed to create input context" +msgstr "E285: Theip ar chruthú comhthéacs ionchuir" + +msgid "E286: Failed to open input method" +msgstr "E286: Theip ar oscailt mhodh ionchuir" + +msgid "E287: Warning: Could not set destroy callback to IM" +msgstr "E287: Rabhadh: Níorbh fhéidir aisghlaoch léirscriosta a shocrú le IM" + +msgid "E288: input method doesn't support any style" +msgstr "E288: Ní thacaíonn an modh ionchuir aon stíl" + +msgid "E289: input method doesn't support my preedit type" +msgstr "E289: ní thacaíonn an modh ionchuir mo chineál réamheagair" + msgid "E293: block was not locked" msgstr "E293: ní raibh an bloc faoi ghlas" -#: ../memfile.c:799 msgid "E294: Seek error in swap file read" msgstr "E294: Earráid chuardaigh agus comhad babhtála á léamh" -#: ../memfile.c:803 msgid "E295: Read error in swap file" msgstr "E295: Earráid sa léamh i gcomhad babhtála" -#: ../memfile.c:849 msgid "E296: Seek error in swap file write" msgstr "E296: Earráid chuardaigh agus comhad babhtála á scríobh" -#: ../memfile.c:865 msgid "E297: Write error in swap file" msgstr "E297: Earráid sa scríobh i gcomhad babhtála" -#: ../memfile.c:1036 msgid "E300: Swap file already exists (symlink attack?)" msgstr "E300: Tá comhad babhtála ann cheana (ionsaí le naisc shiombalacha?)" -#: ../memline.c:318 msgid "E298: Didn't get block nr 0?" msgstr "E298: Ní bhfuarthas bloc 0?" -#: ../memline.c:361 msgid "E298: Didn't get block nr 1?" msgstr "E298: Ní bhfuarthas bloc a haon?" -#: ../memline.c:377 msgid "E298: Didn't get block nr 2?" msgstr "E298: Ní bhfuarthas bloc a dó?" +msgid "E843: Error while updating swap file crypt" +msgstr "E843: Earráid agus criptiú an chomhaid bhabhtála á nuashonrú" + #. could not (re)open the swap file, what can we do???? -#: ../memline.c:465 msgid "E301: Oops, lost the swap file!!!" msgstr "E301: Úps, cailleadh an comhad babhtála!!!" -#: ../memline.c:477 msgid "E302: Could not rename swap file" msgstr "E302: Níorbh fhéidir an comhad babhtála a athainmniú" -#: ../memline.c:554 #, c-format msgid "E303: Unable to open swap file for \"%s\", recovery impossible" msgstr "" "E303: Ní féidir comhad babhtála le haghaidh \"%s\" a oscailt, ní féidir " "athshlánú" -#: ../memline.c:666 msgid "E304: ml_upd_block0(): Didn't get block 0??" msgstr "E304: ml_upd_block0(): Ní bhfuarthas bloc 0??" -#. no swap files found -#: ../memline.c:830 #, c-format msgid "E305: No swap file found for %s" msgstr "E305: Níor aimsíodh comhad babhtála le haghaidh %s" -#: ../memline.c:839 msgid "Enter number of swap file to use (0 to quit): " msgstr "Iontráil uimhir an chomhaid babhtála le húsáid (0 = scoir): " -#: ../memline.c:879 #, c-format msgid "E306: Cannot open %s" msgstr "E306: Ní féidir %s a oscailt" -#: ../memline.c:897 msgid "Unable to read block 0 from " msgstr "Ní féidir bloc 0 a léamh ó " -#: ../memline.c:900 msgid "" "\n" "Maybe no changes were made or Vim did not update the swap file." @@ -3745,28 +3438,22 @@ msgstr "" "B'fhéidir nach raibh aon athrú á dhéanamh, nó tá an comhad\n" "babhtála as dáta." -#: ../memline.c:909 msgid " cannot be used with this version of Vim.\n" msgstr " níl ar fáil leis an leagan seo de Vim.\n" -#: ../memline.c:911 msgid "Use Vim version 3.0.\n" msgstr "Bain úsáid as Vim, leagan 3.0.\n" -#: ../memline.c:916 #, c-format msgid "E307: %s does not look like a Vim swap file" msgstr "E307: Níl %s cosúil le comhad babhtála Vim" -#: ../memline.c:922 msgid " cannot be used on this computer.\n" msgstr " níl ar fáil ar an ríomhaire seo.\n" -#: ../memline.c:924 msgid "The file was created on " msgstr "Cruthaíodh an comhad seo ar " -#: ../memline.c:928 msgid "" ",\n" "or the file has been damaged." @@ -3774,86 +3461,107 @@ msgstr "" ",\n" "is é sin nó rinneadh dochar don chomhad." -#: ../memline.c:945 +#, c-format +msgid "" +"E833: %s is encrypted and this version of Vim does not support encryption" +msgstr "" +"E833: tá %s criptithe agus ní thacaíonn an leagan seo de Vim le criptiú" + msgid " has been damaged (page size is smaller than minimum value).\n" msgstr " rinneadh dochar dó (méid an leathanaigh níos lú ná an íosmhéid).\n" -#: ../memline.c:974 #, c-format msgid "Using swap file \"%s\"" msgstr "Comhad babhtála \"%s\" á úsáid" -#: ../memline.c:980 #, c-format msgid "Original file \"%s\"" msgstr "Comhad bunúsach \"%s\"" -#: ../memline.c:995 msgid "E308: Warning: Original file may have been changed" msgstr "E308: Rabhadh: Is féidir gur athraíodh an comhad bunúsach" -#: ../memline.c:1061 +#, c-format +msgid "Swap file is encrypted: \"%s\"" +msgstr "Tá an comhad babhtála criptithe: \"%s\"" + +msgid "" +"\n" +"If you entered a new crypt key but did not write the text file," +msgstr "" +"\n" +"Má chuir tú eochair nua chriptiúcháin isteach, ach mura scríobh tú an " +"téacschomhad," + +msgid "" +"\n" +"enter the new crypt key." +msgstr "" +"\n" +"cuir isteach an eochair nua chriptiúcháin." + +msgid "" +"\n" +"If you wrote the text file after changing the crypt key press enter" +msgstr "" +"\n" +"Má scríobh tú an téacschomhad tar éis duit an eochair chriptiúcháín a athrú, " +"brúigh Enter" + +msgid "" +"\n" +"to use the same key for text file and swap file" +msgstr "" +"\n" +"chun an eochair chéanna a úsáid don téacschomhad agus an comhad babhtála" + #, c-format msgid "E309: Unable to read block 1 from %s" msgstr "E309: Ní féidir bloc a haon a léamh ó %s" -#: ../memline.c:1065 msgid "???MANY LINES MISSING" msgstr "???GO LEOR LÍNTE AR IARRAIDH" -#: ../memline.c:1076 msgid "???LINE COUNT WRONG" msgstr "???LÍON MÍCHEART NA LÍNTE" -#: ../memline.c:1082 msgid "???EMPTY BLOCK" msgstr "???BLOC FOLAMH" -#: ../memline.c:1103 msgid "???LINES MISSING" msgstr "???LÍNTE AR IARRAIDH" -#: ../memline.c:1128 #, c-format msgid "E310: Block 1 ID wrong (%s not a .swp file?)" msgstr "E310: Aitheantas mícheart ar bhloc a haon (níl %s ina chomhad .swp?)" -#: ../memline.c:1133 msgid "???BLOCK MISSING" msgstr "???BLOC AR IARRAIDH" -#: ../memline.c:1147 msgid "??? from here until ???END lines may be messed up" msgstr "??? is féidir go ndearnadh praiseach de línte ó anseo go ???END" -#: ../memline.c:1164 msgid "??? from here until ???END lines may have been inserted/deleted" msgstr "??? is féidir go bhfuil línte ionsáite/scriosta ó anseo go ???END" -#: ../memline.c:1181 msgid "???END" msgstr "???DEIREADH" -#: ../memline.c:1238 msgid "E311: Recovery Interrupted" msgstr "E311: Idirbhriseadh an t-athshlánú" -#: ../memline.c:1243 msgid "" "E312: Errors detected while recovering; look for lines starting with ???" msgstr "" "E312: Braitheadh earráidí le linn athshlánaithe; féach ar na línte le ??? ar " "tosach" -#: ../memline.c:1245 msgid "See \":help E312\" for more information." msgstr "Bain triail as \":help E312\" chun tuilleadh eolais a fháil." -#: ../memline.c:1249 msgid "Recovery completed. You should check if everything is OK." msgstr "Athshlánaíodh. Ba chóir duit gach rud a sheiceáil uair amháin eile." -#: ../memline.c:1251 msgid "" "\n" "(You might want to write out this file under another name\n" @@ -3861,73 +3569,61 @@ msgstr "" "\n" "(B'fhéidir gur mian leat an comhad seo a shábháil de réir ainm eile\n" -#: ../memline.c:1252 -#, fuzzy msgid "and run diff with the original file to check for changes)" -msgstr "" -"agus déan comparáid leis an chomhad bhunúsach (m.sh. le `diff') chun " -"athruithe a scrúdú)\n" +msgstr "agus déan comparáid leis an mbunchomhad chun athruithe a lorg)" -#: ../memline.c:1254 msgid "Recovery completed. Buffer contents equals file contents." msgstr "" +"Athshlánú críochnaithe. Is ionann an t-ábhar sa mhaolán agus an t-ábhar sa " +"chomhad." -#: ../memline.c:1255 -#, fuzzy msgid "" "\n" "You may want to delete the .swp file now.\n" "\n" msgstr "" -"Scrios an comhad .swp tar éis sin.\n" "\n" +"B'fhéidir gur mhaith leat an comhad .swp a scriosadh anois.\n" +"\n" + +msgid "Using crypt key from swap file for the text file.\n" +msgstr "" +"Eochair chriptiúcháin ón gcomhad babhtála á húsáid ar an téacschomhad.\n" #. use msg() to start the scrolling properly -#: ../memline.c:1327 msgid "Swap files found:" msgstr "Comhaid bhabhtála aimsithe:" -#: ../memline.c:1446 msgid " In current directory:\n" msgstr " Sa chomhadlann reatha:\n" -#: ../memline.c:1448 msgid " Using specified name:\n" msgstr " Ag baint úsáid as ainm socraithe:\n" -#: ../memline.c:1450 msgid " In directory " msgstr " Sa chomhadlann " -#: ../memline.c:1465 msgid " -- none --\n" msgstr " -- neamhní --\n" -#: ../memline.c:1527 msgid " owned by: " msgstr " úinéir: " -#: ../memline.c:1529 msgid " dated: " msgstr " dátaithe: " -#: ../memline.c:1532 ../memline.c:3231 msgid " dated: " msgstr " dátaithe: " -#: ../memline.c:1548 msgid " [from Vim version 3.0]" msgstr " [ó leagan 3.0 Vim]" -#: ../memline.c:1550 msgid " [does not look like a Vim swap file]" msgstr " [ní cosúil le comhad babhtála Vim]" -#: ../memline.c:1552 msgid " file name: " msgstr " ainm comhaid: " -#: ../memline.c:1558 msgid "" "\n" " modified: " @@ -3935,15 +3631,12 @@ msgstr "" "\n" " mionathraithe: " -#: ../memline.c:1559 msgid "YES" msgstr "IS SEA" -#: ../memline.c:1559 msgid "no" msgstr "ní hea" -#: ../memline.c:1562 msgid "" "\n" " user name: " @@ -3951,11 +3644,9 @@ msgstr "" "\n" " úsáideoir: " -#: ../memline.c:1568 msgid " host name: " msgstr " ainm an óstríomhaire: " -#: ../memline.c:1570 msgid "" "\n" " host name: " @@ -3963,7 +3654,6 @@ msgstr "" "\n" " óstainm: " -#: ../memline.c:1575 msgid "" "\n" " process ID: " @@ -3971,11 +3661,16 @@ msgstr "" "\n" " PID: " -#: ../memline.c:1579 msgid " (still running)" msgstr " (ag rith fós)" -#: ../memline.c:1586 +msgid "" +"\n" +" [not usable with this version of Vim]" +msgstr "" +"\n" +" [ní inúsáidte leis an leagan seo Vim]" + msgid "" "\n" " [not usable on this computer]" @@ -3983,97 +3678,75 @@ msgstr "" "\n" " [ní inúsáidte ar an ríomhaire seo]" -#: ../memline.c:1590 msgid " [cannot be read]" msgstr " [ní féidir a léamh]" -#: ../memline.c:1593 msgid " [cannot be opened]" msgstr " [ní féidir oscailt]" -#: ../memline.c:1698 msgid "E313: Cannot preserve, there is no swap file" msgstr "E313: Ní féidir é a chaomhnú, níl aon chomhad babhtála ann" -#: ../memline.c:1747 msgid "File preserved" msgstr "Caomhnaíodh an comhad" -#: ../memline.c:1749 msgid "E314: Preserve failed" msgstr "E314: Theip ar chaomhnú" -#: ../memline.c:1819 #, c-format -msgid "E315: ml_get: invalid lnum: %<PRId64>" -msgstr "E315: ml_get: lnum neamhbhailí: %<PRId64>" +msgid "E315: ml_get: invalid lnum: %ld" +msgstr "E315: ml_get: lnum neamhbhailí: %ld" -#: ../memline.c:1851 #, c-format -msgid "E316: ml_get: cannot find line %<PRId64>" -msgstr "E316: ml_get: líne %<PRId64> gan aimsiú" +msgid "E316: ml_get: cannot find line %ld" +msgstr "E316: ml_get: líne %ld gan aimsiú" -#: ../memline.c:2236 msgid "E317: pointer block id wrong 3" msgstr "E317: aitheantas mícheart ar an mbloc pointeora 3" -#: ../memline.c:2311 msgid "stack_idx should be 0" msgstr "ba chóir do stack_idx a bheith 0" -#: ../memline.c:2369 msgid "E318: Updated too many blocks?" msgstr "E318: An iomarca bloic nuashonraithe?" -#: ../memline.c:2511 msgid "E317: pointer block id wrong 4" msgstr "E317: aitheantas mícheart ar an mbloc pointeora 4" -#: ../memline.c:2536 msgid "deleted block 1?" msgstr "bloc a haon scriosta?" -#: ../memline.c:2707 #, c-format -msgid "E320: Cannot find line %<PRId64>" -msgstr "E320: Líne %<PRId64> gan aimsiú" +msgid "E320: Cannot find line %ld" +msgstr "E320: Líne %ld gan aimsiú" -#: ../memline.c:2916 msgid "E317: pointer block id wrong" msgstr "E317: aitheantas mícheart ar an mbloc pointeora" -#: ../memline.c:2930 msgid "pe_line_count is zero" msgstr "is 0 pe_line_count\"" -#: ../memline.c:2955 #, c-format -msgid "E322: line number out of range: %<PRId64> past the end" -msgstr "E322: líne-uimhir as raon: %<PRId64> thar dheireadh" +msgid "E322: line number out of range: %ld past the end" +msgstr "E322: líne-uimhir as raon: %ld thar dheireadh" -#: ../memline.c:2959 #, c-format -msgid "E323: line count wrong in block %<PRId64>" -msgstr "E323: líon mícheart na línte i mbloc %<PRId64>" +msgid "E323: line count wrong in block %ld" +msgstr "E323: líon mícheart na línte i mbloc %ld" -#: ../memline.c:2999 msgid "Stack size increases" msgstr "Méadaíonn an chruach" -#: ../memline.c:3038 msgid "E317: pointer block id wrong 2" msgstr "E317: aitheantas mícheart ar an mbloc pointeora 2" -#: ../memline.c:3070 #, c-format msgid "E773: Symlink loop for \"%s\"" msgstr "E773: Ciogal i naisc shiombalacha le haghaidh \"%s\"" -#: ../memline.c:3221 msgid "E325: ATTENTION" msgstr "E325: AIRE" -#: ../memline.c:3222 msgid "" "\n" "Found a swap file by the name \"" @@ -4081,45 +3754,31 @@ msgstr "" "\n" "Fuarthas comhad babhtála darbh ainm \"" -#: ../memline.c:3226 msgid "While opening file \"" msgstr "Agus an comhad seo á oscailt: \"" -#: ../memline.c:3239 msgid " NEWER than swap file!\n" msgstr " NÍOS NUAÍ ná comhad babhtála!\n" -#: ../memline.c:3244 -#, fuzzy +#. Some of these messages are long to allow translation to +#. * other languages. msgid "" "\n" "(1) Another program may be editing the same file. If this is the case,\n" " be careful not to end up with two different instances of the same\n" -" file when making changes." +" file when making changes. Quit, or continue with caution.\n" msgstr "" "\n" -"(1) Is féidir go bhfuil clár eile ag rochtain an comhad seo.\n" -" Más ea, bí cúramach nach bhfuil dhá leagan den chomhad\n" -" céanna.\n" - -#: ../memline.c:3245 -#, fuzzy -msgid " Quit, or continue with caution.\n" -msgstr " Scoir, nó lean ar aghaidh go hairdeallach.\n" +"(1) Seans go bhfuil an comhad seo á chur in eagar ag clár eile. Má tá,\n" +" bí cúramach nach bhfuil dhá leagan den chomhad céanna agat nuair\n" +" a athraíonn tú é. Scoir anois, nó lean ort go faichilleach.\n" -#: ../memline.c:3246 -#, fuzzy msgid "(2) An edit session for this file crashed.\n" -msgstr "" -"\n" -"(2) Rinne Vim thobscor agus an comhad seo\n" -" idir lámha agat.\n" +msgstr "(2) Thuairteáil seisiún eagarthóireachta.\n" -#: ../memline.c:3247 msgid " If this is the case, use \":recover\" or \"vim -r " msgstr " Más amhlaidh, bain úsáid as \":recover\" nó \"vim -r " -#: ../memline.c:3249 msgid "" "\"\n" " to recover the changes (see \":help recovery\").\n" @@ -4127,11 +3786,9 @@ msgstr "" "\"\n" " chun na hathruithe a fháil ar ais (féach \":help recovery\").\n" -#: ../memline.c:3250 msgid " If you did this already, delete the swap file \"" msgstr " Má tá sé seo déanta cheana agat, scrios an comhad babhtála \"" -#: ../memline.c:3252 msgid "" "\"\n" " to avoid this message.\n" @@ -4139,23 +3796,18 @@ msgstr "" "\"\n" " chun an teachtaireacht seo a sheachaint.\n" -#: ../memline.c:3450 ../memline.c:3452 msgid "Swap file \"" msgstr "Comhad babhtála \"" -#: ../memline.c:3451 ../memline.c:3455 msgid "\" already exists!" msgstr "\" tá sé ann cheana!" -#: ../memline.c:3457 msgid "VIM - ATTENTION" msgstr "VIM - AIRE" -#: ../memline.c:3459 msgid "Swap file already exists!" msgstr "Tá comhad babhtála ann cheana!" -#: ../memline.c:3464 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4169,7 +3821,6 @@ msgstr "" "&Scoir\n" "&Tobscoir" -#: ../memline.c:3467 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4185,58 +3836,36 @@ msgstr "" "&Scoir\n" "&Tobscoir" -#. -#. * Change the ".swp" extension to find another file that can be used. -#. * First decrement the last char: ".swo", ".swn", etc. -#. * If that still isn't enough decrement the last but one char: ".svz" -#. * Can happen when editing many "No Name" buffers. -#. -#. ".s?a" -#. ".saa": tried enough, give up -#: ../memline.c:3528 msgid "E326: Too many swap files found" msgstr "E326: Aimsíodh an iomarca comhaid bhabhtála" -#: ../memory.c:227 -#, c-format -msgid "E342: Out of memory! (allocating %<PRIu64> bytes)" -msgstr "E342: Cuimhne ídithe! (%<PRIu64> beart á ndáileadh)" - -#: ../menu.c:62 msgid "E327: Part of menu-item path is not sub-menu" msgstr "E327: Ní fo-roghchlár í páirt de chonair roghchláir" -#: ../menu.c:63 msgid "E328: Menu only exists in another mode" msgstr "E328: Níl an roghchlár ar fáil sa mhód seo" -#: ../menu.c:64 #, c-format msgid "E329: No menu \"%s\"" msgstr "E329: Níl aon roghchlár darbh ainm \"%s\"" #. Only a mnemonic or accelerator is not valid. -#: ../menu.c:329 msgid "E792: Empty menu name" msgstr "E792: Ainm folamh ar an roghchlár" -#: ../menu.c:340 msgid "E330: Menu path must not lead to a sub-menu" msgstr "E330: Ní cheadaítear conair roghchláir a threoraíonn go fo-roghchlár" -#: ../menu.c:365 msgid "E331: Must not add menu items directly to menu bar" msgstr "" "E331: Ní cheadaítear míreanna roghchláir a chur le barra roghchláir go " "díreach" -#: ../menu.c:370 msgid "E332: Separator cannot be part of a menu path" msgstr "E332: Ní cheadaítear deighilteoir mar pháirt de chonair roghchláir" #. Now we have found the matching menu, and we list the mappings #. Highlight title -#: ../menu.c:762 msgid "" "\n" "--- Menus ---" @@ -4244,69 +3873,61 @@ msgstr "" "\n" "--- Roghchláir ---" -#: ../menu.c:1313 +msgid "Tear off this menu" +msgstr "Bain an roghchlár seo" + msgid "E333: Menu path must lead to a menu item" msgstr "E333: Ní mór conair roghchláir a threorú chun mír roghchláir" -#: ../menu.c:1330 #, c-format msgid "E334: Menu not found: %s" msgstr "E334: Roghchlár gan aimsiú: %s" -#: ../menu.c:1396 #, c-format msgid "E335: Menu not defined for %s mode" msgstr "E335: Níl an roghchlár ar fáil sa mhód %s" -#: ../menu.c:1426 msgid "E336: Menu path must lead to a sub-menu" msgstr "E336: Ní mór conair roghchláir a threorú chun fo-roghchlár" -#: ../menu.c:1447 msgid "E337: Menu not found - check menu names" msgstr "E337: Roghchlár gan aimsiú - deimhnigh ainmneacha na roghchlár" -#: ../message.c:423 #, c-format msgid "Error detected while processing %s:" msgstr "Earráid agus %s á phróiseáil:" -#: ../message.c:445 #, c-format msgid "line %4ld:" msgstr "líne %4ld:" -#: ../message.c:617 #, c-format msgid "E354: Invalid register name: '%s'" msgstr "E354: Ainm neamhbhailí tabhaill: '%s'" -#: ../message.c:986 +msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>" +msgstr "" +"Cothaitheoir na dteachtaireachtaí: Kevin P. Scannell <scannell@slu.edu>" + msgid "Interrupt: " msgstr "Idirbhriseadh: " -#: ../message.c:988 msgid "Press ENTER or type command to continue" msgstr "Brúigh ENTER nó iontráil ordú le leanúint" -#: ../message.c:1843 #, c-format -msgid "%s line %<PRId64>" -msgstr "%s líne %<PRId64>" +msgid "%s line %ld" +msgstr "%s líne %ld" -#: ../message.c:2392 msgid "-- More --" msgstr "-- Tuilleadh --" -#: ../message.c:2398 msgid " SPACE/d/j: screen/page/line down, b/u/k: up, q: quit " msgstr " SPÁS/d/j: scáileán/leathanach/líne síos, b/u/k: suas, q: scoir " -#: ../message.c:3021 ../message.c:3031 msgid "Question" msgstr "Ceist" -#: ../message.c:3023 msgid "" "&Yes\n" "&No" @@ -4314,17 +3935,6 @@ msgstr "" "&Tá\n" "&Níl" -#: ../message.c:3033 -msgid "" -"&Yes\n" -"&No\n" -"&Cancel" -msgstr "" -"&Tá\n" -"&Níl\n" -"&Cealaigh" - -#: ../message.c:3045 msgid "" "&Yes\n" "&No\n" @@ -4338,180 +3948,251 @@ msgstr "" "&Dealaigh Uile\n" "&Cealaigh" -#: ../message.c:3058 +msgid "Select Directory dialog" +msgstr "Dialóg `Roghnaigh Comhadlann'" + +msgid "Save File dialog" +msgstr "Dialóg `Sábháil Comhad'" + +msgid "Open File dialog" +msgstr "Dialóg `Oscail Comhad'" + +#. TODO: non-GUI file selector here +msgid "E338: Sorry, no file browser in console mode" +msgstr "E338: Níl brabhsálaí comhaid ar fáil sa mhód consóil" + msgid "E766: Insufficient arguments for printf()" msgstr "E766: Easpa argóintí d'fheidhm printf()" -#: ../message.c:3119 msgid "E807: Expected Float argument for printf()" msgstr "E807: Bhíothas ag súil le hargóint Snámhphointe d'fheidhm printf()" -#: ../message.c:3873 msgid "E767: Too many arguments to printf()" msgstr "E767: An iomarca argóintí d'fheidhm printf()" -#: ../misc1.c:2256 msgid "W10: Warning: Changing a readonly file" msgstr "W10: Rabhadh: Comhad inléite amháin á athrú" -#: ../misc1.c:2537 msgid "Type number and <Enter> or click with mouse (empty cancels): " msgstr "" "Clóscríobh uimhir agus <Enter> nó cliceáil leis an luch (fág folamh le " "cealú): " -#: ../misc1.c:2539 msgid "Type number and <Enter> (empty cancels): " msgstr "Clóscríobh uimhir agus <Enter> (fág folamh le cealú): " -#: ../misc1.c:2585 msgid "1 more line" msgstr "1 líne eile" -#: ../misc1.c:2588 msgid "1 line less" msgstr "1 líne níos lú" -#: ../misc1.c:2593 #, c-format -msgid "%<PRId64> more lines" -msgstr "%<PRId64> líne eile" +msgid "%ld more lines" +msgstr "%ld líne eile" -#: ../misc1.c:2596 #, c-format -msgid "%<PRId64> fewer lines" -msgstr "%<PRId64> líne níos lú" +msgid "%ld fewer lines" +msgstr "%ld líne níos lú" -#: ../misc1.c:2599 msgid " (Interrupted)" msgstr " (Idirbhriste)" -#: ../misc1.c:2635 msgid "Beep!" msgstr "Bíp!" -#: ../misc2.c:738 +msgid "ERROR: " +msgstr "EARRÁID: " + +#, c-format +msgid "" +"\n" +"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n" +msgstr "" +"\n" +"[beart] iomlán dáilte-saor %lu-%lu, in úsáid %lu, buaic %lu\n" + +#, c-format +msgid "" +"[calls] total re/malloc()'s %lu, total free()'s %lu\n" +"\n" +msgstr "" +"[glaonna] re/malloc(): %lu, free(): %lu\n" +"\n" + +msgid "E340: Line is becoming too long" +msgstr "E340: Tá an líne ag éirí rófhada" + +#, c-format +msgid "E341: Internal error: lalloc(%ld, )" +msgstr "E341: Earráid inmheánach: lalloc(%ld, )" + +#, c-format +msgid "E342: Out of memory! (allocating %lu bytes)" +msgstr "E342: Cuimhne ídithe! (%lu beart á ndáileadh)" + #, c-format msgid "Calling shell to execute: \"%s\"" msgstr "An t-ordú seo á rith leis an bhlaosc: \"%s\"" -#: ../normal.c:183 +msgid "E545: Missing colon" +msgstr "E545: Idirstad ar iarraidh" + +msgid "E546: Illegal mode" +msgstr "E546: Mód neamhcheadaithe" + +msgid "E547: Illegal mouseshape" +msgstr "E547: Cruth neamhcheadaithe luiche" + +msgid "E548: digit expected" +msgstr "E548: ag súil le digit" + +msgid "E549: Illegal percentage" +msgstr "E549: Céatadán neamhcheadaithe" + +msgid "E854: path too long for completion" +msgstr "E854: conair rófhada le comhlánú" + +#, c-format +msgid "" +"E343: Invalid path: '**[number]' must be at the end of the path or be " +"followed by '%s'." +msgstr "" +"E343: Conair neamhbhailí: ní mór '**[uimhir]' a bheith ag deireadh na " +"conaire, nó le '%s' ina dhiaidh." + +#, c-format +msgid "E344: Can't find directory \"%s\" in cdpath" +msgstr "E344: Ní féidir comhadlann \"%s\" a aimsiú sa cdpath" + +#, c-format +msgid "E345: Can't find file \"%s\" in path" +msgstr "E345: Ní féidir comhad \"%s\" a aimsiú sa chonair" + +#, c-format +msgid "E346: No more directory \"%s\" found in cdpath" +msgstr "E346: Níl comhadlann \"%s\" sa cdpath a thuilleadh" + +#, c-format +msgid "E347: No more file \"%s\" found in path" +msgstr "E347: Níl comhad \"%s\" sa chonair a thuilleadh" + +#, c-format +msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" +msgstr "E668: Mód mícheart rochtana ar an chomhad eolas naisc NetBeans: \"%s\"" + +#, c-format +msgid "E658: NetBeans connection lost for buffer %ld" +msgstr "E658: Cailleadh nasc NetBeans le haghaidh maoláin %ld" + +msgid "E838: netbeans is not supported with this GUI" +msgstr "E838: Ní thacaítear le netbeans sa GUI seo" + +msgid "E511: netbeans already connected" +msgstr "E511: Tá netbeans ceangailte cheana" + +#, c-format +msgid "E505: %s is read-only (add ! to override)" +msgstr "E505: Tá %s inléite amháin (cuir ! leis chun sárú)" + msgid "E349: No identifier under cursor" msgstr "E349: Níl aitheantóir faoin chúrsóir" -#: ../normal.c:1866 msgid "E774: 'operatorfunc' is empty" msgstr "E774: 'operatorfunc' folamh" -#: ../normal.c:2637 +msgid "E775: Eval feature not available" +msgstr "E775: Níl an ghné Eval le fáil" + msgid "Warning: terminal cannot highlight" msgstr "Rabhadh: ní féidir leis an teirminéal aibhsiú" -#: ../normal.c:2807 msgid "E348: No string under cursor" msgstr "E348: Níl teaghrán faoin chúrsóir" -#: ../normal.c:3937 msgid "E352: Cannot erase folds with current 'foldmethod'" msgstr "E352: Ní féidir fillteacha a léirscriosadh leis an 'foldmethod' reatha" -#: ../normal.c:5897 msgid "E664: changelist is empty" msgstr "E664: tá liosta na n-athruithe folamh" -#: ../normal.c:5899 msgid "E662: At start of changelist" msgstr "E662: Ag tosach liosta na n-athruithe" -#: ../normal.c:5901 msgid "E663: At end of changelist" msgstr "E663: Ag deireadh liosta na n-athruithe" -#: ../normal.c:7053 -msgid "Type :quit<Enter> to exit Nvim" +msgid "Type :quit<Enter> to exit Vim" msgstr "Clóscríobh :quit<Enter> chun Vim a scor" # ouch - English -ed ? -#: ../ops.c:248 #, c-format msgid "1 line %sed 1 time" msgstr "1 líne %s uair amháin" # ouch - English -ed ? -#: ../ops.c:250 #, c-format msgid "1 line %sed %d times" msgstr "1 líne %s %d uair" # ouch - English -ed ? -#: ../ops.c:253 #, c-format -msgid "%<PRId64> lines %sed 1 time" -msgstr "%<PRId64> líne %sed uair amháin" +msgid "%ld lines %sed 1 time" +msgstr "%ld líne %sed uair amháin" # ouch - English -ed ? -#: ../ops.c:256 #, c-format -msgid "%<PRId64> lines %sed %d times" -msgstr "%<PRId64> líne %sed %d uair" +msgid "%ld lines %sed %d times" +msgstr "%ld líne %sed %d uair" -#: ../ops.c:592 #, c-format -msgid "%<PRId64> lines to indent... " -msgstr "%<PRId64> líne le heangú... " +msgid "%ld lines to indent... " +msgstr "%ld líne le heangú... " -#: ../ops.c:634 msgid "1 line indented " msgstr "eangaíodh líne amháin " -#: ../ops.c:636 #, c-format -msgid "%<PRId64> lines indented " -msgstr "%<PRId64> líne eangaithe " +msgid "%ld lines indented " +msgstr "%ld líne eangaithe " -#: ../ops.c:938 msgid "E748: No previously used register" msgstr "E748: Níl aon tabhall úsáidte roimhe seo" #. must display the prompt -#: ../ops.c:1433 msgid "cannot yank; delete anyway" msgstr "ní féidir a sracadh; scrios mar sin féin" -#: ../ops.c:1929 msgid "1 line changed" msgstr "athraíodh líne amháin" -#: ../ops.c:1931 #, c-format -msgid "%<PRId64> lines changed" -msgstr "athraíodh %<PRId64> líne" +msgid "%ld lines changed" +msgstr "athraíodh %ld líne" + +#, c-format +msgid "freeing %ld lines" +msgstr "%ld líne á saoradh" -#: ../ops.c:2521 msgid "block of 1 line yanked" msgstr "sracadh bloc de líne amháin" -#: ../ops.c:2523 msgid "1 line yanked" msgstr "sracadh líne amháin" -#: ../ops.c:2525 #, c-format -msgid "block of %<PRId64> lines yanked" -msgstr "sracadh bloc de %<PRId64> líne" +msgid "block of %ld lines yanked" +msgstr "sracadh bloc de %ld líne" -#: ../ops.c:2528 #, c-format -msgid "%<PRId64> lines yanked" -msgstr "%<PRId64> líne sractha" +msgid "%ld lines yanked" +msgstr "%ld líne sractha" -#: ../ops.c:2710 #, c-format msgid "E353: Nothing in register %s" msgstr "E353: Tabhall folamh %s" #. Highlight title -#: ../ops.c:3185 msgid "" "\n" "--- Registers ---" @@ -4519,11 +4200,9 @@ msgstr "" "\n" "--- Tabhaill ---" -#: ../ops.c:4455 msgid "Illegal register name" msgstr "Ainm neamhcheadaithe tabhaill" -#: ../ops.c:4533 msgid "" "\n" "# Registers:\n" @@ -4531,185 +4210,175 @@ msgstr "" "\n" "# Tabhaill:\n" -#: ../ops.c:4575 #, c-format msgid "E574: Unknown register type %d" msgstr "E574: Cineál anaithnid tabhaill %d" -#: ../ops.c:5089 +msgid "" +"E883: search pattern and expression register may not contain two or more " +"lines" +msgstr "" +"E883: ní cheadaítear níos mó ná líne amháin i bpatrún cuardaigh ná sa " +"slonntabhall" + #, c-format -msgid "%<PRId64> Cols; " -msgstr "%<PRId64> Colún; " +msgid "%ld Cols; " +msgstr "%ld Colún; " -#: ../ops.c:5097 #, c-format -msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Bytes" -msgstr "" -"Roghnaíodh %s%<PRId64> as %<PRId64> Líne; %<PRId64> as %<PRId64> Focal; " -"%<PRId64> as %<PRId64> Beart" +msgid "Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Bytes" +msgstr "Roghnaíodh %s%ld as %ld Líne; %lld as %lld Focal; %lld as %lld Beart" -#: ../ops.c:5105 #, c-format msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Chars; %<PRId64> of %<PRId64> Bytes" +"Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Chars; %lld of " +"%lld Bytes" msgstr "" -"Roghnaíodh %s%<PRId64> as %<PRId64> Líne; %<PRId64> as %<PRId64> Focal; " -"%<PRId64> as %<PRId64> Carachtar; %<PRId64> as %<PRId64> Beart" +"Roghnaíodh %s%ld as %ld Líne; %lld as %lld Focal; %lld as %lld Carachtar; %lld as %lld Beart" -#: ../ops.c:5123 #, c-format -msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Byte " -"%<PRId64> of %<PRId64>" -msgstr "" -"Col %s as %s; Líne %<PRId64> as %<PRId64>; Focal %<PRId64> as %<PRId64>; " -"Beart %<PRId64> as %<PRId64>" +msgid "Col %s of %s; Line %ld of %ld; Word %lld of %lld; Byte %lld of %lld" +msgstr "Col %s as %s; Líne %ld as %ld; Focal %lld as %lld; Beart %lld as %lld" -#: ../ops.c:5133 #, c-format msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Char " -"%<PRId64> of %<PRId64>; Byte %<PRId64> of %<PRId64>" +"Col %s of %s; Line %ld of %ld; Word %lld of %lld; Char %lld of %lld; Byte " +"%lld of %lld" msgstr "" -"Col %s as %s; Líne %<PRId64> as %<PRId64>; Focal %<PRId64> as %<PRId64>; " -"Carachtar %<PRId64> as %<PRId64>; Beart %<PRId64> as %<PRId64>" +"Col %s as %s; Líne %ld as %ld; Focal %lld as %lld; Carachtar %lld as %lld; Beart %lld as %lld" -#: ../ops.c:5146 #, c-format -msgid "(+%<PRId64> for BOM)" -msgstr "(+%<PRId64> do BOM)" +msgid "(+%ld for BOM)" +msgstr "(+%ld do BOM)" -#: ../option.c:1238 msgid "%<%f%h%m%=Page %N" msgstr "%<%f%h%m%=Leathanach %N" -#: ../option.c:1574 msgid "Thanks for flying Vim" msgstr "Go raibh míle maith agat as Vim a úsáid" -#. found a mismatch: skip -#: ../option.c:2698 msgid "E518: Unknown option" msgstr "E518: Rogha anaithnid" -#: ../option.c:2709 msgid "E519: Option not supported" msgstr "E519: Níl an rogha seo ar fáil" -#: ../option.c:2740 msgid "E520: Not allowed in a modeline" msgstr "E520: Ní cheadaithe i módlíne" -#: ../option.c:2815 msgid "E846: Key code not set" -msgstr "" +msgstr "E846: Cód eochrach gan socrú" -#: ../option.c:2924 msgid "E521: Number required after =" msgstr "E521: Tá gá le huimhir i ndiaidh =" -#: ../option.c:3226 ../option.c:3864 msgid "E522: Not found in termcap" msgstr "E522: Gan aimsiú sa termcap" -#: ../option.c:3335 #, c-format msgid "E539: Illegal character <%s>" msgstr "E539: Carachtar neamhcheadaithe <%s>" -#: ../option.c:3862 +#, c-format +msgid "For option %s" +msgstr "Le haghaidh rogha %s" + msgid "E529: Cannot set 'term' to empty string" msgstr "E529: Ní féidir 'term' a shocrú mar theaghrán folamh" -#: ../option.c:3885 +msgid "E530: Cannot change term in GUI" +msgstr "E530: Ní féidir 'term' a athrú sa GUI" + +msgid "E531: Use \":gui\" to start the GUI" +msgstr "E531: Úsáid \":gui\" chun an GUI a chur ag obair" + msgid "E589: 'backupext' and 'patchmode' are equal" msgstr "E589: is ionann iad 'backupext' agus 'patchmode'" -#: ../option.c:3964 msgid "E834: Conflicts with value of 'listchars'" -msgstr "" +msgstr "E834: Tagann sé salach ar luach de 'listchars'" -#: ../option.c:3966 msgid "E835: Conflicts with value of 'fillchars'" -msgstr "" +msgstr "E835: Tagann sé salach ar luach de 'fillchars'" + +msgid "E617: Cannot be changed in the GTK+ 2 GUI" +msgstr "E617: Ní féidir é a athrú sa GUI GTK+ 2" -#: ../option.c:4163 msgid "E524: Missing colon" msgstr "E524: Idirstad ar iarraidh" -#: ../option.c:4165 msgid "E525: Zero length string" msgstr "E525: Teaghrán folamh" -#: ../option.c:4220 #, c-format msgid "E526: Missing number after <%s>" msgstr "E526: Uimhir ar iarraidh i ndiaidh <%s>" -#: ../option.c:4232 msgid "E527: Missing comma" msgstr "E527: Camóg ar iarraidh" -#: ../option.c:4239 msgid "E528: Must specify a ' value" msgstr "E528: Caithfidh luach ' a shonrú" -#: ../option.c:4271 msgid "E595: contains unprintable or wide character" msgstr "E595: tá carachtar neamhghrafach nó leathan ann" -#: ../option.c:4469 +msgid "E596: Invalid font(s)" +msgstr "E596: Cló(nna) neamhbhailí" + +msgid "E597: can't select fontset" +msgstr "E597: ní féidir tacar cló a roghnú" + +msgid "E598: Invalid fontset" +msgstr "E598: Tacar cló neamhbhailí" + +msgid "E533: can't select wide font" +msgstr "E533: ní féidir cló leathan a roghnú" + +msgid "E534: Invalid wide font" +msgstr "E534: Cló leathan neamhbhailí" + #, c-format msgid "E535: Illegal character after <%c>" msgstr "E535: Carachtar neamhbhailí i ndiaidh <%c>" -#: ../option.c:4534 msgid "E536: comma required" msgstr "E536: tá gá le camóg" -#: ../option.c:4543 #, c-format msgid "E537: 'commentstring' must be empty or contain %s" msgstr "" "E537: ní mór %s a bheith i 'commentstring', is é sin nó ní mór dó a bheith " "folamh" -#: ../option.c:4928 +msgid "E538: No mouse support" +msgstr "E538: Gan tacaíocht luiche" + msgid "E540: Unclosed expression sequence" msgstr "E540: Seicheamh gan dúnadh" -#: ../option.c:4932 msgid "E541: too many items" msgstr "E541: an iomarca míreanna" -#: ../option.c:4934 msgid "E542: unbalanced groups" msgstr "E542: grúpaí neamhchothromaithe" -#: ../option.c:5148 msgid "E590: A preview window already exists" msgstr "E590: Tá fuinneog réamhamhairc ann cheana" -#: ../option.c:5311 msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'" msgstr "" "W17: Tá UTF-8 ag teastáil le haghaidh Araibise, socraigh é le ':set " "encoding=utf-8'" -#: ../option.c:5623 #, c-format msgid "E593: Need at least %d lines" msgstr "E593: Tá gá le %d líne ar a laghad" -#: ../option.c:5631 #, c-format msgid "E594: Need at least %d columns" msgstr "E594: Tá gá le %d colún ar a laghad" -#: ../option.c:6011 #, c-format msgid "E355: Unknown option: %s" msgstr "E355: Rogha anaithnid: %s" @@ -4717,12 +4386,10 @@ msgstr "E355: Rogha anaithnid: %s" #. 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. -#: ../option.c:6037 #, c-format msgid "E521: Number required: &%s = '%s'" msgstr "E521: Uimhir de dhíth: &%s = '%s'" -#: ../option.c:6149 msgid "" "\n" "--- Terminal codes ---" @@ -4730,7 +4397,6 @@ msgstr "" "\n" "--- Cóid teirminéil ---" -#: ../option.c:6151 msgid "" "\n" "--- Global option values ---" @@ -4738,7 +4404,6 @@ msgstr "" "\n" "--- Luachanna na roghanna comhchoiteann ---" -#: ../option.c:6153 msgid "" "\n" "--- Local option values ---" @@ -4746,7 +4411,6 @@ msgstr "" "\n" "--- Luachanna na roghanna logánta ---" -#: ../option.c:6155 msgid "" "\n" "--- Options ---" @@ -4754,29 +4418,148 @@ msgstr "" "\n" "--- Roghanna ---" -#: ../option.c:6816 msgid "E356: get_varp ERROR" msgstr "E356: EARRÁID get_varp" -#: ../option.c:7696 #, c-format msgid "E357: 'langmap': Matching character missing for %s" msgstr "E357: 'langmap': Carachtar comhoiriúnach ar iarraidh le haghaidh %s" -#: ../option.c:7715 #, c-format msgid "E358: 'langmap': Extra characters after semicolon: %s" msgstr "E358: 'langmap': Carachtair breise i ndiaidh an idirstad: %s" -#: ../os/shell.c:194 +msgid "cannot open " +msgstr "ní féidir a oscailt: " + +msgid "VIM: Can't open window!\n" +msgstr "VIM: Ní féidir fuinneog a oscailt!\n" + +msgid "Need Amigados version 2.04 or later\n" +msgstr "Tá gá le Amigados leagan 2.04 nó níos déanaí\n" + +#, c-format +msgid "Need %s version %ld\n" +msgstr "Tá gá le %s, leagan %ld\n" + +msgid "Cannot open NIL:\n" +msgstr "Ní féidir NIL a oscailt:\n" + +msgid "Cannot create " +msgstr "Ní féidir a chruthú: " + +#, c-format +msgid "Vim exiting with %d\n" +msgstr "Vim á scor le stádas %d\n" + +msgid "cannot change console mode ?!\n" +msgstr "ní féidir mód consóil a athrú ?!\n" + +msgid "mch_get_shellsize: not a console??\n" +msgstr "mch_get_shellsize: ní consól é seo??\n" + +#. if Vim opened a window: Executing a shell may cause crashes +msgid "E360: Cannot execute shell with -f option" +msgstr "E360: Ní féidir blaosc a rith le rogha -f" + +msgid "Cannot execute " +msgstr "Ní féidir blaosc a rith: " + +msgid "shell " +msgstr "blaosc " + +msgid " returned\n" +msgstr " aisfhilleadh\n" + +msgid "ANCHOR_BUF_SIZE too small." +msgstr "ANCHOR_BUF_SIZE róbheag." + +msgid "I/O ERROR" +msgstr "EARRÁID I/A" + +msgid "Message" +msgstr "Teachtaireacht" + +msgid "E237: Printer selection failed" +msgstr "E237: Theip ar roghnú printéara" + +#, c-format +msgid "to %s on %s" +msgstr "go %s ar %s" + +#, c-format +msgid "E613: Unknown printer font: %s" +msgstr "E613: Clófhoireann anaithnid printéara: %s" + +#, c-format +msgid "E238: Print error: %s" +msgstr "E238: Earráid phriontála: %s" + +#, c-format +msgid "Printing '%s'" +msgstr "'%s' á phriontáil" + +#, c-format +msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" +msgstr "" +"E244: Ainm neamhcheadaithe ar thacar carachtar \"%s\" mar pháirt d'ainm cló " +"\"%s\"" + +#, c-format +msgid "E244: Illegal quality name \"%s\" in font name \"%s\"" +msgstr "" +"E244: Ainm neamhcheadaithe ar cháilíocht \"%s\" in ainm cló \"%s\"" + +#, c-format +msgid "E245: Illegal char '%c' in font name \"%s\"" +msgstr "E245: Carachtar neamhcheadaithe '%c' mar pháirt d'ainm cló \"%s\"" + +#, c-format +msgid "Opening the X display took %ld msec" +msgstr "Thóg %ld ms chun an scáileán X a oscailt" + msgid "" "\n" -"Cannot execute shell " +"Vim: Got X error\n" msgstr "" "\n" -"Ní féidir blaosc a rith " +"Vim: Fuarthas earráid ó X\n" + +msgid "Testing the X display failed" +msgstr "Theip ar thástáil an scáileáin X" + +msgid "Opening the X display timed out" +msgstr "Oscailt an scáileáin X thar am" + +msgid "" +"\n" +"Could not get security context for " +msgstr "" +"\n" +"Níorbh fhéidir comhthéacs slándála a fháil le haghaidh " + +msgid "" +"\n" +"Could not set security context for " +msgstr "" +"\n" +"Níorbh fhéidir comhthéacs slándála a shocrú le haghaidh " + +#, c-format +msgid "Could not set security context %s for %s" +msgstr "Níorbh fhéidir comhthéacs slándála %s a shocrú le haghaidh %s" + +#, c-format +msgid "Could not get security context %s for %s. Removing it!" +msgstr "Níorbh fhéidir comhthéacs slándála %s a fháil le haghaidh %s. Á bhaint!" + +msgid "" +"\n" +"Cannot execute shell sh\n" +msgstr "" +"\n" +"Ní féidir an bhlaosc sh a rith\n" -#: ../os/shell.c:439 msgid "" "\n" "shell returned " @@ -4784,472 +4567,476 @@ msgstr "" "\n" "d'aisfhill an bhlaosc " -#: ../os_unix.c:465 ../os_unix.c:471 msgid "" "\n" -"Could not get security context for " +"Cannot create pipes\n" msgstr "" "\n" -"Níorbh fhéidir comhthéacs slándála a fháil le haghaidh " +"Ní féidir píopaí a chruthú\n" -#: ../os_unix.c:479 +# "fork" not in standard refs/corpus. Maybe want a "gabhl*" word instead? -KPS msgid "" "\n" -"Could not set security context for " +"Cannot fork\n" msgstr "" "\n" -"Níorbh fhéidir comhthéacs slándála a shocrú le haghaidh " +"Ní féidir forc a dhéanamh\n" + +msgid "" +"\n" +"Cannot execute shell " +msgstr "" +"\n" +"Ní féidir blaosc a rith " + +msgid "" +"\n" +"Command terminated\n" +msgstr "" +"\n" +"Ordú críochnaithe\n" + +msgid "XSMP lost ICE connection" +msgstr "Chaill XSMP an nasc ICE" -#: ../os_unix.c:1558 ../os_unix.c:1647 #, c-format msgid "dlerror = \"%s\"" msgstr "dlerror = \"%s\"" -#: ../path.c:1449 +msgid "Opening the X display failed" +msgstr "Theip ar oscailt an scáileáin X" + +msgid "XSMP handling save-yourself request" +msgstr "Iarratas sábháil-do-féin á láimhseáil ag XSMP" + +msgid "XSMP opening connection" +msgstr "Nasc á oscailt ag XSMP" + +msgid "XSMP ICE connection watch failed" +msgstr "Theip ar fhaire nasc ICE XSMP" + #, c-format -msgid "E447: Can't find file \"%s\" in path" -msgstr "E447: Níl aon fháil ar chomhad \"%s\" sa chonair" +msgid "XSMP SmcOpenConnection failed: %s" +msgstr "Theip ar XSMP SmcOpenConnection: %s" + +msgid "At line" +msgstr "Ag líne" + +msgid "Could not load vim32.dll!" +msgstr "Níorbh fhéidir vim32.dll a luchtú!" + +msgid "VIM Error" +msgstr "Earráid VIM" + +msgid "Could not fix up function pointers to the DLL!" +msgstr "Níorbh fhéidir pointeoirí feidhme a chóiriú i gcomhair an DLL!" + +#, c-format +msgid "Vim: Caught %s event\n" +msgstr "Vim: Fuarthas teagmhas %s\n" + +msgid "close" +msgstr "dún" + +msgid "logoff" +msgstr "logáil amach" + +msgid "shutdown" +msgstr "múchadh" + +msgid "E371: Command not found" +msgstr "E371: Ní bhfuarthas an t-ordú" + +msgid "" +"VIMRUN.EXE not found in your $PATH.\n" +"External commands will not pause after completion.\n" +"See :help win32-vimrun for more information." +msgstr "" +"Níor aimsíodh VIMRUN.EXE i do $PATH.\n" +"Ní mhoilleoidh orduithe seachtracha agus iad curtha i gcrích.\n" +"Féach ar :help win32-vimrun chun níos mó eolas a fháil." + +msgid "Vim Warning" +msgstr "Rabhadh Vim" + +#, c-format +msgid "shell returned %d" +msgstr "d'aisfhill an bhlaosc %d" -#: ../quickfix.c:359 #, c-format msgid "E372: Too many %%%c in format string" msgstr "E372: An iomarca %%%c i dteaghrán formáide" -#: ../quickfix.c:371 #, c-format msgid "E373: Unexpected %%%c in format string" msgstr "E373: %%%c gan choinne i dteaghrán formáide" -#: ../quickfix.c:420 msgid "E374: Missing ] in format string" msgstr "E374: ] ar iarraidh i dteaghrán formáide" -#: ../quickfix.c:431 #, c-format msgid "E375: Unsupported %%%c in format string" msgstr "E375: %%%c gan tacaíocht i dteaghrán formáide" -#: ../quickfix.c:448 #, c-format msgid "E376: Invalid %%%c in format string prefix" msgstr "E376: %%%c neamhbhailí i réimír an teaghráin formáide" -#: ../quickfix.c:454 #, c-format msgid "E377: Invalid %%%c in format string" msgstr "E377: %%%c neamhbhailí i dteaghrán formáide" #. nothing found -#: ../quickfix.c:477 msgid "E378: 'errorformat' contains no pattern" msgstr "E378: Níl aon phatrún i 'errorformat'" -#: ../quickfix.c:695 msgid "E379: Missing or empty directory name" msgstr "E379: Ainm comhadlainne ar iarraidh, nó folamh" -#: ../quickfix.c:1305 msgid "E553: No more items" msgstr "E553: Níl aon mhír eile" -#: ../quickfix.c:1674 +msgid "E924: Current window was closed" +msgstr "E924: Dúnadh an fhuinneog reatha" + +msgid "E925: Current quickfix was changed" +msgstr "E925: Athraíodh an mearcheartúchán reatha" + +msgid "E926: Current location list was changed" +msgstr "E926: Athraíodh an liosta suíomh reatha" + #, c-format msgid "(%d of %d)%s%s: " msgstr "(%d as %d)%s%s: " -#: ../quickfix.c:1676 msgid " (line deleted)" msgstr " (líne scriosta)" -#: ../quickfix.c:1863 +#, c-format +msgid "%serror list %d of %d; %d errors " +msgstr "%sliosta earráidí %d as %d; %d earráid " + msgid "E380: At bottom of quickfix stack" -msgstr "E380: In íochtar na cruaiche quickfix" +msgstr "E380: In íochtar chruach na mearcheartúchán" -#: ../quickfix.c:1869 msgid "E381: At top of quickfix stack" -msgstr "E381: In uachtar na cruaiche quickfix" +msgstr "E381: In uachtar chruach na mearcheartúchán" -#: ../quickfix.c:1880 -#, c-format -msgid "error list %d of %d; %d errors" -msgstr "liosta earráidí %d as %d; %d earráid" +msgid "No entries" +msgstr "Gan iontráil" -#: ../quickfix.c:2427 msgid "E382: Cannot write, 'buftype' option is set" msgstr "E382: Ní féidir scríobh, rogha 'buftype' socraithe" -#: ../quickfix.c:2812 +msgid "Error file" +msgstr "Comhad earráide" + msgid "E683: File name missing or invalid pattern" msgstr "E683: Ainm comhaid ar iarraidh, nó patrún neamhbhailí" -#: ../quickfix.c:2911 #, c-format msgid "Cannot open file \"%s\"" msgstr "Ní féidir comhad \"%s\" a oscailt" -#: ../quickfix.c:3429 msgid "E681: Buffer is not loaded" msgstr "E681: Níl an maolán luchtaithe" -#: ../quickfix.c:3487 msgid "E777: String or List expected" msgstr "E777: Bhíothas ag súil le Teaghrán nó Liosta" -#: ../regexp.c:359 #, c-format msgid "E369: invalid item in %s%%[]" msgstr "E369: mír neamhbhailí i %s%%[]" -#: ../regexp.c:374 #, c-format msgid "E769: Missing ] after %s[" msgstr "E769: ] ar iarraidh i ndiaidh %s[" -#: ../regexp.c:375 #, c-format msgid "E53: Unmatched %s%%(" msgstr "E53: %s%%( corr" -#: ../regexp.c:376 #, c-format msgid "E54: Unmatched %s(" msgstr "E54: %s( corr" -#: ../regexp.c:377 #, c-format msgid "E55: Unmatched %s)" msgstr "E55: %s) corr" -#: ../regexp.c:378 msgid "E66: \\z( not allowed here" msgstr "E66: ní cheadaítear \\z( anseo" -#: ../regexp.c:379 msgid "E67: \\z1 et al. not allowed here" msgstr "E67: ní cheadaítear \\z1 et al. anseo" -#: ../regexp.c:380 #, c-format msgid "E69: Missing ] after %s%%[" msgstr "E69: ] ar iarraidh i ndiaidh %s%%[" -#: ../regexp.c:381 #, c-format msgid "E70: Empty %s%%[]" msgstr "E70: %s%%[] folamh" -#: ../regexp.c:1209 ../regexp.c:1224 msgid "E339: Pattern too long" msgstr "E339: Slonn rófhada" -#: ../regexp.c:1371 msgid "E50: Too many \\z(" msgstr "E50: an iomarca \\z(" -#: ../regexp.c:1378 #, c-format msgid "E51: Too many %s(" msgstr "E51: an iomarca %s(" -#: ../regexp.c:1427 msgid "E52: Unmatched \\z(" msgstr "E52: \\z( corr" -#: ../regexp.c:1637 #, c-format msgid "E59: invalid character after %s@" msgstr "E59: carachtar neamhbhailí i ndiaidh %s@" -#: ../regexp.c:1672 #, c-format msgid "E60: Too many complex %s{...}s" msgstr "E60: An iomarca %s{...} coimpléascach" -#: ../regexp.c:1687 #, c-format msgid "E61: Nested %s*" msgstr "E61: %s* neadaithe" -#: ../regexp.c:1690 #, c-format msgid "E62: Nested %s%c" msgstr "E62: %s%c neadaithe" -#: ../regexp.c:1800 msgid "E63: invalid use of \\_" msgstr "E63: úsáid neamhbhailí de \\_" -#: ../regexp.c:1850 #, c-format msgid "E64: %s%c follows nothing" msgstr "E64: níl aon rud roimh %s%c" -#: ../regexp.c:1902 msgid "E65: Illegal back reference" msgstr "E65: Cúltagairt neamhbhailí" -#: ../regexp.c:1943 msgid "E68: Invalid character after \\z" msgstr "E68: Carachtar neamhbhailí i ndiaidh \\z" -#: ../regexp.c:2049 ../regexp_nfa.c:1296 #, c-format msgid "E678: Invalid character after %s%%[dxouU]" msgstr "E678: Carachtar neamhbhailí i ndiaidh %s%%[dxouU]" -#: ../regexp.c:2107 #, c-format msgid "E71: Invalid character after %s%%" msgstr "E71: Carachtar neamhbhailí i ndiaidh %s%%" -#: ../regexp.c:3017 #, c-format msgid "E554: Syntax error in %s{...}" msgstr "E554: Earráid chomhréire i %s{...}" -#: ../regexp.c:3805 msgid "External submatches:\n" msgstr "Fo-mheaitseáil sheachtrach:\n" -#: ../regexp.c:7022 +#, c-format +msgid "E888: (NFA regexp) cannot repeat %s" +msgstr "E888: (slonn NFA) ní féidir %s a athdhéanamh" + msgid "" "E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be " "used " msgstr "" +"E864: Ní cheadaítear ach 0, 1, nó 2 tar éis \\%#=. Úsáidfear an t-inneall " +"uathoibríoch " -#: ../regexp_nfa.c:239 -msgid "E865: (NFA) Regexp end encountered prematurely" +msgid "Switching to backtracking RE engine for pattern: " msgstr "" +"Ag athrú go dtí an t-inneall rianaithe siar le haghaidh an phatrúin seo: " + +msgid "E865: (NFA) Regexp end encountered prematurely" +msgstr "E865: (NFA) Thángthas ar dheireadh an tsloinn gan súil leis" -#: ../regexp_nfa.c:240 #, c-format msgid "E866: (NFA regexp) Misplaced %c" -msgstr "" +msgstr "E866: (slonn NFA) %c as áit" -#: ../regexp_nfa.c:242 #, c-format -msgid "E877: (NFA regexp) Invalid character class: %<PRId64>" -msgstr "" +msgid "E877: (NFA regexp) Invalid character class: %ld" +msgstr "E877: (slonn NFA) Aicme carachtar neamhbhailí: %ld" -#: ../regexp_nfa.c:1261 #, c-format msgid "E867: (NFA) Unknown operator '\\z%c'" -msgstr "" +msgstr "E867: (NFA) Oibreoir anaithnid '\\z%c'" -#: ../regexp_nfa.c:1387 #, c-format msgid "E867: (NFA) Unknown operator '\\%%%c'" -msgstr "" +msgstr "E867: (NFA) Oibreoir anaithnid '\\%%%c'" + +#. should never happen +msgid "E868: Error building NFA with equivalence class!" +msgstr "E868: Earráid agus NFA á thógáil le haicme coibhéise!" -#: ../regexp_nfa.c:1802 #, c-format msgid "E869: (NFA) Unknown operator '\\@%c'" -msgstr "" +msgstr "E869: (NFA) Oibreoir anaithnid '\\@%c'" -#: ../regexp_nfa.c:1831 msgid "E870: (NFA regexp) Error reading repetition limits" -msgstr "" +msgstr "E870: (slonn NFA) Earráid agus teorainneacha athdhéanta á léamh" #. Can't have a multi follow a multi. -#: ../regexp_nfa.c:1895 msgid "E871: (NFA regexp) Can't have a multi follow a multi !" -msgstr "" +msgstr "E871: (slonn NFA) Ní cheadaítear ilchodach tar éis ilchodach!" #. Too many `(' -#: ../regexp_nfa.c:2037 msgid "E872: (NFA regexp) Too many '('" -msgstr "" +msgstr "E872: (slonn NFA) An iomarca '('" -#: ../regexp_nfa.c:2042 -#, fuzzy msgid "E879: (NFA regexp) Too many \\z(" -msgstr "E50: an iomarca \\z(" +msgstr "E879: (slonn NFA) An iomarca \\z(" -#: ../regexp_nfa.c:2066 msgid "E873: (NFA regexp) proper termination error" -msgstr "" +msgstr "E873: (slonn NFA) críochnú neamhoiriúnach" -#: ../regexp_nfa.c:2599 msgid "E874: (NFA) Could not pop the stack !" -msgstr "" +msgstr "E874: (NFA) Níorbh fhéidir an chruach a phlobadh!" -#: ../regexp_nfa.c:3298 msgid "" "E875: (NFA regexp) (While converting from postfix to NFA), too many states " "left on stack" msgstr "" +"E875: (slonn NFA) (Le linn tiontaithe ó postfix go NFA), an iomarca " +"staideanna fágtha ar an gcruach" -#: ../regexp_nfa.c:3302 msgid "E876: (NFA regexp) Not enough space to store the whole NFA " +msgstr "E876: (slonn NFA) Níl go leor spáis ann don NFA iomlán " + +msgid "E878: (NFA) Could not allocate memory for branch traversal!" msgstr "" +"E878: (NFA) Níorbh fhéidir cuimhne a leithdháileadh leis an gcraobh a " +"thrasnaíl!" -#: ../regexp_nfa.c:4571 ../regexp_nfa.c:4869 msgid "" "Could not open temporary log file for writing, displaying on stderr ... " msgstr "" +"Níorbh fhéidir logchomhad sealadach a oscailt le scríobh ann, á thaispeáint " +"ar stderr..." -#: ../regexp_nfa.c:4840 #, c-format msgid "(NFA) COULD NOT OPEN %s !" -msgstr "" +msgstr "(NFA) NÍORBH FHÉIDIR %s A OSCAILT!" -#: ../regexp_nfa.c:6049 -#, fuzzy msgid "Could not open temporary log file for writing " -msgstr "E214: Ní féidir comhad sealadach a aimsiú chun scríobh ann" +msgstr "Níorbh fhéidir logchomhad sealadach a oscailt le scríobh ann " -#: ../screen.c:7435 msgid " VREPLACE" msgstr " V-IONADAIGH" -#: ../screen.c:7437 msgid " REPLACE" msgstr " ATHCHUR" -#: ../screen.c:7440 msgid " REVERSE" msgstr " TIONTÚ" -#: ../screen.c:7441 msgid " INSERT" msgstr " IONSÁ" -#: ../screen.c:7443 msgid " (insert)" msgstr " (ionsáigh)" -#: ../screen.c:7445 msgid " (replace)" msgstr " (ionadaigh)" -#: ../screen.c:7447 msgid " (vreplace)" msgstr " (v-ionadaigh)" -#: ../screen.c:7449 msgid " Hebrew" msgstr " Eabhrais" -#: ../screen.c:7454 msgid " Arabic" msgstr " Araibis" -#: ../screen.c:7456 -msgid " (lang)" -msgstr " (teanga)" - -#: ../screen.c:7459 msgid " (paste)" msgstr " (greamaigh)" -#: ../screen.c:7469 msgid " VISUAL" msgstr " RADHARCACH" -#: ../screen.c:7470 msgid " VISUAL LINE" msgstr " LÍNE RADHARCACH" -#: ../screen.c:7471 msgid " VISUAL BLOCK" msgstr " BLOC RADHARCACH" -#: ../screen.c:7472 msgid " SELECT" msgstr " ROGHNÚ" -#: ../screen.c:7473 msgid " SELECT LINE" msgstr " SELECT LINE" -#: ../screen.c:7474 msgid " SELECT BLOCK" msgstr " SELECT BLOCK" -#: ../screen.c:7486 ../screen.c:7541 msgid "recording" msgstr "á thaifeadadh" -#: ../search.c:487 #, c-format msgid "E383: Invalid search string: %s" msgstr "E383: Teaghrán cuardaigh neamhbhailí: %s" -#: ../search.c:832 #, c-format msgid "E384: search hit TOP without match for: %s" msgstr "E384: bhuail an cuardach an BARR gan teaghrán comhoiriúnach le %s" -#: ../search.c:835 #, c-format msgid "E385: search hit BOTTOM without match for: %s" msgstr "E385: bhuail an cuardach an BUN gan teaghrán comhoiriúnach le %s" -#: ../search.c:1200 msgid "E386: Expected '?' or '/' after ';'" msgstr "E386: Ag súil le '?' nó '/' i ndiaidh ';'" -#: ../search.c:4085 msgid " (includes previously listed match)" msgstr " (tá an teaghrán comhoiriúnaithe roimhe seo san áireamh)" #. cursor at status line -#: ../search.c:4104 msgid "--- Included files " msgstr "--- Comhaid cheanntáisc " -#: ../search.c:4106 msgid "not found " msgstr "gan aimsiú" -#: ../search.c:4107 msgid "in path ---\n" msgstr "i gconair ---\n" -#: ../search.c:4168 msgid " (Already listed)" msgstr " (Liostaithe cheana féin)" -#: ../search.c:4170 msgid " NOT FOUND" msgstr " AR IARRAIDH" -#: ../search.c:4211 #, c-format msgid "Scanning included file: %s" msgstr "Comhad ceanntáisc á scanadh: %s" -#: ../search.c:4216 #, c-format msgid "Searching included file %s" msgstr "Comhad ceanntáisc %s á chuardach" -#: ../search.c:4405 msgid "E387: Match is on current line" msgstr "E387: Tá an teaghrán comhoiriúnaithe ar an líne reatha" -#: ../search.c:4517 msgid "All included files were found" msgstr "Aimsíodh gach comhad ceanntáisc" -#: ../search.c:4519 msgid "No included files" msgstr "Gan comhaid cheanntáisc" -#: ../search.c:4527 msgid "E388: Couldn't find definition" msgstr "E388: Sainmhíniú gan aimsiú" -#: ../search.c:4529 msgid "E389: Couldn't find pattern" msgstr "E389: Patrún gan aimsiú" -#: ../search.c:4668 msgid "Substitute " msgstr "Ionadú " # in .viminfo -#: ../search.c:4681 #, c-format msgid "" "\n" @@ -5260,98 +5047,130 @@ msgstr "" "# %sPatrún Cuardaigh Is Déanaí:\n" "~" -#: ../spell.c:951 -msgid "E759: Format error in spell file" -msgstr "E759: Earráid fhormáide i gcomhad litrithe" +msgid "E756: Spell checking is not enabled" +msgstr "E756: Níl seiceáil litrithe cumasaithe" + +#, c-format +msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" +msgstr "" +"Rabhadh: Ní féidir liosta focal \"%s_%s.spl\" nó \"%s_ascii.spl\" a aimsiú" + +#, c-format +msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" +msgstr "" +"Rabhadh: Ní féidir liosta focal \"%s.%s.spl\" nó \"%s.ascii.spl\" a aimsiú" + +msgid "E797: SpellFileMissing autocommand deleted buffer" +msgstr "E797: Scrios uathordú SpellFileMissing an maolán" + +#, c-format +msgid "Warning: region %s not supported" +msgstr "Rabhadh: réigiún %s gan tacaíocht" + +msgid "Sorry, no suggestions" +msgstr "Tá brón orm, níl aon mholadh ann" + +#, c-format +msgid "Sorry, only %ld suggestions" +msgstr "Tá brón orm, níl ach %ld moladh ann" + +#. for when 'cmdheight' > 1 +#. avoid more prompt +#, c-format +msgid "Change \"%.*s\" to:" +msgstr "Athraigh \"%.*s\" go:" + +#, c-format +msgid " < \"%.*s\"" +msgstr " < \"%.*s\"" + +msgid "E752: No previous spell replacement" +msgstr "E752: Níl aon ionadaí litrithe roimhe seo" + +#, c-format +msgid "E753: Not found: %s" +msgstr "E753: Gan aimsiú: %s" -#: ../spell.c:952 msgid "E758: Truncated spell file" msgstr "E758: Comhad teasctha litrithe" -#: ../spell.c:953 #, c-format msgid "Trailing text in %s line %d: %s" msgstr "Téacs chun deiridh i %s líne %d: %s" -#: ../spell.c:954 #, c-format msgid "Affix name too long in %s line %d: %s" msgstr "Ainm foircinn rófhada i %s líne %d: %s" -#: ../spell.c:955 msgid "E761: Format error in affix file FOL, LOW or UPP" msgstr "E761: Earráid fhormáide i gcomhad foircinn FOL, LOW, nó UPP" -#: ../spell.c:957 msgid "E762: Character in FOL, LOW or UPP is out of range" msgstr "E762: Carachtar i FOL, LOW nó UPP as raon" -#: ../spell.c:958 msgid "Compressing word tree..." msgstr "Crann focal á chomhbhrú..." -#: ../spell.c:1951 -msgid "E756: Spell checking is not enabled" -msgstr "E756: Níl seiceáil litrithe cumasaithe" - -#: ../spell.c:2249 -#, c-format -msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" -msgstr "" -"Rabhadh: Ní féidir liosta focal \"%s.%s.spl\" nó \"%s.ascii.spl\" a aimsiú" - -#: ../spell.c:2473 #, c-format msgid "Reading spell file \"%s\"" msgstr "Comhad litrithe \"%s\" á léamh" -#: ../spell.c:2496 msgid "E757: This does not look like a spell file" msgstr "E757: Níl sé cosúil le comhad litrithe" -#: ../spell.c:2501 msgid "E771: Old spell file, needs to be updated" msgstr "E771: Seanchomhad litrithe, tá gá lena nuashonrú" -#: ../spell.c:2504 msgid "E772: Spell file is for newer version of Vim" msgstr "E772: Oibríonn an comhad litrithe le leagan níos nuaí de Vim" -#: ../spell.c:2602 msgid "E770: Unsupported section in spell file" msgstr "E770: Rannán gan tacaíocht i gcomhad litrithe" -#: ../spell.c:3762 #, c-format -msgid "Warning: region %s not supported" -msgstr "Rabhadh: réigiún %s gan tacaíocht" +msgid "E778: This does not look like a .sug file: %s" +msgstr "E778: Níl sé cosúil le comhad .sug: %s" + +#, c-format +msgid "E779: Old .sug file, needs to be updated: %s" +msgstr "E779: Seanchomhad .sug, tá gá lena nuashonrú: %s" + +#, c-format +msgid "E780: .sug file is for newer version of Vim: %s" +msgstr "E780: Oibríonn an comhad .sug le leagan níos nuaí de Vim: %s" + +#, c-format +msgid "E781: .sug file doesn't match .spl file: %s" +msgstr "E781: Níl an comhad .sug comhoiriúnach leis an gcomhad .spl: %s" + +#, c-format +msgid "E782: error while reading .sug file: %s" +msgstr "E782: earráid agus comhad .sug á léamh: %s" -#: ../spell.c:4550 #, c-format msgid "Reading affix file %s ..." msgstr "Comhad foircinn %s á léamh..." -#: ../spell.c:4589 ../spell.c:5635 ../spell.c:6140 #, c-format msgid "Conversion failure for word in %s line %d: %s" msgstr "Theip ar thiontú focail i %s líne %d: %s" -#: ../spell.c:4630 ../spell.c:6170 #, c-format msgid "Conversion in %s not supported: from %s to %s" msgstr "Tiontú i %s gan tacaíocht: ó %s go %s" -#: ../spell.c:4642 +#, c-format +msgid "Conversion in %s not supported" +msgstr "Tiontú i %s gan tacaíocht" + #, c-format msgid "Invalid value for FLAG in %s line %d: %s" msgstr "Luach neamhbhailí ar FLAG i %s líne %d: %s" -#: ../spell.c:4655 #, c-format msgid "FLAG after using flags in %s line %d: %s" msgstr "FLAG i ndiaidh bratacha in úsáid i %s líne %d: %s" -#: ../spell.c:4723 #, c-format msgid "" "Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line " @@ -5360,7 +5179,6 @@ msgstr "" "Seans go bhfaighfidh tú torthaí míchearta má chuireann tú COMPOUNDFORBIDFLAG " "tar éis míre PFX i %s líne %d" -#: ../spell.c:4731 #, c-format msgid "" "Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line " @@ -5369,42 +5187,34 @@ msgstr "" "Seans go bhfaighfidh tú torthaí míchearta má chuireann tú COMPOUNDPERMITFLAG " "tar éis míre PFX i %s líne %d" -#: ../spell.c:4747 #, c-format msgid "Wrong COMPOUNDRULES value in %s line %d: %s" msgstr "Luach mícheart ar COMPOUNDRULES i %s líne %d: %s" -#: ../spell.c:4771 #, c-format msgid "Wrong COMPOUNDWORDMAX value in %s line %d: %s" msgstr "Luach mícheart ar COMPOUNDWORDMAX i %s líne %d: %s" -#: ../spell.c:4777 #, c-format msgid "Wrong COMPOUNDMIN value in %s line %d: %s" msgstr "Luach mícheart ar COMPOUNDMIN i %s líne %d: %s" -#: ../spell.c:4783 #, c-format msgid "Wrong COMPOUNDSYLMAX value in %s line %d: %s" msgstr "Luach mícheart ar COMPOUNDSYLMAX i %s líne %d: %s" -#: ../spell.c:4795 #, c-format msgid "Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s" msgstr "Luach mícheart ar CHECKCOMPOUNDPATTERN i %s líne %d: %s" -#: ../spell.c:4847 #, c-format msgid "Different combining flag in continued affix block in %s line %d: %s" msgstr "Bratach dhifriúil cheangail i mbloc leanta foircinn i %s líne %d: %s" -#: ../spell.c:4850 #, c-format msgid "Duplicate affix in %s line %d: %s" msgstr "Clib dhúblach i %s líne %d: %s" -#: ../spell.c:4871 #, c-format msgid "" "Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in %s " @@ -5413,335 +5223,230 @@ msgstr "" "Foirceann in úsáid le haghaidh BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/" "NOSUGGEST freisin i %s líne %d: %s" -#: ../spell.c:4893 #, c-format msgid "Expected Y or N in %s line %d: %s" msgstr "Bhíothas ag súil le `Y' nó `N' i %s líne %d: %s" -#: ../spell.c:4968 #, c-format msgid "Broken condition in %s line %d: %s" msgstr "Coinníoll briste i %s líne %d: %s" -#: ../spell.c:5091 #, c-format msgid "Expected REP(SAL) count in %s line %d" msgstr "Bhíothas ag súil le líon na REP(SAL) i %s líne %d" -#: ../spell.c:5120 #, c-format msgid "Expected MAP count in %s line %d" msgstr "Bhíothas ag súil le líon na MAP i %s líne %d" -#: ../spell.c:5132 #, c-format msgid "Duplicate character in MAP in %s line %d" msgstr "Carachtar dúblach i MAP i %s líne %d" -#: ../spell.c:5176 #, c-format msgid "Unrecognized or duplicate item in %s line %d: %s" msgstr "Mír anaithnid nó dhúblach i %s líne %d: %s" -#: ../spell.c:5197 #, c-format msgid "Missing FOL/LOW/UPP line in %s" msgstr "Líne FOL/LOW/UPP ar iarraidh i %s" -#: ../spell.c:5220 msgid "COMPOUNDSYLMAX used without SYLLABLE" msgstr "COMPOUNDSYLMAX in úsáid gan SYLLABLE" -#: ../spell.c:5236 msgid "Too many postponed prefixes" msgstr "An iomarca réimíreanna curtha siar" -#: ../spell.c:5238 msgid "Too many compound flags" msgstr "An iomarca bratach comhfhocail" -#: ../spell.c:5240 msgid "Too many postponed prefixes and/or compound flags" msgstr "An iomarca réimíreanna curtha siar agus/nó bratacha comhfhocal" -#: ../spell.c:5250 #, c-format msgid "Missing SOFO%s line in %s" msgstr "Líne SOFO%s ar iarraidh i %s" -#: ../spell.c:5253 #, c-format msgid "Both SAL and SOFO lines in %s" msgstr "Línte SAL agus SOFO araon i %s" -#: ../spell.c:5331 #, c-format msgid "Flag is not a number in %s line %d: %s" msgstr "Ní uimhir í an bhratach i %s líne %d: %s" -#: ../spell.c:5334 #, c-format msgid "Illegal flag in %s line %d: %s" msgstr "Bratach neamhcheadaithe i %s líne %d: %s" -#: ../spell.c:5493 ../spell.c:5501 #, c-format msgid "%s value differs from what is used in another .aff file" msgstr "Tá difear idir luach %s agus an luach i gcomhad .aff eile" -#: ../spell.c:5602 #, c-format msgid "Reading dictionary file %s ..." msgstr "Foclóir %s á léamh ..." -#: ../spell.c:5611 #, c-format msgid "E760: No word count in %s" msgstr "E760: Líon na bhfocal ar iarraidh i %s" -#: ../spell.c:5669 #, c-format msgid "line %6d, word %6d - %s" msgstr "líne %6d, focal %6d - %s" -#: ../spell.c:5691 #, c-format msgid "Duplicate word in %s line %d: %s" msgstr "Focal dúblach i %s líne %d: %s" -#: ../spell.c:5694 #, c-format msgid "First duplicate word in %s line %d: %s" msgstr "An chéad fhocal dúblach i %s líne %d: %s" -#: ../spell.c:5746 #, c-format msgid "%d duplicate word(s) in %s" msgstr "%d focal dúblach i %s" -#: ../spell.c:5748 #, c-format msgid "Ignored %d word(s) with non-ASCII characters in %s" msgstr "Rinneadh neamhshuim ar %d focal le carachtair neamh-ASCII i %s" -#: ../spell.c:6115 #, c-format msgid "Reading word file %s ..." msgstr "Comhad focail %s á léamh ..." -#: ../spell.c:6155 #, c-format msgid "Duplicate /encoding= line ignored in %s line %d: %s" msgstr "Rinneadh neamhshuim ar líne dhúblach `/encoding=' i %s líne %d: %s" -#: ../spell.c:6159 #, c-format msgid "/encoding= line after word ignored in %s line %d: %s" msgstr "" "Rinneadh neamhshuim ar líne `/encoding=' i ndiaidh focail i %s líne %d: %s" -#: ../spell.c:6180 #, c-format msgid "Duplicate /regions= line ignored in %s line %d: %s" msgstr "Rinneadh neamhshuim ar líne `/regions=' i %s líne %d: %s" -#: ../spell.c:6185 #, c-format msgid "Too many regions in %s line %d: %s" msgstr "An iomarca réigiún i %s líne %d: %s" -#: ../spell.c:6198 #, c-format msgid "/ line ignored in %s line %d: %s" msgstr "Rinneadh neamhshuim ar líne `/' i %s líne %d: %s" -#: ../spell.c:6224 #, c-format msgid "Invalid region nr in %s line %d: %s" msgstr "Uimhir neamhbhailí réigiúin i %s líne %d: %s" -#: ../spell.c:6230 #, c-format msgid "Unrecognized flags in %s line %d: %s" msgstr "Bratacha anaithnide i %s líne %d: %s" -#: ../spell.c:6257 #, c-format msgid "Ignored %d words with non-ASCII characters" msgstr "Rinneadh neamhshuim ar %d focal le carachtair neamh-ASCII" -#: ../spell.c:6656 +msgid "E845: Insufficient memory, word list will be incomplete" +msgstr "E845: Easpa cuimhne, beidh an liosta focal neamhiomlán" + #, c-format msgid "Compressed %d of %d nodes; %d (%d%%) remaining" msgstr "Comhbhrúdh %d as %d nód; %d (%d%%) fágtha" -#: ../spell.c:7340 msgid "Reading back spell file..." msgstr "Comhad litrithe á léamh arís..." -#. Go through the trie of good words, soundfold each word and add it to -#. the soundfold trie. -#: ../spell.c:7357 +#. +#. * Go through the trie of good words, soundfold each word and add it to +#. * the soundfold trie. +#. msgid "Performing soundfolding..." msgstr "Fuaimfhilleadh..." -#: ../spell.c:7368 #, c-format -msgid "Number of words after soundfolding: %<PRId64>" -msgstr "Líon na bhfocal tar éis fuaimfhillte: %<PRId64>" +msgid "Number of words after soundfolding: %ld" +msgstr "Líon na bhfocal tar éis fuaimfhillte: %ld" -#: ../spell.c:7476 #, c-format msgid "Total number of words: %d" msgstr "Líon iomlán na bhfocal: %d" -#: ../spell.c:7655 #, c-format msgid "Writing suggestion file %s ..." msgstr "Comhad moltaí %s á scríobh ..." -#: ../spell.c:7707 ../spell.c:7927 #, c-format msgid "Estimated runtime memory use: %d bytes" msgstr "Cuimhne measta a bheith in úsáid le linn rite: %d beart" -#: ../spell.c:7820 msgid "E751: Output file name must not have region name" msgstr "E751: Ní cheadaítear ainm réigiúin in ainm an aschomhaid" -#: ../spell.c:7822 msgid "E754: Only up to 8 regions supported" msgstr "E754: Ní thacaítear le níos mó ná 8 réigiún" -#: ../spell.c:7846 #, c-format msgid "E755: Invalid region in %s" msgstr "E755: Réigiún neamhbhailí i %s" -#: ../spell.c:7907 msgid "Warning: both compounding and NOBREAK specified" msgstr "Rabhadh: sonraíodh comhfhocail agus NOBREAK araon" -#: ../spell.c:7920 #, c-format msgid "Writing spell file %s ..." msgstr "Comhad litrithe %s á scríobh ..." -#: ../spell.c:7925 msgid "Done!" msgstr "Críochnaithe!" -#: ../spell.c:8034 #, c-format -msgid "E765: 'spellfile' does not have %<PRId64> entries" -msgstr "E765: níl %<PRId64> iontráil i 'spellfile'" +msgid "E765: 'spellfile' does not have %ld entries" +msgstr "E765: níl %ld iontráil i 'spellfile'" -#: ../spell.c:8074 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' removed from %s" -msgstr "Baineadh focal ó %s" +msgstr "Baineadh focal '%.*s' ó %s" -#: ../spell.c:8117 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' added to %s" -msgstr "Cuireadh focal le %s" +msgstr "Cuireadh focal '%.*s' le %s" -#: ../spell.c:8381 msgid "E763: Word characters differ between spell files" msgstr "E763: Tá carachtair dhifriúla fhocail sna comhaid litrithe" -#: ../spell.c:8684 -msgid "Sorry, no suggestions" -msgstr "Tá brón orm, níl aon mholadh ann" - -#: ../spell.c:8687 -#, c-format -msgid "Sorry, only %<PRId64> suggestions" -msgstr "Tá brón orm, níl ach %<PRId64> moladh ann" - -#. for when 'cmdheight' > 1 -#. avoid more prompt -#: ../spell.c:8704 -#, c-format -msgid "Change \"%.*s\" to:" -msgstr "Athraigh \"%.*s\" go:" - -#: ../spell.c:8737 -#, c-format -msgid " < \"%.*s\"" -msgstr " < \"%.*s\"" - -#: ../spell.c:8882 -msgid "E752: No previous spell replacement" -msgstr "E752: Níl aon ionadaí litrithe roimhe seo" - -#: ../spell.c:8925 -#, c-format -msgid "E753: Not found: %s" -msgstr "E753: Gan aimsiú: %s" - -#: ../spell.c:9276 -#, c-format -msgid "E778: This does not look like a .sug file: %s" -msgstr "E778: Níl sé cosúil le comhad .sug: %s" - -#: ../spell.c:9282 -#, c-format -msgid "E779: Old .sug file, needs to be updated: %s" -msgstr "E779: Seanchomhad .sug, tá gá lena nuashonrú: %s" - -#: ../spell.c:9286 -#, c-format -msgid "E780: .sug file is for newer version of Vim: %s" -msgstr "E780: Oibríonn an comhad .sug le leagan níos nuaí de Vim: %s" - -#: ../spell.c:9295 -#, c-format -msgid "E781: .sug file doesn't match .spl file: %s" -msgstr "E781: Níl an comhad .sug comhoiriúnach leis an gcomhad .spl: %s" - -#: ../spell.c:9305 -#, c-format -msgid "E782: error while reading .sug file: %s" -msgstr "E782: earráid agus comhad .sug á léamh: %s" - #. This should have been checked when generating the .spl -#. file. -#: ../spell.c:11575 +#. * file. msgid "E783: duplicate char in MAP entry" msgstr "E783: carachtar dúblach in iontráil MAP" -#: ../syntax.c:266 msgid "No Syntax items defined for this buffer" msgstr "Níl aon mhír chomhréire sainmhínithe le haghaidh an mhaoláin seo" -#: ../syntax.c:3083 ../syntax.c:3104 ../syntax.c:3127 #, c-format msgid "E390: Illegal argument: %s" msgstr "E390: Argóint neamhcheadaithe: %s" -#: ../syntax.c:3299 +msgid "syntax iskeyword " +msgstr "comhréir iskeyword " + #, c-format msgid "E391: No such syntax cluster: %s" msgstr "E391: Níl a leithéid de mhogall comhréire: %s" -#: ../syntax.c:3433 msgid "syncing on C-style comments" msgstr "ag sioncrónú ar nóta den nós C" -#: ../syntax.c:3439 msgid "no syncing" msgstr "gan sioncrónú" -#: ../syntax.c:3441 msgid "syncing starts " msgstr "tosaíonn an sioncrónú " -#: ../syntax.c:3443 ../syntax.c:3506 msgid " lines before top line" msgstr " línte roimh an bharr" -#: ../syntax.c:3448 msgid "" "\n" "--- Syntax sync items ---" @@ -5749,7 +5454,6 @@ msgstr "" "\n" "--- Míreanna Comhréire Sionc ---" -#: ../syntax.c:3452 msgid "" "\n" "syncing on items" @@ -5757,7 +5461,6 @@ msgstr "" "\n" "ag sioncrónú ar mhíreanna" -#: ../syntax.c:3457 msgid "" "\n" "--- Syntax items ---" @@ -5765,275 +5468,217 @@ msgstr "" "\n" "--- Míreanna comhréire ---" -#: ../syntax.c:3475 #, c-format msgid "E392: No such syntax cluster: %s" msgstr "E392: Níl a leithéid de mhogall comhréire: %s" -#: ../syntax.c:3497 msgid "minimal " msgstr "íosta " -#: ../syntax.c:3503 msgid "maximal " msgstr "uasta " -#: ../syntax.c:3513 msgid "; match " msgstr "; meaitseáil " -#: ../syntax.c:3515 msgid " line breaks" msgstr " bristeacha líne" -#: ../syntax.c:4076 msgid "E395: contains argument not accepted here" msgstr "E395: tá argóint ann nach nglactar leis anseo" -#: ../syntax.c:4096 -#, fuzzy msgid "E844: invalid cchar value" -msgstr "E474: Argóint neamhbhailí" +msgstr "E844: luach neamhbhailí cchar" -#: ../syntax.c:4107 msgid "E393: group[t]here not accepted here" msgstr "E393: ní ghlactar le group[t]here anseo" -#: ../syntax.c:4126 #, c-format msgid "E394: Didn't find region item for %s" msgstr "E394: Níor aimsíodh mír réigiúin le haghaidh %s" -#: ../syntax.c:4188 msgid "E397: Filename required" msgstr "E397: Tá gá le hainm comhaid" -#: ../syntax.c:4221 -#, fuzzy msgid "E847: Too many syntax includes" -msgstr "E77: An iomarca ainmneacha comhaid" +msgstr "E847: An iomarca comhad comhréire in úsáid" -#: ../syntax.c:4303 #, c-format msgid "E789: Missing ']': %s" msgstr "E789: ']' ar iarraidh: %s" -#: ../syntax.c:4531 +#, c-format +msgid "E890: trailing char after ']': %s]%s" +msgstr "E890: carachtar tar éis ']': %s]%s" + #, c-format msgid "E398: Missing '=': %s" msgstr "E398: '=' ar iarraidh: %s" -#: ../syntax.c:4666 #, c-format msgid "E399: Not enough arguments: syntax region %s" msgstr "E399: Níl go leor argóintí ann: réigiún comhréire %s" -#: ../syntax.c:4870 -#, fuzzy msgid "E848: Too many syntax clusters" -msgstr "E391: Níl a leithéid de mhogall comhréire: %s" +msgstr "E848: An iomarca mogall comhréire" -#: ../syntax.c:4954 msgid "E400: No cluster specified" msgstr "E400: Níor sonraíodh mogall" -#. end delimiter not found -#: ../syntax.c:4986 #, c-format msgid "E401: Pattern delimiter not found: %s" msgstr "E401: Teormharcóir patrúin gan aimsiú: %s" -#: ../syntax.c:5049 #, c-format msgid "E402: Garbage after pattern: %s" msgstr "E402: Dramhaíl i ndiaidh patrúin: %s" -#: ../syntax.c:5120 msgid "E403: syntax sync: line continuations pattern specified twice" msgstr "E403: comhréir sionc: tugadh patrún leanúint líne faoi dhó" -#: ../syntax.c:5169 #, c-format msgid "E404: Illegal arguments: %s" msgstr "E404: Argóintí neamhcheadaithe: %s" -#: ../syntax.c:5217 #, c-format msgid "E405: Missing equal sign: %s" msgstr "E405: Sín chothroime ar iarraidh: %s" -#: ../syntax.c:5222 #, c-format msgid "E406: Empty argument: %s" msgstr "E406: Argóint fholamh: %s" -#: ../syntax.c:5240 #, c-format msgid "E407: %s not allowed here" msgstr "E407: ní cheadaítear %s anseo" -#: ../syntax.c:5246 #, c-format msgid "E408: %s must be first in contains list" msgstr "E408: ní foláir %s a thabhairt ar dtús sa liosta `contains'" -#: ../syntax.c:5304 #, c-format msgid "E409: Unknown group name: %s" msgstr "E409: Ainm anaithnid grúpa: %s" -#: ../syntax.c:5512 #, c-format msgid "E410: Invalid :syntax subcommand: %s" msgstr "E410: Fo-ordú neamhbhailí :syntax: %s" -#: ../syntax.c:5854 msgid "" " TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN" msgstr "" +" IOMLÁN LÍON MEAITS IS MOILLE MEÁN AINM PATRÚN" -#: ../syntax.c:6146 msgid "E679: recursive loop loading syncolor.vim" msgstr "E679: lúb athchúrsach agus syncolor.vim á luchtú" -#: ../syntax.c:6256 #, c-format msgid "E411: highlight group not found: %s" msgstr "E411: Grúpa aibhsithe gan aimsiú: %s" -#: ../syntax.c:6278 #, c-format msgid "E412: Not enough arguments: \":highlight link %s\"" msgstr "E412: Easpa argóintí: \":highlight link %s\"" -#: ../syntax.c:6284 #, c-format msgid "E413: Too many arguments: \":highlight link %s\"" msgstr "E413: An iomarca argóintí: \":highlight link %s\"" -#: ../syntax.c:6302 msgid "E414: group has settings, highlight link ignored" msgstr "" "E414: tá socruithe ag an ghrúpa, ag déanamh neamhshuim ar nasc aibhsithe" -#: ../syntax.c:6367 #, c-format msgid "E415: unexpected equal sign: %s" msgstr "E415: sín chothroime gan choinne: %s" -#: ../syntax.c:6395 #, c-format msgid "E416: missing equal sign: %s" msgstr "E416: sín chothroime ar iarraidh: %s" -#: ../syntax.c:6418 #, c-format msgid "E417: missing argument: %s" msgstr "E417: argóint ar iarraidh: %s" -#: ../syntax.c:6446 #, c-format msgid "E418: Illegal value: %s" msgstr "E418: Luach neamhcheadaithe: %s" -#: ../syntax.c:6496 msgid "E419: FG color unknown" msgstr "E419: Dath anaithnid an chúlra" -#: ../syntax.c:6504 msgid "E420: BG color unknown" msgstr "E420: Dath anaithnid an tulra" -#: ../syntax.c:6564 #, c-format msgid "E421: Color name or number not recognized: %s" msgstr "E421: Níor aithníodh ainm/uimhir an datha: %s" -#: ../syntax.c:6714 #, c-format msgid "E422: terminal code too long: %s" msgstr "E422: cód teirminéil rófhada: %s" -#: ../syntax.c:6753 #, c-format msgid "E423: Illegal argument: %s" msgstr "E423: Argóint neamhcheadaithe: %s" -#: ../syntax.c:6925 msgid "E424: Too many different highlighting attributes in use" msgstr "E424: An iomarca tréithe aibhsithe in úsáid" -#: ../syntax.c:7427 msgid "E669: Unprintable character in group name" msgstr "E669: Carachtar neamhghrafach in ainm grúpa" -#: ../syntax.c:7434 msgid "W18: Invalid character in group name" msgstr "W18: Carachtar neamhbhailí in ainm grúpa" -#: ../syntax.c:7448 msgid "E849: Too many highlight and syntax groups" -msgstr "" +msgstr "E849: An iomarca grúpaí aibhsithe agus comhréire" -#: ../tag.c:104 msgid "E555: at bottom of tag stack" msgstr "E555: in íochtar na cruaiche clibeanna" -#: ../tag.c:105 msgid "E556: at top of tag stack" msgstr "E556: in uachtar na cruaiche clibeanna" -#: ../tag.c:380 msgid "E425: Cannot go before first matching tag" msgstr "E425: Ní féidir a dhul roimh an chéad chlib chomhoiriúnach" -#: ../tag.c:504 #, c-format msgid "E426: tag not found: %s" msgstr "E426: clib gan aimsiú: %s" -#: ../tag.c:528 msgid " # pri kind tag" msgstr " # tos cin clib" -#: ../tag.c:531 msgid "file\n" msgstr "comhad\n" -#: ../tag.c:829 msgid "E427: There is only one matching tag" msgstr "E427: Tá aon chlib chomhoiriúnach amháin" -#: ../tag.c:831 msgid "E428: Cannot go beyond last matching tag" msgstr "E428: Ní féidir a dhul thar an chlib chomhoiriúnach deireanach" -#: ../tag.c:850 #, c-format msgid "File \"%s\" does not exist" msgstr "Níl a leithéid de chomhad \"%s\" ann" #. Give an indication of the number of matching tags -#: ../tag.c:859 #, c-format msgid "tag %d of %d%s" msgstr "clib %d as %d%s" -#: ../tag.c:862 msgid " or more" msgstr " nó os a chionn" -#: ../tag.c:864 msgid " Using tag with different case!" msgstr " Ag úsáid clib le cás eile!" -#: ../tag.c:909 #, c-format msgid "E429: File \"%s\" does not exist" msgstr "E429: Níl a leithéid de chomhad \"%s\"" #. Highlight title -#: ../tag.c:960 msgid "" "\n" " # TO tag FROM line in file/text" @@ -6041,79 +5686,66 @@ msgstr "" "\n" " # Go clib Ó líne i gcomhad/téacs" -#: ../tag.c:1303 #, c-format msgid "Searching tags file %s" msgstr "Comhad clibeanna %s á chuardach" -#: ../tag.c:1545 +#, c-format +msgid "E430: Tag file path truncated for %s\n" +msgstr "E430: Teascadh conair an chomhaid clibeanna le haghaidh %s\n" + msgid "Ignoring long line in tags file" msgstr "Ag déanamh neamhaird de líne fhada sa chomhad clibeanna" -#: ../tag.c:1915 #, c-format msgid "E431: Format error in tags file \"%s\"" msgstr "E431: Earráid fhormáide i gcomhad clibeanna \"%s\"" -#: ../tag.c:1917 #, c-format -msgid "Before byte %<PRId64>" -msgstr "Roimh bheart %<PRId64>" +msgid "Before byte %ld" +msgstr "Roimh bheart %ld" -#: ../tag.c:1929 #, c-format msgid "E432: Tags file not sorted: %s" msgstr "E432: Comhad clibeanna gan sórtáil: %s" #. never opened any tags file -#: ../tag.c:1960 msgid "E433: No tags file" msgstr "E433: Níl aon chomhad clibeanna" -#: ../tag.c:2536 msgid "E434: Can't find tag pattern" msgstr "E434: Patrún clibe gan aimsiú" -#: ../tag.c:2544 msgid "E435: Couldn't find tag, just guessing!" msgstr "E435: Clib gan aimsiú, ag tabhairt buille faoi thuairim!" -#: ../tag.c:2797 -#, fuzzy, c-format +#, c-format msgid "Duplicate field name: %s" -msgstr "Clib dhúblach i %s líne %d: %s" +msgstr "Ainm réimse dúbailte: %s" -#: ../term.c:1442 msgid "' not known. Available builtin terminals are:" msgstr "' anaithnid. Is iad seo na teirminéil insuite:" -#: ../term.c:1463 msgid "defaulting to '" msgstr "réamhshocrú = '" -#: ../term.c:1731 msgid "E557: Cannot open termcap file" msgstr "E557: Ní féidir an comhad termcap a oscailt" -#: ../term.c:1735 msgid "E558: Terminal entry not found in terminfo" msgstr "E558: Iontráil teirminéil gan aimsiú sa terminfo" -#: ../term.c:1737 msgid "E559: Terminal entry not found in termcap" msgstr "E559: Iontráil teirminéil gan aimsiú sa termcap" -#: ../term.c:1878 #, c-format msgid "E436: No \"%s\" entry in termcap" msgstr "E436: Níl aon iontráil \"%s\" sa termcap" -#: ../term.c:2249 msgid "E437: terminal capability \"cm\" required" msgstr "E437: tá gá leis an chumas teirminéil \"cm\"" #. Highlight title -#: ../term.c:4376 msgid "" "\n" "--- Terminal keys ---" @@ -6121,169 +5753,342 @@ msgstr "" "\n" "--- Eochracha teirminéil ---" -#: ../ui.c:481 +msgid "Cannot open $VIMRUNTIME/rgb.txt" +msgstr "Ní féidir $VIMRUNTIME/rgb.txt a oscailt" + +msgid "new shell started\n" +msgstr "tosaíodh blaosc nua\n" + msgid "Vim: Error reading input, exiting...\n" msgstr "Vim: Earráid agus an t-inchomhad á léamh; ag scor...\n" +msgid "Used CUT_BUFFER0 instead of empty selection" +msgstr "Úsáideadh CUT_BUFFER0 in ionad roghnúcháin folaimh" + #. This happens when the FileChangedRO autocommand changes the #. * file in a way it becomes shorter. -#: ../undo.c:379 -#, fuzzy msgid "E881: Line count changed unexpectedly" -msgstr "E787: Athraíodh an maolán gan choinne" +msgstr "E881: Athraíodh líon na línte gan súil leis" + +#. must display the prompt +msgid "No undo possible; continue anyway" +msgstr "Ní féidir a chealú; lean ar aghaidh mar sin féin" -#: ../undo.c:627 -#, fuzzy, c-format +#, c-format msgid "E828: Cannot open undo file for writing: %s" -msgstr "E212: Ní féidir comhad a oscailt chun scríobh ann" +msgstr "E828: Ní féidir comhad staire a oscailt le scríobh ann: %s" -#: ../undo.c:717 #, c-format msgid "E825: Corrupted undo file (%s): %s" -msgstr "" +msgstr "E825: Comhad staire truaillithe (%s): %s" -#: ../undo.c:1039 msgid "Cannot write undo file in any directory in 'undodir'" -msgstr "" +msgstr "Ní féidir comhad staire a shábháil in aon chomhadlann in 'undodir'" -#: ../undo.c:1074 #, c-format msgid "Will not overwrite with undo file, cannot read: %s" -msgstr "" +msgstr "Ní forscríobhfar le comhad staire, ní féidir é a léamh: %s" -#: ../undo.c:1092 #, c-format msgid "Will not overwrite, this is not an undo file: %s" -msgstr "" +msgstr "Ní forscríobhfar é, ní comhad staire é seo: %s" -#: ../undo.c:1108 msgid "Skipping undo file write, nothing to undo" -msgstr "" +msgstr "Ní scríobhfar an comhad staire, níl aon stair ann" -#: ../undo.c:1121 -#, fuzzy, c-format +#, c-format msgid "Writing undo file: %s" -msgstr "Comhad viminfo \"%s\" á scríobh" +msgstr "Comhad staire á scríobh: %s" -#: ../undo.c:1213 -#, fuzzy, c-format +#, c-format msgid "E829: write error in undo file: %s" -msgstr "E297: Earráid sa scríobh i gcomhad babhtála" +msgstr "E829: earráid le linn scríofa i gcomhad staire: %s" -#: ../undo.c:1280 #, c-format msgid "Not reading undo file, owner differs: %s" -msgstr "" +msgstr "Níor léadh an comhad staire; úinéir difriúil: %s" -#: ../undo.c:1292 -#, fuzzy, c-format +#, c-format msgid "Reading undo file: %s" -msgstr "Comhad focail %s á léamh ..." +msgstr "Comhad staire á léamh: %s" -#: ../undo.c:1299 -#, fuzzy, c-format +#, c-format msgid "E822: Cannot open undo file for reading: %s" -msgstr "E195: Ní féidir an comhad viminfo a oscailt chun léamh" +msgstr "E822: Ní féidir an comhad staire a oscailt lena léamh: %s" -#: ../undo.c:1308 -#, fuzzy, c-format +#, c-format msgid "E823: Not an undo file: %s" -msgstr "E753: Gan aimsiú: %s" +msgstr "E823: Ní comhad staire é: %s" + +#, c-format +msgid "E832: Non-encrypted file has encrypted undo file: %s" +msgstr "E832: Comhad neamhchriptithe le comhad staire criptithe: %s" -#: ../undo.c:1313 -#, fuzzy, c-format +#, c-format +msgid "E826: Undo file decryption failed: %s" +msgstr "E826: Níorbh fhéidir an comhad staire a dhíchriptiú: %s" + +#, c-format +msgid "E827: Undo file is encrypted: %s" +msgstr "E827: Tá an comhad staire criptithe: %s" + +#, c-format msgid "E824: Incompatible undo file: %s" -msgstr "E484: Ní féidir comhad %s a oscailt" +msgstr "E824: Comhad staire neamh-chomhoiriúnach: %s" -#: ../undo.c:1328 msgid "File contents changed, cannot use undo info" -msgstr "" +msgstr "Athraíodh ábhar an chomhaid, ní féidir comhad staire a úsáid" -#: ../undo.c:1497 -#, fuzzy, c-format +#, c-format msgid "Finished reading undo file %s" -msgstr "deireadh ag foinsiú %s" +msgstr "Comhad staire %s léite" -#: ../undo.c:1586 ../undo.c:1812 msgid "Already at oldest change" msgstr "Ag an athrú is sine cheana" -#: ../undo.c:1597 ../undo.c:1814 msgid "Already at newest change" msgstr "Ag an athrú is nuaí cheana" -#: ../undo.c:1806 -#, fuzzy, c-format -msgid "E830: Undo number %<PRId64> not found" -msgstr "Níor aimsíodh cealú uimhir a %<PRId64>" +#, c-format +msgid "E830: Undo number %ld not found" +msgstr "E830: Mír staire %ld gan aimsiú" -#: ../undo.c:1979 msgid "E438: u_undo: line numbers wrong" msgstr "E438: u_undo: líne-uimhreacha míchearta" -#: ../undo.c:2183 msgid "more line" msgstr "líne eile" -#: ../undo.c:2185 msgid "more lines" msgstr "líne eile" -#: ../undo.c:2187 msgid "line less" msgstr "líne níos lú" -#: ../undo.c:2189 msgid "fewer lines" msgstr "líne níos lú" -#: ../undo.c:2193 msgid "change" msgstr "athrú" -#: ../undo.c:2195 msgid "changes" msgstr "athrú" -#: ../undo.c:2225 #, c-format -msgid "%<PRId64> %s; %s #%<PRId64> %s" -msgstr "%<PRId64> %s; %s #%<PRId64> %s" +msgid "%ld %s; %s #%ld %s" +msgstr "%ld %s; %s #%ld %s" -#: ../undo.c:2228 msgid "before" msgstr "roimh" -#: ../undo.c:2228 msgid "after" msgstr "tar éis" -#: ../undo.c:2325 msgid "Nothing to undo" msgstr "Níl faic le cealú" -#: ../undo.c:2330 msgid "number changes when saved" -msgstr "" +msgstr "athraíonn an uimhir ag am sábhála" -#: ../undo.c:2360 #, c-format -msgid "%<PRId64> seconds ago" -msgstr "%<PRId64> soicind ó shin" +msgid "%ld seconds ago" +msgstr "%ld soicind ó shin" -#: ../undo.c:2372 msgid "E790: undojoin is not allowed after undo" msgstr "E790: ní cheadaítear \"undojoin\" tar éis \"undo\"" -#: ../undo.c:2466 msgid "E439: undo list corrupt" msgstr "E439: tá an liosta cealaithe truaillithe" -#: ../undo.c:2495 msgid "E440: undo line missing" msgstr "E440: líne chealaithe ar iarraidh" -#: ../version.c:600 +#, c-format +msgid "E122: Function %s already exists, add ! to replace it" +msgstr "E122: Tá feidhm %s ann cheana, cuir ! leis an ordú chun é a asáitiú" + +msgid "E717: Dictionary entry already exists" +msgstr "E717: Tá an iontráil foclóra seo ann cheana" + +msgid "E718: Funcref required" +msgstr "E718: Tá gá le Funcref" + +#, c-format +msgid "E130: Unknown function: %s" +msgstr "E130: Feidhm anaithnid: %s" + +#, c-format +msgid "E125: Illegal argument: %s" +msgstr "E125: Argóint neamhcheadaithe: %s" + +#, c-format +msgid "E853: Duplicate argument name: %s" +msgstr "E853: Argóint dhúbailte: %s" + +#, c-format +msgid "E740: Too many arguments for function %s" +msgstr "E740: An iomarca argóintí d'fheidhm %s" + +#, c-format +msgid "E116: Invalid arguments for function %s" +msgstr "E116: Argóintí neamhbhailí d'fheidhm %s" + +msgid "E132: Function call depth is higher than 'maxfuncdepth'" +msgstr "E132: Doimhneacht na nglaonna níos mó ná 'maxfuncdepth'" + +#, c-format +msgid "calling %s" +msgstr "%s á glao" + +#, c-format +msgid "%s aborted" +msgstr "%s tobscortha" + +#, c-format +msgid "%s returning #%ld" +msgstr "%s ag aisfhilleadh #%ld" + +#, c-format +msgid "%s returning %s" +msgstr "%s ag aisfhilleadh %s" + +msgid "E699: Too many arguments" +msgstr "E699: An iomarca argóintí" + +#, c-format +msgid "E117: Unknown function: %s" +msgstr "E117: Feidhm anaithnid: %s" + +#, c-format +msgid "E933: Function was deleted: %s" +msgstr "E933: Scriosadh an fheidhm: %s" + +#, c-format +msgid "E119: Not enough arguments for function: %s" +msgstr "E119: Níl go leor feidhmeanna d'fheidhm: %s" + +#, c-format +msgid "E120: Using <SID> not in a script context: %s" +msgstr "E120: <SID> á úsáid ach gan a bheith i gcomhthéacs scripte: %s" + +#, c-format +msgid "E725: Calling dict function without Dictionary: %s" +msgstr "E725: Feidhm 'dict' á ghlao gan Foclóir: %s" + +msgid "E129: Function name required" +msgstr "E129: Tá gá le hainm feidhme" + +#, c-format +msgid "E128: Function name must start with a capital or \"s:\": %s" +msgstr "" +"E128: Caithfidh ceannlitir a bheith ar dtús ainm feidhme, nó \"s:\": %s" + +#, c-format +msgid "E884: Function name cannot contain a colon: %s" +msgstr "E884: Ní cheadaítear idirstad in ainm feidhme: %s" + +#, c-format +msgid "E123: Undefined function: %s" +msgstr "E123: Feidhm gan sainmhíniú: %s" + +#, c-format +msgid "E124: Missing '(': %s" +msgstr "E124: '(' ar iarraidh: %s" + +msgid "E862: Cannot use g: here" +msgstr "E862: Ní féidir g: a úsáid anseo" + +#, c-format +msgid "E932: Closure function should not be at top level: %s" +msgstr "E932: Ní mór don chlabhsúr a bheith ag an mbarrleibhéal: %s" + +msgid "E126: Missing :endfunction" +msgstr "E126: :endfunction ar iarraidh" + +#, c-format +msgid "E707: Function name conflicts with variable: %s" +msgstr "E707: Tagann ainm na feidhme salach ar athróg: %s" + +#, c-format +msgid "E127: Cannot redefine function %s: It is in use" +msgstr "" +"E127: Ní féidir sainmhíniú nua a dhéanamh ar fheidhm %s: In úsáid cheana" + +#, c-format +msgid "E746: Function name does not match script file name: %s" +msgstr "" +"E746: Níl ainm na feidhme comhoiriúnach le hainm comhaid na scripte: %s" + +#, c-format +msgid "E131: Cannot delete function %s: It is in use" +msgstr "E131: Ní féidir feidhm %s a scriosadh: Tá sé in úsáid faoi láthair" + +msgid "E133: :return not inside a function" +msgstr "E133: Caithfidh :return a bheith isteach i bhfeidhm" + +#, c-format +msgid "E107: Missing parentheses: %s" +msgstr "E107: Lúibíní ar iarraidh: %s" + +msgid "" +"\n" +"MS-Windows 64-bit GUI version" +msgstr "" +"\n" +"Leagan GUI 64 giotán MS-Windows" + +msgid "" +"\n" +"MS-Windows 32-bit GUI version" +msgstr "" +"\n" +"Leagan GUI 32 giotán MS-Windows" + +msgid " with OLE support" +msgstr " le tacaíocht OLE" + +msgid "" +"\n" +"MS-Windows 64-bit console version" +msgstr "" +"\n" +"Leagan consóil 64 giotán MS-Windows" + +msgid "" +"\n" +"MS-Windows 32-bit console version" +msgstr "" +"\n" +"Leagan consóil 32 giotán MS-Windows" + +msgid "" +"\n" +"MacOS X (unix) version" +msgstr "" +"\n" +"Leagan MacOS X (unix)" + +msgid "" +"\n" +"MacOS X version" +msgstr "" +"\n" +"Leagan MacOS X" + +msgid "" +"\n" +"MacOS version" +msgstr "" +"\n" +"Leagan MacOS" + +msgid "" +"\n" +"OpenVMS version" +msgstr "" +"\n" +"Leagan OpenVMS" + msgid "" "\n" "Included patches: " @@ -6291,7 +6096,6 @@ msgstr "" "\n" "Paistí san áireamh: " -#: ../version.c:627 msgid "" "\n" "Extra patches: " @@ -6299,11 +6103,9 @@ msgstr "" "\n" "Paistí sa bhreis: " -#: ../version.c:639 ../version.c:864 msgid "Modified by " msgstr "Mionathraithe ag " -#: ../version.c:646 msgid "" "\n" "Compiled " @@ -6312,11 +6114,9 @@ msgstr "" "Tiomsaithe " # with "Tiomsaithe" -#: ../version.c:649 msgid "by " msgstr "ag " -#: ../version.c:660 msgid "" "\n" "Huge version " @@ -6324,656 +6124,952 @@ msgstr "" "\n" "Leagan ollmhór " -#: ../version.c:661 +msgid "" +"\n" +"Big version " +msgstr "" +"\n" +"Leagan mór " + +msgid "" +"\n" +"Normal version " +msgstr "" +"\n" +"Leagan coitianta " + +msgid "" +"\n" +"Small version " +msgstr "" +"\n" +"Leagan beag " + +msgid "" +"\n" +"Tiny version " +msgstr "" +"\n" +"Leagan beag bídeach " + msgid "without GUI." msgstr "gan GUI." -#: ../version.c:662 +msgid "with GTK3 GUI." +msgstr "le GUI GTK3." + +msgid "with GTK2-GNOME GUI." +msgstr "le GUI GTK2-GNOME." + +msgid "with GTK2 GUI." +msgstr "le GUI GTK2." + +msgid "with X11-Motif GUI." +msgstr "le GUI X11-Motif." + +msgid "with X11-neXtaw GUI." +msgstr "le GUI X11-neXtaw." + +msgid "with X11-Athena GUI." +msgstr "le GUI X11-Athena." + +msgid "with Photon GUI." +msgstr "le GUI Photon." + +msgid "with GUI." +msgstr "le GUI." + +msgid "with Carbon GUI." +msgstr "le GUI Carbon." + +msgid "with Cocoa GUI." +msgstr "le GUI Cocoa." + +msgid "with (classic) GUI." +msgstr "le GUI (clasaiceach)." + msgid " Features included (+) or not (-):\n" msgstr " Gnéithe san áireamh (+) nó nach bhfuil (-):\n" -#: ../version.c:667 msgid " system vimrc file: \"" msgstr " comhad vimrc an chórais: \"" -#: ../version.c:672 msgid " user vimrc file: \"" msgstr " comhad vimrc úsáideora: \"" -#: ../version.c:677 msgid " 2nd user vimrc file: \"" msgstr " dara comhad vimrc úsáideora: \"" -#: ../version.c:682 msgid " 3rd user vimrc file: \"" msgstr " tríú comhad vimrc úsáideora: \"" -#: ../version.c:687 msgid " user exrc file: \"" msgstr " comhad exrc úsáideora: \"" -#: ../version.c:692 msgid " 2nd user exrc file: \"" msgstr " dara comhad úsáideora exrc: \"" -#: ../version.c:699 +msgid " system gvimrc file: \"" +msgstr " comhad gvimrc córais: \"" + +msgid " user gvimrc file: \"" +msgstr " comhad gvimrc úsáideora: \"" + +msgid "2nd user gvimrc file: \"" +msgstr "dara comhad gvimrc úsáideora: \"" + +msgid "3rd user gvimrc file: \"" +msgstr "tríú comhad gvimrc úsáideora: \"" + +msgid " defaults file: \"" +msgstr " comhad na réamhshocruithe: \"" + +msgid " system menu file: \"" +msgstr " comhad roghchláir an chórais: \"" + msgid " fall-back for $VIM: \"" msgstr " rogha thánaisteach do $VIM: \"" -#: ../version.c:705 msgid " f-b for $VIMRUNTIME: \"" msgstr " f-b do $VIMRUNTIME: \"" -#: ../version.c:709 msgid "Compilation: " msgstr "Tiomsú: " -#: ../version.c:712 +msgid "Compiler: " +msgstr "Tiomsaitheoir: " + msgid "Linking: " msgstr "Nascáil: " -#: ../version.c:717 msgid " DEBUG BUILD" msgstr " LEAGAN DÍFHABHTAITHE" -#: ../version.c:767 msgid "VIM - Vi IMproved" msgstr "VIM - Vi IMproved" -#: ../version.c:769 msgid "version " msgstr "leagan " -#: ../version.c:770 msgid "by Bram Moolenaar et al." msgstr "le Bram Moolenaar et al." -#: ../version.c:774 msgid "Vim is open source and freely distributable" msgstr "Is saorbhogearra é Vim" -#: ../version.c:776 msgid "Help poor children in Uganda!" msgstr "Tabhair cabhair do pháistí bochta in Uganda!" -#: ../version.c:777 msgid "type :help iccf<Enter> for information " msgstr "clóscríobh :help iccf<Enter> chun eolas a fháil " -#: ../version.c:779 msgid "type :q<Enter> to exit " msgstr "clóscríobh :q<Enter> chun scoir " -#: ../version.c:780 msgid "type :help<Enter> or <F1> for on-line help" msgstr "clóscríobh :help<Enter> nó <F1> le haghaidh cabhrach ar líne" -#: ../version.c:781 -msgid "type :help version7<Enter> for version info" -msgstr "clóscríobh :help version7<Enter> le haghaidh eolais faoin leagan" +msgid "type :help version8<Enter> for version info" +msgstr "clóscríobh :help version8<Enter> le haghaidh eolais faoin leagan" -#: ../version.c:784 msgid "Running in Vi compatible mode" msgstr "Sa mhód comhoiriúnachta Vi" -#: ../version.c:785 msgid "type :set nocp<Enter> for Vim defaults" msgstr "" "clóscríobh :set nocp<Enter> chun na réamhshocruithe Vim a thaispeáint" -#: ../version.c:786 msgid "type :help cp-default<Enter> for info on this" msgstr "" "clóscríobh :help cp-default<Enter> chun níos mó eolas faoi seo a fháil" -#: ../version.c:827 +# don't see where to localize "Help->Orphans"? --kps +msgid "menu Help->Orphans for information " +msgstr "roghchlár Help->Orphans chun eolas a fháil " + +msgid "Running modeless, typed text is inserted" +msgstr "Á rith gan mhóid, ag ionsá an téacs atá iontráilte" + +# same problem --kps +msgid "menu Edit->Global Settings->Toggle Insert Mode " +msgstr "roghchlár Edit->Global Settings->Toggle Insert Mode " + +msgid " for two modes " +msgstr " do dhá mhód " + +# same problem --kps +msgid "menu Edit->Global Settings->Toggle Vi Compatible" +msgstr "roghchlár Edit->Global Settings->Toggle Vi Compatible" + +msgid " for Vim defaults " +msgstr " le haghaidh réamhshocruithe Vim " + msgid "Sponsor Vim development!" msgstr "Bí i d'urraitheoir Vim!" -#: ../version.c:828 msgid "Become a registered Vim user!" msgstr "Bí i d'úsáideoir cláraithe Vim!" -#: ../version.c:831 msgid "type :help sponsor<Enter> for information " msgstr "clóscríobh :help sponsor<Enter> chun eolas a fháil " -#: ../version.c:832 msgid "type :help register<Enter> for information " msgstr "clóscríobh :help register<Enter> chun eolas a fháil " -#: ../version.c:834 msgid "menu Help->Sponsor/Register for information " msgstr "roghchlár Help->Sponsor/Register chun eolas a fháil " -#: ../window.c:119 msgid "Already only one window" msgstr "Níl ach aon fhuinneog amháin ann cheana" -#: ../window.c:224 msgid "E441: There is no preview window" msgstr "E441: Níl aon fhuinneog réamhamhairc ann" -#: ../window.c:559 msgid "E442: Can't split topleft and botright at the same time" msgstr "E442: Ní féidir a scoilteadh topleft agus botright san am céanna" -#: ../window.c:1228 msgid "E443: Cannot rotate when another window is split" msgstr "E443: Ní féidir rothlú nuair atá fuinneog eile scoilte" -#: ../window.c:1803 msgid "E444: Cannot close last window" msgstr "E444: Ní féidir an fhuinneog dheiridh a dhúnadh" -#: ../window.c:1810 msgid "E813: Cannot close autocmd window" msgstr "E813: Ní féidir fuinneog autocmd a dhúnadh" -#: ../window.c:1814 msgid "E814: Cannot close window, only autocmd window would remain" msgstr "" "E814: Ní féidir an fhuinneog a dhúnadh, ní bheadh ach fuinneog autocmd fágtha" -#: ../window.c:2717 msgid "E445: Other window contains changes" msgstr "E445: Tá athruithe ann san fhuinneog eile" -#: ../window.c:4805 msgid "E446: No file name under cursor" msgstr "E446: Níl ainm comhaid faoin chúrsóir" -#~ msgid "Patch file" -#~ msgstr "Comhad paiste" +#, c-format +msgid "E447: Can't find file \"%s\" in path" +msgstr "E447: Níl aon fháil ar chomhad \"%s\" sa chonair" -#~ msgid "" -#~ "&OK\n" -#~ "&Cancel" -#~ msgstr "" -#~ "&OK\n" -#~ "&Cealaigh" +#, c-format +msgid "E799: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E799: Aitheantas neamhbhailí: %ld (ní mór dó a bheith >= 1)" -#~ msgid "E240: No connection to Vim server" -#~ msgstr "E240: Níl aon nasc le freastalaí Vim" +#, c-format +msgid "E801: ID already taken: %ld" +msgstr "E801: Aitheantas in úsáid cheana: %ld" -#~ msgid "E241: Unable to send to %s" -#~ msgstr "E241: Ní féidir aon rud a sheoladh chuig %s" +msgid "List or number required" +msgstr "Tá gá le liosta nó uimhir" -#~ msgid "E277: Unable to read a server reply" -#~ msgstr "E277: Ní féidir freagra ón fhreastalaí a léamh" +#, c-format +msgid "E802: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E802: Aitheantas neamhbhailí: %ld (ní mór dó a bheith >= 1)" -#~ msgid "E258: Unable to send to client" -#~ msgstr "E258: Ní féidir aon rud a sheoladh chuig an chliant" +#, c-format +msgid "E803: ID not found: %ld" +msgstr "E803: Aitheantas gan aimsiú: %ld" -#~ msgid "Save As" -#~ msgstr "Sábháil Mar" +#, c-format +msgid "E370: Could not load library %s" +msgstr "E370: Níorbh fhéidir an leabharlann %s a oscailt" -#~ msgid "Edit File" -#~ msgstr "Cuir Comhad in Eagar" +msgid "Sorry, this command is disabled: the Perl library could not be loaded." +msgstr "" +"Tá brón orm, níl an t-ordú seo le fáil: níorbh fhéidir an leabharlann Perl a " +"luchtú." -#~ msgid " (NOT FOUND)" -#~ msgstr " (AR IARRAIDH)" +msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" +msgstr "E299: Ní cheadaítear luacháil Perl i mbosca gainimh gan an modúl Safe" -#~ msgid "Source Vim script" -#~ msgstr "Foinsigh script Vim" +msgid "Edit with &multiple Vims" +msgstr "Cuir in eagar le Vimeanna io&madúla" -#~ msgid "Edit File in new window" -#~ msgstr "Cuir comhad in eagar i bhfuinneog nua" +msgid "Edit with single &Vim" +msgstr "Cuir in eagar le &Vim aonair" -#~ msgid "Append File" -#~ msgstr "Cuir Comhad i nDeireadh" +msgid "Diff with Vim" +msgstr "Diff le Vim" -#~ msgid "Window position: X %d, Y %d" -#~ msgstr "Ionad na fuinneoige: X %d, Y %d" +msgid "Edit with &Vim" +msgstr "Cuir in Eagar le &Vim" -#~ msgid "Save Redirection" -#~ msgstr "Sábháil Atreorú" +#. Now concatenate +msgid "Edit with existing Vim - " +msgstr "Cuir in Eagar le Vim beo - " -#~ msgid "Save View" -#~ msgstr "Sábháil an tAmharc" +msgid "Edits the selected file(s) with Vim" +msgstr "Cuir an comhad roghnaithe in eagar le Vim" -#~ msgid "Save Session" -#~ msgstr "Sábháil an Seisiún" +msgid "Error creating process: Check if gvim is in your path!" +msgstr "" +"Earráid agus próiseas á chruthú: Deimhnigh go bhfuil gvim i do chonair!" -#~ msgid "Save Setup" -#~ msgstr "Sábháil an Socrú" +msgid "gvimext.dll error" +msgstr "earráid gvimext.dll" -#~ msgid "E809: #< is not available without the +eval feature" -#~ msgstr "E809: níl #< ar fáil gan ghné +eval" +msgid "Path length too long!" +msgstr "Conair rófhada!" -#~ msgid "E196: No digraphs in this version" -#~ msgstr "E196: Ní cheadaítear déghraif sa leagan seo" +msgid "--No lines in buffer--" +msgstr "--Tá an maolán folamh--" -#~ msgid "is a device (disabled with 'opendevice' option)" -#~ msgstr "is gléas é seo (díchumasaithe le rogha 'opendevice')" +#. +#. * The error messages that can be shared are included here. +#. * Excluded are errors that are only used once and debugging messages. +#. +msgid "E470: Command aborted" +msgstr "E470: Ordú tobscortha" -#~ msgid "Reading from stdin..." -#~ msgstr "Ag léamh ón ionchur caighdeánach..." +msgid "E471: Argument required" +msgstr "E471: Tá gá le hargóint" -#~ msgid "[crypted]" -#~ msgstr "[criptithe]" +msgid "E10: \\ should be followed by /, ? or &" +msgstr "E10: Ba chóir /, ? nó & a chur i ndiaidh \\" -#~ msgid "NetBeans disallows writes of unmodified buffers" -#~ msgstr "Ní cheadaíonn NetBeans maoláin gan athrú a bheith scríofa" +msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" +msgstr "" +"E11: Neamhbhailí i bhfuinneog líne na n-orduithe; <CR>=rith, CTRL-C=scoir" -#~ msgid "Partial writes disallowed for NetBeans buffers" -#~ msgstr "Ní cheadaítear maoláin NetBeans a bheith scríofa go neamhiomlán" +msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" +msgstr "" +"E12: Ní cheadaítear ordú ó exrc/vimrc sa chomhadlann reatha ná ó chuardach " +"clibe" -#~ msgid "writing to device disabled with 'opendevice' option" -#~ msgstr "díchumasaíodh scríobh chuig gléas le rogha 'opendevice'" +msgid "E171: Missing :endif" +msgstr "E171: :endif ar iarraidh" -#~ msgid "E460: The resource fork would be lost (add ! to override)" -#~ msgstr "E460: Chaillfí an forc acmhainne (cuir ! leis an ordú chun sárú)" +msgid "E600: Missing :endtry" +msgstr "E600: :endtry ar iarraidh" -#~ msgid "E229: Cannot start the GUI" -#~ msgstr "E229: Ní féidir an GUI a chur ag obair" +msgid "E170: Missing :endwhile" +msgstr "E170: :endwhile ar iarraidh" -#~ msgid "E230: Cannot read from \"%s\"" -#~ msgstr "E230: Ní féidir léamh ó \"%s\"" +msgid "E170: Missing :endfor" +msgstr "E170: :endfor ar iarraidh" -#~ msgid "E665: Cannot start GUI, no valid font found" -#~ msgstr "" -#~ "E665: Ní féidir an GUI a chur ag obair, níl aon chlófhoireann bhailí ann" +msgid "E588: :endwhile without :while" +msgstr "E588: :endwhile gan :while" -#~ msgid "E231: 'guifontwide' invalid" -#~ msgstr "E231: 'guifontwide' neamhbhailí" +msgid "E588: :endfor without :for" +msgstr "E588: :endfor gan :for" + +msgid "E13: File exists (add ! to override)" +msgstr "E13: Tá comhad ann cheana (cuir ! leis an ordú chun forscríobh)" + +msgid "E472: Command failed" +msgstr "E472: Theip ar ordú" -#~ msgid "E599: Value of 'imactivatekey' is invalid" -#~ msgstr "E599: Luach neamhbhailí ar 'imactivatekey'" +#, c-format +msgid "E234: Unknown fontset: %s" +msgstr "E234: Tacar cló anaithnid: %s" -#~ msgid "E254: Cannot allocate color %s" -#~ msgstr "E254: Ní féidir dath %s a dháileadh" +#, c-format +msgid "E235: Unknown font: %s" +msgstr "E235: Clófhoireann anaithnid: %s" -#~ msgid "No match at cursor, finding next" -#~ msgstr "Níl a leithéid ag an chúrsóir, ag cuardach ar an chéad cheann eile" +#, c-format +msgid "E236: Font \"%s\" is not fixed-width" +msgstr "E236: Ní cló aonleithid é \"%s\"" -#~ msgid "<cannot open> " -#~ msgstr "<ní féidir a oscailt> " +msgid "E473: Internal error" +msgstr "E473: Earráid inmheánach" -#~ msgid "E616: vim_SelFile: can't get font %s" -#~ msgstr "E616: vim_SelFile: níl aon fháil ar an chlófhoireann %s" +msgid "Interrupted" +msgstr "Idirbhriste" -#~ msgid "E614: vim_SelFile: can't return to current directory" -#~ msgstr "" -#~ "E614: vim_SelFile: ní féidir dul ar ais go dtí an chomhadlann reatha" +msgid "E14: Invalid address" +msgstr "E14: Drochsheoladh" -#~ msgid "Pathname:" -#~ msgstr "Conair:" +msgid "E474: Invalid argument" +msgstr "E474: Argóint neamhbhailí" -#~ msgid "E615: vim_SelFile: can't get current directory" -#~ msgstr "E615: vim_SelFile: níl an chomhadlann reatha ar fáil" +#, c-format +msgid "E475: Invalid argument: %s" +msgstr "E475: Argóint neamhbhailí: %s" -#~ msgid "OK" -#~ msgstr "OK" +#, c-format +msgid "E15: Invalid expression: %s" +msgstr "E15: Slonn neamhbhailí: %s" -#~ msgid "Cancel" -#~ msgstr "Cealaigh" +msgid "E16: Invalid range" +msgstr "E16: Raon neamhbhailí" -#~ msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." -#~ msgstr "" -#~ "Giuirléid Scrollbharra: Ní féidir céimseata an mhapa picteilíní a fháil." +msgid "E476: Invalid command" +msgstr "E476: Ordú neamhbhailí" -#~ msgid "Vim dialog" -#~ msgstr "Dialóg Vim" +#, c-format +msgid "E17: \"%s\" is a directory" +msgstr "E17: is comhadlann \"%s\"" -#~ msgid "E232: Cannot create BalloonEval with both message and callback" -#~ msgstr "" -#~ "E232: Ní féidir BalloonEval a chruthú le teachtaireacht agus aisghlaoch " -#~ "araon" +#, c-format +msgid "E364: Library call failed for \"%s()\"" +msgstr "E364: Theip ar ghlao leabharlainne \"%s()\"" -#~ msgid "Vim dialog..." -#~ msgstr "Dialóg Vim..." +#, c-format +msgid "E448: Could not load library function %s" +msgstr "E448: Ní féidir feidhm %s leabharlainne a luchtú" -#~ msgid "Input _Methods" -#~ msgstr "_Modhanna ionchuir" +msgid "E19: Mark has invalid line number" +msgstr "E19: Tá líne-uimhir neamhbhailí ag an mharc" -# in OLT --KPS -#~ msgid "VIM - Search and Replace..." -#~ msgstr "VIM - Cuardaigh agus Athchuir..." +msgid "E20: Mark not set" +msgstr "E20: Marc gan socrú" -#~ msgid "VIM - Search..." -#~ msgstr "VIM - Cuardaigh..." +msgid "E21: Cannot make changes, 'modifiable' is off" +msgstr "" +"E21: Ní féidir athruithe a chur i bhfeidhm, níl an bhratach 'modifiable' " +"socraithe" -#~ msgid "Find what:" -#~ msgstr "Aimsigh:" +msgid "E22: Scripts nested too deep" +msgstr "E22: scripteanna neadaithe ródhomhain" -#~ msgid "Replace with:" -#~ msgstr "Le cur in ionad:" +msgid "E23: No alternate file" +msgstr "E23: Níl aon chomhad malartach" -#~ msgid "Match whole word only" -#~ msgstr "Focal iomlán amháin" +msgid "E24: No such abbreviation" +msgstr "E24: Níl a leithéid de ghiorrúchán ann" -#~ msgid "Match case" -#~ msgstr "Meaitseáil an cás" +msgid "E477: No ! allowed" +msgstr "E477: Ní cheadaítear !" -#~ msgid "Direction" -#~ msgstr "Treo" +msgid "E25: GUI cannot be used: Not enabled at compile time" +msgstr "E25: Ní féidir an GUI a úsáid: Níor cumasaíodh é ag am tiomsaithe" -#~ msgid "Up" -#~ msgstr "Suas" +msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" +msgstr "" +"E26: Níl tacaíocht Eabhraise ar fáil: Níor cumasaíodh é ag am tiomsaithe\n" -#~ msgid "Down" -#~ msgstr "Síos" +msgid "E27: Farsi cannot be used: Not enabled at compile time\n" +msgstr "" +"E27: Níl tacaíocht Pheirsise ar fáil: Níor cumasaíodh é ag am tiomsaithe\n" -#~ msgid "Find Next" -#~ msgstr "An Chéad Cheann Eile" +msgid "E800: Arabic cannot be used: Not enabled at compile time\n" +msgstr "" +"E800: Níl tacaíocht Araibise ar fáil: Níor cumasaíodh é ag am tiomsaithe\n" -#~ msgid "Replace" -#~ msgstr "Ionadaigh" +#, c-format +msgid "E28: No such highlight group name: %s" +msgstr "E28: Níl a leithéid d'ainm grúpa aibhsithe: %s" -#~ msgid "Replace All" -#~ msgstr "Ionadaigh Uile" +msgid "E29: No inserted text yet" +msgstr "E29: Níl aon téacs ionsáite go dtí seo" -#~ msgid "Vim: Received \"die\" request from session manager\n" -#~ msgstr "Vim: Fuarthas iarratas \"die\" ó bhainisteoir an tseisiúin\n" +msgid "E30: No previous command line" +msgstr "E30: Níl aon líne na n-orduithe roimhe seo" -#~ msgid "Close" -#~ msgstr "Dún" +msgid "E31: No such mapping" +msgstr "E31: Níl a leithéid de mhapáil" -#~ msgid "New tab" -#~ msgstr "Cluaisín nua" +msgid "E479: No match" +msgstr "E479: Níl aon rud comhoiriúnach ann" -#~ msgid "Open Tab..." -#~ msgstr "Oscail Cluaisín..." +#, c-format +msgid "E480: No match: %s" +msgstr "E480: Níl aon rud comhoiriúnach ann: %s" -#~ msgid "Vim: Main window unexpectedly destroyed\n" -#~ msgstr "Vim: Milleadh an príomhfhuinneog gan choinne\n" +msgid "E32: No file name" +msgstr "E32: Níl aon ainm comhaid" -#~ msgid "Font Selection" -#~ msgstr "Roghnú Cló" +msgid "E33: No previous substitute regular expression" +msgstr "E33: Níl aon slonn ionadaíochta roimhe seo" -#~ msgid "&Filter" -#~ msgstr "&Scagaire" +msgid "E34: No previous command" +msgstr "E34: Níl aon ordú roimhe seo" -#~ msgid "&Cancel" -#~ msgstr "&Cealaigh" +msgid "E35: No previous regular expression" +msgstr "E35: Níl aon slonn ionadaíochta roimhe seo" -#~ msgid "Directories" -#~ msgstr "Comhadlanna" +msgid "E481: No range allowed" +msgstr "E481: Ní cheadaítear raon" -#~ msgid "Filter" -#~ msgstr "Scagaire" +msgid "E36: Not enough room" +msgstr "E36: Níl slí a dhóthain ann" -#~ msgid "&Help" -#~ msgstr "&Cabhair" +#, c-format +msgid "E247: no registered server named \"%s\"" +msgstr "E247: níl aon fhreastalaí cláraithe leis an ainm \"%s\"" -#~ msgid "Files" -#~ msgstr "Comhaid" +#, c-format +msgid "E482: Can't create file %s" +msgstr "E482: Ní féidir comhad %s a chruthú" -#~ msgid "&OK" -#~ msgstr "&OK" +msgid "E483: Can't get temp file name" +msgstr "E483: Níl aon fháil ar ainm comhaid sealadach" -#~ msgid "Selection" -#~ msgstr "Roghnú" +#, c-format +msgid "E484: Can't open file %s" +msgstr "E484: Ní féidir comhad %s a oscailt" -#~ msgid "Find &Next" -#~ msgstr "An Chéad Chea&nn Eile" +#, c-format +msgid "E485: Can't read file %s" +msgstr "E485: Ní féidir comhad %s a léamh" -#~ msgid "&Replace" -#~ msgstr "&Ionadaigh" +msgid "E37: No write since last change (add ! to override)" +msgstr "E37: Tá athruithe ann gan sábháil (cuir ! leis an ordú chun sárú)" -#~ msgid "Replace &All" -#~ msgstr "Ionadaigh &Uile" +msgid "E37: No write since last change" +msgstr "E37: Gan scríobh ón athrú is déanaí" -#~ msgid "&Undo" -#~ msgstr "&Cealaigh" +msgid "E38: Null argument" +msgstr "E38: Argóint nialasach" -#~ msgid "E671: Cannot find window title \"%s\"" -#~ msgstr "E671: Ní féidir teideal na fuinneoige \"%s\" a aimsiú" +msgid "E39: Number expected" +msgstr "E39: Ag súil le huimhir" -#~ msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." -#~ msgstr "E243: Argóint gan tacaíocht: \"-%s\"; Bain úsáid as an leagan OLE." +#, c-format +msgid "E40: Can't open errorfile %s" +msgstr "E40: Ní féidir an comhad earráide %s a oscailt" -#~ msgid "E672: Unable to open window inside MDI application" -#~ msgstr "E672: Ní féidir fuinneog a oscailt isteach i bhfeidhmchlár MDI" +msgid "E233: cannot open display" +msgstr "E233: ní féidir an scáileán a oscailt" -#~ msgid "Close tab" -#~ msgstr "Dún cluaisín" +msgid "E41: Out of memory!" +msgstr "E41: Cuimhne ídithe!" -#~ msgid "Open tab..." -#~ msgstr "Oscail cluaisín..." +msgid "Pattern not found" +msgstr "Patrún gan aimsiú" -#~ msgid "Find string (use '\\\\' to find a '\\')" -#~ msgstr "Aimsigh teaghrán (bain úsáid as '\\\\' chun '\\' a aimsiú)" +#, c-format +msgid "E486: Pattern not found: %s" +msgstr "E486: Patrún gan aimsiú: %s" -#~ msgid "Find & Replace (use '\\\\' to find a '\\')" -#~ msgstr "Aimsigh & Athchuir (úsáid '\\\\' chun '\\' a aimsiú)" +msgid "E487: Argument must be positive" +msgstr "E487: Ní foláir argóint dheimhneach" -#~ msgid "Not Used" -#~ msgstr "Gan Úsáid" +msgid "E459: Cannot go back to previous directory" +msgstr "E459: Ní féidir a fhilleadh ar an chomhadlann roimhe seo" -#~ msgid "Directory\t*.nothing\n" -#~ msgstr "Comhadlann\t*.neamhní\n" +msgid "E42: No Errors" +msgstr "E42: Níl Aon Earráid Ann" -#~ msgid "" -#~ "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" -#~ msgstr "" -#~ "Vim E458: Ní féidir iontráil dathmhapála a dháileadh, is féidir go mbeidh " -#~ "dathanna míchearta ann" +msgid "E776: No location list" +msgstr "E776: Gan liosta suíomh" -#~ msgid "E250: Fonts for the following charsets are missing in fontset %s:" -#~ msgstr "" -#~ "E250: Clónna ar iarraidh le haghaidh na dtacar carachtar i dtacar cló %s:" +msgid "E43: Damaged match string" +msgstr "E43: Teaghrán cuardaigh loite" + +msgid "E44: Corrupted regexp program" +msgstr "E44: Clár na sloinn ionadaíochta truaillithe" + +msgid "E45: 'readonly' option is set (add ! to override)" +msgstr "E45: tá an rogha 'readonly' socraithe (cuir ! leis an ordú chun sárú)" -#~ msgid "E252: Fontset name: %s" -#~ msgstr "E252: Ainm an tacar cló: %s" +#, c-format +msgid "E46: Cannot change read-only variable \"%s\"" +msgstr "E46: Ní féidir athróg inléite amháin \"%s\" a athrú" -#~ msgid "Font '%s' is not fixed-width" -#~ msgstr "Ní cló aonleithid é '%s'" +#, c-format +msgid "E794: Cannot set variable in the sandbox: \"%s\"" +msgstr "E794: Ní féidir athróg a shocrú sa bhosca gainimh: \"%s\"" + +msgid "E713: Cannot use empty key for Dictionary" +msgstr "E713: Ní féidir eochair fholamh a úsáid le Foclóir" -#~ msgid "E253: Fontset name: %s\n" -#~ msgstr "E253: Ainm an tacar cló: %s\n" +msgid "E715: Dictionary required" +msgstr "E715: Tá gá le foclóir" -#~ msgid "Font0: %s\n" -#~ msgstr "Cló0: %s\n" +#, c-format +msgid "E684: list index out of range: %ld" +msgstr "E684: innéacs liosta as raon: %ld" -#~ msgid "Font1: %s\n" -#~ msgstr "Cló1: %s\n" +#, c-format +msgid "E118: Too many arguments for function: %s" +msgstr "E118: An iomarca argóintí d'fheidhm: %s" -#~ msgid "Font%<PRId64> width is not twice that of font0\n" -#~ msgstr "Níl Cló%<PRId64> níos leithne faoi dhó ná cló0\n" +#, c-format +msgid "E716: Key not present in Dictionary: %s" +msgstr "E716: Níl an eochair seo san Fhoclóir: %s" -#~ msgid "Font0 width: %<PRId64>\n" -#~ msgstr "Leithead Cló0: %<PRId64>\n" +msgid "E714: List required" +msgstr "E714: Tá gá le liosta" -#~ msgid "" -#~ "Font1 width: %<PRId64>\n" -#~ "\n" -#~ msgstr "" -#~ "Leithead Cló1: %<PRId64>\n" -#~ "\n" +#, c-format +msgid "E712: Argument of %s must be a List or Dictionary" +msgstr "E712: Caithfidh argóint de %s a bheith ina Liosta nó Foclóir" -#~ msgid "Invalid font specification" -#~ msgstr "Sonrú neamhbhailí cló" +msgid "E47: Error while reading errorfile" +msgstr "E47: Earráid agus comhad earráide á léamh" -#~ msgid "&Dismiss" -#~ msgstr "&Ruaig" +msgid "E48: Not allowed in sandbox" +msgstr "E48: Ní cheadaítear é seo i mbosca gainimh" -#~ msgid "no specific match" -#~ msgstr "níl a leithéid ann" +msgid "E523: Not allowed here" +msgstr "E523: Ní cheadaítear é anseo" -#~ msgid "Vim - Font Selector" -#~ msgstr "Vim - Roghnú Cló" +msgid "E359: Screen mode setting not supported" +msgstr "E359: Ní féidir an mód scáileáin a shocrú" -#~ msgid "Name:" -#~ msgstr "Ainm:" +msgid "E49: Invalid scroll size" +msgstr "E49: Méid neamhbhailí scrollaithe" -#~ msgid "Show size in Points" -#~ msgstr "Taispeáin méid (Pointí)" +msgid "E91: 'shell' option is empty" +msgstr "E91: rogha 'shell' folamh" -#~ msgid "Encoding:" -#~ msgstr "Ionchódú:" +msgid "E255: Couldn't read in sign data!" +msgstr "E255: Níorbh fhéidir na sonraí comhartha a léamh!" -#~ msgid "Font:" -#~ msgstr "Cló:" +msgid "E72: Close error on swap file" +msgstr "E72: Earráid agus comhad babhtála á dhúnadh" -#~ msgid "Style:" -#~ msgstr "Stíl:" +msgid "E73: tag stack empty" +msgstr "E73: tá cruach na gclibeanna folamh" -#~ msgid "Size:" -#~ msgstr "Méid:" +msgid "E74: Command too complex" +msgstr "E74: Ordú róchasta" -#~ msgid "E256: Hangul automata ERROR" -#~ msgstr "E256: EARRÁID leis na huathoibreáin Hangul" +msgid "E75: Name too long" +msgstr "E75: Ainm rófhada" -#~ msgid "E563: stat error" -#~ msgstr "E563: earráid stat" +msgid "E76: Too many [" +msgstr "E76: an iomarca [" + +msgid "E77: Too many file names" +msgstr "E77: An iomarca ainmneacha comhaid" -#~ msgid "E625: cannot open cscope database: %s" -#~ msgstr "E625: ní féidir bunachar sonraí cscope a oscailt: %s" +msgid "E488: Trailing characters" +msgstr "E488: Carachtair chun deiridh" -#~ msgid "E626: cannot get cscope database information" -#~ msgstr "E626: ní féidir eolas a fháil faoin bhunachar sonraí cscope" +msgid "E78: Unknown mark" +msgstr "E78: Marc anaithnid" -#~ msgid "" -#~ "E815: Sorry, this command is disabled, the MzScheme libraries could not " -#~ "be loaded." -#~ msgstr "" -#~ "E815: Tá brón orm, bhí an t-ordú seo díchumasaithe, níorbh fhéidir " -#~ "leabharlanna MzScheme a luchtú." +msgid "E79: Cannot expand wildcards" +msgstr "E79: Ní féidir saoróga a leathnú" -#~ msgid "invalid expression" -#~ msgstr "slonn neamhbhailí" +msgid "E591: 'winheight' cannot be smaller than 'winminheight'" +msgstr "E591: ní cheadaítear 'winheight' a bheith níos lú ná 'winminheight'" -#~ msgid "expressions disabled at compile time" -#~ msgstr "díchumasaíodh sloinn ag am an tiomsaithe" +msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" +msgstr "E592: ní cheadaítear 'winwidth' a bheith níos lú ná 'winminwidth'" -#~ msgid "hidden option" -#~ msgstr "rogha fholaithe" +msgid "E80: Error while writing" +msgstr "E80: Earráid agus á scríobh" -#~ msgid "unknown option" -#~ msgstr "rogha anaithnid" +msgid "Zero count" +msgstr "Nialas" -#~ msgid "window index is out of range" -#~ msgstr "innéacs fuinneoige as raon" +msgid "E81: Using <SID> not in a script context" +msgstr "E81: <SID> á úsáid nach i gcomhthéacs scripte" -#~ msgid "couldn't open buffer" -#~ msgstr "ní féidir maolán a oscailt" +msgid "E449: Invalid expression received" +msgstr "E449: Fuarthas slonn neamhbhailí" -#~ msgid "cannot save undo information" -#~ msgstr "ní féidir eolas cealaithe a shábháil" +msgid "E463: Region is guarded, cannot modify" +msgstr "E463: Réigiún cosanta, ní féidir é a athrú" -#~ msgid "cannot delete line" -#~ msgstr "ní féidir an líne a scriosadh" +msgid "E744: NetBeans does not allow changes in read-only files" +msgstr "E744: Ní cheadaíonn NetBeans aon athrú i gcomhaid inléite amháin" -#~ msgid "cannot replace line" -#~ msgstr "ní féidir an líne a athchur" +#, c-format +msgid "E685: Internal error: %s" +msgstr "E685: Earráid inmheánach: %s" -#~ msgid "cannot insert line" -#~ msgstr "ní féidir líne a ionsá" +msgid "E363: pattern uses more memory than 'maxmempattern'" +msgstr "E363: úsáideann an patrún níos mó cuimhne ná 'maxmempattern'" -#~ msgid "string cannot contain newlines" -#~ msgstr "ní cheadaítear carachtair líne nua sa teaghrán" +msgid "E749: empty buffer" +msgstr "E749: maolán folamh" -#~ msgid "Vim error: ~a" -#~ msgstr "earráid Vim: ~a" +#, c-format +msgid "E86: Buffer %ld does not exist" +msgstr "E86: Níl a leithéid de mhaolán %ld" -#~ msgid "Vim error" -#~ msgstr "earráid Vim" +msgid "E682: Invalid search pattern or delimiter" +msgstr "E682: Patrún nó teormharcóir neamhbhailí cuardaigh" -#~ msgid "buffer is invalid" -#~ msgstr "maolán neamhbhailí" +msgid "E139: File is loaded in another buffer" +msgstr "E139: Tá an comhad luchtaithe i maolán eile" -#~ msgid "window is invalid" -#~ msgstr "fuinneog neamhbhailí" +#, c-format +msgid "E764: Option '%s' is not set" +msgstr "E764: Rogha '%s' gan socrú" -#~ msgid "linenr out of range" -#~ msgstr "líne-uimhir as raon" +msgid "E850: Invalid register name" +msgstr "E850: Ainm neamhbhailí tabhaill" -#~ msgid "not allowed in the Vim sandbox" -#~ msgstr "ní cheadaítear é seo i mbosca gainimh Vim" +#, c-format +msgid "E919: Directory not found in '%s': \"%s\"" +msgstr "E919: Comhadlann gan aimsiú in '%s': \"%s\"" -#~ msgid "" -#~ "E263: Sorry, this command is disabled, the Python library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E263: Tá brón orm, níl an t-ordú seo le fáil, níorbh fhéidir an " -#~ "leabharlann Python a luchtú." +msgid "search hit TOP, continuing at BOTTOM" +msgstr "Buaileadh an BARR le linn an chuardaigh, ag leanúint ag an CHRÍOCH" -#~ msgid "E659: Cannot invoke Python recursively" -#~ msgstr "E659: Ní féidir Python a rith go hathchúrsach" +msgid "search hit BOTTOM, continuing at TOP" +msgstr "Buaileadh an BUN le linn an chuardaigh, ag leanúint ag an BHARR" -#~ msgid "can't delete OutputObject attributes" -#~ msgstr "ní féidir tréithe OutputObject a scriosadh" +#, c-format +msgid "Need encryption key for \"%s\"" +msgstr "Eochair chriptiúcháin le haghaidh \"%s\" de dhíth" -#~ msgid "softspace must be an integer" -#~ msgstr "caithfidh softspace a bheith ina shlánuimhir" +msgid "empty keys are not allowed" +msgstr "ní cheadaítear eochracha folmha" -#~ msgid "invalid attribute" -#~ msgstr "aitreabúid neamhbhailí" +msgid "dictionary is locked" +msgstr "tá an foclóir faoi ghlas" -#~ msgid "writelines() requires list of strings" -#~ msgstr "liosta teaghrán ag teastáil ó writelines()" +msgid "list is locked" +msgstr "tá an liosta faoi ghlas" -#~ msgid "E264: Python: Error initialising I/O objects" -#~ msgstr "E264: Python: Earráid agus réada I/A á dtúsú" +#, c-format +msgid "failed to add key '%s' to dictionary" +msgstr "níorbh fhéidir eochair '%s' a chur leis an bhfoclóir" -#~ msgid "attempt to refer to deleted buffer" -#~ msgstr "rinneadh iarracht ar mhaolán scriosta a rochtain" +#, c-format +msgid "index must be int or slice, not %s" +msgstr "ní mór don innéacs a bheith ina shlánuimhir nó ina shlisne, seachas %s" -#~ msgid "line number out of range" -#~ msgstr "líne-uimhir as raon" +#, c-format +msgid "expected str() or unicode() instance, but got %s" +msgstr "bhíothas ag súil le str() nó unicode(), ach fuarthas %s" -#~ msgid "<buffer object (deleted) at %p>" -#~ msgstr "<réad maoláin (scriosta) ag %p>" +#, c-format +msgid "expected bytes() or str() instance, but got %s" +msgstr "bhíothas ag súil le bytes() nó str(), ach fuarthas %s" -#~ msgid "invalid mark name" -#~ msgstr "ainm neamhbhailí mairc" +#, c-format +msgid "" +"expected int(), long() or something supporting coercing to long(), but got %s" +msgstr "" +"bhíothas ag súil le int(), long(), nó rud éigin inathraithe ina long(), ach " +"fuarthas %s" -#~ msgid "no such buffer" -#~ msgstr "níl a leithéid de mhaolán ann" +#, c-format +msgid "expected int() or something supporting coercing to int(), but got %s" +msgstr "" +"bhíothas ag súil le int() nó rud éigin inathraithe ina int(), ach fuarthas %s" -#~ msgid "attempt to refer to deleted window" -#~ msgstr "rinneadh iarracht ar fhuinneog scriosta a rochtain" +msgid "value is too large to fit into C int type" +msgstr "tá an luach níos mó ná athróg int sa teanga C" -#~ msgid "readonly attribute" -#~ msgstr "tréith inléite amháin" +msgid "value is too small to fit into C int type" +msgstr "tá an luach níos lú ná athróg int sa teanga C" -#~ msgid "cursor position outside buffer" -#~ msgstr "cúrsóir taobh amuigh den mhaolán" +msgid "number must be greater than zero" +msgstr "ní mór don uimhir a bheith deimhneach" -#~ msgid "<window object (deleted) at %p>" -#~ msgstr "<réad fuinneoige (scriosta) ag %p>" +msgid "number must be greater or equal to zero" +msgstr "ní mór don uimhir a bheith >= 0" -#~ msgid "<window object (unknown) at %p>" -#~ msgstr "<réad fuinneoige (anaithnid) ag %p>" +msgid "can't delete OutputObject attributes" +msgstr "ní féidir tréithe OutputObject a scriosadh" -#~ msgid "<window %d>" -#~ msgstr "<fuinneog %d>" +#, c-format +msgid "invalid attribute: %s" +msgstr "aitreabúid neamhbhailí: %s" -#~ msgid "no such window" -#~ msgstr "níl a leithéid d'fhuinneog ann" +msgid "E264: Python: Error initialising I/O objects" +msgstr "E264: Python: Earráid agus réada I/A á dtúsú" -#~ msgid "E265: $_ must be an instance of String" -#~ msgstr "E265: caithfidh $_ a bheith cineál Teaghráin" +msgid "failed to change directory" +msgstr "níorbh fhéidir an chomhadlann a athrú" -#~ msgid "" -#~ "E266: Sorry, this command is disabled, the Ruby library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E266: Tá brón orm, níl an t-ordú seo le fáil, níorbh fhéidir an " -#~ "leabharlann Ruby a luchtú." +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got %s" +msgstr "" +"bhíothas ag súil le 3-chodach mar thoradh ar imp.find_module(), ach fuarthas " +"%s" + +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got tuple of size %d" +msgstr "" +"bhíothas ag súil le 3-chodach mar thoradh ar imp.find_module(), ach fuarthas " +"%d-chodach" + +msgid "internal error: imp.find_module returned tuple with NULL" +msgstr "earráid inmheánach: fuarthas codach NULL ar ais ó imp.find_module" + +msgid "cannot delete vim.Dictionary attributes" +msgstr "ní féidir tréithe vim.Dictionary a scriosadh" + +msgid "cannot modify fixed dictionary" +msgstr "ní féidir foclóir socraithe a athrú" + +#, c-format +msgid "cannot set attribute %s" +msgstr "ní féidir tréith %s a shocrú" + +msgid "hashtab changed during iteration" +msgstr "athraíodh an haistáb le linn atriallta" + +#, c-format +msgid "expected sequence element of size 2, but got sequence of size %d" +msgstr "bhíothas ag súil le heilimint de mhéid 2, ach fuarthas méid %d" + +msgid "list constructor does not accept keyword arguments" +msgstr "ní ghlacann cruthaitheoir an liosta le hargóintí eochairfhocail" + +msgid "list index out of range" +msgstr "innéacs liosta as raon" + +#. No more suitable format specifications in python-2.3 +#, c-format +msgid "internal error: failed to get vim list item %d" +msgstr "earráid inmheánach: níl aon fháil ar mhír %d sa liosta vim" -#~ msgid "E267: unexpected return" -#~ msgstr "E267: \"return\" gan choinne" +msgid "slice step cannot be zero" +msgstr "ní cheadaítear slisne le céim 0" -#~ msgid "E268: unexpected next" -#~ msgstr "E268: \"next\" gan choinne" +#, c-format +msgid "attempt to assign sequence of size greater than %d to extended slice" +msgstr "iarracht ar sheicheamh níos mó ná %d a shannadh do shlisne fadaithe" + +#, c-format +msgid "internal error: no vim list item %d" +msgstr "earráid inmheánach: níl aon mhír %d sa liosta vim" + +msgid "internal error: not enough list items" +msgstr "earráid inmheánach: níl go leor míreanna liosta ann" + +msgid "internal error: failed to add item to list" +msgstr "earráid inmheánach: níorbh fhéidir mír a chur leis an liosta" -#~ msgid "E269: unexpected break" -#~ msgstr "E269: \"break\" gan choinne" +#, c-format +msgid "attempt to assign sequence of size %d to extended slice of size %d" +msgstr "iarracht ar sheicheamh de mhéid %d a shannadh do shlisne de mhéid %d" + +msgid "failed to add item to list" +msgstr "níorbh fhéidir mír a chur leis an liosta" -#~ msgid "E270: unexpected redo" -#~ msgstr "E270: \"redo\" gan choinne" +msgid "cannot delete vim.List attributes" +msgstr "ní féidir tréithe vim.List a scriosadh" -#~ msgid "E271: retry outside of rescue clause" -#~ msgstr "E271: \"retry\" taobh amuigh de chlásal tarrthála" +msgid "cannot modify fixed list" +msgstr "ní féidir liosta socraithe a athrú" -#~ msgid "E272: unhandled exception" -#~ msgstr "E272: eisceacht gan láimhseáil" +#, c-format +msgid "unnamed function %s does not exist" +msgstr "níl feidhm %s gan ainm ann" + +#, c-format +msgid "function %s does not exist" +msgstr "níl feidhm %s ann" -#~ msgid "E273: unknown longjmp status %d" -#~ msgstr "E273: stádas anaithnid longjmp %d" +#, c-format +msgid "failed to run function %s" +msgstr "níorbh fhéidir feidhm %s a rith" + +msgid "unable to get option value" +msgstr "ní féidir luach na rogha a fháil" + +msgid "internal error: unknown option type" +msgstr "earráid inmheánach: cineál rogha anaithnid" + +msgid "problem while switching windows" +msgstr "tharla earráid agus an fhuinneog á hathrú" + +#, c-format +msgid "unable to unset global option %s" +msgstr "ní féidir rogha chomhchoiteann %s a dhíshocrú" + +#, c-format +msgid "unable to unset option %s which does not have global value" +msgstr "ní féidir rogha %s gan luach comhchoiteann a dhíshocrú" + +msgid "attempt to refer to deleted tab page" +msgstr "tagairt déanta do leathanach cluaisíní scriosta" + +msgid "no such tab page" +msgstr "níl a leithéid de leathanach cluaisíní ann" + +msgid "attempt to refer to deleted window" +msgstr "rinneadh iarracht ar fhuinneog scriosta a rochtain" + +msgid "readonly attribute: buffer" +msgstr "tréith inléite amháin: maolán" + +msgid "cursor position outside buffer" +msgstr "cúrsóir taobh amuigh den mhaolán" + +msgid "no such window" +msgstr "níl a leithéid d'fhuinneog ann" + +msgid "attempt to refer to deleted buffer" +msgstr "rinneadh iarracht ar mhaolán scriosta a rochtain" + +msgid "failed to rename buffer" +msgstr "níorbh fhéidir ainm nua a chur ar an maolán" + +msgid "mark name must be a single character" +msgstr "ní cheadaítear ach carachtar amháin in ainm an mhairc" + +#, c-format +msgid "expected vim.Buffer object, but got %s" +msgstr "bhíothas ag súil le réad vim.Buffer, ach fuarthas %s" + +#, c-format +msgid "failed to switch to buffer %d" +msgstr "níorbh fhéidir athrú go dtí maolán a %d" + +#, c-format +msgid "expected vim.Window object, but got %s" +msgstr "bhíothas ag súil le réad vim.Window, ach fuarthas %s" + +msgid "failed to find window in the current tab page" +msgstr "níor aimsíodh fuinneog sa leathanach cluaisíní reatha" + +msgid "did not switch to the specified window" +msgstr "níor athraíodh go dtí an fhuinneog roghnaithe" + +#, c-format +msgid "expected vim.TabPage object, but got %s" +msgstr "bhíothas ag súil le réad vim.TabPage, ach fuarthas %s" + +msgid "did not switch to the specified tab page" +msgstr "níor athraíodh go dtí an leathanach cluaisíní roghnaithe" + +msgid "failed to run the code" +msgstr "níorbh fhéidir an cód a chur ar siúl" + +msgid "E858: Eval did not return a valid python object" +msgstr "E858: Ní bhfuarthas réad bailí python ar ais ó Eval" + +msgid "E859: Failed to convert returned python object to vim value" +msgstr "E859: Níorbh fhéidir luach vim a dhéanamh as an réad python" + +#, c-format +msgid "unable to convert %s to vim dictionary" +msgstr "ní féidir foclóir vim a dhéanamh as %s" + +#, c-format +msgid "unable to convert %s to vim list" +msgstr "ní féidir liosta vim a dhéanamh as %s" + +#, c-format +msgid "unable to convert %s to vim structure" +msgstr "ní féidir struchtúr vim a dhéanamh as %s" + +msgid "internal error: NULL reference passed" +msgstr "earráid inmheánach: tagairt NULL seolta" + +msgid "internal error: invalid value type" +msgstr "earráid inmheánach: cineál neamhbhailí" + +msgid "" +"Failed to set path hook: sys.path_hooks is not a list\n" +"You should now do the following:\n" +"- append vim.path_hook to sys.path_hooks\n" +"- append vim.VIM_SPECIAL_PATH to sys.path\n" +msgstr "" +"Níorbh fhéidir path_hook a shocrú: ní liosta é sys.path_hooks\n" +"Ba chóir duit na rudaí seo a leanas a dhéanamh:\n" +"- cuir vim.path_hook le deireadh sys.path_hooks\n" +"- cuir vim.VIM_SPECIAL_PATH le deireadh sys.path\n" + +msgid "" +"Failed to set path: sys.path is not a list\n" +"You should now append vim.VIM_SPECIAL_PATH to sys.path" +msgstr "" +"Níorbh fhéidir an chonair a shocrú: ní liosta é sys.path\n" +"Ba chóir duit vim.VIM_SPECIAL_PATH a cheangal le deireadh sys.path" + +#~ msgid "E693: Can only compare Funcref with Funcref" +#~ msgstr "E693: Is féidir Funcref a chur i gcomparáid le Funcref eile amháin" + +#~ msgid "E706: Variable type mismatch for: %s" +#~ msgstr "E706: Mímheaitseáil idir cineálacha athróige: %s" + +#~ msgid "%ld characters" +#~ msgstr "%ld carachtar" #~ msgid "Toggle implementation/definition" #~ msgstr "Scoránaigh feidhmiú/sainmhíniú" @@ -7063,255 +7159,112 @@ msgstr "E446: Níl ainm comhaid faoin chúrsóir" #~ msgid "Sniff: Error during write. Disconnected" #~ msgstr "Sniff: Earráid sa scríobh. Dínasctha" -#~ msgid "invalid buffer number" -#~ msgstr "uimhir neamhbhailí mhaoláin" - -#~ msgid "not implemented yet" -#~ msgstr "níl ar fáil" - -#~ msgid "cannot set line(s)" -#~ msgstr "ní féidir lín(t)e a shocrú" - -#~ msgid "mark not set" -#~ msgstr "marc gan socrú" - -#~ msgid "row %d column %d" -#~ msgstr "líne %d colún %d" - -#~ msgid "cannot insert/append line" -#~ msgstr "ní féidir líne a ionsá/iarcheangal" - -#~ msgid "unknown flag: " -#~ msgstr "bratach anaithnid: " - -#~ msgid "unknown vimOption" -#~ msgstr "vimOption anaithnid" - -#~ msgid "keyboard interrupt" -#~ msgstr "idirbhriseadh méarchláir" - -#~ msgid "vim error" -#~ msgstr "earráid vim" - -#~ msgid "cannot create buffer/window command: object is being deleted" -#~ msgstr "ní féidir ordú maoláin/fuinneoige a chruthú: réad á scriosadh" - -#~ msgid "" -#~ "cannot register callback command: buffer/window is already being deleted" -#~ msgstr "" -#~ "ní féidir ordú aisghlaoch a chlárú: maolán/fuinneog á scriosadh cheana" - -#~ msgid "" -#~ "E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-" -#~ "dev@vim.org" -#~ msgstr "" -#~ "E280: EARRÁID MHARFACH TCL: liosta truaillithe tagartha!? Seol tuairisc " -#~ "fhabht chuig <vim-dev@vim.org> le do thoil" - -#~ msgid "cannot register callback command: buffer/window reference not found" -#~ msgstr "" -#~ "ní féidir ordú aisghlaoch a chlárú: tagairt mhaolán/fhuinneoige gan aimsiú" - -#~ msgid "" -#~ "E571: Sorry, this command is disabled: the Tcl library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E571: Tá brón orm, níl an t-ordú seo le fáil: níorbh fhéidir an " -#~ "leabharlann Tcl a luchtú." +#~ msgid " Quit, or continue with caution.\n" +#~ msgstr " Scoir, nó lean ar aghaidh go hairdeallach.\n" -#~ msgid "" -#~ "E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim." -#~ "org" -#~ msgstr "" -#~ "E281: EARRÁID TCL: níl an cód scortha ina shlánuimhir!? Seol tuairisc " -#~ "fhabht chuig <vim-dev@vim.org> le do thoil" - -#~ msgid "E572: exit code %d" -#~ msgstr "E572: cód scortha %d" +#~ msgid "Cannot connect to Netbeans #2" +#~ msgstr "Ní féidir nascadh le Netbeans #2" -#~ msgid "cannot get line" -#~ msgstr "ní féidir an líne a fháil" +#~ msgid "read from Netbeans socket" +#~ msgstr "léadh ó shoicéad Netbeans" -#~ msgid "Unable to register a command server name" -#~ msgstr "Ní féidir ainm fhreastalaí ordaithe a chlárú" +#~ msgid "'columns' is not 80, cannot execute external commands" +#~ msgstr "ní 80 é 'columns', ní féidir orduithe seachtracha a rith" -#~ msgid "E248: Failed to send command to the destination program" -#~ msgstr "E248: Theip ar sheoladh ordú chuig an sprioc-chlár" +#~ msgid "Could not set security context " +#~ msgstr "Níorbh fhéidir comhthéacs slándála a shocrú " -#~ msgid "E573: Invalid server id used: %s" -#~ msgstr "E573: Aitheantas neamhbhailí freastalaí in úsáid: %s" +#~ msgid " for " +#~ msgstr " le haghaidh " -#~ msgid "E251: VIM instance registry property is badly formed. Deleted!" -#~ msgstr "E251: Airí míchumtha sa chlárlann áisc VIM. Scriosta!" +#~ msgid "Could not get security context " +#~ msgstr "Níorbh fhéidir comhthéacs slándála a fháil " -#~ msgid "This Vim was not compiled with the diff feature." -#~ msgstr "Níor tiomsaíodh an leagan Vim seo le `diff' ar fáil." +#~ msgid ". Removing it!\n" +#~ msgstr ". Á scriosadh!\n" -#~ msgid "'-nb' cannot be used: not enabled at compile time\n" -#~ msgstr "Ní féidir '-nb' a úsáid: níor cumasaíodh é ag am tiomsaithe\n" +#~ msgid " (lang)" +#~ msgstr " (teanga)" -#~ msgid "Vim: Error: Failure to start gvim from NetBeans\n" -#~ msgstr "Vim: Earráid: Theip ar thosú gvim ó NetBeans\n" +#~ msgid "E759: Format error in spell file" +#~ msgstr "E759: Earráid fhormáide i gcomhad litrithe" #~ msgid "" #~ "\n" -#~ "Where case is ignored prepend / to make flag upper case" +#~ "MS-Windows 16/32-bit GUI version" #~ msgstr "" #~ "\n" -#~ "Nuair nach cásíogair é, cuir '/' ag tosach na brataí chun í a chur sa " -#~ "chás uachtair" - -#~ msgid "-register\t\tRegister this gvim for OLE" -#~ msgstr "-register\t\tCláraigh an gvim seo le haghaidh OLE" - -#~ msgid "-unregister\t\tUnregister gvim for OLE" -#~ msgstr "-unregister\t\tDíchláraigh an gvim seo le haghaidh OLE" - -#~ msgid "-g\t\t\tRun using GUI (like \"gvim\")" -#~ msgstr "-g\t\t\tRith agus úsáid an GUI (mar \"gvim\")" - -#~ msgid "-f or --nofork\tForeground: Don't fork when starting GUI" -#~ msgstr "-f nó --nofork\tTulra: Ná déan forc agus an GUI á thosú" - -#~ msgid "-f\t\t\tDon't use newcli to open window" -#~ msgstr "-f\t\t\tNá húsáid newcli chun fuinneog a oscailt" - -#~ msgid "-dev <device>\t\tUse <device> for I/O" -#~ msgstr "-dev <gléas>\t\tBain úsáid as <gléas> do I/A" - -#~ msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" -#~ msgstr "-U <gvimrc>\t\tBain úsáid as <gvimrc> in ionad aon .gvimrc" - -#~ msgid "-x\t\t\tEdit encrypted files" -#~ msgstr "-x\t\t\tCuir comhaid chriptithe in eagar" - -#~ msgid "-display <display>\tConnect vim to this particular X-server" -#~ msgstr "-display <freastalaí>\tNasc vim leis an bhfreastalaí-X seo" - -#~ msgid "-X\t\t\tDo not connect to X server" -#~ msgstr "-X\t\t\tNá naisc leis an bhfreastalaí X" - -#~ msgid "--remote <files>\tEdit <files> in a Vim server if possible" -#~ msgstr "" -#~ "--remote <comhaid>\tCuir <comhaid> in eagar le freastalaí Vim más féidir" - -#~ msgid "--remote-silent <files> Same, don't complain if there is no server" -#~ msgstr "" -#~ "--remote-silent <comhaid> Mar an gcéanna, ná déan gearán mura bhfuil " -#~ "freastalaí ann" - -#~ msgid "" -#~ "--remote-wait <files> As --remote but wait for files to have been edited" -#~ msgstr "" -#~ "--remote-wait <comhaid> Mar --remote ach fan leis na comhaid a bheith " -#~ "curtha in eagar" - -#~ msgid "" -#~ "--remote-wait-silent <files> Same, don't complain if there is no server" -#~ msgstr "" -#~ "--remote-wait-silent <comhaid> Mar an gcéanna, ná déan gearán mura " -#~ "bhfuil freastalaí ann" - -#~ msgid "" -#~ "--remote-tab[-wait][-silent] <files> As --remote but use tab page per " -#~ "file" -#~ msgstr "" -#~ "--remote-tab[-wait][-silent] <comhaid> Cosúil le --remote ach oscail " -#~ "cluaisín do gach comhad" - -#~ msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" -#~ msgstr "" -#~ "--remote-send <eochracha>\tSeol <eochracha> chuig freastalaí Vim agus " -#~ "scoir" - -#~ msgid "" -#~ "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" -#~ msgstr "" -#~ "--remote-expr <slonn>\tLuacháil <slonn> le freastalaí Vim agus taispeáin " -#~ "an toradh" - -#~ msgid "--serverlist\t\tList available Vim server names and exit" -#~ msgstr "--serverlist\t\tTaispeáin freastalaithe Vim atá ar fáil agus scoir" +#~ "Leagan GUI 16/32 giotán MS-Windows" -#~ msgid "--servername <name>\tSend to/become the Vim server <name>" -#~ msgstr "--servername <ainm>\tSeol chuig/Téigh i do fhreastalaí Vim <ainm>" +#~ msgid " in Win32s mode" +#~ msgstr " i mód Win32s" #~ msgid "" #~ "\n" -#~ "Arguments recognised by gvim (Motif version):\n" +#~ "MS-Windows 16-bit version" #~ msgstr "" #~ "\n" -#~ "Argóintí ar eolas do gvim (leagan Motif):\n" +#~ "Leagan 16 giotán MS-Windows" #~ msgid "" #~ "\n" -#~ "Arguments recognised by gvim (neXtaw version):\n" +#~ "32-bit MS-DOS version" #~ msgstr "" #~ "\n" -#~ "Argóintí ar eolas do gvim (leagan neXtaw):\n" +#~ "Leagan 32 giotán MS-DOS" #~ msgid "" #~ "\n" -#~ "Arguments recognised by gvim (Athena version):\n" +#~ "16-bit MS-DOS version" #~ msgstr "" #~ "\n" -#~ "Argóintí ar eolas do gvim (leagan Athena):\n" +#~ "Leagan 16 giotán MS-DOS" -#~ msgid "-display <display>\tRun vim on <display>" -#~ msgstr "-display <scáileán>\tRith vim ar <scáileán>" +#~ msgid "WARNING: Windows 95/98/ME detected" +#~ msgstr "RABHADH: Braitheadh Windows 95/98/ME" -#~ msgid "-iconic\t\tStart vim iconified" -#~ msgstr "-iconic\t\tTosaigh vim sa mhód íoslaghdaithe" +#~ msgid "type :help windows95<Enter> for info on this" +#~ msgstr "clóscríobh :help windows95<Enter> chun eolas a fháil " -#~ msgid "-name <name>\t\tUse resource as if vim was <name>" -#~ msgstr "-name <ainm>\t\tÚsáid acmhainn mar a bheadh vim <ainm>" +#~ msgid "function constructor does not accept keyword arguments" +#~ msgstr "ní ghlacann cruthaitheoir na feidhme le hargóintí eochairfhocail" -#~ msgid "\t\t\t (Unimplemented)\n" -#~ msgstr "\t\t\t (Níl ar fáil)\n" +#~ msgid "Vim dialog..." +#~ msgstr "Dialóg Vim..." -#~ msgid "-background <color>\tUse <color> for the background (also: -bg)" -#~ msgstr "-background <dath>\tBain úsáid as <dath> don chúlra (-bg fosta)" +#~ msgid "Font Selection" +#~ msgstr "Roghnú Cló" -#~ msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" -#~ msgstr "" -#~ "-foreground <dath>\tÚsáid <dath> le haghaidh gnáth-théacs (fosta: -fg)" +#~ msgid "softspace must be an integer" +#~ msgstr "caithfidh softspace a bheith ina shlánuimhir" -#~ msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" -#~ msgstr "-font <cló>\t\tÚsáid <cló> le haghaidh gnáth-théacs (fosta: -fn)" +#~ msgid "writelines() requires list of strings" +#~ msgstr "liosta teaghrán ag teastáil ó writelines()" -#~ msgid "-boldfont <font>\tUse <font> for bold text" -#~ msgstr "-boldfont <cló>\tBain úsáid as <cló> do chló trom" +#~ msgid "<buffer object (deleted) at %p>" +#~ msgstr "<réad maoláin (scriosta) ag %p>" -#~ msgid "-italicfont <font>\tUse <font> for italic text" -#~ msgstr "-italicfont <cló>\tÚsáid <cló> le haghaidh téacs iodálach" +#~ msgid "<window object (deleted) at %p>" +#~ msgstr "<réad fuinneoige (scriosta) ag %p>" -#~ msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" -#~ msgstr "" -#~ "-geometry <geoim>\tÚsáid <geoim> le haghaidh na céimseatan tosaigh " -#~ "(fosta: -geom)" +#~ msgid "<window object (unknown) at %p>" +#~ msgstr "<réad fuinneoige (anaithnid) ag %p>" -#~ msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" -#~ msgstr "-borderwidth <leithead>\tSocraigh <leithead> na himlíne (-bw fosta)" +#~ msgid "<window %d>" +#~ msgstr "<fuinneog %d>" #~ msgid "" -#~ "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" -#~ msgstr "" -#~ "-scrollbarwidth <leithead> Socraigh leithead na scrollbharraí a bheith " -#~ "<leithead> (fosta: -sw)" - -#~ msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" +#~ "E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim." +#~ "org" #~ msgstr "" -#~ "-menuheight <airde>\tSocraigh airde an bharra roghchláir a bheith <airde> " -#~ "(fosta: -mh)" - -#~ msgid "-reverse\t\tUse reverse video (also: -rv)" -#~ msgstr "-reverse\t\tÚsáid fís aisiompaithe (fosta: -rv)" +#~ "E281: EARRÁID TCL: níl an cód scortha ina shlánuimhir!? Seol tuairisc " +#~ "fhabht chuig <vim-dev@vim.org> le do thoil" -#~ msgid "+reverse\t\tDon't use reverse video (also: +rv)" -#~ msgstr "+reverse\t\tNá húsáid fís aisiompaithe (fosta: +rv)" +#~ msgid "-name <name>\t\tUse resource as if vim was <name>" +#~ msgstr "-name <ainm>\t\tÚsáid acmhainn mar a bheadh vim <ainm>" -#~ msgid "-xrm <resource>\tSet the specified resource" -#~ msgstr "-xrm <acmhainn>\tSocraigh an acmhainn sainithe" +#~ msgid "\t\t\t (Unimplemented)\n" +#~ msgstr "\t\t\t (Níl ar fáil)\n" #~ msgid "" #~ "\n" @@ -7326,66 +7279,6 @@ msgstr "E446: Níl ainm comhaid faoin chúrsóir" #~ msgid "--rows <number>\tInitial height of window in rows" #~ msgstr "--rows <uimhir>\tAirde fhuinneoige i dtosach (rónna)" -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (GTK+ version):\n" -#~ msgstr "" -#~ "\n" -#~ "Argóintí ar eolas do gvim (leagan GTK+):\n" - -#~ msgid "-display <display>\tRun vim on <display> (also: --display)" -#~ msgstr "-display <scáileán>\tRith vim ar <scáileán> (fosta: --display)" - -#~ msgid "--role <role>\tSet a unique role to identify the main window" -#~ msgstr "" -#~ "--role <ról>\tSocraigh ról sainiúil chun an phríomhfhuinneog a aithint" - -#~ msgid "--socketid <xid>\tOpen Vim inside another GTK widget" -#~ msgstr "--socketid <xid>\tOscail Vim isteach i ngiuirléid GTK eile" - -#~ msgid "-P <parent title>\tOpen Vim inside parent application" -#~ msgstr "-P <máthairchlár>\tOscail Vim isteach sa mháthairchlár" - -#~ msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" -#~ msgstr "--windowid <HWND>\tOscail Vim isteach i ngiuirléid win32 eile" - -#~ msgid "No display" -#~ msgstr "Gan taispeáint" - -#~ msgid ": Send failed.\n" -#~ msgstr ": Theip ar seoladh.\n" - -#~ msgid ": Send failed. Trying to execute locally\n" -#~ msgstr ": Theip ar seoladh. Ag baint triail as go logánta\n" - -#~ msgid "%d of %d edited" -#~ msgstr "%d as %d déanta" - -#~ msgid "No display: Send expression failed.\n" -#~ msgstr "Gan taispeáint: Theip ar sheoladh sloinn.\n" - -#~ msgid ": Send expression failed.\n" -#~ msgstr ": Theip ar sheoladh sloinn.\n" - -#~ msgid "E543: Not a valid codepage" -#~ msgstr "E543: Ní códleathanach bailí é" - -#~ msgid "E285: Failed to create input context" -#~ msgstr "E285: Theip ar chruthú comhthéacs ionchuir" - -#~ msgid "E286: Failed to open input method" -#~ msgstr "E286: Theip ar oscailt mhodh ionchuir" - -#~ msgid "E287: Warning: Could not set destroy callback to IM" -#~ msgstr "" -#~ "E287: Rabhadh: Níorbh fhéidir aisghlaoch léirscriosta a shocrú le IM" - -#~ msgid "E288: input method doesn't support any style" -#~ msgstr "E288: Ní thacaíonn an modh ionchuir aon stíl" - -#~ msgid "E289: input method doesn't support my preedit type" -#~ msgstr "E289: ní thacaíonn an modh ionchuir mo chineál réamheagair" - #~ msgid "E290: over-the-spot style requires fontset" #~ msgstr "E290: tacar cló ag teastáil ó stíl thar-an-spota" @@ -7397,197 +7290,15 @@ msgstr "E446: Níl ainm comhaid faoin chúrsóir" #~ msgid "E292: Input Method Server is not running" #~ msgstr "E292: Níl an Freastalaí Mhodh Ionchuir ag rith" -#~ msgid "" -#~ "\n" -#~ " [not usable with this version of Vim]" -#~ msgstr "" -#~ "\n" -#~ " [ní inúsáidte leis an leagan seo Vim]" - -#~ msgid "Tear off this menu" -#~ msgstr "Bain an roghchlár seo" - -#~ msgid "Select Directory dialog" -#~ msgstr "Dialóg `Roghnaigh Comhadlann'" - -#~ msgid "Save File dialog" -#~ msgstr "Dialóg `Sábháil Comhad'" - -#~ msgid "Open File dialog" -#~ msgstr "Dialóg `Oscail Comhad'" - -#~ msgid "E338: Sorry, no file browser in console mode" -#~ msgstr "E338: Níl brabhsálaí comhaid ar fáil sa mhód consóil" - #~ msgid "Vim: preserving files...\n" #~ msgstr "Vim: comhaid á gcaomhnú...\n" #~ msgid "Vim: Finished.\n" #~ msgstr "Vim: Críochnaithe.\n" -#~ msgid "ERROR: " -#~ msgstr "EARRÁID: " - -#~ msgid "" -#~ "\n" -#~ "[bytes] total alloc-freed %<PRIu64>-%<PRIu64>, in use %<PRIu64>, peak use " -#~ "%<PRIu64>\n" -#~ msgstr "" -#~ "\n" -#~ "[beart] iomlán dáilte-saor %<PRIu64>-%<PRIu64>, in úsáid %<PRIu64>, buaic " -#~ "%<PRIu64>\n" - -#~ msgid "" -#~ "[calls] total re/malloc()'s %<PRIu64>, total free()'s %<PRIu64>\n" -#~ "\n" -#~ msgstr "" -#~ "[glaonna] re/malloc(): %<PRIu64>, free(): %<PRIu64>\n" -#~ "\n" - -#~ msgid "E340: Line is becoming too long" -#~ msgstr "E340: Tá an líne ag éirí rófhada" - -#~ msgid "E341: Internal error: lalloc(%<PRId64>, )" -#~ msgstr "E341: Earráid inmheánach: lalloc(%<PRId64>, )" - -#~ msgid "E547: Illegal mouseshape" -#~ msgstr "E547: Cruth neamhcheadaithe luiche" - -#~ msgid "Enter encryption key: " -#~ msgstr "Iontráil eochair chriptiúcháin: " - -#~ msgid "Enter same key again: " -#~ msgstr "Iontráil an eochair arís: " - -#~ msgid "Keys don't match!" -#~ msgstr "Níl na heochracha comhoiriúnach le chéile!" - -#~ msgid "Cannot connect to Netbeans #2" -#~ msgstr "Ní féidir nascadh le Netbeans #2" - -#~ msgid "Cannot connect to Netbeans" -#~ msgstr "Ní féidir nascadh le Netbeans" - -#~ msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" -#~ msgstr "" -#~ "E668: Mód mícheart rochtana ar an chomhad eolas naisc NetBeans: \"%s\"" - -#~ msgid "read from Netbeans socket" -#~ msgstr "léadh ó shoicéad Netbeans" - -#~ msgid "E658: NetBeans connection lost for buffer %<PRId64>" -#~ msgstr "E658: Cailleadh nasc NetBeans le haghaidh maoláin %<PRId64>" - #~ msgid "E505: " #~ msgstr "E505: " -#~ msgid "E775: Eval feature not available" -#~ msgstr "E775: Níl an ghné Eval le fáil" - -#~ msgid "freeing %<PRId64> lines" -#~ msgstr "%<PRId64> líne á saoradh" - -#~ msgid "E530: Cannot change term in GUI" -#~ msgstr "E530: Ní féidir 'term' a athrú sa GUI" - -#~ msgid "E531: Use \":gui\" to start the GUI" -#~ msgstr "E531: Úsáid \":gui\" chun an GUI a chur ag obair" - -#~ msgid "E617: Cannot be changed in the GTK+ 2 GUI" -#~ msgstr "E617: Ní féidir é a athrú sa GUI GTK+ 2" - -#~ msgid "E596: Invalid font(s)" -#~ msgstr "E596: Cló(nna) neamhbhailí" - -#~ msgid "E597: can't select fontset" -#~ msgstr "E597: ní féidir tacar cló a roghnú" - -#~ msgid "E598: Invalid fontset" -#~ msgstr "E598: Tacar cló neamhbhailí" - -#~ msgid "E533: can't select wide font" -#~ msgstr "E533: ní féidir cló leathan a roghnú" - -#~ msgid "E534: Invalid wide font" -#~ msgstr "E534: Cló leathan neamhbhailí" - -#~ msgid "E538: No mouse support" -#~ msgstr "E538: Gan tacaíocht luiche" - -#~ msgid "cannot open " -#~ msgstr "ní féidir a oscailt: " - -#~ msgid "VIM: Can't open window!\n" -#~ msgstr "VIM: Ní féidir fuinneog a oscailt!\n" - -#~ msgid "Need Amigados version 2.04 or later\n" -#~ msgstr "Tá gá le Amigados leagan 2.04 nó níos déanaí\n" - -#~ msgid "Need %s version %<PRId64>\n" -#~ msgstr "Tá gá le %s, leagan %<PRId64>\n" - -#~ msgid "Cannot open NIL:\n" -#~ msgstr "Ní féidir NIL a oscailt:\n" - -#~ msgid "Cannot create " -#~ msgstr "Ní féidir a chruthú: " - -#~ msgid "Vim exiting with %d\n" -#~ msgstr "Vim á scor le stádas %d\n" - -#~ msgid "cannot change console mode ?!\n" -#~ msgstr "ní féidir mód consóil a athrú ?!\n" - -#~ msgid "mch_get_shellsize: not a console??\n" -#~ msgstr "mch_get_shellsize: ní consól é seo??\n" - -#~ msgid "E360: Cannot execute shell with -f option" -#~ msgstr "E360: Ní féidir blaosc a rith le rogha -f" - -#~ msgid "Cannot execute " -#~ msgstr "Ní féidir blaosc a rith: " - -#~ msgid "shell " -#~ msgstr "blaosc " - -#~ msgid " returned\n" -#~ msgstr " aisfhilleadh\n" - -#~ msgid "ANCHOR_BUF_SIZE too small." -#~ msgstr "ANCHOR_BUF_SIZE róbheag." - -#~ msgid "I/O ERROR" -#~ msgstr "EARRÁID I/A" - -#~ msgid "Message" -#~ msgstr "Teachtaireacht" - -#~ msgid "'columns' is not 80, cannot execute external commands" -#~ msgstr "ní 80 é 'columns', ní féidir orduithe seachtracha a rith" - -#~ msgid "E237: Printer selection failed" -#~ msgstr "E237: Theip ar roghnú printéara" - -#~ msgid "to %s on %s" -#~ msgstr "go %s ar %s" - -#~ msgid "E613: Unknown printer font: %s" -#~ msgstr "E613: Clófhoireann anaithnid printéara: %s" - -#~ msgid "E238: Print error: %s" -#~ msgstr "E238: Earráid phriontála: %s" - -#~ msgid "Printing '%s'" -#~ msgstr "'%s' á phriontáil" - -#~ msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" -#~ msgstr "" -#~ "E244: Ainm neamhcheadaithe ar thacar carachtar \"%s\" mar pháirt d'ainm " -#~ "cló \"%s\"" - -#~ msgid "E245: Illegal char '%c' in font name \"%s\"" -#~ msgstr "E245: Carachtar neamhcheadaithe '%c' mar pháirt d'ainm cló \"%s\"" - #~ msgid "Vim: Double signal, exiting\n" #~ msgstr "Vim: Comhartha dúbailte, ag scor\n" @@ -7597,419 +7308,23 @@ msgstr "E446: Níl ainm comhaid faoin chúrsóir" #~ msgid "Vim: Caught deadly signal\n" #~ msgstr "Vim: Fuarthas comhartha marfach\n" -#~ msgid "Opening the X display took %<PRId64> msec" -#~ msgstr "Thóg %<PRId64> ms chun an scáileán X a oscailt" - -#~ msgid "" -#~ "\n" -#~ "Vim: Got X error\n" -#~ msgstr "" -#~ "\n" -#~ "Vim: Fuarthas earráid ó X\n" - -#~ msgid "Testing the X display failed" -#~ msgstr "Theip ar thástáil an scáileáin X" - -#~ msgid "Opening the X display timed out" -#~ msgstr "Oscailt an scáileáin X thar am" - -#~ msgid "" -#~ "\n" -#~ "Cannot execute shell sh\n" -#~ msgstr "" -#~ "\n" -#~ "Ní féidir an bhlaosc sh a rith\n" - -#~ msgid "" -#~ "\n" -#~ "Cannot create pipes\n" -#~ msgstr "" -#~ "\n" -#~ "Ní féidir píopaí a chruthú\n" - -# "fork" not in standard refs/corpus. Maybe want a "gabhl*" word instead? -KPS -#~ msgid "" -#~ "\n" -#~ "Cannot fork\n" -#~ msgstr "" -#~ "\n" -#~ "Ní féidir forc a dhéanamh\n" - -#~ msgid "" -#~ "\n" -#~ "Command terminated\n" -#~ msgstr "" -#~ "\n" -#~ "Ordú críochnaithe\n" - -#~ msgid "XSMP lost ICE connection" -#~ msgstr "Chaill XSMP an nasc ICE" - -#~ msgid "Opening the X display failed" -#~ msgstr "Theip ar oscailt an scáileáin X" - -#~ msgid "XSMP handling save-yourself request" -#~ msgstr "Iarratas sábháil-do-féin á láimhseáil ag XSMP" - -#~ msgid "XSMP opening connection" -#~ msgstr "Nasc á oscailt ag XSMP" - -#~ msgid "XSMP ICE connection watch failed" -#~ msgstr "Theip ar fhaire nasc ICE XSMP" - -#~ msgid "XSMP SmcOpenConnection failed: %s" -#~ msgstr "Theip ar XSMP SmcOpenConnection: %s" - -#~ msgid "At line" -#~ msgstr "Ag líne" - -#~ msgid "Could not load vim32.dll!" -#~ msgstr "Níorbh fhéidir vim32.dll a luchtú!" - -#~ msgid "VIM Error" -#~ msgstr "Earráid VIM" - -#~ msgid "Could not fix up function pointers to the DLL!" -#~ msgstr "Níorbh fhéidir pointeoirí feidhme a chóiriú i gcomhair an DLL!" - -#~ msgid "shell returned %d" -#~ msgstr "d'aisfhill an bhlaosc %d" - -#~ msgid "Vim: Caught %s event\n" -#~ msgstr "Vim: Fuarthas teagmhas %s\n" - -#~ msgid "close" -#~ msgstr "dún" - -#~ msgid "logoff" -#~ msgstr "logáil amach" - -#~ msgid "shutdown" -#~ msgstr "múchadh" - -#~ msgid "E371: Command not found" -#~ msgstr "E371: Ní bhfuarthas an t-ordú" - -#~ msgid "" -#~ "VIMRUN.EXE not found in your $PATH.\n" -#~ "External commands will not pause after completion.\n" -#~ "See :help win32-vimrun for more information." -#~ msgstr "" -#~ "Níor aimsíodh VIMRUN.EXE i do $PATH.\n" -#~ "Ní mhoilleoidh orduithe seachtracha agus iad curtha i gcrích.\n" -#~ "Féach ar :help win32-vimrun chun níos mó eolas a fháil." - -#~ msgid "Vim Warning" -#~ msgstr "Rabhadh Vim" - -#~ msgid "Conversion in %s not supported" -#~ msgstr "Tiontú i %s gan tacaíocht" - #~ msgid "E396: containedin argument not accepted here" #~ msgstr "E396: ní ghlactar leis an argóint containedin anseo" -#~ msgid "E430: Tag file path truncated for %s\n" -#~ msgstr "E430: Teascadh conair an chomhaid clibeanna le haghaidh %s\n" - -#~ msgid "new shell started\n" -#~ msgstr "tosaíodh blaosc nua\n" - -#~ msgid "Used CUT_BUFFER0 instead of empty selection" -#~ msgstr "Úsáideadh CUT_BUFFER0 in ionad roghnúcháin folaimh" - -#~ msgid "No undo possible; continue anyway" -#~ msgstr "Ní féidir a chealú; lean ar aghaidh mar sin féin" - # columns? #~ msgid "number changes time" #~ msgstr "uimhir athruithe am" #~ msgid "" #~ "\n" -#~ "MS-Windows 16/32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Leagan GUI 16/32 giotán MS-Windows" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Leagan GUI 64 giotán MS-Windows" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Leagan GUI 32 giotán MS-Windows" - -#~ msgid " in Win32s mode" -#~ msgstr " i mód Win32s" - -#~ msgid " with OLE support" -#~ msgstr " le tacaíocht OLE" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit console version" -#~ msgstr "" -#~ "\n" -#~ "Leagan consóil 64 giotán MS-Windows" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit console version" -#~ msgstr "" -#~ "\n" -#~ "Leagan consóil 32 giotán MS-Windows" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16-bit version" -#~ msgstr "" -#~ "\n" -#~ "Leagan 16 giotán MS-Windows" - -#~ msgid "" -#~ "\n" -#~ "32-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "Leagan 32 giotán MS-DOS" - -#~ msgid "" -#~ "\n" -#~ "16-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "Leagan 16 giotán MS-DOS" - -#~ msgid "" -#~ "\n" -#~ "MacOS X (unix) version" -#~ msgstr "" -#~ "\n" -#~ "Leagan MacOS X (unix)" - -#~ msgid "" -#~ "\n" -#~ "MacOS X version" -#~ msgstr "" -#~ "\n" -#~ "Leagan MacOS X" - -#~ msgid "" -#~ "\n" -#~ "MacOS version" -#~ msgstr "" -#~ "\n" -#~ "Leagan MacOS" - -#~ msgid "" -#~ "\n" #~ "RISC OS version" #~ msgstr "" #~ "\n" #~ "Leagan RISC OS" -#~ msgid "" -#~ "\n" -#~ "OpenVMS version" -#~ msgstr "" -#~ "\n" -#~ "Leagan OpenVMS" - -#~ msgid "" -#~ "\n" -#~ "Big version " -#~ msgstr "" -#~ "\n" -#~ "Leagan mór " - -#~ msgid "" -#~ "\n" -#~ "Normal version " -#~ msgstr "" -#~ "\n" -#~ "Leagan coitianta " - -#~ msgid "" -#~ "\n" -#~ "Small version " -#~ msgstr "" -#~ "\n" -#~ "Leagan beag " - -#~ msgid "" -#~ "\n" -#~ "Tiny version " -#~ msgstr "" -#~ "\n" -#~ "Leagan beag bídeach " - -#~ msgid "with GTK2-GNOME GUI." -#~ msgstr "le GUI GTK2-GNOME." - #~ msgid "with GTK-GNOME GUI." #~ msgstr "le GUI GTK-GNOME." -#~ msgid "with GTK2 GUI." -#~ msgstr "le GUI GTK2." - -#~ msgid "with GTK GUI." -#~ msgstr "le GUI GTK." - -#~ msgid "with X11-Motif GUI." -#~ msgstr "le GUI X11-Motif." - -#~ msgid "with X11-neXtaw GUI." -#~ msgstr "le GUI X11-neXtaw." - -#~ msgid "with X11-Athena GUI." -#~ msgstr "le GUI X11-Athena." - -#~ msgid "with Photon GUI." -#~ msgstr "le GUI Photon." - -#~ msgid "with GUI." -#~ msgstr "le GUI." - -#~ msgid "with Carbon GUI." -#~ msgstr "le GUI Carbon." - -#~ msgid "with Cocoa GUI." -#~ msgstr "le GUI Cocoa." - -#~ msgid "with (classic) GUI." -#~ msgstr "le GUI (clasaiceach)." - -#~ msgid " system gvimrc file: \"" -#~ msgstr " comhad gvimrc córais: \"" - -#~ msgid " user gvimrc file: \"" -#~ msgstr " comhad gvimrc úsáideora: \"" - -#~ msgid "2nd user gvimrc file: \"" -#~ msgstr "dara comhad gvimrc úsáideora: \"" - -#~ msgid "3rd user gvimrc file: \"" -#~ msgstr "tríú comhad gvimrc úsáideora: \"" - -#~ msgid " system menu file: \"" -#~ msgstr " comhad roghchláir an chórais: \"" - -#~ msgid "Compiler: " -#~ msgstr "Tiomsaitheoir: " - -# don't see where to localize "Help->Orphans"? --kps -#~ msgid "menu Help->Orphans for information " -#~ msgstr "roghchlár Help->Orphans chun eolas a fháil " - -#~ msgid "Running modeless, typed text is inserted" -#~ msgstr "Á rith gan mhóid, ag ionsá an téacs atá iontráilte" - -# same problem --kps -#~ msgid "menu Edit->Global Settings->Toggle Insert Mode " -#~ msgstr "roghchlár Edit->Global Settings->Toggle Insert Mode " - -#~ msgid " for two modes " -#~ msgstr " do dhá mhód " - -# same problem --kps -#~ msgid "menu Edit->Global Settings->Toggle Vi Compatible" -#~ msgstr "roghchlár Edit->Global Settings->Toggle Vi Compatible" - -#~ msgid " for Vim defaults " -#~ msgstr " le haghaidh réamhshocruithe Vim " - -#~ msgid "WARNING: Windows 95/98/ME detected" -#~ msgstr "RABHADH: Braitheadh Windows 95/98/ME" - -#~ msgid "type :help windows95<Enter> for info on this" -#~ msgstr "clóscríobh :help windows95<Enter> chun eolas a fháil " - -#~ msgid "E370: Could not load library %s" -#~ msgstr "E370: Níorbh fhéidir an leabharlann %s a oscailt" - -#~ msgid "" -#~ "Sorry, this command is disabled: the Perl library could not be loaded." -#~ msgstr "" -#~ "Tá brón orm, níl an t-ordú seo le fáil: níorbh fhéidir an leabharlann " -#~ "Perl a luchtú." - -#~ msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" -#~ msgstr "" -#~ "E299: Ní cheadaítear luacháil Perl i mbosca gainimh gan an modúl Safe" - -#~ msgid "Edit with &multiple Vims" -#~ msgstr "Cuir in eagar le Vimeanna io&madúla" - -#~ msgid "Edit with single &Vim" -#~ msgstr "Cuir in eagar le &Vim aonair" - -#~ msgid "Diff with Vim" -#~ msgstr "Diff le Vim" - -#~ msgid "Edit with &Vim" -#~ msgstr "Cuir in Eagar le &Vim" - -#~ msgid "Edit with existing Vim - " -#~ msgstr "Cuir in Eagar le Vim beo - " - -#~ msgid "Edits the selected file(s) with Vim" -#~ msgstr "Cuir an comhad roghnaithe in eagar le Vim" - -#~ msgid "Error creating process: Check if gvim is in your path!" -#~ msgstr "" -#~ "Earráid agus próiseas á chruthú: Deimhnigh go bhfuil gvim i do chonair!" - -#~ msgid "gvimext.dll error" -#~ msgstr "earráid gvimext.dll" - -#~ msgid "Path length too long!" -#~ msgstr "Conair rófhada!" - -#~ msgid "E234: Unknown fontset: %s" -#~ msgstr "E234: Tacar cló anaithnid: %s" - -#~ msgid "E235: Unknown font: %s" -#~ msgstr "E235: Clófhoireann anaithnid: %s" - -#~ msgid "E236: Font \"%s\" is not fixed-width" -#~ msgstr "E236: Ní cló aonleithid é \"%s\"" - -#~ msgid "E448: Could not load library function %s" -#~ msgstr "E448: Ní féidir feidhm %s leabharlainne a luchtú" - -#~ msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" -#~ msgstr "" -#~ "E26: Níl tacaíocht Eabhraise ar fáil: Níor cumasaíodh é ag am tiomsaithe\n" - -#~ msgid "E27: Farsi cannot be used: Not enabled at compile time\n" -#~ msgstr "" -#~ "E27: Níl tacaíocht Pheirsise ar fáil: Níor cumasaíodh é ag am tiomsaithe\n" - -#~ msgid "E800: Arabic cannot be used: Not enabled at compile time\n" -#~ msgstr "" -#~ "E800: Níl tacaíocht Araibise ar fáil: Níor cumasaíodh é ag am tiomsaithe\n" - -#~ msgid "E247: no registered server named \"%s\"" -#~ msgstr "E247: níl aon fhreastalaí cláraithe leis an ainm \"%s\"" - -#~ msgid "E233: cannot open display" -#~ msgstr "E233: ní féidir an scáileán a oscailt" - -#~ msgid "E449: Invalid expression received" -#~ msgstr "E449: Fuarthas slonn neamhbhailí" - -#~ msgid "E463: Region is guarded, cannot modify" -#~ msgstr "E463: Réigiún cosanta, ní féidir é a athrú" - -#~ msgid "E744: NetBeans does not allow changes in read-only files" -#~ msgstr "E744: Ní cheadaíonn NetBeans aon athrú i gcomhaid inléite amháin" - #~ msgid "E569: maximum number of cscope connections reached" #~ msgstr "E569: ní cheadaítear níos mó ná an líon uasta nasc cscope" @@ -8070,8 +7385,8 @@ msgstr "E446: Níl ainm comhaid faoin chúrsóir" #~ msgstr "" #~ "Ní mór do charachtar a úsáidtear ar SLASH a bheith ASCII; i %s líne %d: %s" -#~ msgid "%<PRId64> changes" -#~ msgstr "%<PRId64> athrú" +#~ msgid "%ld changes" +#~ msgstr "%ld athrú" #~ msgid "with KDE GUI." #~ msgstr "le GUI KDE." diff --git a/src/nvim/po/it.po b/src/nvim/po/it.po index 6c62262675..b8b119ade6 100644 --- a/src/nvim/po/it.po +++ b/src/nvim/po/it.po @@ -2541,7 +2541,7 @@ msgstr "E490: Non trovo alcuna piegatura" #: ../fold.c:544 msgid "E350: Cannot create fold with current 'foldmethod'" -msgstr "E350: Non posso create piegatura con il 'foldmethod' in uso" +msgstr "E350: Non posso creare piegatura con il 'foldmethod' in uso" #: ../fold.c:546 msgid "E351: Cannot delete fold with current 'foldmethod'" diff --git a/src/nvim/po/ja.euc-jp.po b/src/nvim/po/ja.euc-jp.po index c6425324b1..4b32096f1a 100644 --- a/src/nvim/po/ja.euc-jp.po +++ b/src/nvim/po/ja.euc-jp.po @@ -1,3 +1,4 @@ + # Japanese translation for Vim # # Do ":help uganda" in Vim to read copying and usage conditions. @@ -14,213 +15,176 @@ msgid "" msgstr "" "Project-Id-Version: Vim 7.4\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-02-01 09:02+0900\n" -"PO-Revision-Date: 2016-02-01 09:08+0900\n" +"POT-Creation-Date: 2016-09-10 21:10+0900\n" +"PO-Revision-Date: 2016-09-10 21:20+0900\n" "Last-Translator: MURAOKA Taro <koron.kaoriya@gmail.com>\n" "Language-Team: vim-jp (https://github.com/vim-jp/lang-ja)\n" "Language: Japanese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=euc-jp\n" "Content-Transfer-Encoding: 8-bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" -#: ../api/private/helpers.c:201 -#, fuzzy -msgid "Unable to get option value" -msgstr "¥ª¥×¥·¥ç¥ó¤ÎÃͤϼèÆÀ¤Ç¤¤Þ¤»¤ó" +msgid "E831: bf_key_init() called with empty password" +msgstr "E831: bf_key_init() ¤¬¶õ¥Ñ¥¹¥ï¡¼¥É¤Ç¸Æ¤Ó½Ð¤µ¤ì¤Þ¤·¤¿" -#: ../api/private/helpers.c:204 -msgid "internal error: unknown option type" -msgstr "ÆâÉô¥¨¥é¡¼: ̤ÃΤΥª¥×¥·¥ç¥ó·¿¤Ç¤¹" +msgid "E820: sizeof(uint32_t) != 4" +msgstr "E820: sizeof(uint32_t) != 4" + +msgid "E817: Blowfish big/little endian use wrong" +msgstr "E817: Blowfish°Å¹æ¤Î¥Ó¥Ã¥°/¥ê¥È¥ë¥¨¥ó¥Ç¥£¥¢¥ó¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹" + +msgid "E818: sha256 test failed" +msgstr "E818: sha256¤Î¥Æ¥¹¥È¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" + +msgid "E819: Blowfish test failed" +msgstr "E819: Blowfish°Å¹æ¤Î¥Æ¥¹¥È¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#: ../buffer.c:92 msgid "[Location List]" msgstr "[¥í¥±¡¼¥·¥ç¥ó¥ê¥¹¥È]" -#: ../buffer.c:93 msgid "[Quickfix List]" msgstr "[Quickfix¥ê¥¹¥È]" -#: ../buffer.c:94 msgid "E855: Autocommands caused command to abort" msgstr "E855: autocommand¤¬¥³¥Þ¥ó¥É¤ÎÄä»ß¤ò°ú¤µ¯¤³¤·¤Þ¤·¤¿" -#: ../buffer.c:135 msgid "E82: Cannot allocate any buffer, exiting..." msgstr "E82: ¥Ð¥Ã¥Õ¥¡¤ò1¤Ä¤âºîÀ®¤Ç¤¤Ê¤¤¤Î¤Ç, ½ªÎ»¤·¤Þ¤¹..." -#: ../buffer.c:138 msgid "E83: Cannot allocate buffer, using other one..." msgstr "E83: ¥Ð¥Ã¥Õ¥¡¤òºîÀ®¤Ç¤¤Ê¤¤¤Î¤Ç, ¾¤Î¤ò»ÈÍѤ·¤Þ¤¹..." -#: ../buffer.c:763 +msgid "E931: Buffer cannot be registered" +msgstr "E931: ¥Ð¥Ã¥Õ¥¡¤òÅÐÏ¿¤Ç¤¤Þ¤»¤ó" + +msgid "E937: Attempt to delete a buffer that is in use" +msgstr "E937: »ÈÍÑÃæ¤Î¥Ð¥Ã¥Õ¥¡¤òºï½ü¤·¤è¤¦¤È»î¤ß¤Þ¤·¤¿" + msgid "E515: No buffers were unloaded" msgstr "E515: ²òÊü¤µ¤ì¤¿¥Ð¥Ã¥Õ¥¡¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../buffer.c:765 msgid "E516: No buffers were deleted" msgstr "E516: ºï½ü¤µ¤ì¤¿¥Ð¥Ã¥Õ¥¡¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../buffer.c:767 msgid "E517: No buffers were wiped out" msgstr "E517: ÇË´þ¤µ¤ì¤¿¥Ð¥Ã¥Õ¥¡¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../buffer.c:772 msgid "1 buffer unloaded" msgstr "1 ¸Ä¤Î¥Ð¥Ã¥Õ¥¡¤¬²òÊü¤µ¤ì¤Þ¤·¤¿" -#: ../buffer.c:774 #, c-format msgid "%d buffers unloaded" msgstr "%d ¸Ä¤Î¥Ð¥Ã¥Õ¥¡¤¬²òÊü¤µ¤ì¤Þ¤·¤¿" -#: ../buffer.c:777 msgid "1 buffer deleted" msgstr "1 ¸Ä¤Î¥Ð¥Ã¥Õ¥¡¤¬ºï½ü¤µ¤ì¤Þ¤·¤¿" -#: ../buffer.c:779 #, c-format msgid "%d buffers deleted" msgstr "%d ¸Ä¤Î¥Ð¥Ã¥Õ¥¡¤¬ºï½ü¤µ¤ì¤Þ¤·¤¿" -#: ../buffer.c:782 msgid "1 buffer wiped out" msgstr "1 ¸Ä¤Î¥Ð¥Ã¥Õ¥¡¤¬ÇË´þ¤µ¤ì¤Þ¤·¤¿" -#: ../buffer.c:784 #, c-format msgid "%d buffers wiped out" msgstr "%d ¸Ä¤Î¥Ð¥Ã¥Õ¥¡¤¬ÇË´þ¤µ¤ì¤Þ¤·¤¿" -#: ../buffer.c:806 msgid "E90: Cannot unload last buffer" msgstr "E90: ºÇ¸å¤Î¥Ð¥Ã¥Õ¥¡¤Ï²òÊü¤Ç¤¤Þ¤»¤ó" -#: ../buffer.c:874 msgid "E84: No modified buffer found" msgstr "E84: Êѹ¹¤µ¤ì¤¿¥Ð¥Ã¥Õ¥¡¤Ï¤¢¤ê¤Þ¤»¤ó" #. back where we started, didn't find anything. -#: ../buffer.c:903 msgid "E85: There is no listed buffer" msgstr "E85: ¥ê¥¹¥Èɽ¼¨¤µ¤ì¤ë¥Ð¥Ã¥Õ¥¡¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../buffer.c:913 -#, c-format -msgid "E86: Buffer %<PRId64> does not exist" -msgstr "E86: ¥Ð¥Ã¥Õ¥¡ %<PRId64> ¤Ï¤¢¤ê¤Þ¤»¤ó" - -#: ../buffer.c:915 msgid "E87: Cannot go beyond last buffer" msgstr "E87: ºÇ¸å¤Î¥Ð¥Ã¥Õ¥¡¤ò±Û¤¨¤Æ°Üư¤Ï¤Ç¤¤Þ¤»¤ó" -#: ../buffer.c:917 msgid "E88: Cannot go before first buffer" msgstr "E88: ºÇ½é¤Î¥Ð¥Ã¥Õ¥¡¤è¤êÁ°¤Ø¤Ï°Üư¤Ç¤¤Þ¤»¤ó" -#: ../buffer.c:945 #, c-format -msgid "" -"E89: No write since last change for buffer %<PRId64> (add ! to override)" -msgstr "E89: ¥Ð¥Ã¥Õ¥¡ %<PRId64> ¤ÎÊѹ¹¤ÏÊݸ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó (! ¤ÇÊѹ¹¤òÇË´þ)" +msgid "E89: No write since last change for buffer %ld (add ! to override)" +msgstr "E89: ¥Ð¥Ã¥Õ¥¡ %ld ¤ÎÊѹ¹¤ÏÊݸ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó (! ¤ÇÊѹ¹¤òÇË´þ)" -#. wrap around (may cause duplicates) -#: ../buffer.c:1423 msgid "W14: Warning: List of file names overflow" msgstr "W14: ·Ù¹ð: ¥Õ¥¡¥¤¥ë̾¤Î¥ê¥¹¥È¤¬Ä¹²á¤®¤Þ¤¹" -#: ../buffer.c:1555 ../quickfix.c:3361 #, c-format -msgid "E92: Buffer %<PRId64> not found" -msgstr "E92: ¥Ð¥Ã¥Õ¥¡ %<PRId64> ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" +msgid "E92: Buffer %ld not found" +msgstr "E92: ¥Ð¥Ã¥Õ¥¡ %ld ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../buffer.c:1798 #, c-format msgid "E93: More than one match for %s" msgstr "E93: %s ¤ËÊ£¿ô¤Î³ºÅö¤¬¤¢¤ê¤Þ¤·¤¿" -#: ../buffer.c:1800 #, c-format msgid "E94: No matching buffer for %s" msgstr "E94: %s ¤Ë³ºÅö¤¹¤ë¥Ð¥Ã¥Õ¥¡¤Ï¤¢¤ê¤Þ¤»¤ó¤Ç¤·¤¿" -#: ../buffer.c:2161 #, c-format -msgid "line %<PRId64>" -msgstr "¹Ô %<PRId64>" +msgid "line %ld" +msgstr "¹Ô %ld" -#: ../buffer.c:2233 msgid "E95: Buffer with this name already exists" msgstr "E95: ¤³¤Î̾Á°¤Î¥Ð¥Ã¥Õ¥¡¤Ï´û¤Ë¤¢¤ê¤Þ¤¹" -#: ../buffer.c:2498 msgid " [Modified]" msgstr " [Êѹ¹¤¢¤ê]" -#: ../buffer.c:2501 msgid "[Not edited]" msgstr "[̤ÊÔ½¸]" -#: ../buffer.c:2504 msgid "[New file]" msgstr "[¿·¥Õ¥¡¥¤¥ë]" -#: ../buffer.c:2505 msgid "[Read errors]" msgstr "[ÆÉ¹þ¥¨¥é¡¼]" -#: ../buffer.c:2506 ../buffer.c:3217 ../fileio.c:1807 ../screen.c:4895 msgid "[RO]" msgstr "[ÆÉÀì]" -#: ../buffer.c:2507 ../fileio.c:1807 msgid "[readonly]" msgstr "[ÆÉ¹þÀìÍÑ]" -#: ../buffer.c:2524 #, c-format msgid "1 line --%d%%--" msgstr "1 ¹Ô --%d%%--" -#: ../buffer.c:2526 #, c-format -msgid "%<PRId64> lines --%d%%--" -msgstr "%<PRId64> ¹Ô --%d%%--" +msgid "%ld lines --%d%%--" +msgstr "%ld ¹Ô --%d%%--" -#: ../buffer.c:2530 #, c-format -msgid "line %<PRId64> of %<PRId64> --%d%%-- col " -msgstr "¹Ô %<PRId64> (Á´ÂÎ %<PRId64>) --%d%%-- col " +msgid "line %ld of %ld --%d%%-- col " +msgstr "¹Ô %ld (Á´ÂÎ %ld) --%d%%-- col " -#: ../buffer.c:2632 ../buffer.c:4292 ../memline.c:1554 msgid "[No Name]" msgstr "[̵̾]" #. must be a help buffer -#: ../buffer.c:2667 msgid "help" msgstr "¥Ø¥ë¥×" -#: ../buffer.c:3225 ../screen.c:4883 msgid "[Help]" msgstr "[¥Ø¥ë¥×]" -#: ../buffer.c:3254 ../screen.c:4887 msgid "[Preview]" msgstr "[¥×¥ì¥Ó¥å¡¼]" -#: ../buffer.c:3528 msgid "All" msgstr "Á´¤Æ" -#: ../buffer.c:3528 msgid "Bot" msgstr "ËöÈø" -#: ../buffer.c:3531 msgid "Top" msgstr "ÀèÆ¬" -#: ../buffer.c:4244 msgid "" "\n" "# Buffer list:\n" @@ -228,11 +192,9 @@ msgstr "" "\n" "# ¥Ð¥Ã¥Õ¥¡¥ê¥¹¥È:\n" -#: ../buffer.c:4289 msgid "[Scratch]" msgstr "[²¼½ñ¤]" -#: ../buffer.c:4529 msgid "" "\n" "--- Signs ---" @@ -240,200 +202,235 @@ msgstr "" "\n" "--- ¥µ¥¤¥ó ---" -#: ../buffer.c:4538 #, c-format msgid "Signs for %s:" msgstr "%s ¤Î¥µ¥¤¥ó:" -#: ../buffer.c:4543 #, c-format -msgid " line=%<PRId64> id=%d name=%s" -msgstr " ¹Ô=%<PRId64> ¼±ÊÌ»Ò=%d ̾Á°=%s" +msgid " line=%ld id=%d name=%s" +msgstr " ¹Ô=%ld ¼±ÊÌ»Ò=%d ̾Á°=%s" -#: ../cursor_shape.c:68 -msgid "E545: Missing colon" -msgstr "E545: ¥³¥í¥ó¤¬¤¢¤ê¤Þ¤»¤ó" +msgid "E902: Cannot connect to port" +msgstr "E902: ¥Ý¡¼¥È¤ËÀܳ¤Ç¤¤Þ¤»¤ó" -#: ../cursor_shape.c:70 ../cursor_shape.c:94 -msgid "E546: Illegal mode" -msgstr "E546: ÉÔÀµ¤Ê¥â¡¼¥É¤Ç¤¹" +msgid "E901: gethostbyname() in channel_open()" +msgstr "E901: channel_open() Æâ¤Î gethostbyname() ¤¬¼ºÇÔ¤·¤Þ¤·¤¿" -#: ../cursor_shape.c:134 -msgid "E548: digit expected" -msgstr "E548: ¿ôÃͤ¬É¬ÍפǤ¹" +msgid "E898: socket() in channel_open()" +msgstr "E898: channel_open() Æâ¤Î socket() ¤¬¼ºÇÔ¤·¤Þ¤·¤¿" -#: ../cursor_shape.c:138 -msgid "E549: Illegal percentage" -msgstr "E549: ÉÔÀµ¤Ê¥Ñ¡¼¥»¥ó¥Æ¡¼¥¸¤Ç¤¹" +msgid "E903: received command with non-string argument" +msgstr "E903: Èóʸ»úÎó¤Î°ú¿ô¤Î¥³¥Þ¥ó¥É¤ò¼õ¿®¤·¤Þ¤·¤¿" + +msgid "E904: last argument for expr/call must be a number" +msgstr "E904: expr/call ¤ÎºÇ¸å¤Î°ú¿ô¤Ï¿ô»ú¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" + +msgid "E904: third argument for call must be a list" +msgstr "E904: call ¤Î3ÈÖÌܤΰú¿ô¤Ï¥ê¥¹¥È·¿¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" + +#, c-format +msgid "E905: received unknown command: %s" +msgstr "E905: ̤ÃΤΥ³¥Þ¥ó¥É¤ò¼õ¿®¤·¤Þ¤·¤¿: %s" + +#, c-format +msgid "E630: %s(): write while not connected" +msgstr "E630: %s(): ÈóÀܳ¾õÂ֤ǽñ¤¹þ¤ß¤Þ¤·¤¿" + +#, c-format +msgid "E631: %s(): write failed" +msgstr "E631: %s(): ½ñ¤¹þ¤ß¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" + +#, c-format +msgid "E917: Cannot use a callback with %s()" +msgstr "E917: %s() ¤Ë¥³¡¼¥ë¥Ð¥Ã¥¯¤Ï»È¤¨¤Þ¤»¤ó" + +msgid "E912: cannot use ch_evalexpr()/ch_sendexpr() with a raw or nl channel" +msgstr "E912: À¸¤ä nl ¥Á¥ã¥ó¥Í¥ë¤Ë ch_evalexpr()/ch_sendexpr ¤Ï»È¤¨¤Þ¤»¤ó" + +msgid "E906: not an open channel" +msgstr "E906: ³«¤¤¤Æ¤¤¤Ê¤¤¥Á¥ã¥ó¥Í¥ë¤Ç¤¹" + +msgid "E920: _io file requires _name to be set" +msgstr "E920: _io ¥Õ¥¡¥¤¥ë¤Ï _name ¤ÎÀßÄ꤬ɬÍפǤ¹" + +msgid "E915: in_io buffer requires in_buf or in_name to be set" +msgstr "E915: in_io ¥Ð¥Ã¥Õ¥¡¤Ï in_buf ¤« in_name ¤ÎÀßÄ꤬ɬÍפǤ¹" + +#, c-format +msgid "E918: buffer must be loaded: %s" +msgstr "E918: ¥Ð¥Ã¥Õ¥¡¤¬¥í¡¼¥É¤µ¤ì¤Æ¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó: %s" + +msgid "E821: File is encrypted with unknown method" +msgstr "E821: ¥Õ¥¡¥¤¥ë¤¬Ì¤ÃΤÎÊýË¡¤Ç°Å¹æ²½¤µ¤ì¤Æ¤¤¤Þ¤¹" + +msgid "Warning: Using a weak encryption method; see :help 'cm'" +msgstr "·Ù¹ð: ¼å¤¤°Å¹æÊýË¡¤ò»È¤Ã¤Æ¤¤¤Þ¤¹; :help 'cm' ¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤" + +msgid "Enter encryption key: " +msgstr "°Å¹æ²½ÍѤΥ¡¼¤òÆþÎϤ·¤Æ¤¯¤À¤µ¤¤: " + +msgid "Enter same key again: " +msgstr "¤â¤¦°ìÅÙÆ±¤¸¥¡¼¤òÆþÎϤ·¤Æ¤¯¤À¤µ¤¤: " + +msgid "Keys don't match!" +msgstr "¥¡¼¤¬°ìÃפ·¤Þ¤»¤ó" + +msgid "[crypted]" +msgstr "[°Å¹æ²½]" + +#, c-format +msgid "E720: Missing colon in Dictionary: %s" +msgstr "E720: ¼½ñ·¿¤Ë¥³¥í¥ó¤¬¤¢¤ê¤Þ¤»¤ó: %s" + +#, c-format +msgid "E721: Duplicate key in Dictionary: \"%s\"" +msgstr "E721: ¼½ñ·¿¤Ë½ÅÊ£¥¡¼¤¬¤¢¤ê¤Þ¤¹: \"%s\"" + +#, c-format +msgid "E722: Missing comma in Dictionary: %s" +msgstr "E722: ¼½ñ·¿¤Ë¥«¥ó¥Þ¤¬¤¢¤ê¤Þ¤»¤ó: %s" + +#, c-format +msgid "E723: Missing end of Dictionary '}': %s" +msgstr "E723: ¼½ñ·¿¤ÎºÇ¸å¤Ë '}' ¤¬¤¢¤ê¤Þ¤»¤ó: %s" + +msgid "extend() argument" +msgstr "extend() ¤Î°ú¿ô" -#: ../diff.c:146 #, c-format -msgid "E96: Can not diff more than %<PRId64> buffers" -msgstr "E96: %<PRId64> °Ê¾å¤Î¥Ð¥Ã¥Õ¥¡¤Ïdiff¤Ç¤¤Þ¤»¤ó" +msgid "E737: Key already exists: %s" +msgstr "E737: ¥¡¼¤Ï´û¤Ë¸ºß¤·¤Þ¤¹: %s" + +#, c-format +msgid "E96: Cannot diff more than %ld buffers" +msgstr "E96: %ld °Ê¾å¤Î¥Ð¥Ã¥Õ¥¡¤Ïdiff¤Ç¤¤Þ¤»¤ó" -#: ../diff.c:753 msgid "E810: Cannot read or write temp files" msgstr "E810: °ì»þ¥Õ¥¡¥¤¥ë¤ÎÆÉ¹þ¤â¤·¤¯¤Ï½ñ¹þ¤¬¤Ç¤¤Þ¤»¤ó" -#: ../diff.c:755 msgid "E97: Cannot create diffs" msgstr "E97: º¹Ê¬¤òºîÀ®¤Ç¤¤Þ¤»¤ó" -#: ../diff.c:966 +msgid "Patch file" +msgstr "¥Ñ¥Ã¥Á¥Õ¥¡¥¤¥ë" + msgid "E816: Cannot read patch output" msgstr "E816: patch¤Î½ÐÎϤòÆÉ¹þ¤á¤Þ¤»¤ó" -#: ../diff.c:1220 msgid "E98: Cannot read diff output" msgstr "E98: diff¤Î½ÐÎϤòÆÉ¹þ¤á¤Þ¤»¤ó" -#: ../diff.c:2081 msgid "E99: Current buffer is not in diff mode" msgstr "E99: ¸½ºß¤Î¥Ð¥Ã¥Õ¥¡¤Ïº¹Ê¬¥â¡¼¥É¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../diff.c:2100 msgid "E793: No other buffer in diff mode is modifiable" msgstr "E793: º¹Ê¬¥â¡¼¥É¤Ç¤¢¤ë¾¤Î¥Ð¥Ã¥Õ¥¡¤ÏÊѹ¹¤Ç¤¤Þ¤»¤ó" -#: ../diff.c:2102 msgid "E100: No other buffer in diff mode" msgstr "E100: º¹Ê¬¥â¡¼¥É¤Ç¤¢¤ë¾¤Î¥Ð¥Ã¥Õ¥¡¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../diff.c:2112 msgid "E101: More than two buffers in diff mode, don't know which one to use" msgstr "" "E101: º¹Ê¬¥â¡¼¥É¤Î¥Ð¥Ã¥Õ¥¡¤¬2¸Ä°Ê¾å¤¢¤ë¤Î¤Ç¡¢¤É¤ì¤ò»È¤¦¤«ÆÃÄê¤Ç¤¤Þ¤»¤ó" -#: ../diff.c:2141 #, c-format msgid "E102: Can't find buffer \"%s\"" msgstr "E102: ¥Ð¥Ã¥Õ¥¡ \"%s\" ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../diff.c:2152 #, c-format msgid "E103: Buffer \"%s\" is not in diff mode" msgstr "E103: ¥Ð¥Ã¥Õ¥¡ \"%s\" ¤Ïº¹Ê¬¥â¡¼¥É¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../diff.c:2193 msgid "E787: Buffer changed unexpectedly" msgstr "E787: ͽ´ü¤»¤º¥Ð¥Ã¥Õ¥¡¤¬Êѹ¹Êѹ¹¤µ¤ì¤Þ¤·¤¿" -#: ../digraph.c:1598 msgid "E104: Escape not allowed in digraph" msgstr "E104: ¹ç»ú¤ËEscape¤Ï»ÈÍѤǤ¤Þ¤»¤ó" -#: ../digraph.c:1760 msgid "E544: Keymap file not found" msgstr "E544: ¥¡¼¥Þ¥Ã¥×¥Õ¥¡¥¤¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../digraph.c:1785 msgid "E105: Using :loadkeymap not in a sourced file" msgstr "E105: :source ¤Ç¼è¹þ¤à¥Õ¥¡¥¤¥ë°Ê³°¤Ç¤Ï :loadkeymap ¤ò»È¤¨¤Þ¤»¤ó" -#: ../digraph.c:1821 msgid "E791: Empty keymap entry" msgstr "E791: ¶õ¤Î¥¡¼¥Þ¥Ã¥×¥¨¥ó¥È¥ê" -#: ../edit.c:82 msgid " Keyword completion (^N^P)" msgstr " ¥¡¼¥ï¡¼¥ÉÊä´° (^N^P)" #. ctrl_x_mode == 0, ^P/^N compl. -#: ../edit.c:83 msgid " ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" msgstr " ^X ¥â¡¼¥É (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" -#: ../edit.c:85 msgid " Whole line completion (^L^N^P)" msgstr " ¹Ô(Á´ÂÎ)Êä´° (^L^N^P)" -#: ../edit.c:86 msgid " File name completion (^F^N^P)" msgstr " ¥Õ¥¡¥¤¥ë̾Êä´° (^F^N^P)" -#: ../edit.c:87 msgid " Tag completion (^]^N^P)" msgstr " ¥¿¥°Êä´° (^]^N^P)" -#: ../edit.c:88 msgid " Path pattern completion (^N^P)" msgstr " ¥Ñ¥¹¥Ñ¥¿¡¼¥óÊä´° (^N^P)" -#: ../edit.c:89 msgid " Definition completion (^D^N^P)" msgstr " ÄêµÁÊä´° (^D^N^P)" -#: ../edit.c:91 msgid " Dictionary completion (^K^N^P)" msgstr " ¼½ñÊä´° (^K^N^P)" -#: ../edit.c:92 msgid " Thesaurus completion (^T^N^P)" msgstr " ¥·¥½¡¼¥é¥¹Êä´° (^T^N^P)" -#: ../edit.c:93 msgid " Command-line completion (^V^N^P)" msgstr " ¥³¥Þ¥ó¥É¥é¥¤¥óÊä´° (^V^N^P)" -#: ../edit.c:94 msgid " User defined completion (^U^N^P)" msgstr " ¥æ¡¼¥¶¡¼ÄêµÁÊä´° (^U^N^P)" -#: ../edit.c:95 msgid " Omni completion (^O^N^P)" msgstr " ¥ª¥à¥ËÊä´° (^O^N^P)" -#: ../edit.c:96 msgid " Spelling suggestion (s^N^P)" msgstr " Ä֤꽤Àµ¸õÊä (s^N^P)" -#: ../edit.c:97 msgid " Keyword Local completion (^N^P)" msgstr " ¶É½ê¥¡¼¥ï¡¼¥ÉÊä´° (^N^P)" -#: ../edit.c:100 msgid "Hit end of paragraph" msgstr "ÃÊÍî¤ÎºÇ¸å¤Ë¥Ò¥Ã¥È" -#: ../edit.c:101 msgid "E839: Completion function changed window" msgstr "E839: Êä´Ö´Ø¿ô¤¬¥¦¥£¥ó¥É¥¦¤òÊѹ¹¤·¤Þ¤·¤¿" -#: ../edit.c:102 msgid "E840: Completion function deleted text" msgstr "E840: Êä´°´Ø¿ô¤¬¥Æ¥¥¹¥È¤òºï½ü¤·¤Þ¤·¤¿" -#: ../edit.c:1847 msgid "'dictionary' option is empty" msgstr "'dictionary' ¥ª¥×¥·¥ç¥ó¤¬¶õ¤Ç¤¹" -#: ../edit.c:1848 msgid "'thesaurus' option is empty" msgstr "'thesaurus' ¥ª¥×¥·¥ç¥ó¤¬¶õ¤Ç¤¹" -#: ../edit.c:2655 #, c-format msgid "Scanning dictionary: %s" msgstr "¼½ñ¤ò¥¹¥¥ã¥óÃæ: %s" -#: ../edit.c:3079 msgid " (insert) Scroll (^E/^Y)" msgstr " (ÁÞÆþ) ¥¹¥¯¥í¡¼¥ë(^E/^Y)" -#: ../edit.c:3081 msgid " (replace) Scroll (^E/^Y)" msgstr " (ÃÖ´¹) ¥¹¥¯¥í¡¼¥ë (^E/^Y)" -#: ../edit.c:3587 #, c-format msgid "Scanning: %s" msgstr "¥¹¥¥ã¥óÃæ: %s" -#: ../edit.c:3614 msgid "Scanning tags." msgstr "¥¿¥°¤ò¥¹¥¥ã¥óÃæ." -#: ../edit.c:4519 msgid " Adding" msgstr " ÄɲÃÃæ" @@ -441,431 +438,161 @@ msgstr " ÄɲÃÃæ" #. * be called before line = ml_get(), or when this address is no #. * longer needed. -- Acevedo. #. -#: ../edit.c:4562 msgid "-- Searching..." msgstr "-- ¸¡º÷Ãæ..." -#: ../edit.c:4618 msgid "Back at original" msgstr "»Ï¤á¤ËÌá¤ë" -#: ../edit.c:4621 msgid "Word from other line" msgstr "¾¤Î¹Ô¤Îñ¸ì" -#: ../edit.c:4624 msgid "The only match" msgstr "Í£°ì¤Î³ºÅö" -#: ../edit.c:4680 #, c-format msgid "match %d of %d" msgstr "%d ÈÖÌܤγºÅö (Á´³ºÅö %d ¸ÄÃæ)" -#: ../edit.c:4684 #, c-format msgid "match %d" msgstr "%d ÈÖÌܤγºÅö" -#: ../eval.c:137 +#. maximum nesting of lists and dicts msgid "E18: Unexpected characters in :let" msgstr "E18: ͽ´ü¤»¤Ìʸ»ú¤¬ :let ¤Ë¤¢¤ê¤Þ¤·¤¿" -#: ../eval.c:138 -#, c-format -msgid "E684: list index out of range: %<PRId64>" -msgstr "E684: ¥ê¥¹¥È¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤¬Èϰϳ°¤Ç¤¹: %<PRId64>" - -#: ../eval.c:139 #, c-format msgid "E121: Undefined variable: %s" msgstr "E121: ̤ÄêµÁ¤ÎÊÑ¿ô¤Ç¤¹: %s" -#: ../eval.c:140 msgid "E111: Missing ']'" msgstr "E111: ']' ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../eval.c:141 -#, c-format -msgid "E686: Argument of %s must be a List" -msgstr "E686: %s ¤Î°ú¿ô¤Ï¥ê¥¹¥È·¿¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" - -#: ../eval.c:143 -#, c-format -msgid "E712: Argument of %s must be a List or Dictionary" -msgstr "E712: %s ¤Î°ú¿ô¤Ï¥ê¥¹¥È·¿¤Þ¤¿¤Ï¼½ñ·¿¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" - -#: ../eval.c:144 -msgid "E713: Cannot use empty key for Dictionary" -msgstr "E713: ¼½ñ·¿¤Ë¶õ¤Î¥¡¼¤ò»È¤¦¤³¤È¤Ï¤Ç¤¤Þ¤»¤ó" - -#: ../eval.c:145 -msgid "E714: List required" -msgstr "E714: ¥ê¥¹¥È·¿¤¬É¬ÍפǤ¹" - -#: ../eval.c:146 -msgid "E715: Dictionary required" -msgstr "E715: ¼½ñ·¿¤¬É¬ÍפǤ¹" - -#: ../eval.c:147 -#, c-format -msgid "E118: Too many arguments for function: %s" -msgstr "E118: ´Ø¿ô¤Î°ú¿ô¤¬Â¿²á¤®¤Þ¤¹: %s" - -#: ../eval.c:148 -#, c-format -msgid "E716: Key not present in Dictionary: %s" -msgstr "E716: ¼½ñ·¿¤Ë¥¡¼¤¬Â¸ºß¤·¤Þ¤»¤ó: %s" - -#: ../eval.c:150 -#, c-format -msgid "E122: Function %s already exists, add ! to replace it" -msgstr "E122: ´Ø¿ô %s ¤ÏÄêµÁºÑ¤Ç¤¹, ºÆÄêµÁ¤¹¤ë¤Ë¤Ï ! ¤òÄɲ䷤Ƥ¯¤À¤µ¤¤" - -#: ../eval.c:151 -msgid "E717: Dictionary entry already exists" -msgstr "E717: ¼½ñ·¿Æâ¤Ë¥¨¥ó¥È¥ê¤¬´û¤Ë¸ºß¤·¤Þ¤¹" - -#: ../eval.c:152 -msgid "E718: Funcref required" -msgstr "E718: ´Ø¿ô»²¾È·¿¤¬Í׵ᤵ¤ì¤Þ¤¹" - -#: ../eval.c:153 msgid "E719: Cannot use [:] with a Dictionary" msgstr "E719: [:] ¤ò¼½ñ·¿¤ÈÁȤ߹ç¤ï¤»¤Æ¤Ï»È¤¨¤Þ¤»¤ó" -#: ../eval.c:154 #, c-format msgid "E734: Wrong variable type for %s=" msgstr "E734: °Û¤Ê¤Ã¤¿·¿¤ÎÊÑ¿ô¤Ç¤¹ %s=" -#: ../eval.c:155 -#, c-format -msgid "E130: Unknown function: %s" -msgstr "E130: ̤ÃΤδؿô¤Ç¤¹: %s" - -#: ../eval.c:156 #, c-format msgid "E461: Illegal variable name: %s" msgstr "E461: ÉÔÀµ¤ÊÊÑ¿ô̾¤Ç¤¹: %s" -#: ../eval.c:157 msgid "E806: using Float as a String" msgstr "E806: ÉâÆ°¾®¿ôÅÀ¿ô¤òʸ»úÎó¤È¤·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹" -#: ../eval.c:1830 msgid "E687: Less targets than List items" msgstr "E687: ¥¿¡¼¥²¥Ã¥È¤¬¥ê¥¹¥È·¿Æâ¤ÎÍ×ÁǤè¤ê¤â¾¯¤Ê¤¤¤Ç¤¹" -#: ../eval.c:1834 msgid "E688: More targets than List items" msgstr "E688: ¥¿¡¼¥²¥Ã¥È¤¬¥ê¥¹¥È·¿Æâ¤ÎÍ×ÁǤè¤ê¤â¿¤¤¤Ç¤¹" -#: ../eval.c:1906 msgid "Double ; in list of variables" msgstr "¥ê¥¹¥È·¿¤ÎÃͤË2¤Ä°Ê¾å¤Î ; ¤¬¸¡½Ð¤µ¤ì¤Þ¤·¤¿" -#: ../eval.c:2078 #, c-format msgid "E738: Can't list variables for %s" msgstr "E738: %s ¤ÎÃͤò°ìÍ÷ɽ¼¨¤Ç¤¤Þ¤»¤ó" -#: ../eval.c:2391 msgid "E689: Can only index a List or Dictionary" msgstr "E689: ¥ê¥¹¥È·¿¤È¼½ñ·¿°Ê³°¤Ï¥¤¥ó¥Ç¥Ã¥¯¥¹»ØÄê¤Ç¤¤Þ¤»¤ó" -#: ../eval.c:2396 msgid "E708: [:] must come last" msgstr "E708: [:] ¤ÏºÇ¸å¤Ç¤Ê¤±¤ì¤Ð¤¤¤±¤Þ¤»¤ó" -#: ../eval.c:2439 msgid "E709: [:] requires a List value" msgstr "E709: [:] ¤Ë¤Ï¥ê¥¹¥È·¿¤ÎÃͤ¬É¬ÍפǤ¹" -#: ../eval.c:2674 msgid "E710: List value has more items than target" msgstr "E710: ¥ê¥¹¥È·¿ÊÑ¿ô¤Ë¥¿¡¼¥²¥Ã¥È¤è¤ê¤â¿¤¤Í×ÁǤ¬¤¢¤ê¤Þ¤¹" -#: ../eval.c:2678 msgid "E711: List value has not enough items" msgstr "E711: ¥ê¥¹¥È·¿ÊÑ¿ô¤Ë½½Ê¬¤Ê¿ô¤ÎÍ×ÁǤ¬¤¢¤ê¤Þ¤»¤ó" # -#: ../eval.c:2867 msgid "E690: Missing \"in\" after :for" msgstr "E690: :for ¤Î¸å¤Ë \"in\" ¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../eval.c:3063 -#, c-format -msgid "E107: Missing parentheses: %s" -msgstr "E107: ¥«¥Ã¥³ '(' ¤¬¤¢¤ê¤Þ¤»¤ó: %s" - -#: ../eval.c:3263 #, c-format msgid "E108: No such variable: \"%s\"" msgstr "E108: ¤½¤ÎÊÑ¿ô¤Ï¤¢¤ê¤Þ¤»¤ó: \"%s\"" -#: ../eval.c:3333 msgid "E743: variable nested too deep for (un)lock" msgstr "E743: (¥¢¥ó)¥í¥Ã¥¯¤¹¤ë¤Ë¤ÏÊÑ¿ô¤ÎÆþ¤ì»Ò¤¬¿¼²á¤®¤Þ¤¹" -#: ../eval.c:3630 msgid "E109: Missing ':' after '?'" msgstr "E109: '?' ¤Î¸å¤Ë ':' ¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../eval.c:3893 msgid "E691: Can only compare List with List" msgstr "E691: ¥ê¥¹¥È·¿¤Ï¥ê¥¹¥È·¿¤È¤·¤«Èæ³Ó¤Ç¤¤Þ¤»¤ó" -#: ../eval.c:3895 -msgid "E692: Invalid operation for Lists" +msgid "E692: Invalid operation for List" msgstr "E692: ¥ê¥¹¥È·¿¤Ë¤Ï̵¸ú¤ÊÁàºî¤Ç¤¹" -#: ../eval.c:3915 msgid "E735: Can only compare Dictionary with Dictionary" msgstr "E735: ¼½ñ·¿¤Ï¼½ñ·¿¤È¤·¤«Èæ³Ó¤Ç¤¤Þ¤»¤ó" -#: ../eval.c:3917 msgid "E736: Invalid operation for Dictionary" msgstr "E736: ¼½ñ·¿¤Ë¤Ï̵¸ú¤ÊÁàºî¤Ç¤¹" -#: ../eval.c:3932 -msgid "E693: Can only compare Funcref with Funcref" -msgstr "E693: ´Ø¿ô»²¾È·¿¤Ï´Ø¿ô»²¾È·¿¤È¤·¤«Èæ³Ó¤Ç¤¤Þ¤»¤ó" - -#: ../eval.c:3934 msgid "E694: Invalid operation for Funcrefs" msgstr "E694: ´Ø¿ô»²¾È·¿¤Ë¤Ï̵¸ú¤ÊÁàºî¤Ç¤¹" -#: ../eval.c:4277 msgid "E804: Cannot use '%' with Float" msgstr "E804: '%' ¤òÉâÆ°¾®¿ôÅÀ¿ô¤ÈÁȤ߹ç¤ï¤»¤Æ¤Ï»È¤¨¤Þ¤»¤ó" -#: ../eval.c:4478 msgid "E110: Missing ')'" msgstr "E110: ')' ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../eval.c:4609 msgid "E695: Cannot index a Funcref" msgstr "E695: ´Ø¿ô»²¾È·¿¤Ï¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ç¤¤Þ¤»¤ó" -#: ../eval.c:4839 +msgid "E909: Cannot index a special variable" +msgstr "E909: ÆÃ¼ìÊÑ¿ô¤Ï¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ç¤¤Þ¤»¤ó" + #, c-format msgid "E112: Option name missing: %s" msgstr "E112: ¥ª¥×¥·¥ç¥ó̾¤¬¤¢¤ê¤Þ¤»¤ó: %s" -#: ../eval.c:4855 #, c-format msgid "E113: Unknown option: %s" msgstr "E113: ̤ÃΤΥª¥×¥·¥ç¥ó¤Ç¤¹: %s" -#: ../eval.c:4904 #, c-format msgid "E114: Missing quote: %s" msgstr "E114: °úÍÑÉä (\") ¤¬¤¢¤ê¤Þ¤»¤ó: %s" -#: ../eval.c:5020 #, c-format msgid "E115: Missing quote: %s" msgstr "E115: °úÍÑÉä (') ¤¬¤¢¤ê¤Þ¤»¤ó: %s" -#: ../eval.c:5084 -#, c-format -msgid "E696: Missing comma in List: %s" -msgstr "E696: ¥ê¥¹¥È·¿¤Ë¥«¥ó¥Þ¤¬¤¢¤ê¤Þ¤»¤ó: %s" - -#: ../eval.c:5091 -#, c-format -msgid "E697: Missing end of List ']': %s" -msgstr "E697: ¥ê¥¹¥È·¿¤ÎºÇ¸å¤Ë ']' ¤¬¤¢¤ê¤Þ¤»¤ó: %s" - -#: ../eval.c:5807 msgid "Not enough memory to set references, garbage collection aborted!" msgstr "" "¥¬¡¼¥Ù¥Ã¥¸¥³¥ì¥¯¥·¥ç¥ó¤òÃæ»ß¤·¤Þ¤·¤¿! »²¾È¤òºîÀ®¤¹¤ë¤Î¤Ë¥á¥â¥ê¤¬ÉÔ¤·¤Þ¤·¤¿" -#: ../eval.c:6475 -#, c-format -msgid "E720: Missing colon in Dictionary: %s" -msgstr "E720: ¼½ñ·¿¤Ë¥³¥í¥ó¤¬¤¢¤ê¤Þ¤»¤ó: %s" - -#: ../eval.c:6499 -#, c-format -msgid "E721: Duplicate key in Dictionary: \"%s\"" -msgstr "E721: ¼½ñ·¿¤Ë½ÅÊ£¥¡¼¤¬¤¢¤ê¤Þ¤¹: \"%s\"" - -#: ../eval.c:6517 -#, c-format -msgid "E722: Missing comma in Dictionary: %s" -msgstr "E722: ¼½ñ·¿¤Ë¥«¥ó¥Þ¤¬¤¢¤ê¤Þ¤»¤ó: %s" - -#: ../eval.c:6524 -#, c-format -msgid "E723: Missing end of Dictionary '}': %s" -msgstr "E723: ¼½ñ·¿¤ÎºÇ¸å¤Ë '}' ¤¬¤¢¤ê¤Þ¤»¤ó: %s" - -#: ../eval.c:6555 msgid "E724: variable nested too deep for displaying" msgstr "E724: ɽ¼¨¤¹¤ë¤Ë¤ÏÊÑ¿ô¤ÎÆþ¤ì»Ò¤¬¿¼²á¤®¤Þ¤¹" -#: ../eval.c:7188 -#, c-format -msgid "E740: Too many arguments for function %s" -msgstr "E740: ´Ø¿ô¤Î°ú¿ô¤¬Â¿²á¤®¤Þ¤¹: %s" - -#: ../eval.c:7190 -#, c-format -msgid "E116: Invalid arguments for function %s" -msgstr "E116: ´Ø¿ô¤Î̵¸ú¤Ê°ú¿ô¤Ç¤¹: %s" - -#: ../eval.c:7377 -#, c-format -msgid "E117: Unknown function: %s" -msgstr "E117: ̤ÃΤδؿô¤Ç¤¹: %s" - -#: ../eval.c:7383 -#, c-format -msgid "E119: Not enough arguments for function: %s" -msgstr "E119: ´Ø¿ô¤Î°ú¿ô¤¬Â¤ê¤Þ¤»¤ó: %s" - -#: ../eval.c:7387 -#, c-format -msgid "E120: Using <SID> not in a script context: %s" -msgstr "E120: ¥¹¥¯¥ê¥×¥È°Ê³°¤Ç<SID>¤¬»È¤ï¤ì¤Þ¤·¤¿: %s" - -#: ../eval.c:7391 -#, c-format -msgid "E725: Calling dict function without Dictionary: %s" -msgstr "E725: ¼½ñÍÑ´Ø¿ô¤¬¸Æ¤Ð¤ì¤Þ¤·¤¿¤¬¼½ñ¤¬¤¢¤ê¤Þ¤»¤ó: %s" - -#: ../eval.c:7453 -msgid "E808: Number or Float required" -msgstr "E808: ¿ôÃͤ«ÉâÆ°¾®¿ôÅÀ¿ô¤¬É¬ÍפǤ¹" - -#: ../eval.c:7503 -msgid "add() argument" -msgstr "add() ¤Î°ú¿ô" - -#: ../eval.c:7907 -msgid "E699: Too many arguments" -msgstr "E699: °ú¿ô¤¬Â¿²á¤®¤Þ¤¹" - -#: ../eval.c:8073 -msgid "E785: complete() can only be used in Insert mode" -msgstr "E785: complete() ¤ÏÁÞÆþ¥â¡¼¥É¤Ç¤·¤«ÍøÍѤǤ¤Þ¤»¤ó" - -#: ../eval.c:8156 -msgid "&Ok" -msgstr "&Ok" - -#: ../eval.c:8676 -#, c-format -msgid "E737: Key already exists: %s" -msgstr "E737: ¥¡¼¤Ï´û¤Ë¸ºß¤·¤Þ¤¹: %s" - -#: ../eval.c:8692 -msgid "extend() argument" -msgstr "extend() ¤Î°ú¿ô" - -#: ../eval.c:8915 -msgid "map() argument" -msgstr "map() ¤Î°ú¿ô" - -#: ../eval.c:8916 -msgid "filter() argument" -msgstr "filter() ¤Î°ú¿ô" - -#: ../eval.c:9229 -#, c-format -msgid "+-%s%3ld lines: " -msgstr "+-%s%3ld ¹Ô: " - -#: ../eval.c:9291 -#, c-format -msgid "E700: Unknown function: %s" -msgstr "E700: ̤ÃΤδؿô¤Ç¤¹: %s" - -#: ../eval.c:10729 -msgid "called inputrestore() more often than inputsave()" -msgstr "inputrestore() ¤¬ inputsave() ¤è¤ê¤â¿¤¯¸Æ¤Ð¤ì¤Þ¤·¤¿" - -#: ../eval.c:10771 -msgid "insert() argument" -msgstr "insert() ¤Î°ú¿ô" - -#: ../eval.c:10841 -msgid "E786: Range not allowed" -msgstr "E786: ÈϰϻØÄê¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" - -#: ../eval.c:11140 -msgid "E701: Invalid type for len()" -msgstr "E701: len() ¤Ë¤Ï̵¸ú¤Ê·¿¤Ç¤¹" - -#: ../eval.c:11980 -msgid "E726: Stride is zero" -msgstr "E726: ¥¹¥È¥é¥¤¥É(Á°¿ÊÎÌ)¤¬ 0 ¤Ç¤¹" - -#: ../eval.c:11982 -msgid "E727: Start past end" -msgstr "E727: ³«»Ï°ÌÃÖ¤¬½ªÎ»°ÌÃÖ¤ò±Û¤¨¤Þ¤·¤¿" - -#: ../eval.c:12024 ../eval.c:15297 -msgid "<empty>" -msgstr "<¶õ>" - -#: ../eval.c:12282 -msgid "remove() argument" -msgstr "remove() ¤Î°ú¿ô" - -# Added at 10-Mar-2004. -#: ../eval.c:12466 -msgid "E655: Too many symbolic links (cycle?)" -msgstr "E655: ¥·¥ó¥Ü¥ê¥Ã¥¯¥ê¥ó¥¯¤¬Â¿²á¤®¤Þ¤¹ (½Û´Ä¤·¤Æ¤¤¤ë²ÄǽÀ¤¬¤¢¤ê¤Þ¤¹)" - -#: ../eval.c:12593 -msgid "reverse() argument" -msgstr "reverse() ¤Î°ú¿ô" - -#: ../eval.c:13721 -msgid "sort() argument" -msgstr "sort() ¤Î°ú¿ô" - -#: ../eval.c:13721 -msgid "uniq() argument" -msgstr "uniq() ¤Î°ú¿ô" - -#: ../eval.c:13776 -msgid "E702: Sort compare function failed" -msgstr "E702: ¥½¡¼¥È¤ÎÈæ³Ó´Ø¿ô¤¬¼ºÇÔ¤·¤Þ¤·¤¿" - -#: ../eval.c:13806 -msgid "E882: Uniq compare function failed" -msgstr "E882: Uniq ¤ÎÈæ³Ó´Ø¿ô¤¬¼ºÇÔ¤·¤Þ¤·¤¿" - -#: ../eval.c:14085 -msgid "(Invalid)" -msgstr "(̵¸ú)" - -#: ../eval.c:14590 -msgid "E677: Error writing temp file" -msgstr "E677: °ì»þ¥Õ¥¡¥¤¥ë½ñ¹þÃæ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤Þ¤·¤¿" - -#: ../eval.c:16159 msgid "E805: Using a Float as a Number" msgstr "E805: ÉâÆ°¾®¿ôÅÀ¿ô¤ò¿ôÃͤȤ·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹" -#: ../eval.c:16162 msgid "E703: Using a Funcref as a Number" msgstr "E703: ´Ø¿ô»²¾È·¿¤ò¿ôÃͤȤ·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹¡£" -#: ../eval.c:16170 msgid "E745: Using a List as a Number" msgstr "E745: ¥ê¥¹¥È·¿¤ò¿ôÃͤȤ·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹" -#: ../eval.c:16173 msgid "E728: Using a Dictionary as a Number" msgstr "E728: ¼½ñ·¿¤ò¿ôÃͤȤ·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹" +msgid "E910: Using a Job as a Number" +msgstr "E910: ¥¸¥ç¥Ö¤ò¿ôÃͤȤ·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹" + +msgid "E913: Using a Channel as a Number" +msgstr "E913: ¥Á¥ã¥ó¥Í¥ë¤ò¿ôÃͤȤ·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹¡£" + msgid "E891: Using a Funcref as a Float" msgstr "E891: ´Ø¿ô»²¾È·¿¤òÉâÆ°¾®¿ôÅÀ¿ô¤È¤·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹¡£" @@ -878,265 +605,280 @@ msgstr "E893: ¥ê¥¹¥È·¿¤òÉâÆ°¾®¿ôÅÀ¿ô¤È¤·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹" msgid "E894: Using a Dictionary as a Float" msgstr "E894: ¼½ñ·¿¤òÉâÆ°¾®¿ôÅÀ¿ô¤È¤·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹" -#: ../eval.c:16259 +msgid "E907: Using a special value as a Float" +msgstr "E907: ÆÃ¼ìÃͤòÉâÆ°¾®¿ôÅÀ¿ô¤È¤·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹" + +msgid "E911: Using a Job as a Float" +msgstr "E911: ¥¸¥ç¥Ö¤òÉâÆ°¾®¿ôÅÀ¿ô¤È¤·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹" + +msgid "E914: Using a Channel as a Float" +msgstr "E914: ¥Á¥ã¥ó¥Í¥ë¤òÉâÆ°¾®¿ôÅÀ¿ô¤È¤·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹¡£" + msgid "E729: using Funcref as a String" msgstr "E729: ´Ø¿ô»²¾È·¿¤òʸ»úÎó¤È¤·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹" -#: ../eval.c:16262 msgid "E730: using List as a String" msgstr "E730: ¥ê¥¹¥È·¿¤òʸ»úÎó¤È¤·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹" -#: ../eval.c:16265 msgid "E731: using Dictionary as a String" msgstr "E731: ¼½ñ·¿¤òʸ»úÎó¤È¤·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹" -#: ../eval.c:16619 -#, c-format -msgid "E706: Variable type mismatch for: %s" -msgstr "E706: ÊÑ¿ô¤Î·¿¤¬°ìÃפ·¤Þ¤»¤ó: %s" +msgid "E908: using an invalid value as a String" +msgstr "E908: ̵¸ú¤ÊÃͤòʸ»úÎó¤È¤·¤Æ°·¤Ã¤Æ¤¤¤Þ¤¹" -#: ../eval.c:16705 #, c-format msgid "E795: Cannot delete variable %s" msgstr "E795: ÊÑ¿ô %s ¤òºï½ü¤Ç¤¤Þ¤»¤ó" -#: ../eval.c:16724 #, c-format msgid "E704: Funcref variable name must start with a capital: %s" msgstr "E704: ´Ø¿ô»²¾È·¿ÊÑ¿ô̾¤ÏÂçʸ»ú¤Ç»Ï¤Þ¤é¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó: %s" -#: ../eval.c:16732 #, c-format msgid "E705: Variable name conflicts with existing function: %s" msgstr "E705: ÊÑ¿ô̾¤¬´û¸¤Î´Ø¿ô̾¤È¾×ÆÍ¤·¤Þ¤¹: %s" -#: ../eval.c:16763 #, c-format msgid "E741: Value is locked: %s" msgstr "E741: Ãͤ¬¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤Þ¤¹: %s" -#: ../eval.c:16764 ../eval.c:16769 ../message.c:1839 msgid "Unknown" msgstr "ÉÔÌÀ" -#: ../eval.c:16768 #, c-format msgid "E742: Cannot change value of %s" msgstr "E742: %s ¤ÎÃͤòÊѹ¹¤Ç¤¤Þ¤»¤ó" -#: ../eval.c:16838 msgid "E698: variable nested too deep for making a copy" msgstr "E698: ¥³¥Ô¡¼¤ò¼è¤ë¤Ë¤ÏÊÑ¿ô¤ÎÆþ¤ì»Ò¤¬¿¼²á¤®¤Þ¤¹" -#: ../eval.c:17249 -#, c-format -msgid "E123: Undefined function: %s" -msgstr "E123: ̤ÄêµÁ¤Î´Ø¿ô¤Ç¤¹: %s" +msgid "" +"\n" +"# global variables:\n" +msgstr "" +"\n" +"# ¥°¥í¡¼¥Ð¥ëÊÑ¿ô:\n" -#: ../eval.c:17260 -#, c-format -msgid "E124: Missing '(': %s" -msgstr "E124: '(' ¤¬¤¢¤ê¤Þ¤»¤ó: %s" +msgid "" +"\n" +"\tLast set from " +msgstr "" +"\n" +"\tºÇ¸å¤Ë¥»¥Ã¥È¤·¤¿¥¹¥¯¥ê¥×¥È: " -#: ../eval.c:17293 -msgid "E862: Cannot use g: here" -msgstr "E862: ¤³¤³¤Ç¤Ï g: ¤Ï»È¤¨¤Þ¤»¤ó" +msgid "map() argument" +msgstr "map() ¤Î°ú¿ô" -#: ../eval.c:17312 -#, c-format -msgid "E125: Illegal argument: %s" -msgstr "E125: ÉÔÀµ¤Ê°ú¿ô¤Ç¤¹: %s" +msgid "filter() argument" +msgstr "filter() ¤Î°ú¿ô" -#: ../eval.c:17323 #, c-format -msgid "E853: Duplicate argument name: %s" -msgstr "E853: °ú¿ô̾¤¬½ÅÊ£¤·¤Æ¤¤¤Þ¤¹: %s" +msgid "E686: Argument of %s must be a List" +msgstr "E686: %s ¤Î°ú¿ô¤Ï¥ê¥¹¥È·¿¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" -#: ../eval.c:17416 -msgid "E126: Missing :endfunction" -msgstr "E126: :endfunction ¤¬¤¢¤ê¤Þ¤»¤ó" +msgid "E928: String required" +msgstr "E928: ʸ»úÎó¤¬É¬ÍפǤ¹" -#: ../eval.c:17537 -#, c-format -msgid "E707: Function name conflicts with variable: %s" -msgstr "E707: ´Ø¿ô̾¤¬ÊÑ¿ô̾¤È¾×ÆÍ¤·¤Þ¤¹: %s" +msgid "E808: Number or Float required" +msgstr "E808: ¿ôÃͤ«ÉâÆ°¾®¿ôÅÀ¿ô¤¬É¬ÍפǤ¹" -#: ../eval.c:17549 -#, c-format -msgid "E127: Cannot redefine function %s: It is in use" -msgstr "E127: ´Ø¿ô %s ¤òºÆÄêµÁ¤Ç¤¤Þ¤»¤ó: »ÈÍÑÃæ¤Ç¤¹" +msgid "add() argument" +msgstr "add() ¤Î°ú¿ô" -#: ../eval.c:17604 -#, c-format -msgid "E746: Function name does not match script file name: %s" -msgstr "E746: ´Ø¿ô̾¤¬¥¹¥¯¥ê¥×¥È¤Î¥Õ¥¡¥¤¥ë̾¤È°ìÃפ·¤Þ¤»¤ó: %s" +msgid "E785: complete() can only be used in Insert mode" +msgstr "E785: complete() ¤ÏÁÞÆþ¥â¡¼¥É¤Ç¤·¤«ÍøÍѤǤ¤Þ¤»¤ó" -#: ../eval.c:17716 -msgid "E129: Function name required" -msgstr "E129: ´Ø¿ô̾¤¬Í׵ᤵ¤ì¤Þ¤¹" +#. +#. * Yes this is ugly, I don't particularly like it either. But doing it +#. * this way has the compelling advantage that translations need not to +#. * be touched at all. See below what 'ok' and 'ync' are used for. +#. +msgid "&Ok" +msgstr "&Ok" -#: ../eval.c:17824 #, c-format -msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "E128: ´Ø¿ô̾¤ÏÂçʸ»ú¤« \"s:\" ¤Ç»Ï¤Þ¤é¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó: %s" +msgid "+-%s%3ld line: " +msgid_plural "+-%s%3ld lines: " +msgstr[0] "+-%s%3ld ¹Ô: " -#: ../eval.c:17833 #, c-format -msgid "E884: Function name cannot contain a colon: %s" -msgstr "E884: ´Ø¿ô̾¤Ë¤Ï¥³¥í¥ó¤Ï´Þ¤á¤é¤ì¤Þ¤»¤ó: %s" +msgid "E700: Unknown function: %s" +msgstr "E700: ̤ÃΤδؿô¤Ç¤¹: %s" -#: ../eval.c:18336 -#, c-format -msgid "E131: Cannot delete function %s: It is in use" -msgstr "E131: ´Ø¿ô %s ¤òºï½ü¤Ç¤¤Þ¤»¤ó: »ÈÍÑÃæ¤Ç¤¹" +msgid "E922: expected a dict" +msgstr "E922: ¼½ñ¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤Þ¤¹" -#: ../eval.c:18441 -msgid "E132: Function call depth is higher than 'maxfuncdepth'" -msgstr "E132: ´Ø¿ô¸Æ½Ð¤ÎÆþ¤ì»Ò¿ô¤¬ 'maxfuncdepth' ¤òͤ¨¤Þ¤·¤¿" +msgid "E923: Second argument of function() must be a list or a dict" +msgstr "E923: function() ¤ÎÂè 2 °ú¿ô¤Ï¥ê¥¹¥È·¿¤Þ¤¿¤Ï¼½ñ·¿¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" -#: ../eval.c:18568 -#, c-format -msgid "calling %s" -msgstr "%s ¤ò¼Â¹ÔÃæ¤Ç¤¹" +msgid "" +"&OK\n" +"&Cancel" +msgstr "" +"·èÄê(&O)\n" +"¥¥ã¥ó¥»¥ë(&C)" -#: ../eval.c:18651 -#, c-format -msgid "%s aborted" -msgstr "%s ¤¬ÃæÃǤµ¤ì¤Þ¤·¤¿" +msgid "called inputrestore() more often than inputsave()" +msgstr "inputrestore() ¤¬ inputsave() ¤è¤ê¤â¿¤¯¸Æ¤Ð¤ì¤Þ¤·¤¿" + +msgid "insert() argument" +msgstr "insert() ¤Î°ú¿ô" + +msgid "E786: Range not allowed" +msgstr "E786: ÈϰϻØÄê¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" + +msgid "E916: not a valid job" +msgstr "E916: ͸ú¤Ê¥¸¥ç¥Ö¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó" + +msgid "E701: Invalid type for len()" +msgstr "E701: len() ¤Ë¤Ï̵¸ú¤Ê·¿¤Ç¤¹" -#: ../eval.c:18653 #, c-format -msgid "%s returning #%<PRId64>" -msgstr "%s ¤¬ #%<PRId64> ¤òÊÖ¤·¤Þ¤·¤¿" +msgid "E798: ID is reserved for \":match\": %ld" +msgstr "E798: ID ¤Ï \":match\" ¤Î¤¿¤á¤ËͽÌó¤µ¤ì¤Æ¤¤¤Þ¤¹: %ld" + +msgid "E726: Stride is zero" +msgstr "E726: ¥¹¥È¥é¥¤¥É(Á°¿ÊÎÌ)¤¬ 0 ¤Ç¤¹" + +msgid "E727: Start past end" +msgstr "E727: ³«»Ï°ÌÃÖ¤¬½ªÎ»°ÌÃÖ¤ò±Û¤¨¤Þ¤·¤¿" + +msgid "<empty>" +msgstr "<¶õ>" + +msgid "E240: No connection to Vim server" +msgstr "E240: Vim ¥µ¡¼¥Ð¡¼¤Ø¤ÎÀܳ¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../eval.c:18670 #, c-format -msgid "%s returning %s" -msgstr "%s ¤¬ %s ¤òÊÖ¤·¤Þ¤·¤¿" +msgid "E241: Unable to send to %s" +msgstr "E241: %s ¤ØÁ÷¤ë¤³¤È¤¬¤Ç¤¤Þ¤»¤ó" + +msgid "E277: Unable to read a server reply" +msgstr "E277: ¥µ¡¼¥Ð¡¼¤Î±þÅú¤¬¤¢¤ê¤Þ¤»¤ó" + +msgid "remove() argument" +msgstr "remove() ¤Î°ú¿ô" + +# Added at 10-Mar-2004. +msgid "E655: Too many symbolic links (cycle?)" +msgstr "E655: ¥·¥ó¥Ü¥ê¥Ã¥¯¥ê¥ó¥¯¤¬Â¿²á¤®¤Þ¤¹ (½Û´Ä¤·¤Æ¤¤¤ë²ÄǽÀ¤¬¤¢¤ê¤Þ¤¹)" + +msgid "reverse() argument" +msgstr "reverse() ¤Î°ú¿ô" + +msgid "E258: Unable to send to client" +msgstr "E258: ¥¯¥é¥¤¥¢¥ó¥È¤ØÁ÷¤ë¤³¤È¤¬¤Ç¤¤Þ¤»¤ó" -#: ../eval.c:18691 ../ex_cmds2.c:2695 #, c-format -msgid "continuing in %s" -msgstr "%s ¤Î¼Â¹Ô¤ò·ÑÂ³Ãæ¤Ç¤¹" +msgid "E927: Invalid action: '%s'" +msgstr "E927: ̵¸ú¤ÊÁàºî¤Ç¤¹: %s" -#: ../eval.c:18795 -msgid "E133: :return not inside a function" -msgstr "E133: ´Ø¿ô³°¤Ë :return ¤¬¤¢¤ê¤Þ¤·¤¿" +msgid "sort() argument" +msgstr "sort() ¤Î°ú¿ô" -#: ../eval.c:19159 -msgid "" -"\n" -"# global variables:\n" -msgstr "" -"\n" -"# ¥°¥í¡¼¥Ð¥ëÊÑ¿ô:\n" +msgid "uniq() argument" +msgstr "uniq() ¤Î°ú¿ô" -#: ../eval.c:19254 -msgid "" -"\n" -"\tLast set from " -msgstr "" -"\n" -"\tLast set from " +msgid "E702: Sort compare function failed" +msgstr "E702: ¥½¡¼¥È¤ÎÈæ³Ó´Ø¿ô¤¬¼ºÇÔ¤·¤Þ¤·¤¿" -#: ../eval.c:19272 -msgid "No old files" -msgstr "¸Å¤¤¥Õ¥¡¥¤¥ë¤Ï¤¢¤ê¤Þ¤»¤ó" +msgid "E882: Uniq compare function failed" +msgstr "E882: Uniq ¤ÎÈæ³Ó´Ø¿ô¤¬¼ºÇÔ¤·¤Þ¤·¤¿" + +msgid "(Invalid)" +msgstr "(̵¸ú)" + +#, c-format +msgid "E935: invalid submatch number: %d" +msgstr "E935: ̵¸ú¤Ê¥µ¥Ö¥Þ¥Ã¥ÁÈÖ¹æ: %d" + +msgid "E677: Error writing temp file" +msgstr "E677: °ì»þ¥Õ¥¡¥¤¥ë½ñ¹þÃæ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤Þ¤·¤¿" + +msgid "E921: Invalid callback argument" +msgstr "E921: ̵¸ú¤Ê¥³¡¼¥ë¥Ð¥Ã¥¯°ú¿ô¤Ç¤¹" -#: ../ex_cmds.c:122 #, c-format msgid "<%s>%s%s %d, Hex %02x, Octal %03o" msgstr "<%s>%s%s %d, 16¿Ê¿ô %02x, 8¿Ê¿ô %03o" -#: ../ex_cmds.c:145 #, c-format msgid "> %d, Hex %04x, Octal %o" msgstr "> %d, 16¿Ê¿ô %04x, 8¿Ê¿ô %o" -#: ../ex_cmds.c:146 #, c-format msgid "> %d, Hex %08x, Octal %o" msgstr "> %d, 16¿Ê¿ô %08x, 8¿Ê¿ô %o" -#: ../ex_cmds.c:684 msgid "E134: Move lines into themselves" msgstr "E134: ¹Ô¤ò¤½¤ì¼«¿È¤Ë¤Ï°Üư¤Ç¤¤Þ¤»¤ó" -#: ../ex_cmds.c:747 msgid "1 line moved" msgstr "1 ¹Ô¤¬°Üư¤µ¤ì¤Þ¤·¤¿" -#: ../ex_cmds.c:749 #, c-format -msgid "%<PRId64> lines moved" -msgstr "%<PRId64> ¹Ô¤¬°Üư¤µ¤ì¤Þ¤·¤¿" +msgid "%ld lines moved" +msgstr "%ld ¹Ô¤¬°Üư¤µ¤ì¤Þ¤·¤¿" -#: ../ex_cmds.c:1175 #, c-format -msgid "%<PRId64> lines filtered" -msgstr "%<PRId64> ¹Ô¤¬¥Õ¥£¥ë¥¿½èÍý¤µ¤ì¤Þ¤·¤¿" +msgid "%ld lines filtered" +msgstr "%ld ¹Ô¤¬¥Õ¥£¥ë¥¿½èÍý¤µ¤ì¤Þ¤·¤¿" -#: ../ex_cmds.c:1194 msgid "E135: *Filter* Autocommands must not change current buffer" msgstr "E135: *¥Õ¥£¥ë¥¿* autocommand¤Ï¸½ºß¤Î¥Ð¥Ã¥Õ¥¡¤òÊѹ¹¤·¤Æ¤Ï¤¤¤±¤Þ¤»¤ó" -#: ../ex_cmds.c:1244 msgid "[No write since last change]\n" msgstr "[ºÇ¸å¤ÎÊѹ¹¤¬Êݸ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó]\n" -#: ../ex_cmds.c:1424 #, c-format msgid "%sviminfo: %s in line: " msgstr "%sviminfo: %s ¹ÔÌÜ: " -#: ../ex_cmds.c:1431 msgid "E136: viminfo: Too many errors, skipping rest of file" msgstr "E136: viminfo: ¥¨¥é¡¼¤¬Â¿²á¤®¤ë¤Î¤Ç, °Ê¹ß¤Ï¥¹¥¥Ã¥×¤·¤Þ¤¹" -#: ../ex_cmds.c:1458 #, c-format msgid "Reading viminfo file \"%s\"%s%s%s" msgstr "viminfo¥Õ¥¡¥¤¥ë \"%s\"%s%s%s ¤òÆÉ¹þ¤ßÃæ" -#: ../ex_cmds.c:1460 msgid " info" msgstr " ¾ðÊó" -#: ../ex_cmds.c:1461 msgid " marks" msgstr " ¥Þ¡¼¥¯" -#: ../ex_cmds.c:1462 msgid " oldfiles" msgstr " µì¥Õ¥¡¥¤¥ë·²" -#: ../ex_cmds.c:1463 msgid " FAILED" msgstr " ¼ºÇÔ" #. avoid a wait_return for this message, it's annoying -#: ../ex_cmds.c:1541 #, c-format msgid "E137: Viminfo file is not writable: %s" msgstr "E137: viminfo¥Õ¥¡¥¤¥ë¤¬½ñ¹þ¤ß¤Ç¤¤Þ¤»¤ó: %s" -#: ../ex_cmds.c:1626 +#, c-format +msgid "E929: Too many viminfo temp files, like %s!" +msgstr "E929: °ì»þviminfo¥Õ¥¡¥¤¥ë¤¬Â¿²á¤®¤Þ¤¹! Îã: %s" + #, c-format msgid "E138: Can't write viminfo file %s!" msgstr "E138: viminfo¥Õ¥¡¥¤¥ë %s ¤òÊݸ¤Ç¤¤Þ¤»¤ó!" -#: ../ex_cmds.c:1635 #, c-format msgid "Writing viminfo file \"%s\"" msgstr "viminfo¥Õ¥¡¥¤¥ë \"%s\" ¤ò½ñ¹þ¤ßÃæ" +#, c-format +msgid "E886: Can't rename viminfo file to %s!" +msgstr "E886: viminfo¥Õ¥¡¥¤¥ë¤ò %s ¤ØÌ¾Á°Êѹ¹¤Ç¤¤Þ¤»¤ó!" + #. Write the info: -#: ../ex_cmds.c:1720 #, c-format msgid "# This viminfo file was generated by Vim %s.\n" msgstr "# ¤³¤Î viminfo ¥Õ¥¡¥¤¥ë¤Ï Vim %s ¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Þ¤·¤¿.\n" -#: ../ex_cmds.c:1722 msgid "" "# You may edit it if you're careful!\n" "\n" @@ -1144,47 +886,47 @@ msgstr "" "# Êѹ¹¤¹¤ëºÝ¤Ë¤Ï½½Ê¬Ãí°Õ¤·¤Æ¤¯¤À¤µ¤¤!\n" "\n" -#: ../ex_cmds.c:1723 msgid "# Value of 'encoding' when this file was written\n" msgstr "# ¤³¤Î¥Õ¥¡¥¤¥ë¤¬½ñ¤«¤ì¤¿»þ¤Î 'encoding' ¤ÎÃÍ\n" -#: ../ex_cmds.c:1800 msgid "Illegal starting char" msgstr "ÉÔÀµ¤ÊÀèÆ¬Ê¸»ú¤Ç¤¹" -#: ../ex_cmds.c:2162 +msgid "" +"\n" +"# Bar lines, copied verbatim:\n" +msgstr "" +"\n" +"# '|' ¤Ç»Ï¤Þ¤ë¹Ô¤Î¡¢Ê¸»úÄ̤ê¤Î¥³¥Ô¡¼:\n" + +msgid "Save As" +msgstr "ÊÌ̾¤ÇÊݸ" + msgid "Write partial file?" msgstr "¥Õ¥¡¥¤¥ë¤òÉôʬŪ¤ËÊݸ¤·¤Þ¤¹¤«?" -#: ../ex_cmds.c:2166 msgid "E140: Use ! to write partial buffer" msgstr "E140: ¥Ð¥Ã¥Õ¥¡¤òÉôʬŪ¤ËÊݸ¤¹¤ë¤Ë¤Ï ! ¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤" -#: ../ex_cmds.c:2281 #, c-format msgid "Overwrite existing file \"%s\"?" msgstr "´û¸¤Î¥Õ¥¡¥¤¥ë \"%s\" ¤ò¾å½ñ¤¤·¤Þ¤¹¤«?" -#: ../ex_cmds.c:2317 #, c-format msgid "Swap file \"%s\" exists, overwrite anyway?" msgstr "¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë \"%s\" ¤¬Â¸ºß¤·¤Þ¤¹. ¾å½ñ¤¤ò¶¯À©¤·¤Þ¤¹¤«?" -#: ../ex_cmds.c:2326 #, c-format msgid "E768: Swap file exists: %s (:silent! overrides)" msgstr "E768: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤·¤Þ¤¹: %s (:silent! ¤òÄɲäǾå½ñ)" -#: ../ex_cmds.c:2381 #, c-format -msgid "E141: No file name for buffer %<PRId64>" -msgstr "E141: ¥Ð¥Ã¥Õ¥¡ %<PRId64> ¤Ë¤Ï̾Á°¤¬¤¢¤ê¤Þ¤»¤ó" +msgid "E141: No file name for buffer %ld" +msgstr "E141: ¥Ð¥Ã¥Õ¥¡ %ld ¤Ë¤Ï̾Á°¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../ex_cmds.c:2412 msgid "E142: File not written: Writing is disabled by 'write' option" msgstr "E142: ¥Õ¥¡¥¤¥ë¤ÏÊݸ¤µ¤ì¤Þ¤»¤ó¤Ç¤·¤¿: 'write' ¥ª¥×¥·¥ç¥ó¤Ë¤è¤ê̵¸ú¤Ç¤¹" -#: ../ex_cmds.c:2434 #, c-format msgid "" "'readonly' option is set for \"%s\".\n" @@ -1193,7 +935,6 @@ msgstr "" "\"%s\" ¤Ë¤Ï 'readonly' ¥ª¥×¥·¥ç¥ó¤¬ÀßÄꤵ¤ì¤Æ¤¤¤Þ¤¹.\n" "¾å½ñ¤¶¯À©¤ò¤·¤Þ¤¹¤«?" -#: ../ex_cmds.c:2439 #, c-format msgid "" "File permissions of \"%s\" are read-only.\n" @@ -1204,83 +945,68 @@ msgstr "" "¤½¤ì¤Ç¤â¶²¤é¤¯½ñ¤¹þ¤à¤³¤È¤Ï²Äǽ¤Ç¤¹.\n" "·Ñ³¤·¤Þ¤¹¤«?" -#: ../ex_cmds.c:2451 #, c-format msgid "E505: \"%s\" is read-only (add ! to override)" msgstr "E505: \"%s\" ¤ÏÆÉ¹þÀìÍѤǤ¹ (¶¯À©½ñ¹þ¤Ë¤Ï ! ¤òÄɲÃ)" -#: ../ex_cmds.c:3120 +msgid "Edit File" +msgstr "¥Õ¥¡¥¤¥ë¤òÊÔ½¸" + #, c-format msgid "E143: Autocommands unexpectedly deleted new buffer %s" msgstr "E143: autocommand¤¬Í½´ü¤»¤º¿·¤·¤¤¥Ð¥Ã¥Õ¥¡ %s ¤òºï½ü¤·¤Þ¤·¤¿" -#: ../ex_cmds.c:3313 msgid "E144: non-numeric argument to :z" msgstr "E144: ¿ô¤Ç¤Ï¤Ê¤¤°ú¿ô¤¬ :z ¤ËÅϤµ¤ì¤Þ¤·¤¿" -#: ../ex_cmds.c:3404 msgid "E145: Shell commands not allowed in rvim" msgstr "E145: rvim¤Ç¤Ï¥·¥§¥ë¥³¥Þ¥ó¥É¤ò»È¤¨¤Þ¤»¤ó" -#: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Àµµ¬É½¸½¤Ïʸ»ú¤Ç¶èÀڤ뤳¤È¤¬¤Ç¤¤Þ¤»¤ó" -#: ../ex_cmds.c:3964 #, c-format msgid "replace with %s (y/n/a/q/l/^E/^Y)?" msgstr "%s ¤ËÃÖ´¹¤·¤Þ¤¹¤«? (y/n/a/q/l/^E/^Y)" -#: ../ex_cmds.c:4379 msgid "(Interrupted) " msgstr "(³ä¹þ¤Þ¤ì¤Þ¤·¤¿) " -#: ../ex_cmds.c:4384 msgid "1 match" msgstr "1 ²Õ½ê³ºÅö¤·¤Þ¤·¤¿" -#: ../ex_cmds.c:4384 msgid "1 substitution" msgstr "1 ²Õ½êÃÖ´¹¤·¤Þ¤·¤¿" -#: ../ex_cmds.c:4387 #, c-format -msgid "%<PRId64> matches" -msgstr "%<PRId64> ²Õ½ê³ºÅö¤·¤Þ¤·¤¿" +msgid "%ld matches" +msgstr "%ld ²Õ½ê³ºÅö¤·¤Þ¤·¤¿" -#: ../ex_cmds.c:4388 #, c-format -msgid "%<PRId64> substitutions" -msgstr "%<PRId64> ²Õ½êÃÖ´¹¤·¤Þ¤·¤¿" +msgid "%ld substitutions" +msgstr "%ld ²Õ½êÃÖ´¹¤·¤Þ¤·¤¿" -#: ../ex_cmds.c:4392 msgid " on 1 line" msgstr " (·× 1 ¹ÔÆâ)" -#: ../ex_cmds.c:4395 #, c-format -msgid " on %<PRId64> lines" -msgstr " (·× %<PRId64> ¹ÔÆâ)" +msgid " on %ld lines" +msgstr " (·× %ld ¹ÔÆâ)" -#: ../ex_cmds.c:4438 msgid "E147: Cannot do :global recursive" msgstr "E147: :global ¤òºÆµ¢Åª¤Ë¤Ï»È¤¨¤Þ¤»¤ó" -#: ../ex_cmds.c:4467 msgid "E148: Regular expression missing from global" msgstr "E148: global¥³¥Þ¥ó¥É¤ËÀµµ¬É½¸½¤¬»ØÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó" -#: ../ex_cmds.c:4508 #, c-format msgid "Pattern found in every line: %s" msgstr "¥Ñ¥¿¡¼¥ó¤¬Á´¤Æ¤Î¹Ô¤Ç¸«¤Ä¤«¤ê¤Þ¤·¤¿: %s" -#: ../ex_cmds.c:4510 #, c-format msgid "Pattern not found: %s" msgstr "¥Ñ¥¿¡¼¥ó¤Ï¸«¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿: %s" -#: ../ex_cmds.c:4587 msgid "" "\n" "# Last Substitute String:\n" @@ -1290,110 +1016,102 @@ msgstr "" "# ºÇ¸å¤ËÃÖ´¹¤µ¤ì¤¿Ê¸»úÎó:\n" "$" -#: ../ex_cmds.c:4679 msgid "E478: Don't panic!" msgstr "E478: ¹²¤Æ¤Ê¤¤¤Ç¤¯¤À¤µ¤¤" -#: ../ex_cmds.c:4717 #, c-format msgid "E661: Sorry, no '%s' help for %s" msgstr "E661: »Äǰ¤Ç¤¹¤¬ '%s' ¤Î¥Ø¥ë¥×¤¬ %s ¤Ë¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../ex_cmds.c:4719 #, c-format msgid "E149: Sorry, no help for %s" msgstr "E149: »Äǰ¤Ç¤¹¤¬ %s ¤Ë¤Ï¥Ø¥ë¥×¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../ex_cmds.c:4751 #, c-format msgid "Sorry, help file \"%s\" not found" msgstr "»Äǰ¤Ç¤¹¤¬¥Ø¥ë¥×¥Õ¥¡¥¤¥ë \"%s\" ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../ex_cmds.c:5323 #, c-format -msgid "E150: Not a directory: %s" -msgstr "E150: ¥Ç¥£¥ì¥¯¥È¥ê¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó: %s" +msgid "E151: No match: %s" +msgstr "E151: ¥Þ¥Ã¥Á¤Ï¤¢¤ê¤Þ¤»¤ó: %s" -#: ../ex_cmds.c:5446 #, c-format msgid "E152: Cannot open %s for writing" msgstr "E152: ½ñ¹þ¤ßÍÑ¤Ë %s ¤ò³«¤±¤Þ¤»¤ó" -#: ../ex_cmds.c:5471 #, c-format msgid "E153: Unable to open %s for reading" msgstr "E153: ÆÉ¹þÍÑ¤Ë %s ¤ò³«¤±¤Þ¤»¤ó" # Added at 29-Apr-2004. -#: ../ex_cmds.c:5500 #, c-format msgid "E670: Mix of help file encodings within a language: %s" msgstr "E670: 1¤Ä¤Î¸À¸ì¤Î¥Ø¥ë¥×¥Õ¥¡¥¤¥ë¤ËÊ£¿ô¤Î¥¨¥ó¥³¡¼¥É¤¬º®ºß¤·¤Æ¤¤¤Þ¤¹: %s" -#: ../ex_cmds.c:5565 #, c-format msgid "E154: Duplicate tag \"%s\" in file %s/%s" msgstr "E154: ¥¿¥° \"%s\" ¤¬¥Õ¥¡¥¤¥ë %s/%s ¤Ë½ÅÊ£¤·¤Æ¤¤¤Þ¤¹" -#: ../ex_cmds.c:5687 +#, c-format +msgid "E150: Not a directory: %s" +msgstr "E150: ¥Ç¥£¥ì¥¯¥È¥ê¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó: %s" + #, c-format msgid "E160: Unknown sign command: %s" msgstr "E160: ̤ÃΤÎsign¥³¥Þ¥ó¥É¤Ç¤¹: %s" -#: ../ex_cmds.c:5704 msgid "E156: Missing sign name" msgstr "E156: sign̾¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../ex_cmds.c:5746 msgid "E612: Too many signs defined" msgstr "E612: sign¤ÎÄêµÁ¤¬Â¿¿ô¸«¤Ä¤«¤ê¤Þ¤·¤¿" -#: ../ex_cmds.c:5813 #, c-format msgid "E239: Invalid sign text: %s" msgstr "E239: ̵¸ú¤Êsign¤Î¥Æ¥¥¹¥È¤Ç¤¹: %s" -#: ../ex_cmds.c:5844 ../ex_cmds.c:6035 #, c-format msgid "E155: Unknown sign: %s" msgstr "E155: ̤ÃΤÎsign¤Ç¤¹: %s" -#: ../ex_cmds.c:5877 msgid "E159: Missing sign number" msgstr "E159: sign¤ÎÈֹ椬¤¢¤ê¤Þ¤»¤ó" -#: ../ex_cmds.c:5971 #, c-format msgid "E158: Invalid buffer name: %s" msgstr "E158: ̵¸ú¤Ê¥Ð¥Ã¥Õ¥¡Ì¾¤Ç¤¹: %s" -#: ../ex_cmds.c:6008 +msgid "E934: Cannot jump to a buffer that does not have a name" +msgstr "E934: ̾Á°¤Î̵¤¤¥Ð¥Ã¥Õ¥¡¤Ø¤Ï¥¸¥ã¥ó¥×¤Ç¤¤Þ¤»¤ó" + #, c-format -msgid "E157: Invalid sign ID: %<PRId64>" -msgstr "E157: ̵¸ú¤Êsign¼±Ê̻ҤǤ¹: %<PRId64>" +msgid "E157: Invalid sign ID: %ld" +msgstr "E157: ̵¸ú¤Êsign¼±Ê̻ҤǤ¹: %ld" #, c-format msgid "E885: Not possible to change sign %s" msgstr "E885: Êѹ¹¤Ç¤¤Ê¤¤ sign ¤Ç¤¹: %s" -#: ../ex_cmds.c:6066 +# Added at 27-Jan-2004. +msgid " (NOT FOUND)" +msgstr " (¸«¤Ä¤«¤ê¤Þ¤»¤ó)" + msgid " (not supported)" msgstr " (È󥵥ݡ¼¥È)" -#: ../ex_cmds.c:6169 msgid "[Deleted]" msgstr "[ºï½üºÑ]" -#: ../ex_cmds2.c:139 +msgid "No old files" +msgstr "¸Å¤¤¥Õ¥¡¥¤¥ë¤Ï¤¢¤ê¤Þ¤»¤ó" + msgid "Entering Debug mode. Type \"cont\" to continue." msgstr "¥Ç¥Ð¥Ã¥°¥â¡¼¥É¤ËÆþ¤ê¤Þ¤¹. ³¤±¤ë¤Ë¤Ï \"cont\" ¤ÈÆþÎϤ·¤Æ¤¯¤À¤µ¤¤." -#: ../ex_cmds2.c:143 ../ex_docmd.c:759 #, c-format -msgid "line %<PRId64>: %s" -msgstr "¹Ô %<PRId64>: %s" +msgid "line %ld: %s" +msgstr "¹Ô %ld: %s" -#: ../ex_cmds2.c:145 #, c-format msgid "cmd: %s" msgstr "¥³¥Þ¥ó¥É: %s" @@ -1405,232 +1123,184 @@ msgstr "¥Õ¥ì¡¼¥à¤¬ 0 ¤Ç¤¹" msgid "frame at highest level: %d" msgstr "ºÇ¹â¥ì¥Ù¥ë¤Î¥Õ¥ì¡¼¥à: %d" -#: ../ex_cmds2.c:322 #, c-format -msgid "Breakpoint in \"%s%s\" line %<PRId64>" -msgstr "¥Ö¥ì¡¼¥¯¥Ý¥¤¥ó¥È \"%s%s\" ¹Ô %<PRId64>" +msgid "Breakpoint in \"%s%s\" line %ld" +msgstr "¥Ö¥ì¡¼¥¯¥Ý¥¤¥ó¥È \"%s%s\" ¹Ô %ld" -#: ../ex_cmds2.c:581 #, c-format msgid "E161: Breakpoint not found: %s" msgstr "E161: ¥Ö¥ì¡¼¥¯¥Ý¥¤¥ó¥È¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó: %s" -#: ../ex_cmds2.c:611 msgid "No breakpoints defined" msgstr "¥Ö¥ì¡¼¥¯¥Ý¥¤¥ó¥È¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#: ../ex_cmds2.c:617 #, c-format -msgid "%3d %s %s line %<PRId64>" -msgstr "%3d %s %s ¹Ô %<PRId64>" +msgid "%3d %s %s line %ld" +msgstr "%3d %s %s ¹Ô %ld" -#: ../ex_cmds2.c:942 msgid "E750: First use \":profile start {fname}\"" msgstr "E750: ½é¤á¤Ë \":profile start {fname}\" ¤ò¼Â¹Ô¤·¤Æ¤¯¤À¤µ¤¤" -#: ../ex_cmds2.c:1269 #, c-format msgid "Save changes to \"%s\"?" msgstr "Êѹ¹¤ò \"%s\" ¤ËÊݸ¤·¤Þ¤¹¤«?" -#: ../ex_cmds2.c:1271 ../ex_docmd.c:8851 msgid "Untitled" msgstr "̵Âê" -#: ../ex_cmds2.c:1421 #, c-format msgid "E162: No write since last change for buffer \"%s\"" msgstr "E162: ¥Ð¥Ã¥Õ¥¡ \"%s\" ¤ÎÊѹ¹¤ÏÊݸ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#: ../ex_cmds2.c:1480 msgid "Warning: Entered other buffer unexpectedly (check autocommands)" msgstr "·Ù¹ð: ͽ´ü¤»¤ºÂ¾¥Ð¥Ã¥Õ¥¡¤Ø°Üư¤·¤Þ¤·¤¿ (autocommands ¤òÄ´¤Ù¤Æ¤¯¤À¤µ¤¤)" -#: ../ex_cmds2.c:1826 msgid "E163: There is only one file to edit" msgstr "E163: ÊÔ½¸¤¹¤ë¥Õ¥¡¥¤¥ë¤Ï1¤Ä¤·¤«¤¢¤ê¤Þ¤»¤ó" -#: ../ex_cmds2.c:1828 msgid "E164: Cannot go before first file" msgstr "E164: ºÇ½é¤Î¥Õ¥¡¥¤¥ë¤è¤êÁ°¤Ë¤Ï¹Ô¤±¤Þ¤»¤ó" -#: ../ex_cmds2.c:1830 msgid "E165: Cannot go beyond last file" msgstr "E165: ºÇ¸å¤Î¥Õ¥¡¥¤¥ë¤ò±Û¤¨¤Æ¸å¤Ë¤Ï¹Ô¤±¤Þ¤»¤ó" -#: ../ex_cmds2.c:2175 #, c-format msgid "E666: compiler not supported: %s" msgstr "E666: ¤½¤Î¥³¥ó¥Ñ¥¤¥é¤Ë¤ÏÂбþ¤·¤Æ¤¤¤Þ¤»¤ó: %s" -#: ../ex_cmds2.c:2257 #, c-format msgid "Searching for \"%s\" in \"%s\"" msgstr "\"%s\" ¤ò \"%s\" ¤«¤é¸¡º÷Ãæ" -#: ../ex_cmds2.c:2284 #, c-format msgid "Searching for \"%s\"" msgstr "\"%s\" ¤ò¸¡º÷Ãæ" -#: ../ex_cmds2.c:2307 #, c-format -msgid "not found in 'runtimepath': \"%s\"" -msgstr "'runtimepath' ¤ÎÃæ¤Ë¤Ï¸«¤Ä¤«¤ê¤Þ¤»¤ó: \"%s\"" +msgid "not found in '%s': \"%s\"" +msgstr "'%s' ¤ÎÃæ¤Ë¤Ï¤¢¤ê¤Þ¤»¤ó: \"%s\"" + +msgid "Source Vim script" +msgstr "Vim¥¹¥¯¥ê¥×¥È¤Î¼è¹þ¤ß" -#: ../ex_cmds2.c:2472 #, c-format msgid "Cannot source a directory: \"%s\"" msgstr "¥Ç¥£¥ì¥¯¥È¥ê¤Ï¼è¹þ¤á¤Þ¤»¤ó: \"%s\"" -#: ../ex_cmds2.c:2518 #, c-format msgid "could not source \"%s\"" msgstr "\"%s\" ¤ò¼è¹þ¤á¤Þ¤»¤ó" -#: ../ex_cmds2.c:2520 #, c-format -msgid "line %<PRId64>: could not source \"%s\"" -msgstr "¹Ô %<PRId64>: \"%s\" ¤ò¼è¹þ¤á¤Þ¤»¤ó" +msgid "line %ld: could not source \"%s\"" +msgstr "¹Ô %ld: \"%s\" ¤ò¼è¹þ¤á¤Þ¤»¤ó" -#: ../ex_cmds2.c:2535 #, c-format msgid "sourcing \"%s\"" msgstr "\"%s\" ¤ò¼è¹þÃæ" -#: ../ex_cmds2.c:2537 #, c-format -msgid "line %<PRId64>: sourcing \"%s\"" -msgstr "¹Ô %<PRId64>: %s ¤ò¼è¹þÃæ" +msgid "line %ld: sourcing \"%s\"" +msgstr "¹Ô %ld: %s ¤ò¼è¹þÃæ" -#: ../ex_cmds2.c:2693 #, c-format msgid "finished sourcing %s" msgstr "%s ¤Î¼è¹þ¤ò´°Î»" -#: ../ex_cmds2.c:2765 +#, c-format +msgid "continuing in %s" +msgstr "%s ¤Î¼Â¹Ô¤ò·ÑÂ³Ãæ¤Ç¤¹" + msgid "modeline" msgstr "¥â¡¼¥É¹Ô" -#: ../ex_cmds2.c:2767 msgid "--cmd argument" msgstr "--cmd °ú¿ô" -#: ../ex_cmds2.c:2769 msgid "-c argument" msgstr "-c °ú¿ô" -#: ../ex_cmds2.c:2771 msgid "environment variable" msgstr "´Ä¶ÊÑ¿ô" -#: ../ex_cmds2.c:2773 msgid "error handler" msgstr "¥¨¥é¡¼¥Ï¥ó¥É¥é" -#: ../ex_cmds2.c:3020 msgid "W15: Warning: Wrong line separator, ^M may be missing" msgstr "W15: ·Ù¹ð: ¹Ô¶èÀÚ¤¬ÉÔÀµ¤Ç¤¹. ^M ¤¬¤Ê¤¤¤Î¤Ç¤·¤ç¤¦" -#: ../ex_cmds2.c:3139 msgid "E167: :scriptencoding used outside of a sourced file" msgstr "E167: :scriptencoding ¤¬¼è¹þ¥¹¥¯¥ê¥×¥È°Ê³°¤Ç»ÈÍѤµ¤ì¤Þ¤·¤¿" -#: ../ex_cmds2.c:3166 msgid "E168: :finish used outside of a sourced file" msgstr "E168: :finish ¤¬¼è¹þ¥¹¥¯¥ê¥×¥È°Ê³°¤Ç»ÈÍѤµ¤ì¤Þ¤·¤¿" -#: ../ex_cmds2.c:3389 #, c-format msgid "Current %slanguage: \"%s\"" msgstr "¸½ºß¤Î %s¸À¸ì: \"%s\"" -#: ../ex_cmds2.c:3404 #, c-format msgid "E197: Cannot set language to \"%s\"" msgstr "E197: ¸À¸ì¤ò \"%s\" ¤ËÀßÄê¤Ç¤¤Þ¤»¤ó" -#. don't redisplay the window -#. don't wait for return -#: ../ex_docmd.c:387 msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." msgstr "" "Ex¥â¡¼¥É¤ËÆþ¤ê¤Þ¤¹. ¥Î¡¼¥Þ¥ë¥â¡¼¥É¤ËÌá¤ë¤Ë¤Ï\"visual\"¤ÈÆþÎϤ·¤Æ¤¯¤À¤µ¤¤." -#: ../ex_docmd.c:428 msgid "E501: At end-of-file" msgstr "E501: ¥Õ¥¡¥¤¥ë¤Î½ªÎ»°ÌÃÖ" -#: ../ex_docmd.c:513 msgid "E169: Command too recursive" msgstr "E169: ¥³¥Þ¥ó¥É¤¬ºÆµ¢Åª²á¤®¤Þ¤¹" -#: ../ex_docmd.c:1006 #, c-format msgid "E605: Exception not caught: %s" msgstr "E605: Îã³°¤¬Ê᪤µ¤ì¤Þ¤»¤ó¤Ç¤·¤¿: %s" -#: ../ex_docmd.c:1085 msgid "End of sourced file" msgstr "¼è¹þ¥Õ¥¡¥¤¥ë¤ÎºÇ¸å¤Ç¤¹" -#: ../ex_docmd.c:1086 msgid "End of function" msgstr "´Ø¿ô¤ÎºÇ¸å¤Ç¤¹" -#: ../ex_docmd.c:1628 msgid "E464: Ambiguous use of user-defined command" msgstr "E464: ¥æ¡¼¥¶¡¼ÄêµÁ¥³¥Þ¥ó¥É¤Î¤¢¤¤¤Þ¤¤¤Ê»ÈÍѤǤ¹" -#: ../ex_docmd.c:1638 msgid "E492: Not an editor command" msgstr "E492: ¥¨¥Ç¥£¥¿¤Î¥³¥Þ¥ó¥É¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../ex_docmd.c:1729 msgid "E493: Backwards range given" msgstr "E493: µÕ¤µ¤Þ¤ÎÈϰϤ¬»ØÄꤵ¤ì¤Þ¤·¤¿" -#: ../ex_docmd.c:1733 msgid "Backwards range given, OK to swap" msgstr "µÕ¤µ¤Þ¤ÎÈϰϤ¬»ØÄꤵ¤ì¤Þ¤·¤¿, ÆþÂØ¤¨¤Þ¤¹¤«?" -#. append -#. typed wrong -#: ../ex_docmd.c:1787 msgid "E494: Use w or w>>" msgstr "E494: w ¤â¤·¤¯¤Ï w>> ¤ò»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤" -#: ../ex_docmd.c:3454 -msgid "E319: The command is not available in this version" +msgid "E319: Sorry, the command is not available in this version" msgstr "E319: ¤³¤Î¥Ð¡¼¥¸¥ç¥ó¤Ç¤Ï¤³¤Î¥³¥Þ¥ó¥É¤ÏÍøÍѤǤ¤Þ¤»¤ó, ¤´¤á¤ó¤Ê¤µ¤¤" -#: ../ex_docmd.c:3752 msgid "E172: Only one file name allowed" msgstr "E172: ¥Õ¥¡¥¤¥ë̾¤Ï 1 ¤Ä¤Ë¤·¤Æ¤¯¤À¤µ¤¤" -#: ../ex_docmd.c:4238 msgid "1 more file to edit. Quit anyway?" msgstr "ÊÔ½¸¤¹¤Ù¤¥Õ¥¡¥¤¥ë¤¬ 1 ¸Ä¤¢¤ê¤Þ¤¹¤¬, ½ªÎ»¤·¤Þ¤¹¤«?" -#: ../ex_docmd.c:4242 #, c-format msgid "%d more files to edit. Quit anyway?" msgstr "ÊÔ½¸¤¹¤Ù¤¥Õ¥¡¥¤¥ë¤¬¤¢¤È %d ¸Ä¤¢¤ê¤Þ¤¹¤¬, ½ªÎ»¤·¤Þ¤¹¤«?" -#: ../ex_docmd.c:4248 msgid "E173: 1 more file to edit" msgstr "E173: ÊÔ½¸¤¹¤Ù¤¥Õ¥¡¥¤¥ë¤¬ 1 ¸Ä¤¢¤ê¤Þ¤¹" -#: ../ex_docmd.c:4250 #, c-format -msgid "E173: %<PRId64> more files to edit" -msgstr "E173: ÊÔ½¸¤¹¤Ù¤¥Õ¥¡¥¤¥ë¤¬¤¢¤È %<PRId64> ¸Ä¤¢¤ê¤Þ¤¹" +msgid "E173: %ld more files to edit" +msgstr "E173: ÊÔ½¸¤¹¤Ù¤¥Õ¥¡¥¤¥ë¤¬¤¢¤È %ld ¸Ä¤¢¤ê¤Þ¤¹" -#: ../ex_docmd.c:4320 msgid "E174: Command already exists: add ! to replace it" msgstr "E174: ¥³¥Þ¥ó¥É¤¬´û¤Ë¤¢¤ê¤Þ¤¹: ºÆÄêµÁ¤¹¤ë¤Ë¤Ï ! ¤òÄɲ䷤Ƥ¯¤À¤µ¤¤" -#: ../ex_docmd.c:4432 msgid "" "\n" " Name Args Address Complete Definition" @@ -1638,51 +1308,40 @@ msgstr "" "\n" " ̾Á° °ú¿ô ¥¢¥É¥ì¥¹ Êä´° ÄêµÁ" -#: ../ex_docmd.c:4516 msgid "No user-defined commands found" msgstr "¥æ¡¼¥¶¡¼ÄêµÁ¥³¥Þ¥ó¥É¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿" -#: ../ex_docmd.c:4538 msgid "E175: No attribute specified" msgstr "E175: °À¤ÏÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#: ../ex_docmd.c:4583 msgid "E176: Invalid number of arguments" msgstr "E176: °ú¿ô¤Î¿ô¤¬Ìµ¸ú¤Ç¤¹" -#: ../ex_docmd.c:4594 msgid "E177: Count cannot be specified twice" msgstr "E177: ¥«¥¦¥ó¥È¤ò2½Å»ØÄꤹ¤ë¤³¤È¤Ï¤Ç¤¤Þ¤»¤ó" -#: ../ex_docmd.c:4603 msgid "E178: Invalid default value for count" msgstr "E178: ¥«¥¦¥ó¥È¤Î¾ÊάÃͤ¬Ìµ¸ú¤Ç¤¹" -#: ../ex_docmd.c:4625 msgid "E179: argument required for -complete" msgstr "E179: -complete ¤Ë¤Ï°ú¿ô¤¬É¬ÍפǤ¹" msgid "E179: argument required for -addr" msgstr "E179: -addr ¤Ë¤Ï°ú¿ô¤¬É¬ÍפǤ¹" -#: ../ex_docmd.c:4635 #, c-format msgid "E181: Invalid attribute: %s" msgstr "E181: ̵¸ú¤Ê°À¤Ç¤¹: %s" -#: ../ex_docmd.c:4678 msgid "E182: Invalid command name" msgstr "E182: ̵¸ú¤Ê¥³¥Þ¥ó¥É̾¤Ç¤¹" -#: ../ex_docmd.c:4691 msgid "E183: User defined commands must start with an uppercase letter" -msgstr "E183: ¥æ¡¼¥¶ÄêµÁ¥³¥Þ¥ó¥É¤Ï±ÑÂçʸ»ú¤Ç»Ï¤Þ¤é¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" +msgstr "E183: ¥æ¡¼¥¶¡¼ÄêµÁ¥³¥Þ¥ó¥É¤Ï±ÑÂçʸ»ú¤Ç»Ï¤Þ¤é¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" -#: ../ex_docmd.c:4696 msgid "E841: Reserved name, cannot be used for user defined command" msgstr "E841: ͽÌó̾¤Ê¤Î¤Ç, ¥æ¡¼¥¶¡¼ÄêµÁ¥³¥Þ¥ó¥É¤ËÍøÍѤǤ¤Þ¤»¤ó" -#: ../ex_docmd.c:4751 #, c-format msgid "E184: No such user-defined command: %s" msgstr "E184: ¤½¤Î¥æ¡¼¥¶¡¼ÄêµÁ¥³¥Þ¥ó¥É¤Ï¤¢¤ê¤Þ¤»¤ó: %s" @@ -1691,293 +1350,261 @@ msgstr "E184: ¤½¤Î¥æ¡¼¥¶¡¼ÄêµÁ¥³¥Þ¥ó¥É¤Ï¤¢¤ê¤Þ¤»¤ó: %s" msgid "E180: Invalid address type value: %s" msgstr "E180: ̵¸ú¤Ê¥¢¥É¥ì¥¹¥¿¥¤¥×ÃͤǤ¹: %s" -#: ../ex_docmd.c:5219 #, c-format msgid "E180: Invalid complete value: %s" msgstr "E180: ̵¸ú¤ÊÊä´°»ØÄê¤Ç¤¹: %s" -#: ../ex_docmd.c:5225 msgid "E468: Completion argument only allowed for custom completion" msgstr "E468: Êä´°°ú¿ô¤Ï¥«¥¹¥¿¥àÊä´°¤Ç¤·¤«»ÈÍѤǤ¤Þ¤»¤ó" -#: ../ex_docmd.c:5231 msgid "E467: Custom completion requires a function argument" msgstr "E467: ¥«¥¹¥¿¥àÊä´°¤Ë¤Ï°ú¿ô¤È¤·¤Æ´Ø¿ô¤¬É¬ÍפǤ¹" -#: ../ex_docmd.c:5257 +msgid "unknown" +msgstr "ÉÔÌÀ" + #, c-format msgid "E185: Cannot find color scheme '%s'" msgstr "E185: ¥«¥é¡¼¥¹¥¡¼¥à '%s' ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../ex_docmd.c:5263 msgid "Greetings, Vim user!" msgstr "Vim »È¤¤¤µ¤ó¡¢¤ä¤¢!" -#: ../ex_docmd.c:5431 msgid "E784: Cannot close last tab page" msgstr "E784: ºÇ¸å¤Î¥¿¥Ö¥Ú¡¼¥¸¤òÊĤ¸¤ë¤³¤È¤Ï¤Ç¤¤Þ¤»¤ó" -#: ../ex_docmd.c:5462 msgid "Already only one tab page" msgstr "´û¤Ë¥¿¥Ö¥Ú¡¼¥¸¤Ï1¤Ä¤·¤«¤¢¤ê¤Þ¤»¤ó" -#: ../ex_docmd.c:6004 +msgid "Edit File in new window" +msgstr "¿·¤·¤¤¥¦¥£¥ó¥É¥¦¤Ç¥Õ¥¡¥¤¥ë¤òÊÔ½¸¤·¤Þ¤¹" + #, c-format msgid "Tab page %d" msgstr "¥¿¥Ö¥Ú¡¼¥¸ %d" -#: ../ex_docmd.c:6295 msgid "No swap file" msgstr "¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../ex_docmd.c:6478 +msgid "Append File" +msgstr "Äɲåե¡¥¤¥ë" + msgid "E747: Cannot change directory, buffer is modified (add ! to override)" msgstr "" "E747: ¥Ð¥Ã¥Õ¥¡¤¬½¤Àµ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ç, ¥Ç¥£¥ì¥¯¥È¥ê¤òÊѹ¹¤Ç¤¤Þ¤»¤ó (! ¤òÄɲäÇ" "¾å½ñ)" -#: ../ex_docmd.c:6485 msgid "E186: No previous directory" msgstr "E186: Á°¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../ex_docmd.c:6530 msgid "E187: Unknown" msgstr "E187: ̤ÃÎ" -#: ../ex_docmd.c:6610 msgid "E465: :winsize requires two number arguments" msgstr "E465: :winsize ¤Ë¤Ï2¤Ä¤Î¿ôÃͤΰú¿ô¤¬É¬ÍפǤ¹" -#: ../ex_docmd.c:6655 +#, c-format +msgid "Window position: X %d, Y %d" +msgstr "¥¦¥£¥ó¥É¥¦°ÌÃÖ: X %d, Y %d" + msgid "E188: Obtaining window position not implemented for this platform" msgstr "" "E188: ¤³¤Î¥×¥é¥Ã¥È¥Û¡¼¥à¤Ë¤Ï¥¦¥£¥ó¥É¥¦°ÌÃ֤μèÆÀµ¡Ç½¤Ï¼ÂÁõ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#: ../ex_docmd.c:6662 msgid "E466: :winpos requires two number arguments" msgstr "E466: :winpos ¤Ë¤Ï2¤Ä¤Î¿ôÃͤΰú¿ô¤¬É¬ÍפǤ¹" -#: ../ex_docmd.c:7241 +msgid "E930: Cannot use :redir inside execute()" +msgstr "E930: execute() ¤ÎÃæ¤Ç¤Ï :redir ¤Ï»È¤¨¤Þ¤»¤ó" + +msgid "Save Redirection" +msgstr "¥ê¥À¥¤¥ì¥¯¥È¤òÊݸ¤·¤Þ¤¹" + +msgid "Save View" +msgstr "¥Ó¥å¡¼¤òÊݸ¤·¤Þ¤¹" + +msgid "Save Session" +msgstr "¥»¥Ã¥·¥ç¥ó¾ðÊó¤òÊݸ¤·¤Þ¤¹" + +msgid "Save Setup" +msgstr "ÀßÄê¤òÊݸ¤·¤Þ¤¹" + #, c-format msgid "E739: Cannot create directory: %s" msgstr "E739: ¥Ç¥£¥ì¥¯¥È¥ê¤òºîÀ®¤Ç¤¤Þ¤»¤ó: %s" -#: ../ex_docmd.c:7268 #, c-format msgid "E189: \"%s\" exists (add ! to override)" msgstr "E189: \"%s\" ¤¬Â¸ºß¤·¤Þ¤¹ (¾å½ñ¤¹¤ë¤Ë¤Ï ! ¤òÄɲ䷤Ƥ¯¤À¤µ¤¤)" -#: ../ex_docmd.c:7273 #, c-format msgid "E190: Cannot open \"%s\" for writing" msgstr "E190: \"%s\" ¤ò½ñ¹þ¤ßÍѤȤ·¤Æ³«¤±¤Þ¤»¤ó" #. set mark -#: ../ex_docmd.c:7294 msgid "E191: Argument must be a letter or forward/backward quote" msgstr "E191: °ú¿ô¤Ï1ʸ»ú¤Î±Ñ»ú¤«°úÍÑÉä (' ¤« `) ¤Ç¤Ê¤±¤ì¤Ð¤¤¤±¤Þ¤»¤ó" -#: ../ex_docmd.c:7333 msgid "E192: Recursive use of :normal too deep" msgstr "E192: :normal ¤ÎºÆµ¢ÍøÍѤ¬¿¼¤¯¤Ê¤ê²á¤®¤Þ¤·¤¿" -#: ../ex_docmd.c:7807 +msgid "E809: #< is not available without the +eval feature" +msgstr "E809: #< ¤Ï +eval µ¡Ç½¤¬Ìµ¤¤¤ÈÍøÍѤǤ¤Þ¤»¤ó" + msgid "E194: No alternate file name to substitute for '#'" msgstr "E194: '#'¤òÃÖ¤´¹¤¨¤ëÉû¥Õ¥¡¥¤¥ë¤Î̾Á°¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../ex_docmd.c:7841 msgid "E495: no autocommand file name to substitute for \"<afile>\"" msgstr "E495: \"<afile>\"¤òÃÖ¤´¹¤¨¤ëautocommand¤Î¥Õ¥¡¥¤¥ë̾¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../ex_docmd.c:7850 msgid "E496: no autocommand buffer number to substitute for \"<abuf>\"" msgstr "E496: \"<abuf>\"¤òÃÖ¤´¹¤¨¤ëautocommand¥Ð¥Ã¥Õ¥¡Èֹ椬¤¢¤ê¤Þ¤»¤ó" -#: ../ex_docmd.c:7861 msgid "E497: no autocommand match name to substitute for \"<amatch>\"" msgstr "E497: \"<amatch>\"¤òÃÖ¤´¹¤¨¤ëautocommand¤Î³ºÅö̾¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../ex_docmd.c:7870 msgid "E498: no :source file name to substitute for \"<sfile>\"" msgstr "E498: \"<sfile>\"¤òÃÖ¤´¹¤¨¤ë :source Âоݥե¡¥¤¥ë̾¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../ex_docmd.c:7876 msgid "E842: no line number to use for \"<slnum>\"" msgstr "E842: \"<slnum>\"¤òÃÖ¤´¹¤¨¤ë¹ÔÈֹ椬¤¢¤ê¤Þ¤»¤ó" -#: ../ex_docmd.c:7903 -#, fuzzy, c-format +#, no-c-format msgid "E499: Empty file name for '%' or '#', only works with \":p:h\"" msgstr "" "E499: '%' ¤ä '#' ¤¬ÌµÌ¾¥Õ¥¡¥¤¥ë¤Ê¤Î¤Ç \":p:h\" ¤òȼ¤ï¤Ê¤¤»È¤¤Êý¤Ï¤Ç¤¤Þ¤»¤ó" -#: ../ex_docmd.c:7905 msgid "E500: Evaluates to an empty string" msgstr "E500: ¶õʸ»úÎó¤È¤·¤ÆÉ¾²Á¤µ¤ì¤Þ¤·¤¿" -#: ../ex_docmd.c:8838 msgid "E195: Cannot open viminfo file for reading" msgstr "E195: viminfo¥Õ¥¡¥¤¥ë¤òÆÉ¹þÍѤȤ·¤Æ³«¤±¤Þ¤»¤ó" -#: ../ex_eval.c:464 +msgid "E196: No digraphs in this version" +msgstr "E196: ¤³¤Î¥Ð¡¼¥¸¥ç¥ó¤Ë¹ç»ú¤Ï¤¢¤ê¤Þ¤»¤ó" + msgid "E608: Cannot :throw exceptions with 'Vim' prefix" msgstr "E608: 'Vim' ¤Ç»Ï¤Þ¤ëÎã³°¤Ï :throw ¤Ç¤¤Þ¤»¤ó" #. always scroll up, don't overwrite -#: ../ex_eval.c:496 #, c-format msgid "Exception thrown: %s" msgstr "Îã³°¤¬È¯À¸¤·¤Þ¤·¤¿: %s" -#: ../ex_eval.c:545 #, c-format msgid "Exception finished: %s" msgstr "Îã³°¤¬¼ý«¤·¤Þ¤·¤¿: %s" -#: ../ex_eval.c:546 #, c-format msgid "Exception discarded: %s" msgstr "Îã³°¤¬ÇË´þ¤µ¤ì¤Þ¤·¤¿: %s" -#: ../ex_eval.c:588 ../ex_eval.c:634 #, c-format -msgid "%s, line %<PRId64>" -msgstr "%s, ¹Ô %<PRId64>" +msgid "%s, line %ld" +msgstr "%s, ¹Ô %ld" #. always scroll up, don't overwrite -#: ../ex_eval.c:608 #, c-format msgid "Exception caught: %s" msgstr "Îã³°¤¬Ê᪤µ¤ì¤Þ¤·¤¿: %s" -#: ../ex_eval.c:676 #, c-format msgid "%s made pending" msgstr "%s ¤Ë¤è¤ê̤·èÄê¾õÂÖ¤¬À¸¤¸¤Þ¤·¤¿" -#: ../ex_eval.c:679 #, c-format msgid "%s resumed" msgstr "%s ¤¬ºÆ³«¤·¤Þ¤·¤¿" -#: ../ex_eval.c:683 #, c-format msgid "%s discarded" msgstr "%s ¤¬ÇË´þ¤µ¤ì¤Þ¤·¤¿" -#: ../ex_eval.c:708 msgid "Exception" msgstr "Îã³°" -#: ../ex_eval.c:713 msgid "Error and interrupt" msgstr "¥¨¥é¡¼¤È³ä¹þ¤ß" -#: ../ex_eval.c:715 msgid "Error" msgstr "¥¨¥é¡¼" #. if (pending & CSTP_INTERRUPT) -#: ../ex_eval.c:717 msgid "Interrupt" msgstr "³ä¹þ¤ß" -#: ../ex_eval.c:795 msgid "E579: :if nesting too deep" msgstr "E579: :if ¤ÎÆþ¤ì»Ò¤¬¿¼²á¤®¤Þ¤¹" -#: ../ex_eval.c:830 msgid "E580: :endif without :if" msgstr "E580: :if ¤Î¤Ê¤¤ :endif ¤¬¤¢¤ê¤Þ¤¹" -#: ../ex_eval.c:873 msgid "E581: :else without :if" msgstr "E581: :if ¤Î¤Ê¤¤ :else ¤¬¤¢¤ê¤Þ¤¹" -#: ../ex_eval.c:876 msgid "E582: :elseif without :if" msgstr "E582: :if ¤Î¤Ê¤¤ :elseif ¤¬¤¢¤ê¤Þ¤¹" -#: ../ex_eval.c:880 msgid "E583: multiple :else" msgstr "E583: Ê£¿ô¤Î :else ¤¬¤¢¤ê¤Þ¤¹" -#: ../ex_eval.c:883 msgid "E584: :elseif after :else" msgstr "E584: :else ¤Î¸å¤Ë :elseif ¤¬¤¢¤ê¤Þ¤¹" -#: ../ex_eval.c:941 msgid "E585: :while/:for nesting too deep" msgstr "E585: :while ¤ä :for ¤ÎÆþ¤ì»Ò¤¬¿¼²á¤®¤Þ¤¹" -#: ../ex_eval.c:1028 msgid "E586: :continue without :while or :for" msgstr "E586: :while ¤ä :for ¤Î¤Ê¤¤ :continue ¤¬¤¢¤ê¤Þ¤¹" -#: ../ex_eval.c:1061 msgid "E587: :break without :while or :for" msgstr "E587: :while ¤ä :for ¤Î¤Ê¤¤ :break ¤¬¤¢¤ê¤Þ¤¹" -#: ../ex_eval.c:1102 msgid "E732: Using :endfor with :while" msgstr "E732: :endfor ¤ò :while ¤ÈÁȤ߹ç¤ï¤»¤Æ¤¤¤Þ¤¹" -#: ../ex_eval.c:1104 msgid "E733: Using :endwhile with :for" msgstr "E733: :endwhile ¤ò :for ¤ÈÁȤ߹ç¤ï¤»¤Æ¤¤¤Þ¤¹" -#: ../ex_eval.c:1247 msgid "E601: :try nesting too deep" msgstr "E601: :try ¤ÎÆþ¤ì»Ò¤¬¿¼²á¤®¤Þ¤¹" -#: ../ex_eval.c:1317 msgid "E603: :catch without :try" msgstr "E603: :try ¤Î¤Ê¤¤ :catch ¤¬¤¢¤ê¤Þ¤¹" #. Give up for a ":catch" after ":finally" and ignore it. #. * Just parse. -#: ../ex_eval.c:1332 msgid "E604: :catch after :finally" msgstr "E604: :finally ¤Î¸å¤Ë :catch ¤¬¤¢¤ê¤Þ¤¹" -#: ../ex_eval.c:1451 msgid "E606: :finally without :try" msgstr "E606: :try ¤Î¤Ê¤¤ :finally ¤¬¤¢¤ê¤Þ¤¹" #. Give up for a multiple ":finally" and ignore it. -#: ../ex_eval.c:1467 msgid "E607: multiple :finally" msgstr "E607: Ê£¿ô¤Î :finally ¤¬¤¢¤ê¤Þ¤¹" -#: ../ex_eval.c:1571 msgid "E602: :endtry without :try" msgstr "E602: :try ¤Î¤Ê¤¤ :endtry ¤Ç¤¹" -#: ../ex_eval.c:2026 msgid "E193: :endfunction not inside a function" msgstr "E193: ´Ø¿ô¤Î³°¤Ë :endfunction ¤¬¤¢¤ê¤Þ¤·¤¿" -#: ../ex_getln.c:1643 msgid "E788: Not allowed to edit another buffer now" msgstr "E788: ¸½ºß¤Ï¾¤Î¥Ð¥Ã¥Õ¥¡¤òÊÔ½¸¤¹¤ë¤³¤È¤Ïµö¤µ¤ì¤Þ¤»¤ó" -#: ../ex_getln.c:1656 msgid "E811: Not allowed to change buffer information now" msgstr "E811: ¸½ºß¤Ï¥Ð¥Ã¥Õ¥¡¾ðÊó¤òÊѹ¹¤¹¤ë¤³¤È¤Ïµö¤µ¤ì¤Þ¤»¤ó" -#: ../ex_getln.c:3178 msgid "tagname" msgstr "¥¿¥°Ì¾" -#: ../ex_getln.c:3181 msgid " kind file\n" msgstr " ¥Õ¥¡¥¤¥ë¼ïÎà\n" -#: ../ex_getln.c:4799 msgid "'history' option is zero" msgstr "¥ª¥×¥·¥ç¥ó 'history' ¤¬¥¼¥í¤Ç¤¹" -#: ../ex_getln.c:5046 #, c-format msgid "" "\n" @@ -1986,303 +1613,224 @@ msgstr "" "\n" "# %s ¹àÌܤÎÍúÎò (¿·¤·¤¤¤â¤Î¤«¤é¸Å¤¤¤â¤Î¤Ø):\n" -#: ../ex_getln.c:5047 msgid "Command Line" msgstr "¥³¥Þ¥ó¥É¥é¥¤¥ó" -#: ../ex_getln.c:5048 msgid "Search String" msgstr "¸¡º÷ʸ»úÎó" -#: ../ex_getln.c:5049 msgid "Expression" msgstr "¼°" -#: ../ex_getln.c:5050 msgid "Input Line" msgstr "ÆþÎϹÔ" -#: ../ex_getln.c:5117 +msgid "Debug Line" +msgstr "¥Ç¥Ð¥Ã¥°¹Ô" + msgid "E198: cmd_pchar beyond the command length" msgstr "E198: cmd_pchar ¤¬¥³¥Þ¥ó¥ÉŤòͤ¨¤Þ¤·¤¿" -#: ../ex_getln.c:5279 msgid "E199: Active window or buffer deleted" msgstr "E199: ¥¢¥¯¥Æ¥£¥Ö¤Ê¥¦¥£¥ó¥É¥¦¤«¥Ð¥Ã¥Õ¥¡¤¬ºï½ü¤µ¤ì¤Þ¤·¤¿" -#: ../file_search.c:203 -msgid "E854: path too long for completion" -msgstr "E854: ¥Ñ¥¹¤¬Ä¹²á¤®¤ÆÊä´°¤Ç¤¤Þ¤»¤ó" - -#: ../file_search.c:446 -#, c-format -msgid "" -"E343: Invalid path: '**[number]' must be at the end of the path or be " -"followed by '%s'." -msgstr "" -"E343: ̵¸ú¤Ê¥Ñ¥¹¤Ç¤¹: '**[¿ôÃÍ]' ¤Ïpath¤ÎºÇ¸å¤« '%s' ¤¬Â³¤¤¤Æ¤Ê¤¤¤È¤¤¤±¤Þ¤»" -"¤ó." - -#: ../file_search.c:1505 -#, c-format -msgid "E344: Can't find directory \"%s\" in cdpath" -msgstr "E344: cdpath¤Ë¤Ï \"%s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó" - -#: ../file_search.c:1508 -#, c-format -msgid "E345: Can't find file \"%s\" in path" -msgstr "E345: path¤Ë¤Ï \"%s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó" - -#: ../file_search.c:1512 -#, c-format -msgid "E346: No more directory \"%s\" found in cdpath" -msgstr "E346: cdpath¤Ë¤Ï¤³¤ì°Ê¾å \"%s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó" - -#: ../file_search.c:1515 -#, c-format -msgid "E347: No more file \"%s\" found in path" -msgstr "E347: ¥Ñ¥¹¤Ë¤Ï¤³¤ì°Ê¾å \"%s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó" - -#: ../fileio.c:137 msgid "E812: Autocommands changed buffer or buffer name" msgstr "E812: autocommand¤¬¥Ð¥Ã¥Õ¥¡¤«¥Ð¥Ã¥Õ¥¡Ì¾¤òÊѹ¹¤·¤Þ¤·¤¿" -#: ../fileio.c:368 msgid "Illegal file name" msgstr "ÉÔÀµ¤Ê¥Õ¥¡¥¤¥ë̾" -#: ../fileio.c:395 ../fileio.c:476 ../fileio.c:2543 ../fileio.c:2578 msgid "is a directory" msgstr "¤Ï¥Ç¥£¥ì¥¯¥È¥ê¤Ç¤¹" -#: ../fileio.c:397 msgid "is not a file" msgstr "¤Ï¥Õ¥¡¥¤¥ë¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../fileio.c:508 ../fileio.c:3522 +msgid "is a device (disabled with 'opendevice' option)" +msgstr "¤Ï¥Ç¥Ð¥¤¥¹¤Ç¤¹ ('opendevice' ¥ª¥×¥·¥ç¥ó¤Ç²óÈò¤Ç¤¤Þ¤¹)" + msgid "[New File]" msgstr "[¿·¥Õ¥¡¥¤¥ë]" -#: ../fileio.c:511 msgid "[New DIRECTORY]" msgstr "[¿·µ¬¥Ç¥£¥ì¥¯¥È¥ê]" -#: ../fileio.c:529 ../fileio.c:532 msgid "[File too big]" msgstr "[¥Õ¥¡¥¤¥ë²áÂç]" -#: ../fileio.c:534 msgid "[Permission Denied]" msgstr "[¸¢¸Â¤¬¤¢¤ê¤Þ¤»¤ó]" -#: ../fileio.c:653 msgid "E200: *ReadPre autocommands made the file unreadable" msgstr "E200: *ReadPre autocommand ¤¬¥Õ¥¡¥¤¥ë¤òÆÉ¹þÉԲĤˤ·¤Þ¤·¤¿" -#: ../fileio.c:655 msgid "E201: *ReadPre autocommands must not change current buffer" msgstr "E201: *ReadPre autocommand ¤Ï¸½ºß¤Î¥Ð¥Ã¥Õ¥¡¤òÊѤ¨¤é¤ì¤Þ¤»¤ó" -#: ../fileio.c:672 -msgid "Nvim: Reading from stdin...\n" +msgid "Vim: Reading from stdin...\n" msgstr "Vim: ɸ½àÆþÎϤ«¤éÆÉ¹þÃæ...\n" +msgid "Reading from stdin..." +msgstr "ɸ½àÆþÎϤ«¤éÆÉ¹þ¤ßÃæ..." + #. Re-opening the original file failed! -#: ../fileio.c:909 msgid "E202: Conversion made file unreadable!" msgstr "E202: ÊÑ´¹¤¬¥Õ¥¡¥¤¥ë¤òÆÉ¹þÉԲĤˤ·¤Þ¤·¤¿" -#. fifo or socket -#: ../fileio.c:1782 msgid "[fifo/socket]" msgstr "[FIFO/¥½¥±¥Ã¥È]" -#. fifo -#: ../fileio.c:1788 msgid "[fifo]" msgstr "[FIFO]" -#. or socket -#: ../fileio.c:1794 msgid "[socket]" msgstr "[¥½¥±¥Ã¥È]" -#. or character special -#: ../fileio.c:1801 msgid "[character special]" msgstr "[¥¥ã¥é¥¯¥¿¡¦¥Ç¥Ð¥¤¥¹]" -#: ../fileio.c:1815 msgid "[CR missing]" msgstr "[CR̵]" -#: ../fileio.c:1819 msgid "[long lines split]" msgstr "[Ĺ¹Ôʬ³ä]" -#: ../fileio.c:1823 ../fileio.c:3512 msgid "[NOT converted]" msgstr "[̤ÊÑ´¹]" -#: ../fileio.c:1826 ../fileio.c:3515 msgid "[converted]" msgstr "[ÊÑ´¹ºÑ]" -#: ../fileio.c:1831 #, c-format -msgid "[CONVERSION ERROR in line %<PRId64>]" -msgstr "[%<PRId64> ¹ÔÌܤÇÊÑ´¹¥¨¥é¡¼]" +msgid "[CONVERSION ERROR in line %ld]" +msgstr "[%ld ¹ÔÌܤÇÊÑ´¹¥¨¥é¡¼]" -#: ../fileio.c:1835 #, c-format -msgid "[ILLEGAL BYTE in line %<PRId64>]" -msgstr "[%<PRId64> ¹ÔÌܤÎÉÔÀµ¤Ê¥Ð¥¤¥È]" +msgid "[ILLEGAL BYTE in line %ld]" +msgstr "[%ld ¹ÔÌܤÎÉÔÀµ¤Ê¥Ð¥¤¥È]" -#: ../fileio.c:1838 msgid "[READ ERRORS]" msgstr "[ÆÉ¹þ¥¨¥é¡¼]" -#: ../fileio.c:2104 msgid "Can't find temp file for conversion" msgstr "ÊÑ´¹¤ËɬÍפʰì»þ¥Õ¥¡¥¤¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../fileio.c:2110 msgid "Conversion with 'charconvert' failed" msgstr "'charconvert' ¤Ë¤è¤ëÊÑ´¹¤¬¼ºÇÔ¤·¤Þ¤·¤¿" -#: ../fileio.c:2113 msgid "can't read output of 'charconvert'" msgstr "'charconvert' ¤Î½ÐÎϤòÆÉ¹þ¤á¤Þ¤»¤ó¤Ç¤·¤¿" -#: ../fileio.c:2437 msgid "E676: No matching autocommands for acwrite buffer" msgstr "E676: acwrite¥Ð¥Ã¥Õ¥¡¤Î³ºÅö¤¹¤ëautocommand¤Ï¸ºß¤·¤Þ¤»¤ó" -#: ../fileio.c:2466 msgid "E203: Autocommands deleted or unloaded buffer to be written" msgstr "E203: Êݸ¤¹¤ë¥Ð¥Ã¥Õ¥¡¤òautocommand¤¬ºï½ü¤«²òÊü¤·¤Þ¤·¤¿" -#: ../fileio.c:2486 msgid "E204: Autocommand changed number of lines in unexpected way" msgstr "E204: autocommand¤¬Í½´ü¤»¤ÌÊýË¡¤Ç¹Ô¿ô¤òÊѹ¹¤·¤Þ¤·¤¿" -#: ../fileio.c:2548 ../fileio.c:2565 +# Added at 19-Jan-2004. +msgid "NetBeans disallows writes of unmodified buffers" +msgstr "NetBeans¤Ï̤Êѹ¹¤Î¥Ð¥Ã¥Õ¥¡¤ò¾å½ñ¤¹¤ë¤³¤È¤Ïµö²Ä¤·¤Æ¤¤¤Þ¤»¤ó" + +msgid "Partial writes disallowed for NetBeans buffers" +msgstr "NetBeans¥Ð¥Ã¥Õ¥¡¤Î°ìÉô¤ò½ñ¤½Ð¤¹¤³¤È¤Ï¤Ç¤¤Þ¤»¤ó" + msgid "is not a file or writable device" msgstr "¤Ï¥Õ¥¡¥¤¥ë¤Ç¤â½ñ¹þ¤ß²Äǽ¥Ç¥Ð¥¤¥¹¤Ç¤â¤¢¤ê¤Þ¤»¤ó" -#: ../fileio.c:2601 +msgid "writing to device disabled with 'opendevice' option" +msgstr "'opendevice' ¥ª¥×¥·¥ç¥ó¤Ë¤è¤ê¥Ç¥Ð¥¤¥¹¤Ø¤Î½ñ¤¹þ¤ß¤Ï¤Ç¤¤Þ¤»¤ó" + msgid "is read-only (add ! to override)" msgstr "¤ÏÆÉ¹þÀìÍѤǤ¹ (¶¯À©½ñ¹þ¤Ë¤Ï ! ¤òÄɲÃ)" -#: ../fileio.c:2886 msgid "E506: Can't write to backup file (add ! to override)" msgstr "E506: ¥Ð¥Ã¥¯¥¢¥Ã¥×¥Õ¥¡¥¤¥ë¤òÊݸ¤Ç¤¤Þ¤»¤ó (! ¤òÄɲäǶ¯À©Êݸ)" -#: ../fileio.c:2898 msgid "E507: Close error for backup file (add ! to override)" msgstr "" "E507: ¥Ð¥Ã¥¯¥¢¥Ã¥×¥Õ¥¡¥¤¥ë¤òÊĤ¸¤ëºÝ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤Þ¤·¤¿ (! ¤òÄɲäǶ¯À©)" -#: ../fileio.c:2901 msgid "E508: Can't read file for backup (add ! to override)" msgstr "E508: ¥Ð¥Ã¥¯¥¢¥Ã¥×ÍÑ¥Õ¥¡¥¤¥ë¤òÆÉ¹þ¤á¤Þ¤»¤ó (! ¤òÄɲäǶ¯À©ÆÉ¹þ)" -#: ../fileio.c:2923 msgid "E509: Cannot create backup file (add ! to override)" msgstr "E509: ¥Ð¥Ã¥¯¥¢¥Ã¥×¥Õ¥¡¥¤¥ë¤òºî¤ì¤Þ¤»¤ó (! ¤òÄɲäǶ¯À©ºîÀ®)" -#: ../fileio.c:3008 msgid "E510: Can't make backup file (add ! to override)" msgstr "E510: ¥Ð¥Ã¥¯¥¢¥Ã¥×¥Õ¥¡¥¤¥ë¤òºî¤ì¤Þ¤»¤ó (! ¤òÄɲäǶ¯À©ºîÀ®)" -#. Can't write without a tempfile! -#: ../fileio.c:3121 +msgid "E460: The resource fork would be lost (add ! to override)" +msgstr "E460: ¥ê¥½¡¼¥¹¥Õ¥©¡¼¥¯¤¬¼º¤ï¤ì¤ë¤«¤â¤·¤ì¤Þ¤»¤ó (! ¤òÄɲäǶ¯À©)" + msgid "E214: Can't find temp file for writing" msgstr "E214: ÊݸÍѰì»þ¥Õ¥¡¥¤¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../fileio.c:3134 msgid "E213: Cannot convert (add ! to write without conversion)" msgstr "E213: ÊÑ´¹¤Ç¤¤Þ¤»¤ó (! ¤òÄɲäÇÊÑ´¹¤»¤º¤ËÊݸ)" -#: ../fileio.c:3169 msgid "E166: Can't open linked file for writing" msgstr "E166: ¥ê¥ó¥¯¤µ¤ì¤¿¥Õ¥¡¥¤¥ë¤Ë½ñ¹þ¤á¤Þ¤»¤ó" -#: ../fileio.c:3173 msgid "E212: Can't open file for writing" msgstr "E212: ½ñ¹þ¤ßÍѤ˥ե¡¥¤¥ë¤ò³«¤±¤Þ¤»¤ó" -#: ../fileio.c:3363 msgid "E667: Fsync failed" msgstr "E667: fsync ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#: ../fileio.c:3398 msgid "E512: Close failed" msgstr "E512: ÊĤ¸¤ë¤³¤È¤Ë¼ºÇÔ" -#: ../fileio.c:3436 msgid "E513: write error, conversion failed (make 'fenc' empty to override)" msgstr "E513: ½ñ¹þ¤ß¥¨¥é¡¼, ÊÑ´¹¼ºÇÔ (¾å½ñ¤¹¤ë¤Ë¤Ï 'fenc' ¤ò¶õ¤Ë¤·¤Æ¤¯¤À¤µ¤¤)" -#: ../fileio.c:3441 #, c-format msgid "" -"E513: write error, conversion failed in line %<PRId64> (make 'fenc' empty to " +"E513: write error, conversion failed in line %ld (make 'fenc' empty to " "override)" msgstr "" -"E513: ½ñ¹þ¤ß¥¨¥é¡¼, ÊÑ´¹¼ºÇÔ, ¹Ô¿ô %<PRId64> (¾å½ñ¤¹¤ë¤Ë¤Ï 'fenc' ¤ò¶õ¤Ë¤·¤Æ" -"¤¯¤À¤µ¤¤)" +"E513: ½ñ¹þ¤ß¥¨¥é¡¼, ÊÑ´¹¼ºÇÔ, ¹Ô¿ô %ld (¾å½ñ¤¹¤ë¤Ë¤Ï 'fenc' ¤ò¶õ¤Ë¤·¤Æ¤¯¤À¤µ" +"¤¤)" -#: ../fileio.c:3448 msgid "E514: write error (file system full?)" msgstr "E514: ½ñ¹þ¤ß¥¨¥é¡¼, (¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤¬ËþÇÕ?)" -#: ../fileio.c:3506 msgid " CONVERSION ERROR" msgstr " ÊÑ´¹¥¨¥é¡¼" -#: ../fileio.c:3509 #, c-format -msgid " in line %<PRId64>;" -msgstr " ¹Ô %<PRId64>;" +msgid " in line %ld;" +msgstr " ¹Ô %ld;" -#: ../fileio.c:3519 msgid "[Device]" msgstr "[¥Ç¥Ð¥¤¥¹]" -#: ../fileio.c:3522 msgid "[New]" msgstr "[¿·]" -#: ../fileio.c:3535 msgid " [a]" msgstr " [a]" -#: ../fileio.c:3535 msgid " appended" msgstr " ÄɲÃ" -#: ../fileio.c:3537 msgid " [w]" msgstr " [w]" -#: ../fileio.c:3537 msgid " written" msgstr " ½ñ¹þ¤ß" -#: ../fileio.c:3579 msgid "E205: Patchmode: can't save original file" msgstr "E205: patchmode: ¸¶ËÜ¥Õ¥¡¥¤¥ë¤òÊݸ¤Ç¤¤Þ¤»¤ó" -#: ../fileio.c:3602 msgid "E206: patchmode: can't touch empty original file" msgstr "E206: patchmode: ¶õ¤Î¸¶ËÜ¥Õ¥¡¥¤¥ë¤òtouch¤Ç¤¤Þ¤»¤ó" -#: ../fileio.c:3616 msgid "E207: Can't delete backup file" msgstr "E207: ¥Ð¥Ã¥¯¥¢¥Ã¥×¥Õ¥¡¥¤¥ë¤ò¾Ã¤»¤Þ¤»¤ó" -#: ../fileio.c:3672 msgid "" "\n" "WARNING: Original file may be lost or damaged\n" @@ -2290,134 +1838,105 @@ msgstr "" "\n" "·Ù¹ð: ¸¶ËÜ¥Õ¥¡¥¤¥ë¤¬¼º¤ï¤ì¤¿¤«Êѹ¹¤µ¤ì¤Þ¤·¤¿\n" -#: ../fileio.c:3675 msgid "don't quit the editor until the file is successfully written!" msgstr "¥Õ¥¡¥¤¥ë¤ÎÊݸ¤ËÀ®¸ù¤¹¤ë¤Þ¤Ç¥¨¥Ç¥£¥¿¤ò½ªÎ»¤·¤Ê¤¤¤Ç¤¯¤À¤µ¤¤!" -#: ../fileio.c:3795 msgid "[dos]" msgstr "[dos]" -#: ../fileio.c:3795 msgid "[dos format]" msgstr "[dos¥Õ¥©¡¼¥Þ¥Ã¥È]" -#: ../fileio.c:3801 msgid "[mac]" msgstr "[mac]" -#: ../fileio.c:3801 msgid "[mac format]" msgstr "[mac¥Õ¥©¡¼¥Þ¥Ã¥È]" -#: ../fileio.c:3807 msgid "[unix]" msgstr "[unix]" -#: ../fileio.c:3807 msgid "[unix format]" msgstr "[unix¥Õ¥©¡¼¥Þ¥Ã¥È]" -#: ../fileio.c:3831 msgid "1 line, " msgstr "1 ¹Ô, " -#: ../fileio.c:3833 #, c-format -msgid "%<PRId64> lines, " -msgstr "%<PRId64> ¹Ô, " +msgid "%ld lines, " +msgstr "%ld ¹Ô, " -#: ../fileio.c:3836 msgid "1 character" msgstr "1 ʸ»ú" -#: ../fileio.c:3838 #, c-format -msgid "%<PRId64> characters" -msgstr "%<PRId64> ʸ»ú" +msgid "%lld characters" +msgstr "%lld ʸ»ú" -#: ../fileio.c:3849 msgid "[noeol]" msgstr "[noeol]" -#: ../fileio.c:3849 msgid "[Incomplete last line]" msgstr "[ºÇ½ª¹Ô¤¬ÉÔ´°Á´]" #. don't overwrite messages here #. must give this prompt #. don't use emsg() here, don't want to flush the buffers -#: ../fileio.c:3865 msgid "WARNING: The file has been changed since reading it!!!" msgstr "·Ù¹ð: ÆÉ¹þ¤ó¤À¸å¤Ë¥Õ¥¡¥¤¥ë¤ËÊѹ¹¤¬¤¢¤ê¤Þ¤·¤¿!!!" -#: ../fileio.c:3867 msgid "Do you really want to write to it" msgstr "ËÜÅö¤Ë¾å½ñ¤¤·¤Þ¤¹¤«" -#: ../fileio.c:4648 #, c-format msgid "E208: Error writing to \"%s\"" msgstr "E208: \"%s\" ¤ò½ñ¹þ¤ßÃæ¤Î¥¨¥é¡¼¤Ç¤¹" -#: ../fileio.c:4655 #, c-format msgid "E209: Error closing \"%s\"" msgstr "E209: \"%s\" ¤òÊĤ¸¤ë»þ¤Ë¥¨¥é¡¼¤Ç¤¹" -#: ../fileio.c:4657 #, c-format msgid "E210: Error reading \"%s\"" msgstr "E210: \"%s\" ¤òÆÉ¹þÃæ¤Î¥¨¥é¡¼¤Ç¤¹" -#: ../fileio.c:4883 msgid "E246: FileChangedShell autocommand deleted buffer" msgstr "E246: autocommand ¤Î FileChangedShell ¤¬¥Ð¥Ã¥Õ¥¡¤òºï½ü¤·¤Þ¤·¤¿" -#: ../fileio.c:4894 #, c-format msgid "E211: File \"%s\" no longer available" msgstr "E211: ¥Õ¥¡¥¤¥ë \"%s\" ¤Ï´û¤Ë¸ºß¤·¤Þ¤»¤ó" -#: ../fileio.c:4906 #, c-format msgid "" "W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as " "well" msgstr "W12: ·Ù¹ð: ¥Õ¥¡¥¤¥ë \"%s\" ¤¬Êѹ¹¤µ¤ìVim¤Î¥Ð¥Ã¥Õ¥¡¤âÊѹ¹¤µ¤ì¤Þ¤·¤¿" -#: ../fileio.c:4907 msgid "See \":help W12\" for more info." msgstr "¾ÜºÙ¤Ï \":help W12\" ¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤" -#: ../fileio.c:4910 #, c-format msgid "W11: Warning: File \"%s\" has changed since editing started" msgstr "W11: ·Ù¹ð: ¥Õ¥¡¥¤¥ë \"%s\" ¤ÏÊÔ½¸³«»Ï¸å¤ËÊѹ¹¤µ¤ì¤Þ¤·¤¿" -#: ../fileio.c:4911 msgid "See \":help W11\" for more info." msgstr "¾ÜºÙ¤Ï \":help W11\" ¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤" -#: ../fileio.c:4914 #, c-format msgid "W16: Warning: Mode of file \"%s\" has changed since editing started" msgstr "W16: ·Ù¹ð: ¥Õ¥¡¥¤¥ë \"%s\" ¤Î¥â¡¼¥É¤¬ÊÔ½¸³«»Ï¸å¤ËÊѹ¹¤µ¤ì¤Þ¤·¤¿" -#: ../fileio.c:4915 msgid "See \":help W16\" for more info." msgstr "¾ÜºÙ¤Ï \":help W16\" ¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤" -#: ../fileio.c:4927 #, c-format msgid "W13: Warning: File \"%s\" has been created after editing started" msgstr "W13: ·Ù¹ð: ¥Õ¥¡¥¤¥ë \"%s\" ¤ÏÊÔ½¸³«»Ï¸å¤ËºîÀ®¤µ¤ì¤Þ¤·¤¿" -#: ../fileio.c:4947 msgid "Warning" msgstr "·Ù¹ð" -#: ../fileio.c:4948 msgid "" "&OK\n" "&Load File" @@ -2425,48 +1944,45 @@ msgstr "" "&OK\n" "¥Õ¥¡¥¤¥ëÆÉ¹þ(&L)" -#: ../fileio.c:5065 #, c-format msgid "E462: Could not prepare for reloading \"%s\"" msgstr "E462: \"%s\" ¤ò¥ê¥í¡¼¥É¤¹¤ë½àÈ÷¤¬¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" -#: ../fileio.c:5078 #, c-format msgid "E321: Could not reload \"%s\"" msgstr "E321: \"%s\" ¤Ï¥ê¥í¡¼¥É¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" -#: ../fileio.c:5601 msgid "--Deleted--" msgstr "--ºï½üºÑ--" -#: ../fileio.c:5732 #, c-format msgid "auto-removing autocommand: %s <buffer=%d>" msgstr "autocommand: %s <¥Ð¥Ã¥Õ¥¡=%d> ¤¬¼«Æ°Åª¤Ëºï½ü¤µ¤ì¤Þ¤¹" #. the group doesn't exist -#: ../fileio.c:5772 #, c-format msgid "E367: No such group: \"%s\"" msgstr "E367: ¤½¤Î¥°¥ë¡¼¥×¤Ï¤¢¤ê¤Þ¤»¤ó: \"%s\"" -#: ../fileio.c:5897 +msgid "E936: Cannot delete the current group" +msgstr "E936: ¸½ºß¤Î¥°¥ë¡¼¥×¤Ïºï½ü¤Ç¤¤Þ¤»¤ó" + +msgid "W19: Deleting augroup that is still in use" +msgstr "W19: »ÈÍÑÃæ¤Î augroup ¤ò¾Ã¤½¤¦¤È¤·¤Æ¤¤¤Þ¤¹" + #, c-format msgid "E215: Illegal character after *: %s" msgstr "E215: * ¤Î¸å¤ËÉÔÀµ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤·¤¿: %s" -#: ../fileio.c:5905 #, c-format msgid "E216: No such event: %s" msgstr "E216: ¤½¤Î¤è¤¦¤Ê¥¤¥Ù¥ó¥È¤Ï¤¢¤ê¤Þ¤»¤ó: %s" -#: ../fileio.c:5907 #, c-format msgid "E216: No such group or event: %s" msgstr "E216: ¤½¤Î¤è¤¦¤Ê¥°¥ë¡¼¥×¤â¤·¤¯¤Ï¥¤¥Ù¥ó¥È¤Ï¤¢¤ê¤Þ¤»¤ó: %s" #. Highlight title -#: ../fileio.c:6090 msgid "" "\n" "--- Auto-Commands ---" @@ -2474,756 +1990,555 @@ msgstr "" "\n" "--- Auto-Commands ---" -#: ../fileio.c:6293 #, c-format msgid "E680: <buffer=%d>: invalid buffer number " msgstr "E680: <¥Ð¥Ã¥Õ¥¡=%d>: ̵¸ú¤Ê¥Ð¥Ã¥Õ¥¡ÈÖ¹æ¤Ç¤¹ " -#: ../fileio.c:6370 msgid "E217: Can't execute autocommands for ALL events" msgstr "E217: Á´¤Æ¤Î¥¤¥Ù¥ó¥È¤ËÂФ·¤Æ¤Îautocommand¤Ï¼Â¹Ô¤Ç¤¤Þ¤»¤ó" -#: ../fileio.c:6393 msgid "No matching autocommands" msgstr "³ºÅö¤¹¤ëautocommand¤Ï¸ºß¤·¤Þ¤»¤ó" -#: ../fileio.c:6831 msgid "E218: autocommand nesting too deep" msgstr "E218: autocommand¤ÎÆþ¤ì»Ò¤¬¿¼²á¤®¤Þ¤¹" -#: ../fileio.c:7143 #, c-format msgid "%s Auto commands for \"%s\"" msgstr "%s Auto commands for \"%s\"" -#: ../fileio.c:7149 #, c-format msgid "Executing %s" msgstr "%s ¤ò¼Â¹Ô¤·¤Æ¤¤¤Þ¤¹" -#: ../fileio.c:7211 #, c-format msgid "autocommand %s" msgstr "autocommand %s" -#: ../fileio.c:7795 msgid "E219: Missing {." msgstr "E219: { ¤¬¤¢¤ê¤Þ¤»¤ó." -#: ../fileio.c:7797 msgid "E220: Missing }." msgstr "E220: } ¤¬¤¢¤ê¤Þ¤»¤ó." -#: ../fold.c:93 msgid "E490: No fold found" msgstr "E490: ÀÞ¾ö¤ß¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../fold.c:544 msgid "E350: Cannot create fold with current 'foldmethod'" msgstr "E350: ¸½ºß¤Î 'foldmethod' ¤Ç¤ÏÀÞ¾ö¤ß¤òºîÀ®¤Ç¤¤Þ¤»¤ó" -#: ../fold.c:546 msgid "E351: Cannot delete fold with current 'foldmethod'" msgstr "E351: ¸½ºß¤Î 'foldmethod' ¤Ç¤ÏÀÞ¾ö¤ß¤òºï½ü¤Ç¤¤Þ¤»¤ó" -#: ../fold.c:1784 #, c-format -msgid "+--%3ld lines folded " -msgstr "+--%3ld ¹Ô¤¬ÀÞ¾ö¤Þ¤ì¤Þ¤·¤¿ " +msgid "+--%3ld line folded " +msgid_plural "+--%3ld lines folded " +msgstr[0] "+--%3ld ¹Ô¤¬ÀÞ¾ö¤Þ¤ì¤Þ¤·¤¿ " -#. buffer has already been read -#: ../getchar.c:273 msgid "E222: Add to read buffer" msgstr "E222: ÆÉ¹þ¥Ð¥Ã¥Õ¥¡¤ØÄɲÃ" -#: ../getchar.c:2040 msgid "E223: recursive mapping" msgstr "E223: ºÆµ¢Åª¥Þ¥Ã¥Ô¥ó¥°" -#: ../getchar.c:2849 #, c-format msgid "E224: global abbreviation already exists for %s" msgstr "E224: %s ¤È¤¤¤¦¥°¥í¡¼¥Ð¥ëû½ÌÆþÎϤϴû¤Ë¸ºß¤·¤Þ¤¹" -#: ../getchar.c:2852 #, c-format msgid "E225: global mapping already exists for %s" msgstr "E225: %s ¤È¤¤¤¦¥°¥í¡¼¥Ð¥ë¥Þ¥Ã¥Ô¥ó¥°¤Ï´û¤Ë¸ºß¤·¤Þ¤¹" -#: ../getchar.c:2952 #, c-format msgid "E226: abbreviation already exists for %s" msgstr "E226: %s ¤È¤¤¤¦Ã»½ÌÆþÎϤϴû¤Ë¸ºß¤·¤Þ¤¹" -#: ../getchar.c:2955 #, c-format msgid "E227: mapping already exists for %s" msgstr "E227: %s ¤È¤¤¤¦¥Þ¥Ã¥Ô¥ó¥°¤Ï´û¤Ë¸ºß¤·¤Þ¤¹" -#: ../getchar.c:3008 msgid "No abbreviation found" msgstr "û½ÌÆþÎϤϸ«¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿" -#: ../getchar.c:3010 msgid "No mapping found" msgstr "¥Þ¥Ã¥Ô¥ó¥°¤Ï¸«¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿" -#: ../getchar.c:3974 msgid "E228: makemap: Illegal mode" msgstr "E228: makemap: ÉÔÀµ¤Ê¥â¡¼¥É" -#. key value of 'cedit' option -#. type of cmdline window or 0 -#. result of cmdline window or 0 -#: ../globals.h:924 -msgid "--No lines in buffer--" -msgstr "--¥Ð¥Ã¥Õ¥¡¤Ë¹Ô¤¬¤¢¤ê¤Þ¤»¤ó--" +msgid "E851: Failed to create a new process for the GUI" +msgstr "E851: GUIÍÑ¤Î¥×¥í¥»¥¹¤Îµ¯Æ°¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#. -#. * The error messages that can be shared are included here. -#. * Excluded are errors that are only used once and debugging messages. -#. -#: ../globals.h:996 -msgid "E470: Command aborted" -msgstr "E470: ¥³¥Þ¥ó¥É¤¬ÃæÃǤµ¤ì¤Þ¤·¤¿" +msgid "E852: The child process failed to start the GUI" +msgstr "E852: »Ò¥×¥í¥»¥¹¤¬GUI¤Îµ¯Æ°¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#: ../globals.h:997 -msgid "E471: Argument required" -msgstr "E471: °ú¿ô¤¬É¬ÍפǤ¹" +msgid "E229: Cannot start the GUI" +msgstr "E229: GUI¤ò³«»Ï¤Ç¤¤Þ¤»¤ó" -#: ../globals.h:998 -msgid "E10: \\ should be followed by /, ? or &" -msgstr "E10: \\ ¤Î¸å¤Ï / ¤« ? ¤« & ¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" +#, c-format +msgid "E230: Cannot read from \"%s\"" +msgstr "E230: \"%s\"¤«¤éÆÉ¹þ¤à¤³¤È¤¬¤Ç¤¤Þ¤»¤ó" -#: ../globals.h:1000 -msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" -msgstr "E11: ¥³¥Þ¥ó¥É¥é¥¤¥ó¤Ç¤Ï̵¸ú¤Ç¤¹; <CR>¤Ç¼Â¹Ô, CTRL-C¤Ç¤ä¤á¤ë" +msgid "E665: Cannot start GUI, no valid font found" +msgstr "E665: ͸ú¤Ê¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤¤¤Î¤Ç, GUI¤ò³«»Ï¤Ç¤¤Þ¤»¤ó" -#: ../globals.h:1002 -msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" -msgstr "" -"E12: ¸½ºß¤Î¥Ç¥£¥ì¥¯¥È¥ê¤ä¥¿¥°¸¡º÷¤Ç¤Ïexrc/vimrc¤Î¥³¥Þ¥ó¥É¤Ïµö²Ä¤µ¤ì¤Þ¤»¤ó" +msgid "E231: 'guifontwide' invalid" +msgstr "E231: 'guifontwide' ¤¬Ìµ¸ú¤Ç¤¹" -#: ../globals.h:1003 -msgid "E171: Missing :endif" -msgstr "E171: :endif ¤¬¤¢¤ê¤Þ¤»¤ó" +msgid "E599: Value of 'imactivatekey' is invalid" +msgstr "E599: 'imactivatekey' ¤ËÀßÄꤵ¤ì¤¿Ãͤ¬Ìµ¸ú¤Ç¤¹" -#: ../globals.h:1004 -msgid "E600: Missing :endtry" -msgstr "E600: :endtry ¤¬¤¢¤ê¤Þ¤»¤ó" +#, c-format +msgid "E254: Cannot allocate color %s" +msgstr "E254: %s ¤Î¿§¤ò³ä¤êÅö¤Æ¤é¤ì¤Þ¤»¤ó" -#: ../globals.h:1005 -msgid "E170: Missing :endwhile" -msgstr "E170: :endwhile ¤¬¤¢¤ê¤Þ¤»¤ó" +msgid "No match at cursor, finding next" +msgstr "¥«¡¼¥½¥ë¤Î°ÌÃ֤˥ޥåÁ¤Ï¤¢¤ê¤Þ¤»¤ó, ¼¡¤ò¸¡º÷¤·¤Æ¤¤¤Þ¤¹" -#: ../globals.h:1006 -msgid "E170: Missing :endfor" -msgstr "E170: :endfor ¤¬¤¢¤ê¤Þ¤»¤ó" - -#: ../globals.h:1007 -msgid "E588: :endwhile without :while" -msgstr "E588: :while ¤Î¤Ê¤¤ :endwhile ¤¬¤¢¤ê¤Þ¤¹" +msgid "<cannot open> " +msgstr "<³«¤±¤Þ¤»¤ó> " -#: ../globals.h:1008 -msgid "E588: :endfor without :for" -msgstr "E588: :endfor ¤Î¤Ê¤¤ :for ¤¬¤¢¤ê¤Þ¤¹" +#, c-format +msgid "E616: vim_SelFile: can't get font %s" +msgstr "E616: vim_SelFile: ¥Õ¥©¥ó¥È %s ¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó" -#: ../globals.h:1009 -msgid "E13: File exists (add ! to override)" -msgstr "E13: ¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤·¤Þ¤¹ (! ¤òÄɲäǾå½ñ)" +msgid "E614: vim_SelFile: can't return to current directory" +msgstr "E614: vim_SelFile: ¸½ºß¤Î¥Ç¥£¥ì¥¯¥È¥ê¤ËÌá¤ì¤Þ¤»¤ó" -#: ../globals.h:1010 -msgid "E472: Command failed" -msgstr "E472: ¥³¥Þ¥ó¥É¤¬¼ºÇÔ¤·¤Þ¤·¤¿" +msgid "Pathname:" +msgstr "¥Ñ¥¹Ì¾:" -#: ../globals.h:1011 -msgid "E473: Internal error" -msgstr "E473: ÆâÉô¥¨¥é¡¼¤Ç¤¹" +msgid "E615: vim_SelFile: can't get current directory" +msgstr "E615: vim_SelFile: ¸½ºß¤Î¥Ç¥£¥ì¥¯¥È¥ê¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó" -#: ../globals.h:1012 -msgid "Interrupted" -msgstr "³ä¹þ¤Þ¤ì¤Þ¤·¤¿" +msgid "OK" +msgstr "OK" -#: ../globals.h:1013 -msgid "E14: Invalid address" -msgstr "E14: ̵¸ú¤Ê¥¢¥É¥ì¥¹¤Ç¤¹" +msgid "Cancel" +msgstr "¥¥ã¥ó¥»¥ë" -#: ../globals.h:1014 -msgid "E474: Invalid argument" -msgstr "E474: ̵¸ú¤Ê°ú¿ô¤Ç¤¹" +msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." +msgstr "¥¹¥¯¥í¡¼¥ë¥Ð¡¼: ²èÁü¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿." -#: ../globals.h:1015 -#, c-format -msgid "E475: Invalid argument: %s" -msgstr "E475: ̵¸ú¤Ê°ú¿ô¤Ç¤¹: %s" +msgid "Vim dialog" +msgstr "Vim ¥À¥¤¥¢¥í¥°" -#: ../globals.h:1016 -#, c-format -msgid "E15: Invalid expression: %s" -msgstr "E15: ̵¸ú¤Ê¼°¤Ç¤¹: %s" +msgid "E232: Cannot create BalloonEval with both message and callback" +msgstr "E232: ¥á¥Ã¥»¡¼¥¸¤È¥³¡¼¥ë¥Ð¥Ã¥¯¤Î¤¢¤ë BalloonEval ¤òºîÀ®¤Ç¤¤Þ¤»¤ó" -#: ../globals.h:1017 -msgid "E16: Invalid range" -msgstr "E16: ̵¸ú¤ÊÈϰϤǤ¹" +msgid "_Cancel" +msgstr "¥¥ã¥ó¥»¥ë(_C)" -#: ../globals.h:1018 -msgid "E476: Invalid command" -msgstr "E476: ̵¸ú¤Ê¥³¥Þ¥ó¥É¤Ç¤¹" +msgid "_Save" +msgstr "Êݸ(_S)" -#: ../globals.h:1019 -#, c-format -msgid "E17: \"%s\" is a directory" -msgstr "E17: \"%s\" ¤Ï¥Ç¥£¥ì¥¯¥È¥ê¤Ç¤¹" +msgid "_Open" +msgstr "³«¤¯(_O)" -#: ../globals.h:1020 -#, fuzzy -msgid "E900: Invalid job id" -msgstr "E49: ̵¸ú¤Ê¥¹¥¯¥í¡¼¥ëÎ̤Ǥ¹" +msgid "_OK" +msgstr "_OK" -#: ../globals.h:1021 -msgid "E901: Job table is full" +msgid "" +"&Yes\n" +"&No\n" +"&Cancel" msgstr "" +"¤Ï¤¤(&Y)\n" +"¤¤¤¤¤¨(&N)\n" +"¥¥ã¥ó¥»¥ë(&C)" -#: ../globals.h:1024 -#, c-format -msgid "E364: Library call failed for \"%s()\"" -msgstr "E364: \"%s\"() ¤Î¥é¥¤¥Ö¥é¥ê¸Æ½Ð¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" +msgid "Yes" +msgstr "¤Ï¤¤" -#: ../globals.h:1026 -msgid "E19: Mark has invalid line number" -msgstr "E19: ¥Þ¡¼¥¯¤Ë̵¸ú¤Ê¹ÔÈֹ椬»ØÄꤵ¤ì¤Æ¤¤¤Þ¤·¤¿" +msgid "No" +msgstr "¤¤¤¤¤¨" -#: ../globals.h:1027 -msgid "E20: Mark not set" -msgstr "E20: ¥Þ¡¼¥¯¤ÏÀßÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó" +msgid "Input _Methods" +msgstr "¥¤¥ó¥×¥Ã¥È¥á¥½¥Ã¥É" -#: ../globals.h:1029 -msgid "E21: Cannot make changes, 'modifiable' is off" -msgstr "E21: 'modifiable' ¤¬¥ª¥Õ¤Ê¤Î¤Ç, Êѹ¹¤Ç¤¤Þ¤»¤ó" +msgid "VIM - Search and Replace..." +msgstr "VIM - ¸¡º÷¤ÈÃÖ´¹..." -#: ../globals.h:1030 -msgid "E22: Scripts nested too deep" -msgstr "E22: ¥¹¥¯¥ê¥×¥È¤ÎÆþ¤ì»Ò¤¬¿¼²á¤®¤Þ¤¹" +msgid "VIM - Search..." +msgstr "VIM - ¸¡º÷..." -#: ../globals.h:1031 -msgid "E23: No alternate file" -msgstr "E23: Éû¥Õ¥¡¥¤¥ë¤Ï¤¢¤ê¤Þ¤»¤ó" +msgid "Find what:" +msgstr "¸¡º÷ʸ»úÎó:" -#: ../globals.h:1032 -msgid "E24: No such abbreviation" -msgstr "E24: ¤½¤Î¤è¤¦¤Êû½ÌÆþÎϤϤ¢¤ê¤Þ¤»¤ó" +msgid "Replace with:" +msgstr "ÃÖ´¹Ê¸»úÎó:" -#: ../globals.h:1033 -msgid "E477: No ! allowed" -msgstr "E477: ! ¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" +#. whole word only button +msgid "Match whole word only" +msgstr "Àµ³Î¤Ë³ºÅö¤¹¤ë¤â¤Î¤À¤±" -#: ../globals.h:1035 -msgid "E25: Nvim does not have a built-in GUI" -msgstr "E25: GUI¤Ï»ÈÍÑÉÔ²Äǽ¤Ç¤¹: ¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹" +#. match case button +msgid "Match case" +msgstr "Âçʸ»ú/¾®Ê¸»ú¤ò¶èÊ̤¹¤ë" -#: ../globals.h:1036 -#, c-format -msgid "E28: No such highlight group name: %s" -msgstr "E28: ¤½¤Î¤è¤¦¤Ê̾¤Î¥Ï¥¤¥é¥¤¥È¥°¥ë¡¼¥×¤Ï¤¢¤ê¤Þ¤»¤ó: %s" +msgid "Direction" +msgstr "Êý¸þ" -#: ../globals.h:1037 -msgid "E29: No inserted text yet" -msgstr "E29: ¤Þ¤À¥Æ¥¥¹¥È¤¬ÁÞÆþ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" +#. 'Up' and 'Down' buttons +msgid "Up" +msgstr "¾å" -#: ../globals.h:1038 -msgid "E30: No previous command line" -msgstr "E30: °ÊÁ°¤Ë¥³¥Þ¥ó¥É¹Ô¤¬¤¢¤ê¤Þ¤»¤ó" +msgid "Down" +msgstr "²¼" -#: ../globals.h:1039 -msgid "E31: No such mapping" -msgstr "E31: ¤½¤Î¤è¤¦¤Ê¥Þ¥Ã¥Ô¥ó¥°¤Ï¤¢¤ê¤Þ¤»¤ó" +msgid "Find Next" +msgstr "¼¡¤ò¸¡º÷" -#: ../globals.h:1040 -msgid "E479: No match" -msgstr "E479: ³ºÅö¤Ï¤¢¤ê¤Þ¤»¤ó" +msgid "Replace" +msgstr "ÃÖ´¹" -#: ../globals.h:1041 -#, c-format -msgid "E480: No match: %s" -msgstr "E480: ³ºÅö¤Ï¤¢¤ê¤Þ¤»¤ó: %s" +msgid "Replace All" +msgstr "Á´¤ÆÃÖ´¹" -#: ../globals.h:1042 -msgid "E32: No file name" -msgstr "E32: ¥Õ¥¡¥¤¥ë̾¤¬¤¢¤ê¤Þ¤»¤ó" +msgid "_Close" +msgstr "ÊĤ¸¤ë(_C)" -#: ../globals.h:1044 -msgid "E33: No previous substitute regular expression" -msgstr "E33: Àµµ¬É½¸½ÃÖ´¹¤¬¤Þ¤À¼Â¹Ô¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" +msgid "Vim: Received \"die\" request from session manager\n" +msgstr "Vim: ¥»¥Ã¥·¥ç¥ó¥Þ¥Í¡¼¥¸¥ã¤«¤é \"die\" Í×µá¤ò¼õ¤±¼è¤ê¤Þ¤·¤¿\n" -#: ../globals.h:1045 -msgid "E34: No previous command" -msgstr "E34: ¥³¥Þ¥ó¥É¤¬¤Þ¤À¼Â¹Ô¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" +msgid "Close tab" +msgstr "¥¿¥Ö¥Ú¡¼¥¸¤òÊĤ¸¤ë" -#: ../globals.h:1046 -msgid "E35: No previous regular expression" -msgstr "E35: Àµµ¬É½¸½¤¬¤Þ¤À¼Â¹Ô¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" +msgid "New tab" +msgstr "¿·µ¬¥¿¥Ö¥Ú¡¼¥¸" -#: ../globals.h:1047 -msgid "E481: No range allowed" -msgstr "E481: ÈϰϻØÄê¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" +msgid "Open Tab..." +msgstr "¥¿¥Ö¥Ú¡¼¥¸¤ò³«¤¯..." -#: ../globals.h:1048 -msgid "E36: Not enough room" -msgstr "E36: ¥¦¥£¥ó¥É¥¦¤Ë½½Ê¬¤Ê¹â¤µ¤â¤·¤¯¤ÏÉý¤¬¤¢¤ê¤Þ¤»¤ó" +msgid "Vim: Main window unexpectedly destroyed\n" +msgstr "Vim: ¥á¥¤¥ó¥¦¥£¥ó¥É¥¦¤¬ÉÔ°Õ¤ËÇ˲õ¤µ¤ì¤Þ¤·¤¿\n" -#: ../globals.h:1049 -#, c-format -msgid "E482: Can't create file %s" -msgstr "E482: ¥Õ¥¡¥¤¥ë %s ¤òºîÀ®¤Ç¤¤Þ¤»¤ó" +msgid "&Filter" +msgstr "¥Õ¥£¥ë¥¿(&F)" -#: ../globals.h:1050 -msgid "E483: Can't get temp file name" -msgstr "E483: °ì»þ¥Õ¥¡¥¤¥ë¤Î̾Á°¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó" +msgid "&Cancel" +msgstr "¥¥ã¥ó¥»¥ë(&C)" -#: ../globals.h:1051 -#, c-format -msgid "E484: Can't open file %s" -msgstr "E484: ¥Õ¥¡¥¤¥ë \"%s\" ¤ò³«¤±¤Þ¤»¤ó" +msgid "Directories" +msgstr "¥Ç¥£¥ì¥¯¥È¥ê" -#: ../globals.h:1052 -#, c-format -msgid "E485: Can't read file %s" -msgstr "E485: ¥Õ¥¡¥¤¥ë %s ¤òÆÉ¹þ¤á¤Þ¤»¤ó" +msgid "Filter" +msgstr "¥Õ¥£¥ë¥¿" -#: ../globals.h:1054 -msgid "E37: No write since last change (add ! to override)" -msgstr "E37: ºÇ¸å¤ÎÊѹ¹¤¬Êݸ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó (! ¤òÄɲäÇÊѹ¹¤òÇË´þ)" +msgid "&Help" +msgstr "¥Ø¥ë¥×(&H)" -#: ../globals.h:1055 -msgid "E37: No write since last change" -msgstr "E37: ºÇ¸å¤ÎÊѹ¹¤¬Êݸ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" +msgid "Files" +msgstr "¥Õ¥¡¥¤¥ë" -#: ../globals.h:1056 -msgid "E38: Null argument" -msgstr "E38: °ú¿ô¤¬¶õ¤Ç¤¹" +msgid "&OK" +msgstr "&OK" -#: ../globals.h:1057 -msgid "E39: Number expected" -msgstr "E39: ¿ôÃͤ¬Í׵ᤵ¤ì¤Æ¤¤¤Þ¤¹" +msgid "Selection" +msgstr "ÁªÂò" -#: ../globals.h:1058 -#, c-format -msgid "E40: Can't open errorfile %s" -msgstr "E40: ¥¨¥é¡¼¥Õ¥¡¥¤¥ë %s ¤ò³«¤±¤Þ¤»¤ó" +msgid "Find &Next" +msgstr "¼¡¤ò¸¡º÷(&N)" -#: ../globals.h:1059 -msgid "E41: Out of memory!" -msgstr "E41: ¥á¥â¥ê¤¬¿Ô¤²Ì¤Æ¤Þ¤·¤¿!" +msgid "&Replace" +msgstr "ÃÖ´¹(&R)" -#: ../globals.h:1060 -msgid "Pattern not found" -msgstr "¥Ñ¥¿¡¼¥ó¤Ï¸«¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿" +msgid "Replace &All" +msgstr "Á´¤ÆÃÖ´¹(&A)" -#: ../globals.h:1061 -#, c-format -msgid "E486: Pattern not found: %s" -msgstr "E486: ¥Ñ¥¿¡¼¥ó¤Ï¸«¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿: %s" +msgid "&Undo" +msgstr "¥¢¥ó¥É¥¥(&U)" -#: ../globals.h:1062 -msgid "E487: Argument must be positive" -msgstr "E487: °ú¿ô¤ÏÀµ¤ÎÃͤǤʤ±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" +msgid "Open tab..." +msgstr "¥¿¥Ö¥Ú¡¼¥¸¤ò³«¤¯" -#: ../globals.h:1064 -msgid "E459: Cannot go back to previous directory" -msgstr "E459: Á°¤Î¥Ç¥£¥ì¥¯¥È¥ê¤ËÌá¤ì¤Þ¤»¤ó" +msgid "Find string (use '\\\\' to find a '\\')" +msgstr "¸¡º÷ʸ»úÎó ('\\' ¤ò¸¡º÷¤¹¤ë¤Ë¤Ï '\\\\')" -#: ../globals.h:1066 -msgid "E42: No Errors" -msgstr "E42: ¥¨¥é¡¼¤Ï¤¢¤ê¤Þ¤»¤ó" +msgid "Find & Replace (use '\\\\' to find a '\\')" +msgstr "¸¡º÷¡¦ÃÖ´¹ ('\\' ¤ò¸¡º÷¤¹¤ë¤Ë¤Ï '\\\\')" -#: ../globals.h:1067 -msgid "E776: No location list" -msgstr "E776: ¥í¥±¡¼¥·¥ç¥ó¥ê¥¹¥È¤Ï¤¢¤ê¤Þ¤»¤ó" - -#: ../globals.h:1068 -msgid "E43: Damaged match string" -msgstr "E43: ³ºÅöʸ»úÎó¤¬ÇË»¤·¤Æ¤¤¤Þ¤¹" +#. We fake this: Use a filter that doesn't select anything and a default +#. * file name that won't be used. +msgid "Not Used" +msgstr "»È¤ï¤ì¤Þ¤»¤ó" -#: ../globals.h:1069 -msgid "E44: Corrupted regexp program" -msgstr "E44: ÉÔÀµ¤ÊÀµµ¬É½¸½¥×¥í¥°¥é¥à¤Ç¤¹" +msgid "Directory\t*.nothing\n" +msgstr "¥Ç¥£¥ì¥¯¥È¥ê\t*.nothing\n" -#: ../globals.h:1071 -msgid "E45: 'readonly' option is set (add ! to override)" -msgstr "E45: 'readonly' ¥ª¥×¥·¥ç¥ó¤¬ÀßÄꤵ¤ì¤Æ¤¤¤Þ¤¹ (! ¤òÄɲäǾå½ñ¤)" - -#: ../globals.h:1073 #, c-format -msgid "E46: Cannot change read-only variable \"%s\"" -msgstr "E46: ÆÉ¼èÀìÍÑÊÑ¿ô \"%s\" ¤Ë¤ÏÃͤòÀßÄê¤Ç¤¤Þ¤»¤ó" +msgid "E671: Cannot find window title \"%s\"" +msgstr "E671: ¥¿¥¤¥È¥ë¤¬ \"%s\" ¤Î¥¦¥£¥ó¥É¥¦¤Ï¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../globals.h:1075 #, c-format -msgid "E794: Cannot set variable in the sandbox: \"%s\"" -msgstr "E794: ¥µ¥ó¥É¥Ü¥Ã¥¯¥¹¤Ç¤ÏÊÑ¿ô \"%s\" ¤ËÃͤòÀßÄê¤Ç¤¤Þ¤»¤ó" - -#: ../globals.h:1076 -msgid "E47: Error while reading errorfile" -msgstr "E47: ¥¨¥é¡¼¥Õ¥¡¥¤¥ë¤ÎÆÉ¹þÃæ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤Þ¤·¤¿" - -#: ../globals.h:1078 -msgid "E48: Not allowed in sandbox" -msgstr "E48: ¥µ¥ó¥É¥Ü¥Ã¥¯¥¹¤Ç¤Ïµö¤µ¤ì¤Þ¤»¤ó" - -#: ../globals.h:1080 -msgid "E523: Not allowed here" -msgstr "E523: ¤³¤³¤Ç¤Ïµö²Ä¤µ¤ì¤Þ¤»¤ó" +msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." +msgstr "E243: °ú¿ô¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó: \"-%s\"; OLEÈǤò»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤." -#: ../globals.h:1082 -msgid "E359: Screen mode setting not supported" -msgstr "E359: ¥¹¥¯¥ê¡¼¥ó¥â¡¼¥É¤ÎÀßÄê¤Ë¤ÏÂбþ¤·¤Æ¤¤¤Þ¤»¤ó" +msgid "E672: Unable to open window inside MDI application" +msgstr "E672: MDI¥¢¥×¥ê¤ÎÃæ¤Ç¤Ï¥¦¥£¥ó¥É¥¦¤ò³«¤±¤Þ¤»¤ó" -#: ../globals.h:1083 -msgid "E49: Invalid scroll size" -msgstr "E49: ̵¸ú¤Ê¥¹¥¯¥í¡¼¥ëÎ̤Ǥ¹" +msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" +msgstr "Vim E458: ¿§»ØÄ꤬Àµ¤·¤¯¤Ê¤¤¤Î¤Ç¥¨¥ó¥È¥ê¤ò³ä¤êÅö¤Æ¤é¤ì¤Þ¤»¤ó" -#: ../globals.h:1084 -msgid "E91: 'shell' option is empty" -msgstr "E91: 'shell' ¥ª¥×¥·¥ç¥ó¤¬¶õ¤Ç¤¹" +#, c-format +msgid "E250: Fonts for the following charsets are missing in fontset %s:" +msgstr "E250: °Ê²¼¤Îʸ»ú¥»¥Ã¥È¤Î¥Õ¥©¥ó¥È¤¬¤¢¤ê¤Þ¤»¤ó %s:" -#: ../globals.h:1085 -msgid "E255: Couldn't read in sign data!" -msgstr "E255: sign ¤Î¥Ç¡¼¥¿¤òÆÉ¹þ¤á¤Þ¤»¤ó¤Ç¤·¤¿" +#, c-format +msgid "E252: Fontset name: %s" +msgstr "E252: ¥Õ¥©¥ó¥È¥»¥Ã¥È̾: %s" -#: ../globals.h:1086 -msgid "E72: Close error on swap file" -msgstr "E72: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤Î¥¯¥í¡¼¥º»þ¥¨¥é¡¼¤Ç¤¹" +#, c-format +msgid "Font '%s' is not fixed-width" +msgstr "¥Õ¥©¥ó¥È '%s' ¤Ï¸ÇÄêÉý¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../globals.h:1087 -msgid "E73: tag stack empty" -msgstr "E73: ¥¿¥°¥¹¥¿¥Ã¥¯¤¬¶õ¤Ç¤¹" +#, c-format +msgid "E253: Fontset name: %s" +msgstr "E253: ¥Õ¥©¥ó¥È¥»¥Ã¥È̾: %s" -#: ../globals.h:1088 -msgid "E74: Command too complex" -msgstr "E74: ¥³¥Þ¥ó¥É¤¬Ê£»¨²á¤®¤Þ¤¹" +#, c-format +msgid "Font0: %s" +msgstr "¥Õ¥©¥ó¥È0: %s" -#: ../globals.h:1089 -msgid "E75: Name too long" -msgstr "E75: ̾Á°¤¬Ä¹²á¤®¤Þ¤¹" +#, c-format +msgid "Font1: %s" +msgstr "¥Õ¥©¥ó¥È1: %s" -#: ../globals.h:1090 -msgid "E76: Too many [" -msgstr "E76: [ ¤¬Â¿²á¤®¤Þ¤¹" +#, c-format +msgid "Font%ld width is not twice that of font0" +msgstr "¥Õ¥©¥ó¥È%ld ¤ÎÉý¤¬¥Õ¥©¥ó¥È0¤Î2ÇܤǤϤ¢¤ê¤Þ¤»¤ó" -#: ../globals.h:1091 -msgid "E77: Too many file names" -msgstr "E77: ¥Õ¥¡¥¤¥ë̾¤¬Â¿²á¤®¤Þ¤¹" +#, c-format +msgid "Font0 width: %ld" +msgstr "¥Õ¥©¥ó¥È0¤ÎÉý: %ld" -#: ../globals.h:1092 -msgid "E488: Trailing characters" -msgstr "E488: ;ʬ¤Êʸ»ú¤¬¸å¤í¤Ë¤¢¤ê¤Þ¤¹" +#, c-format +msgid "Font1 width: %ld" +msgstr "¥Õ¥©¥ó¥È1¤ÎÉý: %ld" -#: ../globals.h:1093 -msgid "E78: Unknown mark" -msgstr "E78: ̤ÃΤΥޡ¼¥¯" +msgid "Invalid font specification" +msgstr "̵¸ú¤Ê¥Õ¥©¥ó¥È»ØÄê¤Ç¤¹" -#: ../globals.h:1094 -msgid "E79: Cannot expand wildcards" -msgstr "E79: ¥ï¥¤¥ë¥É¥«¡¼¥É¤òŸ³«¤Ç¤¤Þ¤»¤ó" +msgid "&Dismiss" +msgstr "µÑ²¼¤¹¤ë(&D)" -#: ../globals.h:1096 -msgid "E591: 'winheight' cannot be smaller than 'winminheight'" -msgstr "E591: 'winheight' ¤Ï 'winminheight' ¤è¤ê¾®¤µ¤¯¤Ç¤¤Þ¤»¤ó" +msgid "no specific match" +msgstr "¥Þ¥Ã¥Á¤¹¤ë¤â¤Î¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../globals.h:1098 -msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" -msgstr "E592: 'winwidth' ¤Ï 'winminwidth' ¤è¤ê¾®¤µ¤¯¤Ç¤¤Þ¤»¤ó" +msgid "Vim - Font Selector" +msgstr "Vim - ¥Õ¥©¥ó¥ÈÁªÂò" -#: ../globals.h:1099 -msgid "E80: Error while writing" -msgstr "E80: ½ñ¹þ¤ßÃæ¤Î¥¨¥é¡¼" +msgid "Name:" +msgstr "̾Á°:" -#: ../globals.h:1100 -msgid "Zero count" -msgstr "¥¼¥í¥«¥¦¥ó¥È" +#. create toggle button +msgid "Show size in Points" +msgstr "¥µ¥¤¥º¤ò¥Ý¥¤¥ó¥È¤Çɽ¼¨¤¹¤ë" -#: ../globals.h:1101 -msgid "E81: Using <SID> not in a script context" -msgstr "E81: ¥¹¥¯¥ê¥×¥È°Ê³°¤Ç<SID>¤¬»È¤ï¤ì¤Þ¤·¤¿" +msgid "Encoding:" +msgstr "¥¨¥ó¥³¡¼¥É:" -#: ../globals.h:1102 -#, c-format -msgid "E685: Internal error: %s" -msgstr "E685: ÆâÉô¥¨¥é¡¼¤Ç¤¹: %s" +msgid "Font:" +msgstr "¥Õ¥©¥ó¥È:" -#: ../globals.h:1104 -msgid "E363: pattern uses more memory than 'maxmempattern'" -msgstr "E363: ¥Ñ¥¿¡¼¥ó¤¬ 'maxmempattern' °Ê¾å¤Î¥á¥â¥ê¤ò»ÈÍѤ·¤Þ¤¹" +msgid "Style:" +msgstr "¥¹¥¿¥¤¥ë:" -#: ../globals.h:1105 -msgid "E749: empty buffer" -msgstr "E749: ¥Ð¥Ã¥Õ¥¡¤¬¶õ¤Ç¤¹" +msgid "Size:" +msgstr "¥µ¥¤¥º:" -#: ../globals.h:1108 -msgid "E682: Invalid search pattern or delimiter" -msgstr "E682: ¸¡º÷¥Ñ¥¿¡¼¥ó¤«¶èÀڤ굹椬ÉÔÀµ¤Ç¤¹" +msgid "E256: Hangul automata ERROR" +msgstr "E256: ¥Ï¥ó¥°¥ë¥ª¡¼¥È¥Þ¥È¥ó¥¨¥é¡¼" -#: ../globals.h:1109 -msgid "E139: File is loaded in another buffer" -msgstr "E139: Ʊ¤¸Ì¾Á°¤Î¥Õ¥¡¥¤¥ë¤¬Â¾¤Î¥Ð¥Ã¥Õ¥¡¤ÇÆÉ¹þ¤Þ¤ì¤Æ¤¤¤Þ¤¹" - -#: ../globals.h:1110 -#, c-format -msgid "E764: Option '%s' is not set" -msgstr "E764: ¥ª¥×¥·¥ç¥ó '%s' ¤ÏÀßÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó" - -#: ../globals.h:1111 -msgid "E850: Invalid register name" -msgstr "E850: ̵¸ú¤Ê¥ì¥¸¥¹¥¿Ì¾¤Ç¤¹" - -#: ../globals.h:1114 -msgid "search hit TOP, continuing at BOTTOM" -msgstr "¾å¤Þ¤Ç¸¡º÷¤·¤¿¤Î¤Ç²¼¤ËÌá¤ê¤Þ¤¹" - -#: ../globals.h:1115 -msgid "search hit BOTTOM, continuing at TOP" -msgstr "²¼¤Þ¤Ç¸¡º÷¤·¤¿¤Î¤Ç¾å¤ËÌá¤ê¤Þ¤¹" - -#: ../hardcopy.c:240 msgid "E550: Missing colon" msgstr "E550: ¥³¥í¥ó¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../hardcopy.c:252 msgid "E551: Illegal component" msgstr "E551: ÉÔÀµ¤Ê¹½Ê¸Í×ÁǤǤ¹" -#: ../hardcopy.c:259 msgid "E552: digit expected" msgstr "E552: ¿ôÃͤ¬É¬ÍפǤ¹" -#: ../hardcopy.c:473 #, c-format msgid "Page %d" msgstr "%d ¥Ú¡¼¥¸" -#: ../hardcopy.c:597 msgid "No text to be printed" msgstr "°õºþ¤¹¤ë¥Æ¥¥¹¥È¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../hardcopy.c:668 #, c-format msgid "Printing page %d (%d%%)" msgstr "°õºþÃæ: ¥Ú¡¼¥¸ %d (%d%%)" -#: ../hardcopy.c:680 #, c-format msgid " Copy %d of %d" msgstr " ¥³¥Ô¡¼ %d (Á´ %d Ãæ)" -#: ../hardcopy.c:733 #, c-format msgid "Printed: %s" msgstr "°õºþ¤·¤Þ¤·¤¿: %s" -#: ../hardcopy.c:740 msgid "Printing aborted" msgstr "°õºþ¤¬Ãæ»ß¤µ¤ì¤Þ¤·¤¿" -#: ../hardcopy.c:1365 msgid "E455: Error writing to PostScript output file" msgstr "E455: PostScript½ÐÎÏ¥Õ¥¡¥¤¥ë¤Î½ñ¹þ¤ß¥¨¥é¡¼¤Ç¤¹" -#: ../hardcopy.c:1747 #, c-format msgid "E624: Can't open file \"%s\"" msgstr "E624: ¥Õ¥¡¥¤¥ë \"%s\" ¤ò³«¤±¤Þ¤»¤ó" -#: ../hardcopy.c:1756 ../hardcopy.c:2470 #, c-format msgid "E457: Can't read PostScript resource file \"%s\"" msgstr "E457: PostScript¤Î¥ê¥½¡¼¥¹¥Õ¥¡¥¤¥ë \"%s\" ¤òÆÉ¹þ¤á¤Þ¤»¤ó" -#: ../hardcopy.c:1772 #, c-format msgid "E618: file \"%s\" is not a PostScript resource file" msgstr "E618: ¥Õ¥¡¥¤¥ë \"%s\" ¤Ï PostScript ¥ê¥½¡¼¥¹¥Õ¥¡¥¤¥ë¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../hardcopy.c:1788 ../hardcopy.c:1805 ../hardcopy.c:1844 #, c-format msgid "E619: file \"%s\" is not a supported PostScript resource file" msgstr "E619: ¥Õ¥¡¥¤¥ë \"%s\" ¤ÏÂбþ¤·¤Æ¤¤¤Ê¤¤ PostScript ¥ê¥½¡¼¥¹¥Õ¥¡¥¤¥ë¤Ç¤¹" -#: ../hardcopy.c:1856 #, c-format msgid "E621: \"%s\" resource file has wrong version" msgstr "E621: ¥ê¥½¡¼¥¹¥Õ¥¡¥¤¥ë \"%s\" ¤Ï¥Ð¡¼¥¸¥ç¥ó¤¬°Û¤Ê¤ê¤Þ¤¹" -#: ../hardcopy.c:2225 msgid "E673: Incompatible multi-byte encoding and character set." msgstr "E673: ¸ß´¹À¤Î̵¤¤¥Þ¥ë¥Á¥Ð¥¤¥È¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤Èʸ»ú¥»¥Ã¥È¤Ç¤¹" -#: ../hardcopy.c:2238 msgid "E674: printmbcharset cannot be empty with multi-byte encoding." msgstr "E674: ¥Þ¥ë¥Á¥Ð¥¤¥È¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤Ç¤Ï printmbcharset ¤ò¶õ¤Ë¤Ç¤¤Þ¤»¤ó" -#: ../hardcopy.c:2254 msgid "E675: No default font specified for multi-byte printing." msgstr "" "E675: ¥Þ¥ë¥Á¥Ð¥¤¥Èʸ»ú¤ò°õºþ¤¹¤ë¤¿¤á¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥©¥ó¥È¤¬»ØÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó" -#: ../hardcopy.c:2426 msgid "E324: Can't open PostScript output file" msgstr "E324: PostScript½ÐÎÏÍѤΥե¡¥¤¥ë¤ò³«¤±¤Þ¤»¤ó" -#: ../hardcopy.c:2458 #, c-format msgid "E456: Can't open file \"%s\"" msgstr "E456: ¥Õ¥¡¥¤¥ë \"%s\" ¤ò³«¤±¤Þ¤»¤ó" -#: ../hardcopy.c:2583 msgid "E456: Can't find PostScript resource file \"prolog.ps\"" msgstr "E456: PostScript¤Î¥ê¥½¡¼¥¹¥Õ¥¡¥¤¥ë \"prolog.ps\" ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../hardcopy.c:2593 msgid "E456: Can't find PostScript resource file \"cidfont.ps\"" msgstr "E456: PostScript¤Î¥ê¥½¡¼¥¹¥Õ¥¡¥¤¥ë \"cidfont.ps\" ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../hardcopy.c:2622 ../hardcopy.c:2639 ../hardcopy.c:2665 #, c-format msgid "E456: Can't find PostScript resource file \"%s.ps\"" msgstr "E456: PostScript¤Î¥ê¥½¡¼¥¹¥Õ¥¡¥¤¥ë \"%s.ps\" ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../hardcopy.c:2654 #, c-format msgid "E620: Unable to convert to print encoding \"%s\"" msgstr "E620: °õºþ¥¨¥ó¥³¡¼¥É \"%s\" ¤ØÊÑ´¹¤Ç¤¤Þ¤»¤ó" -#: ../hardcopy.c:2877 msgid "Sending to printer..." msgstr "¥×¥ê¥ó¥¿¤ËÁ÷¿®Ãæ..." -#: ../hardcopy.c:2881 msgid "E365: Failed to print PostScript file" msgstr "E365: PostScript¥Õ¥¡¥¤¥ë¤Î°õºþ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#: ../hardcopy.c:2883 msgid "Print job sent." msgstr "°õºþ¥¸¥ç¥Ö¤òÁ÷¿®¤·¤Þ¤·¤¿." -#: ../if_cscope.c:85 msgid "Add a new database" msgstr "¿·¥Ç¡¼¥¿¥Ù¡¼¥¹¤òÄɲÃ" -#: ../if_cscope.c:87 msgid "Query for a pattern" msgstr "¥Ñ¥¿¡¼¥ó¤Î¥¯¥¨¥ê¡¼¤òÄɲÃ" -#: ../if_cscope.c:89 msgid "Show this message" msgstr "¤³¤Î¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë" -#: ../if_cscope.c:91 msgid "Kill a connection" msgstr "Àܳ¤ò½ªÎ»¤¹¤ë" -#: ../if_cscope.c:93 msgid "Reinit all connections" msgstr "Á´¤Æ¤ÎÀܳ¤òºÆ½é´ü²½¤¹¤ë" -#: ../if_cscope.c:95 msgid "Show connections" msgstr "Àܳ¤òɽ¼¨¤¹¤ë" -#: ../if_cscope.c:101 #, c-format msgid "E560: Usage: cs[cope] %s" msgstr "E560: »ÈÍÑÊýË¡: cs[cope] %s" -#: ../if_cscope.c:225 msgid "This cscope command does not support splitting the window.\n" msgstr "¤³¤Îcscope¥³¥Þ¥ó¥É¤Ïʬ³ä¥¦¥£¥ó¥É¥¦¤Ç¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó.\n" -#: ../if_cscope.c:266 msgid "E562: Usage: cstag <ident>" msgstr "E562: »ÈÍÑË¡: cstag <ident>" -#: ../if_cscope.c:313 msgid "E257: cstag: tag not found" msgstr "E257: cstag: ¥¿¥°¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../if_cscope.c:461 #, c-format msgid "E563: stat(%s) error: %d" msgstr "E563: stat(%s) ¥¨¥é¡¼: %d" -#: ../if_cscope.c:551 +msgid "E563: stat error" +msgstr "E563: stat ¥¨¥é¡¼" + #, c-format msgid "E564: %s is not a directory or a valid cscope database" msgstr "E564: %s ¤Ï¥Ç¥£¥ì¥¯¥È¥êµÚ¤Ó͸ú¤Êcscope¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../if_cscope.c:566 #, c-format msgid "Added cscope database %s" msgstr "cscope¥Ç¡¼¥¿¥Ù¡¼¥¹ %s ¤òÄɲÃ" -#: ../if_cscope.c:616 #, c-format -msgid "E262: error reading cscope connection %<PRId64>" -msgstr "E262: cscope¤ÎÀܳ %<PRId64> ¤òÆÉ¹þ¤ßÃæ¤Î¥¨¥é¡¼¤Ç¤¹" +msgid "E262: error reading cscope connection %ld" +msgstr "E262: cscope¤ÎÀܳ %ld ¤òÆÉ¹þ¤ßÃæ¤Î¥¨¥é¡¼¤Ç¤¹" -#: ../if_cscope.c:711 msgid "E561: unknown cscope search type" msgstr "E561: ̤ÃΤÎcscope¸¡º÷·¿¤Ç¤¹" -#: ../if_cscope.c:752 ../if_cscope.c:789 msgid "E566: Could not create cscope pipes" msgstr "E566: cscope¥Ñ¥¤¥×¤òºîÀ®¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" -#: ../if_cscope.c:767 msgid "E622: Could not fork for cscope" msgstr "E622: cscope¤Îµ¯Æ°½àÈ÷(fork)¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#: ../if_cscope.c:849 msgid "cs_create_connection setpgid failed" msgstr "cs_create_connection ¤Ø¤Î setpgid ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#: ../if_cscope.c:853 ../if_cscope.c:889 msgid "cs_create_connection exec failed" msgstr "cs_create_connection ¤Î¼Â¹Ô¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#: ../if_cscope.c:863 ../if_cscope.c:902 msgid "cs_create_connection: fdopen for to_fp failed" msgstr "cs_create_connection: to_fp ¤Î fdopen ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#: ../if_cscope.c:865 ../if_cscope.c:906 msgid "cs_create_connection: fdopen for fr_fp failed" msgstr "cs_create_connection: fr_fp ¤Î fdopen ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#: ../if_cscope.c:890 msgid "E623: Could not spawn cscope process" msgstr "E623: cscope¥×¥í¥»¥¹¤òµ¯Æ°¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" -#: ../if_cscope.c:932 msgid "E567: no cscope connections" msgstr "E567: cscopeÀܳ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#: ../if_cscope.c:1009 #, c-format msgid "E469: invalid cscopequickfix flag %c for %c" msgstr "E469: ̵¸ú¤Ê cscopequickfix ¥Õ¥é¥° %c ¤Î %c ¤Ç¤¹" -#: ../if_cscope.c:1058 #, c-format msgid "E259: no matches found for cscope query %s of %s" msgstr "E259: cscope¥¯¥¨¥ê¡¼ %s of %s ¤Ë³ºÅö¤¬¤¢¤ê¤Þ¤»¤ó¤Ç¤·¤¿" -#: ../if_cscope.c:1142 msgid "cscope commands:\n" msgstr "cscope¥³¥Þ¥ó¥É:\n" -#: ../if_cscope.c:1150 #, c-format msgid "%-5s: %s%*s (Usage: %s)" msgstr "%-5s: %s%*s (»ÈÍÑË¡: %s)" -#: ../if_cscope.c:1155 msgid "" "\n" +" a: Find assignments to this symbol\n" " c: Find functions calling this function\n" " d: Find functions called by this function\n" " e: Find this egrep pattern\n" @@ -3234,6 +2549,7 @@ msgid "" " t: Find this text string\n" msgstr "" "\n" +" a: ¤³¤Î¥·¥ó¥Ü¥ë¤ËÂФ¹¤ëÂåÆþ¤òõ¤¹\n" " c: ¤³¤Î´Ø¿ô¤ò¸Æ¤ó¤Ç¤¤¤ë´Ø¿ô¤òõ¤¹\n" " d: ¤³¤Î´Ø¿ô¤«¤é¸Æ¤ó¤Ç¤¤¤ë´Ø¿ô¤òõ¤¹\n" " e: ¤³¤Îegrep¥Ñ¥¿¡¼¥ó¤òõ¤¹\n" @@ -3243,31 +2559,32 @@ msgstr "" " s: ¤³¤ÎC¥·¥ó¥Ü¥ë¤òõ¤¹\n" " t: ¤³¤Î¥Æ¥¥¹¥Èʸ»úÎó¤òõ¤¹\n" -#: ../if_cscope.c:1226 +#, c-format +msgid "E625: cannot open cscope database: %s" +msgstr "E625: cscope¥Ç¡¼¥¿¥Ù¡¼¥¹: %s ¤ò³«¤¯¤³¤È¤¬¤Ç¤¤Þ¤»¤ó" + +msgid "E626: cannot get cscope database information" +msgstr "E626: cscope¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¾ðÊó¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó" + msgid "E568: duplicate cscope database not added" msgstr "E568: ½ÅÊ£¤¹¤ëcscope¥Ç¡¼¥¿¥Ù¡¼¥¹¤ÏÄɲ䵤ì¤Þ¤»¤ó¤Ç¤·¤¿" -#: ../if_cscope.c:1335 #, c-format msgid "E261: cscope connection %s not found" msgstr "E261: cscopeÀܳ %s ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿" -#: ../if_cscope.c:1364 #, c-format msgid "cscope connection %s closed" msgstr "cscopeÀܳ %s ¤¬ÊĤ¸¤é¤ì¤Þ¤·¤¿" #. should not reach here -#: ../if_cscope.c:1486 msgid "E570: fatal error in cs_manage_matches" msgstr "E570: cs_manage_matches ¤ÇÃ×̿Ū¤Ê¥¨¥é¡¼¤Ç¤¹" -#: ../if_cscope.c:1693 #, c-format msgid "Cscope tag: %s" msgstr "Cscope ¥¿¥°: %s" -#: ../if_cscope.c:1711 msgid "" "\n" " # line" @@ -3275,87 +2592,300 @@ msgstr "" "\n" " # ¹ÔÈÖ¹æ" -#: ../if_cscope.c:1713 msgid "filename / context / line\n" msgstr "¥Õ¥¡¥¤¥ë̾ / ʸ̮ / ¹Ô\n" -#: ../if_cscope.c:1809 #, c-format msgid "E609: Cscope error: %s" msgstr "E609: cscope¥¨¥é¡¼: %s" -#: ../if_cscope.c:2053 msgid "All cscope databases reset" msgstr "Á´¤Æ¤Îcscope¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¥ê¥»¥Ã¥È¤·¤Þ¤¹" -#: ../if_cscope.c:2123 msgid "no cscope connections\n" msgstr "cscopeÀܳ¤¬¤¢¤ê¤Þ¤»¤ó\n" -#: ../if_cscope.c:2126 msgid " # pid database name prepend path\n" msgstr " # pid ¥Ç¡¼¥¿¥Ù¡¼¥¹Ì¾ prepend ¥Ñ¥¹\n" -#: ../main.c:144 +msgid "Lua library cannot be loaded." +msgstr "Lua¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤Ç¤¤Þ¤»¤ó." + +msgid "cannot save undo information" +msgstr "¥¢¥ó¥É¥¥¾ðÊó¤¬Êݸ¤Ç¤¤Þ¤»¤ó" + +msgid "" +"E815: Sorry, this command is disabled, the MzScheme libraries could not be " +"loaded." +msgstr "E815: ¤³¤Î¥³¥Þ¥ó¥É¤Ï̵¸ú¤Ç¤¹. MzScheme ¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤Ç¤¤Þ¤»¤ó." + +msgid "" +"E895: Sorry, this command is disabled, the MzScheme's racket/base module " +"could not be loaded." +msgstr "" +"E895: ¤³¤Î¥³¥Þ¥ó¥É¤Ï̵¸ú¤Ç¤¹,¤´¤á¤ó¤Ê¤µ¤¤. MzScheme ¤Î racket/base ¥â¥¸¥å¡¼¥ë" +"¤¬¥í¡¼¥É¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿." + +msgid "invalid expression" +msgstr "̵¸ú¤Ê¼°¤Ç¤¹" + +msgid "expressions disabled at compile time" +msgstr "¼°¤Ï¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹" + +msgid "hidden option" +msgstr "±£¤·¥ª¥×¥·¥ç¥ó" + +msgid "unknown option" +msgstr "̤ÃΤΥª¥×¥·¥ç¥ó¤Ç¤¹" + +msgid "window index is out of range" +msgstr "Èϰϳ°¤Î¥¦¥£¥ó¥É¥¦ÈÖ¹æ¤Ç¤¹" + +msgid "couldn't open buffer" +msgstr "¥Ð¥Ã¥Õ¥¡¤ò³«¤±¤Þ¤»¤ó" + +msgid "cannot delete line" +msgstr "¹Ô¤ò¾Ã¤»¤Þ¤»¤ó" + +msgid "cannot replace line" +msgstr "¹Ô¤òÃÖ´¹¤Ç¤¤Þ¤»¤ó" + +msgid "cannot insert line" +msgstr "¹Ô¤òÁÞÆþ¤Ç¤¤Þ¤»¤ó" + +msgid "string cannot contain newlines" +msgstr "ʸ»úÎó¤Ë¤Ï²þ¹Ôʸ»ú¤ò´Þ¤á¤é¤ì¤Þ¤»¤ó" + +msgid "error converting Scheme values to Vim" +msgstr "SchemeÃͤÎVim¤Ø¤ÎÊÑ´¹¥¨¥é¡¼" + +msgid "Vim error: ~a" +msgstr "Vim ¥¨¥é¡¼: ~a" + +msgid "Vim error" +msgstr "Vim ¥¨¥é¡¼" + +msgid "buffer is invalid" +msgstr "¥Ð¥Ã¥Õ¥¡¤Ï̵¸ú¤Ç¤¹" + +msgid "window is invalid" +msgstr "¥¦¥£¥ó¥É¥¦¤Ï̵¸ú¤Ç¤¹" + +msgid "linenr out of range" +msgstr "Èϰϳ°¤Î¹ÔÈÖ¹æ¤Ç¤¹" + +msgid "not allowed in the Vim sandbox" +msgstr "¥µ¥ó¥É¥Ü¥Ã¥¯¥¹¤Ç¤Ïµö¤µ¤ì¤Þ¤»¤ó" + +msgid "E836: This Vim cannot execute :python after using :py3" +msgstr "E836: ¤³¤ÎVim¤Ç¤Ï :py3 ¤ò»È¤Ã¤¿¸å¤Ë :python ¤ò»È¤¨¤Þ¤»¤ó" + +msgid "" +"E263: Sorry, this command is disabled, the Python library could not be " +"loaded." +msgstr "" +"E263: ¤³¤Î¥³¥Þ¥ó¥É¤Ï̵¸ú¤Ç¤¹,¤´¤á¤ó¤Ê¤µ¤¤: Python¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤Ç¤¤Þ¤»¤ó" +"¤Ç¤·¤¿." + +msgid "" +"E887: Sorry, this command is disabled, the Python's site module could not be " +"loaded." +msgstr "" +"E887: ¤³¤Î¥³¥Þ¥ó¥É¤Ï̵¸ú¤Ç¤¹,¤´¤á¤ó¤Ê¤µ¤¤. Python ¤Î site ¥â¥¸¥å¡¼¥ë¤ò¥í¡¼¥É" +"¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿." + +# Added at 07-Feb-2004. +msgid "E659: Cannot invoke Python recursively" +msgstr "E659: Python ¤òºÆµ¢Åª¤Ë¼Â¹Ô¤¹¤ë¤³¤È¤Ï¤Ç¤¤Þ¤»¤ó" + +msgid "E837: This Vim cannot execute :py3 after using :python" +msgstr "E837: ¤³¤ÎVim¤Ç¤Ï :python ¤ò»È¤Ã¤¿¸å¤Ë :py3 ¤ò»È¤¨¤Þ¤»¤ó" + +msgid "E265: $_ must be an instance of String" +msgstr "E265: $_ ¤Ïʸ»úÎó¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" + +msgid "" +"E266: Sorry, this command is disabled, the Ruby library could not be loaded." +msgstr "" +"E266: ¤³¤Î¥³¥Þ¥ó¥É¤Ï̵¸ú¤Ç¤¹,¤´¤á¤ó¤Ê¤µ¤¤: Ruby¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤Ç¤¤Þ¤»¤ó¤Ç" +"¤·¤¿." + +msgid "E267: unexpected return" +msgstr "E267: ͽ´ü¤»¤Ì return ¤Ç¤¹" + +msgid "E268: unexpected next" +msgstr "E268: ͽ´ü¤»¤Ì next ¤Ç¤¹" + +msgid "E269: unexpected break" +msgstr "E269: ͽ´ü¤»¤Ì break ¤Ç¤¹" + +msgid "E270: unexpected redo" +msgstr "E270: ͽ´ü¤»¤Ì redo ¤Ç¤¹" + +msgid "E271: retry outside of rescue clause" +msgstr "E271: rescue ¤Î³°¤Î retry ¤Ç¤¹" + +msgid "E272: unhandled exception" +msgstr "E272: ¼è¤ê°·¤ï¤ì¤Ê¤«¤Ã¤¿Îã³°¤¬¤¢¤ê¤Þ¤¹" + +#, c-format +msgid "E273: unknown longjmp status %d" +msgstr "E273: ̤ÃΤÎlongjmp¾õÂÖ: %d" + +msgid "invalid buffer number" +msgstr "̵¸ú¤Ê¥Ð¥Ã¥Õ¥¡ÈÖ¹æ¤Ç¤¹" + +msgid "not implemented yet" +msgstr "¤Þ¤À¼ÂÁõ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" + +#. ??? +msgid "cannot set line(s)" +msgstr "¹Ô¤òÀßÄê¤Ç¤¤Þ¤»¤ó" + +msgid "invalid mark name" +msgstr "̵¸ú¤Ê¥Þ¡¼¥¯Ì¾¤Ç¤¹" + +msgid "mark not set" +msgstr "¥Þ¡¼¥¯¤ÏÀßÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó" + +#, c-format +msgid "row %d column %d" +msgstr "¹Ô %d Îó %d" + +msgid "cannot insert/append line" +msgstr "¹Ô¤ÎÁÞÆþ/Äɲäò¤Ç¤¤Þ¤»¤ó" + +msgid "line number out of range" +msgstr "Èϰϳ°¤Î¹ÔÈÖ¹æ¤Ç¤¹" + +msgid "unknown flag: " +msgstr "̤ÃΤΥե饰: " + +msgid "unknown vimOption" +msgstr "̤ÃΤΠvimOption ¤Ç¤¹" + +msgid "keyboard interrupt" +msgstr "¥¡¼¥Ü¡¼¥É³ä¹þ¤ß" + +msgid "vim error" +msgstr "vim ¥¨¥é¡¼" + +msgid "cannot create buffer/window command: object is being deleted" +msgstr "" +"¥Ð¥Ã¥Õ¥¡/¥¦¥£¥ó¥É¥¦ºîÀ®¥³¥Þ¥ó¥É¤òºîÀ®¤Ç¤¤Þ¤»¤ó: ¥ª¥Ö¥¸¥§¥¯¥È¤¬¾Ãµî¤µ¤ì¤Æ¤¤¤Þ" +"¤·¤¿" + +msgid "" +"cannot register callback command: buffer/window is already being deleted" +msgstr "" +"¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥É¤òÅÐÏ¿¤Ç¤¤Þ¤»¤ó: ¥Ð¥Ã¥Õ¥¡/¥¦¥£¥ó¥É¥¦¤¬´û¤Ë¾Ãµî¤µ¤ì¤Þ¤·¤¿" + +#. This should never happen. Famous last word? +msgid "" +"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim." +"org" +msgstr "" +"E280: TCL Ã×̿Ū¥¨¥é¡¼: reflist ±øÀ÷!? vim-dev@vim.org ¤ËÊó¹ð¤·¤Æ¤¯¤À¤µ¤¤" + +msgid "cannot register callback command: buffer/window reference not found" +msgstr "" +"¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥É¤òÅÐÏ¿¤Ç¤¤Þ¤»¤ó: ¥Ð¥Ã¥Õ¥¡/¥¦¥£¥ó¥É¥¦¤Î»²¾È¤¬¸«¤Ä¤«¤ê¤Þ¤»" +"¤ó" + +msgid "" +"E571: Sorry, this command is disabled: the Tcl library could not be loaded." +msgstr "" +"E571: ¤³¤Î¥³¥Þ¥ó¥É¤Ï̵¸ú¤Ç¤¹,¤´¤á¤ó¤Ê¤µ¤¤: Tcl¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤Ç¤¤Þ¤»¤ó¤Ç" +"¤·¤¿." + +#, c-format +msgid "E572: exit code %d" +msgstr "E572: ½ªÎ»¥³¡¼¥É %d" + +msgid "cannot get line" +msgstr "¹Ô¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó" + +msgid "Unable to register a command server name" +msgstr "Ì¿Î᥵¡¼¥Ð¡¼¤Î̾Á°¤òÅÐÏ¿¤Ç¤¤Þ¤»¤ó" + +msgid "E248: Failed to send command to the destination program" +msgstr "E248: ÌÜŪ¤Î¥×¥í¥°¥é¥à¤Ø¤Î¥³¥Þ¥ó¥ÉÁ÷¿®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" + +#, c-format +msgid "E573: Invalid server id used: %s" +msgstr "E573: ̵¸ú¤Ê¥µ¡¼¥Ð¡¼ID¤¬»È¤ï¤ì¤Þ¤·¤¿: %s" + +msgid "E251: VIM instance registry property is badly formed. Deleted!" +msgstr "E251: VIM ¼ÂÂΤÎÅÐÏ¿¥×¥í¥Ñ¥Æ¥£¤¬ÉÔÀµ¤Ç¤¹. ¾Ãµî¤·¤Þ¤·¤¿!" + +#, c-format +msgid "E696: Missing comma in List: %s" +msgstr "E696: ¥ê¥¹¥È·¿¤Ë¥«¥ó¥Þ¤¬¤¢¤ê¤Þ¤»¤ó: %s" + +#, c-format +msgid "E697: Missing end of List ']': %s" +msgstr "E697: ¥ê¥¹¥È·¿¤ÎºÇ¸å¤Ë ']' ¤¬¤¢¤ê¤Þ¤»¤ó: %s" + msgid "Unknown option argument" msgstr "̤ÃΤΥª¥×¥·¥ç¥ó°ú¿ô¤Ç¤¹" -#: ../main.c:146 msgid "Too many edit arguments" msgstr "ÊÔ½¸°ú¿ô¤¬Â¿²á¤®¤Þ¤¹" -#: ../main.c:148 msgid "Argument missing after" msgstr "°ú¿ô¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../main.c:150 msgid "Garbage after option argument" msgstr "¥ª¥×¥·¥ç¥ó°ú¿ô¤Î¸å¤Ë¥´¥ß¤¬¤¢¤ê¤Þ¤¹" -#: ../main.c:152 msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments" msgstr "\"+command\", \"-c command\", \"--cmd command\" ¤Î°ú¿ô¤¬Â¿²á¤®¤Þ¤¹" -#: ../main.c:154 msgid "Invalid argument for" msgstr "̵¸ú¤Ê°ú¿ô¤Ç¤¹: " -#: ../main.c:294 #, c-format msgid "%d files to edit\n" msgstr "%d ¸Ä¤Î¥Õ¥¡¥¤¥ë¤¬ÊÔ½¸¤ò¹µ¤¨¤Æ¤¤¤Þ¤¹\n" -#: ../main.c:1342 +msgid "netbeans is not supported with this GUI\n" +msgstr "netbeans ¤Ï¤³¤ÎGUI¤Ç¤ÏÍøÍѤǤ¤Þ¤»¤ó\n" + +msgid "'-nb' cannot be used: not enabled at compile time\n" +msgstr "'-nb' »ÈÍÑÉÔ²Äǽ¤Ç¤¹: ¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹\n" + +msgid "This Vim was not compiled with the diff feature." +msgstr "¤³¤ÎVim¤Ë¤Ïdiffµ¡Ç½¤¬¤¢¤ê¤Þ¤»¤ó(¥³¥ó¥Ñ¥¤¥ë»þÀßÄê)." + msgid "Attempt to open script file again: \"" msgstr "¥¹¥¯¥ê¥×¥È¥Õ¥¡¥¤¥ë¤òºÆ¤Ó³«¤¤¤Æ¤ß¤Þ¤¹: \"" -#: ../main.c:1350 msgid "Cannot open for reading: \"" msgstr "ÆÉ¹þÍѤȤ·¤Æ³«¤±¤Þ¤»¤ó" -#: ../main.c:1393 msgid "Cannot open for script output: \"" msgstr "¥¹¥¯¥ê¥×¥È½ÐÎÏÍѤò³«¤±¤Þ¤»¤ó" -#: ../main.c:1622 +msgid "Vim: Error: Failure to start gvim from NetBeans\n" +msgstr "Vim: ¥¨¥é¡¼: NetBeans¤«¤égvim¤ò¥¹¥¿¡¼¥È¤Ç¤¤Þ¤»¤ó\n" + +msgid "Vim: Error: This version of Vim does not run in a Cygwin terminal\n" +msgstr "Vim: ¥¨¥é¡¼: ¤³¤Î¥Ð¡¼¥¸¥ç¥ó¤ÎVim¤ÏCygwinüËö¤Ç¤Ïưºî¤·¤Þ¤»¤ó\n" + msgid "Vim: Warning: Output is not to a terminal\n" msgstr "Vim: ·Ù¹ð: üËö¤Ø¤Î½ÐÎϤǤϤ¢¤ê¤Þ¤»¤ó\n" -#: ../main.c:1624 msgid "Vim: Warning: Input is not from a terminal\n" msgstr "Vim: ·Ù¹ð: üËö¤«¤é¤ÎÆþÎϤǤϤ¢¤ê¤Þ¤»¤ó\n" #. just in case.. -#: ../main.c:1891 msgid "pre-vimrc command line" msgstr "vimrcÁ°¤Î¥³¥Þ¥ó¥É¥é¥¤¥ó" -#: ../main.c:1964 #, c-format msgid "E282: Cannot read from \"%s\"" msgstr "E282: \"%s\"¤«¤éÆÉ¹þ¤à¤³¤È¤¬¤Ç¤¤Þ¤»¤ó" -#: ../main.c:2149 msgid "" "\n" "More info with: \"vim -h\"\n" @@ -3363,23 +2893,18 @@ msgstr "" "\n" "¤è¤ê¾ÜºÙ¤Ê¾ðÊó¤Ï: \"vim -h\"\n" -#: ../main.c:2178 msgid "[file ..] edit specified file(s)" msgstr "[¥Õ¥¡¥¤¥ë..] ¤¢¤ë¥Õ¥¡¥¤¥ë¤òÊÔ½¸¤¹¤ë" -#: ../main.c:2179 msgid "- read text from stdin" msgstr "- ɸ½àÆþÎϤ«¤é¥Æ¥¥¹¥È¤òÆÉ¹þ¤à" -#: ../main.c:2180 msgid "-t tag edit file where tag is defined" msgstr "-t ¥¿¥° ¥¿¥°¤¬ÄêµÁ¤µ¤ì¤¿¤È¤³¤í¤«¤éÊÔ½¸¤¹¤ë" -#: ../main.c:2181 msgid "-q [errorfile] edit file with first error" msgstr "-q [errorfile] ºÇ½é¤Î¥¨¥é¡¼¤ÇÊÔ½¸¤¹¤ë" -#: ../main.c:2187 msgid "" "\n" "\n" @@ -3389,11 +2914,9 @@ msgstr "" "\n" "»ÈÍÑË¡:" -#: ../main.c:2189 msgid " vim [arguments] " msgstr " vim [°ú¿ô] " -#: ../main.c:2193 msgid "" "\n" " or:" @@ -3401,7 +2924,13 @@ msgstr "" "\n" " ¤â¤·¤¯¤Ï:" -#: ../main.c:2196 +msgid "" +"\n" +"Where case is ignored prepend / to make flag upper case" +msgstr "" +"\n" +"Â羮ʸ»ú¤¬Ìµ»ë¤µ¤ì¤ë¾ì¹ç¤ÏÂçʸ»ú¤Ë¤¹¤ë¤¿¤á¤Ë / ¤òÁ°ÃÖ¤·¤Æ¤¯¤À¤µ¤¤" + msgid "" "\n" "\n" @@ -3411,189 +2940,319 @@ msgstr "" "\n" "°ú¿ô:\n" -#: ../main.c:2197 msgid "--\t\t\tOnly file names after this" msgstr "--\t\t\t¤³¤Î¤¢¤È¤Ë¤Ï¥Õ¥¡¥¤¥ë̾¤À¤±" -#: ../main.c:2199 msgid "--literal\t\tDon't expand wildcards" msgstr "--literal\t\t¥ï¥¤¥ë¥É¥«¡¼¥É¤òŸ³«¤·¤Ê¤¤" -#: ../main.c:2201 +msgid "-register\t\tRegister this gvim for OLE" +msgstr "-register\t\t¤³¤Îgvim¤òOLE¤È¤·¤ÆÅÐÏ¿¤¹¤ë" + +msgid "-unregister\t\tUnregister gvim for OLE" +msgstr "-unregister\t\tgvim¤ÎOLEÅÐÏ¿¤ò²ò½ü¤¹¤ë" + +msgid "-g\t\t\tRun using GUI (like \"gvim\")" +msgstr "-g\t\t\tGUI¤Çµ¯Æ°¤¹¤ë (\"gvim\" ¤ÈƱ¤¸)" + +msgid "-f or --nofork\tForeground: Don't fork when starting GUI" +msgstr "-f or --nofork\t¥Õ¥©¥¢¥°¥é¥¦¥ó¥É: GUI¤ò»Ï¤á¤ë¤È¤¤Ëfork¤·¤Ê¤¤" + msgid "-v\t\t\tVi mode (like \"vi\")" msgstr "-v\t\t\tVi¥â¡¼¥É (\"vi\" ¤ÈƱ¤¸)" -#: ../main.c:2202 msgid "-e\t\t\tEx mode (like \"ex\")" msgstr "-e\t\t\tEx¥â¡¼¥É (\"ex\" ¤ÈƱ¤¸)" -#: ../main.c:2203 msgid "-E\t\t\tImproved Ex mode" msgstr "-E\t\t\t²þÎÉEx¥â¡¼¥É" -#: ../main.c:2204 msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")" msgstr "-s\t\t\t¥µ¥¤¥ì¥ó¥È(¥Ð¥Ã¥Á)¥â¡¼¥É (\"ex\" ÀìÍÑ)" -#: ../main.c:2205 msgid "-d\t\t\tDiff mode (like \"vimdiff\")" msgstr "-d\t\t\tº¹Ê¬¥â¡¼¥É (\"vidiff\" ¤ÈƱ¤¸)" -#: ../main.c:2206 msgid "-y\t\t\tEasy mode (like \"evim\", modeless)" msgstr "-y\t\t\t¥¤¡¼¥¸¡¼¥â¡¼¥É (\"evim\" ¤ÈƱ¤¸, ¥â¡¼¥É̵)" -#: ../main.c:2207 msgid "-R\t\t\tReadonly mode (like \"view\")" msgstr "-R\t\t\tÆÉ¹þÀìÍѥ⡼¥É (\"view\" ¤ÈƱ¤¸)" -#: ../main.c:2208 msgid "-Z\t\t\tRestricted mode (like \"rvim\")" msgstr "-Z\t\t\tÀ©¸Â¥â¡¼¥É (\"rvim\" ¤ÈƱ¤¸)" -#: ../main.c:2209 msgid "-m\t\t\tModifications (writing files) not allowed" msgstr "-m\t\t\tÊѹ¹ (¥Õ¥¡¥¤¥ëÊݸ»þ) ¤ò¤Ç¤¤Ê¤¤¤è¤¦¤Ë¤¹¤ë" -#: ../main.c:2210 msgid "-M\t\t\tModifications in text not allowed" msgstr "-M\t\t\t¥Æ¥¥¹¥È¤ÎÊÔ½¸¤ò¹Ô¤Ê¤¨¤Ê¤¤¤è¤¦¤Ë¤¹¤ë" -#: ../main.c:2211 msgid "-b\t\t\tBinary mode" msgstr "-b\t\t\t¥Ð¥¤¥Ê¥ê¥â¡¼¥É" -#: ../main.c:2212 msgid "-l\t\t\tLisp mode" msgstr "-l\t\t\tLisp¥â¡¼¥É" -#: ../main.c:2213 msgid "-C\t\t\tCompatible with Vi: 'compatible'" msgstr "-C\t\t\tVi¸ß´¹¥â¡¼¥É: 'compatible'" -#: ../main.c:2214 msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'" msgstr "-N\t\t\tViÈó¸ß´¹¥â¡¼¥É: 'nocompatible" -#: ../main.c:2215 msgid "-V[N][fname]\t\tBe verbose [level N] [log messages to fname]" msgstr "-V[N][fname]\t\t¥í¥°½ÐÎÏÀßÄê [¥ì¥Ù¥ë N] [¥í¥°¥Õ¥¡¥¤¥ë̾ fname]" -#: ../main.c:2216 msgid "-D\t\t\tDebugging mode" msgstr "-D\t\t\t¥Ç¥Ð¥Ã¥°¥â¡¼¥É" -#: ../main.c:2217 msgid "-n\t\t\tNo swap file, use memory only" msgstr "-n\t\t\t¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤ò»ÈÍѤ»¤º¥á¥â¥ê¤À¤±" -#: ../main.c:2218 msgid "-r\t\t\tList swap files and exit" msgstr "-r\t\t\t¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤òÎóµó¤·½ªÎ»" -#: ../main.c:2219 msgid "-r (with file name)\tRecover crashed session" msgstr "-r (¥Õ¥¡¥¤¥ë̾)\t¥¯¥é¥Ã¥·¥å¤·¤¿¥»¥Ã¥·¥ç¥ó¤òÉüµ¢" -#: ../main.c:2220 msgid "-L\t\t\tSame as -r" msgstr "-L\t\t\t-r¤ÈƱ¤¸" -#: ../main.c:2221 +msgid "-f\t\t\tDon't use newcli to open window" +msgstr "-f\t\t\t¥¦¥£¥ó¥É¥¦¤ò³«¤¯¤Î¤Ë newcli ¤ò»ÈÍѤ·¤Ê¤¤" + +msgid "-dev <device>\t\tUse <device> for I/O" +msgstr "-dev <device>\t\tI/O¤Ë <device> ¤ò»ÈÍѤ¹¤ë" + msgid "-A\t\t\tstart in Arabic mode" msgstr "-A\t\t\t¥¢¥é¥Ó¥¢¸ì¥â¡¼¥É¤Çµ¯Æ°¤¹¤ë" -#: ../main.c:2222 msgid "-H\t\t\tStart in Hebrew mode" msgstr "-H\t\t\t¥Ø¥Ö¥é¥¤¸ì¥â¡¼¥É¤Çµ¯Æ°¤¹¤ë" -#: ../main.c:2223 msgid "-F\t\t\tStart in Farsi mode" msgstr "-F\t\t\t¥Ú¥ë¥·¥¢¸ì¥â¡¼¥É¤Çµ¯Æ°¤¹¤ë" -#: ../main.c:2224 msgid "-T <terminal>\tSet terminal type to <terminal>" msgstr "-T <terminal>\tüËö¤ò <terminal> ¤ËÀßÄꤹ¤ë" -#: ../main.c:2225 +msgid "--not-a-term\t\tSkip warning for input/output not being a terminal" +msgstr "--not-a-term\t\tÆþ½ÐÎϤ¬Ã¼Ëö¤Ç¤Ê¤¤¤È¤Î·Ù¹ð¤ò¥¹¥¥Ã¥×¤¹¤ë" + msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc" msgstr "-u <vimrc>\t\t.vimrc¤ÎÂå¤ï¤ê¤Ë <vimrc> ¤ò»È¤¦" -#: ../main.c:2226 +msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" +msgstr "-U <gvimrc>\t\t.gvimrc¤ÎÂå¤ï¤ê¤Ë <gvimrc> ¤ò»È¤¦" + msgid "--noplugin\t\tDon't load plugin scripts" msgstr "--noplugin\t\t¥×¥é¥°¥¤¥ó¥¹¥¯¥ê¥×¥È¤ò¥í¡¼¥É¤·¤Ê¤¤" -#: ../main.c:2227 msgid "-p[N]\t\tOpen N tab pages (default: one for each file)" msgstr "-p[N]\t\tN ¸Ä¥¿¥Ö¥Ú¡¼¥¸¤ò³«¤¯(¾ÊάÃÍ: ¥Õ¥¡¥¤¥ë¤Ë¤Ä¤1¸Ä)" -#: ../main.c:2228 msgid "-o[N]\t\tOpen N windows (default: one for each file)" msgstr "-o[N]\t\tN ¸Ä¥¦¥£¥ó¥É¥¦¤ò³«¤¯(¾ÊάÃÍ: ¥Õ¥¡¥¤¥ë¤Ë¤Ä¤1¸Ä)" -#: ../main.c:2229 msgid "-O[N]\t\tLike -o but split vertically" msgstr "-O[N]\t\t-o¤ÈƱ¤¸¤À¤¬¿âľʬ³ä" -#: ../main.c:2230 msgid "+\t\t\tStart at end of file" msgstr "+\t\t\t¥Õ¥¡¥¤¥ë¤ÎºÇ¸å¤«¤é¤Ï¤¸¤á¤ë" -#: ../main.c:2231 msgid "+<lnum>\t\tStart at line <lnum>" msgstr "+<lnum>\t\t<lnum> ¹Ô¤«¤é¤Ï¤¸¤á¤ë" -#: ../main.c:2232 msgid "--cmd <command>\tExecute <command> before loading any vimrc file" msgstr "--cmd <command>\tvimrc¤ò¥í¡¼¥É¤¹¤ëÁ°¤Ë <command> ¤ò¼Â¹Ô¤¹¤ë" -#: ../main.c:2233 msgid "-c <command>\t\tExecute <command> after loading the first file" msgstr "-c <command>\t\tºÇ½é¤Î¥Õ¥¡¥¤¥ë¤ò¥í¡¼¥É¸å <command> ¤ò¼Â¹Ô¤¹¤ë" -#: ../main.c:2235 msgid "-S <session>\t\tSource file <session> after loading the first file" msgstr "-S <session>\t\tºÇ½é¤Î¥Õ¥¡¥¤¥ë¤ò¥í¡¼¥É¸å¥Õ¥¡¥¤¥ë <session> ¤ò¼è¹þ¤à" -#: ../main.c:2236 msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>" msgstr "-s <scriptin>\t¥Õ¥¡¥¤¥ë <scriptin> ¤«¤é¥Î¡¼¥Þ¥ë¥³¥Þ¥ó¥É¤òÆÉ¹þ¤à" -#: ../main.c:2237 msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>" msgstr "-w <scriptout>\tÆþÎϤ·¤¿Á´¥³¥Þ¥ó¥É¤ò¥Õ¥¡¥¤¥ë <scriptout> ¤ËÄɲ乤ë" -#: ../main.c:2238 msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>" msgstr "-W <scriptout>\tÆþÎϤ·¤¿Á´¥³¥Þ¥ó¥É¤ò¥Õ¥¡¥¤¥ë <scriptout> ¤ËÊݸ¤¹¤ë" -#: ../main.c:2240 +msgid "-x\t\t\tEdit encrypted files" +msgstr "-x\t\t\t°Å¹æ²½¤µ¤ì¤¿¥Õ¥¡¥¤¥ë¤òÊÔ½¸¤¹¤ë" + +msgid "-display <display>\tConnect vim to this particular X-server" +msgstr "-display <display>\tvim¤ò»ØÄꤷ¤¿ X ¥µ¡¼¥Ð¡¼¤ËÀܳ¤¹¤ë" + +msgid "-X\t\t\tDo not connect to X server" +msgstr "-X\t\t\tX¥µ¡¼¥Ð¡¼¤ËÀܳ¤·¤Ê¤¤" + +msgid "--remote <files>\tEdit <files> in a Vim server if possible" +msgstr "--remote <files>\t²Äǽ¤Ê¤é¤ÐVim¥µ¡¼¥Ð¡¼¤Ç <files> ¤òÊÔ½¸¤¹¤ë" + +msgid "--remote-silent <files> Same, don't complain if there is no server" +msgstr "--remote-silent <files> Ʊ¾å, ¥µ¡¼¥Ð¡¼¤¬Ìµ¤¯¤Æ¤â·Ù¹ðʸ¤ò½ÐÎϤ·¤Ê¤¤" + +msgid "" +"--remote-wait <files> As --remote but wait for files to have been edited" +msgstr "--remote-wait <files>\t--remote¸å ¥Õ¥¡¥¤¥ë¤ÎÊÔ½¸¤¬½ª¤ï¤ë¤Î¤òÂÔ¤Ä" + +msgid "" +"--remote-wait-silent <files> Same, don't complain if there is no server" +msgstr "" +"--remote-wait-silent <files> Ʊ¾å, ¥µ¡¼¥Ð¡¼¤¬Ìµ¤¯¤Æ¤â·Ù¹ðʸ¤ò½ÐÎϤ·¤Ê¤¤" + +msgid "" +"--remote-tab[-wait][-silent] <files> As --remote but use tab page per file" +msgstr "" +"--remote-tab[-wait][-silent] <files> --remote¤Ç¥Õ¥¡¥¤¥ë1¤Ä¤Ë¤Ä¤1¤Ä¤Î¥¿¥Ö" +"¥Ú¡¼¥¸¤ò³«¤¯" + +msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" +msgstr "--remote-send <keys>\tVim¥µ¡¼¥Ð¡¼¤Ë <keys> ¤òÁ÷¿®¤·¤Æ½ªÎ»¤¹¤ë" + +msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" +msgstr "--remote-expr <expr>\t¥µ¡¼¥Ð¡¼¤Ç <expr> ¤ò¼Â¹Ô¤·¤Æ·ë²Ì¤òɽ¼¨¤¹¤ë" + +msgid "--serverlist\t\tList available Vim server names and exit" +msgstr "--serverlist\t\tVim¥µ¡¼¥Ð¡¼Ì¾¤Î°ìÍ÷¤òɽ¼¨¤·¤Æ½ªÎ»¤¹¤ë" + +msgid "--servername <name>\tSend to/become the Vim server <name>" +msgstr "--servername <name>\tVim¥µ¡¼¥Ð¡¼ <name> ¤ËÁ÷¿®/̾Á°ÀßÄꤹ¤ë" + msgid "--startuptime <file>\tWrite startup timing messages to <file>" msgstr "--startuptime <file>\tµ¯Æ°¤Ë¤«¤«¤Ã¤¿»þ´Ö¤Î¾ÜºÙ¤ò <file> ¤Ø½ÐÎϤ¹¤ë" -#: ../main.c:2242 msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo" msgstr "-i <viminfo>\t\t.viminfo¤ÎÂå¤ï¤ê¤Ë <viminfo> ¤ò»È¤¦" -#: ../main.c:2243 msgid "-h or --help\tPrint Help (this message) and exit" msgstr "-h or --help\t¥Ø¥ë¥×(¤³¤Î¥á¥Ã¥»¡¼¥¸)¤òɽ¼¨¤·½ªÎ»¤¹¤ë" -#: ../main.c:2244 msgid "--version\t\tPrint version information and exit" msgstr "--version\t\t¥Ð¡¼¥¸¥ç¥ó¾ðÊó¤òɽ¼¨¤·½ªÎ»¤¹¤ë" -#: ../mark.c:676 +msgid "" +"\n" +"Arguments recognised by gvim (Motif version):\n" +msgstr "" +"\n" +"gvim¤Ë¤è¤Ã¤Æ²ò¼á¤µ¤ì¤ë°ú¿ô(Motif¥Ð¡¼¥¸¥ç¥ó):\n" + +msgid "" +"\n" +"Arguments recognised by gvim (neXtaw version):\n" +msgstr "" +"\n" +"gvim¤Ë¤è¤Ã¤Æ²ò¼á¤µ¤ì¤ë°ú¿ô(neXtaw¥Ð¡¼¥¸¥ç¥ó):\n" + +msgid "" +"\n" +"Arguments recognised by gvim (Athena version):\n" +msgstr "" +"\n" +"gvim¤Ë¤è¤Ã¤Æ²ò¼á¤µ¤ì¤ë°ú¿ô(Athena¥Ð¡¼¥¸¥ç¥ó):\n" + +msgid "-display <display>\tRun vim on <display>" +msgstr "-display <display>\t<display> ¤Çvim¤ò¼Â¹Ô¤¹¤ë" + +msgid "-iconic\t\tStart vim iconified" +msgstr "-iconic\t\tºÇ¾®²½¤·¤¿¾õÂÖ¤Çvim¤òµ¯Æ°¤¹¤ë" + +msgid "-background <color>\tUse <color> for the background (also: -bg)" +msgstr "-background <color>\tÇØ·Ê¿§¤Ë <color> ¤ò»È¤¦(ƱµÁ: -bg)" + +msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" +msgstr "-foreground <color>\tÁ°·Ê¿§¤Ë <color> ¤ò»È¤¦(ƱµÁ: -fg)" + +msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" +msgstr "-font <font>\t\t¥Æ¥¥¹¥Èɽ¼¨¤Ë <font> ¤ò»È¤¦(ƱµÁ: -fn)" + +msgid "-boldfont <font>\tUse <font> for bold text" +msgstr "-boldfont <font>\tÂÀ»ú¤Ë <font> ¤ò»È¤¦" + +msgid "-italicfont <font>\tUse <font> for italic text" +msgstr "-italicfont <for>\t¼ÐÂλú¤Ë <font> ¤ò»È¤¦" + +msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" +msgstr "-geometry <geom>\t½é´üÇÛÃÖ¤Ë <geom> ¤ò»È¤¦(ƱµÁ: -geom)" + +msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" +msgstr "-borderwidth <width>\t¶³¦¤ÎÉý¤ò <width> ¤Ë¤¹¤ë(ƱµÁ: -bw)" + +msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" +msgstr "" +"-scrollbarwidth <width> ¥¹¥¯¥í¡¼¥ë¥Ð¡¼¤ÎÉý¤ò <width> ¤Ë¤¹¤ë(ƱµÁ: -sw)" + +msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" +msgstr "-menuheight <height>\t¥á¥Ë¥å¡¼¥Ð¡¼¤Î¹â¤µ¤ò <height> ¤Ë¤¹¤ë(ƱµÁ: -mh)" + +msgid "-reverse\t\tUse reverse video (also: -rv)" +msgstr "-reverse\t\tȿž±ÇÁü¤ò»ÈÍѤ¹¤ë(ƱµÁ: -rv)" + +msgid "+reverse\t\tDon't use reverse video (also: +rv)" +msgstr "+reverse\t\tȿž±ÇÁü¤ò»ÈÍѤ·¤Ê¤¤(ƱµÁ: +rv)" + +msgid "-xrm <resource>\tSet the specified resource" +msgstr "-xrm <resource>\tÆÃÄê¤Î¥ê¥½¡¼¥¹¤ò»ÈÍѤ¹¤ë" + +msgid "" +"\n" +"Arguments recognised by gvim (GTK+ version):\n" +msgstr "" +"\n" +"gvim¤Ë¤è¤Ã¤Æ²ò¼á¤µ¤ì¤ë°ú¿ô(GTK+¥Ð¡¼¥¸¥ç¥ó):\n" + +msgid "-display <display>\tRun vim on <display> (also: --display)" +msgstr "-display <display>\t<display> ¤Çvim¤ò¼Â¹Ô¤¹¤ë(ƱµÁ: --display)" + +msgid "--role <role>\tSet a unique role to identify the main window" +msgstr "--role <role>\t¥á¥¤¥ó¥¦¥£¥ó¥É¥¦¤ò¼±Ê̤¹¤ë°ì°Õ¤ÊÌò³ä(role)¤òÀßÄꤹ¤ë" + +msgid "--socketid <xid>\tOpen Vim inside another GTK widget" +msgstr "--socketid <xid>\t°Û¤Ê¤ëGTK widget¤ÇVim¤ò³«¤¯" + +msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" +msgstr "--echo-wid\t\t¥¦¥£¥ó¥É¥¦ID¤òɸ½à½ÐÎϤ˽ÐÎϤ¹¤ë" + +msgid "-P <parent title>\tOpen Vim inside parent application" +msgstr "-P <¿Æ¤Î¥¿¥¤¥È¥ë>\tVim¤ò¿Æ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤ÎÃæ¤Çµ¯Æ°¤¹¤ë" + +msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" +msgstr "--windowid <HWND>\t°Û¤Ê¤ëWin32 widget¤ÎÆâÉô¤ËVim¤ò³«¤¯" + +msgid "No display" +msgstr "¥Ç¥£¥¹¥×¥ì¥¤¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" + +#. Failed to send, abort. +msgid ": Send failed.\n" +msgstr ": Á÷¿®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿.\n" + +#. Let vim start normally. +msgid ": Send failed. Trying to execute locally\n" +msgstr ": Á÷¿®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿. ¥í¡¼¥«¥ë¤Ç¤Î¼Â¹Ô¤ò»î¤ß¤Æ¤¤¤Þ¤¹\n" + +#, c-format +msgid "%d of %d edited" +msgstr "%d ¸Ä (%d ¸ÄÃæ) ¤Î¥Õ¥¡¥¤¥ë¤òÊÔ½¸¤·¤Þ¤·¤¿" + +msgid "No display: Send expression failed.\n" +msgstr "¥Ç¥£¥¹¥×¥ì¥¤¤¬¤¢¤ê¤Þ¤»¤ó: ¼°¤ÎÁ÷¿®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿.\n" + +msgid ": Send expression failed.\n" +msgstr ": ¼°¤ÎÁ÷¿®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿.\n" + msgid "No marks set" msgstr "¥Þ¡¼¥¯¤¬ÀßÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó" -#: ../mark.c:678 #, c-format msgid "E283: No marks matching \"%s\"" msgstr "E283: \"%s\" ¤Ë³ºÅö¤¹¤ë¥Þ¡¼¥¯¤¬¤¢¤ê¤Þ¤»¤ó" #. Highlight title -#: ../mark.c:687 msgid "" "\n" "mark line col file/text" @@ -3602,7 +3261,6 @@ msgstr "" "mark ¹Ô Îó ¥Õ¥¡¥¤¥ë/¥Æ¥¥¹¥È" #. Highlight title -#: ../mark.c:789 msgid "" "\n" " jump line col file/text" @@ -3611,7 +3269,6 @@ msgstr "" " jump ¹Ô Îó ¥Õ¥¡¥¤¥ë/¥Æ¥¥¹¥È" #. Highlight title -#: ../mark.c:831 msgid "" "\n" "change line col text" @@ -3619,7 +3276,6 @@ msgstr "" "\n" "Êѹ¹ ¹Ô Îó ¥Æ¥¥¹¥È" -#: ../mark.c:1238 msgid "" "\n" "# File marks:\n" @@ -3628,7 +3284,6 @@ msgstr "" "# ¥Õ¥¡¥¤¥ë¥Þ¡¼¥¯:\n" #. Write the jumplist with -' -#: ../mark.c:1271 msgid "" "\n" "# Jumplist (newest first):\n" @@ -3636,7 +3291,6 @@ msgstr "" "\n" "# ¥¸¥ã¥ó¥×¥ê¥¹¥È (¿·¤·¤¤¤â¤Î¤¬Àè):\n" -#: ../mark.c:1352 msgid "" "\n" "# History of marks within files (newest to oldest):\n" @@ -3644,84 +3298,88 @@ msgstr "" "\n" "# ¥Õ¥¡¥¤¥ëÆâ¥Þ¡¼¥¯¤ÎÍúÎò (¿·¤·¤¤¤â¤Î¤«¤é¸Å¤¤¤â¤Î):\n" -#: ../mark.c:1431 msgid "Missing '>'" msgstr "'>' ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../memfile.c:426 +msgid "E543: Not a valid codepage" +msgstr "E543: ̵¸ú¤Ê¥³¡¼¥É¥Ú¡¼¥¸¤Ç¤¹" + +msgid "E284: Cannot set IC values" +msgstr "E284: IC¤ÎÃͤòÀßÄê¤Ç¤¤Þ¤»¤ó" + +msgid "E285: Failed to create input context" +msgstr "E285: ¥¤¥ó¥×¥Ã¥È¥³¥ó¥Æ¥¥¹¥È¤ÎºîÀ®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" + +msgid "E286: Failed to open input method" +msgstr "E286: ¥¤¥ó¥×¥Ã¥È¥á¥½¥Ã¥É¤Î¥ª¡¼¥×¥ó¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" + +msgid "E287: Warning: Could not set destroy callback to IM" +msgstr "E287: ·Ù¹ð: IM¤ÎÇ˲õ¥³¡¼¥ë¥Ð¥Ã¥¯¤òÀßÄê¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" + +msgid "E288: input method doesn't support any style" +msgstr "E288: ¥¤¥ó¥×¥Ã¥È¥á¥½¥Ã¥É¤Ï¤É¤ó¤Ê¥¹¥¿¥¤¥ë¤â¥µ¥Ý¡¼¥È¤·¤Þ¤»¤ó" + +msgid "E289: input method doesn't support my preedit type" +msgstr "E289: ¥¤¥ó¥×¥Ã¥È¥á¥½¥Ã¥É¤Ï my preedit type ¤ò¥µ¥Ý¡¼¥È¤·¤Þ¤»¤ó" + msgid "E293: block was not locked" msgstr "E293: ¥Ö¥í¥Ã¥¯¤¬¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#: ../memfile.c:799 msgid "E294: Seek error in swap file read" msgstr "E294: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ëÆÉ¹þ»þ¤Ë¥·¡¼¥¯¥¨¥é¡¼¤Ç¤¹" -#: ../memfile.c:803 msgid "E295: Read error in swap file" msgstr "E295: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤ÎÆÉ¹þ¤ß¥¨¥é¡¼¤Ç¤¹" -#: ../memfile.c:849 msgid "E296: Seek error in swap file write" msgstr "E296: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë½ñ¹þ¤ß»þ¤Ë¥·¡¼¥¯¥¨¥é¡¼¤Ç¤¹" -#: ../memfile.c:865 msgid "E297: Write error in swap file" msgstr "E297: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤Î½ñ¹þ¤ß¥¨¥é¡¼¤Ç¤¹" -#: ../memfile.c:1036 msgid "E300: Swap file already exists (symlink attack?)" msgstr "E300: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬´û¤Ë¸ºß¤·¤Þ¤¹ (symlink¤Ë¤è¤ë¹¶·â?)" -#: ../memline.c:318 msgid "E298: Didn't get block nr 0?" msgstr "E298: ¥Ö¥í¥Ã¥¯ 0 ¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó?" -#: ../memline.c:361 msgid "E298: Didn't get block nr 1?" msgstr "E298: ¥Ö¥í¥Ã¥¯ 1 ¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó?" -#: ../memline.c:377 msgid "E298: Didn't get block nr 2?" msgstr "E298: ¥Ö¥í¥Ã¥¯ 2 ¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó?" +msgid "E843: Error while updating swap file crypt" +msgstr "E843: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤Î°Å¹æ¤ò¹¹¿·Ãæ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤Þ¤·¤¿" + #. could not (re)open the swap file, what can we do???? -#: ../memline.c:465 msgid "E301: Oops, lost the swap file!!!" msgstr "E301: ¤ª¤Ã¤È, ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬¼º¤ï¤ì¤Þ¤·¤¿!!!" -#: ../memline.c:477 msgid "E302: Could not rename swap file" msgstr "E302: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤Î̾Á°¤òÊѤ¨¤é¤ì¤Þ¤»¤ó" -#: ../memline.c:554 #, c-format msgid "E303: Unable to open swap file for \"%s\", recovery impossible" msgstr "E303: \"%s\" ¤Î¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤ò³«¤±¤Ê¤¤¤Î¤Ç¥ê¥«¥Ð¥ê¤ÏÉÔ²Äǽ¤Ç¤¹" -#: ../memline.c:666 msgid "E304: ml_upd_block0(): Didn't get block 0??" msgstr "E304: ml_upd_block0(): ¥Ö¥í¥Ã¥¯ 0 ¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿??" -#. no swap files found -#: ../memline.c:830 #, c-format msgid "E305: No swap file found for %s" msgstr "E305: %s ¤Ë¤Ï¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../memline.c:839 msgid "Enter number of swap file to use (0 to quit): " msgstr "»ÈÍѤ¹¤ë¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤ÎÈÖ¹æ¤òÆþÎϤ·¤Æ¤¯¤À¤µ¤¤(0 ¤Ç½ªÎ»): " -#: ../memline.c:879 #, c-format msgid "E306: Cannot open %s" msgstr "E306: %s ¤ò³«¤±¤Þ¤»¤ó" -#: ../memline.c:897 msgid "Unable to read block 0 from " msgstr "¥Ö¥í¥Ã¥¯ 0 ¤òÆÉ¹þ¤á¤Þ¤»¤ó " -#: ../memline.c:900 msgid "" "\n" "Maybe no changes were made or Vim did not update the swap file." @@ -3729,28 +3387,22 @@ msgstr "" "\n" "¶²¤é¤¯Êѹ¹¤¬¤µ¤ì¤Æ¤¤¤Ê¤¤¤«Vim¤¬¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤ò¹¹¿·¤·¤Æ¤¤¤Þ¤»¤ó." -#: ../memline.c:909 msgid " cannot be used with this version of Vim.\n" msgstr " Vim¤Î¤³¤Î¥Ð¡¼¥¸¥ç¥ó¤Ç¤Ï»ÈÍѤǤ¤Þ¤»¤ó.\n" -#: ../memline.c:911 msgid "Use Vim version 3.0.\n" msgstr "Vim¤Î¥Ð¡¼¥¸¥ç¥ó3.0¤ò»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤.\n" -#: ../memline.c:916 #, c-format msgid "E307: %s does not look like a Vim swap file" msgstr "E307: %s ¤ÏVim¤Î¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤Ç¤Ï¤Ê¤¤¤è¤¦¤Ç¤¹" -#: ../memline.c:922 msgid " cannot be used on this computer.\n" msgstr " ¤³¤Î¥³¥ó¥Ô¥å¡¼¥¿¤Ç¤Ï»ÈÍѤǤ¤Þ¤»¤ó.\n" -#: ../memline.c:924 msgid "The file was created on " msgstr "¤³¤Î¥Õ¥¡¥¤¥ë¤Ï¼¡¤Î¾ì½ê¤Çºî¤é¤ì¤Þ¤·¤¿ " -#: ../memline.c:928 msgid "" ",\n" "or the file has been damaged." @@ -3758,85 +3410,104 @@ msgstr "" ",\n" "¤â¤·¤¯¤Ï¥Õ¥¡¥¤¥ë¤¬Â»½ý¤·¤Æ¤¤¤Þ¤¹." -#: ../memline.c:945 +#, c-format +msgid "" +"E833: %s is encrypted and this version of Vim does not support encryption" +msgstr "" +"E833: %s ¤Ï¤³¤Î¥Ð¡¼¥¸¥ç¥ó¤ÎVim¤Ç¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤Ê¤¤·Á¼°¤Ç°Å¹æ²½¤µ¤ì¤Æ¤¤¤Þ¤¹" + msgid " has been damaged (page size is smaller than minimum value).\n" msgstr " ¤Ï»½ý¤·¤Æ¤¤¤Þ¤¹ (¥Ú¡¼¥¸¥µ¥¤¥º¤¬ºÇ¾®Ãͤò²¼²ó¤Ã¤Æ¤¤¤Þ¤¹).\n" -#: ../memline.c:974 #, c-format msgid "Using swap file \"%s\"" msgstr "¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë \"%s\" ¤ò»ÈÍÑÃæ" -#: ../memline.c:980 #, c-format msgid "Original file \"%s\"" msgstr "¸¶ËÜ¥Õ¥¡¥¤¥ë \"%s\"" -#: ../memline.c:995 msgid "E308: Warning: Original file may have been changed" msgstr "E308: ·Ù¹ð: ¸¶ËÜ¥Õ¥¡¥¤¥ë¤¬Êѹ¹¤µ¤ì¤Æ¤¤¤Þ¤¹" -#: ../memline.c:1061 +#, c-format +msgid "Swap file is encrypted: \"%s\"" +msgstr "¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤Ï°Å¹æ²½¤µ¤ì¤Æ¤¤¤Þ¤¹: \"%s\"" + +msgid "" +"\n" +"If you entered a new crypt key but did not write the text file," +msgstr "" +"\n" +"¿·¤·¤¤°Å¹æ¥¡¼¤òÆþÎϤ·¤¿¤¢¤È¤Ë¥Æ¥¥¹¥È¥Õ¥¡¥¤¥ë¤òÊݸ¤·¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ï," + +msgid "" +"\n" +"enter the new crypt key." +msgstr "" +"\n" +"¿·¤·¤¤°Å¹æ¥¡¼¤òÆþÎϤ·¤Æ¤¯¤À¤µ¤¤." + +msgid "" +"\n" +"If you wrote the text file after changing the crypt key press enter" +msgstr "" +"\n" +"°Å¹æ¥¡¼¤òÊѤ¨¤¿¤¢¤È¤Ë¥Æ¥¥¹¥È¥Õ¥¡¥¤¥ë¤òÊݸ¤·¤¿¾ì¹ç¤Ï, ¥Æ¥¥¹¥È¥Õ¥¡¥¤¥ë¤È" + +msgid "" +"\n" +"to use the same key for text file and swap file" +msgstr "" +"\n" +"¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤ËƱ¤¸°Å¹æ¥¡¼¤ò»È¤¦¤¿¤á¤Ëenter¤À¤±¤ò²¡¤·¤Æ¤¯¤À¤µ¤¤." + #, c-format msgid "E309: Unable to read block 1 from %s" msgstr "E309: %s ¤«¤é¥Ö¥í¥Ã¥¯ 1 ¤òÆÉ¹þ¤á¤Þ¤»¤ó" -#: ../memline.c:1065 msgid "???MANY LINES MISSING" msgstr "???¿¤¯¤Î¹Ô¤¬¼º¤ï¤ì¤Æ¤¤¤Þ¤¹" -#: ../memline.c:1076 msgid "???LINE COUNT WRONG" msgstr "???¹Ô¿ô¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹" -#: ../memline.c:1082 msgid "???EMPTY BLOCK" msgstr "???¥Ö¥í¥Ã¥¯¤¬¶õ¤Ç¤¹" -#: ../memline.c:1103 msgid "???LINES MISSING" msgstr "???¹Ô¤¬¼º¤ï¤ì¤Æ¤¤¤Þ¤¹" -#: ../memline.c:1128 #, c-format msgid "E310: Block 1 ID wrong (%s not a .swp file?)" msgstr "E310: ¥Ö¥í¥Ã¥¯ 1 ¤ÎID¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹(%s ¤¬.swp¥Õ¥¡¥¤¥ë¤Ç¤Ê¤¤?)" -#: ../memline.c:1133 msgid "???BLOCK MISSING" msgstr "???¥Ö¥í¥Ã¥¯¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../memline.c:1147 msgid "??? from here until ???END lines may be messed up" msgstr "??? ¤³¤³¤«¤é ???END ¤Þ¤Ç¤Î¹Ô¤¬Ç˲õ¤µ¤ì¤Æ¤¤¤ë¤è¤¦¤Ç¤¹" -#: ../memline.c:1164 msgid "??? from here until ???END lines may have been inserted/deleted" msgstr "??? ¤³¤³¤«¤é ???END ¤Þ¤Ç¤Î¹Ô¤¬ÁÞÆþ¤«ºï½ü¤µ¤ì¤¿¤è¤¦¤Ç¤¹" -#: ../memline.c:1181 msgid "???END" msgstr "???END" -#: ../memline.c:1238 msgid "E311: Recovery Interrupted" msgstr "E311: ¥ê¥«¥Ð¥ê¤¬³ä¹þ¤Þ¤ì¤Þ¤·¤¿" -#: ../memline.c:1243 msgid "" "E312: Errors detected while recovering; look for lines starting with ???" msgstr "" "E312: ¥ê¥«¥Ð¥ê¤ÎºÇÃæ¤Ë¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤Þ¤·¤¿; ???¤Ç»Ï¤Þ¤ë¹Ô¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤" -#: ../memline.c:1245 msgid "See \":help E312\" for more information." msgstr "¾ÜºÙ¤Ï \":help E312\" ¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤" -#: ../memline.c:1249 msgid "Recovery completed. You should check if everything is OK." msgstr "¥ê¥«¥Ð¥ê¤¬½ªÎ»¤·¤Þ¤·¤¿. Á´¤Æ¤¬Àµ¤·¤¤¤«¥Á¥§¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤." -#: ../memline.c:1251 msgid "" "\n" "(You might want to write out this file under another name\n" @@ -3844,15 +3515,12 @@ msgstr "" "\n" "(Êѹ¹¤ò¥Á¥§¥Ã¥¯¤¹¤ë¤¿¤á¤Ë, ¤³¤Î¥Õ¥¡¥¤¥ë¤òÊ̤Î̾Á°¤ÇÊݸ¤·¤¿¾å¤Ç\n" -#: ../memline.c:1252 msgid "and run diff with the original file to check for changes)" msgstr "¸¶ËÜ¥Õ¥¡¥¤¥ë¤È¤Î diff ¤ò¼Â¹Ô¤¹¤ë¤ÈÎɤ¤¤Ç¤·¤ç¤¦)" -#: ../memline.c:1254 msgid "Recovery completed. Buffer contents equals file contents." msgstr "Éü¸µ´°Î». ¥Ð¥Ã¥Õ¥¡¤ÎÆâÍÆ¤Ï¥Õ¥¡¥¤¥ë¤ÈƱ¤¸¤Ë¤Ê¤ê¤Þ¤·¤¿." -#: ../memline.c:1255 msgid "" "\n" "You may want to delete the .swp file now.\n" @@ -3862,52 +3530,43 @@ msgstr "" "¸µ¤Î.swp¥Õ¥¡¥¤¥ë¤Ïºï½ü¤·¤Æ¤â¹½¤¤¤Þ¤»¤ó\n" "\n" +msgid "Using crypt key from swap file for the text file.\n" +msgstr "¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤«¤é¼èÆÀ¤·¤¿°Å¹æ¥¡¼¤ò¥Æ¥¥¹¥È¥Õ¥¡¥¤¥ë¤Ë»È¤¤¤Þ¤¹.\n" + #. use msg() to start the scrolling properly -#: ../memline.c:1327 msgid "Swap files found:" msgstr "¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬Ê£¿ô¸«¤Ä¤«¤ê¤Þ¤·¤¿:" -#: ../memline.c:1446 msgid " In current directory:\n" msgstr " ¸½ºß¤Î¥Ç¥£¥ì¥¯¥È¥ê:\n" -#: ../memline.c:1448 msgid " Using specified name:\n" msgstr " °Ê²¼¤Î̾Á°¤ò»ÈÍÑÃæ:\n" -#: ../memline.c:1450 msgid " In directory " msgstr " ¥Ç¥£¥ì¥¯¥È¥ê " -#: ../memline.c:1465 msgid " -- none --\n" msgstr " -- ¤Ê¤· --\n" -#: ../memline.c:1527 msgid " owned by: " msgstr " ½êͼÔ: " -#: ../memline.c:1529 msgid " dated: " msgstr " ÆüÉÕ: " -#: ../memline.c:1532 ../memline.c:3231 msgid " dated: " msgstr " ÆüÉÕ: " -#: ../memline.c:1548 msgid " [from Vim version 3.0]" msgstr " [from Vim version 3.0]" -#: ../memline.c:1550 msgid " [does not look like a Vim swap file]" msgstr " [Vim¤Î¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤Ç¤Ï¤Ê¤¤¤è¤¦¤Ç¤¹]" -#: ../memline.c:1552 msgid " file name: " msgstr " ¥Õ¥¡¥¤¥ë̾: " -#: ../memline.c:1558 msgid "" "\n" " modified: " @@ -3915,15 +3574,12 @@ msgstr "" "\n" " Êѹ¹¾õÂÖ: " -#: ../memline.c:1559 msgid "YES" msgstr "¤¢¤ê" -#: ../memline.c:1559 msgid "no" msgstr "¤Ê¤·" -#: ../memline.c:1562 msgid "" "\n" " user name: " @@ -3931,11 +3587,9 @@ msgstr "" "\n" " ¥æ¡¼¥¶¡¼Ì¾: " -#: ../memline.c:1568 msgid " host name: " msgstr " ¥Û¥¹¥È̾: " -#: ../memline.c:1570 msgid "" "\n" " host name: " @@ -3943,7 +3597,6 @@ msgstr "" "\n" " ¥Û¥¹¥È̾: " -#: ../memline.c:1575 msgid "" "\n" " process ID: " @@ -3951,11 +3604,16 @@ msgstr "" "\n" " ¥×¥í¥»¥¹ID: " -#: ../memline.c:1579 msgid " (still running)" msgstr " (¤Þ¤À¼Â¹ÔÃæ)" -#: ../memline.c:1586 +msgid "" +"\n" +" [not usable with this version of Vim]" +msgstr "" +"\n" +" [¤³¤ÎVim¥Ð¡¼¥¸¥ç¥ó¤Ç¤Ï»ÈÍѤǤ¤Þ¤»¤ó]" + msgid "" "\n" " [not usable on this computer]" @@ -3963,97 +3621,75 @@ msgstr "" "\n" " [¤³¤Î¥³¥ó¥Ô¥å¡¼¥¿¤Ç¤Ï»ÈÍѤǤ¤Þ¤»¤ó]" -#: ../memline.c:1590 msgid " [cannot be read]" msgstr " [ÆÉ¹þ¤á¤Þ¤»¤ó]" -#: ../memline.c:1593 msgid " [cannot be opened]" msgstr " [³«¤±¤Þ¤»¤ó]" -#: ../memline.c:1698 msgid "E313: Cannot preserve, there is no swap file" msgstr "E313: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬Ìµ¤¤¤Î¤Ç°Ý»ý¤Ç¤¤Þ¤»¤ó" -#: ../memline.c:1747 msgid "File preserved" msgstr "¥Õ¥¡¥¤¥ë¤¬°Ý»ý¤µ¤ì¤Þ¤¹" -#: ../memline.c:1749 msgid "E314: Preserve failed" msgstr "E314: °Ý»ý¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#: ../memline.c:1819 #, c-format -msgid "E315: ml_get: invalid lnum: %<PRId64>" -msgstr "E315: ml_get: ̵¸ú¤Êlnum¤Ç¤¹: %<PRId64>" +msgid "E315: ml_get: invalid lnum: %ld" +msgstr "E315: ml_get: ̵¸ú¤Êlnum¤Ç¤¹: %ld" -#: ../memline.c:1851 #, c-format -msgid "E316: ml_get: cannot find line %<PRId64>" -msgstr "E316: ml_get: ¹Ô %<PRId64> ¤ò¸«¤Ä¤±¤é¤ì¤Þ¤»¤ó" +msgid "E316: ml_get: cannot find line %ld" +msgstr "E316: ml_get: ¹Ô %ld ¤ò¸«¤Ä¤±¤é¤ì¤Þ¤»¤ó" -#: ../memline.c:2236 msgid "E317: pointer block id wrong 3" msgstr "E317: ¥Ý¥¤¥ó¥¿¥Ö¥í¥Ã¥¯¤ÎID¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹ 3" -#: ../memline.c:2311 msgid "stack_idx should be 0" msgstr "stack_idx ¤Ï 0 ¤Ç¤¢¤ë¤Ù¤¤Ç¤¹" -#: ../memline.c:2369 msgid "E318: Updated too many blocks?" msgstr "E318: ¹¹¿·¤µ¤ì¤¿¥Ö¥í¥Ã¥¯¤¬Â¿²á¤®¤ë¤«¤â?" -#: ../memline.c:2511 msgid "E317: pointer block id wrong 4" msgstr "E317: ¥Ý¥¤¥ó¥¿¥Ö¥í¥Ã¥¯¤ÎID¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹ 4" -#: ../memline.c:2536 msgid "deleted block 1?" msgstr "¥Ö¥í¥Ã¥¯ 1 ¤Ï¾Ã¤µ¤ì¤¿?" -#: ../memline.c:2707 #, c-format -msgid "E320: Cannot find line %<PRId64>" -msgstr "E320: ¹Ô %<PRId64> ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" +msgid "E320: Cannot find line %ld" +msgstr "E320: ¹Ô %ld ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../memline.c:2916 msgid "E317: pointer block id wrong" msgstr "E317: ¥Ý¥¤¥ó¥¿¥Ö¥í¥Ã¥¯¤ÎID¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹" -#: ../memline.c:2930 msgid "pe_line_count is zero" msgstr "pe_line_count ¤¬¥¼¥í¤Ç¤¹" -#: ../memline.c:2955 #, c-format -msgid "E322: line number out of range: %<PRId64> past the end" -msgstr "E322: ¹ÔÈֹ椬Èϰϳ°¤Ç¤¹: %<PRId64> ͤ¨¤Æ¤¤¤Þ¤¹" +msgid "E322: line number out of range: %ld past the end" +msgstr "E322: ¹ÔÈֹ椬Èϰϳ°¤Ç¤¹: %ld ͤ¨¤Æ¤¤¤Þ¤¹" -#: ../memline.c:2959 #, c-format -msgid "E323: line count wrong in block %<PRId64>" -msgstr "E323: ¥Ö¥í¥Ã¥¯ %<PRId64> ¤Î¹Ô¥«¥¦¥ó¥È¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹" +msgid "E323: line count wrong in block %ld" +msgstr "E323: ¥Ö¥í¥Ã¥¯ %ld ¤Î¹Ô¥«¥¦¥ó¥È¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹" -#: ../memline.c:2999 msgid "Stack size increases" msgstr "¥¹¥¿¥Ã¥¯¥µ¥¤¥º¤¬Áý¤¨¤Þ¤¹" -#: ../memline.c:3038 msgid "E317: pointer block id wrong 2" msgstr "E317: ¥Ý¥¤¥ó¥¿¥Ö¥í¥Ã¥¯¤ÎID¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹ 2" -#: ../memline.c:3070 #, c-format msgid "E773: Symlink loop for \"%s\"" msgstr "E773: \"%s\" ¤Î¥·¥ó¥Ü¥ê¥Ã¥¯¥ê¥ó¥¯¤¬¥ë¡¼¥×¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹" -#: ../memline.c:3221 msgid "E325: ATTENTION" msgstr "E325: Ãí°Õ" -#: ../memline.c:3222 msgid "" "\n" "Found a swap file by the name \"" @@ -4061,39 +3697,32 @@ msgstr "" "\n" "¼¡¤Î̾Á°¤Ç¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤ò¸«¤Ä¤±¤Þ¤·¤¿ \"" -#: ../memline.c:3226 msgid "While opening file \"" msgstr "¼¡¤Î¥Õ¥¡¥¤¥ë¤ò³«¤¤¤Æ¤¤¤ëºÇÃæ \"" -#: ../memline.c:3239 msgid " NEWER than swap file!\n" msgstr " ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤è¤ê¤â¿·¤·¤¤¤Ç¤¹!\n" -#: ../memline.c:3244 +#. Some of these messages are long to allow translation to +#. * other languages. msgid "" "\n" "(1) Another program may be editing the same file. If this is the case,\n" " be careful not to end up with two different instances of the same\n" -" file when making changes." +" file when making changes. Quit, or continue with caution.\n" msgstr "" "\n" "(1) ÊÌ¤Î¥×¥í¥°¥é¥à¤¬Æ±¤¸¥Õ¥¡¥¤¥ë¤òÊÔ½¸¤·¤Æ¤¤¤ë¤«¤â¤·¤ì¤Þ¤»¤ó.\n" " ¤³¤Î¾ì¹ç¤Ë¤Ï, Êѹ¹¤ò¤·¤Æ¤·¤Þ¤¦¤È1¤Ä¤Î¥Õ¥¡¥¤¥ë¤ËÂФ·¤Æ°Û¤Ê¤ë2¤Ä¤Î\n" -" ¥¤¥ó¥¹¥¿¥ó¥¹¤¬¤Ç¤¤Æ¤·¤Þ¤¦¤Î¤Ç, ¤½¤¦¤·¤Ê¤¤¤è¤¦¤Ëµ¤¤ò¤Ä¤±¤Æ¤¯¤À¤µ¤¤." - -#: ../memline.c:3245 -msgid " Quit, or continue with caution.\n" -msgstr " ½ªÎ»¤¹¤ë¤«, Ãí°Õ¤·¤Ê¤¬¤é³¤±¤Æ¤¯¤À¤µ¤¤.\n" +" ¥¤¥ó¥¹¥¿¥ó¥¹¤¬¤Ç¤¤Æ¤·¤Þ¤¦¤Î¤Ç, ¤½¤¦¤·¤Ê¤¤¤è¤¦¤Ëµ¤¤ò¤Ä¤±¤Æ¤¯¤À¤µ¤¤.\n" +" ½ªÎ»¤¹¤ë¤«, Ãí°Õ¤·¤Ê¤¬¤é³¤±¤Æ¤¯¤À¤µ¤¤.\n" -#: ../memline.c:3246 msgid "(2) An edit session for this file crashed.\n" msgstr "(2) ¤³¤Î¥Õ¥¡¥¤¥ë¤ÎÊÔ½¸¥»¥Ã¥·¥ç¥ó¤¬¥¯¥é¥Ã¥·¥å¤·¤¿.\n" -#: ../memline.c:3247 msgid " If this is the case, use \":recover\" or \"vim -r " msgstr " ¤³¤Î¾ì¹ç¤Ë¤Ï \":recover\" ¤« \"vim -r " -#: ../memline.c:3249 msgid "" "\"\n" " to recover the changes (see \":help recovery\").\n" @@ -4101,11 +3730,9 @@ msgstr "" "\"\n" " ¤ò»ÈÍѤ·¤ÆÊѹ¹¤ò¥ê¥«¥Ð¡¼¤·¤Þ¤¹(\":help recovery\" ¤ò»²¾È).\n" -#: ../memline.c:3250 msgid " If you did this already, delete the swap file \"" msgstr " ´û¤Ë¤³¤ì¤ò¹Ô¤Ê¤Ã¤¿¤Î¤Ê¤é¤Ð, ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë \"" -#: ../memline.c:3252 msgid "" "\"\n" " to avoid this message.\n" @@ -4113,23 +3740,18 @@ msgstr "" "\"\n" " ¤ò¾Ã¤»¤Ð¤³¤Î¥á¥Ã¥»¡¼¥¸¤ò²óÈò¤Ç¤¤Þ¤¹.\n" -#: ../memline.c:3450 ../memline.c:3452 msgid "Swap file \"" msgstr "¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë \"" -#: ../memline.c:3451 ../memline.c:3455 msgid "\" already exists!" msgstr "\" ¤¬´û¤Ë¤¢¤ê¤Þ¤¹!" -#: ../memline.c:3457 msgid "VIM - ATTENTION" msgstr "VIM - Ãí°Õ" -#: ../memline.c:3459 msgid "Swap file already exists!" msgstr "¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬´û¤Ë¸ºß¤·¤Þ¤¹!" -#: ../memline.c:3464 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4143,7 +3765,6 @@ msgstr "" "½ªÎ»¤¹¤ë(&Q)\n" "Ãæ»ß¤¹¤ë(&A)" -#: ../memline.c:3467 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4159,56 +3780,34 @@ msgstr "" "½ªÎ»¤¹¤ë(&Q)\n" "Ãæ»ß¤¹¤ë(&A)" -#. -#. * Change the ".swp" extension to find another file that can be used. -#. * First decrement the last char: ".swo", ".swn", etc. -#. * If that still isn't enough decrement the last but one char: ".svz" -#. * Can happen when editing many "No Name" buffers. -#. -#. ".s?a" -#. ".saa": tried enough, give up -#: ../memline.c:3528 msgid "E326: Too many swap files found" msgstr "E326: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬Â¿¿ô¸«¤Ä¤«¤ê¤Þ¤·¤¿" -#: ../memory.c:227 -#, c-format -msgid "E342: Out of memory! (allocating %<PRIu64> bytes)" -msgstr "E342: ¥á¥â¥ê¤¬Â¤ê¤Þ¤»¤ó! (%<PRIu64> ¥Ð¥¤¥È¤ò³äÅöÍ×µá)" - -#: ../menu.c:62 msgid "E327: Part of menu-item path is not sub-menu" msgstr "E327: ¥á¥Ë¥å¡¼¥¢¥¤¥Æ¥à¤Î¥Ñ¥¹¤ÎÉôʬ¤¬¥µ¥Ö¥á¥Ë¥å¡¼¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../menu.c:63 msgid "E328: Menu only exists in another mode" msgstr "E328: ¥á¥Ë¥å¡¼¤Ï¾¤Î¥â¡¼¥É¤Ë¤À¤±¤¢¤ê¤Þ¤¹" -#: ../menu.c:64 #, c-format msgid "E329: No menu \"%s\"" msgstr "E329: \"%s\" ¤È¤¤¤¦¥á¥Ë¥å¡¼¤Ï¤¢¤ê¤Þ¤»¤ó" #. Only a mnemonic or accelerator is not valid. -#: ../menu.c:329 msgid "E792: Empty menu name" msgstr "E792: ¥á¥Ë¥å¡¼Ì¾¤¬¶õ¤Ç¤¹" -#: ../menu.c:340 msgid "E330: Menu path must not lead to a sub-menu" msgstr "E330: ¥á¥Ë¥å¡¼¥Ñ¥¹¤Ï¥µ¥Ö¥á¥Ë¥å¡¼¤òÀ¸¤¸¤ë¤Ù¤¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../menu.c:365 msgid "E331: Must not add menu items directly to menu bar" msgstr "E331: ¥á¥Ë¥å¡¼¥Ð¡¼¤Ë¤ÏľÀÜ¥á¥Ë¥å¡¼¥¢¥¤¥Æ¥à¤òÄɲäǤ¤Þ¤»¤ó" -#: ../menu.c:370 msgid "E332: Separator cannot be part of a menu path" msgstr "E332: ¶èÀÚ¤ê¤Ï¥á¥Ë¥å¡¼¥Ñ¥¹¤Î°ìÉô¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó" #. Now we have found the matching menu, and we list the mappings #. Highlight title -#: ../menu.c:762 msgid "" "\n" "--- Menus ---" @@ -4216,69 +3815,60 @@ msgstr "" "\n" "--- ¥á¥Ë¥å¡¼ ---" -#: ../menu.c:1313 +msgid "Tear off this menu" +msgstr "¤³¤Î¥á¥Ë¥å¡¼¤òÀÚ¤ê¼è¤ë" + msgid "E333: Menu path must lead to a menu item" msgstr "E333: ¥á¥Ë¥å¡¼¥Ñ¥¹¤Ï¥á¥Ë¥å¡¼¥¢¥¤¥Æ¥à¤òÀ¸¤¸¤Ê¤±¤ì¤Ð¤¤¤±¤Þ¤»¤ó" -#: ../menu.c:1330 #, c-format msgid "E334: Menu not found: %s" msgstr "E334: ¥á¥Ë¥å¡¼¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó: %s" -#: ../menu.c:1396 #, c-format msgid "E335: Menu not defined for %s mode" msgstr "E335: %s ¤Ë¤Ï¥á¥Ë¥å¡¼¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#: ../menu.c:1426 msgid "E336: Menu path must lead to a sub-menu" msgstr "E336: ¥á¥Ë¥å¡¼¥Ñ¥¹¤Ï¥µ¥Ö¥á¥Ë¥å¡¼¤òÀ¸¤¸¤Ê¤±¤ì¤Ð¤¤¤±¤Þ¤»¤ó" -#: ../menu.c:1447 msgid "E337: Menu not found - check menu names" msgstr "E337: ¥á¥Ë¥å¡¼¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó - ¥á¥Ë¥å¡¼Ì¾¤ò³Îǧ¤·¤Æ¤¯¤À¤µ¤¤" -#: ../message.c:423 #, c-format msgid "Error detected while processing %s:" msgstr "%s ¤Î½èÍýÃæ¤Ë¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤Þ¤·¤¿:" -#: ../message.c:445 #, c-format msgid "line %4ld:" msgstr "¹Ô %4ld:" -#: ../message.c:617 #, c-format msgid "E354: Invalid register name: '%s'" msgstr "E354: ̵¸ú¤Ê¥ì¥¸¥¹¥¿Ì¾: '%s'" -#: ../message.c:986 +msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>" +msgstr "ÆüËܸì¥á¥Ã¥»¡¼¥¸ËÝÌõ/´Æ½¤: ¼²¬ ÂÀϺ <koron.kaoriya@gmail.com>" + msgid "Interrupt: " msgstr "³ä¹þ¤ß: " -#: ../message.c:988 msgid "Press ENTER or type command to continue" msgstr "³¤±¤ë¤Ë¤ÏENTER¤ò²¡¤¹¤«¥³¥Þ¥ó¥É¤òÆþÎϤ·¤Æ¤¯¤À¤µ¤¤" -#: ../message.c:1843 #, c-format -msgid "%s line %<PRId64>" -msgstr "%s ¹Ô %<PRId64>" +msgid "%s line %ld" +msgstr "%s ¹Ô %ld" -#: ../message.c:2392 msgid "-- More --" msgstr "-- ·Ñ³ --" -#: ../message.c:2398 msgid " SPACE/d/j: screen/page/line down, b/u/k: up, q: quit " msgstr " SPACE/d/j: ²èÌÌ/¥Ú¡¼¥¸/¹Ô ²¼, b/u/k: ¾å, q: ½ªÎ» " -#: ../message.c:3021 ../message.c:3031 msgid "Question" msgstr "¼ÁÌä" -#: ../message.c:3023 msgid "" "&Yes\n" "&No" @@ -4286,17 +3876,6 @@ msgstr "" "¤Ï¤¤(&Y)\n" "¤¤¤¤¤¨(&N)" -#: ../message.c:3033 -msgid "" -"&Yes\n" -"&No\n" -"&Cancel" -msgstr "" -"¤Ï¤¤(&Y)\n" -"¤¤¤¤¤¨(&N)\n" -"¥¥ã¥ó¥»¥ë(&C)" - -#: ../message.c:3045 msgid "" "&Yes\n" "&No\n" @@ -4310,175 +3889,247 @@ msgstr "" "Á´¤ÆÊü´þ(&D)\n" "¥¥ã¥ó¥»¥ë(&C)" -#: ../message.c:3058 +msgid "Select Directory dialog" +msgstr "¥Ç¥£¥ì¥¯¥È¥êÁªÂò¥À¥¤¥¢¥í¥°" + +msgid "Save File dialog" +msgstr "¥Õ¥¡¥¤¥ëÊݸ¥À¥¤¥¢¥í¥°" + +msgid "Open File dialog" +msgstr "¥Õ¥¡¥¤¥ëÆÉ¹þ¥À¥¤¥¢¥í¥°" + +#. TODO: non-GUI file selector here +msgid "E338: Sorry, no file browser in console mode" +msgstr "E338: ¥³¥ó¥½¡¼¥ë¥â¡¼¥É¤Ç¤Ï¥Õ¥¡¥¤¥ë¥Ö¥é¥¦¥¶¤ò»È¤¨¤Þ¤»¤ó, ¤´¤á¤ó¤Ê¤µ¤¤" + msgid "E766: Insufficient arguments for printf()" msgstr "E766: printf() ¤Î°ú¿ô¤¬ÉÔ½½Ê¬¤Ç¤¹" -#: ../message.c:3119 msgid "E807: Expected Float argument for printf()" msgstr "E807: printf() ¤Î°ú¿ô¤Ë¤ÏÉâÆ°¾¯¿ôÅÀ¿ô¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤Þ¤¹" -#: ../message.c:3873 msgid "E767: Too many arguments to printf()" msgstr "E767: printf() ¤Î°ú¿ô¤¬Â¿²á¤®¤Þ¤¹" -#: ../misc1.c:2256 msgid "W10: Warning: Changing a readonly file" msgstr "W10: ·Ù¹ð: ÆÉ¹þÀìÍÑ¥Õ¥¡¥¤¥ë¤òÊѹ¹¤·¤Þ¤¹" -#: ../misc1.c:2537 msgid "Type number and <Enter> or click with mouse (empty cancels): " msgstr "" "ÈÖ¹æ¤È<Enter>¤òÆþÎϤ¹¤ë¤«¥Þ¥¦¥¹¤Ç¥¯¥ê¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤ (¶õ¤Ç¥¥ã¥ó¥»¥ë): " -#: ../misc1.c:2539 msgid "Type number and <Enter> (empty cancels): " msgstr "ÈÖ¹æ¤È<Enter>¤òÆþÎϤ·¤Æ¤¯¤À¤µ¤¤ (¶õ¤Ç¥¥ã¥ó¥»¥ë): " -#: ../misc1.c:2585 msgid "1 more line" msgstr "1 ¹Ô Äɲä·¤Þ¤·¤¿" -#: ../misc1.c:2588 msgid "1 line less" msgstr "1 ¹Ô ºï½ü¤·¤Þ¤·¤¿" -#: ../misc1.c:2593 #, c-format -msgid "%<PRId64> more lines" -msgstr "%<PRId64> ¹Ô Äɲä·¤Þ¤·¤¿" +msgid "%ld more lines" +msgstr "%ld ¹Ô Äɲä·¤Þ¤·¤¿" -#: ../misc1.c:2596 #, c-format -msgid "%<PRId64> fewer lines" -msgstr "%<PRId64> ¹Ô ºï½ü¤·¤Þ¤·¤¿" +msgid "%ld fewer lines" +msgstr "%ld ¹Ô ºï½ü¤·¤Þ¤·¤¿" -#: ../misc1.c:2599 msgid " (Interrupted)" msgstr " (³ä¹þ¤Þ¤ì¤Þ¤·¤¿)" -#: ../misc1.c:2635 msgid "Beep!" msgstr "¥Ó¡¼¥Ã!" -#: ../misc2.c:738 +msgid "ERROR: " +msgstr "¥¨¥é¡¼: " + +#, c-format +msgid "" +"\n" +"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n" +msgstr "" +"\n" +"[¥á¥â¥ê(¥Ð¥¤¥È)] Áí³äÅö-²òÊüÎÌ %lu-%lu, »ÈÍÑÎÌ %lu, ¥Ô¡¼¥¯»þ %lu\n" + +#, c-format +msgid "" +"[calls] total re/malloc()'s %lu, total free()'s %lu\n" +"\n" +msgstr "" +"[¸Æ½Ð] Áí re/malloc() ²ó¿ô %lu, Áí free() ²ó¿ô %lu\n" +"\n" + +msgid "E340: Line is becoming too long" +msgstr "E340: ¹Ô¤¬Ä¹¤¯¤Ê¤ê²á¤®¤Þ¤·¤¿" + +#, c-format +msgid "E341: Internal error: lalloc(%ld, )" +msgstr "E341: ÆâÉô¥¨¥é¡¼: lalloc(%ld,)" + +#, c-format +msgid "E342: Out of memory! (allocating %lu bytes)" +msgstr "E342: ¥á¥â¥ê¤¬Â¤ê¤Þ¤»¤ó! (%lu ¥Ð¥¤¥È¤ò³äÅöÍ×µá)" + #, c-format msgid "Calling shell to execute: \"%s\"" msgstr "¼Â¹Ô¤Î¤¿¤á¤Ë¥·¥§¥ë¤ò¸Æ½Ð¤·Ãæ: \"%s\"" -#: ../normal.c:183 +msgid "E545: Missing colon" +msgstr "E545: ¥³¥í¥ó¤¬¤¢¤ê¤Þ¤»¤ó" + +msgid "E546: Illegal mode" +msgstr "E546: ÉÔÀµ¤Ê¥â¡¼¥É¤Ç¤¹" + +msgid "E547: Illegal mouseshape" +msgstr "E547: ÉÔÀµ¤Ê 'mouseshape' ¤Ç¤¹" + +msgid "E548: digit expected" +msgstr "E548: ¿ôÃͤ¬É¬ÍפǤ¹" + +msgid "E549: Illegal percentage" +msgstr "E549: ÉÔÀµ¤Ê¥Ñ¡¼¥»¥ó¥Æ¡¼¥¸¤Ç¤¹" + +msgid "E854: path too long for completion" +msgstr "E854: ¥Ñ¥¹¤¬Ä¹²á¤®¤ÆÊä´°¤Ç¤¤Þ¤»¤ó" + +#, c-format +msgid "" +"E343: Invalid path: '**[number]' must be at the end of the path or be " +"followed by '%s'." +msgstr "" +"E343: ̵¸ú¤Ê¥Ñ¥¹¤Ç¤¹: '**[¿ôÃÍ]' ¤Ïpath¤ÎºÇ¸å¤« '%s' ¤¬Â³¤¤¤Æ¤Ê¤¤¤È¤¤¤±¤Þ¤»" +"¤ó." + +#, c-format +msgid "E344: Can't find directory \"%s\" in cdpath" +msgstr "E344: cdpath¤Ë¤Ï \"%s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó" + +#, c-format +msgid "E345: Can't find file \"%s\" in path" +msgstr "E345: path¤Ë¤Ï \"%s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó" + +#, c-format +msgid "E346: No more directory \"%s\" found in cdpath" +msgstr "E346: cdpath¤Ë¤Ï¤³¤ì°Ê¾å \"%s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó" + +#, c-format +msgid "E347: No more file \"%s\" found in path" +msgstr "E347: ¥Ñ¥¹¤Ë¤Ï¤³¤ì°Ê¾å \"%s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó" + +#, c-format +msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" +msgstr "" +"E668: NetBeans¤ÎÀܳ¾ðÊó¥Õ¥¡¥¤¥ë¤Î¥¢¥¯¥»¥¹¥â¡¼¥É¤ËÌäÂ꤬¤¢¤ê¤Þ¤¹: \"%s\"" + +#, c-format +msgid "E658: NetBeans connection lost for buffer %ld" +msgstr "E658: ¥Ð¥Ã¥Õ¥¡ %ld ¤Î NetBeans Àܳ¤¬¼º¤ï¤ì¤Þ¤·¤¿" + +msgid "E838: netbeans is not supported with this GUI" +msgstr "E838: NetBeans¤Ï¤³¤ÎGUI¤Ë¤ÏÂбþ¤·¤Æ¤¤¤Þ¤»¤ó" + +msgid "E511: netbeans already connected" +msgstr "E511: NetBeans¤Ï´û¤ËÀܳ¤·¤Æ¤¤¤Þ¤¹" + +#, c-format +msgid "E505: %s is read-only (add ! to override)" +msgstr "E505: %s ¤ÏÆÉ¹þÀìÍѤǤ¹ (¶¯À©½ñ¹þ¤Ë¤Ï ! ¤òÄɲÃ)" + msgid "E349: No identifier under cursor" msgstr "E349: ¥«¡¼¥½¥ë¤Î°ÌÃ֤ˤϼ±Ê̻Ҥ¬¤¢¤ê¤Þ¤»¤ó" -#: ../normal.c:1866 msgid "E774: 'operatorfunc' is empty" msgstr "E774: 'operatorfunc' ¥ª¥×¥·¥ç¥ó¤¬¶õ¤Ç¤¹" -#: ../normal.c:2637 +msgid "E775: Eval feature not available" +msgstr "E775: ¼°É¾²Áµ¡Ç½¤¬Ìµ¸ú¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹" + msgid "Warning: terminal cannot highlight" msgstr "·Ù¹ð: »ÈÍѤ·¤Æ¤¤¤ëüËö¤Ï¥Ï¥¤¥é¥¤¥È¤Ç¤¤Þ¤»¤ó" -#: ../normal.c:2807 msgid "E348: No string under cursor" msgstr "E348: ¥«¡¼¥½¥ë¤Î°ÌÃ֤ˤÏʸ»úÎ󤬤¢¤ê¤Þ¤»¤ó" -#: ../normal.c:3937 msgid "E352: Cannot erase folds with current 'foldmethod'" msgstr "E352: ¸½ºß¤Î 'foldmethod' ¤Ç¤ÏÀÞ¾ö¤ß¤ò¾Ãµî¤Ç¤¤Þ¤»¤ó" -#: ../normal.c:5897 msgid "E664: changelist is empty" msgstr "E664: Êѹ¹¥ê¥¹¥È¤¬¶õ¤Ç¤¹" -#: ../normal.c:5899 msgid "E662: At start of changelist" msgstr "E662: Êѹ¹¥ê¥¹¥È¤ÎÀèÆ¬" -#: ../normal.c:5901 msgid "E663: At end of changelist" msgstr "E663: Êѹ¹¥ê¥¹¥È¤ÎËöÈø" -#: ../normal.c:7053 -msgid "Type :quit<Enter> to exit Nvim" +msgid "Type :quit<Enter> to exit Vim" msgstr "Vim¤ò½ªÎ»¤¹¤ë¤Ë¤Ï :quit<Enter> ¤ÈÆþÎϤ·¤Æ¤¯¤À¤µ¤¤" -#: ../ops.c:248 #, c-format msgid "1 line %sed 1 time" msgstr "1 ¹Ô¤¬ %s ¤Ç 1 ²ó½èÍý¤µ¤ì¤Þ¤·¤¿" -#: ../ops.c:250 #, c-format msgid "1 line %sed %d times" msgstr "1 ¹Ô¤¬ %s ¤Ç %d ²ó½èÍý¤µ¤ì¤Þ¤·¤¿" -#: ../ops.c:253 #, c-format -msgid "%<PRId64> lines %sed 1 time" -msgstr "%<PRId64> ¹Ô¤¬ %s ¤Ç 1 ²ó½èÍý¤µ¤ì¤Þ¤·¤¿" +msgid "%ld lines %sed 1 time" +msgstr "%ld ¹Ô¤¬ %s ¤Ç 1 ²ó½èÍý¤µ¤ì¤Þ¤·¤¿" -#: ../ops.c:256 #, c-format -msgid "%<PRId64> lines %sed %d times" -msgstr "%<PRId64> ¹Ô¤¬ %s ¤Ç %d ²ó½èÍý¤µ¤ì¤Þ¤·¤¿" +msgid "%ld lines %sed %d times" +msgstr "%ld ¹Ô¤¬ %s ¤Ç %d ²ó½èÍý¤µ¤ì¤Þ¤·¤¿" -#: ../ops.c:592 #, c-format -msgid "%<PRId64> lines to indent... " -msgstr "%<PRId64> ¹Ô¤¬¥¤¥ó¥Ç¥ó¥È¤µ¤ì¤Þ¤¹... " +msgid "%ld lines to indent... " +msgstr "%ld ¹Ô¤¬¥¤¥ó¥Ç¥ó¥È¤µ¤ì¤Þ¤¹... " -#: ../ops.c:634 msgid "1 line indented " msgstr "1 ¹Ô¤ò¥¤¥ó¥Ç¥ó¥È¤·¤Þ¤·¤¿ " -#: ../ops.c:636 #, c-format -msgid "%<PRId64> lines indented " -msgstr "%<PRId64> ¹Ô¤ò¥¤¥ó¥Ç¥ó¥È¤·¤Þ¤·¤¿ " +msgid "%ld lines indented " +msgstr "%ld ¹Ô¤ò¥¤¥ó¥Ç¥ó¥È¤·¤Þ¤·¤¿ " -#: ../ops.c:938 msgid "E748: No previously used register" msgstr "E748: ¤Þ¤À¥ì¥¸¥¹¥¿¤ò»ÈÍѤ·¤Æ¤¤¤Þ¤»¤ó" #. must display the prompt -#: ../ops.c:1433 msgid "cannot yank; delete anyway" msgstr "¥ä¥ó¥¯¤Ç¤¤Þ¤»¤ó; ¤È¤Ë¤«¤¯¾Ãµî" -#: ../ops.c:1929 msgid "1 line changed" msgstr "1 ¹Ô¤¬Êѹ¹¤µ¤ì¤Þ¤·¤¿" -#: ../ops.c:1931 #, c-format -msgid "%<PRId64> lines changed" -msgstr "%<PRId64> ¹Ô¤¬Êѹ¹¤µ¤ì¤Þ¤·¤¿" +msgid "%ld lines changed" +msgstr "%ld ¹Ô¤¬Êѹ¹¤µ¤ì¤Þ¤·¤¿" + +#, c-format +msgid "freeing %ld lines" +msgstr "%ld ¹Ô¤ò²òÊüÃæ" -#: ../ops.c:2521 msgid "block of 1 line yanked" msgstr "1 ¹Ô¤Î¥Ö¥í¥Ã¥¯¤¬¥ä¥ó¥¯¤µ¤ì¤Þ¤·¤¿" -#: ../ops.c:2523 msgid "1 line yanked" msgstr "1 ¹Ô¤¬¥ä¥ó¥¯¤µ¤ì¤Þ¤·¤¿" -#: ../ops.c:2525 #, c-format -msgid "block of %<PRId64> lines yanked" -msgstr "%<PRId64> ¹Ô¤Î¥Ö¥í¥Ã¥¯¤¬¥ä¥ó¥¯¤µ¤ì¤Þ¤·¤¿" +msgid "block of %ld lines yanked" +msgstr "%ld ¹Ô¤Î¥Ö¥í¥Ã¥¯¤¬¥ä¥ó¥¯¤µ¤ì¤Þ¤·¤¿" -#: ../ops.c:2528 #, c-format -msgid "%<PRId64> lines yanked" -msgstr "%<PRId64> ¹Ô¤¬¥ä¥ó¥¯¤µ¤ì¤Þ¤·¤¿" +msgid "%ld lines yanked" +msgstr "%ld ¹Ô¤¬¥ä¥ó¥¯¤µ¤ì¤Þ¤·¤¿" -#: ../ops.c:2710 #, c-format msgid "E353: Nothing in register %s" msgstr "E353: ¥ì¥¸¥¹¥¿ %s ¤Ë¤Ï²¿¤â¤¢¤ê¤Þ¤»¤ó" #. Highlight title -#: ../ops.c:3185 msgid "" "\n" "--- Registers ---" @@ -4486,11 +4137,9 @@ msgstr "" "\n" "--- ¥ì¥¸¥¹¥¿ ---" -#: ../ops.c:4455 msgid "Illegal register name" msgstr "ÉÔÀµ¤Ê¥ì¥¸¥¹¥¿Ì¾" -#: ../ops.c:4533 msgid "" "\n" "# Registers:\n" @@ -4498,7 +4147,6 @@ msgstr "" "\n" "# ¥ì¥¸¥¹¥¿:\n" -#: ../ops.c:4575 #, c-format msgid "E574: Unknown register type %d" msgstr "E574: ̤ÃΤΥ쥸¥¹¥¿·¿ %d ¤Ç¤¹" @@ -4508,86 +4156,61 @@ msgid "" "lines" msgstr "E883: ¸¡º÷¥Ñ¥¿¡¼¥ó¤È¼°¥ì¥¸¥¹¥¿¤Ë¤Ï2¹Ô°Ê¾å¤ò´Þ¤á¤é¤ì¤Þ¤»¤ó" -#: ../ops.c:5089 #, c-format -msgid "%<PRId64> Cols; " -msgstr "%<PRId64> Îó; " +msgid "%ld Cols; " +msgstr "%ld Îó; " -#: ../ops.c:5097 #, c-format -msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Bytes" -msgstr "" -"ÁªÂò %s%<PRId64> / %<PRId64> ¹Ô; %<PRId64> / %<PRId64> ñ¸ì; %<PRId64> / " -"%<PRId64> ¥Ð¥¤¥È" +msgid "Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Bytes" +msgstr "ÁªÂò %s%ld / %ld ¹Ô; %lld / %lld ñ¸ì; %lld / %lld ¥Ð¥¤¥È" -#: ../ops.c:5105 #, c-format msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Chars; %<PRId64> of %<PRId64> Bytes" +"Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Chars; %lld of " +"%lld Bytes" msgstr "" -"ÁªÂò %s%<PRId64> / %<PRId64> ¹Ô; %<PRId64> / %<PRId64> ñ¸ì; %<PRId64> / " -"%<PRId64> ʸ»ú; %<PRId64> / %<PRId64> ¥Ð¥¤¥È" +"ÁªÂò %s%ld / %ld ¹Ô; %lld / %lld ñ¸ì; %lld / %lld ʸ»ú; %lld / %lld ¥Ð¥¤¥È" -#: ../ops.c:5123 #, c-format -msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Byte " -"%<PRId64> of %<PRId64>" -msgstr "" -"Îó %s / %s; ¹Ô %<PRId64> of %<PRId64>; ñ¸ì %<PRId64> / %<PRId64>; ¥Ð¥¤¥È " -"%<PRId64> / %<PRId64>" +msgid "Col %s of %s; Line %ld of %ld; Word %lld of %lld; Byte %lld of %lld" +msgstr "Îó %s / %s; ¹Ô %ld of %ld; ñ¸ì %lld / %lld; ¥Ð¥¤¥È %lld / %lld" -#: ../ops.c:5133 #, c-format msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Char " -"%<PRId64> of %<PRId64>; Byte %<PRId64> of %<PRId64>" +"Col %s of %s; Line %ld of %ld; Word %lld of %lld; Char %lld of %lld; Byte " +"%lld of %lld" msgstr "" -"Îó %s / %s; ¹Ô %<PRId64> / %<PRId64>; ñ¸ì %<PRId64> / %<PRId64>; ʸ»ú " -"%<PRId64> / %<PRId64>; ¥Ð¥¤¥È %<PRId64> of %<PRId64>" +"Îó %s / %s; ¹Ô %ld / %ld; ñ¸ì %lld / %lld; ʸ»ú %lld / %lld; ¥Ð¥¤¥È %lld of " +"%lld" -#: ../ops.c:5146 #, c-format -msgid "(+%<PRId64> for BOM)" -msgstr "(+%<PRId64> for BOM)" +msgid "(+%ld for BOM)" +msgstr "(+%ld for BOM)" -#: ../option.c:1238 msgid "%<%f%h%m%=Page %N" msgstr "%<%f%h%m%=%N ¥Ú¡¼¥¸" -#: ../option.c:1574 msgid "Thanks for flying Vim" msgstr "Vim ¤ò»È¤Ã¤Æ¤¯¤ì¤Æ¤¢¤ê¤¬¤È¤¦" -#. found a mismatch: skip -#: ../option.c:2698 msgid "E518: Unknown option" msgstr "E518: ̤ÃΤΥª¥×¥·¥ç¥ó¤Ç¤¹" -#: ../option.c:2709 msgid "E519: Option not supported" msgstr "E519: ¥ª¥×¥·¥ç¥ó¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#: ../option.c:2740 msgid "E520: Not allowed in a modeline" msgstr "E520: modeline ¤Ç¤Ïµö²Ä¤µ¤ì¤Þ¤»¤ó" -#: ../option.c:2815 msgid "E846: Key code not set" msgstr "E846: ¥¡¼¥³¡¼¥É¤¬ÀßÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó" -#: ../option.c:2924 msgid "E521: Number required after =" msgstr "E521: = ¤Î¸å¤Ë¤Ï¿ô»ú¤¬É¬ÍפǤ¹" -#: ../option.c:3226 ../option.c:3864 msgid "E522: Not found in termcap" msgstr "E522: termcap Æâ¤Ë¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../option.c:3335 #, c-format msgid "E539: Illegal character <%s>" msgstr "E539: ÉÔÀµ¤Êʸ»ú¤Ç¤¹ <%s>" @@ -4596,93 +4219,99 @@ msgstr "E539: ÉÔÀµ¤Êʸ»ú¤Ç¤¹ <%s>" msgid "For option %s" msgstr "¥ª¥×¥·¥ç¥ó: %s" -#: ../option.c:3862 msgid "E529: Cannot set 'term' to empty string" msgstr "E529: 'term' ¤Ë¤Ï¶õʸ»úÎó¤òÀßÄê¤Ç¤¤Þ¤»¤ó" -#: ../option.c:3885 +msgid "E530: Cannot change term in GUI" +msgstr "E530: GUI¤Ç¤Ï 'term' ¤òÊѹ¹¤Ç¤¤Þ¤»¤ó" + +msgid "E531: Use \":gui\" to start the GUI" +msgstr "E531: GUI¤ò¥¹¥¿¡¼¥È¤¹¤ë¤Ë¤Ï \":gui\" ¤ò»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤" + msgid "E589: 'backupext' and 'patchmode' are equal" msgstr "E589: 'backupext' ¤È 'patchmode' ¤¬Æ±¤¸¤Ç¤¹" -#: ../option.c:3964 msgid "E834: Conflicts with value of 'listchars'" msgstr "E834: 'listchars'¤ÎÃͤËÌ·½â¤¬¤¢¤ê¤Þ¤¹" -#: ../option.c:3966 msgid "E835: Conflicts with value of 'fillchars'" msgstr "E835: 'fillchars'¤ÎÃͤËÌ·½â¤¬¤¢¤ê¤Þ¤¹" -#: ../option.c:4163 +msgid "E617: Cannot be changed in the GTK+ 2 GUI" +msgstr "E617: GTK+2 GUI¤Ç¤ÏÊѹ¹¤Ç¤¤Þ¤»¤ó" + msgid "E524: Missing colon" msgstr "E524: ¥³¥í¥ó¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../option.c:4165 msgid "E525: Zero length string" msgstr "E525: ʸ»úÎó¤ÎŤµ¤¬¥¼¥í¤Ç¤¹" -#: ../option.c:4220 #, c-format msgid "E526: Missing number after <%s>" msgstr "E526: <%s> ¤Î¸å¤Ë¿ô»ú¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../option.c:4232 msgid "E527: Missing comma" msgstr "E527: ¥«¥ó¥Þ¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../option.c:4239 msgid "E528: Must specify a ' value" msgstr "E528: ' ¤ÎÃͤò»ØÄꤷ¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" -#: ../option.c:4271 msgid "E595: contains unprintable or wide character" msgstr "E595: ɽ¼¨¤Ç¤¤Ê¤¤Ê¸»ú¤«¥ï¥¤¥Éʸ»ú¤ò´Þ¤ó¤Ç¤¤¤Þ¤¹" -#: ../option.c:4469 +msgid "E596: Invalid font(s)" +msgstr "E596: ̵¸ú¤Ê¥Õ¥©¥ó¥È¤Ç¤¹" + +msgid "E597: can't select fontset" +msgstr "E597: ¥Õ¥©¥ó¥È¥»¥Ã¥È¤òÁªÂò¤Ç¤¤Þ¤»¤ó" + +msgid "E598: Invalid fontset" +msgstr "E598: ̵¸ú¤Ê¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ç¤¹" + +msgid "E533: can't select wide font" +msgstr "E533: ¥ï¥¤¥É¥Õ¥©¥ó¥È¤òÁªÂò¤Ç¤¤Þ¤»¤ó" + +msgid "E534: Invalid wide font" +msgstr "E534: ̵¸ú¤Ê¥ï¥¤¥É¥Õ¥©¥ó¥È¤Ç¤¹" + #, c-format msgid "E535: Illegal character after <%c>" msgstr "E535: <%c> ¤Î¸å¤ËÉÔÀµ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤¹" -#: ../option.c:4534 msgid "E536: comma required" msgstr "E536: ¥«¥ó¥Þ¤¬É¬ÍפǤ¹" -#: ../option.c:4543 #, c-format msgid "E537: 'commentstring' must be empty or contain %s" msgstr "E537: 'commentstring' ¤Ï¶õ¤Ç¤¢¤ë¤« %s ¤ò´Þ¤àɬÍפ¬¤¢¤ê¤Þ¤¹" -#: ../option.c:4928 +msgid "E538: No mouse support" +msgstr "E538: ¥Þ¥¦¥¹¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó" + msgid "E540: Unclosed expression sequence" msgstr "E540: ¼°¤¬½ªÎ»¤·¤Æ¤¤¤Þ¤»¤ó" -#: ../option.c:4932 msgid "E541: too many items" msgstr "E541: Í×ÁǤ¬Â¿²á¤®¤Þ¤¹" -#: ../option.c:4934 msgid "E542: unbalanced groups" msgstr "E542: ¥°¥ë¡¼¥×¤¬Äà¹ç¤¤¤Þ¤»¤ó" -#: ../option.c:5148 msgid "E590: A preview window already exists" msgstr "E590: ¥×¥ì¥Ó¥å¡¼¥¦¥£¥ó¥É¥¦¤¬´û¤Ë¸ºß¤·¤Þ¤¹" -#: ../option.c:5311 msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'" msgstr "" "W17: ¥¢¥é¥Ó¥¢Ê¸»ú¤Ë¤ÏUTF-8¤¬É¬ÍפʤΤÇ, ':set encoding=utf-8' ¤·¤Æ¤¯¤À¤µ¤¤" -#: ../option.c:5623 #, c-format msgid "E593: Need at least %d lines" msgstr "E593: ºÇÄã %d ¤Î¹Ô¿ô¤¬É¬ÍפǤ¹" -#: ../option.c:5631 #, c-format msgid "E594: Need at least %d columns" msgstr "E594: ºÇÄã %d ¤Î¥«¥é¥àÉý¤¬É¬ÍפǤ¹" -#: ../option.c:6011 #, c-format msgid "E355: Unknown option: %s" msgstr "E355: ̤ÃΤΥª¥×¥·¥ç¥ó¤Ç¤¹: %s" @@ -4690,12 +4319,10 @@ msgstr "E355: ̤ÃΤΥª¥×¥·¥ç¥ó¤Ç¤¹: %s" #. 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. -#: ../option.c:6037 #, c-format msgid "E521: Number required: &%s = '%s'" msgstr "E521: ¿ô»ú¤¬É¬ÍפǤ¹: &%s = '%s'" -#: ../option.c:6149 msgid "" "\n" "--- Terminal codes ---" @@ -4703,7 +4330,6 @@ msgstr "" "\n" "--- üËö¥³¡¼¥É ---" -#: ../option.c:6151 msgid "" "\n" "--- Global option values ---" @@ -4711,7 +4337,6 @@ msgstr "" "\n" "--- ¥°¥í¡¼¥Ð¥ë¥ª¥×¥·¥ç¥óÃÍ ---" -#: ../option.c:6153 msgid "" "\n" "--- Local option values ---" @@ -4719,7 +4344,6 @@ msgstr "" "\n" "--- ¥í¡¼¥«¥ë¥ª¥×¥·¥ç¥óÃÍ ---" -#: ../option.c:6155 msgid "" "\n" "--- Options ---" @@ -4727,37 +4351,119 @@ msgstr "" "\n" "--- ¥ª¥×¥·¥ç¥ó ---" -#: ../option.c:6816 msgid "E356: get_varp ERROR" msgstr "E356: get_varp ¥¨¥é¡¼" -#: ../option.c:7696 #, c-format msgid "E357: 'langmap': Matching character missing for %s" msgstr "E357: 'langmap': %s ¤ËÂбþ¤¹¤ëʸ»ú¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../option.c:7715 #, c-format msgid "E358: 'langmap': Extra characters after semicolon: %s" msgstr "E358: 'langmap': ¥»¥ß¥³¥í¥ó¤Î¸å¤Ë;ʬ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤¹: %s" -#: ../os/shell.c:194 -msgid "" -"\n" -"Cannot execute shell " -msgstr "" -"\n" -"¥·¥§¥ë¤ò¼Â¹Ô¤Ç¤¤Þ¤»¤ó " +msgid "cannot open " +msgstr "³«¤±¤Þ¤»¤ó " + +msgid "VIM: Can't open window!\n" +msgstr "VIM: ¥¦¥£¥ó¥É¥¦¤ò³«¤±¤Þ¤»¤ó!\n" + +msgid "Need Amigados version 2.04 or later\n" +msgstr "Amigados¤Î¥Ð¡¼¥¸¥ç¥ó 2.04¤«¤½¤ì°Ê¹ß¤¬É¬ÍפǤ¹\n" + +#, c-format +msgid "Need %s version %ld\n" +msgstr "%s ¤Î¥Ð¡¼¥¸¥ç¥ó %ld ¤¬É¬ÍפǤ¹\n" + +msgid "Cannot open NIL:\n" +msgstr "NIL¤ò³«¤±¤Þ¤»¤ó:\n" + +msgid "Cannot create " +msgstr "ºîÀ®¤Ç¤¤Þ¤»¤ó " + +#, c-format +msgid "Vim exiting with %d\n" +msgstr "Vim¤Ï %d ¤Ç½ªÎ»¤·¤Þ¤¹\n" + +msgid "cannot change console mode ?!\n" +msgstr "¥³¥ó¥½¡¼¥ë¥â¡¼¥É¤òÊѹ¹¤Ç¤¤Þ¤»¤ó?!\n" + +msgid "mch_get_shellsize: not a console??\n" +msgstr "mch_get_shellsize: ¥³¥ó¥½¡¼¥ë¤Ç¤Ï¤Ê¤¤??\n" + +#. if Vim opened a window: Executing a shell may cause crashes +msgid "E360: Cannot execute shell with -f option" +msgstr "E360: -f ¥ª¥×¥·¥ç¥ó¤Ç¥·¥§¥ë¤ò¼Â¹Ô¤Ç¤¤Þ¤»¤ó" + +msgid "Cannot execute " +msgstr "¼Â¹Ô¤Ç¤¤Þ¤»¤ó " + +msgid "shell " +msgstr "¥·¥§¥ë " + +msgid " returned\n" +msgstr " Ìá¤ê¤Þ¤·¤¿\n" + +msgid "ANCHOR_BUF_SIZE too small." +msgstr "ANCHOR_BUF_SIZE ¤¬¾®¤µ²á¤®¤Þ¤¹." + +msgid "I/O ERROR" +msgstr "Æþ½ÐÎÏ¥¨¥é¡¼" + +msgid "Message" +msgstr "¥á¥Ã¥»¡¼¥¸" + +msgid "'columns' is not 80, cannot execute external commands" +msgstr "'columns' ¤¬ 80 ¤Ç¤Ï¤Ê¤¤¤¿¤á¡¢³°Éô¥³¥Þ¥ó¥É¤ò¼Â¹Ô¤Ç¤¤Þ¤»¤ó" + +msgid "E237: Printer selection failed" +msgstr "E237: ¥×¥ê¥ó¥¿¤ÎÁªÂò¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" + +#, c-format +msgid "to %s on %s" +msgstr "%s ¤Ø (%s ¾å¤Î)" + +#, c-format +msgid "E613: Unknown printer font: %s" +msgstr "E613: ̤ÃΤΥץê¥ó¥¿¥ª¥×¥·¥ç¥ó¤Ç¤¹: %s" + +#, c-format +msgid "E238: Print error: %s" +msgstr "E238: °õºþ¥¨¥é¡¼: %s" + +#, c-format +msgid "Printing '%s'" +msgstr "°õºþ¤·¤Æ¤¤¤Þ¤¹: '%s'" + +#, c-format +msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" +msgstr "E244: ʸ»ú¥»¥Ã¥È̾ \"%s\" ¤ÏÉÔÀµ¤Ç¤¹ (¥Õ¥©¥ó¥È̾ \"%s\")" + +#, c-format +msgid "E244: Illegal quality name \"%s\" in font name \"%s\"" +msgstr "E244: ÉʼÁ̾ \"%s\" ¤ÏÉÔÀµ¤Ç¤¹ (¥Õ¥©¥ó¥È̾ \"%s\")" + +#, c-format +msgid "E245: Illegal char '%c' in font name \"%s\"" +msgstr "E245: '%c' ¤ÏÉÔÀµ¤Êʸ»ú¤Ç¤¹ (¥Õ¥©¥ó¥È̾ \"%s\")" + +#, c-format +msgid "Opening the X display took %ld msec" +msgstr "X¥µ¡¼¥Ð¡¼¤Ø¤ÎÀܳ¤Ë %ld ¥ß¥êÉ䫤«¤ê¤Þ¤·¤¿" -#: ../os/shell.c:439 msgid "" "\n" -"shell returned " +"Vim: Got X error\n" msgstr "" "\n" -"¥·¥§¥ë¤¬ÃͤòÊÖ¤·¤Þ¤·¤¿ " +"Vim: X ¤Î¥¨¥é¡¼¤ò¸¡½Ð¤·¤Þ¤·¤¿r\n" + +msgid "Testing the X display failed" +msgstr "X display ¤Î¥Á¥§¥Ã¥¯¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" + +msgid "Opening the X display timed out" +msgstr "X display ¤Î open ¤¬¥¿¥¤¥à¥¢¥¦¥È¤·¤Þ¤·¤¿" -#: ../os_unix.c:465 ../os_unix.c:471 msgid "" "\n" "Could not get security context for " @@ -4765,7 +4471,6 @@ msgstr "" "\n" "¥»¥¥å¥ê¥Æ¥£¥³¥ó¥Æ¥¥¹¥È¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó " -#: ../os_unix.c:479 msgid "" "\n" "Could not set security context for " @@ -4781,223 +4486,293 @@ msgstr "¥»¥¥å¥ê¥Æ¥£¥³¥ó¥Æ¥¥¹¥È %s ¤ò %s ¤ËÀßÄê¤Ç¤¤Þ¤»¤ó" msgid "Could not get security context %s for %s. Removing it!" msgstr "¥»¥¥å¥ê¥Æ¥£¥³¥ó¥Æ¥¥¹¥È %s ¤ò %s ¤«¤é¼èÆÀ¤Ç¤¤Þ¤»¤ó. ºï½ü¤·¤Þ¤¹!" -#: ../os_unix.c:1558 ../os_unix.c:1647 +msgid "" +"\n" +"Cannot execute shell sh\n" +msgstr "" +"\n" +"sh ¥·¥§¥ë¤ò¼Â¹Ô¤Ç¤¤Þ¤»¤ó\n" + +msgid "" +"\n" +"shell returned " +msgstr "" +"\n" +"¥·¥§¥ë¤¬ÃͤòÊÖ¤·¤Þ¤·¤¿ " + +msgid "" +"\n" +"Cannot create pipes\n" +msgstr "" +"\n" +"¥Ñ¥¤¥×¤òºîÀ®¤Ç¤¤Þ¤»¤ó\n" + +msgid "" +"\n" +"Cannot fork\n" +msgstr "" +"\n" +"fork ¤Ç¤¤Þ¤»¤ó\n" + +msgid "" +"\n" +"Cannot execute shell " +msgstr "" +"\n" +"¥·¥§¥ë¤ò¼Â¹Ô¤Ç¤¤Þ¤»¤ó " + +msgid "" +"\n" +"Command terminated\n" +msgstr "" +"\n" +"¥³¥Þ¥ó¥É¤òÃæÃǤ·¤Þ¤·¤¿\n" + +msgid "XSMP lost ICE connection" +msgstr "XSMP ¤¬ICEÀܳ¤ò¼º¤¤¤Þ¤·¤¿" + #, c-format msgid "dlerror = \"%s\"" msgstr "dlerror = \"%s\"" -#: ../path.c:1449 +msgid "Opening the X display failed" +msgstr "X display ¤Î open ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" + +msgid "XSMP handling save-yourself request" +msgstr "XSMP ¤¬save-yourselfÍ×µá¤ò½èÍý¤·¤Æ¤¤¤Þ¤¹" + +msgid "XSMP opening connection" +msgstr "XSMP ¤¬Àܳ¤ò³«»Ï¤·¤Æ¤¤¤Þ¤¹" + +msgid "XSMP ICE connection watch failed" +msgstr "XSMP ICEÀܳ¤¬¼ºÇÔ¤·¤¿¤è¤¦¤Ç¤¹" + #, c-format -msgid "E447: Can't find file \"%s\" in path" -msgstr "E447: path¤Ë¤Ï \"%s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó" +msgid "XSMP SmcOpenConnection failed: %s" +msgstr "XSMP SmcOpenConnection¤¬¼ºÇÔ¤·¤Þ¤·¤¿: %s" + +msgid "At line" +msgstr "¹Ô" + +msgid "Could not load vim32.dll!" +msgstr "vim32.dll ¤ò¥í¡¼¥É¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" + +msgid "VIM Error" +msgstr "VIM¥¨¥é¡¼" + +msgid "Could not fix up function pointers to the DLL!" +msgstr "DLL¤«¤é´Ø¿ô¥Ý¥¤¥ó¥¿¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" + +#, c-format +msgid "Vim: Caught %s event\n" +msgstr "Vim: ¥¤¥Ù¥ó¥È %s ¤ò¸¡ÃÎ\n" + +msgid "close" +msgstr "ÊĤ¸¤ë" + +msgid "logoff" +msgstr "¥í¥°¥ª¥Õ" + +msgid "shutdown" +msgstr "¥·¥ã¥Ã¥È¥À¥¦¥ó" + +msgid "E371: Command not found" +msgstr "E371: ¥³¥Þ¥ó¥É¤¬¤¢¤ê¤Þ¤»¤ó" + +msgid "" +"VIMRUN.EXE not found in your $PATH.\n" +"External commands will not pause after completion.\n" +"See :help win32-vimrun for more information." +msgstr "" +"VIMRUN.EXE¤¬ $PATH ¤ÎÃæ¤Ë¸«¤Ä¤«¤ê¤Þ¤»¤ó.\n" +"³°Éô¥³¥Þ¥ó¥É¤Î½ªÎ»¸å¤Ë°ì»þÄä»ß¤ò¤·¤Þ¤»¤ó.\n" +"¾ÜºÙ¤Ï :help win32-vimrun ¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤." + +msgid "Vim Warning" +msgstr "Vim¤Î·Ù¹ð" + +#, c-format +msgid "shell returned %d" +msgstr "¥·¥§¥ë¤¬¥³¡¼¥É %d ¤Ç½ªÎ»¤·¤Þ¤·¤¿" -#: ../quickfix.c:359 #, c-format msgid "E372: Too many %%%c in format string" msgstr "E372: ¥Õ¥©¡¼¥Þ¥Ã¥Èʸ»úÎó¤Ë %%%c ¤¬Â¿²á¤®¤Þ¤¹" -#: ../quickfix.c:371 #, c-format msgid "E373: Unexpected %%%c in format string" msgstr "E373: ¥Õ¥©¡¼¥Þ¥Ã¥Èʸ»úÎó¤Ëͽ´ü¤»¤Ì %%%c ¤¬¤¢¤ê¤Þ¤·¤¿" -#: ../quickfix.c:420 msgid "E374: Missing ] in format string" msgstr "E374: ¥Õ¥©¡¼¥Þ¥Ã¥Èʸ»úÎó¤Ë ] ¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../quickfix.c:431 #, c-format msgid "E375: Unsupported %%%c in format string" msgstr "E375: ¥Õ¥©¡¼¥Þ¥Ã¥Èʸ»úÎó¤Ç¤Ï %%%c ¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó" -#: ../quickfix.c:448 #, c-format msgid "E376: Invalid %%%c in format string prefix" msgstr "E376: ¥Õ¥©¡¼¥Þ¥Ã¥Èʸ»úÎó¤ÎÁ°ÃÖ¤Ë̵¸ú¤Ê %%%c ¤¬¤¢¤ê¤Þ¤¹" -#: ../quickfix.c:454 #, c-format msgid "E377: Invalid %%%c in format string" msgstr "E377: ¥Õ¥©¡¼¥Þ¥Ã¥Èʸ»úÎó¤Ë̵¸ú¤Ê %%%c ¤¬¤¢¤ê¤Þ¤¹" #. nothing found -#: ../quickfix.c:477 msgid "E378: 'errorformat' contains no pattern" msgstr "E378: 'errorformat' ¤Ë¥Ñ¥¿¡¼¥ó¤¬»ØÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó" -#: ../quickfix.c:695 msgid "E379: Missing or empty directory name" msgstr "E379: ¥Ç¥£¥ì¥¯¥È¥ê̾¤¬Ìµ¤¤¤«¶õ¤Ç¤¹" -#: ../quickfix.c:1305 msgid "E553: No more items" msgstr "E553: Í×ÁǤ¬¤â¤¦¤¢¤ê¤Þ¤»¤ó" -#: ../quickfix.c:1674 +msgid "E924: Current window was closed" +msgstr "E924: ¸½ºß¤Î¥¦¥£¥ó¥É¥¦¤¬ÊĤ¸¤é¤ì¤Þ¤·¤¿" + +msgid "E925: Current quickfix was changed" +msgstr "E925: ¸½ºß¤Î quickfix ¤¬Êѹ¹¤µ¤ì¤Þ¤·¤¿" + +msgid "E926: Current location list was changed" +msgstr "E926: ¸½ºß¤Î¥í¥±¡¼¥·¥ç¥ó¥ê¥¹¥È¤¬Êѹ¹¤µ¤ì¤Þ¤·¤¿" + #, c-format msgid "(%d of %d)%s%s: " msgstr "(%d of %d)%s%s: " -#: ../quickfix.c:1676 msgid " (line deleted)" msgstr " (¹Ô¤¬ºï½ü¤µ¤ì¤Þ¤·¤¿)" -#: ../quickfix.c:1863 +#, c-format +msgid "%serror list %d of %d; %d errors " +msgstr "%s ¥¨¥é¡¼°ìÍ÷ %d of %d; %d ¸Ä¥¨¥é¡¼" + msgid "E380: At bottom of quickfix stack" msgstr "E380: quickfix ¥¹¥¿¥Ã¥¯¤ÎËöÈø¤Ç¤¹" -#: ../quickfix.c:1869 msgid "E381: At top of quickfix stack" msgstr "E381: quickfix ¥¹¥¿¥Ã¥¯¤ÎÀèÆ¬¤Ç¤¹" -#: ../quickfix.c:1880 -#, c-format -msgid "error list %d of %d; %d errors" -msgstr "¥¨¥é¡¼°ìÍ÷ %d of %d; %d ¸Ä¥¨¥é¡¼" +msgid "No entries" +msgstr "¥¨¥ó¥È¥ê¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../quickfix.c:2427 msgid "E382: Cannot write, 'buftype' option is set" msgstr "E382: 'buftype' ¥ª¥×¥·¥ç¥ó¤¬ÀßÄꤵ¤ì¤Æ¤¤¤ë¤Î¤Ç½ñ¹þ¤ß¤Þ¤»¤ó" -#: ../quickfix.c:2812 +msgid "Error file" +msgstr "¥¨¥é¡¼¥Õ¥¡¥¤¥ë" + msgid "E683: File name missing or invalid pattern" msgstr "E683: ¥Õ¥¡¥¤¥ë̾¤¬Ìµ¤¤¤«Ìµ¸ú¤Ê¥Ñ¥¿¡¼¥ó¤Ç¤¹" -#: ../quickfix.c:2911 #, c-format msgid "Cannot open file \"%s\"" msgstr "¥Õ¥¡¥¤¥ë \"%s\" ¤ò³«¤±¤Þ¤»¤ó" -#: ../quickfix.c:3429 msgid "E681: Buffer is not loaded" msgstr "E681: ¥Ð¥Ã¥Õ¥¡¤ÏÆÉ¤ß¹þ¤Þ¤ì¤Þ¤»¤ó¤Ç¤·¤¿" -#: ../quickfix.c:3487 msgid "E777: String or List expected" msgstr "E777: ʸ»úÎ󤫥ꥹ¥È¤¬É¬ÍפǤ¹" -#: ../regexp.c:359 #, c-format msgid "E369: invalid item in %s%%[]" msgstr "E369: ̵¸ú¤Ê¹àÌܤǤ¹: %s%%[]" # -#: ../regexp.c:374 #, c-format msgid "E769: Missing ] after %s[" msgstr "E769: %s[ ¤Î¸å¤Ë ] ¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../regexp.c:375 #, c-format msgid "E53: Unmatched %s%%(" msgstr "E53: %s%%( ¤¬Äà¤ê¹ç¤Ã¤Æ¤¤¤Þ¤»¤ó" -#: ../regexp.c:376 #, c-format msgid "E54: Unmatched %s(" msgstr "E54: %s( ¤¬Äà¤ê¹ç¤Ã¤Æ¤¤¤Þ¤»¤ó" -#: ../regexp.c:377 #, c-format msgid "E55: Unmatched %s)" msgstr "E55: %s) ¤¬Äà¤ê¹ç¤Ã¤Æ¤¤¤Þ¤»¤ó" # -#: ../regexp.c:378 msgid "E66: \\z( not allowed here" msgstr "E66: \\z( ¤Ï¥³¥³¤Ç¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" # -#: ../regexp.c:379 msgid "E67: \\z1 et al. not allowed here" msgstr "E67: \\z1 ¤½¤Î¾¤Ï¥³¥³¤Ç¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" # -#: ../regexp.c:380 #, c-format msgid "E69: Missing ] after %s%%[" msgstr "E69: %s%%[ ¤Î¸å¤Ë ] ¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../regexp.c:381 #, c-format msgid "E70: Empty %s%%[]" msgstr "E70: %s%%[] ¤¬¶õ¤Ç¤¹" -#: ../regexp.c:1209 ../regexp.c:1224 msgid "E339: Pattern too long" msgstr "E339: ¥Ñ¥¿¡¼¥ó¤¬Ä¹²á¤®¤Þ¤¹" -#: ../regexp.c:1371 msgid "E50: Too many \\z(" msgstr "E50: \\z( ¤¬Â¿²á¤®¤Þ¤¹" -#: ../regexp.c:1378 #, c-format msgid "E51: Too many %s(" msgstr "E51: %s( ¤¬Â¿²á¤®¤Þ¤¹" -#: ../regexp.c:1427 msgid "E52: Unmatched \\z(" msgstr "E52: \\z( ¤¬Äà¤ê¹ç¤Ã¤Æ¤¤¤Þ¤»¤ó" -#: ../regexp.c:1637 #, c-format msgid "E59: invalid character after %s@" msgstr "E59: %s@ ¤Î¸å¤ËÉÔÀµ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤·¤¿" -#: ../regexp.c:1672 #, c-format msgid "E60: Too many complex %s{...}s" msgstr "E60: Ê£»¨¤Ê %s{...} ¤¬Â¿²á¤®¤Þ¤¹" -#: ../regexp.c:1687 #, c-format msgid "E61: Nested %s*" msgstr "E61:%s* ¤¬Æþ¤ì»Ò¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹" -#: ../regexp.c:1690 #, c-format msgid "E62: Nested %s%c" msgstr "E62:%s%c ¤¬Æþ¤ì»Ò¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹" # -#: ../regexp.c:1800 msgid "E63: invalid use of \\_" msgstr "E63: \\_ ¤Î̵¸ú¤Ê»ÈÍÑÊýË¡¤Ç¤¹" -#: ../regexp.c:1850 #, c-format msgid "E64: %s%c follows nothing" msgstr "E64:%s%c ¤Î¸å¤Ë¤Ê¤Ë¤â¤¢¤ê¤Þ¤»¤ó" # -#: ../regexp.c:1902 msgid "E65: Illegal back reference" msgstr "E65: ÉÔÀµ¤Ê¸åÊý»²¾È¤Ç¤¹" # -#: ../regexp.c:1943 msgid "E68: Invalid character after \\z" msgstr "E68: \\z ¤Î¸å¤ËÉÔÀµ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤·¤¿" # -#: ../regexp.c:2049 ../regexp_nfa.c:1296 #, c-format msgid "E678: Invalid character after %s%%[dxouU]" msgstr "E678: %s%%[dxouU] ¤Î¸å¤ËÉÔÀµ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤·¤¿" # -#: ../regexp.c:2107 #, c-format msgid "E71: Invalid character after %s%%" msgstr "E71: %s%% ¤Î¸å¤ËÉÔÀµ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤·¤¿" -#: ../regexp.c:3017 #, c-format msgid "E554: Syntax error in %s{...}" msgstr "E554: %s{...} Æâ¤Ëʸˡ¥¨¥é¡¼¤¬¤¢¤ê¤Þ¤¹" -#: ../regexp.c:3805 msgid "External submatches:\n" msgstr "³°Éô¤ÎÉôʬ³ºÅö:\n" @@ -5005,7 +4780,6 @@ msgstr "³°Éô¤ÎÉôʬ³ºÅö:\n" msgid "E888: (NFA regexp) cannot repeat %s" msgstr "E888: (NFA Àµµ¬É½¸½) ·«¤êÊÖ¤»¤Þ¤»¤ó %s" -#: ../regexp.c:7022 msgid "" "E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be " "used " @@ -5016,62 +4790,54 @@ msgstr "" msgid "Switching to backtracking RE engine for pattern: " msgstr "¼¡¤Î¥Ñ¥¿¡¼¥ó¤Ë¥Ð¥Ã¥¯¥È¥é¥Ã¥¥ó¥° RE ¥¨¥ó¥¸¥ó¤òŬÍѤ·¤Þ¤¹: " -#: ../regexp_nfa.c:239 msgid "E865: (NFA) Regexp end encountered prematurely" msgstr "E865: (NFA) ´üÂÔ¤è¤êÁ᤯Àµµ¬É½¸½¤Î½ªÃ¼¤ËÅþ㤷¤Þ¤·¤¿" -#: ../regexp_nfa.c:240 #, c-format msgid "E866: (NFA regexp) Misplaced %c" msgstr "E866: (NFA Àµµ¬É½¸½) °ÌÃÖ¤¬¸í¤Ã¤Æ¤¤¤Þ¤¹: %c" -#: ../regexp_nfa.c:242 +# #, c-format -msgid "E877: (NFA regexp) Invalid character class: %<PRId64>" -msgstr "E877: (NFA Àµµ¬É½¸½) ̵¸ú¤Êʸ»ú¥¯¥é¥¹: %<PRId64>" +msgid "E877: (NFA regexp) Invalid character class: %ld" +msgstr "E877: (NFA Àµµ¬É½¸½) ̵¸ú¤Êʸ»ú¥¯¥é¥¹: %ld" -#: ../regexp_nfa.c:1261 #, c-format msgid "E867: (NFA) Unknown operator '\\z%c'" msgstr "E867: (NFA) ̤ÃΤΥª¥Ú¥ì¡¼¥¿¤Ç¤¹: '\\z%c'" -#: ../regexp_nfa.c:1387 #, c-format msgid "E867: (NFA) Unknown operator '\\%%%c'" msgstr "E867: (NFA) ̤ÃΤΥª¥Ú¥ì¡¼¥¿¤Ç¤¹: '\\%%%c'" -#: ../regexp_nfa.c:1802 +#. should never happen +msgid "E868: Error building NFA with equivalence class!" +msgstr "E868: Åù²Á¥¯¥é¥¹¤ò´Þ¤àNFA¹½Ãۤ˼ºÇÔ¤·¤Þ¤·¤¿!" + #, c-format msgid "E869: (NFA) Unknown operator '\\@%c'" msgstr "E869: (NFA) ̤ÃΤΥª¥Ú¥ì¡¼¥¿¤Ç¤¹: '\\@%c'" -#: ../regexp_nfa.c:1831 msgid "E870: (NFA regexp) Error reading repetition limits" msgstr "E870: (NFA Àµµ¬É½¸½) ·«¤êÊÖ¤·¤ÎÀ©¸Â²ó¿ô¤òÆÉ¹þÃæ¤Ë¥¨¥é¡¼" #. Can't have a multi follow a multi. -#: ../regexp_nfa.c:1895 msgid "E871: (NFA regexp) Can't have a multi follow a multi !" msgstr "E871: (NFA Àµµ¬É½¸½) ·«¤êÊÖ¤· ¤Î¸å¤Ë ·«¤êÊÖ¤· ¤Ï¤Ç¤¤Þ¤»¤ó!" #. Too many `(' -#: ../regexp_nfa.c:2037 msgid "E872: (NFA regexp) Too many '('" msgstr "E872: (NFA Àµµ¬É½¸½) '(' ¤¬Â¿²á¤®¤Þ¤¹" -#: ../regexp_nfa.c:2042 msgid "E879: (NFA regexp) Too many \\z(" msgstr "E879: (NFA Àµµ¬É½¸½) \\z( ¤¬Â¿²á¤®¤Þ¤¹" -#: ../regexp_nfa.c:2066 msgid "E873: (NFA regexp) proper termination error" msgstr "E873: (NFA Àµµ¬É½¸½) ½ªÃ¼µ¹æ¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../regexp_nfa.c:2599 msgid "E874: (NFA) Could not pop the stack !" msgstr "E874: (NFA) ¥¹¥¿¥Ã¥¯¤ò¥Ý¥Ã¥×¤Ç¤¤Þ¤»¤ó!" -#: ../regexp_nfa.c:3298 msgid "" "E875: (NFA regexp) (While converting from postfix to NFA), too many states " "left on stack" @@ -5079,177 +4845,136 @@ msgstr "" "E875: (NFA Àµµ¬É½¸½) (¸åÃÖʸ»úÎó¤òNFA¤ËÊÑ´¹Ãæ¤Ë) ¥¹¥¿¥Ã¥¯¤Ë»Ä¤µ¤ì¤¿¥¹¥Æ¡¼¥È¤¬" "¿²á¤®¤Þ¤¹" -#: ../regexp_nfa.c:3302 msgid "E876: (NFA regexp) Not enough space to store the whole NFA " msgstr "E876: (NFA Àµµ¬É½¸½) NFAÁ´ÂΤòÊݸ¤¹¤ë¤Ë¤Ï¶õ¤¥¹¥Ú¡¼¥¹¤¬Â¤ê¤Þ¤»¤ó" -#: ../regexp_nfa.c:4571 ../regexp_nfa.c:4869 +msgid "E878: (NFA) Could not allocate memory for branch traversal!" +msgstr "E878: (NFA) ¸½ºß²£ÃÇÃæ¤Î¥Ö¥é¥ó¥Á¤Ë½½Ê¬¤Ê¥á¥â¥ê¤ò³ä¤êÅö¤Æ¤é¤ì¤Þ¤»¤ó!" + msgid "" "Could not open temporary log file for writing, displaying on stderr ... " msgstr "" "NFAÀµµ¬É½¸½¥¨¥ó¥¸¥óÍÑ¤Î¥í¥°¥Õ¥¡¥¤¥ë¤ò½ñ¹þÍѤȤ·¤Æ³«¤±¤Þ¤»¤ó¡£¥í¥°¤Ïɸ½à½ÐÎϤË" "½ÐÎϤ·¤Þ¤¹¡£" -#: ../regexp_nfa.c:4840 #, c-format msgid "(NFA) COULD NOT OPEN %s !" msgstr "(NFA) ¥í¥°¥Õ¥¡¥¤¥ë %s ¤ò³«¤±¤Þ¤»¤ó!" -#: ../regexp_nfa.c:6049 msgid "Could not open temporary log file for writing " msgstr "NFAÀµµ¬É½¸½¥¨¥ó¥¸¥óÍÑ¤Î¥í¥°¥Õ¥¡¥¤¥ë¤ò½ñ¹þÍѤȤ·¤Æ³«¤±¤Þ¤»¤ó¡£" -#: ../screen.c:7435 msgid " VREPLACE" msgstr " ²¾ÁÛÃÖ´¹" -#: ../screen.c:7437 msgid " REPLACE" msgstr " ÃÖ´¹" -#: ../screen.c:7440 msgid " REVERSE" msgstr " ȿž" -#: ../screen.c:7441 msgid " INSERT" msgstr " ÁÞÆþ" -#: ../screen.c:7443 msgid " (insert)" msgstr " (ÁÞÆþ)" -#: ../screen.c:7445 msgid " (replace)" msgstr " (ÃÖ´¹)" -#: ../screen.c:7447 msgid " (vreplace)" msgstr " (²¾ÁÛÃÖ´¹)" -#: ../screen.c:7449 msgid " Hebrew" msgstr " ¥Ø¥Ö¥é¥¤" -#: ../screen.c:7454 msgid " Arabic" msgstr " ¥¢¥é¥Ó¥¢" -#: ../screen.c:7456 -msgid " (lang)" -msgstr " (¸À¸ì)" - -#: ../screen.c:7459 msgid " (paste)" msgstr " (ޤêÉÕ¤±)" -#: ../screen.c:7469 msgid " VISUAL" msgstr " ¥Ó¥¸¥å¥¢¥ë" -#: ../screen.c:7470 msgid " VISUAL LINE" msgstr " ¥Ó¥¸¥å¥¢¥ë ¹Ô" -#: ../screen.c:7471 msgid " VISUAL BLOCK" msgstr " ¥Ó¥¸¥å¥¢¥ë ¶ë·Á" -#: ../screen.c:7472 msgid " SELECT" msgstr " ¥»¥ì¥¯¥È" -#: ../screen.c:7473 msgid " SELECT LINE" msgstr " ¹Ô»Ø¸þÁªÂò" -#: ../screen.c:7474 msgid " SELECT BLOCK" msgstr " ¶ë·ÁÁªÂò" -#: ../screen.c:7486 ../screen.c:7541 msgid "recording" msgstr "µÏ¿Ãæ" -#: ../search.c:487 #, c-format msgid "E383: Invalid search string: %s" msgstr "E383: ̵¸ú¤Ê¸¡º÷ʸ»úÎó¤Ç¤¹: %s" -#: ../search.c:832 #, c-format msgid "E384: search hit TOP without match for: %s" msgstr "E384: ¾å¤Þ¤Ç¸¡º÷¤·¤Þ¤·¤¿¤¬³ºÅö²Õ½ê¤Ï¤¢¤ê¤Þ¤»¤ó: %s" -#: ../search.c:835 #, c-format msgid "E385: search hit BOTTOM without match for: %s" msgstr "E385: ²¼¤Þ¤Ç¸¡º÷¤·¤Þ¤·¤¿¤¬³ºÅö²Õ½ê¤Ï¤¢¤ê¤Þ¤»¤ó: %s" -#: ../search.c:1200 msgid "E386: Expected '?' or '/' after ';'" msgstr "E386: ';' ¤Î¤¢¤È¤Ë¤Ï '?' ¤« '/' ¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤ë" -#: ../search.c:4085 msgid " (includes previously listed match)" msgstr " (Á°¤ËÎóµó¤·¤¿³ºÅö²Õ½ê¤ò´Þ¤à)" #. cursor at status line -#: ../search.c:4104 msgid "--- Included files " msgstr "--- ¥¤¥ó¥¯¥ë¡¼¥É¤µ¤ì¤¿¥Õ¥¡¥¤¥ë " -#: ../search.c:4106 msgid "not found " msgstr "¸«¤Ä¤«¤ê¤Þ¤»¤ó " -#: ../search.c:4107 msgid "in path ---\n" msgstr "¥Ñ¥¹¤Ë ----\n" -#: ../search.c:4168 msgid " (Already listed)" msgstr " (´û¤ËÎóµó)" -#: ../search.c:4170 msgid " NOT FOUND" msgstr " ¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../search.c:4211 #, c-format msgid "Scanning included file: %s" msgstr "¥¤¥ó¥¯¥ë¡¼¥É¤µ¤ì¤¿¥Õ¥¡¥¤¥ë¤ò¥¹¥¥ã¥óÃæ: %s" -#: ../search.c:4216 #, c-format msgid "Searching included file %s" msgstr "¥¤¥ó¥¯¥ë¡¼¥É¤µ¤ì¤¿¥Õ¥¡¥¤¥ë¤ò¥¹¥¥ã¥óÃæ %s" -#: ../search.c:4405 msgid "E387: Match is on current line" msgstr "E387: ¸½ºß¹Ô¤Ë³ºÅö¤¬¤¢¤ê¤Þ¤¹" -#: ../search.c:4517 msgid "All included files were found" msgstr "Á´¤Æ¤Î¥¤¥ó¥¯¥ë¡¼¥É¤µ¤ì¤¿¥Õ¥¡¥¤¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤·¤¿" -#: ../search.c:4519 msgid "No included files" msgstr "¥¤¥ó¥¯¥ë¡¼¥É¥Õ¥¡¥¤¥ë¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../search.c:4527 msgid "E388: Couldn't find definition" msgstr "E388: ÄêµÁ¤ò¸«¤Ä¤±¤é¤ì¤Þ¤»¤ó" -#: ../search.c:4529 msgid "E389: Couldn't find pattern" msgstr "E389: ¥Ñ¥¿¡¼¥ó¤ò¸«¤Ä¤±¤é¤ì¤Þ¤»¤ó" -#: ../search.c:4668 msgid "Substitute " msgstr "Substitute " -#: ../search.c:4681 #, c-format msgid "" "\n" @@ -5260,99 +4985,131 @@ msgstr "" "# ºÇ¸å¤Î %s¸¡º÷¥Ñ¥¿¡¼¥ó:\n" "~" -#: ../spell.c:951 -msgid "E759: Format error in spell file" -msgstr "E759: ¥¹¥Ú¥ë¥Õ¥¡¥¤¥ë¤Î½ñ¼°¥¨¥é¡¼¤Ç¤¹" +msgid "E756: Spell checking is not enabled" +msgstr "E756: ¥¹¥Ú¥ë¥Á¥§¥Ã¥¯¤Ï̵¸ú²½¤µ¤ì¤Æ¤¤¤Þ¤¹" + +#, c-format +msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" +msgstr "" +"·Ù¹ð: ñ¸ì¥ê¥¹¥È \"%s_%s.spl\" ¤ª¤è¤Ó \"%s_ascii.spl\" ¤Ï¸«¤Ä¤«¤ê¤Þ¤»¤ó" + +#, c-format +msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" +msgstr "" +"·Ù¹ð: ñ¸ì¥ê¥¹¥È \"%s.%s.spl\" ¤ª¤è¤Ó \"%s.ascii.spl\" ¤Ï¸«¤Ä¤«¤ê¤Þ¤»¤ó" + +msgid "E797: SpellFileMissing autocommand deleted buffer" +msgstr "E797: autocommand ¤Î SpellFileMissing ¤¬¥Ð¥Ã¥Õ¥¡¤òºï½ü¤·¤Þ¤·¤¿" + +#, c-format +msgid "Warning: region %s not supported" +msgstr "·Ù¹ð9: %s ¤È¤¤¤¦ÈϰϤϥµ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" + +msgid "Sorry, no suggestions" +msgstr "»Äǰ¤Ç¤¹¤¬, ½¤Àµ¸õÊä¤Ï¤¢¤ê¤Þ¤»¤ó" + +#, c-format +msgid "Sorry, only %ld suggestions" +msgstr "»Äǰ¤Ç¤¹¤¬, ½¤Àµ¸õÊä¤Ï %ld ¸Ä¤·¤«¤¢¤ê¤Þ¤»¤ó" + +#. for when 'cmdheight' > 1 +#. avoid more prompt +#, c-format +msgid "Change \"%.*s\" to:" +msgstr "\"%.*s\" ¤ò¼¡¤ØÊÑ´¹:" + +#, c-format +msgid " < \"%.*s\"" +msgstr " < \"%.*s\"" + +msgid "E752: No previous spell replacement" +msgstr "E752: ¥¹¥Ú¥ëÃÖ´¹¤¬¤Þ¤À¼Â¹Ô¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" + +#, c-format +msgid "E753: Not found: %s" +msgstr "E753: ¸«¤Ä¤«¤ê¤Þ¤»¤ó: %s" -#: ../spell.c:952 msgid "E758: Truncated spell file" msgstr "E758: ¥¹¥Ú¥ë¥Õ¥¡¥¤¥ë¤¬ÀÚ¼è¤é¤ì¤Æ¤¤¤ë¤è¤¦¤Ç¤¹" -#: ../spell.c:953 #, c-format msgid "Trailing text in %s line %d: %s" msgstr "%s (%d ¹ÔÌÜ) ¤Ë³¤¯¥Æ¥¥¹¥È: %s" -#: ../spell.c:954 #, c-format msgid "Affix name too long in %s line %d: %s" msgstr "%s (%d ¹ÔÌÜ) ¤Î affix ̾¤¬Ä¹²á¤®¤Þ¤¹: %s" -#: ../spell.c:955 msgid "E761: Format error in affix file FOL, LOW or UPP" msgstr "" "E761: affix¥Õ¥¡¥¤¥ë¤Î FOL, LOW ¤â¤·¤¯¤Ï UPP ¤Î¥Õ¥©¡¼¥Þ¥Ã¥È¤Ë¥¨¥é¡¼¤¬¤¢¤ê¤Þ¤¹" -#: ../spell.c:957 msgid "E762: Character in FOL, LOW or UPP is out of range" msgstr "E762: FOL, LOW ¤â¤·¤¯¤Ï UPP ¤Îʸ»ú¤¬Èϰϳ°¤Ç¤¹" -#: ../spell.c:958 msgid "Compressing word tree..." msgstr "ñ¸ì¥Ä¥ê¡¼¤ò°µ½Ì¤·¤Æ¤¤¤Þ¤¹..." -#: ../spell.c:1951 -msgid "E756: Spell checking is not enabled" -msgstr "E756: ¥¹¥Ú¥ë¥Á¥§¥Ã¥¯¤Ï̵¸ú²½¤µ¤ì¤Æ¤¤¤Þ¤¹" - -#: ../spell.c:2249 -#, c-format -msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" -msgstr "" -"·Ù¹ð: ñ¸ì¥ê¥¹¥È \"%s.%s.spl\" ¤ª¤è¤Ó \"%s.ascii.spl\" ¤Ï¸«¤Ä¤«¤ê¤Þ¤»¤ó" - -#: ../spell.c:2473 #, c-format msgid "Reading spell file \"%s\"" msgstr "¥¹¥Ú¥ë¥Õ¥¡¥¤¥ë \"%s\" ¤òÆÉ¹þÃæ" -#: ../spell.c:2496 msgid "E757: This does not look like a spell file" msgstr "E757: ¥¹¥Ú¥ë¥Õ¥¡¥¤¥ë¤Ç¤Ï¤Ê¤¤¤è¤¦¤Ç¤¹" -#: ../spell.c:2501 msgid "E771: Old spell file, needs to be updated" msgstr "E771: ¸Å¤¤¥¹¥Ú¥ë¥Õ¥¡¥¤¥ë¤Ê¤Î¤Ç, ¥¢¥Ã¥×¥Ç¡¼¥È¤·¤Æ¤¯¤À¤µ¤¤" -#: ../spell.c:2504 msgid "E772: Spell file is for newer version of Vim" msgstr "E772: ¤è¤ê¿·¤·¤¤¥Ð¡¼¥¸¥ç¥ó¤Î Vim ÍѤΥ¹¥Ú¥ë¥Õ¥¡¥¤¥ë¤Ç¤¹" -#: ../spell.c:2602 msgid "E770: Unsupported section in spell file" msgstr "E770: ¥¹¥Ú¥ë¥Õ¥¡¥¤¥ë¤Ë¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤Ê¤¤¥»¥¯¥·¥ç¥ó¤¬¤¢¤ê¤Þ¤¹" -#: ../spell.c:3762 #, c-format -msgid "Warning: region %s not supported" -msgstr "·Ù¹ð9: %s ¤È¤¤¤¦ÈϰϤϥµ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" +msgid "E778: This does not look like a .sug file: %s" +msgstr "E778: .sug ¥Õ¥¡¥¤¥ë¤Ç¤Ï¤Ê¤¤¤è¤¦¤Ç¤¹: %s" + +#, c-format +msgid "E779: Old .sug file, needs to be updated: %s" +msgstr "E779: ¸Å¤¤ .sug ¥Õ¥¡¥¤¥ë¤Ê¤Î¤Ç, ¥¢¥Ã¥×¥Ç¡¼¥È¤·¤Æ¤¯¤À¤µ¤¤: %s" + +#, c-format +msgid "E780: .sug file is for newer version of Vim: %s" +msgstr "E780: ¤è¤ê¿·¤·¤¤¥Ð¡¼¥¸¥ç¥ó¤Î Vim ÍѤΠ.sug ¥Õ¥¡¥¤¥ë¤Ç¤¹: %s" + +#, c-format +msgid "E781: .sug file doesn't match .spl file: %s" +msgstr "E781: .sug ¥Õ¥¡¥¤¥ë¤¬ .spl ¥Õ¥¡¥¤¥ë¤È°ìÃפ·¤Þ¤»¤ó: %s" + +#, c-format +msgid "E782: error while reading .sug file: %s" +msgstr "E782: .sug ¥Õ¥¡¥¤¥ë¤ÎÆÉ¹þÃæ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤Þ¤·¤¿: %s" -#: ../spell.c:4550 #, c-format msgid "Reading affix file %s ..." msgstr "affix ¥Õ¥¡¥¤¥ë %s ¤òÆÉ¹þÃæ..." -#: ../spell.c:4589 ../spell.c:5635 ../spell.c:6140 #, c-format msgid "Conversion failure for word in %s line %d: %s" msgstr "%s (%d ¹ÔÌÜ) ¤Îñ¸ì¤òÊÑ´¹¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿: %s" -#: ../spell.c:4630 ../spell.c:6170 #, c-format msgid "Conversion in %s not supported: from %s to %s" msgstr "%s Æâ¤Î¼¡¤ÎÊÑ´¹¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó: %s ¤«¤é %s ¤Ø" -#: ../spell.c:4642 +#, c-format +msgid "Conversion in %s not supported" +msgstr "%s Æâ¤ÎÊÑ´¹¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" + #, c-format msgid "Invalid value for FLAG in %s line %d: %s" msgstr "%s Æâ¤Î %d ¹ÔÌܤΠFLAG ¤Ë̵¸ú¤ÊÃͤ¬¤¢¤ê¤Þ¤¹: %s" -#: ../spell.c:4655 #, c-format msgid "FLAG after using flags in %s line %d: %s" msgstr "%s Æâ¤Î %d ¹ÔÌܤ˥ե饰¤ÎÆó½Å»ÈÍѤ¬¤¢¤ê¤Þ¤¹: %s" -#: ../spell.c:4723 #, c-format msgid "" "Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line " @@ -5361,7 +5118,6 @@ msgstr "" "%s ¤Î %d ¹ÔÌܤΠPFX ¹àÌܤθå¤Î COMPOUNDFORBIDFLAG ¤ÎÄêµÁ¤Ï¸í¤Ã¤¿·ë²Ì¤òÀ¸¤¸¤ë" "¤³¤È¤¬¤¢¤ê¤Þ¤¹" -#: ../spell.c:4731 #, c-format msgid "" "Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line " @@ -5370,43 +5126,35 @@ msgstr "" "%s ¤Î %d ¹ÔÌܤΠPFX ¹àÌܤθå¤Î COMPOUNDPERMITFLAG ¤ÎÄêµÁ¤Ï¸í¤Ã¤¿·ë²Ì¤òÀ¸¤¸¤ë" "¤³¤È¤¬¤¢¤ê¤Þ¤¹" -#: ../spell.c:4747 #, c-format msgid "Wrong COMPOUNDRULES value in %s line %d: %s" msgstr "COMPOUNDRULES ¤ÎÃͤ˸í¤ê¤¬¤¢¤ê¤Þ¤¹. ¥Õ¥¡¥¤¥ë %s ¤Î %d ¹ÔÌÜ: %s" -#: ../spell.c:4771 #, c-format msgid "Wrong COMPOUNDWORDMAX value in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌܤΠCOMPOUNDWORDMAX ¤ÎÃͤ˸í¤ê¤¬¤¢¤ê¤Þ¤¹: %s" -#: ../spell.c:4777 #, c-format msgid "Wrong COMPOUNDMIN value in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌܤΠCOMPOUNDMIN ¤ÎÃͤ˸í¤ê¤¬¤¢¤ê¤Þ¤¹: %s" -#: ../spell.c:4783 #, c-format msgid "Wrong COMPOUNDSYLMAX value in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌܤΠCOMPOUNDSYLMAX ¤ÎÃͤ˸í¤ê¤¬¤¢¤ê¤Þ¤¹: %s" -#: ../spell.c:4795 #, c-format msgid "Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌܤΠCHECKCOMPOUNDPATTERN ¤ÎÃͤ˸í¤ê¤¬¤¢¤ê¤Þ¤¹: %s" -#: ../spell.c:4847 #, c-format msgid "Different combining flag in continued affix block in %s line %d: %s" msgstr "" "%s ¤Î %d ¹ÔÌܤΠϢ³ affix ¥Ö¥í¥Ã¥¯¤Î¥Õ¥é¥°¤ÎÁȹ礻¤Ë°ã¤¤¤¬¤¢¤ê¤Þ¤¹: %s" -#: ../spell.c:4850 #, c-format msgid "Duplicate affix in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌÜ¤Ë ½ÅÊ£¤·¤¿ affix ¤ò¸¡½Ð¤·¤Þ¤·¤¿: %s" -#: ../spell.c:4871 #, c-format msgid "" "Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in %s " @@ -5415,308 +5163,206 @@ msgstr "" "%s ¤Î %d ¹ÔÌܤΠaffix ¤Ï BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST " "¤Ë»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤: %s" -#: ../spell.c:4893 #, c-format msgid "Expected Y or N in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌÜ¤Ç¤Ï Y ¤« N ¤¬É¬ÍפǤ¹: %s" -#: ../spell.c:4968 #, c-format msgid "Broken condition in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌܤΠ¾ò·ï¤Ï²õ¤ì¤Æ¤¤¤Þ¤¹: %s" -#: ../spell.c:5091 #, c-format msgid "Expected REP(SAL) count in %s line %d" msgstr "%s ¤Î %d ¹ÔÌÜ¤Ë¤Ï REP(SAL) ¤Î²ó¿ô¤¬É¬ÍפǤ¹" -#: ../spell.c:5120 #, c-format msgid "Expected MAP count in %s line %d" msgstr "%s ¤Î %d ¹ÔÌÜ¤Ë¤Ï MAP ¤Î²ó¿ô¤¬É¬ÍפǤ¹" -#: ../spell.c:5132 #, c-format msgid "Duplicate character in MAP in %s line %d" msgstr "%s ¤Î %d ¹ÔÌܤΠMAP ¤Ë½ÅÊ£¤·¤¿Ê¸»ú¤¬¤¢¤ê¤Þ¤¹" -#: ../spell.c:5176 #, c-format msgid "Unrecognized or duplicate item in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌÜ¤Ë Ç§¼±¤Ç¤¤Ê¤¤¤«½ÅÊ£¤·¤¿¹àÌܤ¬¤¢¤ê¤Þ¤¹: %s" -#: ../spell.c:5197 #, c-format msgid "Missing FOL/LOW/UPP line in %s" msgstr "%s ¹ÔÌÜ¤Ë FOL/LOW/UPP ¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../spell.c:5220 msgid "COMPOUNDSYLMAX used without SYLLABLE" msgstr "SYLLABLE ¤¬»ØÄꤵ¤ì¤Ê¤¤ COMPOUNDSYLMAX" -#: ../spell.c:5236 msgid "Too many postponed prefixes" msgstr "ÃÙ±ä¸åÃÖ»Ò¤¬Â¿²á¤®¤Þ¤¹" -#: ../spell.c:5238 msgid "Too many compound flags" msgstr "Ê£¹ç¥Õ¥é¥°¤¬Â¿²á¤®¤Þ¤¹" -#: ../spell.c:5240 msgid "Too many postponed prefixes and/or compound flags" msgstr "ÃÙ±ä¸åÃÖ»Ò ¤È/¤â¤·¤¯¤Ï Ê£¹ç¥Õ¥é¥°¤¬Â¿²á¤®¤Þ¤¹" -#: ../spell.c:5250 #, c-format msgid "Missing SOFO%s line in %s" msgstr "SOFO%s ¹Ô¤¬ %s ¤Ë¤¢¤ê¤Þ¤»¤ó" -#: ../spell.c:5253 #, c-format msgid "Both SAL and SOFO lines in %s" msgstr "SAL¹Ô ¤È SOFO¹Ô ¤¬ %s ¤ÇξÊý»ØÄꤵ¤ì¤Æ¤¤¤Þ¤¹" -#: ../spell.c:5331 #, c-format msgid "Flag is not a number in %s line %d: %s" msgstr "%s ¤Î %d ¹Ô¤Î ¥Õ¥é¥°¤¬¿ôÃͤǤϤ¢¤ê¤Þ¤»¤ó: %s" -#: ../spell.c:5334 #, c-format msgid "Illegal flag in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌܤΠ¥Õ¥é¥°¤¬ÉÔÀµ¤Ç¤¹: %s" -#: ../spell.c:5493 ../spell.c:5501 #, c-format msgid "%s value differs from what is used in another .aff file" msgstr "ÃÍ %s ¤Ï¾¤Î .aff ¥Õ¥¡¥¤¥ë¤Ç»ÈÍѤµ¤ì¤¿¤Î¤È°Û¤Ê¤ê¤Þ¤¹" -#: ../spell.c:5602 #, c-format msgid "Reading dictionary file %s ..." msgstr "¼½ñ¥Õ¥¡¥¤¥ë %s ¤ò¥¹¥¥ã¥óÃæ..." -#: ../spell.c:5611 #, c-format msgid "E760: No word count in %s" msgstr "E760: %s ¤Ë¤Ïñ¸ì¿ô¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../spell.c:5669 #, c-format msgid "line %6d, word %6d - %s" msgstr "¹Ô %6d, ñ¸ì %6d - %s" -#: ../spell.c:5691 #, c-format msgid "Duplicate word in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌÜ¤Ç ½Åʣñ¸ì¤¬¸«¤Ä¤«¤ê¤Þ¤·¤¿: %s" -#: ../spell.c:5694 #, c-format msgid "First duplicate word in %s line %d: %s" msgstr "½ÅÊ£¤Î¤¦¤ÁºÇ½é¤Îñ¸ì¤Ï %s ¤Î %d ¹ÔÌܤǤ¹: %s" -#: ../spell.c:5746 #, c-format msgid "%d duplicate word(s) in %s" msgstr "%d ¸Ä¤Îñ¸ì¤¬¸«¤Ä¤«¤ê¤Þ¤·¤¿ (%s Æâ)" -#: ../spell.c:5748 #, c-format msgid "Ignored %d word(s) with non-ASCII characters in %s" msgstr "ÈóASCIIʸ»ú¤ò´Þ¤à %d ¸Ä¤Îñ¸ì¤ò̵»ë¤·¤Þ¤·¤¿ (%s Æâ)" -#: ../spell.c:6115 #, c-format msgid "Reading word file %s ..." msgstr "ɸ½àÆþÎϤ«¤éÆÉ¹þ¤ßÃæ %s ..." -#: ../spell.c:6155 #, c-format msgid "Duplicate /encoding= line ignored in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌܤΠ½ÅÊ£¤·¤¿ /encoding= ¹Ô¤ò̵»ë¤·¤Þ¤·¤¿: %s" -#: ../spell.c:6159 #, c-format msgid "/encoding= line after word ignored in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌܤΠñ¸ì¤Î¸å¤Î /encoding= ¹Ô¤ò̵»ë¤·¤Þ¤·¤¿: %s" -#: ../spell.c:6180 #, c-format msgid "Duplicate /regions= line ignored in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌܤΠ½ÅÊ£¤·¤¿ /regions= ¹Ô¤ò̵»ë¤·¤Þ¤·¤¿: %s" -#: ../spell.c:6185 #, c-format msgid "Too many regions in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌÜ, ÈϰϻØÄ꤬¿²á¤®¤Þ¤¹: %s" -#: ../spell.c:6198 #, c-format msgid "/ line ignored in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌܤΠ½ÅÊ£¤·¤¿ / ¹Ô¤ò̵»ë¤·¤Þ¤·¤¿: %s" -#: ../spell.c:6224 #, c-format msgid "Invalid region nr in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌÜ Ìµ¸ú¤Ê nr Îΰè¤Ç¤¹: %s" -#: ../spell.c:6230 #, c-format msgid "Unrecognized flags in %s line %d: %s" msgstr "%s ¤Î %d ¹ÔÌÜ Ç§¼±ÉÔǽ¤Ê¥Õ¥é¥°¤Ç¤¹: %s" -#: ../spell.c:6257 #, c-format msgid "Ignored %d words with non-ASCII characters" msgstr "ÈóASCIIʸ»ú¤ò´Þ¤à %d ¸Ä¤Îñ¸ì¤ò̵»ë¤·¤Þ¤·¤¿" -#: ../spell.c:6656 +msgid "E845: Insufficient memory, word list will be incomplete" +msgstr "E845: ¥á¥â¥ê¤¬Â¤ê¤Ê¤¤¤Î¤Ç¡¢Ã±¸ì¥ê¥¹¥È¤ÏÉÔ´°Á´¤Ç¤¹" + #, c-format msgid "Compressed %d of %d nodes; %d (%d%%) remaining" msgstr "¥Î¡¼¥É %d ¸Ä(Á´ %d ¸ÄÃæ) ¤ò°µ½Ì¤·¤Þ¤·¤¿; »Ä¤ê %d (%d%%)" -#: ../spell.c:7340 msgid "Reading back spell file..." msgstr "¥¹¥Ú¥ë¥Õ¥¡¥¤¥ë¤òµÕÆÉ¹þÃæ" -#. Go through the trie of good words, soundfold each word and add it to -#. the soundfold trie. -#: ../spell.c:7357 +#. +#. * Go through the trie of good words, soundfold each word and add it to +#. * the soundfold trie. +#. msgid "Performing soundfolding..." msgstr "²»À¼¾ö¹þ¤ß¤ò¼Â¹ÔÃæ..." -#: ../spell.c:7368 #, c-format -msgid "Number of words after soundfolding: %<PRId64>" -msgstr "²»À¼¾ö¹þ¤ß¸å¤ÎÁíñ¸ì¿ô: %<PRId64>" +msgid "Number of words after soundfolding: %ld" +msgstr "²»À¼¾ö¹þ¤ß¸å¤ÎÁíñ¸ì¿ô: %ld" -#: ../spell.c:7476 #, c-format msgid "Total number of words: %d" msgstr "Áíñ¸ì¿ô: %d" -#: ../spell.c:7655 #, c-format msgid "Writing suggestion file %s ..." msgstr "½¤Àµ¸õÊä¥Õ¥¡¥¤¥ë \"%s\" ¤ò½ñ¹þ¤ßÃæ..." -#: ../spell.c:7707 ../spell.c:7927 #, c-format msgid "Estimated runtime memory use: %d bytes" msgstr "¿äÄê¥á¥â¥ê»ÈÍÑÎÌ: %d ¥Ð¥¤¥È" -#: ../spell.c:7820 msgid "E751: Output file name must not have region name" msgstr "E751: ½ÐÎÏ¥Õ¥¡¥¤¥ë̾¤Ë¤ÏÈϰÏ̾¤ò´Þ¤á¤é¤ì¤Þ¤»¤ó" -#: ../spell.c:7822 msgid "E754: Only up to 8 regions supported" msgstr "E754: ÈÏ°Ï¤Ï 8 ¸Ä¤Þ¤Ç¤·¤«¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#: ../spell.c:7846 #, c-format msgid "E755: Invalid region in %s" msgstr "E755: ̵¸ú¤ÊÈϰϤǤ¹: %s" -#: ../spell.c:7907 msgid "Warning: both compounding and NOBREAK specified" msgstr "·Ù¹ð: Ê£¹ç¥Õ¥é¥°¤È NOBREAK ¤¬Î¾Êý¤È¤â»ØÄꤵ¤ì¤Þ¤·¤¿" -#: ../spell.c:7920 #, c-format msgid "Writing spell file %s ..." msgstr "¥¹¥Ú¥ë¥Õ¥¡¥¤¥ë %s ¤ò½ñ¹þ¤ßÃæ..." -#: ../spell.c:7925 msgid "Done!" msgstr "¼Â¹Ô¤·¤Þ¤·¤¿!" -#: ../spell.c:8034 #, c-format -msgid "E765: 'spellfile' does not have %<PRId64> entries" -msgstr "E765: 'spellfile' ¤Ë¤Ï %<PRId64> ¸Ä¤Î¥¨¥ó¥È¥ê¤Ï¤¢¤ê¤Þ¤»¤ó" +msgid "E765: 'spellfile' does not have %ld entries" +msgstr "E765: 'spellfile' ¤Ë¤Ï %ld ¸Ä¤Î¥¨¥ó¥È¥ê¤Ï¤¢¤ê¤Þ¤»¤ó" -#: ../spell.c:8074 #, c-format msgid "Word '%.*s' removed from %s" msgstr "ñ¸ì '%.*s' ¤¬ %s ¤«¤éºï½ü¤µ¤ì¤Þ¤·¤¿" -#: ../spell.c:8117 #, c-format msgid "Word '%.*s' added to %s" msgstr "ñ¸ì '%.*s' ¤¬ %s ¤ØÄɲ䵤ì¤Þ¤·¤¿" -#: ../spell.c:8381 msgid "E763: Word characters differ between spell files" msgstr "E763: ñ¸ì¤Îʸ»ú¤¬¥¹¥Ú¥ë¥Õ¥¡¥¤¥ë¤È°Û¤Ê¤ê¤Þ¤¹" -#: ../spell.c:8684 -msgid "Sorry, no suggestions" -msgstr "»Äǰ¤Ç¤¹¤¬, ½¤Àµ¸õÊä¤Ï¤¢¤ê¤Þ¤»¤ó" - -#: ../spell.c:8687 -#, c-format -msgid "Sorry, only %<PRId64> suggestions" -msgstr "»Äǰ¤Ç¤¹¤¬, ½¤Àµ¸õÊä¤Ï %<PRId64> ¸Ä¤·¤«¤¢¤ê¤Þ¤»¤ó" - -#. for when 'cmdheight' > 1 -#. avoid more prompt -#: ../spell.c:8704 -#, c-format -msgid "Change \"%.*s\" to:" -msgstr "\"%.*s\" ¤ò¼¡¤ØÊÑ´¹:" - -#: ../spell.c:8737 -#, c-format -msgid " < \"%.*s\"" -msgstr " < \"%.*s\"" - -#: ../spell.c:8882 -msgid "E752: No previous spell replacement" -msgstr "E752: ¥¹¥Ú¥ëÃÖ´¹¤¬¤Þ¤À¼Â¹Ô¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" - -#: ../spell.c:8925 -#, c-format -msgid "E753: Not found: %s" -msgstr "E753: ¸«¤Ä¤«¤ê¤Þ¤»¤ó: %s" - -#: ../spell.c:9276 -#, c-format -msgid "E778: This does not look like a .sug file: %s" -msgstr "E778: .sug ¥Õ¥¡¥¤¥ë¤Ç¤Ï¤Ê¤¤¤è¤¦¤Ç¤¹: %s" - -#: ../spell.c:9282 -#, c-format -msgid "E779: Old .sug file, needs to be updated: %s" -msgstr "E779: ¸Å¤¤ .sug ¥Õ¥¡¥¤¥ë¤Ê¤Î¤Ç, ¥¢¥Ã¥×¥Ç¡¼¥È¤·¤Æ¤¯¤À¤µ¤¤: %s" - -#: ../spell.c:9286 -#, c-format -msgid "E780: .sug file is for newer version of Vim: %s" -msgstr "E780: ¤è¤ê¿·¤·¤¤¥Ð¡¼¥¸¥ç¥ó¤Î Vim ÍѤΠ.sug ¥Õ¥¡¥¤¥ë¤Ç¤¹: %s" - -#: ../spell.c:9295 -#, c-format -msgid "E781: .sug file doesn't match .spl file: %s" -msgstr "E781: .sug ¥Õ¥¡¥¤¥ë¤¬ .spl ¥Õ¥¡¥¤¥ë¤È°ìÃפ·¤Þ¤»¤ó: %s" - -#: ../spell.c:9305 -#, c-format -msgid "E782: error while reading .sug file: %s" -msgstr "E782: .sug ¥Õ¥¡¥¤¥ë¤ÎÆÉ¹þÃæ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤Þ¤·¤¿: %s" - #. This should have been checked when generating the .spl -#. file. -#: ../spell.c:11575 +#. * file. msgid "E783: duplicate char in MAP entry" msgstr "E783: MAP ¥¨¥ó¥È¥ê¤Ë½Åʣʸ»ú¤¬Â¸ºß¤·¤Þ¤¹" -#: ../syntax.c:266 msgid "No Syntax items defined for this buffer" msgstr "¤³¤Î¥Ð¥Ã¥Õ¥¡¤ËÄêµÁ¤µ¤ì¤¿¹½Ê¸Í×ÁǤϤ¢¤ê¤Þ¤»¤ó" -#: ../syntax.c:3083 ../syntax.c:3104 ../syntax.c:3127 #, c-format msgid "E390: Illegal argument: %s" msgstr "E390: ÉÔÀµ¤Ê°ú¿ô¤Ç¤¹: %s" @@ -5724,28 +5370,22 @@ msgstr "E390: ÉÔÀµ¤Ê°ú¿ô¤Ç¤¹: %s" msgid "syntax iskeyword " msgstr "¥·¥ó¥¿¥Ã¥¯¥¹ÍÑ iskeyword " -#: ../syntax.c:3299 #, c-format msgid "E391: No such syntax cluster: %s" msgstr "E391: ¤½¤Î¤è¤¦¤Ê¹½Ê¸¥¯¥é¥¹¥¿¤Ï¤¢¤ê¤Þ¤»¤ó: %s" -#: ../syntax.c:3433 msgid "syncing on C-style comments" msgstr "C¸À¸ìÉ÷¥³¥á¥ó¥È¤«¤éƱ´üÃæ" -#: ../syntax.c:3439 msgid "no syncing" msgstr "È󯱴ü" -#: ../syntax.c:3441 msgid "syncing starts " msgstr "Ʊ´ü³«»Ï " -#: ../syntax.c:3443 ../syntax.c:3506 msgid " lines before top line" msgstr " ¹ÔÁ°(¥È¥Ã¥×¹Ô¤è¤ê¤â)" -#: ../syntax.c:3448 msgid "" "\n" "--- Syntax sync items ---" @@ -5753,7 +5393,6 @@ msgstr "" "\n" "--- ¹½Ê¸Æ±´üÍ×ÁÇ ---" -#: ../syntax.c:3452 msgid "" "\n" "syncing on items" @@ -5761,7 +5400,6 @@ msgstr "" "\n" "Í×ÁǾå¤ÇƱ´üÃæ" -#: ../syntax.c:3457 msgid "" "\n" "--- Syntax items ---" @@ -5769,53 +5407,41 @@ msgstr "" "\n" "--- ¹½Ê¸Í×ÁÇ ---" -#: ../syntax.c:3475 #, c-format msgid "E392: No such syntax cluster: %s" msgstr "E392: ¤½¤Î¤è¤¦¤Ê¹½Ê¸¥¯¥é¥¹¥¿¤Ï¤¢¤ê¤Þ¤»¤ó: %s" -#: ../syntax.c:3497 msgid "minimal " msgstr "minimal " -#: ../syntax.c:3503 msgid "maximal " msgstr "maximal " -#: ../syntax.c:3513 msgid "; match " msgstr "; ³ºÅö " -#: ../syntax.c:3515 msgid " line breaks" msgstr " ¸Ä¤Î²þ¹Ô" -#: ../syntax.c:4076 msgid "E395: contains argument not accepted here" msgstr "E395: ¤³¤Î¾ì½ê¤Ç¤Ï°ú¿ôcontains¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#: ../syntax.c:4096 msgid "E844: invalid cchar value" msgstr "E844: ̵¸ú¤Êcchar¤ÎÃͤǤ¹" -#: ../syntax.c:4107 msgid "E393: group[t]here not accepted here" msgstr "E393: ¤³¤³¤Ç¤Ï¥°¥ë¡¼¥×¤Ïµö²Ä¤µ¤ì¤Þ¤»¤ó" -#: ../syntax.c:4126 #, c-format msgid "E394: Didn't find region item for %s" msgstr "E394: %s ¤ÎÈϰÏÍ×ÁǤ¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../syntax.c:4188 msgid "E397: Filename required" msgstr "E397: ¥Õ¥¡¥¤¥ë̾¤¬É¬ÍפǤ¹" -#: ../syntax.c:4221 msgid "E847: Too many syntax includes" msgstr "E847: ¹½Ê¸¤Î¼è¤ê¹þ¤ß(include)¤¬Â¿²á¤®¤Þ¤¹" -#: ../syntax.c:4303 #, c-format msgid "E789: Missing ']': %s" msgstr "E789: ']' ¤¬¤¢¤ê¤Þ¤»¤ó: %s" @@ -5824,221 +5450,173 @@ msgstr "E789: ']' ¤¬¤¢¤ê¤Þ¤»¤ó: %s" msgid "E890: trailing char after ']': %s]%s" msgstr "E890: ']' ¤Î¸å¤í¤Ë;ʬ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤¹: %s]%s" -#: ../syntax.c:4531 #, c-format msgid "E398: Missing '=': %s" msgstr "E398: '=' ¤¬¤¢¤ê¤Þ¤»¤ó: %s" -#: ../syntax.c:4666 #, c-format msgid "E399: Not enough arguments: syntax region %s" msgstr "E399: °ú¿ô¤¬Â¤ê¤Þ¤»¤ó: ¹½Ê¸ÈÏ°Ï %s" -#: ../syntax.c:4870 msgid "E848: Too many syntax clusters" msgstr "E848: ¹½Ê¸¥¯¥é¥¹¥¿¤¬Â¿²á¤®¤Þ¤¹" -#: ../syntax.c:4954 msgid "E400: No cluster specified" msgstr "E400: ¥¯¥é¥¹¥¿¤¬»ØÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó" -#. end delimiter not found -#: ../syntax.c:4986 #, c-format msgid "E401: Pattern delimiter not found: %s" msgstr "E401: ¥Ñ¥¿¡¼¥ó¶èÀڤ꤬¸«¤Ä¤«¤ê¤Þ¤»¤ó: %s" -#: ../syntax.c:5049 #, c-format msgid "E402: Garbage after pattern: %s" msgstr "E402: ¥Ñ¥¿¡¼¥ó¤Î¤¢¤È¤Ë¥´¥ß¤¬¤¢¤ê¤Þ¤¹: %s" -#: ../syntax.c:5120 msgid "E403: syntax sync: line continuations pattern specified twice" msgstr "E403: ¹½Ê¸Æ±´ü: Ϣ³¹Ô¥Ñ¥¿¡¼¥ó¤¬2ÅÙ»ØÄꤵ¤ì¤Þ¤·¤¿" -#: ../syntax.c:5169 #, c-format msgid "E404: Illegal arguments: %s" msgstr "E404: ÉÔÀµ¤Ê°ú¿ô¤Ç¤¹: %s" -#: ../syntax.c:5217 #, c-format msgid "E405: Missing equal sign: %s" msgstr "E405: Åù¹æ¤¬¤¢¤ê¤Þ¤»¤ó: %s" -#: ../syntax.c:5222 #, c-format msgid "E406: Empty argument: %s" msgstr "E406: ¶õ¤Î°ú¿ô: %s" -#: ../syntax.c:5240 #, c-format msgid "E407: %s not allowed here" msgstr "E407: %s ¤Ï¥³¥³¤Ç¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#: ../syntax.c:5246 #, c-format msgid "E408: %s must be first in contains list" msgstr "E408: %s ¤ÏÆâÍÆ¥ê¥¹¥È¤ÎÀèÆ¬¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤" -#: ../syntax.c:5304 #, c-format msgid "E409: Unknown group name: %s" msgstr "E409: ̤ÃΤΥ°¥ë¡¼¥×̾: %s" -#: ../syntax.c:5512 #, c-format msgid "E410: Invalid :syntax subcommand: %s" msgstr "E410: ̵¸ú¤Ê :syntax ¤Î¥µ¥Ö¥³¥Þ¥ó¥É: %s" -#: ../syntax.c:5854 msgid "" " TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN" msgstr "" " TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN" -#: ../syntax.c:6146 msgid "E679: recursive loop loading syncolor.vim" msgstr "E679: syncolor.vim ¤ÎºÆµ¢¸Æ¤Ó½Ð¤·¤ò¸¡½Ð¤·¤Þ¤·¤¿" -#: ../syntax.c:6256 #, c-format msgid "E411: highlight group not found: %s" msgstr "E411: ¥Ï¥¤¥é¥¤¥È¥°¥ë¡¼¥×¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó: %s" -#: ../syntax.c:6278 #, c-format msgid "E412: Not enough arguments: \":highlight link %s\"" msgstr "E412: °ú¿ô¤¬½¼Ê¬¤Ç¤Ï¤Ê¤¤: \":highlight link %s\"" -#: ../syntax.c:6284 #, c-format msgid "E413: Too many arguments: \":highlight link %s\"" msgstr "E413: °ú¿ô¤¬Â¿²á¤®¤Þ¤¹: \":highlight link %s\"" -#: ../syntax.c:6302 msgid "E414: group has settings, highlight link ignored" msgstr "E414: ¥°¥ë¡¼¥×¤¬ÀßÄꤵ¤ì¤Æ¤¤¤ë¤Î¤Ç¥Ï¥¤¥é¥¤¥È¥ê¥ó¥¯¤Ï̵»ë¤µ¤ì¤Þ¤¹" -#: ../syntax.c:6367 #, c-format msgid "E415: unexpected equal sign: %s" msgstr "E415: ͽ´ü¤»¤ÌÅù¹æ¤Ç¤¹: %s" -#: ../syntax.c:6395 #, c-format msgid "E416: missing equal sign: %s" msgstr "E416: Åù¹æ¤¬¤¢¤ê¤Þ¤»¤ó: %s" -#: ../syntax.c:6418 #, c-format msgid "E417: missing argument: %s" msgstr "E417: °ú¿ô¤¬¤¢¤ê¤Þ¤»¤ó: %s" -#: ../syntax.c:6446 #, c-format msgid "E418: Illegal value: %s" msgstr "E418: ÉÔÀµ¤ÊÃͤǤ¹: %s" -#: ../syntax.c:6496 msgid "E419: FG color unknown" msgstr "E419: ̤ÃΤÎÁ°·Ê¿§¤Ç¤¹" -#: ../syntax.c:6504 msgid "E420: BG color unknown" msgstr "E420: ̤ÃΤÎÇØ·Ê¿§¤Ç¤¹" -#: ../syntax.c:6564 #, c-format msgid "E421: Color name or number not recognized: %s" msgstr "E421: ¥«¥é¡¼Ì¾¤äÈÖ¹æ¤òǧ¼±¤Ç¤¤Þ¤»¤ó: %s" -#: ../syntax.c:6714 #, c-format msgid "E422: terminal code too long: %s" msgstr "E422: ½ªÃ¼¥³¡¼¥É¤¬Ä¹²á¤®¤Þ¤¹: %s" -#: ../syntax.c:6753 #, c-format msgid "E423: Illegal argument: %s" msgstr "E423: ÉÔÀµ¤Ê°ú¿ô¤Ç¤¹: %s" -#: ../syntax.c:6925 msgid "E424: Too many different highlighting attributes in use" msgstr "E424: ¿¤¯¤Î°Û¤Ê¤ë¥Ï¥¤¥é¥¤¥È°À¤¬»È¤ï¤ì²á¤®¤Æ¤¤¤Þ¤¹" -#: ../syntax.c:7427 msgid "E669: Unprintable character in group name" msgstr "E669: ¥°¥ë¡¼¥×̾¤Ë°õºþÉÔ²Äǽ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤¹" -#: ../syntax.c:7434 msgid "W18: Invalid character in group name" msgstr "W18: ¥°¥ë¡¼¥×̾¤ËÉÔÀµ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤¹" -#: ../syntax.c:7448 msgid "E849: Too many highlight and syntax groups" msgstr "E849: ¥Ï¥¤¥é¥¤¥È¤È¹½Ê¸¥°¥ë¡¼¥×¤¬Â¿²á¤®¤Þ¤¹" -#: ../tag.c:104 msgid "E555: at bottom of tag stack" msgstr "E555: ¥¿¥°¥¹¥¿¥Ã¥¯¤ÎËöÈø¤Ç¤¹" -#: ../tag.c:105 msgid "E556: at top of tag stack" msgstr "E556: ¥¿¥°¥¹¥¿¥Ã¥¯¤ÎÀèÆ¬¤Ç¤¹" -#: ../tag.c:380 msgid "E425: Cannot go before first matching tag" msgstr "E425: ºÇ½é¤Î³ºÅö¥¿¥°¤òͤ¨¤ÆÌá¤ë¤³¤È¤Ï¤Ç¤¤Þ¤»¤ó" -#: ../tag.c:504 #, c-format msgid "E426: tag not found: %s" msgstr "E426: ¥¿¥°¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó: %s" -#: ../tag.c:528 msgid " # pri kind tag" msgstr " # pri kind tag" -#: ../tag.c:531 msgid "file\n" msgstr "¥Õ¥¡¥¤¥ë\n" -#: ../tag.c:829 msgid "E427: There is only one matching tag" msgstr "E427: ³ºÅö¥¿¥°¤¬1¤Ä¤À¤±¤·¤«¤¢¤ê¤Þ¤»¤ó" -#: ../tag.c:831 msgid "E428: Cannot go beyond last matching tag" msgstr "E428: ºÇ¸å¤Ë³ºÅö¤¹¤ë¥¿¥°¤òͤ¨¤Æ¿Ê¤à¤³¤È¤Ï¤Ç¤¤Þ¤»¤ó" -#: ../tag.c:850 #, c-format msgid "File \"%s\" does not exist" msgstr "¥Õ¥¡¥¤¥ë \"%s\" ¤¬¤¢¤ê¤Þ¤»¤ó" #. Give an indication of the number of matching tags -#: ../tag.c:859 #, c-format msgid "tag %d of %d%s" msgstr "¥¿¥° %d (Á´%d%s)" -#: ../tag.c:862 msgid " or more" msgstr " ¤«¤½¤ì°Ê¾å" -#: ../tag.c:864 msgid " Using tag with different case!" msgstr " ¥¿¥°¤ò°Û¤Ê¤ëcase¤Ç»ÈÍѤ·¤Þ¤¹!" -#: ../tag.c:909 #, c-format msgid "E429: File \"%s\" does not exist" msgstr "E429: ¥Õ¥¡¥¤¥ë \"%s\" ¤¬¤¢¤ê¤Þ¤»¤ó" #. Highlight title -#: ../tag.c:960 msgid "" "\n" " # TO tag FROM line in file/text" @@ -6046,79 +5624,66 @@ msgstr "" "\n" " # TO ¥¿¥° FROM ¹Ô in file/text" -#: ../tag.c:1303 #, c-format msgid "Searching tags file %s" msgstr "¥¿¥°¥Õ¥¡¥¤¥ë %s ¤ò¸¡º÷Ãæ" -#: ../tag.c:1545 +#, c-format +msgid "E430: Tag file path truncated for %s\n" +msgstr "E430: ¥¿¥°¥Õ¥¡¥¤¥ë¤Î¥Ñ¥¹¤¬ %s ¤ËÀÚ¤ê¼Î¤Æ¤é¤ì¤Þ¤·¤¿\n" + msgid "Ignoring long line in tags file" msgstr "¥¿¥°¥Õ¥¡¥¤¥ëÆâ¤ÎŤ¤¹Ô¤ò̵»ë¤·¤Þ¤¹" -#: ../tag.c:1915 #, c-format msgid "E431: Format error in tags file \"%s\"" msgstr "E431: ¥¿¥°¥Õ¥¡¥¤¥ë \"%s\" ¤Î¥Õ¥©¡¼¥Þ¥Ã¥È¤Ë¥¨¥é¡¼¤¬¤¢¤ê¤Þ¤¹" -#: ../tag.c:1917 #, c-format -msgid "Before byte %<PRId64>" -msgstr "ľÁ°¤Î %<PRId64> ¥Ð¥¤¥È" +msgid "Before byte %ld" +msgstr "ľÁ°¤Î %ld ¥Ð¥¤¥È" -#: ../tag.c:1929 #, c-format msgid "E432: Tags file not sorted: %s" msgstr "E432: ¥¿¥°¥Õ¥¡¥¤¥ë¤¬¥½¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó: %s" #. never opened any tags file -#: ../tag.c:1960 msgid "E433: No tags file" msgstr "E433: ¥¿¥°¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../tag.c:2536 msgid "E434: Can't find tag pattern" msgstr "E434: ¥¿¥°¥Ñ¥¿¡¼¥ó¤ò¸«¤Ä¤±¤é¤ì¤Þ¤»¤ó" -#: ../tag.c:2544 msgid "E435: Couldn't find tag, just guessing!" msgstr "E435: ¥¿¥°¤ò¸«¤Ä¤±¤é¤ì¤Ê¤¤¤Î¤Çñ¤Ë¿ä¬¤·¤Þ¤¹!" -#: ../tag.c:2797 #, c-format msgid "Duplicate field name: %s" msgstr "½ÅÊ£¤·¤¿¥Õ¥£¡¼¥ë¥É̾: %s" -#: ../term.c:1442 msgid "' not known. Available builtin terminals are:" msgstr "' ¤Ï̤ÃΤǤ¹. ¸½¹Ô¤ÎÁȤ߹þ¤ßüËö¤Ï¼¡¤Î¤È¤ª¤ê¤Ç¤¹:" -#: ../term.c:1463 msgid "defaulting to '" msgstr "¾ÊάÃͤò¼¡¤Î¤è¤¦¤ËÀßÄꤷ¤Þ¤¹ '" -#: ../term.c:1731 msgid "E557: Cannot open termcap file" msgstr "E557: termcap¥Õ¥¡¥¤¥ë¤ò³«¤±¤Þ¤»¤ó" -#: ../term.c:1735 msgid "E558: Terminal entry not found in terminfo" msgstr "E558: terminfo¤ËüËö¥¨¥ó¥È¥ê¤ò¸«¤Ä¤±¤é¤ì¤Þ¤»¤ó" -#: ../term.c:1737 msgid "E559: Terminal entry not found in termcap" msgstr "E559: termcap¤ËüËö¥¨¥ó¥È¥ê¤ò¸«¤Ä¤±¤é¤ì¤Þ¤»¤ó" -#: ../term.c:1878 #, c-format msgid "E436: No \"%s\" entry in termcap" msgstr "E436: termcap¤Ë \"%s\" ¤Î¥¨¥ó¥È¥ê¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../term.c:2249 msgid "E437: terminal capability \"cm\" required" msgstr "E437: üËö¤Ë \"cm\" µ¡Ç½¤¬É¬ÍפǤ¹" #. Highlight title -#: ../term.c:4376 msgid "" "\n" "--- Terminal keys ---" @@ -6126,168 +5691,347 @@ msgstr "" "\n" "--- üËö¥¡¼ ---" -#: ../ui.c:481 +msgid "Cannot open $VIMRUNTIME/rgb.txt" +msgstr "$VIMRUNTIME/rgb.txt¤ò³«¤±¤Þ¤»¤ó" + +msgid "new shell started\n" +msgstr "¿·¤·¤¤¥·¥§¥ë¤òµ¯Æ°¤·¤Þ¤¹\n" + msgid "Vim: Error reading input, exiting...\n" msgstr "Vim: ÆþÎϤòÆÉ¹þ¤ßÃæ¤Î¥¨¥é¡¼¤Ë¤è¤ê½ªÎ»¤·¤Þ¤¹...\n" +msgid "Used CUT_BUFFER0 instead of empty selection" +msgstr "¶õ¤ÎÁªÂòÎΰè¤Î¤«¤ï¤ê¤ËCUT_BUFFER0¤¬»ÈÍѤµ¤ì¤Þ¤·¤¿" + #. This happens when the FileChangedRO autocommand changes the #. * file in a way it becomes shorter. -#: ../undo.c:379 msgid "E881: Line count changed unexpectedly" msgstr "E881: ͽ´ü¤»¤º¹Ô¥«¥¦¥ó¥È¤¬ÊѤï¤ê¤Þ¤·¤¿" -#: ../undo.c:627 +#. must display the prompt +msgid "No undo possible; continue anyway" +msgstr "²Äǽ¤Ê¥¢¥ó¥É¥¥¤Ï¤¢¤ê¤Þ¤»¤ó: ¤È¤ê¤¢¤¨¤ºÂ³¤±¤Þ¤¹" + #, c-format msgid "E828: Cannot open undo file for writing: %s" msgstr "E828: ½ñ¹þ¤ßÍѤ˥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤ò³«¤±¤Þ¤»¤ó: %s" -#: ../undo.c:717 #, c-format msgid "E825: Corrupted undo file (%s): %s" msgstr "E825: ¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤¬²õ¤ì¤Æ¤¤¤Þ¤¹ (%s): %s" -#: ../undo.c:1039 msgid "Cannot write undo file in any directory in 'undodir'" msgstr "'undodir'¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ë¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤ò½ñ¤¹þ¤á¤Þ¤»¤ó" -#: ../undo.c:1074 #, c-format msgid "Will not overwrite with undo file, cannot read: %s" msgstr "¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤È¤·¤ÆÆÉ¤ß¹þ¤á¤Ê¤¤¤Î¤Ç¾å½ñ¤¤·¤Þ¤»¤ó: %s" -#: ../undo.c:1092 #, c-format msgid "Will not overwrite, this is not an undo file: %s" msgstr "¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤Ç¤Ï¤Ê¤¤¤Î¤Ç¾å½ñ¤¤·¤Þ¤»¤ó: %s" -#: ../undo.c:1108 msgid "Skipping undo file write, nothing to undo" msgstr "Âоݤ¬¤Ê¤¤¤Î¤Ç¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤Î½ñ¤¹þ¤ß¤ò¥¹¥¥Ã¥×¤·¤Þ¤¹" -#: ../undo.c:1121 #, c-format msgid "Writing undo file: %s" msgstr "¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë½ñ¤¹þ¤ßÃæ: %s" -#: ../undo.c:1213 #, c-format msgid "E829: write error in undo file: %s" msgstr "E829: ¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤Î½ñ¤¹þ¤ß¥¨¥é¡¼¤Ç¤¹: %s" -#: ../undo.c:1280 #, c-format msgid "Not reading undo file, owner differs: %s" msgstr "¥ª¡¼¥Ê¡¼¤¬°Û¤Ê¤ë¤Î¤Ç¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤òÆÉ¤ß¹þ¤ß¤Þ¤»¤ó: %s" -#: ../undo.c:1292 #, c-format msgid "Reading undo file: %s" msgstr "¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ëÆÉ¹þÃæ: %s" -#: ../undo.c:1299 #, c-format msgid "E822: Cannot open undo file for reading: %s" msgstr "E822: ¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤òÆÉ¹þÍѤȤ·¤Æ³«¤±¤Þ¤»¤ó: %s" -#: ../undo.c:1308 #, c-format msgid "E823: Not an undo file: %s" msgstr "E823: ¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó: %s" -#: ../undo.c:1313 +#, c-format +msgid "E832: Non-encrypted file has encrypted undo file: %s" +msgstr "E832: Èó°Å¹æ²½¥Õ¥¡¥¤¥ë¤¬°Å¹æ²½¤µ¤ì¤¿¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤ò»È¤Ã¤Æ¤Þ¤¹: %s" + +#, c-format +msgid "E826: Undo file decryption failed: %s" +msgstr "E826: °Å¹æ²½¤µ¤ì¤¿¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤Î²òÆÉ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿: %s" + +#, c-format +msgid "E827: Undo file is encrypted: %s" +msgstr "E827: ¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤¬°Å¹æ²½¤µ¤ì¤Æ¤¤¤Þ¤¹: %s" + #, c-format msgid "E824: Incompatible undo file: %s" msgstr "E824: ¸ß´¹À¤Î̵¤¤¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤Ç¤¹: %s" -#: ../undo.c:1328 msgid "File contents changed, cannot use undo info" msgstr "¥Õ¥¡¥¤¥ë¤ÎÆâÍÆ¤¬ÊѤï¤Ã¤Æ¤¤¤ë¤¿¤á¡¢¥¢¥ó¥É¥¥¾ðÊó¤òÍøÍѤǤ¤Þ¤»¤ó" -#: ../undo.c:1497 #, c-format msgid "Finished reading undo file %s" msgstr "¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë %s ¤Î¼è¹þ¤ò´°Î»" -#: ../undo.c:1586 ../undo.c:1812 msgid "Already at oldest change" msgstr "´û¤Ë°ìÈָŤ¤Êѹ¹¤Ç¤¹" -#: ../undo.c:1597 ../undo.c:1814 msgid "Already at newest change" msgstr "´û¤Ë°ìÈÖ¿·¤·¤¤Êѹ¹¤Ç¤¹" -#: ../undo.c:1806 #, c-format -msgid "E830: Undo number %<PRId64> not found" -msgstr "E830: ¥¢¥ó¥É¥¥ÈÖ¹æ %<PRId64> ¤Ï¸«¤Ä¤«¤ê¤Þ¤»¤ó" +msgid "E830: Undo number %ld not found" +msgstr "E830: ¥¢¥ó¥É¥¥ÈÖ¹æ %ld ¤Ï¸«¤Ä¤«¤ê¤Þ¤»¤ó" -#: ../undo.c:1979 msgid "E438: u_undo: line numbers wrong" msgstr "E438: u_undo: ¹ÔÈֹ椬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹" -#: ../undo.c:2183 msgid "more line" msgstr "¹Ô Äɲä·¤Þ¤·¤¿" -#: ../undo.c:2185 msgid "more lines" msgstr "¹Ô Äɲä·¤Þ¤·¤¿" -#: ../undo.c:2187 msgid "line less" msgstr "¹Ô ºï½ü¤·¤Þ¤·¤¿" -#: ../undo.c:2189 msgid "fewer lines" msgstr "¹Ô ºï½ü¤·¤Þ¤·¤¿" -#: ../undo.c:2193 msgid "change" msgstr "²Õ½êÊѹ¹¤·¤Þ¤·¤¿" -#: ../undo.c:2195 msgid "changes" msgstr "²Õ½êÊѹ¹¤·¤Þ¤·¤¿" -#: ../undo.c:2225 #, c-format -msgid "%<PRId64> %s; %s #%<PRId64> %s" -msgstr "%<PRId64> %s; %s #%<PRId64> %s" +msgid "%ld %s; %s #%ld %s" +msgstr "%ld %s; %s #%ld %s" -#: ../undo.c:2228 msgid "before" msgstr "Á°Êý" -#: ../undo.c:2228 msgid "after" msgstr "¸åÊý" -#: ../undo.c:2325 msgid "Nothing to undo" msgstr "¥¢¥ó¥É¥¥Âоݤ¬¤¢¤ê¤Þ¤»¤ó" -#: ../undo.c:2330 msgid "number changes when saved" msgstr "ÄÌÈÖ Êѹ¹¿ô Êѹ¹»þ´ü ÊݸºÑ" -#: ../undo.c:2360 #, c-format -msgid "%<PRId64> seconds ago" -msgstr "%<PRId64> É÷вᤷ¤Æ¤¤¤Þ¤¹" +msgid "%ld seconds ago" +msgstr "%ld É÷вᤷ¤Æ¤¤¤Þ¤¹" -#: ../undo.c:2372 msgid "E790: undojoin is not allowed after undo" msgstr "E790: undo ¤Îľ¸å¤Ë undojoin ¤Ï¤Ç¤¤Þ¤»¤ó" -#: ../undo.c:2466 msgid "E439: undo list corrupt" msgstr "E439: ¥¢¥ó¥É¥¥¥ê¥¹¥È¤¬²õ¤ì¤Æ¤¤¤Þ¤¹" -#: ../undo.c:2495 msgid "E440: undo line missing" msgstr "E440: ¥¢¥ó¥É¥¥¹Ô¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../version.c:600 +#, c-format +msgid "E122: Function %s already exists, add ! to replace it" +msgstr "E122: ´Ø¿ô %s ¤ÏÄêµÁºÑ¤Ç¤¹, ºÆÄêµÁ¤¹¤ë¤Ë¤Ï ! ¤òÄɲ䷤Ƥ¯¤À¤µ¤¤" + +msgid "E717: Dictionary entry already exists" +msgstr "E717: ¼½ñ·¿Æâ¤Ë¥¨¥ó¥È¥ê¤¬´û¤Ë¸ºß¤·¤Þ¤¹" + +msgid "E718: Funcref required" +msgstr "E718: ´Ø¿ô»²¾È·¿¤¬Í׵ᤵ¤ì¤Þ¤¹" + +#, c-format +msgid "E130: Unknown function: %s" +msgstr "E130: ̤ÃΤδؿô¤Ç¤¹: %s" + +#, c-format +msgid "E125: Illegal argument: %s" +msgstr "E125: ÉÔÀµ¤Ê°ú¿ô¤Ç¤¹: %s" + +#, c-format +msgid "E853: Duplicate argument name: %s" +msgstr "E853: °ú¿ô̾¤¬½ÅÊ£¤·¤Æ¤¤¤Þ¤¹: %s" + +#, c-format +msgid "E740: Too many arguments for function %s" +msgstr "E740: ´Ø¿ô¤Î°ú¿ô¤¬Â¿²á¤®¤Þ¤¹: %s" + +#, c-format +msgid "E116: Invalid arguments for function %s" +msgstr "E116: ´Ø¿ô¤Î̵¸ú¤Ê°ú¿ô¤Ç¤¹: %s" + +msgid "E132: Function call depth is higher than 'maxfuncdepth'" +msgstr "E132: ´Ø¿ô¸Æ½Ð¤ÎÆþ¤ì»Ò¿ô¤¬ 'maxfuncdepth' ¤òͤ¨¤Þ¤·¤¿" + +#, c-format +msgid "calling %s" +msgstr "%s ¤ò¼Â¹ÔÃæ¤Ç¤¹" + +#, c-format +msgid "%s aborted" +msgstr "%s ¤¬ÃæÃǤµ¤ì¤Þ¤·¤¿" + +#, c-format +msgid "%s returning #%ld" +msgstr "%s ¤¬ #%ld ¤òÊÖ¤·¤Þ¤·¤¿" + +#, c-format +msgid "%s returning %s" +msgstr "%s ¤¬ %s ¤òÊÖ¤·¤Þ¤·¤¿" + +msgid "E699: Too many arguments" +msgstr "E699: °ú¿ô¤¬Â¿²á¤®¤Þ¤¹" + +#, c-format +msgid "E117: Unknown function: %s" +msgstr "E117: ̤ÃΤδؿô¤Ç¤¹: %s" + +#, c-format +msgid "E933: Function was deleted: %s" +msgstr "E933: ´Ø¿ô¤Ïºï½ü¤µ¤ì¤Þ¤·¤¿: %s" + +#, c-format +msgid "E119: Not enough arguments for function: %s" +msgstr "E119: ´Ø¿ô¤Î°ú¿ô¤¬Â¤ê¤Þ¤»¤ó: %s" + +#, c-format +msgid "E120: Using <SID> not in a script context: %s" +msgstr "E120: ¥¹¥¯¥ê¥×¥È°Ê³°¤Ç<SID>¤¬»È¤ï¤ì¤Þ¤·¤¿: %s" + +#, c-format +msgid "E725: Calling dict function without Dictionary: %s" +msgstr "E725: ¼½ñÍÑ´Ø¿ô¤¬¸Æ¤Ð¤ì¤Þ¤·¤¿¤¬¼½ñ¤¬¤¢¤ê¤Þ¤»¤ó: %s" + +msgid "E129: Function name required" +msgstr "E129: ´Ø¿ô̾¤¬Í׵ᤵ¤ì¤Þ¤¹" + +#, c-format +msgid "E128: Function name must start with a capital or \"s:\": %s" +msgstr "E128: ´Ø¿ô̾¤ÏÂçʸ»ú¤« \"s:\" ¤Ç»Ï¤Þ¤é¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó: %s" + +#, c-format +msgid "E884: Function name cannot contain a colon: %s" +msgstr "E884: ´Ø¿ô̾¤Ë¤Ï¥³¥í¥ó¤Ï´Þ¤á¤é¤ì¤Þ¤»¤ó: %s" + +#, c-format +msgid "E123: Undefined function: %s" +msgstr "E123: ̤ÄêµÁ¤Î´Ø¿ô¤Ç¤¹: %s" + +#, c-format +msgid "E124: Missing '(': %s" +msgstr "E124: '(' ¤¬¤¢¤ê¤Þ¤»¤ó: %s" + +msgid "E862: Cannot use g: here" +msgstr "E862: ¤³¤³¤Ç¤Ï g: ¤Ï»È¤¨¤Þ¤»¤ó" + +#, c-format +msgid "E932: Closure function should not be at top level: %s" +msgstr "E932: ¥¯¥í¡¼¥¸¥ã¡¼´Ø¿ô¤Ï¥È¥Ã¥×¥ì¥Ù¥ë¤Ëµ½Ò¤Ç¤¤Þ¤»¤ó: %s" + +msgid "E126: Missing :endfunction" +msgstr "E126: :endfunction ¤¬¤¢¤ê¤Þ¤»¤ó" + +#, c-format +msgid "E707: Function name conflicts with variable: %s" +msgstr "E707: ´Ø¿ô̾¤¬ÊÑ¿ô̾¤È¾×ÆÍ¤·¤Þ¤¹: %s" + +#, c-format +msgid "E127: Cannot redefine function %s: It is in use" +msgstr "E127: ´Ø¿ô %s ¤òºÆÄêµÁ¤Ç¤¤Þ¤»¤ó: »ÈÍÑÃæ¤Ç¤¹" + +#, c-format +msgid "E746: Function name does not match script file name: %s" +msgstr "E746: ´Ø¿ô̾¤¬¥¹¥¯¥ê¥×¥È¤Î¥Õ¥¡¥¤¥ë̾¤È°ìÃפ·¤Þ¤»¤ó: %s" + +#, c-format +msgid "E131: Cannot delete function %s: It is in use" +msgstr "E131: ´Ø¿ô %s ¤òºï½ü¤Ç¤¤Þ¤»¤ó: »ÈÍÑÃæ¤Ç¤¹" + +msgid "E133: :return not inside a function" +msgstr "E133: ´Ø¿ô³°¤Ë :return ¤¬¤¢¤ê¤Þ¤·¤¿" + +#, c-format +msgid "E107: Missing parentheses: %s" +msgstr "E107: ¥«¥Ã¥³ '(' ¤¬¤¢¤ê¤Þ¤»¤ó: %s" + +#. Only MS VC 4.1 and earlier can do Win32s +msgid "" +"\n" +"MS-Windows 16/32-bit GUI version" +msgstr "" +"\n" +"MS-Windows 16/32 ¥Ó¥Ã¥È GUI ÈÇ" + +msgid "" +"\n" +"MS-Windows 64-bit GUI version" +msgstr "" +"\n" +"MS-Windows 64 ¥Ó¥Ã¥È GUI ÈÇ" + +msgid "" +"\n" +"MS-Windows 32-bit GUI version" +msgstr "" +"\n" +"MS-Windows 32 ¥Ó¥Ã¥È GUI ÈÇ" + +msgid " with OLE support" +msgstr " with OLE ¥µ¥Ý¡¼¥È" + +msgid "" +"\n" +"MS-Windows 64-bit console version" +msgstr "" +"\n" +"MS-Windows 64 ¥Ó¥Ã¥È ¥³¥ó¥½¡¼¥ë ÈÇ" + +msgid "" +"\n" +"MS-Windows 32-bit console version" +msgstr "" +"\n" +"MS-Windows 32 ¥Ó¥Ã¥È ¥³¥ó¥½¡¼¥ë ÈÇ" + +msgid "" +"\n" +"MacOS X (unix) version" +msgstr "" +"\n" +"MacOS X (unix) ÈÇ" + +msgid "" +"\n" +"MacOS X version" +msgstr "" +"\n" +"MacOS X ÈÇ" + +msgid "" +"\n" +"MacOS version" +msgstr "" +"\n" +"MacOS ÈÇ" + +msgid "" +"\n" +"OpenVMS version" +msgstr "" +"\n" +"OpenVMS ÈÇ" + msgid "" "\n" "Included patches: " @@ -6295,7 +6039,6 @@ msgstr "" "\n" "ŬÍѺѥѥåÁ: " -#: ../version.c:627 msgid "" "\n" "Extra patches: " @@ -6303,11 +6046,9 @@ msgstr "" "\n" "ÄɲóÈÄ¥¥Ñ¥Ã¥Á: " -#: ../version.c:639 ../version.c:864 msgid "Modified by " msgstr "Modified by " -#: ../version.c:646 msgid "" "\n" "Compiled " @@ -6315,11 +6056,9 @@ msgstr "" "\n" "Compiled " -#: ../version.c:649 msgid "by " msgstr "by " -#: ../version.c:660 msgid "" "\n" "Huge version " @@ -6327,1886 +6066,926 @@ msgstr "" "\n" "Huge ÈÇ " -#: ../version.c:661 +msgid "" +"\n" +"Big version " +msgstr "" +"\n" +"Big ÈÇ " + +msgid "" +"\n" +"Normal version " +msgstr "" +"\n" +"Ä̾ï ÈÇ " + +msgid "" +"\n" +"Small version " +msgstr "" +"\n" +"Small ÈÇ " + +msgid "" +"\n" +"Tiny version " +msgstr "" +"\n" +"Tiny ÈÇ " + msgid "without GUI." msgstr "without GUI." -#: ../version.c:662 +msgid "with GTK3 GUI." +msgstr "with GTK3 GUI." + +msgid "with GTK2-GNOME GUI." +msgstr "with GTK2-GNOME GUI." + +msgid "with GTK2 GUI." +msgstr "with GTK2 GUI." + +msgid "with X11-Motif GUI." +msgstr "with X11-Motif GUI." + +msgid "with X11-neXtaw GUI." +msgstr "with X11-neXtaw GUI." + +msgid "with X11-Athena GUI." +msgstr "with X11-Athena GUI." + +msgid "with Photon GUI." +msgstr "with Photon GUI." + +msgid "with GUI." +msgstr "with GUI." + +msgid "with Carbon GUI." +msgstr "with Carbon GUI." + +msgid "with Cocoa GUI." +msgstr "with Cocoa GUI." + +msgid "with (classic) GUI." +msgstr "with (¥¯¥é¥·¥Ã¥¯) GUI." + msgid " Features included (+) or not (-):\n" msgstr " µ¡Ç½¤Î°ìÍ÷ ͸ú(+)/̵¸ú(-)\n" -#: ../version.c:667 msgid " system vimrc file: \"" msgstr " ¥·¥¹¥Æ¥à vimrc: \"" -#: ../version.c:672 msgid " user vimrc file: \"" msgstr " ¥æ¡¼¥¶¡¼ vimrc: \"" -#: ../version.c:677 msgid " 2nd user vimrc file: \"" msgstr " Âè2¥æ¡¼¥¶¡¼ vimrc: \"" -#: ../version.c:682 msgid " 3rd user vimrc file: \"" msgstr " Âè3¥æ¡¼¥¶¡¼ vimrc: \"" -#: ../version.c:687 msgid " user exrc file: \"" msgstr " ¥æ¡¼¥¶¡¼ exrc: \"" -#: ../version.c:692 msgid " 2nd user exrc file: \"" msgstr " Âè2¥æ¡¼¥¶¡¼ exrc: \"" -#: ../version.c:699 +msgid " system gvimrc file: \"" +msgstr " ¥·¥¹¥Æ¥à gvimrc: \"" + +msgid " user gvimrc file: \"" +msgstr " ¥æ¡¼¥¶¡¼ gvimrc: \"" + +msgid "2nd user gvimrc file: \"" +msgstr " Âè2¥æ¡¼¥¶¡¼ gvimrc: \"" + +msgid "3rd user gvimrc file: \"" +msgstr " Âè3¥æ¡¼¥¶¡¼ gvimrc: \"" + +msgid " defaults file: \"" +msgstr " ¥Ç¥Õ¥©¥ë¥È¥Õ¥¡¥¤¥ë: \"" + +msgid " system menu file: \"" +msgstr " ¥·¥¹¥Æ¥à¥á¥Ë¥å¡¼: \"" + msgid " fall-back for $VIM: \"" msgstr " ¾Êά»þ¤Î $VIM: \"" -#: ../version.c:705 msgid " f-b for $VIMRUNTIME: \"" msgstr "¾Êά»þ¤Î $VIMRUNTIME: \"" -#: ../version.c:709 msgid "Compilation: " msgstr "¥³¥ó¥Ñ¥¤¥ë: " -#: ../version.c:712 +msgid "Compiler: " +msgstr "¥³¥ó¥Ñ¥¤¥é: " + msgid "Linking: " msgstr "¥ê¥ó¥¯: " -#: ../version.c:717 msgid " DEBUG BUILD" msgstr "¥Ç¥Ð¥Ã¥°¥Ó¥ë¥É" -#: ../version.c:767 msgid "VIM - Vi IMproved" msgstr "VIM - Vi IMproved" -#: ../version.c:769 msgid "version " msgstr "version " -#: ../version.c:770 msgid "by Bram Moolenaar et al." msgstr "by Bram Moolenaar ¾." -#: ../version.c:774 msgid "Vim is open source and freely distributable" msgstr "Vim ¤Ï¥ª¡¼¥×¥ó¥½¡¼¥¹¤Ç¤¢¤ê¼«Í³¤ËÇÛÉÛ²Äǽ¤Ç¤¹" -#: ../version.c:776 msgid "Help poor children in Uganda!" msgstr "¥¦¥¬¥ó¥À¤Î·Ã¤Þ¤ì¤Ê¤¤»Ò¶¡¤¿¤Á¤Ë±ç½õ¤ò!" -#: ../version.c:777 msgid "type :help iccf<Enter> for information " msgstr "¾ÜºÙ¤Ê¾ðÊó¤Ï :help iccf<Enter> " -#: ../version.c:779 msgid "type :q<Enter> to exit " msgstr "½ªÎ»¤¹¤ë¤Ë¤Ï :q<Enter> " -#: ../version.c:780 msgid "type :help<Enter> or <F1> for on-line help" msgstr "¥ª¥ó¥é¥¤¥ó¥Ø¥ë¥×¤Ï :help<Enter> ¤« <F1> " -#: ../version.c:781 -msgid "type :help version7<Enter> for version info" -msgstr "¥Ð¡¼¥¸¥ç¥ó¾ðÊó¤Ï :help version7<Enter> " +msgid "type :help version8<Enter> for version info" +msgstr "¥Ð¡¼¥¸¥ç¥ó¾ðÊó¤Ï :help version8<Enter> " -#: ../version.c:784 msgid "Running in Vi compatible mode" msgstr "Vi¸ß´¹¥â¡¼¥É¤ÇưºîÃæ" -#: ../version.c:785 msgid "type :set nocp<Enter> for Vim defaults" msgstr "Vim¿ä¾©Ãͤˤ¹¤ë¤Ë¤Ï :set nocp<Enter> " -#: ../version.c:786 msgid "type :help cp-default<Enter> for info on this" msgstr "¾ÜºÙ¤Ê¾ðÊó¤Ï :help cp-default<Enter>" -#: ../version.c:827 +msgid "menu Help->Orphans for information " +msgstr "¾ÜºÙ¤Ï¥á¥Ë¥å¡¼¤Î ¥Ø¥ë¥×->¸É»ù ¤ò»²¾È¤·¤Æ²¼¤µ¤¤ " + +msgid "Running modeless, typed text is inserted" +msgstr "¥â¡¼¥É̵¤Ç¼Â¹ÔÃæ, ¥¿¥¤¥×¤·¤¿Ê¸»ú¤¬ÁÞÆþ¤µ¤ì¤Þ¤¹" + +msgid "menu Edit->Global Settings->Toggle Insert Mode " +msgstr "¥á¥Ë¥å¡¼¤Î ÊÔ½¸->Á´ÂÎÀßÄê->ÁÞÆþ(½é¿´¼Ô)¥â¡¼¥ÉÀÚÂØ " + +msgid " for two modes " +msgstr " ¤Ç¥â¡¼¥ÉÍ¤Ë " + +msgid "menu Edit->Global Settings->Toggle Vi Compatible" +msgstr "¥á¥Ë¥å¡¼¤Î ÊÔ½¸->Á´ÂÎÀßÄê->Vi¸ß´¹¥â¡¼¥ÉÀÚÂØ " + +msgid " for Vim defaults " +msgstr " ¤ÇVim¤È¤·¤ÆÆ°ºî " + msgid "Sponsor Vim development!" msgstr "Vim¤Î³«È¯¤ò±þ±ç¤·¤Æ¤¯¤À¤µ¤¤!" -#: ../version.c:828 msgid "Become a registered Vim user!" msgstr "Vim¤ÎÅÐÏ¿¥æ¡¼¥¶¡¼¤Ë¤Ê¤Ã¤Æ¤¯¤À¤µ¤¤!" -#: ../version.c:831 msgid "type :help sponsor<Enter> for information " msgstr "¾ÜºÙ¤Ê¾ðÊó¤Ï :help sponsor<Enter> " -#: ../version.c:832 msgid "type :help register<Enter> for information " msgstr "¾ÜºÙ¤Ê¾ðÊó¤Ï :help register<Enter> " -#: ../version.c:834 msgid "menu Help->Sponsor/Register for information " msgstr "¾ÜºÙ¤Ï¥á¥Ë¥å¡¼¤Î ¥Ø¥ë¥×->¥¹¥Ý¥ó¥µ¡¼/ÅÐÏ¿ ¤ò»²¾È¤·¤Æ²¼¤µ¤¤" -#: ../window.c:119 +msgid "WARNING: Windows 95/98/ME detected" +msgstr "·Ù¹ð: Windows 95/98/ME ¤ò¸¡½Ð¤·¤Þ¤·¤¿" + +msgid "type :help windows95<Enter> for info on this" +msgstr "¾ÜºÙ¤Ê¾ðÊó¤Ï :help windows95<Enter>" + msgid "Already only one window" msgstr "´û¤Ë¥¦¥£¥ó¥É¥¦¤Ï1¤Ä¤·¤«¤¢¤ê¤Þ¤»¤ó" -#: ../window.c:224 msgid "E441: There is no preview window" msgstr "E441: ¥×¥ì¥Ó¥å¡¼¥¦¥£¥ó¥É¥¦¤¬¤¢¤ê¤Þ¤»¤ó" -#: ../window.c:559 msgid "E442: Can't split topleft and botright at the same time" msgstr "E442: º¸¾å¤È±¦²¼¤òƱ»þ¤Ëʬ³ä¤¹¤ë¤³¤È¤Ï¤Ç¤¤Þ¤»¤ó" -#: ../window.c:1228 msgid "E443: Cannot rotate when another window is split" msgstr "E443: ¾¤Î¥¦¥£¥ó¥É¥¦¤¬Ê¬³ä¤µ¤ì¤Æ¤¤¤ë»þ¤Ë¤Ï½ç²ó¤Ç¤¤Þ¤»¤ó" -#: ../window.c:1803 msgid "E444: Cannot close last window" msgstr "E444: ºÇ¸å¤Î¥¦¥£¥ó¥É¥¦¤òÊĤ¸¤ë¤³¤È¤Ï¤Ç¤¤Þ¤»¤ó" -#: ../window.c:1810 msgid "E813: Cannot close autocmd window" msgstr "E813: autocmd¥¦¥£¥ó¥É¥¦¤ÏÊĤ¸¤é¤ì¤Þ¤»¤ó" -#: ../window.c:1814 msgid "E814: Cannot close window, only autocmd window would remain" msgstr "E814: autocmd¥¦¥£¥ó¥É¥¦¤·¤«»Ä¤é¤Ê¤¤¤¿¤á¡¢¥¦¥£¥ó¥É¥¦¤ÏÊĤ¸¤é¤ì¤Þ¤»¤ó" -#: ../window.c:2717 msgid "E445: Other window contains changes" msgstr "E445: ¾¤Î¥¦¥£¥ó¥É¥¦¤Ë¤ÏÊѹ¹¤¬¤¢¤ê¤Þ¤¹" -#: ../window.c:4805 msgid "E446: No file name under cursor" msgstr "E446: ¥«¡¼¥½¥ë¤Î²¼¤Ë¥Õ¥¡¥¤¥ë̾¤¬¤¢¤ê¤Þ¤»¤ó" -msgid "List or number required" -msgstr "¥ê¥¹¥È¤«¿ôÃͤ¬É¬ÍפǤ¹" - -#~ msgid "E831: bf_key_init() called with empty password" -#~ msgstr "E831: bf_key_init() ¤¬¶õ¥Ñ¥¹¥ï¡¼¥É¤Ç¸Æ¤Ó½Ð¤µ¤ì¤Þ¤·¤¿" - -#~ msgid "E820: sizeof(uint32_t) != 4" -#~ msgstr "E820: sizeof(uint32_t) != 4" - -#~ msgid "E817: Blowfish big/little endian use wrong" -#~ msgstr "E817: Blowfish°Å¹æ¤Î¥Ó¥Ã¥°/¥ê¥È¥ë¥¨¥ó¥Ç¥£¥¢¥ó¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹" - -#~ msgid "E818: sha256 test failed" -#~ msgstr "E818: sha256¤Î¥Æ¥¹¥È¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" - -#~ msgid "E819: Blowfish test failed" -#~ msgstr "E819: Blowfish°Å¹æ¤Î¥Æ¥¹¥È¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" - -#~ msgid "Patch file" -#~ msgstr "¥Ñ¥Ã¥Á¥Õ¥¡¥¤¥ë" - -#~ msgid "" -#~ "&OK\n" -#~ "&Cancel" -#~ msgstr "" -#~ "·èÄê(&O)\n" -#~ "¥¥ã¥ó¥»¥ë(&C)" - -#~ msgid "E240: No connection to Vim server" -#~ msgstr "E240: Vim ¥µ¡¼¥Ð¤Ø¤ÎÀܳ¤¬¤¢¤ê¤Þ¤»¤ó" - -#~ msgid "E241: Unable to send to %s" -#~ msgstr "E241: %s ¤ØÁ÷¤ë¤³¤È¤¬¤Ç¤¤Þ¤»¤ó" - -#~ msgid "E277: Unable to read a server reply" -#~ msgstr "E277: ¥µ¡¼¥Ð¤Î±þÅú¤¬¤¢¤ê¤Þ¤»¤ó" - -#~ msgid "E258: Unable to send to client" -#~ msgstr "E258: ¥¯¥é¥¤¥¢¥ó¥È¤ØÁ÷¤ë¤³¤È¤¬¤Ç¤¤Þ¤»¤ó" - -#~ msgid "Save As" -#~ msgstr "ÊÌ̾¤ÇÊݸ" - -#~ msgid "Edit File" -#~ msgstr "¥Õ¥¡¥¤¥ë¤òÊÔ½¸" - -# Added at 27-Jan-2004. -#~ msgid " (NOT FOUND)" -#~ msgstr " (¸«¤Ä¤«¤ê¤Þ¤»¤ó)" - -#~ msgid "Source Vim script" -#~ msgstr "Vim¥¹¥¯¥ê¥×¥È¤Î¼è¹þ¤ß" - -#~ msgid "unknown" -#~ msgstr "ÉÔÌÀ" - -#~ msgid "Edit File in new window" -#~ msgstr "¿·¤·¤¤¥¦¥£¥ó¥É¥¦¤Ç¥Õ¥¡¥¤¥ë¤òÊÔ½¸¤·¤Þ¤¹" - -#~ msgid "Append File" -#~ msgstr "Äɲåե¡¥¤¥ë" - -#~ msgid "Window position: X %d, Y %d" -#~ msgstr "¥¦¥£¥ó¥É¥¦°ÌÃÖ: X %d, Y %d" - -#~ msgid "Save Redirection" -#~ msgstr "¥ê¥À¥¤¥ì¥¯¥È¤òÊݸ¤·¤Þ¤¹" - -#~ msgid "Save View" -#~ msgstr "¥Ó¥å¡¼¤òÊݸ¤·¤Þ¤¹" - -#~ msgid "Save Session" -#~ msgstr "¥»¥Ã¥·¥ç¥ó¾ðÊó¤òÊݸ¤·¤Þ¤¹" - -#~ msgid "Save Setup" -#~ msgstr "ÀßÄê¤òÊݸ¤·¤Þ¤¹" - -#~ msgid "E809: #< is not available without the +eval feature" -#~ msgstr "E809: #< ¤Ï +eval µ¡Ç½¤¬Ìµ¤¤¤ÈÍøÍѤǤ¤Þ¤»¤ó" - -#~ msgid "E196: No digraphs in this version" -#~ msgstr "E196: ¤³¤Î¥Ð¡¼¥¸¥ç¥ó¤Ë¹ç»ú¤Ï¤¢¤ê¤Þ¤»¤ó" - -#~ msgid "is a device (disabled with 'opendevice' option)" -#~ msgstr " ¤Ï¥Ç¥Ð¥¤¥¹¤Ç¤¹ ('opendevice' ¥ª¥×¥·¥ç¥ó¤Ç²óÈò¤Ç¤¤Þ¤¹)" - -#~ msgid "Reading from stdin..." -#~ msgstr "ɸ½àÆþÎϤ«¤éÆÉ¹þ¤ßÃæ..." - -#~ msgid "[blowfish]" -#~ msgstr "[blowfish°Å¹æ²½]" - -#~ msgid "[crypted]" -#~ msgstr "[°Å¹æ²½]" - -#~ msgid "E821: File is encrypted with unknown method" -#~ msgstr "E821: ¥Õ¥¡¥¤¥ë¤¬Ì¤ÃΤÎÊýË¡¤Ç°Å¹æ²½¤µ¤ì¤Æ¤¤¤Þ¤¹" - -# Added at 19-Jan-2004. -#~ msgid "NetBeans disallows writes of unmodified buffers" -#~ msgstr "NetBeans¤Ï̤Êѹ¹¤Î¥Ð¥Ã¥Õ¥¡¤ò¾å½ñ¤¹¤ë¤³¤È¤Ïµö²Ä¤·¤Æ¤¤¤Þ¤»¤ó" - -#~ msgid "Partial writes disallowed for NetBeans buffers" -#~ msgstr "NetBeans¥Ð¥Ã¥Õ¥¡¤Î°ìÉô¤ò½ñ¤½Ð¤¹¤³¤È¤Ï¤Ç¤¤Þ¤»¤ó" - -#~ msgid "writing to device disabled with 'opendevice' option" -#~ msgstr "'opendevice' ¥ª¥×¥·¥ç¥ó¤Ë¤è¤ê¥Ç¥Ð¥¤¥¹¤Ø¤Î½ñ¤¹þ¤ß¤Ï¤Ç¤¤Þ¤»¤ó" - -#~ msgid "E460: The resource fork would be lost (add ! to override)" -#~ msgstr "E460: ¥ê¥½¡¼¥¹¥Õ¥©¡¼¥¯¤¬¼º¤ï¤ì¤ë¤«¤â¤·¤ì¤Þ¤»¤ó (! ¤òÄɲäǶ¯À©)" - -#~ msgid "E851: Failed to create a new process for the GUI" -#~ msgstr "E851: GUIÍÑ¤Î¥×¥í¥»¥¹¤Îµ¯Æ°¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" - -#~ msgid "E852: The child process failed to start the GUI" -#~ msgstr "E852: »Ò¥×¥í¥»¥¹¤¬GUI¤Îµ¯Æ°¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" - -#~ msgid "E229: Cannot start the GUI" -#~ msgstr "E229: GUI¤ò³«»Ï¤Ç¤¤Þ¤»¤ó" - -#~ msgid "E230: Cannot read from \"%s\"" -#~ msgstr "E230: \"%s\"¤«¤éÆÉ¹þ¤à¤³¤È¤¬¤Ç¤¤Þ¤»¤ó" - -#~ msgid "E665: Cannot start GUI, no valid font found" -#~ msgstr "E665: ͸ú¤Ê¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤¤¤Î¤Ç, GUI¤ò³«»Ï¤Ç¤¤Þ¤»¤ó" - -#~ msgid "E231: 'guifontwide' invalid" -#~ msgstr "E231: 'guifontwide' ¤¬Ìµ¸ú¤Ç¤¹" - -#~ msgid "E599: Value of 'imactivatekey' is invalid" -#~ msgstr "E599: 'imactivatekey' ¤ËÀßÄꤵ¤ì¤¿Ãͤ¬Ìµ¸ú¤Ç¤¹" - -#~ msgid "E254: Cannot allocate color %s" -#~ msgstr "E254: %s ¤Î¿§¤ò³ä¤êÅö¤Æ¤é¤ì¤Þ¤»¤ó" - -#~ msgid "No match at cursor, finding next" -#~ msgstr "¥«¡¼¥½¥ë¤Î°ÌÃ֤˥ޥåÁ¤Ï¤¢¤ê¤Þ¤»¤ó, ¼¡¤ò¸¡º÷¤·¤Æ¤¤¤Þ¤¹" - -#~ msgid "<cannot open> " -#~ msgstr "<³«¤±¤Þ¤»¤ó> " - -#~ msgid "E616: vim_SelFile: can't get font %s" -#~ msgstr "E616: vim_SelFile: ¥Õ¥©¥ó¥È %s ¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó" - -#~ msgid "E614: vim_SelFile: can't return to current directory" -#~ msgstr "E614: vim_SelFile: ¸½ºß¤Î¥Ç¥£¥ì¥¯¥È¥ê¤ËÌá¤ì¤Þ¤»¤ó" - -#~ msgid "Pathname:" -#~ msgstr "¥Ñ¥¹Ì¾:" - -#~ msgid "E615: vim_SelFile: can't get current directory" -#~ msgstr "E615: vim_SelFile: ¸½ºß¤Î¥Ç¥£¥ì¥¯¥È¥ê¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó" - -#~ msgid "OK" -#~ msgstr "OK" - -#~ msgid "Cancel" -#~ msgstr "¥¥ã¥ó¥»¥ë" - -#~ msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." -#~ msgstr "¥¹¥¯¥í¡¼¥ë¥Ð¡¼: ²èÁü¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿." - -#~ msgid "Vim dialog" -#~ msgstr "Vim ¥À¥¤¥¢¥í¥°" - -#~ msgid "E232: Cannot create BalloonEval with both message and callback" -#~ msgstr "E232: ¥á¥Ã¥»¡¼¥¸¤È¥³¡¼¥ë¥Ð¥Ã¥¯¤Î¤¢¤ë BalloonEval ¤òºîÀ®¤Ç¤¤Þ¤»¤ó" - -#~ msgid "Input _Methods" -#~ msgstr "¥¤¥ó¥×¥Ã¥È¥á¥½¥Ã¥É" - -#~ msgid "VIM - Search and Replace..." -#~ msgstr "VIM - ¸¡º÷¤ÈÃÖ´¹..." - -#~ msgid "VIM - Search..." -#~ msgstr "VIM - ¸¡º÷..." - -#~ msgid "Find what:" -#~ msgstr "¸¡º÷ʸ»úÎó:" - -#~ msgid "Replace with:" -#~ msgstr "ÃÖ´¹Ê¸»úÎó:" - -#~ msgid "Match whole word only" -#~ msgstr "Àµ³Î¤Ë³ºÅö¤¹¤ë¤â¤Î¤À¤±" - -#~ msgid "Match case" -#~ msgstr "Âçʸ»ú/¾®Ê¸»ú¤ò¶èÊ̤¹¤ë" - -#~ msgid "Direction" -#~ msgstr "Êý¸þ" - -#~ msgid "Up" -#~ msgstr "¾å" - -#~ msgid "Down" -#~ msgstr "²¼" - -#~ msgid "Find Next" -#~ msgstr "¼¡¤ò¸¡º÷" - -#~ msgid "Replace" -#~ msgstr "ÃÖ´¹" - -#~ msgid "Replace All" -#~ msgstr "Á´¤ÆÃÖ´¹" - -#~ msgid "Vim: Received \"die\" request from session manager\n" -#~ msgstr "Vim: ¥»¥Ã¥·¥ç¥ó¥Þ¥Í¡¼¥¸¥ã¤«¤é \"die\" Í×µá¤ò¼õ¤±¼è¤ê¤Þ¤·¤¿\n" - -#~ msgid "Close" -#~ msgstr "ÊĤ¸¤ë" - -#~ msgid "New tab" -#~ msgstr "¿·µ¬¥¿¥Ö¥Ú¡¼¥¸" - -#~ msgid "Open Tab..." -#~ msgstr "¥¿¥Ö¥Ú¡¼¥¸¤ò³«¤¯..." - -#~ msgid "Vim: Main window unexpectedly destroyed\n" -#~ msgstr "Vim: ¥á¥¤¥ó¥¦¥£¥ó¥É¥¦¤¬ÉÔ°Õ¤ËÇ˲õ¤µ¤ì¤Þ¤·¤¿\n" - -#~ msgid "&Filter" -#~ msgstr "¥Õ¥£¥ë¥¿(&F)" - -#~ msgid "&Cancel" -#~ msgstr "¥¥ã¥ó¥»¥ë(&C)" - -#~ msgid "Directories" -#~ msgstr "¥Ç¥£¥ì¥¯¥È¥ê" - -#~ msgid "Filter" -#~ msgstr "¥Õ¥£¥ë¥¿" - -#~ msgid "&Help" -#~ msgstr "¥Ø¥ë¥×(&H)" - -#~ msgid "Files" -#~ msgstr "¥Õ¥¡¥¤¥ë" - -#~ msgid "&OK" -#~ msgstr "&OK" - -#~ msgid "Selection" -#~ msgstr "ÁªÂò" - -#~ msgid "Find &Next" -#~ msgstr "¼¡¤ò¸¡º÷(&N)" - -#~ msgid "&Replace" -#~ msgstr "ÃÖ´¹(&R)" - -#~ msgid "Replace &All" -#~ msgstr "Á´¤ÆÃÖ´¹(&A)" - -#~ msgid "&Undo" -#~ msgstr "¥¢¥ó¥É¥¥(&U)" - -#~ msgid "E671: Cannot find window title \"%s\"" -#~ msgstr "E671: ¥¿¥¤¥È¥ë¤¬ \"%s\" ¤Î¥¦¥£¥ó¥É¥¦¤Ï¸«¤Ä¤«¤ê¤Þ¤»¤ó" - -#~ msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." -#~ msgstr "E243: °ú¿ô¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó: \"-%s\"; OLEÈǤò»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤." - -#~ msgid "E672: Unable to open window inside MDI application" -#~ msgstr "E672: MDI¥¢¥×¥ê¤ÎÃæ¤Ç¤Ï¥¦¥£¥ó¥É¥¦¤ò³«¤±¤Þ¤»¤ó" - -#~ msgid "Close tab" -#~ msgstr "¥¿¥Ö¥Ú¡¼¥¸¤òÊĤ¸¤ë" - -#~ msgid "Open tab..." -#~ msgstr "¥¿¥Ö¥Ú¡¼¥¸¤ò³«¤¯" - -#~ msgid "Find string (use '\\\\' to find a '\\')" -#~ msgstr "¸¡º÷ʸ»úÎó ('\\' ¤ò¸¡º÷¤¹¤ë¤Ë¤Ï '\\\\')" - -#~ msgid "Find & Replace (use '\\\\' to find a '\\')" -#~ msgstr "¸¡º÷¡¦ÃÖ´¹ ('\\' ¤ò¸¡º÷¤¹¤ë¤Ë¤Ï '\\\\')" - -#~ msgid "Not Used" -#~ msgstr "»È¤ï¤ì¤Þ¤»¤ó" - -#~ msgid "Directory\t*.nothing\n" -#~ msgstr "¥Ç¥£¥ì¥¯¥È¥ê\t*.nothing\n" - -#~ msgid "" -#~ "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" -#~ msgstr "Vim E458: ¿§»ØÄ꤬Àµ¤·¤¯¤Ê¤¤¤Î¤Ç¥¨¥ó¥È¥ê¤ò³ä¤êÅö¤Æ¤é¤ì¤Þ¤»¤ó" - -#~ msgid "E250: Fonts for the following charsets are missing in fontset %s:" -#~ msgstr "E250: °Ê²¼¤Îʸ»ú¥»¥Ã¥È¤Î¥Õ¥©¥ó¥È¤¬¤¢¤ê¤Þ¤»¤ó %s:" - -#~ msgid "E252: Fontset name: %s" -#~ msgstr "E252: ¥Õ¥©¥ó¥È¥»¥Ã¥È̾: %s" - -#~ msgid "Font '%s' is not fixed-width" -#~ msgstr "¥Õ¥©¥ó¥È '%s' ¤Ï¸ÇÄêÉý¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó" - -#~ msgid "E253: Fontset name: %s" -#~ msgstr "E253: ¥Õ¥©¥ó¥È¥»¥Ã¥È̾: %s" - -#~ msgid "Font0: %s" -#~ msgstr "¥Õ¥©¥ó¥È0: %s" - -#~ msgid "Font1: %s" -#~ msgstr "¥Õ¥©¥ó¥È1: %s" - -#~ msgid "Font%<PRId64> width is not twice that of font0" -#~ msgstr "¥Õ¥©¥ó¥È%<PRId64> ¤ÎÉý¤¬¥Õ¥©¥ó¥È0¤Î2ÇܤǤϤ¢¤ê¤Þ¤»¤ó" - -#~ msgid "Font0 width: %<PRId64>" -#~ msgstr "¥Õ¥©¥ó¥È0¤ÎÉý: %<PRId64>" - -#~ msgid "Font1 width: %<PRId64>" -#~ msgstr "¥Õ¥©¥ó¥È1¤ÎÉý: %<PRId64>" - -#~ msgid "Invalid font specification" -#~ msgstr "̵¸ú¤Ê¥Õ¥©¥ó¥È»ØÄê¤Ç¤¹" - -#~ msgid "&Dismiss" -#~ msgstr "µÑ²¼¤¹¤ë(&D)" - -#~ msgid "no specific match" -#~ msgstr "¥Þ¥Ã¥Á¤¹¤ë¤â¤Î¤¬¤¢¤ê¤Þ¤»¤ó" - -#~ msgid "Vim - Font Selector" -#~ msgstr "Vim - ¥Õ¥©¥ó¥ÈÁªÂò" - -#~ msgid "Name:" -#~ msgstr "̾Á°:" - -#~ msgid "Show size in Points" -#~ msgstr "¥µ¥¤¥º¤ò¥Ý¥¤¥ó¥È¤Çɽ¼¨¤¹¤ë" - -#~ msgid "Encoding:" -#~ msgstr "¥¨¥ó¥³¡¼¥É:" - -#~ msgid "Font:" -#~ msgstr "¥Õ¥©¥ó¥È:" - -#~ msgid "Style:" -#~ msgstr "¥¹¥¿¥¤¥ë:" - -#~ msgid "Size:" -#~ msgstr "¥µ¥¤¥º:" - -#~ msgid "E256: Hangul automata ERROR" -#~ msgstr "E256: ¥Ï¥ó¥°¥ë¥ª¡¼¥È¥Þ¥È¥ó¥¨¥é¡¼" - -#~ msgid "E563: stat error" -#~ msgstr "E563: stat ¥¨¥é¡¼" - -#~ msgid "E625: cannot open cscope database: %s" -#~ msgstr "E625: cscope¥Ç¡¼¥¿¥Ù¡¼¥¹: %s ¤ò³«¤¯¤³¤È¤¬¤Ç¤¤Þ¤»¤ó" - -#~ msgid "E626: cannot get cscope database information" -#~ msgstr "E626: cscope¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¾ðÊó¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó" - -#~ msgid "Lua library cannot be loaded." -#~ msgstr "Lua¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤Ç¤¤Þ¤»¤ó." - -#~ msgid "cannot save undo information" -#~ msgstr "¥¢¥ó¥É¥¥¾ðÊó¤¬Êݸ¤Ç¤¤Þ¤»¤ó" - -#~ msgid "" -#~ "E815: Sorry, this command is disabled, the MzScheme libraries could not " -#~ "be loaded." -#~ msgstr "" -#~ "E815: ¤³¤Î¥³¥Þ¥ó¥É¤Ï̵¸ú¤Ç¤¹. MzScheme ¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤Ç¤¤Þ¤»¤ó." - -#~ msgid "invalid expression" -#~ msgstr "̵¸ú¤Ê¼°¤Ç¤¹" - -#~ msgid "expressions disabled at compile time" -#~ msgstr "¼°¤Ï¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹" - -#~ msgid "hidden option" -#~ msgstr "±£¤·¥ª¥×¥·¥ç¥ó" - -#~ msgid "unknown option" -#~ msgstr "̤ÃΤΥª¥×¥·¥ç¥ó¤Ç¤¹" - -#~ msgid "window index is out of range" -#~ msgstr "Èϰϳ°¤Î¥¦¥£¥ó¥É¥¦ÈÖ¹æ¤Ç¤¹" - -#~ msgid "couldn't open buffer" -#~ msgstr "¥Ð¥Ã¥Õ¥¡¤ò³«¤±¤Þ¤»¤ó" - -#~ msgid "cannot delete line" -#~ msgstr "¹Ô¤ò¾Ã¤»¤Þ¤»¤ó" - -#~ msgid "cannot replace line" -#~ msgstr "¹Ô¤òÃÖ´¹¤Ç¤¤Þ¤»¤ó" - -#~ msgid "cannot insert line" -#~ msgstr "¹Ô¤òÁÞÆþ¤Ç¤¤Þ¤»¤ó" - -#~ msgid "string cannot contain newlines" -#~ msgstr "ʸ»úÎó¤Ë¤Ï²þ¹Ôʸ»ú¤ò´Þ¤á¤é¤ì¤Þ¤»¤ó" - -#~ msgid "error converting Scheme values to Vim" -#~ msgstr "SchemeÃͤÎVim¤Ø¤ÎÊÑ´¹¥¨¥é¡¼" - -#~ msgid "Vim error: ~a" -#~ msgstr "Vim ¥¨¥é¡¼: ~a" - -#~ msgid "Vim error" -#~ msgstr "Vim ¥¨¥é¡¼" - -#~ msgid "buffer is invalid" -#~ msgstr "¥Ð¥Ã¥Õ¥¡¤Ï̵¸ú¤Ç¤¹" - -#~ msgid "window is invalid" -#~ msgstr "¥¦¥£¥ó¥É¥¦¤Ï̵¸ú¤Ç¤¹" - -#~ msgid "linenr out of range" -#~ msgstr "Èϰϳ°¤Î¹ÔÈÖ¹æ¤Ç¤¹" - -#~ msgid "not allowed in the Vim sandbox" -#~ msgstr "¥µ¥ó¥É¥Ü¥Ã¥¯¥¹¤Ç¤Ïµö¤µ¤ì¤Þ¤»¤ó" - -#~ msgid "E370: Could not load library %s" -#~ msgstr "E370: ¥é¥¤¥Ö¥é¥ê %s ¤ò¥í¡¼¥É¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" - -#~ msgid "" -#~ "Sorry, this command is disabled: the Perl library could not be loaded." -#~ msgstr "" -#~ "¤³¤Î¥³¥Þ¥ó¥É¤Ï̵¸ú¤Ç¤¹, ¤´¤á¤ó¤Ê¤µ¤¤: Perl¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤Ç¤¤Þ¤»¤ó¤Ç¤·" -#~ "¤¿." - -#~ msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" -#~ msgstr "" -#~ "E299: ¥µ¥ó¥É¥Ü¥Ã¥¯¥¹¤Ç¤Ï Safe ¥â¥¸¥å¡¼¥ë¤ò»ÈÍѤ·¤Ê¤¤Perl¥¹¥¯¥ê¥×¥È¤Ï¶Ø¤¸¤é" -#~ "¤ì¤Æ¤¤¤Þ¤¹" - -#~ msgid "E836: This Vim cannot execute :python after using :py3" -#~ msgstr "E836: ¤³¤ÎVim¤Ç¤Ï :py3 ¤ò»È¤Ã¤¿¸å¤Ë :python ¤ò»È¤¨¤Þ¤»¤ó" - -#~ msgid "" -#~ "E263: Sorry, this command is disabled, the Python library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E263: ¤³¤Î¥³¥Þ¥ó¥É¤Ï̵¸ú¤Ç¤¹,¤´¤á¤ó¤Ê¤µ¤¤: Python¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤Ç¤¤Þ" -#~ "¤»¤ó¤Ç¤·¤¿." - -# Added at 07-Feb-2004. -#~ msgid "E659: Cannot invoke Python recursively" -#~ msgstr "E659: Python ¤òºÆµ¢Åª¤Ë¼Â¹Ô¤¹¤ë¤³¤È¤Ï¤Ç¤¤Þ¤»¤ó" - -#~ msgid "E837: This Vim cannot execute :py3 after using :python" -#~ msgstr "E837: ¤³¤ÎVim¤Ç¤Ï :python ¤ò»È¤Ã¤¿¸å¤Ë :py3 ¤ò»È¤¨¤Þ¤»¤ó" - -#~ msgid "E265: $_ must be an instance of String" -#~ msgstr "E265: $_ ¤Ïʸ»úÎó¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" - -#~ msgid "" -#~ "E266: Sorry, this command is disabled, the Ruby library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E266: ¤³¤Î¥³¥Þ¥ó¥É¤Ï̵¸ú¤Ç¤¹,¤´¤á¤ó¤Ê¤µ¤¤: Ruby¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤Ç¤¤Þ¤»" -#~ "¤ó¤Ç¤·¤¿." - -#~ msgid "E267: unexpected return" -#~ msgstr "E267: ͽ´ü¤»¤Ì return ¤Ç¤¹" - -#~ msgid "E268: unexpected next" -#~ msgstr "E268: ͽ´ü¤»¤Ì next ¤Ç¤¹" - -#~ msgid "E269: unexpected break" -#~ msgstr "E269: ͽ´ü¤»¤Ì break ¤Ç¤¹" - -#~ msgid "E270: unexpected redo" -#~ msgstr "E270: ͽ´ü¤»¤Ì redo ¤Ç¤¹" - -#~ msgid "E271: retry outside of rescue clause" -#~ msgstr "E271: rescue ¤Î³°¤Î retry ¤Ç¤¹" - -#~ msgid "E272: unhandled exception" -#~ msgstr "E272: ¼è¤ê°·¤ï¤ì¤Ê¤«¤Ã¤¿Îã³°¤¬¤¢¤ê¤Þ¤¹" - -#~ msgid "E273: unknown longjmp status %d" -#~ msgstr "E273: ̤ÃΤÎlongjmp¾õÂÖ: %d" - -#~ msgid "Toggle implementation/definition" -#~ msgstr "¼ÂÁõ¤ÈÄêµÁ¤òÀÚ¤êÂØ¤¨¤ë" - -#~ msgid "Show base class of" -#~ msgstr "¼¡¤Î¥¯¥é¥¹¤Î´ðÄì¤òɽ¼¨" - -#~ msgid "Show overridden member function" -#~ msgstr "¥ª¡¼¥Ð¡¼¥é¥¤¥É¤µ¤ì¤¿¥á¥ó¥Ð´Ø¿ô¤òɽ¼¨" - -#~ msgid "Retrieve from file" -#~ msgstr "¥Õ¥¡¥¤¥ë¤«¤é²óÉü¤¹¤ë" - -#~ msgid "Retrieve from project" -#~ msgstr "¥×¥í¥¸¥§¥¯¥È¤«¤é²óÉü¤¹¤ë" - -#~ msgid "Retrieve from all projects" -#~ msgstr "Á´¤Æ¤Î¥×¥í¥¸¥§¥¯¥È¤«¤é²óÉü¤¹¤ë" - -#~ msgid "Retrieve" -#~ msgstr "²óÉü" - -#~ msgid "Show source of" -#~ msgstr "¼¡¤Î¥½¡¼¥¹¤òɽ¼¨¤¹¤ë" - -#~ msgid "Find symbol" -#~ msgstr "¸«¤Ä¤±¤¿¥·¥ó¥Ü¥ë" - -#~ msgid "Browse class" -#~ msgstr "¥¯¥é¥¹¤ò»²¾È" - -#~ msgid "Show class in hierarchy" -#~ msgstr "³¬Áؤǥ¯¥é¥¹¤òɽ¼¨" - -#~ msgid "Show class in restricted hierarchy" -#~ msgstr "¸ÂÄꤵ¤ì¤¿³¬Áؤǥ¯¥é¥¹¤òɽ¼¨" - -#~ msgid "Xref refers to" -#~ msgstr "Xref ¤Î»²¾ÈÀè" - -#~ msgid "Xref referred by" -#~ msgstr "Xref ¤¬»²¾È¤µ¤ì¤ë" - -#~ msgid "Xref has a" -#~ msgstr "Xref ¤¬¼¡¤Î¤â¤Î¤ò¤â¤Ã¤Æ¤¤¤Þ¤¹" - -#~ msgid "Xref used by" -#~ msgstr "Xref ¤¬»ÈÍѤµ¤ì¤ë" - -#~ msgid "Show docu of" -#~ msgstr "¼¡¤Îʸ¾Ï¤òɽ¼¨" - -#~ msgid "Generate docu for" -#~ msgstr "¼¡¤Îʸ¾Ï¤òÀ¸À®" - -#~ msgid "" -#~ "Cannot connect to SNiFF+. Check environment (sniffemacs must be found in " -#~ "$PATH).\n" -#~ msgstr "" -#~ "SNiFF+¤ËÀܳ¤Ç¤¤Þ¤»¤ó. ´Ä¶¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤(sniffemacs ¤¬ $PATH ¤Ë" -#~ "¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó).\n" - -#~ msgid "E274: Sniff: Error during read. Disconnected" -#~ msgstr "E274: Sniff: ÆÉ¹þÃæ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤Þ¤·¤¿. ÀÚÃǤ·¤Þ¤·¤¿" - -#~ msgid "SNiFF+ is currently " -#~ msgstr "¸½ºßSNiFF+ ¤Î¾õÂ֤ϡÖ" - -#~ msgid "not " -#~ msgstr "̤" - -#~ msgid "connected" -#~ msgstr "Àܳ¡×¤Ç¤¹" - -#~ msgid "E275: Unknown SNiFF+ request: %s" -#~ msgstr "E275: ̤ÃΤΠSNiFF+ ¥ê¥¯¥¨¥¹¥È¤Ç¤¹: %s" - -#~ msgid "E276: Error connecting to SNiFF+" -#~ msgstr "E276: SNiFF+ ¤Ø¤ÎÀÜÂ³Ãæ¤Î¥¨¥é¡¼¤Ç¤¹" - -#~ msgid "E278: SNiFF+ not connected" -#~ msgstr "E278: SNiFF+ ¤ËÀܳ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" - -#~ msgid "E279: Not a SNiFF+ buffer" -#~ msgstr "E279: SNiFF+ ¥Ð¥Ã¥Õ¥¡¤¬¤¢¤ê¤Þ¤»¤ó" - -#~ msgid "Sniff: Error during write. Disconnected" -#~ msgstr "Sniff: ½ñ¹þ¤ßÃæ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤¿¤Î¤ÇÀÚÃǤ·¤Þ¤·¤¿" - -#~ msgid "invalid buffer number" -#~ msgstr "̵¸ú¤Ê¥Ð¥Ã¥Õ¥¡ÈÖ¹æ¤Ç¤¹" - -#~ msgid "not implemented yet" -#~ msgstr "¤Þ¤À¼ÂÁõ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" - -#~ msgid "cannot set line(s)" -#~ msgstr "¹Ô¤òÀßÄê¤Ç¤¤Þ¤»¤ó" - -#~ msgid "invalid mark name" -#~ msgstr "̵¸ú¤Ê¥Þ¡¼¥¯Ì¾¤Ç¤¹" - -#~ msgid "mark not set" -#~ msgstr "¥Þ¡¼¥¯¤ÏÀßÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó" - -#~ msgid "row %d column %d" -#~ msgstr "¹Ô %d Îó %d" - -#~ msgid "cannot insert/append line" -#~ msgstr "¹Ô¤ÎÁÞÆþ/Äɲäò¤Ç¤¤Þ¤»¤ó" - -#~ msgid "line number out of range" -#~ msgstr "Èϰϳ°¤Î¹ÔÈÖ¹æ¤Ç¤¹" - -#~ msgid "unknown flag: " -#~ msgstr "̤ÃΤΥե饰: " - -#~ msgid "unknown vimOption" -#~ msgstr "̤ÃΤΠvimOption ¤Ç¤¹" - -#~ msgid "keyboard interrupt" -#~ msgstr "¥¡¼¥Ü¡¼¥É³ä¹þ¤ß" - -#~ msgid "vim error" -#~ msgstr "vim ¥¨¥é¡¼" - -#~ msgid "cannot create buffer/window command: object is being deleted" -#~ msgstr "" -#~ "¥Ð¥Ã¥Õ¥¡/¥¦¥£¥ó¥É¥¦ºîÀ®¥³¥Þ¥ó¥É¤òºîÀ®¤Ç¤¤Þ¤»¤ó: ¥ª¥Ö¥¸¥§¥¯¥È¤¬¾Ãµî¤µ¤ì¤Æ" -#~ "¤¤¤Þ¤·¤¿" - -#~ msgid "" -#~ "cannot register callback command: buffer/window is already being deleted" -#~ msgstr "" -#~ "¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥É¤òÅÐÏ¿¤Ç¤¤Þ¤»¤ó: ¥Ð¥Ã¥Õ¥¡/¥¦¥£¥ó¥É¥¦¤¬´û¤Ë¾Ãµî¤µ¤ì¤Þ" -#~ "¤·¤¿" - -#~ msgid "" -#~ "E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-" -#~ "dev@vim.org" -#~ msgstr "" -#~ "E280: TCL Ã×̿Ū¥¨¥é¡¼: reflist ±øÀ÷!? vim-dev@vim.org ¤ËÊó¹ð¤·¤Æ¤¯¤À¤µ¤¤" - -#~ msgid "cannot register callback command: buffer/window reference not found" -#~ msgstr "" -#~ "¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥É¤òÅÐÏ¿¤Ç¤¤Þ¤»¤ó: ¥Ð¥Ã¥Õ¥¡/¥¦¥£¥ó¥É¥¦¤Î»²¾È¤¬¸«¤Ä¤«¤ê" -#~ "¤Þ¤»¤ó" - -#~ msgid "" -#~ "E571: Sorry, this command is disabled: the Tcl library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E571: ¤³¤Î¥³¥Þ¥ó¥É¤Ï̵¸ú¤Ç¤¹,¤´¤á¤ó¤Ê¤µ¤¤: Tcl¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤Ç¤¤Þ¤»¤ó" -#~ "¤Ç¤·¤¿." - -#~ msgid "E572: exit code %d" -#~ msgstr "E572: ½ªÎ»¥³¡¼¥É %d" - -#~ msgid "cannot get line" -#~ msgstr "¹Ô¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó" - -#~ msgid "Unable to register a command server name" -#~ msgstr "Ì¿Î᥵¡¼¥Ð¤Î̾Á°¤òÅÐÏ¿¤Ç¤¤Þ¤»¤ó" - -#~ msgid "E248: Failed to send command to the destination program" -#~ msgstr "E248: ÌÜŪ¤Î¥×¥í¥°¥é¥à¤Ø¤Î¥³¥Þ¥ó¥ÉÁ÷¿®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" - -#~ msgid "E573: Invalid server id used: %s" -#~ msgstr "E573: ̵¸ú¤Ê¥µ¡¼¥ÐID¤¬»È¤ï¤ì¤Þ¤·¤¿: %s" - -#~ msgid "E251: VIM instance registry property is badly formed. Deleted!" -#~ msgstr "E251: VIM ¼ÂÂΤÎÅÐÏ¿¥×¥í¥Ñ¥Æ¥£¤¬ÉÔÀµ¤Ç¤¹. ¾Ãµî¤·¤Þ¤·¤¿!" - -#~ msgid "netbeans is not supported with this GUI\n" -#~ msgstr "netbeans ¤Ï¤³¤ÎGUI¤Ç¤ÏÍøÍѤǤ¤Þ¤»¤ó\n" - -#~ msgid "This Vim was not compiled with the diff feature." -#~ msgstr "¤³¤ÎVim¤Ë¤Ïdiffµ¡Ç½¤¬¤¢¤ê¤Þ¤»¤ó(¥³¥ó¥Ñ¥¤¥ë»þÀßÄê)." - -#~ msgid "'-nb' cannot be used: not enabled at compile time\n" -#~ msgstr "'-nb' »ÈÍÑÉÔ²Äǽ¤Ç¤¹: ¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹\n" - -#~ msgid "Vim: Error: Failure to start gvim from NetBeans\n" -#~ msgstr "Vim: ¥¨¥é¡¼: NetBeans¤«¤égvim¤ò¥¹¥¿¡¼¥È¤Ç¤¤Þ¤»¤ó\n" - -#~ msgid "" -#~ "\n" -#~ "Where case is ignored prepend / to make flag upper case" -#~ msgstr "" -#~ "\n" -#~ "Â羮ʸ»ú¤¬Ìµ»ë¤µ¤ì¤ë¾ì¹ç¤ÏÂçʸ»ú¤Ë¤¹¤ë¤¿¤á¤Ë / ¤òÁ°ÃÖ¤·¤Æ¤¯¤À¤µ¤¤" - -#~ msgid "-register\t\tRegister this gvim for OLE" -#~ msgstr "-register\t\t¤³¤Îgvim¤òOLE¤È¤·¤ÆÅÐÏ¿¤¹¤ë" - -#~ msgid "-unregister\t\tUnregister gvim for OLE" -#~ msgstr "-unregister\t\tgvim¤ÎOLEÅÐÏ¿¤ò²ò½ü¤¹¤ë" - -#~ msgid "-g\t\t\tRun using GUI (like \"gvim\")" -#~ msgstr "-g\t\t\tGUI¤Çµ¯Æ°¤¹¤ë (\"gvim\" ¤ÈƱ¤¸)" - -#~ msgid "-f or --nofork\tForeground: Don't fork when starting GUI" -#~ msgstr "-f or --nofork\t¥Õ¥©¥¢¥°¥é¥¦¥ó¥É: GUI¤ò»Ï¤á¤ë¤È¤¤Ëfork¤·¤Ê¤¤" - -#~ msgid "-f\t\t\tDon't use newcli to open window" -#~ msgstr "-f\t\t\t¥¦¥£¥ó¥É¥¦¤ò³«¤¯¤Î¤Ë newcli ¤ò»ÈÍѤ·¤Ê¤¤" - -#~ msgid "-dev <device>\t\tUse <device> for I/O" -#~ msgstr "-dev <device>\t\tI/O¤Ë <device> ¤ò»ÈÍѤ¹¤ë" - -#~ msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" -#~ msgstr "-U <gvimrc>\t\t.gvimrc¤ÎÂå¤ï¤ê¤Ë <gvimrc> ¤ò»È¤¦" - -#~ msgid "-x\t\t\tEdit encrypted files" -#~ msgstr "-x\t\t\t°Å¹æ²½¤µ¤ì¤¿¥Õ¥¡¥¤¥ë¤òÊÔ½¸¤¹¤ë" - -#~ msgid "-display <display>\tConnect vim to this particular X-server" -#~ msgstr "-display <display>\tvim¤ò»ØÄꤷ¤¿ X ¥µ¡¼¥Ð¤ËÀܳ¤¹¤ë" - -#~ msgid "-X\t\t\tDo not connect to X server" -#~ msgstr "-X\t\t\tX¥µ¡¼¥Ð¤ËÀܳ¤·¤Ê¤¤" - -#~ msgid "--remote <files>\tEdit <files> in a Vim server if possible" -#~ msgstr "--remote <files>\t²Äǽ¤Ê¤é¤ÐVim¥µ¡¼¥Ð¤Ç <files> ¤òÊÔ½¸¤¹¤ë" - -#~ msgid "--remote-silent <files> Same, don't complain if there is no server" -#~ msgstr "--remote-silent <files> Ʊ¾å, ¥µ¡¼¥Ð¤¬Ìµ¤¯¤Æ¤â·Ù¹ðʸ¤ò½ÐÎϤ·¤Ê¤¤" - -#~ msgid "" -#~ "--remote-wait <files> As --remote but wait for files to have been edited" -#~ msgstr "--remote-wait <files>\t--remote¸å ¥Õ¥¡¥¤¥ë¤ÎÊÔ½¸¤¬½ª¤ï¤ë¤Î¤òÂÔ¤Ä" - -#~ msgid "" -#~ "--remote-wait-silent <files> Same, don't complain if there is no server" -#~ msgstr "" -#~ "--remote-wait-silent <files> Ʊ¾å, ¥µ¡¼¥Ð¤¬Ìµ¤¯¤Æ¤â·Ù¹ðʸ¤ò½ÐÎϤ·¤Ê¤¤" - -#~ msgid "" -#~ "--remote-tab[-wait][-silent] <files> As --remote but use tab page per " -#~ "file" -#~ msgstr "" -#~ "--remote-tab[-wait][-silent] <files> --remote¤Ç¥Õ¥¡¥¤¥ë1¤Ä¤Ë¤Ä¤1¤Ä¤Î¥¿¥Ö" -#~ "¥Ú¡¼¥¸¤ò³«¤¯" - -#~ msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" -#~ msgstr "--remote-send <keys>\tVim¥µ¡¼¥Ð¤Ë <keys> ¤òÁ÷¿®¤·¤Æ½ªÎ»¤¹¤ë" - -#~ msgid "" -#~ "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" -#~ msgstr "--remote-expr <expr>\t¥µ¡¼¥Ð¤Ç <expr> ¤ò¼Â¹Ô¤·¤Æ·ë²Ì¤òɽ¼¨¤¹¤ë" - -#~ msgid "--serverlist\t\tList available Vim server names and exit" -#~ msgstr "--serverlist\t\tVim¥µ¡¼¥Ð̾¤Î°ìÍ÷¤òɽ¼¨¤·¤Æ½ªÎ»¤¹¤ë" - -#~ msgid "--servername <name>\tSend to/become the Vim server <name>" -#~ msgstr "--servername <name>\tVim¥µ¡¼¥Ð <name> ¤ËÁ÷¿®/̾Á°ÀßÄꤹ¤ë" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (Motif version):\n" -#~ msgstr "" -#~ "\n" -#~ "gvim¤Ë¤è¤Ã¤Æ²ò¼á¤µ¤ì¤ë°ú¿ô(Motif¥Ð¡¼¥¸¥ç¥ó):\n" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (neXtaw version):\n" -#~ msgstr "" -#~ "\n" -#~ "gvim¤Ë¤è¤Ã¤Æ²ò¼á¤µ¤ì¤ë°ú¿ô(neXtaw¥Ð¡¼¥¸¥ç¥ó):\n" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (Athena version):\n" -#~ msgstr "" -#~ "\n" -#~ "gvim¤Ë¤è¤Ã¤Æ²ò¼á¤µ¤ì¤ë°ú¿ô(Athena¥Ð¡¼¥¸¥ç¥ó):\n" - -#~ msgid "-display <display>\tRun vim on <display>" -#~ msgstr "-display <display>\t<display> ¤Çvim¤ò¼Â¹Ô¤¹¤ë" - -#~ msgid "-iconic\t\tStart vim iconified" -#~ msgstr "-iconic\t\tºÇ¾®²½¤·¤¿¾õÂÖ¤Çvim¤òµ¯Æ°¤¹¤ë" - -#~ msgid "-background <color>\tUse <color> for the background (also: -bg)" -#~ msgstr "-background <color>\tÇØ·Ê¿§¤Ë <color> ¤ò»È¤¦(ƱµÁ: -bg)" - -#~ msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" -#~ msgstr "-foreground <color>\tÁ°·Ê¿§¤Ë <color> ¤ò»È¤¦(ƱµÁ: -fg)" - -#~ msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" -#~ msgstr "-font <font>\t\t¥Æ¥¥¹¥Èɽ¼¨¤Ë <font> ¤ò»È¤¦(ƱµÁ: -fn)" - -#~ msgid "-boldfont <font>\tUse <font> for bold text" -#~ msgstr "-boldfont <font>\tÂÀ»ú¤Ë <font> ¤ò»È¤¦" - -#~ msgid "-italicfont <font>\tUse <font> for italic text" -#~ msgstr "-italicfont <for>\t¼ÐÂλú¤Ë <font> ¤ò»È¤¦" - -#~ msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" -#~ msgstr "-geometry <geom>\t½é´üÇÛÃÖ¤Ë <geom> ¤ò»È¤¦(ƱµÁ: -geom)" - -#~ msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" -#~ msgstr "-borderwidth <width>\t¶³¦¤ÎÉý¤ò <width> ¤Ë¤¹¤ë(ƱµÁ: -bw)" - -#~ msgid "" -#~ "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" -#~ msgstr "" -#~ "-scrollbarwidth <width> ¥¹¥¯¥í¡¼¥ë¥Ð¡¼¤ÎÉý¤ò <width> ¤Ë¤¹¤ë(ƱµÁ: -sw)" - -#~ msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" -#~ msgstr "" -#~ "-menuheight <height>\t¥á¥Ë¥å¡¼¥Ð¡¼¤Î¹â¤µ¤ò <height> ¤Ë¤¹¤ë(ƱµÁ: -mh)" - -#~ msgid "-reverse\t\tUse reverse video (also: -rv)" -#~ msgstr "-reverse\t\tȿž±ÇÁü¤ò»ÈÍѤ¹¤ë(ƱµÁ: -rv)" - -#~ msgid "+reverse\t\tDon't use reverse video (also: +rv)" -#~ msgstr "+reverse\t\tȿž±ÇÁü¤ò»ÈÍѤ·¤Ê¤¤(ƱµÁ: +rv)" - -#~ msgid "-xrm <resource>\tSet the specified resource" -#~ msgstr "-xrm <resource>\tÆÃÄê¤Î¥ê¥½¡¼¥¹¤ò»ÈÍѤ¹¤ë" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (GTK+ version):\n" -#~ msgstr "" -#~ "\n" -#~ "gvim¤Ë¤è¤Ã¤Æ²ò¼á¤µ¤ì¤ë°ú¿ô(GTK+¥Ð¡¼¥¸¥ç¥ó):\n" - -#~ msgid "-display <display>\tRun vim on <display> (also: --display)" -#~ msgstr "-display <display>\t<display> ¤Çvim¤ò¼Â¹Ô¤¹¤ë(ƱµÁ: --display)" - -#~ msgid "--role <role>\tSet a unique role to identify the main window" -#~ msgstr "--role <role>\t¥á¥¤¥ó¥¦¥£¥ó¥É¥¦¤ò¼±Ê̤¹¤ë°ì°Õ¤ÊÌò³ä(role)¤òÀßÄꤹ¤ë" - -#~ msgid "--socketid <xid>\tOpen Vim inside another GTK widget" -#~ msgstr "--socketid <xid>\t°Û¤Ê¤ëGTK widget¤ÇVim¤ò³«¤¯" - -#~ msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" -#~ msgstr "--echo-wid\t\t¥¦¥£¥ó¥É¥¦ID¤òɸ½à½ÐÎϤ˽ÐÎϤ¹¤ë" - -#~ msgid "-P <parent title>\tOpen Vim inside parent application" -#~ msgstr "-P <¿Æ¤Î¥¿¥¤¥È¥ë>\tVim¤ò¿Æ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤ÎÃæ¤Çµ¯Æ°¤¹¤ë" - -#~ msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" -#~ msgstr "--windowid <HWND>\t°Û¤Ê¤ëWin32 widget¤ÎÆâÉô¤ËVim¤ò³«¤¯" - -#~ msgid "No display" -#~ msgstr "¥Ç¥£¥¹¥×¥ì¥¤¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó" - -#~ msgid ": Send failed.\n" -#~ msgstr ": Á÷¿®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿.\n" - -#~ msgid ": Send failed. Trying to execute locally\n" -#~ msgstr ": Á÷¿®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿. ¥í¡¼¥«¥ë¤Ç¤Î¼Â¹Ô¤ò»î¤ß¤Æ¤¤¤Þ¤¹\n" - -#~ msgid "%d of %d edited" -#~ msgstr "%d ¸Ä (%d ¸ÄÃæ) ¤Î¥Õ¥¡¥¤¥ë¤òÊÔ½¸¤·¤Þ¤·¤¿" - -#~ msgid "No display: Send expression failed.\n" -#~ msgstr "¥Ç¥£¥¹¥×¥ì¥¤¤¬¤¢¤ê¤Þ¤»¤ó: ¼°¤ÎÁ÷¿®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿.\n" - -#~ msgid ": Send expression failed.\n" -#~ msgstr ": ¼°¤ÎÁ÷¿®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿.\n" - -#~ msgid "E543: Not a valid codepage" -#~ msgstr "E543: ̵¸ú¤Ê¥³¡¼¥É¥Ú¡¼¥¸¤Ç¤¹" - -#~ msgid "E284: Cannot set IC values" -#~ msgstr "E284: IC¤ÎÃͤòÀßÄê¤Ç¤¤Þ¤»¤ó" - -#~ msgid "E285: Failed to create input context" -#~ msgstr "E285: ¥¤¥ó¥×¥Ã¥È¥³¥ó¥Æ¥¥¹¥È¤ÎºîÀ®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" - -#~ msgid "E286: Failed to open input method" -#~ msgstr "E286: ¥¤¥ó¥×¥Ã¥È¥á¥½¥Ã¥É¤Î¥ª¡¼¥×¥ó¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" - -#~ msgid "E287: Warning: Could not set destroy callback to IM" -#~ msgstr "E287: ·Ù¹ð: IM¤ÎÇ˲õ¥³¡¼¥ë¥Ð¥Ã¥¯¤òÀßÄê¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" - -#~ msgid "E288: input method doesn't support any style" -#~ msgstr "E288: ¥¤¥ó¥×¥Ã¥È¥á¥½¥Ã¥É¤Ï¤É¤ó¤Ê¥¹¥¿¥¤¥ë¤â¥µ¥Ý¡¼¥È¤·¤Þ¤»¤ó" - -#~ msgid "E289: input method doesn't support my preedit type" -#~ msgstr "E289: ¥¤¥ó¥×¥Ã¥È¥á¥½¥Ã¥É¤Ï my preedit type ¤ò¥µ¥Ý¡¼¥È¤·¤Þ¤»¤ó" +#, c-format +msgid "E447: Can't find file \"%s\" in path" +msgstr "E447: path¤Ë¤Ï \"%s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó" -#~ msgid "E843: Error while updating swap file crypt" -#~ msgstr "E843: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤Î°Å¹æ¤ò¹¹¿·Ãæ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤Þ¤·¤¿" +#, c-format +msgid "E799: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E799: ̵¸ú¤Ê ID: %ld (1 °Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó)" -#~ msgid "" -#~ "E833: %s is encrypted and this version of Vim does not support encryption" -#~ msgstr "" -#~ "E833: %s ¤Ï¤³¤Î¥Ð¡¼¥¸¥ç¥ó¤ÎVim¤Ç¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤Ê¤¤·Á¼°¤Ç°Å¹æ²½¤µ¤ì¤Æ¤¤¤Þ¤¹" +#, c-format +msgid "E801: ID already taken: %ld" +msgstr "E801: ID ¤Ï¤¹¤Ç¤ËÍøÍÑÃæ¤Ç¤¹: %ld" -#~ msgid "Swap file is encrypted: \"%s\"" -#~ msgstr "¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤Ï°Å¹æ²½¤µ¤ì¤Æ¤¤¤Þ¤¹: \"%s\"" +msgid "List or number required" +msgstr "¥ê¥¹¥È¤«¿ôÃͤ¬É¬ÍפǤ¹" -#~ msgid "" -#~ "\n" -#~ "If you entered a new crypt key but did not write the text file," -#~ msgstr "" -#~ "\n" -#~ "¿·¤·¤¤°Å¹æ¥¡¼¤òÆþÎϤ·¤¿¤¢¤È¤Ë¥Æ¥¥¹¥È¥Õ¥¡¥¤¥ë¤òÊݸ¤·¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ï," +#, c-format +msgid "E802: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E802: ̵¸ú¤Ê ID: %ld (1 °Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó)" -#~ msgid "" -#~ "\n" -#~ "enter the new crypt key." -#~ msgstr "" -#~ "\n" -#~ "¿·¤·¤¤°Å¹æ¥¡¼¤òÆþÎϤ·¤Æ¤¯¤À¤µ¤¤." +#, c-format +msgid "E803: ID not found: %ld" +msgstr "E803: ID ¤Ï¤¢¤ê¤Þ¤»¤ó: %ld" -#~ msgid "" -#~ "\n" -#~ "If you wrote the text file after changing the crypt key press enter" -#~ msgstr "" -#~ "\n" -#~ "°Å¹æ¥¡¼¤òÊѤ¨¤¿¤¢¤È¤Ë¥Æ¥¥¹¥È¥Õ¥¡¥¤¥ë¤òÊݸ¤·¤¿¾ì¹ç¤Ï, ¥Æ¥¥¹¥È¥Õ¥¡¥¤¥ë¤È" +#, c-format +msgid "E370: Could not load library %s" +msgstr "E370: ¥é¥¤¥Ö¥é¥ê %s ¤ò¥í¡¼¥É¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" -#~ msgid "" -#~ "\n" -#~ "to use the same key for text file and swap file" -#~ msgstr "" -#~ "\n" -#~ "¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤ËƱ¤¸°Å¹æ¥¡¼¤ò»È¤¦¤¿¤á¤Ëenter¤À¤±¤ò²¡¤·¤Æ¤¯¤À¤µ¤¤." +msgid "Sorry, this command is disabled: the Perl library could not be loaded." +msgstr "" +"¤³¤Î¥³¥Þ¥ó¥É¤Ï̵¸ú¤Ç¤¹, ¤´¤á¤ó¤Ê¤µ¤¤: Perl¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿." -#~ msgid "Using crypt key from swap file for the text file.\n" -#~ msgstr "¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤«¤é¼èÆÀ¤·¤¿°Å¹æ¥¡¼¤ò¥Æ¥¥¹¥È¥Õ¥¡¥¤¥ë¤Ë»È¤¤¤Þ¤¹.\n" +msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" +msgstr "" +"E299: ¥µ¥ó¥É¥Ü¥Ã¥¯¥¹¤Ç¤Ï Safe ¥â¥¸¥å¡¼¥ë¤ò»ÈÍѤ·¤Ê¤¤Perl¥¹¥¯¥ê¥×¥È¤Ï¶Ø¤¸¤é¤ì" +"¤Æ¤¤¤Þ¤¹" -#~ msgid "" -#~ "\n" -#~ " [not usable with this version of Vim]" -#~ msgstr "" -#~ "\n" -#~ " [¤³¤ÎVim¥Ð¡¼¥¸¥ç¥ó¤Ç¤Ï»ÈÍѤǤ¤Þ¤»¤ó]" +msgid "Edit with &multiple Vims" +msgstr "Ê£¿ô¤ÎVim¤ÇÊÔ½¸¤¹¤ë (&M)" -#~ msgid "Tear off this menu" -#~ msgstr "¤³¤Î¥á¥Ë¥å¡¼¤òÀÚ¤ê¼è¤ë" +msgid "Edit with single &Vim" +msgstr "1¤Ä¤ÎVim¤ÇÊÔ½¸¤¹¤ë (&V)" -#~ msgid "Select Directory dialog" -#~ msgstr "¥Ç¥£¥ì¥¯¥È¥êÁªÂò¥À¥¤¥¢¥í¥°" +msgid "Diff with Vim" +msgstr "Vim¤Çº¹Ê¬¤òɽ¼¨¤¹¤ë" -#~ msgid "Save File dialog" -#~ msgstr "¥Õ¥¡¥¤¥ëÊݸ¥À¥¤¥¢¥í¥°" +msgid "Edit with &Vim" +msgstr "Vim¤ÇÊÔ½¸¤¹¤ë (&V)" -#~ msgid "Open File dialog" -#~ msgstr "¥Õ¥¡¥¤¥ëÆÉ¹þ¥À¥¤¥¢¥í¥°" +#. Now concatenate +msgid "Edit with existing Vim - " +msgstr "µ¯Æ°ºÑ¤ÎVim¤ÇÊÔ½¸¤¹¤ë - " -#~ msgid "E338: Sorry, no file browser in console mode" -#~ msgstr "" -#~ "E338: ¥³¥ó¥½¡¼¥ë¥â¡¼¥É¤Ç¤Ï¥Õ¥¡¥¤¥ë¥Ö¥é¥¦¥¶¤ò»È¤¨¤Þ¤»¤ó, ¤´¤á¤ó¤Ê¤µ¤¤" +msgid "Edits the selected file(s) with Vim" +msgstr "ÁªÂò¤·¤¿¥Õ¥¡¥¤¥ë¤òVim¤ÇÊÔ½¸¤¹¤ë" -#~ msgid "Vim: preserving files...\n" -#~ msgstr "Vim: ¥Õ¥¡¥¤¥ë¤òÊÝÂ¸Ãæ...\n" +msgid "Error creating process: Check if gvim is in your path!" +msgstr "¥×¥í¥»¥¹¤ÎºîÀ®¤Ë¼ºÇÔ: gvim¤¬´Ä¶ÊÑ¿ôPATH¾å¤Ë¤¢¤ë¤«³Îǧ¤·¤Æ¤¯¤À¤µ¤¤!" -#~ msgid "Vim: Finished.\n" -#~ msgstr "Vim: ½ªÎ»¤·¤Þ¤·¤¿.\n" +msgid "gvimext.dll error" +msgstr "gvimext.dll ¥¨¥é¡¼" -#~ msgid "ERROR: " -#~ msgstr "¥¨¥é¡¼: " +msgid "Path length too long!" +msgstr "¥Ñ¥¹¤¬Ä¹²á¤®¤Þ¤¹!" -#~ msgid "" -#~ "\n" -#~ "[bytes] total alloc-freed %<PRIu64>-%<PRIu64>, in use %<PRIu64>, peak use " -#~ "%<PRIu64>\n" -#~ msgstr "" -#~ "\n" -#~ "[¥á¥â¥ê(¥Ð¥¤¥È)] Áí³äÅö-²òÊüÎÌ %<PRIu64>-%<PRIu64>, »ÈÍÑÎÌ %<PRIu64>, ¥Ô¡¼" -#~ "¥¯»þ %<PRIu64>\n" +msgid "--No lines in buffer--" +msgstr "--¥Ð¥Ã¥Õ¥¡¤Ë¹Ô¤¬¤¢¤ê¤Þ¤»¤ó--" -#~ msgid "" -#~ "[calls] total re/malloc()'s %<PRIu64>, total free()'s %<PRIu64>\n" -#~ "\n" -#~ msgstr "" -#~ "[¸Æ½Ð] Áí re/malloc() ²ó¿ô %<PRIu64>, Áí free() ²ó¿ô %<PRIu64>\n" -#~ "\n" +#. +#. * The error messages that can be shared are included here. +#. * Excluded are errors that are only used once and debugging messages. +#. +msgid "E470: Command aborted" +msgstr "E470: ¥³¥Þ¥ó¥É¤¬ÃæÃǤµ¤ì¤Þ¤·¤¿" -#~ msgid "E340: Line is becoming too long" -#~ msgstr "E340: ¹Ô¤¬Ä¹¤¯¤Ê¤ê²á¤®¤Þ¤·¤¿" +msgid "E471: Argument required" +msgstr "E471: °ú¿ô¤¬É¬ÍפǤ¹" -#~ msgid "E341: Internal error: lalloc(%<PRId64>, )" -#~ msgstr "E341: ÆâÉô¥¨¥é¡¼: lalloc(%<PRId64>,)" +msgid "E10: \\ should be followed by /, ? or &" +msgstr "E10: \\ ¤Î¸å¤Ï / ¤« ? ¤« & ¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" -#~ msgid "E547: Illegal mouseshape" -#~ msgstr "E547: ÉÔÀµ¤Ê 'mouseshape' ¤Ç¤¹" +msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" +msgstr "E11: ¥³¥Þ¥ó¥É¥é¥¤¥ó¤Ç¤Ï̵¸ú¤Ç¤¹; <CR>¤Ç¼Â¹Ô, CTRL-C¤Ç¤ä¤á¤ë" -#~ msgid "Enter encryption key: " -#~ msgstr "°Å¹æ²½ÍѤΥ¡¼¤òÆþÎϤ·¤Æ¤¯¤À¤µ¤¤: " +msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" +msgstr "" +"E12: ¸½ºß¤Î¥Ç¥£¥ì¥¯¥È¥ê¤ä¥¿¥°¸¡º÷¤Ç¤Ïexrc/vimrc¤Î¥³¥Þ¥ó¥É¤Ïµö²Ä¤µ¤ì¤Þ¤»¤ó" -#~ msgid "Enter same key again: " -#~ msgstr "¤â¤¦°ìÅÙÆ±¤¸¥¡¼¤òÆþÎϤ·¤Æ¤¯¤À¤µ¤¤: " +msgid "E171: Missing :endif" +msgstr "E171: :endif ¤¬¤¢¤ê¤Þ¤»¤ó" -#~ msgid "Keys don't match!" -#~ msgstr "¥¡¼¤¬°ìÃפ·¤Þ¤»¤ó" +msgid "E600: Missing :endtry" +msgstr "E600: :endtry ¤¬¤¢¤ê¤Þ¤»¤ó" -#~ msgid "Cannot connect to Netbeans #2" -#~ msgstr "Netbeans #2 ¤ËÀܳ¤Ç¤¤Þ¤»¤ó" +msgid "E170: Missing :endwhile" +msgstr "E170: :endwhile ¤¬¤¢¤ê¤Þ¤»¤ó" -#~ msgid "Cannot connect to Netbeans" -#~ msgstr "Netbeans ¤ËÀܳ¤Ç¤¤Þ¤»¤ó" +msgid "E170: Missing :endfor" +msgstr "E170: :endfor ¤¬¤¢¤ê¤Þ¤»¤ó" -#~ msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" -#~ msgstr "" -#~ "E668: NetBeans¤ÎÀܳ¾ðÊó¥Õ¥¡¥¤¥ë¤Î¥¢¥¯¥»¥¹¥â¡¼¥É¤ËÌäÂ꤬¤¢¤ê¤Þ¤¹: \"%s\"" +msgid "E588: :endwhile without :while" +msgstr "E588: :while ¤Î¤Ê¤¤ :endwhile ¤¬¤¢¤ê¤Þ¤¹" -#~ msgid "read from Netbeans socket" -#~ msgstr "Netbeans ¤Î¥½¥±¥Ã¥È¤òÆÉ¹þ¤ß" +msgid "E588: :endfor without :for" +msgstr "E588: :endfor ¤Î¤Ê¤¤ :for ¤¬¤¢¤ê¤Þ¤¹" -#~ msgid "E658: NetBeans connection lost for buffer %<PRId64>" -#~ msgstr "E658: ¥Ð¥Ã¥Õ¥¡ %<PRId64> ¤Î NetBeans Àܳ¤¬¼º¤ï¤ì¤Þ¤·¤¿" +msgid "E13: File exists (add ! to override)" +msgstr "E13: ¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤·¤Þ¤¹ (! ¤òÄɲäǾå½ñ)" -#~ msgid "E838: netbeans is not supported with this GUI" -#~ msgstr "E838: NetBeans¤Ï¤³¤ÎGUI¤Ë¤ÏÂбþ¤·¤Æ¤¤¤Þ¤»¤ó" +msgid "E472: Command failed" +msgstr "E472: ¥³¥Þ¥ó¥É¤¬¼ºÇÔ¤·¤Þ¤·¤¿" -#~ msgid "E511: netbeans already connected" -#~ msgstr "E511: NetBeans¤Ï´û¤ËÀܳ¤·¤Æ¤¤¤Þ¤¹" +#, c-format +msgid "E234: Unknown fontset: %s" +msgstr "E234: ̤ÃΤΥե©¥ó¥È¥»¥Ã¥È: %s" -#~ msgid "E505: %s is read-only (add ! to override)" -#~ msgstr "E505: %s ¤ÏÆÉ¹þÀìÍѤǤ¹ (¶¯À©½ñ¹þ¤Ë¤Ï ! ¤òÄɲÃ)" +#, c-format +msgid "E235: Unknown font: %s" +msgstr "E235: ̤ÃΤΥե©¥ó¥È: %s" -#~ msgid "E775: Eval feature not available" -#~ msgstr "E775: ¼°É¾²Áµ¡Ç½¤¬Ìµ¸ú¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹" +#, c-format +msgid "E236: Font \"%s\" is not fixed-width" +msgstr "E236: ¥Õ¥©¥ó¥È \"%s\" ¤Ï¸ÇÄêÉý¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó" -#~ msgid "freeing %<PRId64> lines" -#~ msgstr "%<PRId64> ¹Ô¤ò²òÊüÃæ" +msgid "E473: Internal error" +msgstr "E473: ÆâÉô¥¨¥é¡¼¤Ç¤¹" -#~ msgid "E530: Cannot change term in GUI" -#~ msgstr "E530: GUI¤Ç¤Ï 'term' ¤òÊѹ¹¤Ç¤¤Þ¤»¤ó" +msgid "Interrupted" +msgstr "³ä¹þ¤Þ¤ì¤Þ¤·¤¿" -#~ msgid "E531: Use \":gui\" to start the GUI" -#~ msgstr "E531: GUI¤ò¥¹¥¿¡¼¥È¤¹¤ë¤Ë¤Ï \":gui\" ¤ò»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤" +msgid "E14: Invalid address" +msgstr "E14: ̵¸ú¤Ê¥¢¥É¥ì¥¹¤Ç¤¹" -#~ msgid "E617: Cannot be changed in the GTK+ 2 GUI" -#~ msgstr "E617: GTK+2 GUI¤Ç¤ÏÊѹ¹¤Ç¤¤Þ¤»¤ó" +msgid "E474: Invalid argument" +msgstr "E474: ̵¸ú¤Ê°ú¿ô¤Ç¤¹" -#~ msgid "E596: Invalid font(s)" -#~ msgstr "E596: ̵¸ú¤Ê¥Õ¥©¥ó¥È¤Ç¤¹" +#, c-format +msgid "E475: Invalid argument: %s" +msgstr "E475: ̵¸ú¤Ê°ú¿ô¤Ç¤¹: %s" -#~ msgid "E597: can't select fontset" -#~ msgstr "E597: ¥Õ¥©¥ó¥È¥»¥Ã¥È¤òÁªÂò¤Ç¤¤Þ¤»¤ó" +#, c-format +msgid "E15: Invalid expression: %s" +msgstr "E15: ̵¸ú¤Ê¼°¤Ç¤¹: %s" -#~ msgid "E598: Invalid fontset" -#~ msgstr "E598: ̵¸ú¤Ê¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ç¤¹" +msgid "E16: Invalid range" +msgstr "E16: ̵¸ú¤ÊÈϰϤǤ¹" -#~ msgid "E533: can't select wide font" -#~ msgstr "E533: ¥ï¥¤¥É¥Õ¥©¥ó¥È¤òÁªÂò¤Ç¤¤Þ¤»¤ó" +msgid "E476: Invalid command" +msgstr "E476: ̵¸ú¤Ê¥³¥Þ¥ó¥É¤Ç¤¹" -#~ msgid "E534: Invalid wide font" -#~ msgstr "E534: ̵¸ú¤Ê¥ï¥¤¥É¥Õ¥©¥ó¥È¤Ç¤¹" +#, c-format +msgid "E17: \"%s\" is a directory" +msgstr "E17: \"%s\" ¤Ï¥Ç¥£¥ì¥¯¥È¥ê¤Ç¤¹" -#~ msgid "E538: No mouse support" -#~ msgstr "E538: ¥Þ¥¦¥¹¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó" +#, c-format +msgid "E364: Library call failed for \"%s()\"" +msgstr "E364: \"%s\"() ¤Î¥é¥¤¥Ö¥é¥ê¸Æ½Ð¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#~ msgid "cannot open " -#~ msgstr "³«¤±¤Þ¤»¤ó " +#, c-format +msgid "E448: Could not load library function %s" +msgstr "E448: ¥é¥¤¥Ö¥é¥ê¤Î´Ø¿ô %s ¤ò¥í¡¼¥É¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" -#~ msgid "VIM: Can't open window!\n" -#~ msgstr "VIM: ¥¦¥£¥ó¥É¥¦¤ò³«¤±¤Þ¤»¤ó!\n" +msgid "E19: Mark has invalid line number" +msgstr "E19: ¥Þ¡¼¥¯¤Ë̵¸ú¤Ê¹ÔÈֹ椬»ØÄꤵ¤ì¤Æ¤¤¤Þ¤·¤¿" -#~ msgid "Need Amigados version 2.04 or later\n" -#~ msgstr "Amigados¤Î¥Ð¡¼¥¸¥ç¥ó 2.04¤«¤½¤ì°Ê¹ß¤¬É¬ÍפǤ¹\n" +msgid "E20: Mark not set" +msgstr "E20: ¥Þ¡¼¥¯¤ÏÀßÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó" -#~ msgid "Need %s version %<PRId64>\n" -#~ msgstr "%s ¤Î¥Ð¡¼¥¸¥ç¥ó %<PRId64> ¤¬É¬ÍפǤ¹\n" +msgid "E21: Cannot make changes, 'modifiable' is off" +msgstr "E21: 'modifiable' ¤¬¥ª¥Õ¤Ê¤Î¤Ç, Êѹ¹¤Ç¤¤Þ¤»¤ó" -#~ msgid "Cannot open NIL:\n" -#~ msgstr "NIL¤ò³«¤±¤Þ¤»¤ó:\n" +msgid "E22: Scripts nested too deep" +msgstr "E22: ¥¹¥¯¥ê¥×¥È¤ÎÆþ¤ì»Ò¤¬¿¼²á¤®¤Þ¤¹" -#~ msgid "Cannot create " -#~ msgstr "ºîÀ®¤Ç¤¤Þ¤»¤ó " +msgid "E23: No alternate file" +msgstr "E23: Éû¥Õ¥¡¥¤¥ë¤Ï¤¢¤ê¤Þ¤»¤ó" -#~ msgid "Vim exiting with %d\n" -#~ msgstr "Vim¤Ï %d ¤Ç½ªÎ»¤·¤Þ¤¹\n" +msgid "E24: No such abbreviation" +msgstr "E24: ¤½¤Î¤è¤¦¤Êû½ÌÆþÎϤϤ¢¤ê¤Þ¤»¤ó" -#~ msgid "cannot change console mode ?!\n" -#~ msgstr "¥³¥ó¥½¡¼¥ë¥â¡¼¥É¤òÊѹ¹¤Ç¤¤Þ¤»¤ó?!\n" +msgid "E477: No ! allowed" +msgstr "E477: ! ¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#~ msgid "mch_get_shellsize: not a console??\n" -#~ msgstr "mch_get_shellsize: ¥³¥ó¥½¡¼¥ë¤Ç¤Ï¤Ê¤¤??\n" +msgid "E25: GUI cannot be used: Not enabled at compile time" +msgstr "E25: GUI¤Ï»ÈÍÑÉÔ²Äǽ¤Ç¤¹: ¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹" -#~ msgid "E360: Cannot execute shell with -f option" -#~ msgstr "E360: -f ¥ª¥×¥·¥ç¥ó¤Ç¥·¥§¥ë¤ò¼Â¹Ô¤Ç¤¤Þ¤»¤ó" +msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" +msgstr "E26: ¥Ø¥Ö¥é¥¤¸ì¤Ï»ÈÍÑÉÔ²Äǽ¤Ç¤¹: ¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹\n" -#~ msgid "Cannot execute " -#~ msgstr "¼Â¹Ô¤Ç¤¤Þ¤»¤ó " +msgid "E27: Farsi cannot be used: Not enabled at compile time\n" +msgstr "E27: ¥Ú¥ë¥·¥¢¸ì¤Ï»ÈÍÑÉÔ²Äǽ¤Ç¤¹: ¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹\n" -#~ msgid "shell " -#~ msgstr "¥·¥§¥ë " +msgid "E800: Arabic cannot be used: Not enabled at compile time\n" +msgstr "E800: ¥¢¥é¥Ó¥¢¸ì¤Ï»ÈÍÑÉÔ²Äǽ¤Ç¤¹: ¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹\n" -#~ msgid " returned\n" -#~ msgstr " Ìá¤ê¤Þ¤·¤¿\n" +#, c-format +msgid "E28: No such highlight group name: %s" +msgstr "E28: ¤½¤Î¤è¤¦¤Ê̾¤Î¥Ï¥¤¥é¥¤¥È¥°¥ë¡¼¥×¤Ï¤¢¤ê¤Þ¤»¤ó: %s" -#~ msgid "ANCHOR_BUF_SIZE too small." -#~ msgstr "ANCHOR_BUF_SIZE ¤¬¾®¤µ²á¤®¤Þ¤¹." +msgid "E29: No inserted text yet" +msgstr "E29: ¤Þ¤À¥Æ¥¥¹¥È¤¬ÁÞÆþ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#~ msgid "I/O ERROR" -#~ msgstr "Æþ½ÐÎÏ¥¨¥é¡¼" +msgid "E30: No previous command line" +msgstr "E30: °ÊÁ°¤Ë¥³¥Þ¥ó¥É¹Ô¤¬¤¢¤ê¤Þ¤»¤ó" -#~ msgid "Message" -#~ msgstr "¥á¥Ã¥»¡¼¥¸" +msgid "E31: No such mapping" +msgstr "E31: ¤½¤Î¤è¤¦¤Ê¥Þ¥Ã¥Ô¥ó¥°¤Ï¤¢¤ê¤Þ¤»¤ó" -#~ msgid "'columns' is not 80, cannot execute external commands" -#~ msgstr "'columns' ¤¬80¤Ç¤Ï¤Ê¤¤¤¿¤á, ³°Éô¥³¥Þ¥ó¥É¤ò¼Â¹Ô¤Ç¤¤Þ¤»¤ó" +msgid "E479: No match" +msgstr "E479: ³ºÅö¤Ï¤¢¤ê¤Þ¤»¤ó" -#~ msgid "E237: Printer selection failed" -#~ msgstr "E237: ¥×¥ê¥ó¥¿¤ÎÁªÂò¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" +#, c-format +msgid "E480: No match: %s" +msgstr "E480: ³ºÅö¤Ï¤¢¤ê¤Þ¤»¤ó: %s" -#~ msgid "to %s on %s" -#~ msgstr "%s ¤Ø (%s ¾å¤Î)" +msgid "E32: No file name" +msgstr "E32: ¥Õ¥¡¥¤¥ë̾¤¬¤¢¤ê¤Þ¤»¤ó" -#~ msgid "E613: Unknown printer font: %s" -#~ msgstr "E613: ̤ÃΤΥץê¥ó¥¿¥ª¥×¥·¥ç¥ó¤Ç¤¹: %s" +msgid "E33: No previous substitute regular expression" +msgstr "E33: Àµµ¬É½¸½ÃÖ´¹¤¬¤Þ¤À¼Â¹Ô¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#~ msgid "E238: Print error: %s" -#~ msgstr "E238: °õºþ¥¨¥é¡¼: %s" +msgid "E34: No previous command" +msgstr "E34: ¥³¥Þ¥ó¥É¤¬¤Þ¤À¼Â¹Ô¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#~ msgid "Printing '%s'" -#~ msgstr "°õºþ¤·¤Æ¤¤¤Þ¤¹: '%s'" +msgid "E35: No previous regular expression" +msgstr "E35: Àµµ¬É½¸½¤¬¤Þ¤À¼Â¹Ô¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#~ msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" -#~ msgstr "E244: ʸ»ú¥»¥Ã¥È̾ \"%s\" ¤ÏÉÔÀµ¤Ç¤¹ (¥Õ¥©¥ó¥È̾ \"%s\")" +msgid "E481: No range allowed" +msgstr "E481: ÈϰϻØÄê¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#~ msgid "E245: Illegal char '%c' in font name \"%s\"" -#~ msgstr "E245: '%c' ¤ÏÉÔÀµ¤Êʸ»ú¤Ç¤¹ (¥Õ¥©¥ó¥È̾ \"%s\")" +msgid "E36: Not enough room" +msgstr "E36: ¥¦¥£¥ó¥É¥¦¤Ë½½Ê¬¤Ê¹â¤µ¤â¤·¤¯¤ÏÉý¤¬¤¢¤ê¤Þ¤»¤ó" -#~ msgid "Vim: Double signal, exiting\n" -#~ msgstr "Vim: 2½Å¤Î¥·¥°¥Ê¥ë¤Î¤¿¤á, ½ªÎ»¤·¤Þ¤¹\n" +#, c-format +msgid "E247: no registered server named \"%s\"" +msgstr "E247: %s ¤È¤¤¤¦Ì¾Á°¤ÎÅÐÏ¿¤µ¤ì¤¿¥µ¡¼¥Ð¡¼¤Ï¤¢¤ê¤Þ¤»¤ó" -#~ msgid "Vim: Caught deadly signal %s\n" -#~ msgstr "Vim: Ã×̿Ū¥·¥°¥Ê¥ë %s ¤ò¸¡ÃΤ·¤Þ¤·¤¿\n" +#, c-format +msgid "E482: Can't create file %s" +msgstr "E482: ¥Õ¥¡¥¤¥ë %s ¤òºîÀ®¤Ç¤¤Þ¤»¤ó" -#~ msgid "Vim: Caught deadly signal\n" -#~ msgstr "Vim: Ã×̿Ū¥·¥°¥Ê¥ë¤ò¸¡ÃΤ·¤Þ¤·¤¿\n" +msgid "E483: Can't get temp file name" +msgstr "E483: °ì»þ¥Õ¥¡¥¤¥ë¤Î̾Á°¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó" -#~ msgid "Opening the X display took %<PRId64> msec" -#~ msgstr "X¥µ¡¼¥Ð¤Ø¤ÎÀܳ¤Ë %<PRId64> ¥ß¥êÉ䫤«¤ê¤Þ¤·¤¿" +#, c-format +msgid "E484: Can't open file %s" +msgstr "E484: ¥Õ¥¡¥¤¥ë \"%s\" ¤ò³«¤±¤Þ¤»¤ó" -#~ msgid "" -#~ "\n" -#~ "Vim: Got X error\n" -#~ msgstr "" -#~ "\n" -#~ "Vim: X ¤Î¥¨¥é¡¼¤ò¸¡½Ð¤·¤Þ¤·¤¿r\n" +#, c-format +msgid "E485: Can't read file %s" +msgstr "E485: ¥Õ¥¡¥¤¥ë %s ¤òÆÉ¹þ¤á¤Þ¤»¤ó" -#~ msgid "Testing the X display failed" -#~ msgstr "X display ¤Î¥Á¥§¥Ã¥¯¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" +msgid "E37: No write since last change (add ! to override)" +msgstr "E37: ºÇ¸å¤ÎÊѹ¹¤¬Êݸ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó (! ¤òÄɲäÇÊѹ¹¤òÇË´þ)" -#~ msgid "Opening the X display timed out" -#~ msgstr "X display ¤Î open ¤¬¥¿¥¤¥à¥¢¥¦¥È¤·¤Þ¤·¤¿" +msgid "E37: No write since last change" +msgstr "E37: ºÇ¸å¤ÎÊѹ¹¤¬Êݸ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#~ msgid "" -#~ "\n" -#~ "Cannot execute shell sh\n" -#~ msgstr "" -#~ "\n" -#~ "sh ¥·¥§¥ë¤ò¼Â¹Ô¤Ç¤¤Þ¤»¤ó\n" +msgid "E38: Null argument" +msgstr "E38: °ú¿ô¤¬¶õ¤Ç¤¹" -#~ msgid "" -#~ "\n" -#~ "Cannot create pipes\n" -#~ msgstr "" -#~ "\n" -#~ "¥Ñ¥¤¥×¤òºîÀ®¤Ç¤¤Þ¤»¤ó\n" +msgid "E39: Number expected" +msgstr "E39: ¿ôÃͤ¬Í׵ᤵ¤ì¤Æ¤¤¤Þ¤¹" -#~ msgid "" -#~ "\n" -#~ "Cannot fork\n" -#~ msgstr "" -#~ "\n" -#~ "fork ¤Ç¤¤Þ¤»¤ó\n" +#, c-format +msgid "E40: Can't open errorfile %s" +msgstr "E40: ¥¨¥é¡¼¥Õ¥¡¥¤¥ë %s ¤ò³«¤±¤Þ¤»¤ó" -#~ msgid "" -#~ "\n" -#~ "Command terminated\n" -#~ msgstr "" -#~ "\n" -#~ "¥³¥Þ¥ó¥É¤òÃæÃǤ·¤Þ¤·¤¿\n" +msgid "E233: cannot open display" +msgstr "E233: ¥Ç¥£¥¹¥×¥ì¥¤¤ò³«¤±¤Þ¤»¤ó" -#~ msgid "XSMP lost ICE connection" -#~ msgstr "XSMP ¤¬ICEÀܳ¤ò¼º¤¤¤Þ¤·¤¿" +msgid "E41: Out of memory!" +msgstr "E41: ¥á¥â¥ê¤¬¿Ô¤²Ì¤Æ¤Þ¤·¤¿!" -#~ msgid "Opening the X display failed" -#~ msgstr "X display ¤Î open ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" +msgid "Pattern not found" +msgstr "¥Ñ¥¿¡¼¥ó¤Ï¸«¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿" -#~ msgid "XSMP handling save-yourself request" -#~ msgstr "XSMP ¤¬save-yourselfÍ×µá¤ò½èÍý¤·¤Æ¤¤¤Þ¤¹" +#, c-format +msgid "E486: Pattern not found: %s" +msgstr "E486: ¥Ñ¥¿¡¼¥ó¤Ï¸«¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿: %s" -#~ msgid "XSMP opening connection" -#~ msgstr "XSMP ¤¬Àܳ¤ò³«»Ï¤·¤Æ¤¤¤Þ¤¹" +msgid "E487: Argument must be positive" +msgstr "E487: °ú¿ô¤ÏÀµ¤ÎÃͤǤʤ±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" -#~ msgid "XSMP ICE connection watch failed" -#~ msgstr "XSMP ICEÀܳ¤¬¼ºÇÔ¤·¤¿¤è¤¦¤Ç¤¹" +msgid "E459: Cannot go back to previous directory" +msgstr "E459: Á°¤Î¥Ç¥£¥ì¥¯¥È¥ê¤ËÌá¤ì¤Þ¤»¤ó" -#~ msgid "XSMP SmcOpenConnection failed: %s" -#~ msgstr "XSMP SmcOpenConnection¤¬¼ºÇÔ¤·¤Þ¤·¤¿: %s" +msgid "E42: No Errors" +msgstr "E42: ¥¨¥é¡¼¤Ï¤¢¤ê¤Þ¤»¤ó" -#~ msgid "At line" -#~ msgstr "¹Ô" +msgid "E776: No location list" +msgstr "E776: ¥í¥±¡¼¥·¥ç¥ó¥ê¥¹¥È¤Ï¤¢¤ê¤Þ¤»¤ó" -#~ msgid "Could not load vim32.dll!" -#~ msgstr "vim32.dll ¤ò¥í¡¼¥É¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" +msgid "E43: Damaged match string" +msgstr "E43: ³ºÅöʸ»úÎó¤¬ÇË»¤·¤Æ¤¤¤Þ¤¹" -#~ msgid "VIM Error" -#~ msgstr "VIM¥¨¥é¡¼" +msgid "E44: Corrupted regexp program" +msgstr "E44: ÉÔÀµ¤ÊÀµµ¬É½¸½¥×¥í¥°¥é¥à¤Ç¤¹" -#~ msgid "Could not fix up function pointers to the DLL!" -#~ msgstr "DLL¤«¤é´Ø¿ô¥Ý¥¤¥ó¥¿¤ò¼èÆÀ¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" +msgid "E45: 'readonly' option is set (add ! to override)" +msgstr "E45: 'readonly' ¥ª¥×¥·¥ç¥ó¤¬ÀßÄꤵ¤ì¤Æ¤¤¤Þ¤¹ (! ¤òÄɲäǾå½ñ¤)" -#~ msgid "shell returned %d" -#~ msgstr "¥·¥§¥ë¤¬¥³¡¼¥É %d ¤Ç½ªÎ»¤·¤Þ¤·¤¿" +#, c-format +msgid "E46: Cannot change read-only variable \"%s\"" +msgstr "E46: ÆÉ¼èÀìÍÑÊÑ¿ô \"%s\" ¤Ë¤ÏÃͤòÀßÄê¤Ç¤¤Þ¤»¤ó" -#~ msgid "Vim: Caught %s event\n" -#~ msgstr "Vim: ¥¤¥Ù¥ó¥È %s ¤ò¸¡ÃÎ\n" +#, c-format +msgid "E794: Cannot set variable in the sandbox: \"%s\"" +msgstr "E794: ¥µ¥ó¥É¥Ü¥Ã¥¯¥¹¤Ç¤ÏÊÑ¿ô \"%s\" ¤ËÃͤòÀßÄê¤Ç¤¤Þ¤»¤ó" -#~ msgid "close" -#~ msgstr "ÊĤ¸¤ë" +msgid "E713: Cannot use empty key for Dictionary" +msgstr "E713: ¼½ñ·¿¤Ë¶õ¤Î¥¡¼¤ò»È¤¦¤³¤È¤Ï¤Ç¤¤Þ¤»¤ó" -#~ msgid "logoff" -#~ msgstr "¥í¥°¥ª¥Õ" +msgid "E715: Dictionary required" +msgstr "E715: ¼½ñ·¿¤¬É¬ÍפǤ¹" -#~ msgid "shutdown" -#~ msgstr "¥·¥ã¥Ã¥È¥À¥¦¥ó" +#, c-format +msgid "E684: list index out of range: %ld" +msgstr "E684: ¥ê¥¹¥È¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤¬Èϰϳ°¤Ç¤¹: %ld" -#~ msgid "E371: Command not found" -#~ msgstr "E371: ¥³¥Þ¥ó¥É¤¬¤¢¤ê¤Þ¤»¤ó" - -#~ msgid "" -#~ "VIMRUN.EXE not found in your $PATH.\n" -#~ "External commands will not pause after completion.\n" -#~ "See :help win32-vimrun for more information." -#~ msgstr "" -#~ "VIMRUN.EXE¤¬ $PATH ¤ÎÃæ¤Ë¸«¤Ä¤«¤ê¤Þ¤»¤ó.\n" -#~ "³°Éô¥³¥Þ¥ó¥É¤Î½ªÎ»¸å¤Ë°ì»þÄä»ß¤ò¤·¤Þ¤»¤ó.\n" -#~ "¾ÜºÙ¤Ï :help win32-vimrun ¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤." - -#~ msgid "Vim Warning" -#~ msgstr "Vim¤Î·Ù¹ð" - -#~ msgid "Error file" -#~ msgstr "¥¨¥é¡¼¥Õ¥¡¥¤¥ë" - -#~ msgid "E868: Error building NFA with equivalence class!" -#~ msgstr "E868: Åù²Á¥¯¥é¥¹¤ò´Þ¤àNFA¹½Ãۤ˼ºÇÔ¤·¤Þ¤·¤¿!" - -#~ msgid "E878: (NFA) Could not allocate memory for branch traversal!" -#~ msgstr "E878: (NFA) ¸½ºß²£ÃÇÃæ¤Î¥Ö¥é¥ó¥Á¤Ë½½Ê¬¤Ê¥á¥â¥ê¤ò³ä¤êÅö¤Æ¤é¤ì¤Þ¤»¤ó!" - -#~ msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" -#~ msgstr "" -#~ "·Ù¹ð: ñ¸ì¥ê¥¹¥È \"%s_%s.spl\" ¤ª¤è¤Ó \"%s_ascii.spl\" ¤Ï¸«¤Ä¤«¤ê¤Þ¤»¤ó" - -#~ msgid "Conversion in %s not supported" -#~ msgstr "%s Æâ¤ÎÊÑ´¹¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" - -#~ msgid "E845: Insufficient memory, word list will be incomplete" -#~ msgstr "E845: ¥á¥â¥ê¤¬Â¤ê¤Ê¤¤¤Î¤Ç¡¢Ã±¸ì¥ê¥¹¥È¤ÏÉÔ´°Á´¤Ç¤¹" - -#~ msgid "E430: Tag file path truncated for %s\n" -#~ msgstr "E430: ¥¿¥°¥Õ¥¡¥¤¥ë¤Î¥Ñ¥¹¤¬ %s ¤ËÀÚ¤ê¼Î¤Æ¤é¤ì¤Þ¤·¤¿\n" - -#~ msgid "new shell started\n" -#~ msgstr "¿·¤·¤¤¥·¥§¥ë¤òµ¯Æ°¤·¤Þ¤¹\n" - -#~ msgid "Used CUT_BUFFER0 instead of empty selection" -#~ msgstr "¶õ¤ÎÁªÂòÎΰè¤Î¤«¤ï¤ê¤ËCUT_BUFFER0¤¬»ÈÍѤµ¤ì¤Þ¤·¤¿" - -#~ msgid "No undo possible; continue anyway" -#~ msgstr "²Äǽ¤Ê¥¢¥ó¥É¥¥¤Ï¤¢¤ê¤Þ¤»¤ó: ¤È¤ê¤¢¤¨¤ºÂ³¤±¤Þ¤¹" - -#~ msgid "E832: Non-encrypted file has encrypted undo file: %s" -#~ msgstr "" -#~ "E832: Èó°Å¹æ²½¥Õ¥¡¥¤¥ë¤¬°Å¹æ²½¤µ¤ì¤¿¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤ò»È¤Ã¤Æ¤Þ¤¹: %s" - -#~ msgid "E826: Undo file decryption failed: %s" -#~ msgstr "E826: °Å¹æ²½¤µ¤ì¤¿¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤Î²òÆÉ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿: %s" - -#~ msgid "E827: Undo file is encrypted: %s" -#~ msgstr "E827: ¥¢¥ó¥É¥¥¥Õ¥¡¥¤¥ë¤¬°Å¹æ²½¤µ¤ì¤Æ¤¤¤Þ¤¹: %s" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16/32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 16/32 ¥Ó¥Ã¥È GUI ÈÇ" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 64 ¥Ó¥Ã¥È GUI ÈÇ" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 32 ¥Ó¥Ã¥È GUI ÈÇ" - -#~ msgid " in Win32s mode" -#~ msgstr " in Win32s ¥â¡¼¥É" - -#~ msgid " with OLE support" -#~ msgstr " with OLE ¥µ¥Ý¡¼¥È" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit console version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 64 ¥Ó¥Ã¥È ¥³¥ó¥½¡¼¥ë ÈÇ" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit console version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 32 ¥Ó¥Ã¥È ¥³¥ó¥½¡¼¥ë ÈÇ" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16-bit version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 16 ¥Ó¥Ã¥È ÈÇ" - -#~ msgid "" -#~ "\n" -#~ "32-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "32 ¥Ó¥Ã¥È MS-DOS ÈÇ" - -#~ msgid "" -#~ "\n" -#~ "16-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "16 ¥Ó¥Ã¥È MS-DOS ÈÇ" - -#~ msgid "" -#~ "\n" -#~ "MacOS X (unix) version" -#~ msgstr "" -#~ "\n" -#~ "MacOS X (unix) ÈÇ" - -#~ msgid "" -#~ "\n" -#~ "MacOS X version" -#~ msgstr "" -#~ "\n" -#~ "MacOS X ÈÇ" - -#~ msgid "" -#~ "\n" -#~ "MacOS version" -#~ msgstr "" -#~ "\n" -#~ "MacOS ÈÇ" - -#~ msgid "" -#~ "\n" -#~ "OpenVMS version" -#~ msgstr "" -#~ "\n" -#~ "OpenVMS ÈÇ" - -#~ msgid "" -#~ "\n" -#~ "Big version " -#~ msgstr "" -#~ "\n" -#~ "Big ÈÇ " - -#~ msgid "" -#~ "\n" -#~ "Normal version " -#~ msgstr "" -#~ "\n" -#~ "Ä̾ï ÈÇ " - -#~ msgid "" -#~ "\n" -#~ "Small version " -#~ msgstr "" -#~ "\n" -#~ "Small ÈÇ " - -#~ msgid "" -#~ "\n" -#~ "Tiny version " -#~ msgstr "" -#~ "\n" -#~ "Tiny ÈÇ " - -#~ msgid "with GTK2-GNOME GUI." -#~ msgstr "with GTK2-GNOME GUI." +#, c-format +msgid "E118: Too many arguments for function: %s" +msgstr "E118: ´Ø¿ô¤Î°ú¿ô¤¬Â¿²á¤®¤Þ¤¹: %s" -#~ msgid "with GTK2 GUI." -#~ msgstr "with GTK2 GUI." +#, c-format +msgid "E716: Key not present in Dictionary: %s" +msgstr "E716: ¼½ñ·¿¤Ë¥¡¼¤¬Â¸ºß¤·¤Þ¤»¤ó: %s" -#~ msgid "with X11-Motif GUI." -#~ msgstr "with X11-Motif GUI." +msgid "E714: List required" +msgstr "E714: ¥ê¥¹¥È·¿¤¬É¬ÍפǤ¹" -#~ msgid "with X11-neXtaw GUI." -#~ msgstr "with X11-neXtaw GUI." +#, c-format +msgid "E712: Argument of %s must be a List or Dictionary" +msgstr "E712: %s ¤Î°ú¿ô¤Ï¥ê¥¹¥È·¿¤Þ¤¿¤Ï¼½ñ·¿¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" -#~ msgid "with X11-Athena GUI." -#~ msgstr "with X11-Athena GUI." +msgid "E47: Error while reading errorfile" +msgstr "E47: ¥¨¥é¡¼¥Õ¥¡¥¤¥ë¤ÎÆÉ¹þÃæ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤Þ¤·¤¿" -#~ msgid "with Photon GUI." -#~ msgstr "with Photon GUI." +msgid "E48: Not allowed in sandbox" +msgstr "E48: ¥µ¥ó¥É¥Ü¥Ã¥¯¥¹¤Ç¤Ïµö¤µ¤ì¤Þ¤»¤ó" -#~ msgid "with GUI." -#~ msgstr "with GUI." +msgid "E523: Not allowed here" +msgstr "E523: ¤³¤³¤Ç¤Ïµö²Ä¤µ¤ì¤Þ¤»¤ó" -#~ msgid "with Carbon GUI." -#~ msgstr "with Carbon GUI." +msgid "E359: Screen mode setting not supported" +msgstr "E359: ¥¹¥¯¥ê¡¼¥ó¥â¡¼¥É¤ÎÀßÄê¤Ë¤ÏÂбþ¤·¤Æ¤¤¤Þ¤»¤ó" -#~ msgid "with Cocoa GUI." -#~ msgstr "with Cocoa GUI." +msgid "E49: Invalid scroll size" +msgstr "E49: ̵¸ú¤Ê¥¹¥¯¥í¡¼¥ëÎ̤Ǥ¹" -#~ msgid "with (classic) GUI." -#~ msgstr "with (¥¯¥é¥·¥Ã¥¯) GUI." +msgid "E91: 'shell' option is empty" +msgstr "E91: 'shell' ¥ª¥×¥·¥ç¥ó¤¬¶õ¤Ç¤¹" -#~ msgid " system gvimrc file: \"" -#~ msgstr " ¥·¥¹¥Æ¥à gvimrc: \"" +msgid "E255: Couldn't read in sign data!" +msgstr "E255: sign ¤Î¥Ç¡¼¥¿¤òÆÉ¹þ¤á¤Þ¤»¤ó¤Ç¤·¤¿" -#~ msgid " user gvimrc file: \"" -#~ msgstr " ¥æ¡¼¥¶ gvimrc: \"" +msgid "E72: Close error on swap file" +msgstr "E72: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤Î¥¯¥í¡¼¥º»þ¥¨¥é¡¼¤Ç¤¹" -#~ msgid "2nd user gvimrc file: \"" -#~ msgstr " Âè2¥æ¡¼¥¶ gvimrc: \"" +msgid "E73: tag stack empty" +msgstr "E73: ¥¿¥°¥¹¥¿¥Ã¥¯¤¬¶õ¤Ç¤¹" -#~ msgid "3rd user gvimrc file: \"" -#~ msgstr " Âè3¥æ¡¼¥¶ gvimrc: \"" +msgid "E74: Command too complex" +msgstr "E74: ¥³¥Þ¥ó¥É¤¬Ê£»¨²á¤®¤Þ¤¹" -#~ msgid " system menu file: \"" -#~ msgstr " ¥·¥¹¥Æ¥à¥á¥Ë¥å¡¼: \"" +msgid "E75: Name too long" +msgstr "E75: ̾Á°¤¬Ä¹²á¤®¤Þ¤¹" -#~ msgid "Compiler: " -#~ msgstr "¥³¥ó¥Ñ¥¤¥é: " +msgid "E76: Too many [" +msgstr "E76: [ ¤¬Â¿²á¤®¤Þ¤¹" -#~ msgid "menu Help->Orphans for information " -#~ msgstr "¾ÜºÙ¤Ï¥á¥Ë¥å¡¼¤Î ¥Ø¥ë¥×¢ª¸É»ù ¤ò»²¾È¤·¤Æ²¼¤µ¤¤ " +msgid "E77: Too many file names" +msgstr "E77: ¥Õ¥¡¥¤¥ë̾¤¬Â¿²á¤®¤Þ¤¹" -#~ msgid "Running modeless, typed text is inserted" -#~ msgstr "¥â¡¼¥É̵¤Ç¼Â¹ÔÃæ, ¥¿¥¤¥×¤·¤¿Ê¸»ú¤¬ÁÞÆþ¤µ¤ì¤Þ¤¹" +msgid "E488: Trailing characters" +msgstr "E488: ;ʬ¤Êʸ»ú¤¬¸å¤í¤Ë¤¢¤ê¤Þ¤¹" -#~ msgid "menu Edit->Global Settings->Toggle Insert Mode " -#~ msgstr "¥á¥Ë¥å¡¼¤Î ÊÔ½¸¢ªÁ´ÂÎÀßÄꢪÁÞÆþ(½é¿´¼Ô)¥â¡¼¥ÉÀÚÂØ " +msgid "E78: Unknown mark" +msgstr "E78: ̤ÃΤΥޡ¼¥¯" -#~ msgid " for two modes " -#~ msgstr " ¤Ç¥â¡¼¥ÉÍ¤Ë " +msgid "E79: Cannot expand wildcards" +msgstr "E79: ¥ï¥¤¥ë¥É¥«¡¼¥É¤òŸ³«¤Ç¤¤Þ¤»¤ó" -#~ msgid "menu Edit->Global Settings->Toggle Vi Compatible" -#~ msgstr "¥á¥Ë¥å¡¼¤Î ÊÔ½¸¢ªÁ´ÂÎÀßÄꢪVi¸ß´¹¥â¡¼¥ÉÀÚÂØ " +msgid "E591: 'winheight' cannot be smaller than 'winminheight'" +msgstr "E591: 'winheight' ¤Ï 'winminheight' ¤è¤ê¾®¤µ¤¯¤Ç¤¤Þ¤»¤ó" -#~ msgid " for Vim defaults " -#~ msgstr " ¤ÇVim¤È¤·¤ÆÆ°ºî " +msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" +msgstr "E592: 'winwidth' ¤Ï 'winminwidth' ¤è¤ê¾®¤µ¤¯¤Ç¤¤Þ¤»¤ó" -#~ msgid "WARNING: Windows 95/98/ME detected" -#~ msgstr " ·Ù¹ð: Windows 95/98/Me ¤ò¸¡½Ð " +msgid "E80: Error while writing" +msgstr "E80: ½ñ¹þ¤ßÃæ¤Î¥¨¥é¡¼" -#~ msgid "type :help windows95<Enter> for info on this" -#~ msgstr " ¾ÜºÙ¤Ê¾ðÊó¤Ï :help windows95<Enter> " +msgid "Zero count" +msgstr "¥¼¥í¥«¥¦¥ó¥È" -#~ msgid "Edit with &multiple Vims" -#~ msgstr "Ê£¿ô¤ÎVim¤ÇÊÔ½¸¤¹¤ë (&M)" +msgid "E81: Using <SID> not in a script context" +msgstr "E81: ¥¹¥¯¥ê¥×¥È°Ê³°¤Ç<SID>¤¬»È¤ï¤ì¤Þ¤·¤¿" -#~ msgid "Edit with single &Vim" -#~ msgstr "1¤Ä¤ÎVim¤ÇÊÔ½¸¤¹¤ë (&V)" +msgid "E449: Invalid expression received" +msgstr "E449: ̵¸ú¤Ê¼°¤ò¼õ¤±¼è¤ê¤Þ¤·¤¿" -#~ msgid "Diff with Vim" -#~ msgstr "Vim¤Çº¹Ê¬¤òɽ¼¨¤¹¤ë" +msgid "E463: Region is guarded, cannot modify" +msgstr "E463: Îΰ褬Êݸ¤ì¤Æ¤¤¤ë¤Î¤Ç, Êѹ¹¤Ç¤¤Þ¤»¤ó" -#~ msgid "Edit with &Vim" -#~ msgstr "Vim¤ÇÊÔ½¸¤¹¤ë (&V)" +msgid "E744: NetBeans does not allow changes in read-only files" +msgstr "E744: NetBeans ¤ÏÆÉ¹þÀìÍÑ¥Õ¥¡¥¤¥ë¤òÊѹ¹¤¹¤ë¤³¤È¤òµö¤·¤Þ¤»¤ó" -#~ msgid "Edit with existing Vim - " -#~ msgstr "µ¯Æ°ºÑ¤ÎVim¤ÇÊÔ½¸¤¹¤ë - " +#, c-format +msgid "E685: Internal error: %s" +msgstr "E685: ÆâÉô¥¨¥é¡¼¤Ç¤¹: %s" -#~ msgid "Edits the selected file(s) with Vim" -#~ msgstr "ÁªÂò¤·¤¿¥Õ¥¡¥¤¥ë¤òVim¤ÇÊÔ½¸¤¹¤ë" +msgid "E363: pattern uses more memory than 'maxmempattern'" +msgstr "E363: ¥Ñ¥¿¡¼¥ó¤¬ 'maxmempattern' °Ê¾å¤Î¥á¥â¥ê¤ò»ÈÍѤ·¤Þ¤¹" -#~ msgid "Error creating process: Check if gvim is in your path!" -#~ msgstr "¥×¥í¥»¥¹¤ÎºîÀ®¤Ë¼ºÇÔ: gvim¤¬´Ä¶ÊÑ¿ôPATH¾å¤Ë¤¢¤ë¤«³Îǧ¤·¤Æ¤¯¤À¤µ¤¤!" +msgid "E749: empty buffer" +msgstr "E749: ¥Ð¥Ã¥Õ¥¡¤¬¶õ¤Ç¤¹" -#~ msgid "gvimext.dll error" -#~ msgstr "gvimext.dll ¥¨¥é¡¼" +#, c-format +msgid "E86: Buffer %ld does not exist" +msgstr "E86: ¥Ð¥Ã¥Õ¥¡ %ld ¤Ï¤¢¤ê¤Þ¤»¤ó" -#~ msgid "Path length too long!" -#~ msgstr "¥Ñ¥¹¤¬Ä¹¤¹¤®¤Þ¤¹!" +msgid "E682: Invalid search pattern or delimiter" +msgstr "E682: ¸¡º÷¥Ñ¥¿¡¼¥ó¤«¶èÀڤ굹椬ÉÔÀµ¤Ç¤¹" -#~ msgid "E234: Unknown fontset: %s" -#~ msgstr "E234: ̤ÃΤΥե©¥ó¥È¥»¥Ã¥È: %s" +msgid "E139: File is loaded in another buffer" +msgstr "E139: Ʊ¤¸Ì¾Á°¤Î¥Õ¥¡¥¤¥ë¤¬Â¾¤Î¥Ð¥Ã¥Õ¥¡¤ÇÆÉ¹þ¤Þ¤ì¤Æ¤¤¤Þ¤¹" -#~ msgid "E235: Unknown font: %s" -#~ msgstr "E235: ̤ÃΤΥե©¥ó¥È: %s" +#, c-format +msgid "E764: Option '%s' is not set" +msgstr "E764: ¥ª¥×¥·¥ç¥ó '%s' ¤ÏÀßÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó" -#~ msgid "E236: Font \"%s\" is not fixed-width" -#~ msgstr "E236: ¥Õ¥©¥ó¥È \"%s\" ¤Ï¸ÇÄêÉý¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó" +msgid "E850: Invalid register name" +msgstr "E850: ̵¸ú¤Ê¥ì¥¸¥¹¥¿Ì¾¤Ç¤¹" -#~ msgid "E448: Could not load library function %s" -#~ msgstr "E448: ¥é¥¤¥Ö¥é¥ê¤Î´Ø¿ô %s ¤ò¥í¡¼¥É¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" +#, c-format +msgid "E919: Directory not found in '%s': \"%s\"" +msgstr "E919: ¥Ç¥£¥ì¥¯¥È¥ê¤¬ '%s' ¤ÎÃæ¤Ë¤¢¤ê¤Þ¤»¤ó: \"%s\"" -#~ msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" -#~ msgstr "E26: ¥Ø¥Ö¥é¥¤¸ì¤Ï»ÈÍÑÉÔ²Äǽ¤Ç¤¹: ¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹\n" +msgid "search hit TOP, continuing at BOTTOM" +msgstr "¾å¤Þ¤Ç¸¡º÷¤·¤¿¤Î¤Ç²¼¤ËÌá¤ê¤Þ¤¹" -#~ msgid "E27: Farsi cannot be used: Not enabled at compile time\n" -#~ msgstr "E27: ¥Ú¥ë¥·¥¢¸ì¤Ï»ÈÍÑÉÔ²Äǽ¤Ç¤¹: ¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹\n" +msgid "search hit BOTTOM, continuing at TOP" +msgstr "²¼¤Þ¤Ç¸¡º÷¤·¤¿¤Î¤Ç¾å¤ËÌá¤ê¤Þ¤¹" -#~ msgid "E800: Arabic cannot be used: Not enabled at compile time\n" -#~ msgstr "" -#~ "E800: ¥¢¥é¥Ó¥¢¸ì¤Ï»ÈÍÑÉÔ²Äǽ¤Ç¤¹: ¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹\n" +#, c-format +msgid "Need encryption key for \"%s\"" +msgstr "°Å¹æ¥¡¼¤¬É¬ÍפǤ¹: \"%s\"" -#~ msgid "E247: no registered server named \"%s\"" -#~ msgstr "E247: %s ¤È¤¤¤¦Ì¾Á°¤ÎÅÐÏ¿¤µ¤ì¤¿¥µ¡¼¥Ð¤Ï¤¢¤ê¤Þ¤»¤ó" +msgid "empty keys are not allowed" +msgstr "¶õ¤Î¥¡¼¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" -#~ msgid "E233: cannot open display" -#~ msgstr "E233: ¥Ç¥£¥¹¥×¥ì¥¤¤ò³«¤±¤Þ¤»¤ó" +msgid "dictionary is locked" +msgstr "¼½ñ¤Ï¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤Þ¤¹" -#~ msgid "E449: Invalid expression received" -#~ msgstr "E449: ̵¸ú¤Ê¼°¤ò¼õ¤±¼è¤ê¤Þ¤·¤¿" +msgid "list is locked" +msgstr "¥ê¥¹¥È¤Ï¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤Þ¤¹" -#~ msgid "E463: Region is guarded, cannot modify" -#~ msgstr "E463: Îΰ褬Êݸ¤ì¤Æ¤¤¤ë¤Î¤Ç, Êѹ¹¤Ç¤¤Þ¤»¤ó" +#, c-format +msgid "failed to add key '%s' to dictionary" +msgstr "¼½ñ¤Ë¥¡¼ '%s' ¤òÄɲ乤ë¤Î¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#~ msgid "E744: NetBeans does not allow changes in read-only files" -#~ msgstr "E744: NetBeans ¤ÏÆÉ¹þÀìÍÑ¥Õ¥¡¥¤¥ë¤òÊѹ¹¤¹¤ë¤³¤È¤òµö¤·¤Þ¤»¤ó" +#, c-format +msgid "index must be int or slice, not %s" +msgstr "¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ï %s ¤Ç¤Ï¤Ê¤¯À°¿ô¤«¥¹¥é¥¤¥¹¤Ë¤·¤Æ¤¯¤À¤µ¤¤" -#~ msgid "Need encryption key for \"%s\"" -#~ msgstr "°Å¹æ¥¡¼¤¬É¬ÍפǤ¹: \"%s\"" +#, c-format +msgid "expected str() or unicode() instance, but got %s" +msgstr "str() ¤â¤·¤¯¤Ï unicode() ¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ë %s ¤Ç¤·¤¿" -#~ msgid "empty keys are not allowed" -#~ msgstr "¶õ¤Î¥¡¼¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" +#, c-format +msgid "expected bytes() or str() instance, but got %s" +msgstr "bytes() ¤â¤·¤¯¤Ï str() ¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ë %s ¤Ç¤·¤¿" -#~ msgid "dictionary is locked" -#~ msgstr "¼½ñ¤Ï¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤Þ¤¹" +#, c-format +msgid "" +"expected int(), long() or something supporting coercing to long(), but got %s" +msgstr "long() ¤«¤½¤ì¤ØÊÑ´¹²Äǽ¤Ê¤â¤Î¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ë %s ¤Ç¤·¤¿" -#~ msgid "list is locked" -#~ msgstr "¥ê¥¹¥È¤Ï¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤Þ¤¹" +#, c-format +msgid "expected int() or something supporting coercing to int(), but got %s" +msgstr "int() ¤«¤½¤ì¤ØÊÑ´¹²Äǽ¤Ê¤â¤Î¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ë %s ¤Ç¤·¤¿" -#~ msgid "failed to add key '%s' to dictionary" -#~ msgstr "¼½ñ¤Ë¥¡¼ '%s' ¤òÄɲ乤ë¤Î¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" +msgid "value is too large to fit into C int type" +msgstr "C¸À¸ì¤Î int ·¿¤È¤·¤Æ¤ÏÃͤ¬Â礲᤮¤Þ¤¹" -#~ msgid "index must be int or slice, not %s" -#~ msgstr "¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ï %s ¤Ç¤Ï¤Ê¤¯À°¿ô¤«¥¹¥é¥¤¥¹¤Ë¤·¤Æ¤¯¤À¤µ¤¤" +msgid "value is too small to fit into C int type" +msgstr "C¸À¸ì¤Î int ·¿¤È¤·¤Æ¤ÏÃͤ¬¾®¤µ²á¤®¤Þ¤¹" -#~ msgid "expected str() or unicode() instance, but got %s" -#~ msgstr "" -#~ "str() ¤â¤·¤¯¤Ï unicode() ¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ë %s ¤Ç¤·¤¿" +msgid "number must be greater than zero" +msgstr "¿ôÃÍ¤Ï 0 ¤è¤êÂ礤¯¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" -#~ msgid "expected bytes() or str() instance, but got %s" -#~ msgstr "bytes() ¤â¤·¤¯¤Ï str() ¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ë %s ¤Ç¤·¤¿" +msgid "number must be greater or equal to zero" +msgstr "¿ôÃÍ¤Ï 0 ¤«¤½¤ì°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" -#~ msgid "" -#~ "expected int(), long() or something supporting coercing to long(), but " -#~ "got %s" -#~ msgstr "long() ¤«¤½¤ì¤ØÊÑ´¹²Äǽ¤Ê¤â¤Î¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ë %s ¤Ç¤·¤¿" +msgid "can't delete OutputObject attributes" +msgstr "OutputObject°À¤ò¾Ã¤»¤Þ¤»¤ó" -#~ msgid "expected int() or something supporting coercing to int(), but got %s" -#~ msgstr "int() ¤«¤½¤ì¤ØÊÑ´¹²Äǽ¤Ê¤â¤Î¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ë %s ¤Ç¤·¤¿" +#, c-format +msgid "invalid attribute: %s" +msgstr "̵¸ú¤Ê°À¤Ç¤¹: %s" -#~ msgid "value is too large to fit into C int type" -#~ msgstr "C¸À¸ì¤Î int ·¿¤È¤·¤Æ¤ÏÃͤ¬Â礲᤮¤Þ¤¹" +msgid "E264: Python: Error initialising I/O objects" +msgstr "E264: Python: I/O¥ª¥Ö¥¸¥§¥¯¥È¤Î½é´ü²½¥¨¥é¡¼" -#~ msgid "value is too small to fit into C int type" -#~ msgstr "C¸À¸ì¤Î int ·¿¤È¤·¤Æ¤ÏÃͤ¬¾®¤µ²á¤®¤Þ¤¹" +msgid "failed to change directory" +msgstr "¼½ñ¤ÎÊѹ¹¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#~ msgid "number must be greater then zero" -#~ msgstr "¿ôÃÍ¤Ï 0 ¤è¤êÂ礤¯¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got %s" +msgstr "imp.find_module() ¤¬ %s ¤òÊÖ¤·¤Þ¤·¤¿ (´üÂÔÃÍ: 3 Í×ÁǤΥ¿¥×¥ë)" -#~ msgid "number must be greater or equal to zero" -#~ msgstr "¿ôÃÍ¤Ï 0 ¤«¤½¤ì°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got tuple of size %d" +msgstr "imp.find_module() ¤¬ %d Í×ÁǤΥ¿¥×¥ë¤òÊÖ¤·¤Þ¤·¤¿ (´üÂÔÃÍ: 3)" -#~ msgid "can't delete OutputObject attributes" -#~ msgstr "OutputObject°À¤ò¾Ã¤»¤Þ¤»¤ó" +msgid "internal error: imp.find_module returned tuple with NULL" +msgstr "ÆâÉô¥¨¥é¡¼: imp.find_module ¤¬ NULL ¤ò´Þ¤à¥¿¥×¥ë¤òÊÖ¤·¤Þ¤·¤¿" -#~ msgid "invalid attribute: %s" -#~ msgstr "̵¸ú¤Ê°À¤Ç¤¹: %s" +msgid "cannot delete vim.Dictionary attributes" +msgstr "vim.Dictionary°À¤Ï¾Ã¤»¤Þ¤»¤ó" -#~ msgid "E264: Python: Error initialising I/O objects" -#~ msgstr "E264: Python: I/O¥ª¥Ö¥¸¥§¥¯¥È¤Î½é´ü²½¥¨¥é¡¼" +msgid "cannot modify fixed dictionary" +msgstr "¸ÇÄꤵ¤ì¤¿¼½ñ¤ÏÊѹ¹¤Ç¤¤Þ¤»¤ó" -#~ msgid "failed to change directory" -#~ msgstr "¼½ñ¤ÎÊѹ¹¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" +#, c-format +msgid "cannot set attribute %s" +msgstr "°À %s ¤ÏÀßÄê¤Ç¤¤Þ¤»¤ó" -#~ msgid "expected 3-tuple as imp.find_module() result, but got %s" -#~ msgstr "imp.find_module() ¤¬ %s ¤òÊÖ¤·¤Þ¤·¤¿ (´üÂÔÃÍ: 2 Í×ÁǤΥ¿¥×¥ë)" +msgid "hashtab changed during iteration" +msgstr "¥¤¥Æ¥ì¡¼¥·¥ç¥óÃæ¤Ë hashtab ¤¬Êѹ¹¤µ¤ì¤Þ¤·¤¿" -#~ msgid "" -#~ "expected 3-tuple as imp.find_module() result, but got tuple of size %d" -#~ msgstr "impl.find_module() ¤¬ %d Í×ÁǤΥ¿¥×¥ë¤òÊÖ¤·¤Þ¤·¤¿ (´üÂÔÃÍ: 2)" +#, c-format +msgid "expected sequence element of size 2, but got sequence of size %d" +msgstr "¥·¡¼¥±¥ó¥¹¤ÎÍ×ÁÇ¿ô¤Ë¤Ï 2 ¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤Þ¤·¤¿¤¬ %d ¤Ç¤·¤¿" -#~ msgid "internal error: imp.find_module returned tuple with NULL" -#~ msgstr "ÆâÉô¥¨¥é¡¼: imp.find_module ¤¬ NULL ¤ò´Þ¤à¥¿¥×¥ë¤òÊÖ¤·¤Þ¤·¤¿" +msgid "list constructor does not accept keyword arguments" +msgstr "¥ê¥¹¥È¤Î¥³¥ó¥¹¥È¥é¥¯¥¿¤Ï¥¡¼¥ï¡¼¥É°ú¿ô¤ò¼õ¤±ÉÕ¤±¤Þ¤»¤ó" -#~ msgid "cannot delete vim.Dictionary attributes" -#~ msgstr "vim.Dictionary°À¤Ï¾Ã¤»¤Þ¤»¤ó" +msgid "list index out of range" +msgstr "¥ê¥¹¥ÈÈϰϳ°¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ç¤¹" -#~ msgid "cannot modify fixed dictionary" -#~ msgstr "¸ÇÄꤵ¤ì¤¿¼½ñ¤ÏÊѹ¹¤Ç¤¤Þ¤»¤ó" +#. No more suitable format specifications in python-2.3 +#, c-format +msgid "internal error: failed to get vim list item %d" +msgstr "ÆâÉô¥¨¥é¡¼: vim¤Î¥ê¥¹¥ÈÍ×ÁÇ %d ¤Î¼èÆÀ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#~ msgid "cannot set attribute %s" -#~ msgstr "°À %s ¤ÏÀßÄê¤Ç¤¤Þ¤»¤ó" +msgid "slice step cannot be zero" +msgstr "¥¹¥é¥¤¥¹¤Î¥¹¥Æ¥Ã¥×¤Ë 0 ¤Ï»ØÄê¤Ç¤¤Þ¤»¤ó" -#~ msgid "hashtab changed during iteration" -#~ msgstr "¥¤¥Æ¥ì¡¼¥·¥ç¥óÃæ¤Ë hashtab ¤¬Êѹ¹¤µ¤ì¤Þ¤·¤¿" +#, c-format +msgid "attempt to assign sequence of size greater than %d to extended slice" +msgstr "Ťµ %d ¤Î³ÈÄ¥¥¹¥é¥¤¥¹¤Ë¡¢¤è¤êŤ¤¥¹¥é¥¤¥¹¤ò³ä¤êÅö¤Æ¤è¤¦¤È¤·¤Þ¤·¤¿" -#~ msgid "expected sequence element of size 2, but got sequence of size %d" -#~ msgstr "¥·¡¼¥±¥ó¥¹¤ÎÍ×ÁÇ¿ô¤Ë¤Ï 2 ¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤Þ¤·¤¿¤¬ %d ¤Ç¤·¤¿" +#, c-format +msgid "internal error: no vim list item %d" +msgstr "ÆâÉô¥¨¥é¡¼: vim¤Î¥ê¥¹¥ÈÍ×ÁÇ %d ¤Ï¤¢¤ê¤Þ¤»¤ó" -#~ msgid "list constructor does not accept keyword arguments" -#~ msgstr "¥ê¥¹¥È¤Î¥³¥ó¥¹¥È¥é¥¯¥¿¤Ï¥¡¼¥ï¡¼¥É°ú¿ô¤ò¼õ¤±ÉÕ¤±¤Þ¤»¤ó" +msgid "internal error: not enough list items" +msgstr "ÆâÉô¥¨¥é¡¼: ¥ê¥¹¥È¤Ë½½Ê¬¤ÊÍ×ÁǤ¬¤¢¤ê¤Þ¤»¤ó" -#~ msgid "list index out of range" -#~ msgstr "¥ê¥¹¥ÈÈϰϳ°¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ç¤¹" +msgid "internal error: failed to add item to list" +msgstr "ÆâÉô¥¨¥é¡¼: ¥ê¥¹¥È¤Ø¤ÎÍ×ÁÇÄɲä˼ºÇÔ¤·¤Þ¤·¤¿" -#~ msgid "internal error: failed to get vim list item %d" -#~ msgstr "ÆâÉô¥¨¥é¡¼: vim¤Î¥ê¥¹¥ÈÍ×ÁÇ %d ¤Î¼èÆÀ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" +#, c-format +msgid "attempt to assign sequence of size %d to extended slice of size %d" +msgstr "Ťµ %d ¤Î¥¹¥é¥¤¥¹¤ò %d ¤Î³ÈÄ¥¥¹¥é¥¤¥¹¤Ë³ä¤êÅö¤Æ¤è¤¦¤È¤·¤Þ¤·¤¿" -#~ msgid "failed to add item to list" -#~ msgstr "¥ê¥¹¥È¤Ø¤ÎÍ×ÁÇÄɲä˼ºÇÔ¤·¤Þ¤·¤¿" +msgid "failed to add item to list" +msgstr "¥ê¥¹¥È¤Ø¤ÎÍ×ÁÇÄɲä˼ºÇÔ¤·¤Þ¤·¤¿" -#~ msgid "internal error: no vim list item %d" -#~ msgstr "ÆâÉô¥¨¥é¡¼: vim¤Î¥ê¥¹¥ÈÍ×ÁÇ %d ¤Ï¤¢¤ê¤Þ¤»¤ó" +msgid "cannot delete vim.List attributes" +msgstr "vim.List °À¤Ï¾Ã¤»¤Þ¤»¤ó" -#~ msgid "internal error: failed to add item to list" -#~ msgstr "ÆâÉô¥¨¥é¡¼: ¥ê¥¹¥È¤Ø¤ÎÍ×ÁÇÄɲä˼ºÇÔ¤·¤Þ¤·¤¿" +msgid "cannot modify fixed list" +msgstr "¸ÇÄꤵ¤ì¤¿¥ê¥¹¥È¤ÏÊѹ¹¤Ç¤¤Þ¤»¤ó" -#~ msgid "cannot delete vim.List attributes" -#~ msgstr "vim.List °À¤Ï¾Ã¤»¤Þ¤»¤ó" +#, c-format +msgid "unnamed function %s does not exist" +msgstr "̵̾´Ø¿ô %s ¤Ï¸ºß¤·¤Þ¤»¤ó" -#~ msgid "cannot modify fixed list" -#~ msgstr "¸ÇÄꤵ¤ì¤¿¥ê¥¹¥È¤ÏÊѹ¹¤Ç¤¤Þ¤»¤ó" +#, c-format +msgid "function %s does not exist" +msgstr "´Ø¿ô %s ¤¬¤¢¤ê¤Þ¤»¤ó" -#~ msgid "unnamed function %s does not exist" -#~ msgstr "̵̾´Ø¿ô %s ¤Ï¸ºß¤·¤Þ¤»¤ó" +#, c-format +msgid "failed to run function %s" +msgstr "´Ø¿ô %s ¤Î¼Â¹Ô¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#~ msgid "function %s does not exist" -#~ msgstr "´Ø¿ô %s ¤¬¤¢¤ê¤Þ¤»¤ó" +msgid "unable to get option value" +msgstr "¥ª¥×¥·¥ç¥ó¤ÎÃͤϼèÆÀ¤Ç¤¤Þ¤»¤ó" -#~ msgid "function constructor does not accept keyword arguments" -#~ msgstr "´Ø¿ô¤Î¥³¥ó¥¹¥È¥é¥¯¥¿¤Ï¥¡¼¥ï¡¼¥É°ú¿ô¤ò¼õ¤±ÉÕ¤±¤Þ¤»¤ó" +msgid "internal error: unknown option type" +msgstr "ÆâÉô¥¨¥é¡¼: ̤ÃΤΥª¥×¥·¥ç¥ó·¿¤Ç¤¹" -#~ msgid "failed to run function %s" -#~ msgstr "´Ø¿ô %s ¤Î¼Â¹Ô¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" +msgid "problem while switching windows" +msgstr "¥¦¥£¥ó¥É¥¦¤òÀÚ´¹Ãæ¤ËÌäÂ꤬ȯÀ¸¤·¤Þ¤·¤¿" -#~ msgid "problem while switching windows" -#~ msgstr "¥¦¥£¥ó¥É¥¦¤òÀÚ´¹Ãæ¤ËÌäÂ꤬ȯÀ¸¤·¤Þ¤·¤¿" +#, c-format +msgid "unable to unset global option %s" +msgstr "¥°¥í¡¼¥Ð¥ë¥ª¥×¥·¥ç¥ó %s ¤ÎÀßÄê²ò½ü¤Ï¤Ç¤¤Þ¤»¤ó" -#~ msgid "unable to unset global option %s" -#~ msgstr "¥°¥í¡¼¥Ð¥ë¥ª¥×¥·¥ç¥ó %s ¤ÎÀßÄê²ò½ü¤Ï¤Ç¤¤Þ¤»¤ó" +#, c-format +msgid "unable to unset option %s which does not have global value" +msgstr "¥°¥í¡¼¥Ð¥ë¤ÊÃͤÎ̵¤¤¥ª¥×¥·¥ç¥ó %s ¤ÎÀßÄê²ò½ü¤Ï¤Ç¤¤Þ¤»¤ó" -#~ msgid "unable to unset option %s which does not have global value" -#~ msgstr "¥°¥í¡¼¥Ð¥ë¤ÊÃͤÎ̵¤¤¥ª¥×¥·¥ç¥ó %s ¤ÎÀßÄê²ò½ü¤Ï¤Ç¤¤Þ¤»¤ó" +msgid "attempt to refer to deleted tab page" +msgstr "ºï½ü¤µ¤ì¤¿¥¿¥Ö¤ò»²¾È¤·¤è¤¦¤È¤·¤Þ¤·¤¿" -#~ msgid "attempt to refer to deleted tab page" -#~ msgstr "ºï½ü¤µ¤ì¤¿¥¿¥Ö¤ò»²¾È¤·¤è¤¦¤È¤·¤Þ¤·¤¿" +msgid "no such tab page" +msgstr "¤½¤Î¤è¤¦¤Ê¥¿¥Ö¥Ú¡¼¥¸¤Ï¤¢¤ê¤Þ¤»¤ó" -#~ msgid "no such tab page" -#~ msgstr "¤½¤Î¤è¤¦¤Ê¥¿¥Ö¥Ú¡¼¥¸¤Ï¤¢¤ê¤Þ¤»¤ó" +msgid "attempt to refer to deleted window" +msgstr "ºï½ü¤µ¤ì¤¿¥¦¥£¥ó¥É¥¦¤ò»²¾È¤·¤è¤¦¤È¤·¤Þ¤·¤¿" -#~ msgid "attempt to refer to deleted window" -#~ msgstr "ºï½ü¤µ¤ì¤¿¥¦¥£¥ó¥É¥¦¤ò»²¾È¤·¤è¤¦¤È¤·¤Þ¤·¤¿" +msgid "readonly attribute: buffer" +msgstr "ÆÉ¹þÀìÍѰÀ: ¥Ð¥Ã¥Õ¥¡¡¼" -#~ msgid "readonly attribute: buffer" -#~ msgstr "ÆÉ¹þÀìÍѰÀ: ¥Ð¥Ã¥Õ¥¡¡¼" +msgid "cursor position outside buffer" +msgstr "¥«¡¼¥½¥ë°ÌÃÖ¤¬¥Ð¥Ã¥Õ¥¡¤Î³°Â¦¤Ç¤¹" -#~ msgid "cursor position outside buffer" -#~ msgstr "¥«¡¼¥½¥ë°ÌÃÖ¤¬¥Ð¥Ã¥Õ¥¡¤Î³°Â¦¤Ç¤¹" +msgid "no such window" +msgstr "¤½¤Î¤è¤¦¤Ê¥¦¥£¥ó¥É¥¦¤Ï¤¢¤ê¤Þ¤»¤ó" -#~ msgid "no such window" -#~ msgstr "¤½¤Î¤è¤¦¤Ê¥¦¥£¥ó¥É¥¦¤Ï¤¢¤ê¤Þ¤»¤ó" +msgid "attempt to refer to deleted buffer" +msgstr "ºï½ü¤µ¤ì¤¿¥Ð¥Ã¥Õ¥¡¤ò»²¾È¤·¤è¤¦¤È¤·¤Þ¤·¤¿" -#~ msgid "attempt to refer to deleted buffer" -#~ msgstr "ºï½ü¤µ¤ì¤¿¥Ð¥Ã¥Õ¥¡¤ò»²¾È¤·¤è¤¦¤È¤·¤Þ¤·¤¿" +msgid "failed to rename buffer" +msgstr "¥Ð¥Ã¥Õ¥¡Ì¾¤ÎÊѹ¹¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#~ msgid "failed to rename buffer" -#~ msgstr "¥Ð¥Ã¥Õ¥¡Ì¾¤ÎÊѹ¹¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" +msgid "mark name must be a single character" +msgstr "¥Þ¡¼¥¯Ì¾¤Ï1ʸ»ú¤Î¥¢¥ë¥Õ¥¡¥Ù¥Ã¥È¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" -#~ msgid "mark name must be a single character" -#~ msgstr "¥Þ¡¼¥¯Ì¾¤Ï1ʸ»ú¤Î¥¢¥ë¥Õ¥¡¥Ù¥Ã¥È¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó" +#, c-format +msgid "expected vim.Buffer object, but got %s" +msgstr "vim.Buffer¥ª¥Ö¥¸¥§¥¯¥È¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ë %s ¤Ç¤·¤¿" -#~ msgid "expected vim.Buffer object, but got %s" -#~ msgstr "vim.Buffer¥ª¥Ö¥¸¥§¥¯¥È¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ë %s ¤Ç¤·¤¿" +#, c-format +msgid "failed to switch to buffer %d" +msgstr "»ØÄꤵ¤ì¤¿¥Ð¥Ã¥Õ¥¡ %d ¤Ø¤ÎÀÚ¤êÂØ¤¨¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#~ msgid "failed to switch to buffer %d" -#~ msgstr "»ØÄꤵ¤ì¤¿¥Ð¥Ã¥Õ¥¡ %d ¤Ø¤ÎÀÚ¤êÂØ¤¨¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" +#, c-format +msgid "expected vim.Window object, but got %s" +msgstr "vim.Window¥ª¥Ö¥¸¥§¥¯¥È¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ë %s ¤Ç¤·¤¿" -#~ msgid "expected vim.Window object, but got %s" -#~ msgstr "vim.Window¥ª¥Ö¥¸¥§¥¯¥È¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ë %s ¤Ç¤·¤¿" +msgid "failed to find window in the current tab page" +msgstr "¸½ºß¤Î¥¿¥Ö¤Ë¤Ï»ØÄꤵ¤ì¤¿¥¦¥£¥ó¥É¥¦¤¬¤¢¤ê¤Þ¤»¤ó¤Ç¤·¤¿" -#~ msgid "failed to find window in the current tab page" -#~ msgstr "¸½ºß¤Î¥¿¥Ö¤Ë¤Ï»ØÄꤵ¤ì¤¿¥¦¥£¥ó¥É¥¦¤¬¤¢¤ê¤Þ¤»¤ó¤Ç¤·¤¿" +msgid "did not switch to the specified window" +msgstr "»ØÄꤵ¤ì¤¿¥¦¥£¥ó¥É¥¦¤ËÀÚ¤êÂØ¤¨¤Þ¤»¤ó¤Ç¤·¤¿" -#~ msgid "did not switch to the specified window" -#~ msgstr "»ØÄꤵ¤ì¤¿¥¦¥£¥ó¥É¥¦¤ËÀÚ¤êÂØ¤¨¤Þ¤»¤ó¤Ç¤·¤¿" +#, c-format +msgid "expected vim.TabPage object, but got %s" +msgstr "vim.TabPage¥ª¥Ö¥¸¥§¥¯¥È¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ë %s ¤Ç¤·¤¿" -#~ msgid "expected vim.TabPage object, but got %s" -#~ msgstr "vim.TabPage¥ª¥Ö¥¸¥§¥¯¥È¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ë %s ¤Ç¤·¤¿" +msgid "did not switch to the specified tab page" +msgstr "»ØÄꤵ¤ì¤¿¥¿¥Ö¥Ú¡¼¥¸¤ËÀÚ¤êÂØ¤¨¤Þ¤»¤ó¤Ç¤·¤¿" -#~ msgid "did not switch to the specified tab page" -#~ msgstr "»ØÄꤵ¤ì¤¿¥¿¥Ö¥Ú¡¼¥¸¤ËÀÚ¤êÂØ¤¨¤Þ¤»¤ó¤Ç¤·¤¿" +msgid "failed to run the code" +msgstr "¥³¡¼¥É¤Î¼Â¹Ô¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" -#~ msgid "failed to run the code" -#~ msgstr "¥³¡¼¥É¤Î¼Â¹Ô¤Ë¼ºÇÔ¤·¤Þ¤·¤¿" +msgid "E858: Eval did not return a valid python object" +msgstr "E858: ¼°É¾²Á¤Ï͸ú¤Êpython¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤·¤Þ¤»¤ó¤Ç¤·¤¿" -#~ msgid "E858: Eval did not return a valid python object" -#~ msgstr "E858: ¼°É¾²Á¤Ï͸ú¤Êpython¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤·¤Þ¤»¤ó¤Ç¤·¤¿" +msgid "E859: Failed to convert returned python object to vim value" +msgstr "E859: ÊÖ¤µ¤ì¤¿python¥ª¥Ö¥¸¥§¥¯¥È¤òvim¤ÎÃͤËÊÑ´¹¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" -#~ msgid "E859: Failed to convert returned python object to vim value" -#~ msgstr "E859: ÊÖ¤µ¤ì¤¿python¥ª¥Ö¥¸¥§¥¯¥È¤òvim¤ÎÃͤËÊÑ´¹¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" +#, c-format +msgid "unable to convert %s to vim dictionary" +msgstr "%s vim¤Î¼½ñ·¿¤ËÊÑ´¹¤Ç¤¤Þ¤»¤ó" -#~ msgid "unable to convert %s to vim dictionary" -#~ msgstr "%s vim¤Î¼½ñ·¿¤ËÊÑ´¹¤Ç¤¤Þ¤»¤ó" +#, c-format +msgid "unable to convert %s to vim list" +msgstr "%s ¤òvim¤Î¥ê¥¹¥È¤ËÊÑ´¹¤Ç¤¤Þ¤»¤ó" -#~ msgid "unable to convert %s to vim structure" -#~ msgstr "%s ¤òvim¤Î¹½Â¤ÂΤËÊÑ´¹¤Ç¤¤Þ¤»¤ó" +#, c-format +msgid "unable to convert %s to vim structure" +msgstr "%s ¤òvim¤Î¹½Â¤ÂΤËÊÑ´¹¤Ç¤¤Þ¤»¤ó" -#~ msgid "internal error: NULL reference passed" -#~ msgstr "ÆâÉô¥¨¥é¡¼: NULL»²¾È¤¬ÅϤµ¤ì¤Þ¤·¤¿" +msgid "internal error: NULL reference passed" +msgstr "ÆâÉô¥¨¥é¡¼: NULL»²¾È¤¬ÅϤµ¤ì¤Þ¤·¤¿" -#~ msgid "internal error: invalid value type" -#~ msgstr "ÆâÉô¥¨¥é¡¼: ̵¸ú¤ÊÃÍ·¿¤Ç¤¹" +msgid "internal error: invalid value type" +msgstr "ÆâÉô¥¨¥é¡¼: ̵¸ú¤ÊÃÍ·¿¤Ç¤¹" -#~ msgid "" -#~ "Failed to set path hook: sys.path_hooks is not a list\n" -#~ "You should now do the following:\n" -#~ "- append vim.path_hook to sys.path_hooks\n" -#~ "- append vim.VIM_SPECIAL_PATH to sys.path\n" -#~ msgstr "" -#~ "¥Ñ¥¹¥Õ¥Ã¥¯¤ÎÀßÄê¤Ë¼ºÇÔ¤·¤Þ¤·¤¿: sys.path_hooks ¤¬¥ê¥¹¥È¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó\n" -#~ "¤¹¤°¤Ë²¼µ¤ò¼Â»Ü¤·¤Æ¤¯¤À¤µ¤¤:\n" -#~ "- vim.path_hooks ¤ò sys.path_hooks ¤ØÄɲÃ\n" -#~ "- vim.VIM_SPECIAL_PATH ¤ò sys.path ¤ØÄɲÃ\n" +msgid "" +"Failed to set path hook: sys.path_hooks is not a list\n" +"You should now do the following:\n" +"- append vim.path_hook to sys.path_hooks\n" +"- append vim.VIM_SPECIAL_PATH to sys.path\n" +msgstr "" +"¥Ñ¥¹¥Õ¥Ã¥¯¤ÎÀßÄê¤Ë¼ºÇÔ¤·¤Þ¤·¤¿: sys.path_hooks ¤¬¥ê¥¹¥È¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó\n" +"¤¹¤°¤Ë²¼µ¤ò¼Â»Ü¤·¤Æ¤¯¤À¤µ¤¤:\n" +"- vim.path_hooks ¤ò sys.path_hooks ¤ØÄɲÃ\n" +"- vim.VIM_SPECIAL_PATH ¤ò sys.path ¤ØÄɲÃ\n" -#~ msgid "" -#~ "Failed to set path: sys.path is not a list\n" -#~ "You should now append vim.VIM_SPECIAL_PATH to sys.path" -#~ msgstr "" -#~ "¥Ñ¥¹¤ÎÀßÄê¤Ë¼ºÇÔ¤·¤Þ¤·¤¿: sys.path ¤¬¥ê¥¹¥È¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó\n" -#~ "¤¹¤°¤Ë vim.VIM_SPECIAL_PATH ¤ò sys.path ¤ËÄɲ䷤Ƥ¯¤À¤µ¤¤" +msgid "" +"Failed to set path: sys.path is not a list\n" +"You should now append vim.VIM_SPECIAL_PATH to sys.path" +msgstr "" +"¥Ñ¥¹¤ÎÀßÄê¤Ë¼ºÇÔ¤·¤Þ¤·¤¿: sys.path ¤¬¥ê¥¹¥È¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó\n" +"¤¹¤°¤Ë vim.VIM_SPECIAL_PATH ¤ò sys.path ¤ËÄɲ䷤Ƥ¯¤À¤µ¤¤" diff --git a/src/nvim/po/ja.po b/src/nvim/po/ja.po index e12cfb7e70..5cb789c93e 100644 --- a/src/nvim/po/ja.po +++ b/src/nvim/po/ja.po @@ -1,3 +1,4 @@ + # Japanese translation for Vim # # Do ":help uganda" in Vim to read copying and usage conditions. @@ -14,213 +15,176 @@ msgid "" msgstr "" "Project-Id-Version: Vim 7.4\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-02-01 09:02+0900\n" -"PO-Revision-Date: 2013-06-02-01 09:08+09n" +"POT-Creation-Date: 2016-09-10 21:10+0900\n" +"PO-Revision-Date: 2016-09-10 21:20+0900\n" "Last-Translator: MURAOKA Taro <koron.kaoriya@gmail.com>\n" "Language-Team: vim-jp (https://github.com/vim-jp/lang-ja)\n" "Language: Japanese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8-bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" -#: ../api/private/helpers.c:201 -#, fuzzy -msgid "Unable to get option value" -msgstr "オプションã®å€¤ã¯å–å¾—ã§ãã¾ã›ã‚“" +msgid "E831: bf_key_init() called with empty password" +msgstr "E831: bf_key_init() ãŒç©ºãƒ‘スワードã§å‘¼ã³å‡ºã•れã¾ã—ãŸ" -#: ../api/private/helpers.c:204 -msgid "internal error: unknown option type" -msgstr "内部エラー: 未知ã®ã‚ªãƒ—ション型ã§ã™" +msgid "E820: sizeof(uint32_t) != 4" +msgstr "E820: sizeof(uint32_t) != 4" + +msgid "E817: Blowfish big/little endian use wrong" +msgstr "E817: Blowfishæš—å·ã®ãƒ“ッグ/リトルエンディアンãŒé–“é•ã£ã¦ã„ã¾ã™" + +msgid "E818: sha256 test failed" +msgstr "E818: sha256ã®ãƒ†ã‚¹ãƒˆã«å¤±æ•—ã—ã¾ã—ãŸ" + +msgid "E819: Blowfish test failed" +msgstr "E819: Blowfishæš—å·ã®ãƒ†ã‚¹ãƒˆã«å¤±æ•—ã—ã¾ã—ãŸ" -#: ../buffer.c:92 msgid "[Location List]" msgstr "[ãƒã‚±ãƒ¼ã‚·ãƒ§ãƒ³ãƒªã‚¹ãƒˆ]" -#: ../buffer.c:93 msgid "[Quickfix List]" msgstr "[Quickfixリスト]" -#: ../buffer.c:94 msgid "E855: Autocommands caused command to abort" msgstr "E855: autocommandãŒã‚³ãƒžãƒ³ãƒ‰ã®åœæ¢ã‚’引ãèµ·ã“ã—ã¾ã—ãŸ" -#: ../buffer.c:135 msgid "E82: Cannot allocate any buffer, exiting..." msgstr "E82: ãƒãƒƒãƒ•ã‚¡ã‚’1ã¤ã‚‚作æˆã§ããªã„ã®ã§, 終了ã—ã¾ã™..." -#: ../buffer.c:138 msgid "E83: Cannot allocate buffer, using other one..." msgstr "E83: ãƒãƒƒãƒ•ァを作æˆã§ããªã„ã®ã§, ä»–ã®ã‚’使用ã—ã¾ã™..." -#: ../buffer.c:763 +msgid "E931: Buffer cannot be registered" +msgstr "E931: ãƒãƒƒãƒ•ァを登録ã§ãã¾ã›ã‚“" + +msgid "E937: Attempt to delete a buffer that is in use" +msgstr "E937: 使用ä¸ã®ãƒãƒƒãƒ•ァを削除ã—よã†ã¨è©¦ã¿ã¾ã—ãŸ" + msgid "E515: No buffers were unloaded" msgstr "E515: 解放ã•れãŸãƒãƒƒãƒ•ã‚¡ã¯ã‚りã¾ã›ã‚“" -#: ../buffer.c:765 msgid "E516: No buffers were deleted" msgstr "E516: 削除ã•れãŸãƒãƒƒãƒ•ã‚¡ã¯ã‚りã¾ã›ã‚“" -#: ../buffer.c:767 msgid "E517: No buffers were wiped out" msgstr "E517: ç ´æ£„ã•れãŸãƒãƒƒãƒ•ã‚¡ã¯ã‚りã¾ã›ã‚“" -#: ../buffer.c:772 msgid "1 buffer unloaded" msgstr "1 個ã®ãƒãƒƒãƒ•ã‚¡ãŒè§£æ”¾ã•れã¾ã—ãŸ" -#: ../buffer.c:774 #, c-format msgid "%d buffers unloaded" msgstr "%d 個ã®ãƒãƒƒãƒ•ã‚¡ãŒè§£æ”¾ã•れã¾ã—ãŸ" -#: ../buffer.c:777 msgid "1 buffer deleted" msgstr "1 個ã®ãƒãƒƒãƒ•ã‚¡ãŒå‰Šé™¤ã•れã¾ã—ãŸ" -#: ../buffer.c:779 #, c-format msgid "%d buffers deleted" msgstr "%d 個ã®ãƒãƒƒãƒ•ã‚¡ãŒå‰Šé™¤ã•れã¾ã—ãŸ" -#: ../buffer.c:782 msgid "1 buffer wiped out" msgstr "1 個ã®ãƒãƒƒãƒ•ã‚¡ãŒç ´æ£„ã•れã¾ã—ãŸ" -#: ../buffer.c:784 #, c-format msgid "%d buffers wiped out" msgstr "%d 個ã®ãƒãƒƒãƒ•ã‚¡ãŒç ´æ£„ã•れã¾ã—ãŸ" -#: ../buffer.c:806 msgid "E90: Cannot unload last buffer" msgstr "E90: 最後ã®ãƒãƒƒãƒ•ã‚¡ã¯è§£æ”¾ã§ãã¾ã›ã‚“" -#: ../buffer.c:874 msgid "E84: No modified buffer found" msgstr "E84: 変更ã•れãŸãƒãƒƒãƒ•ã‚¡ã¯ã‚りã¾ã›ã‚“" #. back where we started, didn't find anything. -#: ../buffer.c:903 msgid "E85: There is no listed buffer" msgstr "E85: リスト表示ã•れるãƒãƒƒãƒ•ã‚¡ã¯ã‚りã¾ã›ã‚“" -#: ../buffer.c:913 -#, c-format -msgid "E86: Buffer %<PRId64> does not exist" -msgstr "E86: ãƒãƒƒãƒ•ã‚¡ %<PRId64> ã¯ã‚りã¾ã›ã‚“" - -#: ../buffer.c:915 msgid "E87: Cannot go beyond last buffer" msgstr "E87: 最後ã®ãƒãƒƒãƒ•ã‚¡ã‚’è¶Šãˆã¦ç§»å‹•ã¯ã§ãã¾ã›ã‚“" -#: ../buffer.c:917 msgid "E88: Cannot go before first buffer" msgstr "E88: 最åˆã®ãƒãƒƒãƒ•ァよりå‰ã¸ã¯ç§»å‹•ã§ãã¾ã›ã‚“" -#: ../buffer.c:945 #, c-format -msgid "" -"E89: No write since last change for buffer %<PRId64> (add ! to override)" -msgstr "E89: ãƒãƒƒãƒ•ã‚¡ %<PRId64> ã®å¤‰æ›´ã¯ä¿å˜ã•れã¦ã„ã¾ã›ã‚“ (! ã§å¤‰æ›´ã‚’ç ´æ£„)" +msgid "E89: No write since last change for buffer %ld (add ! to override)" +msgstr "E89: ãƒãƒƒãƒ•ã‚¡ %ld ã®å¤‰æ›´ã¯ä¿å˜ã•れã¦ã„ã¾ã›ã‚“ (! ã§å¤‰æ›´ã‚’ç ´æ£„)" -#. wrap around (may cause duplicates) -#: ../buffer.c:1423 msgid "W14: Warning: List of file names overflow" msgstr "W14: è¦å‘Š: ファイルåã®ãƒªã‚¹ãƒˆãŒé•·éŽãŽã¾ã™" -#: ../buffer.c:1555 ../quickfix.c:3361 #, c-format -msgid "E92: Buffer %<PRId64> not found" -msgstr "E92: ãƒãƒƒãƒ•ã‚¡ %<PRId64> ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" +msgid "E92: Buffer %ld not found" +msgstr "E92: ãƒãƒƒãƒ•ã‚¡ %ld ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../buffer.c:1798 #, c-format msgid "E93: More than one match for %s" msgstr "E93: %s ã«è¤‡æ•°ã®è©²å½“ãŒã‚りã¾ã—ãŸ" -#: ../buffer.c:1800 #, c-format msgid "E94: No matching buffer for %s" msgstr "E94: %s ã«è©²å½“ã™ã‚‹ãƒãƒƒãƒ•ã‚¡ã¯ã‚りã¾ã›ã‚“ã§ã—ãŸ" -#: ../buffer.c:2161 #, c-format -msgid "line %<PRId64>" -msgstr "行 %<PRId64>" +msgid "line %ld" +msgstr "行 %ld" -#: ../buffer.c:2233 msgid "E95: Buffer with this name already exists" msgstr "E95: ã“ã®åå‰ã®ãƒãƒƒãƒ•ã‚¡ã¯æ—¢ã«ã‚りã¾ã™" -#: ../buffer.c:2498 msgid " [Modified]" msgstr " [変更ã‚り]" -#: ../buffer.c:2501 msgid "[Not edited]" msgstr "[未編集]" -#: ../buffer.c:2504 msgid "[New file]" msgstr "[新ファイル]" -#: ../buffer.c:2505 msgid "[Read errors]" msgstr "[èªè¾¼ã‚¨ãƒ©ãƒ¼]" -#: ../buffer.c:2506 ../buffer.c:3217 ../fileio.c:1807 ../screen.c:4895 msgid "[RO]" msgstr "[èªå°‚]" -#: ../buffer.c:2507 ../fileio.c:1807 msgid "[readonly]" msgstr "[èªè¾¼å°‚用]" -#: ../buffer.c:2524 #, c-format msgid "1 line --%d%%--" msgstr "1 行 --%d%%--" -#: ../buffer.c:2526 #, c-format -msgid "%<PRId64> lines --%d%%--" -msgstr "%<PRId64> 行 --%d%%--" +msgid "%ld lines --%d%%--" +msgstr "%ld 行 --%d%%--" -#: ../buffer.c:2530 #, c-format -msgid "line %<PRId64> of %<PRId64> --%d%%-- col " -msgstr "行 %<PRId64> (全体 %<PRId64>) --%d%%-- col " +msgid "line %ld of %ld --%d%%-- col " +msgstr "行 %ld (全体 %ld) --%d%%-- col " -#: ../buffer.c:2632 ../buffer.c:4292 ../memline.c:1554 msgid "[No Name]" msgstr "[ç„¡å]" #. must be a help buffer -#: ../buffer.c:2667 msgid "help" msgstr "ヘルプ" -#: ../buffer.c:3225 ../screen.c:4883 msgid "[Help]" msgstr "[ヘルプ]" -#: ../buffer.c:3254 ../screen.c:4887 msgid "[Preview]" msgstr "[プレビュー]" -#: ../buffer.c:3528 msgid "All" msgstr "å…¨ã¦" -#: ../buffer.c:3528 msgid "Bot" msgstr "末尾" -#: ../buffer.c:3531 msgid "Top" msgstr "å…ˆé " -#: ../buffer.c:4244 msgid "" "\n" "# Buffer list:\n" @@ -228,11 +192,9 @@ msgstr "" "\n" "# ãƒãƒƒãƒ•ァリスト:\n" -#: ../buffer.c:4289 msgid "[Scratch]" msgstr "[下書ã]" -#: ../buffer.c:4529 msgid "" "\n" "--- Signs ---" @@ -240,200 +202,235 @@ msgstr "" "\n" "--- サイン ---" -#: ../buffer.c:4538 #, c-format msgid "Signs for %s:" msgstr "%s ã®ã‚µã‚¤ãƒ³:" -#: ../buffer.c:4543 #, c-format -msgid " line=%<PRId64> id=%d name=%s" -msgstr " 行=%<PRId64> è˜åˆ¥å=%d åå‰=%s" +msgid " line=%ld id=%d name=%s" +msgstr " 行=%ld è˜åˆ¥å=%d åå‰=%s" -#: ../cursor_shape.c:68 -msgid "E545: Missing colon" -msgstr "E545: コãƒãƒ³ãŒã‚りã¾ã›ã‚“" +msgid "E902: Cannot connect to port" +msgstr "E902: ãƒãƒ¼ãƒˆã«æŽ¥ç¶šã§ãã¾ã›ã‚“" -#: ../cursor_shape.c:70 ../cursor_shape.c:94 -msgid "E546: Illegal mode" -msgstr "E546: 䏿£ãªãƒ¢ãƒ¼ãƒ‰ã§ã™" +msgid "E901: gethostbyname() in channel_open()" +msgstr "E901: channel_open() 内㮠gethostbyname() ãŒå¤±æ•—ã—ã¾ã—ãŸ" -#: ../cursor_shape.c:134 -msgid "E548: digit expected" -msgstr "E548: 数値ãŒå¿…è¦ã§ã™" +msgid "E898: socket() in channel_open()" +msgstr "E898: channel_open() 内㮠socket() ãŒå¤±æ•—ã—ã¾ã—ãŸ" -#: ../cursor_shape.c:138 -msgid "E549: Illegal percentage" -msgstr "E549: 䏿£ãªãƒ‘ーセンテージã§ã™" +msgid "E903: received command with non-string argument" +msgstr "E903: éžæ–‡å—列ã®å¼•æ•°ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’å—ä¿¡ã—ã¾ã—ãŸ" + +msgid "E904: last argument for expr/call must be a number" +msgstr "E904: expr/call ã®æœ€å¾Œã®å¼•æ•°ã¯æ•°å—ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" + +msgid "E904: third argument for call must be a list" +msgstr "E904: call ã®3番目ã®å¼•æ•°ã¯ãƒªã‚¹ãƒˆåž‹ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" + +#, c-format +msgid "E905: received unknown command: %s" +msgstr "E905: 未知ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’å—ä¿¡ã—ã¾ã—ãŸ: %s" + +#, c-format +msgid "E630: %s(): write while not connected" +msgstr "E630: %s(): éžæŽ¥ç¶šçŠ¶æ…‹ã§æ›¸ãè¾¼ã¿ã¾ã—ãŸ" + +#, c-format +msgid "E631: %s(): write failed" +msgstr "E631: %s(): 書ãè¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ" + +#, c-format +msgid "E917: Cannot use a callback with %s()" +msgstr "E917: %s() ã«ã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯ã¯ä½¿ãˆã¾ã›ã‚“" + +msgid "E912: cannot use ch_evalexpr()/ch_sendexpr() with a raw or nl channel" +msgstr "E912: 生や nl ãƒãƒ£ãƒ³ãƒãƒ«ã« ch_evalexpr()/ch_sendexpr ã¯ä½¿ãˆã¾ã›ã‚“" + +msgid "E906: not an open channel" +msgstr "E906: é–‹ã„ã¦ã„ãªã„ãƒãƒ£ãƒ³ãƒãƒ«ã§ã™" + +msgid "E920: _io file requires _name to be set" +msgstr "E920: _io ファイル㯠_name ã®è¨å®šãŒå¿…è¦ã§ã™" + +msgid "E915: in_io buffer requires in_buf or in_name to be set" +msgstr "E915: in_io ãƒãƒƒãƒ•ァ㯠in_buf ã‹ in_name ã®è¨å®šãŒå¿…è¦ã§ã™" + +#, c-format +msgid "E918: buffer must be loaded: %s" +msgstr "E918: ãƒãƒƒãƒ•ã‚¡ãŒãƒãƒ¼ãƒ‰ã•れã¦ãªã‘れã°ãªã‚Šã¾ã›ã‚“: %s" + +msgid "E821: File is encrypted with unknown method" +msgstr "E821: ãƒ•ã‚¡ã‚¤ãƒ«ãŒæœªçŸ¥ã®æ–¹æ³•ã§æš—å·åŒ–ã•れã¦ã„ã¾ã™" + +msgid "Warning: Using a weak encryption method; see :help 'cm'" +msgstr "è¦å‘Š: å¼±ã„æš—å·æ–¹æ³•を使ã£ã¦ã„ã¾ã™; :help 'cm' ã‚’å‚ç…§ã—ã¦ãã ã•ã„" + +msgid "Enter encryption key: " +msgstr "æš—å·åŒ–用ã®ã‚ーを入力ã—ã¦ãã ã•ã„: " + +msgid "Enter same key again: " +msgstr "ã‚‚ã†ä¸€åº¦åŒã˜ã‚ーを入力ã—ã¦ãã ã•ã„: " + +msgid "Keys don't match!" +msgstr "ã‚ーãŒä¸€è‡´ã—ã¾ã›ã‚“" + +msgid "[crypted]" +msgstr "[æš—å·åŒ–]" + +#, c-format +msgid "E720: Missing colon in Dictionary: %s" +msgstr "E720: 辞書型ã«ã‚³ãƒãƒ³ãŒã‚りã¾ã›ã‚“: %s" + +#, c-format +msgid "E721: Duplicate key in Dictionary: \"%s\"" +msgstr "E721: 辞書型ã«é‡è¤‡ã‚ーãŒã‚りã¾ã™: \"%s\"" + +#, c-format +msgid "E722: Missing comma in Dictionary: %s" +msgstr "E722: 辞書型ã«ã‚«ãƒ³ãƒžãŒã‚りã¾ã›ã‚“: %s" + +#, c-format +msgid "E723: Missing end of Dictionary '}': %s" +msgstr "E723: è¾žæ›¸åž‹ã®æœ€å¾Œã« '}' ãŒã‚りã¾ã›ã‚“: %s" + +msgid "extend() argument" +msgstr "extend() ã®å¼•æ•°" -#: ../diff.c:146 #, c-format -msgid "E96: Can not diff more than %<PRId64> buffers" -msgstr "E96: %<PRId64> 以上ã®ãƒãƒƒãƒ•ã‚¡ã¯diffã§ãã¾ã›ã‚“" +msgid "E737: Key already exists: %s" +msgstr "E737: ã‚ãƒ¼ã¯æ—¢ã«å˜åœ¨ã—ã¾ã™: %s" + +#, c-format +msgid "E96: Cannot diff more than %ld buffers" +msgstr "E96: %ld 以上ã®ãƒãƒƒãƒ•ã‚¡ã¯diffã§ãã¾ã›ã‚“" -#: ../diff.c:753 msgid "E810: Cannot read or write temp files" msgstr "E810: 一時ファイルã®èªè¾¼ã‚‚ã—ãã¯æ›¸è¾¼ãŒã§ãã¾ã›ã‚“" -#: ../diff.c:755 msgid "E97: Cannot create diffs" msgstr "E97: 差分を作æˆã§ãã¾ã›ã‚“" -#: ../diff.c:966 +msgid "Patch file" +msgstr "パッãƒãƒ•ァイル" + msgid "E816: Cannot read patch output" msgstr "E816: patchã®å‡ºåŠ›ã‚’èªè¾¼ã‚ã¾ã›ã‚“" -#: ../diff.c:1220 msgid "E98: Cannot read diff output" msgstr "E98: diffã®å‡ºåŠ›ã‚’èªè¾¼ã‚ã¾ã›ã‚“" -#: ../diff.c:2081 msgid "E99: Current buffer is not in diff mode" msgstr "E99: ç¾åœ¨ã®ãƒãƒƒãƒ•ã‚¡ã¯å·®åˆ†ãƒ¢ãƒ¼ãƒ‰ã§ã¯ã‚りã¾ã›ã‚“" -#: ../diff.c:2100 msgid "E793: No other buffer in diff mode is modifiable" msgstr "E793: 差分モードã§ã‚ã‚‹ä»–ã®ãƒãƒƒãƒ•ã‚¡ã¯å¤‰æ›´ã§ãã¾ã›ã‚“" -#: ../diff.c:2102 msgid "E100: No other buffer in diff mode" msgstr "E100: 差分モードã§ã‚ã‚‹ä»–ã®ãƒãƒƒãƒ•ã‚¡ã¯ã‚りã¾ã›ã‚“" -#: ../diff.c:2112 msgid "E101: More than two buffers in diff mode, don't know which one to use" msgstr "" "E101: 差分モードã®ãƒãƒƒãƒ•ã‚¡ãŒ2個以上ã‚ã‚‹ã®ã§ã€ã©ã‚Œã‚’使ã†ã‹ç‰¹å®šã§ãã¾ã›ã‚“" -#: ../diff.c:2141 #, c-format msgid "E102: Can't find buffer \"%s\"" msgstr "E102: ãƒãƒƒãƒ•ã‚¡ \"%s\" ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../diff.c:2152 #, c-format msgid "E103: Buffer \"%s\" is not in diff mode" msgstr "E103: ãƒãƒƒãƒ•ã‚¡ \"%s\" ã¯å·®åˆ†ãƒ¢ãƒ¼ãƒ‰ã§ã¯ã‚りã¾ã›ã‚“" -#: ../diff.c:2193 msgid "E787: Buffer changed unexpectedly" msgstr "E787: 予期ã›ãšãƒãƒƒãƒ•ã‚¡ãŒå¤‰æ›´å¤‰æ›´ã•れã¾ã—ãŸ" -#: ../digraph.c:1598 msgid "E104: Escape not allowed in digraph" msgstr "E104: åˆå—ã«Escapeã¯ä½¿ç”¨ã§ãã¾ã›ã‚“" -#: ../digraph.c:1760 msgid "E544: Keymap file not found" msgstr "E544: ã‚ーマップファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../digraph.c:1785 msgid "E105: Using :loadkeymap not in a sourced file" msgstr "E105: :source ã§å–込むファイル以外ã§ã¯ :loadkeymap を使ãˆã¾ã›ã‚“" -#: ../digraph.c:1821 msgid "E791: Empty keymap entry" msgstr "E791: 空ã®ã‚ーマップエントリ" -#: ../edit.c:82 msgid " Keyword completion (^N^P)" msgstr " ã‚ーワード補完 (^N^P)" #. ctrl_x_mode == 0, ^P/^N compl. -#: ../edit.c:83 msgid " ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" msgstr " ^X モード (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" -#: ../edit.c:85 msgid " Whole line completion (^L^N^P)" msgstr " 行(全体)補完 (^L^N^P)" -#: ../edit.c:86 msgid " File name completion (^F^N^P)" msgstr " ファイルå補完 (^F^N^P)" -#: ../edit.c:87 msgid " Tag completion (^]^N^P)" msgstr " タグ補完 (^]^N^P)" -#: ../edit.c:88 msgid " Path pattern completion (^N^P)" msgstr " パスパターン補完 (^N^P)" -#: ../edit.c:89 msgid " Definition completion (^D^N^P)" msgstr " 定義補完 (^D^N^P)" -#: ../edit.c:91 msgid " Dictionary completion (^K^N^P)" msgstr " 辞書補完 (^K^N^P)" -#: ../edit.c:92 msgid " Thesaurus completion (^T^N^P)" msgstr " シソーラス補完 (^T^N^P)" -#: ../edit.c:93 msgid " Command-line completion (^V^N^P)" msgstr " コマンドライン補完 (^V^N^P)" -#: ../edit.c:94 msgid " User defined completion (^U^N^P)" msgstr " ユーザー定義補完 (^U^N^P)" -#: ../edit.c:95 msgid " Omni completion (^O^N^P)" msgstr " オムニ補完 (^O^N^P)" -#: ../edit.c:96 msgid " Spelling suggestion (s^N^P)" msgstr " 綴り修æ£å€™è£œ (s^N^P)" -#: ../edit.c:97 msgid " Keyword Local completion (^N^P)" msgstr " 局所ã‚ーワード補完 (^N^P)" -#: ../edit.c:100 msgid "Hit end of paragraph" msgstr "段è½ã®æœ€å¾Œã«ãƒ’ット" -#: ../edit.c:101 msgid "E839: Completion function changed window" msgstr "E839: 補間関数ãŒã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’変更ã—ã¾ã—ãŸ" -#: ../edit.c:102 msgid "E840: Completion function deleted text" msgstr "E840: 補完関数ãŒãƒ†ã‚ストを削除ã—ã¾ã—ãŸ" -#: ../edit.c:1847 msgid "'dictionary' option is empty" msgstr "'dictionary' オプションãŒç©ºã§ã™" -#: ../edit.c:1848 msgid "'thesaurus' option is empty" msgstr "'thesaurus' オプションãŒç©ºã§ã™" -#: ../edit.c:2655 #, c-format msgid "Scanning dictionary: %s" msgstr "辞書をスã‚ャンä¸: %s" -#: ../edit.c:3079 msgid " (insert) Scroll (^E/^Y)" msgstr " (挿入) スクãƒãƒ¼ãƒ«(^E/^Y)" -#: ../edit.c:3081 msgid " (replace) Scroll (^E/^Y)" msgstr " (ç½®æ›) スクãƒãƒ¼ãƒ« (^E/^Y)" -#: ../edit.c:3587 #, c-format msgid "Scanning: %s" msgstr "スã‚ャンä¸: %s" -#: ../edit.c:3614 msgid "Scanning tags." msgstr "タグをスã‚ャンä¸." -#: ../edit.c:4519 msgid " Adding" msgstr " è¿½åŠ ä¸" @@ -441,430 +438,161 @@ msgstr " è¿½åŠ ä¸" #. * be called before line = ml_get(), or when this address is no #. * longer needed. -- Acevedo. #. -#: ../edit.c:4562 msgid "-- Searching..." msgstr "-- 検索ä¸..." -#: ../edit.c:4618 msgid "Back at original" msgstr "å§‹ã‚ã«æˆ»ã‚‹" -#: ../edit.c:4621 msgid "Word from other line" msgstr "ä»–ã®è¡Œã®å˜èªž" -#: ../edit.c:4624 msgid "The only match" msgstr "唯一ã®è©²å½“" -#: ../edit.c:4680 #, c-format msgid "match %d of %d" msgstr "%d 番目ã®è©²å½“ (全該当 %d 個ä¸)" -#: ../edit.c:4684 #, c-format msgid "match %d" msgstr "%d 番目ã®è©²å½“" -#: ../eval.c:137 +#. maximum nesting of lists and dicts msgid "E18: Unexpected characters in :let" msgstr "E18: 予期ã›ã¬æ–‡å—㌠:let ã«ã‚りã¾ã—ãŸ" -#: ../eval.c:138 -#, c-format -msgid "E684: list index out of range: %<PRId64>" -msgstr "E684: リストã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ãŒç¯„囲外ã§ã™: %<PRId64>" - -#: ../eval.c:139 #, c-format msgid "E121: Undefined variable: %s" msgstr "E121: 未定義ã®å¤‰æ•°ã§ã™: %s" -#: ../eval.c:140 msgid "E111: Missing ']'" msgstr "E111: ']' ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../eval.c:141 -#, c-format -msgid "E686: Argument of %s must be a List" -msgstr "E686: %s ã®å¼•æ•°ã¯ãƒªã‚¹ãƒˆåž‹ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" - -#: ../eval.c:143 -#, c-format -msgid "E712: Argument of %s must be a List or Dictionary" -msgstr "E712: %s ã®å¼•æ•°ã¯ãƒªã‚¹ãƒˆåž‹ã¾ãŸã¯è¾žæ›¸åž‹ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" - -#: ../eval.c:144 -msgid "E713: Cannot use empty key for Dictionary" -msgstr "E713: 辞書型ã«ç©ºã®ã‚ーを使ã†ã“ã¨ã¯ã§ãã¾ã›ã‚“" - -#: ../eval.c:145 -msgid "E714: List required" -msgstr "E714: リスト型ãŒå¿…è¦ã§ã™" - -#: ../eval.c:146 -msgid "E715: Dictionary required" -msgstr "E715: 辞書型ãŒå¿…è¦ã§ã™" - -#: ../eval.c:147 -#, c-format -msgid "E118: Too many arguments for function: %s" -msgstr "E118: 関数ã®å¼•æ•°ãŒå¤šéŽãŽã¾ã™: %s" - -#: ../eval.c:148 -#, c-format -msgid "E716: Key not present in Dictionary: %s" -msgstr "E716: 辞書型ã«ã‚ーãŒå˜åœ¨ã—ã¾ã›ã‚“: %s" - -#: ../eval.c:150 -#, c-format -msgid "E122: Function %s already exists, add ! to replace it" -msgstr "E122: 関数 %s ã¯å®šç¾©æ¸ˆã§ã™, å†å®šç¾©ã™ã‚‹ã«ã¯ ! ã‚’è¿½åŠ ã—ã¦ãã ã•ã„" - -#: ../eval.c:151 -msgid "E717: Dictionary entry already exists" -msgstr "E717: 辞書型内ã«ã‚¨ãƒ³ãƒˆãƒªãŒæ—¢ã«å˜åœ¨ã—ã¾ã™" - -#: ../eval.c:152 -msgid "E718: Funcref required" -msgstr "E718: 関数å‚ç…§åž‹ãŒè¦æ±‚ã•れã¾ã™" - -#: ../eval.c:153 msgid "E719: Cannot use [:] with a Dictionary" msgstr "E719: [:] を辞書型ã¨çµ„ã¿åˆã‚ã›ã¦ã¯ä½¿ãˆã¾ã›ã‚“" -#: ../eval.c:154 #, c-format msgid "E734: Wrong variable type for %s=" msgstr "E734: ç•°ãªã£ãŸåž‹ã®å¤‰æ•°ã§ã™ %s=" -#: ../eval.c:155 -#, c-format -msgid "E130: Unknown function: %s" -msgstr "E130: 未知ã®é–¢æ•°ã§ã™: %s" - -#: ../eval.c:156 #, c-format msgid "E461: Illegal variable name: %s" msgstr "E461: 䏿£ãªå¤‰æ•°åã§ã™: %s" -#: ../eval.c:157 msgid "E806: using Float as a String" msgstr "E806: æµ®å‹•å°æ•°ç‚¹æ•°ã‚’æ–‡å—列ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™" -#: ../eval.c:1830 msgid "E687: Less targets than List items" msgstr "E687: ターゲットãŒãƒªã‚¹ãƒˆåž‹å†…ã®è¦ç´ よりも少ãªã„ã§ã™" -#: ../eval.c:1834 msgid "E688: More targets than List items" msgstr "E688: ターゲットãŒãƒªã‚¹ãƒˆåž‹å†…ã®è¦ç´ よりも多ã„ã§ã™" -#: ../eval.c:1906 msgid "Double ; in list of variables" msgstr "リスト型ã®å€¤ã«2ã¤ä»¥ä¸Šã® ; ãŒæ¤œå‡ºã•れã¾ã—ãŸ" -#: ../eval.c:2078 #, c-format msgid "E738: Can't list variables for %s" msgstr "E738: %s ã®å€¤ã‚’一覧表示ã§ãã¾ã›ã‚“" -#: ../eval.c:2391 msgid "E689: Can only index a List or Dictionary" msgstr "E689: リスト型ã¨è¾žæ›¸åž‹ä»¥å¤–ã¯ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹æŒ‡å®šã§ãã¾ã›ã‚“" -#: ../eval.c:2396 msgid "E708: [:] must come last" msgstr "E708: [:] ã¯æœ€å¾Œã§ãªã‘れã°ã„ã‘ã¾ã›ã‚“" -#: ../eval.c:2439 msgid "E709: [:] requires a List value" msgstr "E709: [:] ã«ã¯ãƒªã‚¹ãƒˆåž‹ã®å€¤ãŒå¿…è¦ã§ã™" -#: ../eval.c:2674 msgid "E710: List value has more items than target" msgstr "E710: リスト型変数ã«ã‚¿ãƒ¼ã‚²ãƒƒãƒˆã‚ˆã‚Šã‚‚多ã„è¦ç´ ãŒã‚りã¾ã™" -#: ../eval.c:2678 msgid "E711: List value has not enough items" msgstr "E711: リスト型変数ã«ååˆ†ãªæ•°ã®è¦ç´ ãŒã‚りã¾ã›ã‚“" # -#: ../eval.c:2867 msgid "E690: Missing \"in\" after :for" msgstr "E690: :for ã®å¾Œã« \"in\" ãŒã‚りã¾ã›ã‚“" -#: ../eval.c:3063 -#, c-format -msgid "E107: Missing parentheses: %s" -msgstr "E107: カッコ '(' ãŒã‚りã¾ã›ã‚“: %s" - -#: ../eval.c:3263 #, c-format msgid "E108: No such variable: \"%s\"" msgstr "E108: ãã®å¤‰æ•°ã¯ã‚りã¾ã›ã‚“: \"%s\"" -#: ../eval.c:3333 msgid "E743: variable nested too deep for (un)lock" msgstr "E743: (アン)ãƒãƒƒã‚¯ã™ã‚‹ã«ã¯å¤‰æ•°ã®å…¥ã‚ŒåãŒæ·±éŽãŽã¾ã™" -#: ../eval.c:3630 msgid "E109: Missing ':' after '?'" msgstr "E109: '?' ã®å¾Œã« ':' ãŒã‚りã¾ã›ã‚“" -#: ../eval.c:3893 msgid "E691: Can only compare List with List" msgstr "E691: リスト型ã¯ãƒªã‚¹ãƒˆåž‹ã¨ã—ã‹æ¯”較ã§ãã¾ã›ã‚“" -#: ../eval.c:3895 -msgid "E692: Invalid operation for Lists" +msgid "E692: Invalid operation for List" msgstr "E692: リスト型ã«ã¯ç„¡åŠ¹ãªæ“作ã§ã™" -#: ../eval.c:3915 msgid "E735: Can only compare Dictionary with Dictionary" msgstr "E735: 辞書型ã¯è¾žæ›¸åž‹ã¨ã—ã‹æ¯”較ã§ãã¾ã›ã‚“" -#: ../eval.c:3917 msgid "E736: Invalid operation for Dictionary" msgstr "E736: 辞書型ã«ã¯ç„¡åŠ¹ãªæ“作ã§ã™" -#: ../eval.c:3932 -msgid "E693: Can only compare Funcref with Funcref" -msgstr "E693: 関数å‚ç…§åž‹ã¯é–¢æ•°å‚ç…§åž‹ã¨ã—ã‹æ¯”較ã§ãã¾ã›ã‚“" - -#: ../eval.c:3934 msgid "E694: Invalid operation for Funcrefs" msgstr "E694: 関数å‚ç…§åž‹ã«ã¯ç„¡åŠ¹ãªæ“作ã§ã™" -#: ../eval.c:4277 msgid "E804: Cannot use '%' with Float" msgstr "E804: '%' ã‚’æµ®å‹•å°æ•°ç‚¹æ•°ã¨çµ„ã¿åˆã‚ã›ã¦ã¯ä½¿ãˆã¾ã›ã‚“" -#: ../eval.c:4478 msgid "E110: Missing ')'" msgstr "E110: ')' ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../eval.c:4609 msgid "E695: Cannot index a Funcref" msgstr "E695: 関数å‚ç…§åž‹ã¯ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã§ãã¾ã›ã‚“" -#: ../eval.c:4839 +msgid "E909: Cannot index a special variable" +msgstr "E909: 特殊変数ã¯ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã§ãã¾ã›ã‚“" + #, c-format msgid "E112: Option name missing: %s" msgstr "E112: オプションåãŒã‚りã¾ã›ã‚“: %s" -#: ../eval.c:4855 #, c-format msgid "E113: Unknown option: %s" msgstr "E113: 未知ã®ã‚ªãƒ—ションã§ã™: %s" -#: ../eval.c:4904 #, c-format msgid "E114: Missing quote: %s" msgstr "E114: 引用符 (\") ãŒã‚りã¾ã›ã‚“: %s" -#: ../eval.c:5020 #, c-format msgid "E115: Missing quote: %s" msgstr "E115: 引用符 (') ãŒã‚りã¾ã›ã‚“: %s" -#: ../eval.c:5084 -#, c-format -msgid "E696: Missing comma in List: %s" -msgstr "E696: リスト型ã«ã‚«ãƒ³ãƒžãŒã‚りã¾ã›ã‚“: %s" - -#: ../eval.c:5091 -#, c-format -msgid "E697: Missing end of List ']': %s" -msgstr "E697: ãƒªã‚¹ãƒˆåž‹ã®æœ€å¾Œã« ']' ãŒã‚りã¾ã›ã‚“: %s" - msgid "Not enough memory to set references, garbage collection aborted!" msgstr "" "ã‚¬ãƒ¼ãƒ™ãƒƒã‚¸ã‚³ãƒ¬ã‚¯ã‚·ãƒ§ãƒ³ã‚’ä¸æ¢ã—ã¾ã—ãŸ! å‚照を作æˆã™ã‚‹ã®ã«ãƒ¡ãƒ¢ãƒªãŒä¸è¶³ã—ã¾ã—ãŸ" -#: ../eval.c:6475 -#, c-format -msgid "E720: Missing colon in Dictionary: %s" -msgstr "E720: 辞書型ã«ã‚³ãƒãƒ³ãŒã‚りã¾ã›ã‚“: %s" - -#: ../eval.c:6499 -#, c-format -msgid "E721: Duplicate key in Dictionary: \"%s\"" -msgstr "E721: 辞書型ã«é‡è¤‡ã‚ーãŒã‚りã¾ã™: \"%s\"" - -#: ../eval.c:6517 -#, c-format -msgid "E722: Missing comma in Dictionary: %s" -msgstr "E722: 辞書型ã«ã‚«ãƒ³ãƒžãŒã‚りã¾ã›ã‚“: %s" - -#: ../eval.c:6524 -#, c-format -msgid "E723: Missing end of Dictionary '}': %s" -msgstr "E723: è¾žæ›¸åž‹ã®æœ€å¾Œã« '}' ãŒã‚りã¾ã›ã‚“: %s" - -#: ../eval.c:6555 msgid "E724: variable nested too deep for displaying" msgstr "E724: 表示ã™ã‚‹ã«ã¯å¤‰æ•°ã®å…¥ã‚ŒåãŒæ·±éŽãŽã¾ã™" -#: ../eval.c:7188 -#, c-format -msgid "E740: Too many arguments for function %s" -msgstr "E740: 関数ã®å¼•æ•°ãŒå¤šéŽãŽã¾ã™: %s" - -#: ../eval.c:7190 -#, c-format -msgid "E116: Invalid arguments for function %s" -msgstr "E116: 関数ã®ç„¡åйãªå¼•æ•°ã§ã™: %s" - -#: ../eval.c:7377 -#, c-format -msgid "E117: Unknown function: %s" -msgstr "E117: 未知ã®é–¢æ•°ã§ã™: %s" - -#: ../eval.c:7383 -#, c-format -msgid "E119: Not enough arguments for function: %s" -msgstr "E119: 関数ã®å¼•æ•°ãŒè¶³ã‚Šã¾ã›ã‚“: %s" - -#: ../eval.c:7387 -#, c-format -msgid "E120: Using <SID> not in a script context: %s" -msgstr "E120: スクリプト以外ã§<SID>ãŒä½¿ã‚れã¾ã—ãŸ: %s" - -#: ../eval.c:7391 -#, c-format -msgid "E725: Calling dict function without Dictionary: %s" -msgstr "E725: 辞書用関数ãŒå‘¼ã°ã‚Œã¾ã—ãŸãŒè¾žæ›¸ãŒã‚りã¾ã›ã‚“: %s" - -#: ../eval.c:7453 -msgid "E808: Number or Float required" -msgstr "E808: æ•°å€¤ã‹æµ®å‹•å°æ•°ç‚¹æ•°ãŒå¿…è¦ã§ã™" - -#: ../eval.c:7503 -msgid "add() argument" -msgstr "add() ã®å¼•æ•°" - -#: ../eval.c:7907 -msgid "E699: Too many arguments" -msgstr "E699: 引数ãŒå¤šéŽãŽã¾ã™" - -#: ../eval.c:8073 -msgid "E785: complete() can only be used in Insert mode" -msgstr "E785: complete() ã¯æŒ¿å…¥ãƒ¢ãƒ¼ãƒ‰ã§ã—ã‹åˆ©ç”¨ã§ãã¾ã›ã‚“" - -#: ../eval.c:8156 -msgid "&Ok" -msgstr "&Ok" - -#: ../eval.c:8676 -#, c-format -msgid "E737: Key already exists: %s" -msgstr "E737: ã‚ãƒ¼ã¯æ—¢ã«å˜åœ¨ã—ã¾ã™: %s" - -#: ../eval.c:8692 -msgid "extend() argument" -msgstr "extend() ã®å¼•æ•°" - -#: ../eval.c:8915 -msgid "map() argument" -msgstr "map() ã®å¼•æ•°" - -#: ../eval.c:8916 -msgid "filter() argument" -msgstr "filter() ã®å¼•æ•°" - -#: ../eval.c:9229 -#, c-format -msgid "+-%s%3ld lines: " -msgstr "+-%s%3ld 行: " - -#: ../eval.c:9291 -#, c-format -msgid "E700: Unknown function: %s" -msgstr "E700: 未知ã®é–¢æ•°ã§ã™: %s" - -#: ../eval.c:10729 -msgid "called inputrestore() more often than inputsave()" -msgstr "inputrestore() ㌠inputsave() よりも多ã呼ã°ã‚Œã¾ã—ãŸ" - -#: ../eval.c:10771 -msgid "insert() argument" -msgstr "insert() ã®å¼•æ•°" - -#: ../eval.c:10841 -msgid "E786: Range not allowed" -msgstr "E786: 範囲指定ã¯è¨±å¯ã•れã¦ã„ã¾ã›ã‚“" - -#: ../eval.c:11140 -msgid "E701: Invalid type for len()" -msgstr "E701: len() ã«ã¯ç„¡åйãªåž‹ã§ã™" - -#: ../eval.c:11980 -msgid "E726: Stride is zero" -msgstr "E726: ストライド(å‰é€²é‡)㌠0 ã§ã™" - -#: ../eval.c:11982 -msgid "E727: Start past end" -msgstr "E727: é–‹å§‹ä½ç½®ãŒçµ‚了ä½ç½®ã‚’è¶Šãˆã¾ã—ãŸ" - -#: ../eval.c:12024 ../eval.c:15297 -msgid "<empty>" -msgstr "<空>" - -#: ../eval.c:12282 -msgid "remove() argument" -msgstr "remove() ã®å¼•æ•°" - -# Added at 10-Mar-2004. -#: ../eval.c:12466 -msgid "E655: Too many symbolic links (cycle?)" -msgstr "E655: シンボリックリンクãŒå¤šéŽãŽã¾ã™ (循環ã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™)" - -#: ../eval.c:12593 -msgid "reverse() argument" -msgstr "reverse() ã®å¼•æ•°" - -#: ../eval.c:13721 -msgid "sort() argument" -msgstr "sort() ã®å¼•æ•°" - -#: ../eval.c:13721 -msgid "uniq() argument" -msgstr "uniq() ã®å¼•æ•°" - -#: ../eval.c:13776 -msgid "E702: Sort compare function failed" -msgstr "E702: ã‚½ãƒ¼ãƒˆã®æ¯”較関数ãŒå¤±æ•—ã—ã¾ã—ãŸ" - -#: ../eval.c:13806 -msgid "E882: Uniq compare function failed" -msgstr "E882: Uniq ã®æ¯”較関数ãŒå¤±æ•—ã—ã¾ã—ãŸ" - -#: ../eval.c:14085 -msgid "(Invalid)" -msgstr "(無効)" - -#: ../eval.c:14590 -msgid "E677: Error writing temp file" -msgstr "E677: 一時ファイル書込ä¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ" - -#: ../eval.c:16159 msgid "E805: Using a Float as a Number" msgstr "E805: æµ®å‹•å°æ•°ç‚¹æ•°ã‚’数値ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™" -#: ../eval.c:16162 msgid "E703: Using a Funcref as a Number" msgstr "E703: 関数å‚照型を数値ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™ã€‚" -#: ../eval.c:16170 msgid "E745: Using a List as a Number" msgstr "E745: リスト型を数値ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™" -#: ../eval.c:16173 msgid "E728: Using a Dictionary as a Number" msgstr "E728: 辞書型を数値ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™" +msgid "E910: Using a Job as a Number" +msgstr "E910: ジョブを数値ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™" + +msgid "E913: Using a Channel as a Number" +msgstr "E913: ãƒãƒ£ãƒ³ãƒãƒ«ã‚’数値ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™ã€‚" + msgid "E891: Using a Funcref as a Float" msgstr "E891: 関数å‚ç…§åž‹ã‚’æµ®å‹•å°æ•°ç‚¹æ•°ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™ã€‚" @@ -877,265 +605,280 @@ msgstr "E893: ãƒªã‚¹ãƒˆåž‹ã‚’æµ®å‹•å°æ•°ç‚¹æ•°ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™" msgid "E894: Using a Dictionary as a Float" msgstr "E894: è¾žæ›¸åž‹ã‚’æµ®å‹•å°æ•°ç‚¹æ•°ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™" -#: ../eval.c:16259 +msgid "E907: Using a special value as a Float" +msgstr "E907: ç‰¹æ®Šå€¤ã‚’æµ®å‹•å°æ•°ç‚¹æ•°ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™" + +msgid "E911: Using a Job as a Float" +msgstr "E911: ã‚¸ãƒ§ãƒ–ã‚’æµ®å‹•å°æ•°ç‚¹æ•°ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™" + +msgid "E914: Using a Channel as a Float" +msgstr "E914: ãƒãƒ£ãƒ³ãƒãƒ«ã‚’æµ®å‹•å°æ•°ç‚¹æ•°ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™ã€‚" + msgid "E729: using Funcref as a String" msgstr "E729: 関数å‚照型を文å—列ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™" -#: ../eval.c:16262 msgid "E730: using List as a String" msgstr "E730: リスト型を文å—列ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™" -#: ../eval.c:16265 msgid "E731: using Dictionary as a String" msgstr "E731: 辞書型を文å—列ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™" -#: ../eval.c:16619 -#, c-format -msgid "E706: Variable type mismatch for: %s" -msgstr "E706: 変数ã®åž‹ãŒä¸€è‡´ã—ã¾ã›ã‚“: %s" +msgid "E908: using an invalid value as a String" +msgstr "E908: 無効ãªå€¤ã‚’æ–‡å—列ã¨ã—ã¦æ‰±ã£ã¦ã„ã¾ã™" -#: ../eval.c:16705 #, c-format msgid "E795: Cannot delete variable %s" msgstr "E795: 変数 %s を削除ã§ãã¾ã›ã‚“" -#: ../eval.c:16724 #, c-format msgid "E704: Funcref variable name must start with a capital: %s" msgstr "E704: 関数å‚照型変数åã¯å¤§æ–‡å—ã§å§‹ã¾ã‚‰ãªã‘れã°ãªã‚Šã¾ã›ã‚“: %s" -#: ../eval.c:16732 #, c-format msgid "E705: Variable name conflicts with existing function: %s" msgstr "E705: 変数åãŒæ—¢å˜ã®é–¢æ•°åã¨è¡çªã—ã¾ã™: %s" -#: ../eval.c:16763 #, c-format msgid "E741: Value is locked: %s" msgstr "E741: 値ãŒãƒãƒƒã‚¯ã•れã¦ã„ã¾ã™: %s" -#: ../eval.c:16764 ../eval.c:16769 ../message.c:1839 msgid "Unknown" msgstr "䏿˜Ž" -#: ../eval.c:16768 #, c-format msgid "E742: Cannot change value of %s" msgstr "E742: %s ã®å€¤ã‚’変更ã§ãã¾ã›ã‚“" -#: ../eval.c:16838 msgid "E698: variable nested too deep for making a copy" msgstr "E698: コピーをå–ã‚‹ã«ã¯å¤‰æ•°ã®å…¥ã‚ŒåãŒæ·±éŽãŽã¾ã™" -#: ../eval.c:17249 -#, c-format -msgid "E123: Undefined function: %s" -msgstr "E123: 未定義ã®é–¢æ•°ã§ã™: %s" +msgid "" +"\n" +"# global variables:\n" +msgstr "" +"\n" +"# ã‚°ãƒãƒ¼ãƒãƒ«å¤‰æ•°:\n" -#: ../eval.c:17260 -#, c-format -msgid "E124: Missing '(': %s" -msgstr "E124: '(' ãŒã‚りã¾ã›ã‚“: %s" +msgid "" +"\n" +"\tLast set from " +msgstr "" +"\n" +"\t最後ã«ã‚»ãƒƒãƒˆã—ãŸã‚¹ã‚¯ãƒªãƒ—ト: " -#: ../eval.c:17293 -msgid "E862: Cannot use g: here" -msgstr "E862: ã“ã“ã§ã¯ g: ã¯ä½¿ãˆã¾ã›ã‚“" +msgid "map() argument" +msgstr "map() ã®å¼•æ•°" -#: ../eval.c:17312 -#, c-format -msgid "E125: Illegal argument: %s" -msgstr "E125: 䏿£ãªå¼•æ•°ã§ã™: %s" +msgid "filter() argument" +msgstr "filter() ã®å¼•æ•°" -#: ../eval.c:17323 #, c-format -msgid "E853: Duplicate argument name: %s" -msgstr "E853: 引数åãŒé‡è¤‡ã—ã¦ã„ã¾ã™: %s" +msgid "E686: Argument of %s must be a List" +msgstr "E686: %s ã®å¼•æ•°ã¯ãƒªã‚¹ãƒˆåž‹ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" -#: ../eval.c:17416 -msgid "E126: Missing :endfunction" -msgstr "E126: :endfunction ãŒã‚りã¾ã›ã‚“" +msgid "E928: String required" +msgstr "E928: æ–‡å—列ãŒå¿…è¦ã§ã™" -#: ../eval.c:17537 -#, c-format -msgid "E707: Function name conflicts with variable: %s" -msgstr "E707: 関数åãŒå¤‰æ•°åã¨è¡çªã—ã¾ã™: %s" +msgid "E808: Number or Float required" +msgstr "E808: æ•°å€¤ã‹æµ®å‹•å°æ•°ç‚¹æ•°ãŒå¿…è¦ã§ã™" -#: ../eval.c:17549 -#, c-format -msgid "E127: Cannot redefine function %s: It is in use" -msgstr "E127: 関数 %s ã‚’å†å®šç¾©ã§ãã¾ã›ã‚“: 使用ä¸ã§ã™" +msgid "add() argument" +msgstr "add() ã®å¼•æ•°" -#: ../eval.c:17604 -#, c-format -msgid "E746: Function name does not match script file name: %s" -msgstr "E746: 関数åãŒã‚¹ã‚¯ãƒªãƒ—トã®ãƒ•ァイルåã¨ä¸€è‡´ã—ã¾ã›ã‚“: %s" +msgid "E785: complete() can only be used in Insert mode" +msgstr "E785: complete() ã¯æŒ¿å…¥ãƒ¢ãƒ¼ãƒ‰ã§ã—ã‹åˆ©ç”¨ã§ãã¾ã›ã‚“" -#: ../eval.c:17716 -msgid "E129: Function name required" -msgstr "E129: 関数åãŒè¦æ±‚ã•れã¾ã™" +#. +#. * Yes this is ugly, I don't particularly like it either. But doing it +#. * this way has the compelling advantage that translations need not to +#. * be touched at all. See below what 'ok' and 'ync' are used for. +#. +msgid "&Ok" +msgstr "&Ok" -#: ../eval.c:17824 #, c-format -msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "E128: 関数åã¯å¤§æ–‡å—ã‹ \"s:\" ã§å§‹ã¾ã‚‰ãªã‘れã°ãªã‚Šã¾ã›ã‚“: %s" +msgid "+-%s%3ld line: " +msgid_plural "+-%s%3ld lines: " +msgstr[0] "+-%s%3ld 行: " -#: ../eval.c:17833 #, c-format -msgid "E884: Function name cannot contain a colon: %s" -msgstr "E884: 関数åã«ã¯ã‚³ãƒãƒ³ã¯å«ã‚られã¾ã›ã‚“: %s" +msgid "E700: Unknown function: %s" +msgstr "E700: 未知ã®é–¢æ•°ã§ã™: %s" -#: ../eval.c:18336 -#, c-format -msgid "E131: Cannot delete function %s: It is in use" -msgstr "E131: 関数 %s を削除ã§ãã¾ã›ã‚“: 使用ä¸ã§ã™" +msgid "E922: expected a dict" +msgstr "E922: è¾žæ›¸ãŒæœŸå¾…ã•れã¦ã„ã¾ã™" -#: ../eval.c:18441 -msgid "E132: Function call depth is higher than 'maxfuncdepth'" -msgstr "E132: 関数呼出ã®å…¥ã‚Œå数㌠'maxfuncdepth' ã‚’è¶…ãˆã¾ã—ãŸ" +msgid "E923: Second argument of function() must be a list or a dict" +msgstr "E923: function() ã®ç¬¬ 2 引数ã¯ãƒªã‚¹ãƒˆåž‹ã¾ãŸã¯è¾žæ›¸åž‹ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" -#: ../eval.c:18568 -#, c-format -msgid "calling %s" -msgstr "%s を実行ä¸ã§ã™" +msgid "" +"&OK\n" +"&Cancel" +msgstr "" +"決定(&O)\n" +"ã‚ャンセル(&C)" -#: ../eval.c:18651 -#, c-format -msgid "%s aborted" -msgstr "%s ãŒä¸æ–ã•れã¾ã—ãŸ" +msgid "called inputrestore() more often than inputsave()" +msgstr "inputrestore() ㌠inputsave() よりも多ã呼ã°ã‚Œã¾ã—ãŸ" + +msgid "insert() argument" +msgstr "insert() ã®å¼•æ•°" + +msgid "E786: Range not allowed" +msgstr "E786: 範囲指定ã¯è¨±å¯ã•れã¦ã„ã¾ã›ã‚“" + +msgid "E916: not a valid job" +msgstr "E916: 有効ãªã‚¸ãƒ§ãƒ–ã§ã¯ã‚りã¾ã›ã‚“" + +msgid "E701: Invalid type for len()" +msgstr "E701: len() ã«ã¯ç„¡åйãªåž‹ã§ã™" -#: ../eval.c:18653 #, c-format -msgid "%s returning #%<PRId64>" -msgstr "%s ㌠#%<PRId64> ã‚’è¿”ã—ã¾ã—ãŸ" +msgid "E798: ID is reserved for \":match\": %ld" +msgstr "E798: ID 㯠\":match\" ã®ãŸã‚ã«äºˆç´„ã•れã¦ã„ã¾ã™: %ld" + +msgid "E726: Stride is zero" +msgstr "E726: ストライド(å‰é€²é‡)㌠0 ã§ã™" + +msgid "E727: Start past end" +msgstr "E727: é–‹å§‹ä½ç½®ãŒçµ‚了ä½ç½®ã‚’è¶Šãˆã¾ã—ãŸ" + +msgid "<empty>" +msgstr "<空>" + +msgid "E240: No connection to Vim server" +msgstr "E240: Vim サーãƒãƒ¼ã¸ã®æŽ¥ç¶šãŒã‚りã¾ã›ã‚“" -#: ../eval.c:18670 #, c-format -msgid "%s returning %s" -msgstr "%s ㌠%s ã‚’è¿”ã—ã¾ã—ãŸ" +msgid "E241: Unable to send to %s" +msgstr "E241: %s ã¸é€ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“" + +msgid "E277: Unable to read a server reply" +msgstr "E277: サーãƒãƒ¼ã®å¿œç”ãŒã‚りã¾ã›ã‚“" + +msgid "remove() argument" +msgstr "remove() ã®å¼•æ•°" + +# Added at 10-Mar-2004. +msgid "E655: Too many symbolic links (cycle?)" +msgstr "E655: シンボリックリンクãŒå¤šéŽãŽã¾ã™ (循環ã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™)" + +msgid "reverse() argument" +msgstr "reverse() ã®å¼•æ•°" + +msgid "E258: Unable to send to client" +msgstr "E258: クライアントã¸é€ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“" -#: ../eval.c:18691 ../ex_cmds2.c:2695 #, c-format -msgid "continuing in %s" -msgstr "%s ã®å®Ÿè¡Œã‚’継続ä¸ã§ã™" +msgid "E927: Invalid action: '%s'" +msgstr "E927: ç„¡åŠ¹ãªæ“作ã§ã™: %s" -#: ../eval.c:18795 -msgid "E133: :return not inside a function" -msgstr "E133: 関数外㫠:return ãŒã‚りã¾ã—ãŸ" +msgid "sort() argument" +msgstr "sort() ã®å¼•æ•°" -#: ../eval.c:19159 -msgid "" -"\n" -"# global variables:\n" -msgstr "" -"\n" -"# ã‚°ãƒãƒ¼ãƒãƒ«å¤‰æ•°:\n" +msgid "uniq() argument" +msgstr "uniq() ã®å¼•æ•°" -#: ../eval.c:19254 -msgid "" -"\n" -"\tLast set from " -msgstr "" -"\n" -"\tLast set from " +msgid "E702: Sort compare function failed" +msgstr "E702: ã‚½ãƒ¼ãƒˆã®æ¯”較関数ãŒå¤±æ•—ã—ã¾ã—ãŸ" -#: ../eval.c:19272 -msgid "No old files" -msgstr "å¤ã„ファイルã¯ã‚りã¾ã›ã‚“" +msgid "E882: Uniq compare function failed" +msgstr "E882: Uniq ã®æ¯”較関数ãŒå¤±æ•—ã—ã¾ã—ãŸ" + +msgid "(Invalid)" +msgstr "(無効)" + +#, c-format +msgid "E935: invalid submatch number: %d" +msgstr "E935: 無効ãªã‚µãƒ–マッãƒç•ªå·: %d" + +msgid "E677: Error writing temp file" +msgstr "E677: 一時ファイル書込ä¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ" + +msgid "E921: Invalid callback argument" +msgstr "E921: 無効ãªã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯å¼•æ•°ã§ã™" -#: ../ex_cmds.c:122 #, c-format msgid "<%s>%s%s %d, Hex %02x, Octal %03o" msgstr "<%s>%s%s %d, 16進数 %02x, 8進数 %03o" -#: ../ex_cmds.c:145 #, c-format msgid "> %d, Hex %04x, Octal %o" msgstr "> %d, 16進数 %04x, 8進数 %o" -#: ../ex_cmds.c:146 #, c-format msgid "> %d, Hex %08x, Octal %o" msgstr "> %d, 16進数 %08x, 8進数 %o" -#: ../ex_cmds.c:684 msgid "E134: Move lines into themselves" msgstr "E134: 行をãれ自身ã«ã¯ç§»å‹•ã§ãã¾ã›ã‚“" -#: ../ex_cmds.c:747 msgid "1 line moved" msgstr "1 行ãŒç§»å‹•ã•れã¾ã—ãŸ" -#: ../ex_cmds.c:749 #, c-format -msgid "%<PRId64> lines moved" -msgstr "%<PRId64> 行ãŒç§»å‹•ã•れã¾ã—ãŸ" +msgid "%ld lines moved" +msgstr "%ld 行ãŒç§»å‹•ã•れã¾ã—ãŸ" -#: ../ex_cmds.c:1175 #, c-format -msgid "%<PRId64> lines filtered" -msgstr "%<PRId64> 行ãŒãƒ•ィルタ処ç†ã•れã¾ã—ãŸ" +msgid "%ld lines filtered" +msgstr "%ld 行ãŒãƒ•ィルタ処ç†ã•れã¾ã—ãŸ" -#: ../ex_cmds.c:1194 msgid "E135: *Filter* Autocommands must not change current buffer" msgstr "E135: *フィルタ* autocommandã¯ç¾åœ¨ã®ãƒãƒƒãƒ•ァを変更ã—ã¦ã¯ã„ã‘ã¾ã›ã‚“" -#: ../ex_cmds.c:1244 msgid "[No write since last change]\n" msgstr "[最後ã®å¤‰æ›´ãŒä¿å˜ã•れã¦ã„ã¾ã›ã‚“]\n" -#: ../ex_cmds.c:1424 #, c-format msgid "%sviminfo: %s in line: " msgstr "%sviminfo: %s 行目: " -#: ../ex_cmds.c:1431 msgid "E136: viminfo: Too many errors, skipping rest of file" msgstr "E136: viminfo: エラーãŒå¤šéŽãŽã‚‹ã®ã§, 以é™ã¯ã‚¹ã‚ップã—ã¾ã™" -#: ../ex_cmds.c:1458 #, c-format msgid "Reading viminfo file \"%s\"%s%s%s" msgstr "viminfoファイル \"%s\"%s%s%s ã‚’èªè¾¼ã¿ä¸" -#: ../ex_cmds.c:1460 msgid " info" msgstr " æƒ…å ±" -#: ../ex_cmds.c:1461 msgid " marks" msgstr " マーク" -#: ../ex_cmds.c:1462 msgid " oldfiles" msgstr " 旧ファイル群" -#: ../ex_cmds.c:1463 msgid " FAILED" msgstr " 失敗" #. avoid a wait_return for this message, it's annoying -#: ../ex_cmds.c:1541 #, c-format msgid "E137: Viminfo file is not writable: %s" msgstr "E137: viminfoãƒ•ã‚¡ã‚¤ãƒ«ãŒæ›¸è¾¼ã¿ã§ãã¾ã›ã‚“: %s" -#: ../ex_cmds.c:1626 +#, c-format +msgid "E929: Too many viminfo temp files, like %s!" +msgstr "E929: 一時viminfoファイルãŒå¤šéŽãŽã¾ã™! 例: %s" + #, c-format msgid "E138: Can't write viminfo file %s!" msgstr "E138: viminfoファイル %s ã‚’ä¿å˜ã§ãã¾ã›ã‚“!" -#: ../ex_cmds.c:1635 #, c-format msgid "Writing viminfo file \"%s\"" msgstr "viminfoファイル \"%s\" を書込ã¿ä¸" +#, c-format +msgid "E886: Can't rename viminfo file to %s!" +msgstr "E886: viminfoファイルを %s ã¸åå‰å¤‰æ›´ã§ãã¾ã›ã‚“!" + #. Write the info: -#: ../ex_cmds.c:1720 #, c-format msgid "# This viminfo file was generated by Vim %s.\n" msgstr "# ã“ã® viminfo ファイル㯠Vim %s ã«ã‚ˆã£ã¦ç”Ÿæˆã•れã¾ã—ãŸ.\n" -#: ../ex_cmds.c:1722 msgid "" "# You may edit it if you're careful!\n" "\n" @@ -1143,47 +886,47 @@ msgstr "" "# 変更ã™ã‚‹éš›ã«ã¯å分注æ„ã—ã¦ãã ã•ã„!\n" "\n" -#: ../ex_cmds.c:1723 msgid "# Value of 'encoding' when this file was written\n" msgstr "# ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒæ›¸ã‹ã‚ŒãŸæ™‚ã® 'encoding' ã®å€¤\n" -#: ../ex_cmds.c:1800 msgid "Illegal starting char" msgstr "䏿£ãªå…ˆé æ–‡å—ã§ã™" -#: ../ex_cmds.c:2162 +msgid "" +"\n" +"# Bar lines, copied verbatim:\n" +msgstr "" +"\n" +"# '|' ã§å§‹ã¾ã‚‹è¡Œã®ã€æ–‡å—通りã®ã‚³ãƒ”ー:\n" + +msgid "Save As" +msgstr "別åã§ä¿å˜" + msgid "Write partial file?" msgstr "ファイルを部分的ã«ä¿å˜ã—ã¾ã™ã‹?" -#: ../ex_cmds.c:2166 msgid "E140: Use ! to write partial buffer" msgstr "E140: ãƒãƒƒãƒ•ァを部分的ã«ä¿å˜ã™ã‚‹ã«ã¯ ! を使ã£ã¦ãã ã•ã„" -#: ../ex_cmds.c:2281 #, c-format msgid "Overwrite existing file \"%s\"?" msgstr "æ—¢å˜ã®ãƒ•ァイル \"%s\" を上書ãã—ã¾ã™ã‹?" -#: ../ex_cmds.c:2317 #, c-format msgid "Swap file \"%s\" exists, overwrite anyway?" msgstr "スワップファイル \"%s\" ãŒå˜åœ¨ã—ã¾ã™. 上書ãを強制ã—ã¾ã™ã‹?" -#: ../ex_cmds.c:2326 #, c-format msgid "E768: Swap file exists: %s (:silent! overrides)" msgstr "E768: スワップファイルãŒå˜åœ¨ã—ã¾ã™: %s (:silent! ã‚’è¿½åŠ ã§ä¸Šæ›¸)" -#: ../ex_cmds.c:2381 #, c-format -msgid "E141: No file name for buffer %<PRId64>" -msgstr "E141: ãƒãƒƒãƒ•ã‚¡ %<PRId64> ã«ã¯åå‰ãŒã‚りã¾ã›ã‚“" +msgid "E141: No file name for buffer %ld" +msgstr "E141: ãƒãƒƒãƒ•ã‚¡ %ld ã«ã¯åå‰ãŒã‚りã¾ã›ã‚“" -#: ../ex_cmds.c:2412 msgid "E142: File not written: Writing is disabled by 'write' option" msgstr "E142: ファイルã¯ä¿å˜ã•れã¾ã›ã‚“ã§ã—ãŸ: 'write' オプションã«ã‚ˆã‚Šç„¡åйã§ã™" -#: ../ex_cmds.c:2434 #, c-format msgid "" "'readonly' option is set for \"%s\".\n" @@ -1192,7 +935,6 @@ msgstr "" "\"%s\" ã«ã¯ 'readonly' オプションãŒè¨å®šã•れã¦ã„ã¾ã™.\n" "上書ã強制をã—ã¾ã™ã‹?" -#: ../ex_cmds.c:2439 #, c-format msgid "" "File permissions of \"%s\" are read-only.\n" @@ -1203,83 +945,68 @@ msgstr "" "ãれã§ã‚‚æã‚‰ã書ã込むã“ã¨ã¯å¯èƒ½ã§ã™.\n" "継続ã—ã¾ã™ã‹?" -#: ../ex_cmds.c:2451 #, c-format msgid "E505: \"%s\" is read-only (add ! to override)" msgstr "E505: \"%s\" ã¯èªè¾¼å°‚用ã§ã™ (強制書込ã«ã¯ ! ã‚’è¿½åŠ )" -#: ../ex_cmds.c:3120 +msgid "Edit File" +msgstr "ファイルを編集" + #, c-format msgid "E143: Autocommands unexpectedly deleted new buffer %s" msgstr "E143: autocommandãŒäºˆæœŸã›ãšæ–°ã—ã„ãƒãƒƒãƒ•ã‚¡ %s を削除ã—ã¾ã—ãŸ" -#: ../ex_cmds.c:3313 msgid "E144: non-numeric argument to :z" msgstr "E144: æ•°ã§ã¯ãªã„引数㌠:z ã«æ¸¡ã•れã¾ã—ãŸ" -#: ../ex_cmds.c:3404 msgid "E145: Shell commands not allowed in rvim" msgstr "E145: rvimã§ã¯ã‚·ã‚§ãƒ«ã‚³ãƒžãƒ³ãƒ‰ã‚’使ãˆã¾ã›ã‚“" -#: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: æ£è¦è¡¨ç¾ã¯æ–‡å—ã§åŒºåˆ‡ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“" -#: ../ex_cmds.c:3964 #, c-format msgid "replace with %s (y/n/a/q/l/^E/^Y)?" msgstr "%s ã«ç½®æ›ã—ã¾ã™ã‹? (y/n/a/q/l/^E/^Y)" -#: ../ex_cmds.c:4379 msgid "(Interrupted) " msgstr "(割込ã¾ã‚Œã¾ã—ãŸ) " -#: ../ex_cmds.c:4384 msgid "1 match" msgstr "1 箇所該当ã—ã¾ã—ãŸ" -#: ../ex_cmds.c:4384 msgid "1 substitution" msgstr "1 箇所置æ›ã—ã¾ã—ãŸ" -#: ../ex_cmds.c:4387 #, c-format -msgid "%<PRId64> matches" -msgstr "%<PRId64> 箇所該当ã—ã¾ã—ãŸ" +msgid "%ld matches" +msgstr "%ld 箇所該当ã—ã¾ã—ãŸ" -#: ../ex_cmds.c:4388 #, c-format -msgid "%<PRId64> substitutions" -msgstr "%<PRId64> 箇所置æ›ã—ã¾ã—ãŸ" +msgid "%ld substitutions" +msgstr "%ld 箇所置æ›ã—ã¾ã—ãŸ" -#: ../ex_cmds.c:4392 msgid " on 1 line" msgstr " (計 1 行内)" -#: ../ex_cmds.c:4395 #, c-format -msgid " on %<PRId64> lines" -msgstr " (計 %<PRId64> 行内)" +msgid " on %ld lines" +msgstr " (計 %ld 行内)" -#: ../ex_cmds.c:4438 msgid "E147: Cannot do :global recursive" msgstr "E147: :global ã‚’å†å¸°çš„ã«ã¯ä½¿ãˆã¾ã›ã‚“" -#: ../ex_cmds.c:4467 msgid "E148: Regular expression missing from global" msgstr "E148: globalã‚³ãƒžãƒ³ãƒ‰ã«æ£è¦è¡¨ç¾ãŒæŒ‡å®šã•れã¦ã„ã¾ã›ã‚“" -#: ../ex_cmds.c:4508 #, c-format msgid "Pattern found in every line: %s" msgstr "パターンãŒå…¨ã¦ã®è¡Œã§è¦‹ã¤ã‹ã‚Šã¾ã—ãŸ: %s" -#: ../ex_cmds.c:4510 #, c-format msgid "Pattern not found: %s" msgstr "パターンã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ: %s" -#: ../ex_cmds.c:4587 msgid "" "\n" "# Last Substitute String:\n" @@ -1289,110 +1016,102 @@ msgstr "" "# 最後ã«ç½®æ›ã•ã‚ŒãŸæ–‡å—列:\n" "$" -#: ../ex_cmds.c:4679 msgid "E478: Don't panic!" msgstr "E478: æ…Œã¦ãªã„ã§ãã ã•ã„" -#: ../ex_cmds.c:4717 #, c-format msgid "E661: Sorry, no '%s' help for %s" msgstr "E661: 残念ã§ã™ãŒ '%s' ã®ãƒ˜ãƒ«ãƒ—㌠%s ã«ã¯ã‚りã¾ã›ã‚“" -#: ../ex_cmds.c:4719 #, c-format msgid "E149: Sorry, no help for %s" msgstr "E149: 残念ã§ã™ãŒ %s ã«ã¯ãƒ˜ãƒ«ãƒ—ãŒã‚りã¾ã›ã‚“" -#: ../ex_cmds.c:4751 #, c-format msgid "Sorry, help file \"%s\" not found" msgstr "残念ã§ã™ãŒãƒ˜ãƒ«ãƒ—ファイル \"%s\" ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../ex_cmds.c:5323 #, c-format -msgid "E150: Not a directory: %s" -msgstr "E150: ディレクトリã§ã¯ã‚りã¾ã›ã‚“: %s" +msgid "E151: No match: %s" +msgstr "E151: マッãƒã¯ã‚りã¾ã›ã‚“: %s" -#: ../ex_cmds.c:5446 #, c-format msgid "E152: Cannot open %s for writing" msgstr "E152: 書込ã¿ç”¨ã« %s ã‚’é–‹ã‘ã¾ã›ã‚“" -#: ../ex_cmds.c:5471 #, c-format msgid "E153: Unable to open %s for reading" msgstr "E153: èªè¾¼ç”¨ã« %s ã‚’é–‹ã‘ã¾ã›ã‚“" # Added at 29-Apr-2004. -#: ../ex_cmds.c:5500 #, c-format msgid "E670: Mix of help file encodings within a language: %s" msgstr "E670: 1ã¤ã®è¨€èªžã®ãƒ˜ãƒ«ãƒ—ファイルã«è¤‡æ•°ã®ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ãŒæ··åœ¨ã—ã¦ã„ã¾ã™: %s" -#: ../ex_cmds.c:5565 #, c-format msgid "E154: Duplicate tag \"%s\" in file %s/%s" msgstr "E154: ã‚¿ã‚° \"%s\" ãŒãƒ•ァイル %s/%s ã«é‡è¤‡ã—ã¦ã„ã¾ã™" -#: ../ex_cmds.c:5687 +#, c-format +msgid "E150: Not a directory: %s" +msgstr "E150: ディレクトリã§ã¯ã‚りã¾ã›ã‚“: %s" + #, c-format msgid "E160: Unknown sign command: %s" msgstr "E160: 未知ã®signコマンドã§ã™: %s" -#: ../ex_cmds.c:5704 msgid "E156: Missing sign name" msgstr "E156: signåãŒã‚りã¾ã›ã‚“" -#: ../ex_cmds.c:5746 msgid "E612: Too many signs defined" msgstr "E612: signã®å®šç¾©ãŒå¤šæ•°è¦‹ã¤ã‹ã‚Šã¾ã—ãŸ" -#: ../ex_cmds.c:5813 #, c-format msgid "E239: Invalid sign text: %s" msgstr "E239: 無効ãªsignã®ãƒ†ã‚ストã§ã™: %s" -#: ../ex_cmds.c:5844 ../ex_cmds.c:6035 #, c-format msgid "E155: Unknown sign: %s" msgstr "E155: 未知ã®signã§ã™: %s" -#: ../ex_cmds.c:5877 msgid "E159: Missing sign number" msgstr "E159: signã®ç•ªå·ãŒã‚りã¾ã›ã‚“" -#: ../ex_cmds.c:5971 #, c-format msgid "E158: Invalid buffer name: %s" msgstr "E158: 無効ãªãƒãƒƒãƒ•ã‚¡åã§ã™: %s" -#: ../ex_cmds.c:6008 +msgid "E934: Cannot jump to a buffer that does not have a name" +msgstr "E934: åå‰ã®ç„¡ã„ãƒãƒƒãƒ•ã‚¡ã¸ã¯ã‚¸ãƒ£ãƒ³ãƒ—ã§ãã¾ã›ã‚“" + #, c-format -msgid "E157: Invalid sign ID: %<PRId64>" -msgstr "E157: 無効ãªsignè˜åˆ¥åã§ã™: %<PRId64>" +msgid "E157: Invalid sign ID: %ld" +msgstr "E157: 無効ãªsignè˜åˆ¥åã§ã™: %ld" #, c-format msgid "E885: Not possible to change sign %s" msgstr "E885: 変更ã§ããªã„ sign ã§ã™: %s" -#: ../ex_cmds.c:6066 +# Added at 27-Jan-2004. +msgid " (NOT FOUND)" +msgstr " (見ã¤ã‹ã‚Šã¾ã›ã‚“)" + msgid " (not supported)" msgstr " (éžã‚µãƒãƒ¼ãƒˆ)" -#: ../ex_cmds.c:6169 msgid "[Deleted]" msgstr "[削除済]" -#: ../ex_cmds2.c:139 +msgid "No old files" +msgstr "å¤ã„ファイルã¯ã‚りã¾ã›ã‚“" + msgid "Entering Debug mode. Type \"cont\" to continue." msgstr "デãƒãƒƒã‚°ãƒ¢ãƒ¼ãƒ‰ã«å…¥ã‚Šã¾ã™. ç¶šã‘ã‚‹ã«ã¯ \"cont\" ã¨å…¥åŠ›ã—ã¦ãã ã•ã„." -#: ../ex_cmds2.c:143 ../ex_docmd.c:759 #, c-format -msgid "line %<PRId64>: %s" -msgstr "行 %<PRId64>: %s" +msgid "line %ld: %s" +msgstr "行 %ld: %s" -#: ../ex_cmds2.c:145 #, c-format msgid "cmd: %s" msgstr "コマンド: %s" @@ -1404,232 +1123,184 @@ msgstr "フレーム㌠0 ã§ã™" msgid "frame at highest level: %d" msgstr "最高レベルã®ãƒ•レーム: %d" -#: ../ex_cmds2.c:322 #, c-format -msgid "Breakpoint in \"%s%s\" line %<PRId64>" -msgstr "ブレークãƒã‚¤ãƒ³ãƒˆ \"%s%s\" 行 %<PRId64>" +msgid "Breakpoint in \"%s%s\" line %ld" +msgstr "ブレークãƒã‚¤ãƒ³ãƒˆ \"%s%s\" 行 %ld" -#: ../ex_cmds2.c:581 #, c-format msgid "E161: Breakpoint not found: %s" msgstr "E161: ブレークãƒã‚¤ãƒ³ãƒˆãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“: %s" -#: ../ex_cmds2.c:611 msgid "No breakpoints defined" msgstr "ブレークãƒã‚¤ãƒ³ãƒˆãŒå®šç¾©ã•れã¦ã„ã¾ã›ã‚“" -#: ../ex_cmds2.c:617 #, c-format -msgid "%3d %s %s line %<PRId64>" -msgstr "%3d %s %s 行 %<PRId64>" +msgid "%3d %s %s line %ld" +msgstr "%3d %s %s 行 %ld" -#: ../ex_cmds2.c:942 msgid "E750: First use \":profile start {fname}\"" msgstr "E750: åˆã‚ã« \":profile start {fname}\" を実行ã—ã¦ãã ã•ã„" -#: ../ex_cmds2.c:1269 #, c-format msgid "Save changes to \"%s\"?" msgstr "変更を \"%s\" ã«ä¿å˜ã—ã¾ã™ã‹?" -#: ../ex_cmds2.c:1271 ../ex_docmd.c:8851 msgid "Untitled" msgstr "無題" -#: ../ex_cmds2.c:1421 #, c-format msgid "E162: No write since last change for buffer \"%s\"" msgstr "E162: ãƒãƒƒãƒ•ã‚¡ \"%s\" ã®å¤‰æ›´ã¯ä¿å˜ã•れã¦ã„ã¾ã›ã‚“" -#: ../ex_cmds2.c:1480 msgid "Warning: Entered other buffer unexpectedly (check autocommands)" msgstr "è¦å‘Š: 予期ã›ãšä»–ãƒãƒƒãƒ•ã‚¡ã¸ç§»å‹•ã—ã¾ã—㟠(autocommands を調ã¹ã¦ãã ã•ã„)" -#: ../ex_cmds2.c:1826 msgid "E163: There is only one file to edit" msgstr "E163: 編集ã™ã‚‹ãƒ•ァイルã¯1ã¤ã—ã‹ã‚りã¾ã›ã‚“" -#: ../ex_cmds2.c:1828 msgid "E164: Cannot go before first file" msgstr "E164: 最åˆã®ãƒ•ァイルよりå‰ã«ã¯è¡Œã‘ã¾ã›ã‚“" -#: ../ex_cmds2.c:1830 msgid "E165: Cannot go beyond last file" msgstr "E165: 最後ã®ãƒ•ァイルを越ãˆã¦å¾Œã«ã¯è¡Œã‘ã¾ã›ã‚“" -#: ../ex_cmds2.c:2175 #, c-format msgid "E666: compiler not supported: %s" msgstr "E666: ãã®ã‚³ãƒ³ãƒ‘イラã«ã¯å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“: %s" -#: ../ex_cmds2.c:2257 #, c-format msgid "Searching for \"%s\" in \"%s\"" msgstr "\"%s\" ã‚’ \"%s\" ã‹ã‚‰æ¤œç´¢ä¸" -#: ../ex_cmds2.c:2284 #, c-format msgid "Searching for \"%s\"" msgstr "\"%s\" を検索ä¸" -#: ../ex_cmds2.c:2307 #, c-format -msgid "not found in 'runtimepath': \"%s\"" -msgstr "'runtimepath' ã®ä¸ã«ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“: \"%s\"" +msgid "not found in '%s': \"%s\"" +msgstr "'%s' ã®ä¸ã«ã¯ã‚りã¾ã›ã‚“: \"%s\"" + +msgid "Source Vim script" +msgstr "Vimスクリプトã®å–è¾¼ã¿" -#: ../ex_cmds2.c:2472 #, c-format msgid "Cannot source a directory: \"%s\"" msgstr "ディレクトリã¯å–è¾¼ã‚ã¾ã›ã‚“: \"%s\"" -#: ../ex_cmds2.c:2518 #, c-format msgid "could not source \"%s\"" msgstr "\"%s\" ã‚’å–è¾¼ã‚ã¾ã›ã‚“" -#: ../ex_cmds2.c:2520 #, c-format -msgid "line %<PRId64>: could not source \"%s\"" -msgstr "行 %<PRId64>: \"%s\" ã‚’å–è¾¼ã‚ã¾ã›ã‚“" +msgid "line %ld: could not source \"%s\"" +msgstr "行 %ld: \"%s\" ã‚’å–è¾¼ã‚ã¾ã›ã‚“" -#: ../ex_cmds2.c:2535 #, c-format msgid "sourcing \"%s\"" msgstr "\"%s\" ã‚’å–è¾¼ä¸" -#: ../ex_cmds2.c:2537 #, c-format -msgid "line %<PRId64>: sourcing \"%s\"" -msgstr "行 %<PRId64>: %s ã‚’å–è¾¼ä¸" +msgid "line %ld: sourcing \"%s\"" +msgstr "行 %ld: %s ã‚’å–è¾¼ä¸" -#: ../ex_cmds2.c:2693 #, c-format msgid "finished sourcing %s" msgstr "%s ã®å–込を完了" -#: ../ex_cmds2.c:2765 +#, c-format +msgid "continuing in %s" +msgstr "%s ã®å®Ÿè¡Œã‚’継続ä¸ã§ã™" + msgid "modeline" msgstr "モード行" -#: ../ex_cmds2.c:2767 msgid "--cmd argument" msgstr "--cmd 引数" -#: ../ex_cmds2.c:2769 msgid "-c argument" msgstr "-c 引数" -#: ../ex_cmds2.c:2771 msgid "environment variable" msgstr "環境変数" -#: ../ex_cmds2.c:2773 msgid "error handler" msgstr "エラーãƒãƒ³ãƒ‰ãƒ©" -#: ../ex_cmds2.c:3020 msgid "W15: Warning: Wrong line separator, ^M may be missing" msgstr "W15: è¦å‘Š: 行区切ãŒä¸æ£ã§ã™. ^M ãŒãªã„ã®ã§ã—ょã†" -#: ../ex_cmds2.c:3139 msgid "E167: :scriptencoding used outside of a sourced file" msgstr "E167: :scriptencoding ãŒå–込スクリプト以外ã§ä½¿ç”¨ã•れã¾ã—ãŸ" -#: ../ex_cmds2.c:3166 msgid "E168: :finish used outside of a sourced file" msgstr "E168: :finish ãŒå–込スクリプト以外ã§ä½¿ç”¨ã•れã¾ã—ãŸ" -#: ../ex_cmds2.c:3389 #, c-format msgid "Current %slanguage: \"%s\"" msgstr "ç¾åœ¨ã® %s言語: \"%s\"" -#: ../ex_cmds2.c:3404 #, c-format msgid "E197: Cannot set language to \"%s\"" msgstr "E197: 言語を \"%s\" ã«è¨å®šã§ãã¾ã›ã‚“" -#. don't redisplay the window -#. don't wait for return -#: ../ex_docmd.c:387 msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." msgstr "" "Exモードã«å…¥ã‚Šã¾ã™. ãƒŽãƒ¼ãƒžãƒ«ãƒ¢ãƒ¼ãƒ‰ã«æˆ»ã‚‹ã«ã¯\"visual\"ã¨å…¥åŠ›ã—ã¦ãã ã•ã„." -#: ../ex_docmd.c:428 msgid "E501: At end-of-file" msgstr "E501: ファイルã®çµ‚了ä½ç½®" -#: ../ex_docmd.c:513 msgid "E169: Command too recursive" msgstr "E169: コマンドãŒå†å¸°çš„éŽãŽã¾ã™" -#: ../ex_docmd.c:1006 #, c-format msgid "E605: Exception not caught: %s" msgstr "E605: ä¾‹å¤–ãŒæ•æ‰ã•れã¾ã›ã‚“ã§ã—ãŸ: %s" -#: ../ex_docmd.c:1085 msgid "End of sourced file" msgstr "å–è¾¼ãƒ•ã‚¡ã‚¤ãƒ«ã®æœ€å¾Œã§ã™" -#: ../ex_docmd.c:1086 msgid "End of function" msgstr "é–¢æ•°ã®æœ€å¾Œã§ã™" -#: ../ex_docmd.c:1628 msgid "E464: Ambiguous use of user-defined command" msgstr "E464: ユーザー定義コマンドã®ã‚ã„ã¾ã„ãªä½¿ç”¨ã§ã™" -#: ../ex_docmd.c:1638 msgid "E492: Not an editor command" msgstr "E492: エディタã®ã‚³ãƒžãƒ³ãƒ‰ã§ã¯ã‚りã¾ã›ã‚“" -#: ../ex_docmd.c:1729 msgid "E493: Backwards range given" msgstr "E493: 逆ã•ã¾ã®ç¯„å›²ãŒæŒ‡å®šã•れã¾ã—ãŸ" -#: ../ex_docmd.c:1733 msgid "Backwards range given, OK to swap" msgstr "逆ã•ã¾ã®ç¯„å›²ãŒæŒ‡å®šã•れã¾ã—ãŸ, 入替ãˆã¾ã™ã‹?" -#. append -#. typed wrong -#: ../ex_docmd.c:1787 msgid "E494: Use w or w>>" msgstr "E494: w ã‚‚ã—ã㯠w>> を使用ã—ã¦ãã ã•ã„" -#: ../ex_docmd.c:3454 -msgid "E319: The command is not available in this version" +msgid "E319: Sorry, the command is not available in this version" msgstr "E319: ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã¯ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“, ã”ã‚ã‚“ãªã•ã„" -#: ../ex_docmd.c:3752 msgid "E172: Only one file name allowed" msgstr "E172: ファイルå㯠1 ã¤ã«ã—ã¦ãã ã•ã„" -#: ../ex_docmd.c:4238 msgid "1 more file to edit. Quit anyway?" msgstr "編集ã™ã¹ãファイル㌠1 個ã‚りã¾ã™ãŒ, 終了ã—ã¾ã™ã‹?" -#: ../ex_docmd.c:4242 #, c-format msgid "%d more files to edit. Quit anyway?" msgstr "編集ã™ã¹ãファイルãŒã‚㨠%d 個ã‚りã¾ã™ãŒ, 終了ã—ã¾ã™ã‹?" -#: ../ex_docmd.c:4248 msgid "E173: 1 more file to edit" msgstr "E173: 編集ã™ã¹ãファイル㌠1 個ã‚りã¾ã™" -#: ../ex_docmd.c:4250 #, c-format -msgid "E173: %<PRId64> more files to edit" -msgstr "E173: 編集ã™ã¹ãファイルãŒã‚㨠%<PRId64> 個ã‚りã¾ã™" +msgid "E173: %ld more files to edit" +msgstr "E173: 編集ã™ã¹ãファイルãŒã‚㨠%ld 個ã‚りã¾ã™" -#: ../ex_docmd.c:4320 msgid "E174: Command already exists: add ! to replace it" msgstr "E174: ã‚³ãƒžãƒ³ãƒ‰ãŒæ—¢ã«ã‚りã¾ã™: å†å®šç¾©ã™ã‚‹ã«ã¯ ! ã‚’è¿½åŠ ã—ã¦ãã ã•ã„" -#: ../ex_docmd.c:4432 msgid "" "\n" " Name Args Address Complete Definition" @@ -1637,51 +1308,40 @@ msgstr "" "\n" " åå‰ å¼•æ•° アドレス 補完 定義" -#: ../ex_docmd.c:4516 msgid "No user-defined commands found" msgstr "ユーザー定義コマンドãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ" -#: ../ex_docmd.c:4538 msgid "E175: No attribute specified" msgstr "E175: 属性ã¯å®šç¾©ã•れã¦ã„ã¾ã›ã‚“" -#: ../ex_docmd.c:4583 msgid "E176: Invalid number of arguments" msgstr "E176: å¼•æ•°ã®æ•°ãŒç„¡åйã§ã™" -#: ../ex_docmd.c:4594 msgid "E177: Count cannot be specified twice" msgstr "E177: カウントを2釿Œ‡å®šã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“" -#: ../ex_docmd.c:4603 msgid "E178: Invalid default value for count" msgstr "E178: カウントã®çœç•¥å€¤ãŒç„¡åйã§ã™" -#: ../ex_docmd.c:4625 msgid "E179: argument required for -complete" msgstr "E179: -complete ã«ã¯å¼•æ•°ãŒå¿…è¦ã§ã™" msgid "E179: argument required for -addr" msgstr "E179: -addr ã«ã¯å¼•æ•°ãŒå¿…è¦ã§ã™" -#: ../ex_docmd.c:4635 #, c-format msgid "E181: Invalid attribute: %s" msgstr "E181: 無効ãªå±žæ€§ã§ã™: %s" -#: ../ex_docmd.c:4678 msgid "E182: Invalid command name" msgstr "E182: 無効ãªã‚³ãƒžãƒ³ãƒ‰åã§ã™" -#: ../ex_docmd.c:4691 msgid "E183: User defined commands must start with an uppercase letter" msgstr "E183: ユーザー定義コマンドã¯è‹±å¤§æ–‡å—ã§å§‹ã¾ã‚‰ãªã‘れã°ãªã‚Šã¾ã›ã‚“" -#: ../ex_docmd.c:4696 msgid "E841: Reserved name, cannot be used for user defined command" msgstr "E841: 予約åãªã®ã§, ユーザー定義コマンドã«åˆ©ç”¨ã§ãã¾ã›ã‚“" -#: ../ex_docmd.c:4751 #, c-format msgid "E184: No such user-defined command: %s" msgstr "E184: ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼å®šç¾©ã‚³ãƒžãƒ³ãƒ‰ã¯ã‚りã¾ã›ã‚“: %s" @@ -1690,293 +1350,261 @@ msgstr "E184: ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼å®šç¾©ã‚³ãƒžãƒ³ãƒ‰ã¯ã‚りã¾ã›ã‚“: %s" msgid "E180: Invalid address type value: %s" msgstr "E180: 無効ãªã‚¢ãƒ‰ãƒ¬ã‚¹ã‚¿ã‚¤ãƒ—値ã§ã™: %s" -#: ../ex_docmd.c:5219 #, c-format msgid "E180: Invalid complete value: %s" msgstr "E180: 無効ãªè£œå®ŒæŒ‡å®šã§ã™: %s" -#: ../ex_docmd.c:5225 msgid "E468: Completion argument only allowed for custom completion" msgstr "E468: 補完引数ã¯ã‚«ã‚¹ã‚¿ãƒ 補完ã§ã—ã‹ä½¿ç”¨ã§ãã¾ã›ã‚“" -#: ../ex_docmd.c:5231 msgid "E467: Custom completion requires a function argument" msgstr "E467: カスタム補完ã«ã¯å¼•æ•°ã¨ã—ã¦é–¢æ•°ãŒå¿…è¦ã§ã™" -#: ../ex_docmd.c:5257 +msgid "unknown" +msgstr "䏿˜Ž" + #, c-format msgid "E185: Cannot find color scheme '%s'" msgstr "E185: カラースã‚ーム'%s' ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../ex_docmd.c:5263 msgid "Greetings, Vim user!" msgstr "Vim 使ã„ã•ã‚“ã€ã‚„ã‚!" -#: ../ex_docmd.c:5431 msgid "E784: Cannot close last tab page" msgstr "E784: 最後ã®ã‚¿ãƒ–ページを閉ã˜ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“" -#: ../ex_docmd.c:5462 msgid "Already only one tab page" msgstr "æ—¢ã«ã‚¿ãƒ–ページã¯1ã¤ã—ã‹ã‚りã¾ã›ã‚“" -#: ../ex_docmd.c:6004 +msgid "Edit File in new window" +msgstr "æ–°ã—ã„ウィンドウã§ãƒ•ァイルを編集ã—ã¾ã™" + #, c-format msgid "Tab page %d" msgstr "タブページ %d" -#: ../ex_docmd.c:6295 msgid "No swap file" msgstr "スワップファイルãŒã‚りã¾ã›ã‚“" -#: ../ex_docmd.c:6478 +msgid "Append File" +msgstr "è¿½åŠ ãƒ•ã‚¡ã‚¤ãƒ«" + msgid "E747: Cannot change directory, buffer is modified (add ! to override)" msgstr "" "E747: ãƒãƒƒãƒ•ã‚¡ãŒä¿®æ£ã•れã¦ã„ã‚‹ã®ã§, ディレクトリを変更ã§ãã¾ã›ã‚“ (! ã‚’è¿½åŠ ã§" "上書)" -#: ../ex_docmd.c:6485 msgid "E186: No previous directory" msgstr "E186: å‰ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã¯ã‚りã¾ã›ã‚“" -#: ../ex_docmd.c:6530 msgid "E187: Unknown" msgstr "E187: 未知" -#: ../ex_docmd.c:6610 msgid "E465: :winsize requires two number arguments" msgstr "E465: :winsize ã«ã¯2ã¤ã®æ•°å€¤ã®å¼•æ•°ãŒå¿…è¦ã§ã™" -#: ../ex_docmd.c:6655 +#, c-format +msgid "Window position: X %d, Y %d" +msgstr "ウィンドウä½ç½®: X %d, Y %d" + msgid "E188: Obtaining window position not implemented for this platform" msgstr "" "E188: ã“ã®ãƒ—ラットホームã«ã¯ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ä½ç½®ã®å–得機能ã¯å®Ÿè£…ã•れã¦ã„ã¾ã›ã‚“" -#: ../ex_docmd.c:6662 msgid "E466: :winpos requires two number arguments" msgstr "E466: :winpos ã«ã¯2ã¤ã®æ•°å€¤ã®å¼•æ•°ãŒå¿…è¦ã§ã™" -#: ../ex_docmd.c:7241 +msgid "E930: Cannot use :redir inside execute()" +msgstr "E930: execute() ã®ä¸ã§ã¯ :redir ã¯ä½¿ãˆã¾ã›ã‚“" + +msgid "Save Redirection" +msgstr "リダイレクトをä¿å˜ã—ã¾ã™" + +msgid "Save View" +msgstr "ビューをä¿å˜ã—ã¾ã™" + +msgid "Save Session" +msgstr "ã‚»ãƒƒã‚·ãƒ§ãƒ³æƒ…å ±ã‚’ä¿å˜ã—ã¾ã™" + +msgid "Save Setup" +msgstr "è¨å®šã‚’ä¿å˜ã—ã¾ã™" + #, c-format msgid "E739: Cannot create directory: %s" msgstr "E739: ディレクトリを作æˆã§ãã¾ã›ã‚“: %s" -#: ../ex_docmd.c:7268 #, c-format msgid "E189: \"%s\" exists (add ! to override)" msgstr "E189: \"%s\" ãŒå˜åœ¨ã—ã¾ã™ (上書ã™ã‚‹ã«ã¯ ! ã‚’è¿½åŠ ã—ã¦ãã ã•ã„)" -#: ../ex_docmd.c:7273 #, c-format msgid "E190: Cannot open \"%s\" for writing" msgstr "E190: \"%s\" を書込ã¿ç”¨ã¨ã—ã¦é–‹ã‘ã¾ã›ã‚“" #. set mark -#: ../ex_docmd.c:7294 msgid "E191: Argument must be a letter or forward/backward quote" msgstr "E191: 引数ã¯1æ–‡å—ã®è‹±å—ã‹å¼•用符 (' ã‹ `) ã§ãªã‘れã°ã„ã‘ã¾ã›ã‚“" -#: ../ex_docmd.c:7333 msgid "E192: Recursive use of :normal too deep" msgstr "E192: :normal ã®å†å¸°åˆ©ç”¨ãŒæ·±ããªã‚ŠéŽãŽã¾ã—ãŸ" -#: ../ex_docmd.c:7807 +msgid "E809: #< is not available without the +eval feature" +msgstr "E809: #< 㯠+eval 機能ãŒç„¡ã„ã¨åˆ©ç”¨ã§ãã¾ã›ã‚“" + msgid "E194: No alternate file name to substitute for '#'" msgstr "E194: '#'ã‚’ç½®ãæ›ãˆã‚‹å‰¯ãƒ•ァイルã®åå‰ãŒã‚りã¾ã›ã‚“" -#: ../ex_docmd.c:7841 msgid "E495: no autocommand file name to substitute for \"<afile>\"" msgstr "E495: \"<afile>\"ã‚’ç½®ãæ›ãˆã‚‹autocommandã®ãƒ•ァイルåãŒã‚りã¾ã›ã‚“" -#: ../ex_docmd.c:7850 msgid "E496: no autocommand buffer number to substitute for \"<abuf>\"" msgstr "E496: \"<abuf>\"ã‚’ç½®ãæ›ãˆã‚‹autocommandãƒãƒƒãƒ•ァ番å·ãŒã‚りã¾ã›ã‚“" -#: ../ex_docmd.c:7861 msgid "E497: no autocommand match name to substitute for \"<amatch>\"" msgstr "E497: \"<amatch>\"ã‚’ç½®ãæ›ãˆã‚‹autocommandã®è©²å½“åãŒã‚りã¾ã›ã‚“" -#: ../ex_docmd.c:7870 msgid "E498: no :source file name to substitute for \"<sfile>\"" msgstr "E498: \"<sfile>\"ã‚’ç½®ãæ›ãˆã‚‹ :source 対象ファイルåãŒã‚りã¾ã›ã‚“" -#: ../ex_docmd.c:7876 msgid "E842: no line number to use for \"<slnum>\"" msgstr "E842: \"<slnum>\"ã‚’ç½®ãæ›ãˆã‚‹è¡Œç•ªå·ãŒã‚りã¾ã›ã‚“" -#: ../ex_docmd.c:7903 -#, fuzzy, c-format +#, no-c-format msgid "E499: Empty file name for '%' or '#', only works with \":p:h\"" msgstr "" "E499: '%' ã‚„ '#' ãŒç„¡åファイルãªã®ã§ \":p:h\" ã‚’ä¼´ã‚ãªã„ä½¿ã„æ–¹ã¯ã§ãã¾ã›ã‚“" -#: ../ex_docmd.c:7905 msgid "E500: Evaluates to an empty string" msgstr "E500: 空文å—列ã¨ã—ã¦è©•価ã•れã¾ã—ãŸ" -#: ../ex_docmd.c:8838 msgid "E195: Cannot open viminfo file for reading" msgstr "E195: viminfoファイルをèªè¾¼ç”¨ã¨ã—ã¦é–‹ã‘ã¾ã›ã‚“" -#: ../ex_eval.c:464 +msgid "E196: No digraphs in this version" +msgstr "E196: ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«åˆå—ã¯ã‚りã¾ã›ã‚“" + msgid "E608: Cannot :throw exceptions with 'Vim' prefix" msgstr "E608: 'Vim' ã§å§‹ã¾ã‚‹ä¾‹å¤–㯠:throw ã§ãã¾ã›ã‚“" #. always scroll up, don't overwrite -#: ../ex_eval.c:496 #, c-format msgid "Exception thrown: %s" msgstr "例外ãŒç™ºç”Ÿã—ã¾ã—ãŸ: %s" -#: ../ex_eval.c:545 #, c-format msgid "Exception finished: %s" msgstr "例外ãŒåŽæŸã—ã¾ã—ãŸ: %s" -#: ../ex_eval.c:546 #, c-format msgid "Exception discarded: %s" msgstr "例外ãŒç ´æ£„ã•れã¾ã—ãŸ: %s" -#: ../ex_eval.c:588 ../ex_eval.c:634 #, c-format -msgid "%s, line %<PRId64>" -msgstr "%s, 行 %<PRId64>" +msgid "%s, line %ld" +msgstr "%s, 行 %ld" #. always scroll up, don't overwrite -#: ../ex_eval.c:608 #, c-format msgid "Exception caught: %s" msgstr "ä¾‹å¤–ãŒæ•æ‰ã•れã¾ã—ãŸ: %s" -#: ../ex_eval.c:676 #, c-format msgid "%s made pending" msgstr "%s ã«ã‚ˆã‚Šæœªæ±ºå®šçŠ¶æ…‹ãŒç”Ÿã˜ã¾ã—ãŸ" -#: ../ex_eval.c:679 #, c-format msgid "%s resumed" msgstr "%s ãŒå†é–‹ã—ã¾ã—ãŸ" -#: ../ex_eval.c:683 #, c-format msgid "%s discarded" msgstr "%s ãŒç ´æ£„ã•れã¾ã—ãŸ" -#: ../ex_eval.c:708 msgid "Exception" msgstr "例外" -#: ../ex_eval.c:713 msgid "Error and interrupt" msgstr "エラーã¨å‰²è¾¼ã¿" -#: ../ex_eval.c:715 msgid "Error" msgstr "エラー" #. if (pending & CSTP_INTERRUPT) -#: ../ex_eval.c:717 msgid "Interrupt" msgstr "割込ã¿" -#: ../ex_eval.c:795 msgid "E579: :if nesting too deep" msgstr "E579: :if ã®å…¥ã‚ŒåãŒæ·±éŽãŽã¾ã™" -#: ../ex_eval.c:830 msgid "E580: :endif without :if" msgstr "E580: :if ã®ãªã„ :endif ãŒã‚りã¾ã™" -#: ../ex_eval.c:873 msgid "E581: :else without :if" msgstr "E581: :if ã®ãªã„ :else ãŒã‚りã¾ã™" -#: ../ex_eval.c:876 msgid "E582: :elseif without :if" msgstr "E582: :if ã®ãªã„ :elseif ãŒã‚りã¾ã™" -#: ../ex_eval.c:880 msgid "E583: multiple :else" msgstr "E583: 複数㮠:else ãŒã‚りã¾ã™" -#: ../ex_eval.c:883 msgid "E584: :elseif after :else" msgstr "E584: :else ã®å¾Œã« :elseif ãŒã‚りã¾ã™" -#: ../ex_eval.c:941 msgid "E585: :while/:for nesting too deep" msgstr "E585: :while ã‚„ :for ã®å…¥ã‚ŒåãŒæ·±éŽãŽã¾ã™" -#: ../ex_eval.c:1028 msgid "E586: :continue without :while or :for" msgstr "E586: :while ã‚„ :for ã®ãªã„ :continue ãŒã‚りã¾ã™" -#: ../ex_eval.c:1061 msgid "E587: :break without :while or :for" msgstr "E587: :while ã‚„ :for ã®ãªã„ :break ãŒã‚りã¾ã™" -#: ../ex_eval.c:1102 msgid "E732: Using :endfor with :while" msgstr "E732: :endfor ã‚’ :while ã¨çµ„ã¿åˆã‚ã›ã¦ã„ã¾ã™" -#: ../ex_eval.c:1104 msgid "E733: Using :endwhile with :for" msgstr "E733: :endwhile ã‚’ :for ã¨çµ„ã¿åˆã‚ã›ã¦ã„ã¾ã™" -#: ../ex_eval.c:1247 msgid "E601: :try nesting too deep" msgstr "E601: :try ã®å…¥ã‚ŒåãŒæ·±éŽãŽã¾ã™" -#: ../ex_eval.c:1317 msgid "E603: :catch without :try" msgstr "E603: :try ã®ãªã„ :catch ãŒã‚りã¾ã™" #. Give up for a ":catch" after ":finally" and ignore it. #. * Just parse. -#: ../ex_eval.c:1332 msgid "E604: :catch after :finally" msgstr "E604: :finally ã®å¾Œã« :catch ãŒã‚りã¾ã™" -#: ../ex_eval.c:1451 msgid "E606: :finally without :try" msgstr "E606: :try ã®ãªã„ :finally ãŒã‚りã¾ã™" #. Give up for a multiple ":finally" and ignore it. -#: ../ex_eval.c:1467 msgid "E607: multiple :finally" msgstr "E607: 複数㮠:finally ãŒã‚りã¾ã™" -#: ../ex_eval.c:1571 msgid "E602: :endtry without :try" msgstr "E602: :try ã®ãªã„ :endtry ã§ã™" -#: ../ex_eval.c:2026 msgid "E193: :endfunction not inside a function" msgstr "E193: 関数ã®å¤–ã« :endfunction ãŒã‚りã¾ã—ãŸ" -#: ../ex_getln.c:1643 msgid "E788: Not allowed to edit another buffer now" msgstr "E788: ç¾åœ¨ã¯ä»–ã®ãƒãƒƒãƒ•ァを編集ã™ã‚‹ã“ã¨ã¯è¨±ã•れã¾ã›ã‚“" -#: ../ex_getln.c:1656 msgid "E811: Not allowed to change buffer information now" msgstr "E811: ç¾åœ¨ã¯ãƒãƒƒãƒ•ã‚¡æƒ…å ±ã‚’å¤‰æ›´ã™ã‚‹ã“ã¨ã¯è¨±ã•れã¾ã›ã‚“" -#: ../ex_getln.c:3178 msgid "tagname" msgstr "ã‚¿ã‚°å" -#: ../ex_getln.c:3181 msgid " kind file\n" msgstr " ファイル種類\n" -#: ../ex_getln.c:4799 msgid "'history' option is zero" msgstr "オプション 'history' ãŒã‚¼ãƒã§ã™" -#: ../ex_getln.c:5046 #, c-format msgid "" "\n" @@ -1985,303 +1613,224 @@ msgstr "" "\n" "# %s é …ç›®ã®å±¥æ´ (æ–°ã—ã„ã‚‚ã®ã‹ã‚‰å¤ã„ã‚‚ã®ã¸):\n" -#: ../ex_getln.c:5047 msgid "Command Line" msgstr "コマンドライン" -#: ../ex_getln.c:5048 msgid "Search String" msgstr "検索文å—列" -#: ../ex_getln.c:5049 msgid "Expression" msgstr "å¼" -#: ../ex_getln.c:5050 msgid "Input Line" msgstr "入力行" -#: ../ex_getln.c:5117 +msgid "Debug Line" +msgstr "デãƒãƒƒã‚°è¡Œ" + msgid "E198: cmd_pchar beyond the command length" msgstr "E198: cmd_pchar ãŒã‚³ãƒžãƒ³ãƒ‰é•·ã‚’è¶…ãˆã¾ã—ãŸ" -#: ../ex_getln.c:5279 msgid "E199: Active window or buffer deleted" msgstr "E199: アクティブãªã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‹ãƒãƒƒãƒ•ã‚¡ãŒå‰Šé™¤ã•れã¾ã—ãŸ" -#: ../file_search.c:203 -msgid "E854: path too long for completion" -msgstr "E854: パスãŒé•·éŽãŽã¦è£œå®Œã§ãã¾ã›ã‚“" - -#: ../file_search.c:446 -#, c-format -msgid "" -"E343: Invalid path: '**[number]' must be at the end of the path or be " -"followed by '%s'." -msgstr "" -"E343: 無効ãªãƒ‘スã§ã™: '**[数値]' ã¯pathã®æœ€å¾Œã‹ '%s' ãŒç¶šã„ã¦ãªã„ã¨ã„ã‘ã¾ã›" -"ã‚“." - -#: ../file_search.c:1505 -#, c-format -msgid "E344: Can't find directory \"%s\" in cdpath" -msgstr "E344: cdpathã«ã¯ \"%s\" ã¨ã„ã†ãƒ•ァイルãŒã‚りã¾ã›ã‚“" - -#: ../file_search.c:1508 -#, c-format -msgid "E345: Can't find file \"%s\" in path" -msgstr "E345: pathã«ã¯ \"%s\" ã¨ã„ã†ãƒ•ァイルãŒã‚りã¾ã›ã‚“" - -#: ../file_search.c:1512 -#, c-format -msgid "E346: No more directory \"%s\" found in cdpath" -msgstr "E346: cdpathã«ã¯ã“れ以上 \"%s\" ã¨ã„ã†ãƒ•ァイルãŒã‚りã¾ã›ã‚“" - -#: ../file_search.c:1515 -#, c-format -msgid "E347: No more file \"%s\" found in path" -msgstr "E347: パスã«ã¯ã“れ以上 \"%s\" ã¨ã„ã†ãƒ•ァイルãŒã‚りã¾ã›ã‚“" - -#: ../fileio.c:137 msgid "E812: Autocommands changed buffer or buffer name" msgstr "E812: autocommandãŒãƒãƒƒãƒ•ã‚¡ã‹ãƒãƒƒãƒ•ã‚¡åを変更ã—ã¾ã—ãŸ" -#: ../fileio.c:368 msgid "Illegal file name" msgstr "䏿£ãªãƒ•ァイルå" -#: ../fileio.c:395 ../fileio.c:476 ../fileio.c:2543 ../fileio.c:2578 msgid "is a directory" msgstr "ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã§ã™" -#: ../fileio.c:397 msgid "is not a file" msgstr "ã¯ãƒ•ァイルã§ã¯ã‚りã¾ã›ã‚“" -#: ../fileio.c:508 ../fileio.c:3522 +msgid "is a device (disabled with 'opendevice' option)" +msgstr "ã¯ãƒ‡ãƒã‚¤ã‚¹ã§ã™ ('opendevice' オプションã§å›žé¿ã§ãã¾ã™)" + msgid "[New File]" msgstr "[新ファイル]" -#: ../fileio.c:511 msgid "[New DIRECTORY]" msgstr "[æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒª]" -#: ../fileio.c:529 ../fileio.c:532 msgid "[File too big]" msgstr "[ファイルéŽå¤§]" -#: ../fileio.c:534 msgid "[Permission Denied]" msgstr "[権é™ãŒã‚りã¾ã›ã‚“]" -#: ../fileio.c:653 msgid "E200: *ReadPre autocommands made the file unreadable" msgstr "E200: *ReadPre autocommand ãŒãƒ•ァイルをèªè¾¼ä¸å¯ã«ã—ã¾ã—ãŸ" -#: ../fileio.c:655 msgid "E201: *ReadPre autocommands must not change current buffer" msgstr "E201: *ReadPre autocommand ã¯ç¾åœ¨ã®ãƒãƒƒãƒ•ァを変ãˆã‚‰ã‚Œã¾ã›ã‚“" -#: ../fileio.c:672 -msgid "Nvim: Reading from stdin...\n" +msgid "Vim: Reading from stdin...\n" msgstr "Vim: 標準入力ã‹ã‚‰èªè¾¼ä¸...\n" +msgid "Reading from stdin..." +msgstr "標準入力ã‹ã‚‰èªè¾¼ã¿ä¸..." + #. Re-opening the original file failed! -#: ../fileio.c:909 msgid "E202: Conversion made file unreadable!" msgstr "E202: 変æ›ãŒãƒ•ァイルをèªè¾¼ä¸å¯ã«ã—ã¾ã—ãŸ" -#. fifo or socket -#: ../fileio.c:1782 msgid "[fifo/socket]" msgstr "[FIFO/ソケット]" -#. fifo -#: ../fileio.c:1788 msgid "[fifo]" msgstr "[FIFO]" -#. or socket -#: ../fileio.c:1794 msgid "[socket]" msgstr "[ソケット]" -#. or character special -#: ../fileio.c:1801 msgid "[character special]" msgstr "[ã‚ャラクタ・デãƒã‚¤ã‚¹]" -#: ../fileio.c:1815 msgid "[CR missing]" msgstr "[CRç„¡]" -#: ../fileio.c:1819 msgid "[long lines split]" msgstr "[長行分割]" -#: ../fileio.c:1823 ../fileio.c:3512 msgid "[NOT converted]" msgstr "[未変æ›]" -#: ../fileio.c:1826 ../fileio.c:3515 msgid "[converted]" msgstr "[å¤‰æ›æ¸ˆ]" -#: ../fileio.c:1831 #, c-format -msgid "[CONVERSION ERROR in line %<PRId64>]" -msgstr "[%<PRId64> 行目ã§å¤‰æ›ã‚¨ãƒ©ãƒ¼]" +msgid "[CONVERSION ERROR in line %ld]" +msgstr "[%ld 行目ã§å¤‰æ›ã‚¨ãƒ©ãƒ¼]" -#: ../fileio.c:1835 #, c-format -msgid "[ILLEGAL BYTE in line %<PRId64>]" -msgstr "[%<PRId64> 行目ã®ä¸æ£ãªãƒã‚¤ãƒˆ]" +msgid "[ILLEGAL BYTE in line %ld]" +msgstr "[%ld 行目ã®ä¸æ£ãªãƒã‚¤ãƒˆ]" -#: ../fileio.c:1838 msgid "[READ ERRORS]" msgstr "[èªè¾¼ã‚¨ãƒ©ãƒ¼]" -#: ../fileio.c:2104 msgid "Can't find temp file for conversion" msgstr "変æ›ã«å¿…è¦ãªä¸€æ™‚ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../fileio.c:2110 msgid "Conversion with 'charconvert' failed" msgstr "'charconvert' ã«ã‚ˆã‚‹å¤‰æ›ãŒå¤±æ•—ã—ã¾ã—ãŸ" -#: ../fileio.c:2113 msgid "can't read output of 'charconvert'" msgstr "'charconvert' ã®å‡ºåŠ›ã‚’èªè¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸ" -#: ../fileio.c:2437 msgid "E676: No matching autocommands for acwrite buffer" msgstr "E676: acwriteãƒãƒƒãƒ•ã‚¡ã®è©²å½“ã™ã‚‹autocommandã¯å˜åœ¨ã—ã¾ã›ã‚“" -#: ../fileio.c:2466 msgid "E203: Autocommands deleted or unloaded buffer to be written" msgstr "E203: ä¿å˜ã™ã‚‹ãƒãƒƒãƒ•ã‚¡ã‚’autocommandãŒå‰Šé™¤ã‹è§£æ”¾ã—ã¾ã—ãŸ" -#: ../fileio.c:2486 msgid "E204: Autocommand changed number of lines in unexpected way" msgstr "E204: autocommandãŒäºˆæœŸã›ã¬æ–¹æ³•ã§è¡Œæ•°ã‚’変更ã—ã¾ã—ãŸ" -#: ../fileio.c:2548 ../fileio.c:2565 +# Added at 19-Jan-2004. +msgid "NetBeans disallows writes of unmodified buffers" +msgstr "NetBeansã¯æœªå¤‰æ›´ã®ãƒãƒƒãƒ•ァを上書ã™ã‚‹ã“ã¨ã¯è¨±å¯ã—ã¦ã„ã¾ã›ã‚“" + +msgid "Partial writes disallowed for NetBeans buffers" +msgstr "NetBeansãƒãƒƒãƒ•ã‚¡ã®ä¸€éƒ¨ã‚’書ã出ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“" + msgid "is not a file or writable device" msgstr "ã¯ãƒ•ァイルã§ã‚‚書込ã¿å¯èƒ½ãƒ‡ãƒã‚¤ã‚¹ã§ã‚‚ã‚りã¾ã›ã‚“" -#: ../fileio.c:2601 +msgid "writing to device disabled with 'opendevice' option" +msgstr "'opendevice' オプションã«ã‚ˆã‚Šãƒ‡ãƒã‚¤ã‚¹ã¸ã®æ›¸ãè¾¼ã¿ã¯ã§ãã¾ã›ã‚“" + msgid "is read-only (add ! to override)" msgstr "ã¯èªè¾¼å°‚用ã§ã™ (強制書込ã«ã¯ ! ã‚’è¿½åŠ )" -#: ../fileio.c:2886 msgid "E506: Can't write to backup file (add ! to override)" msgstr "E506: ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ファイルをä¿å˜ã§ãã¾ã›ã‚“ (! ã‚’è¿½åŠ ã§å¼·åˆ¶ä¿å˜)" -#: ../fileio.c:2898 msgid "E507: Close error for backup file (add ! to override)" msgstr "" "E507: ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ファイルを閉ã˜ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—㟠(! ã‚’è¿½åŠ ã§å¼·åˆ¶)" -#: ../fileio.c:2901 msgid "E508: Can't read file for backup (add ! to override)" msgstr "E508: ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—用ファイルをèªè¾¼ã‚ã¾ã›ã‚“ (! ã‚’è¿½åŠ ã§å¼·åˆ¶èªè¾¼)" -#: ../fileio.c:2923 msgid "E509: Cannot create backup file (add ! to override)" msgstr "E509: ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ファイルを作れã¾ã›ã‚“ (! ã‚’è¿½åŠ ã§å¼·åˆ¶ä½œæˆ)" -#: ../fileio.c:3008 msgid "E510: Can't make backup file (add ! to override)" msgstr "E510: ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ファイルを作れã¾ã›ã‚“ (! ã‚’è¿½åŠ ã§å¼·åˆ¶ä½œæˆ)" -#. Can't write without a tempfile! -#: ../fileio.c:3121 +msgid "E460: The resource fork would be lost (add ! to override)" +msgstr "E460: リソースフォークãŒå¤±ã‚れるã‹ã‚‚ã—れã¾ã›ã‚“ (! ã‚’è¿½åŠ ã§å¼·åˆ¶)" + msgid "E214: Can't find temp file for writing" msgstr "E214: ä¿å˜ç”¨ä¸€æ™‚ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../fileio.c:3134 msgid "E213: Cannot convert (add ! to write without conversion)" msgstr "E213: 変æ›ã§ãã¾ã›ã‚“ (! ã‚’è¿½åŠ ã§å¤‰æ›ã›ãšã«ä¿å˜)" -#: ../fileio.c:3169 msgid "E166: Can't open linked file for writing" msgstr "E166: リンクã•れãŸãƒ•ã‚¡ã‚¤ãƒ«ã«æ›¸è¾¼ã‚ã¾ã›ã‚“" -#: ../fileio.c:3173 msgid "E212: Can't open file for writing" msgstr "E212: 書込ã¿ç”¨ã«ãƒ•ァイルを開ã‘ã¾ã›ã‚“" -#: ../fileio.c:3363 msgid "E667: Fsync failed" msgstr "E667: fsync ã«å¤±æ•—ã—ã¾ã—ãŸ" -#: ../fileio.c:3398 msgid "E512: Close failed" msgstr "E512: é–‰ã˜ã‚‹ã“ã¨ã«å¤±æ•—" -#: ../fileio.c:3436 msgid "E513: write error, conversion failed (make 'fenc' empty to override)" msgstr "E513: 書込ã¿ã‚¨ãƒ©ãƒ¼, 変æ›å¤±æ•— (上書ã™ã‚‹ã«ã¯ 'fenc' を空ã«ã—ã¦ãã ã•ã„)" -#: ../fileio.c:3441 #, c-format msgid "" -"E513: write error, conversion failed in line %<PRId64> (make 'fenc' empty to " +"E513: write error, conversion failed in line %ld (make 'fenc' empty to " "override)" msgstr "" -"E513: 書込ã¿ã‚¨ãƒ©ãƒ¼, 変æ›å¤±æ•—, 行数 %<PRId64> (上書ã™ã‚‹ã«ã¯ 'fenc' を空ã«ã—ã¦" -"ãã ã•ã„)" +"E513: 書込ã¿ã‚¨ãƒ©ãƒ¼, 変æ›å¤±æ•—, 行数 %ld (上書ã™ã‚‹ã«ã¯ 'fenc' を空ã«ã—ã¦ãã ã•" +"ã„)" -#: ../fileio.c:3448 msgid "E514: write error (file system full?)" msgstr "E514: 書込ã¿ã‚¨ãƒ©ãƒ¼, (ãƒ•ã‚¡ã‚¤ãƒ«ã‚·ã‚¹ãƒ†ãƒ ãŒæº€æ¯?)" -#: ../fileio.c:3506 msgid " CONVERSION ERROR" msgstr " 変æ›ã‚¨ãƒ©ãƒ¼" -#: ../fileio.c:3509 #, c-format -msgid " in line %<PRId64>;" -msgstr " 行 %<PRId64>;" +msgid " in line %ld;" +msgstr " 行 %ld;" -#: ../fileio.c:3519 msgid "[Device]" msgstr "[デãƒã‚¤ã‚¹]" -#: ../fileio.c:3522 msgid "[New]" msgstr "[æ–°]" -#: ../fileio.c:3535 msgid " [a]" msgstr " [a]" -#: ../fileio.c:3535 msgid " appended" msgstr " è¿½åŠ " -#: ../fileio.c:3537 msgid " [w]" msgstr " [w]" -#: ../fileio.c:3537 msgid " written" msgstr " 書込ã¿" -#: ../fileio.c:3579 msgid "E205: Patchmode: can't save original file" msgstr "E205: patchmode: 原本ファイルをä¿å˜ã§ãã¾ã›ã‚“" -#: ../fileio.c:3602 msgid "E206: patchmode: can't touch empty original file" msgstr "E206: patchmode: 空ã®åŽŸæœ¬ãƒ•ã‚¡ã‚¤ãƒ«ã‚’touchã§ãã¾ã›ã‚“" -#: ../fileio.c:3616 msgid "E207: Can't delete backup file" msgstr "E207: ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ファイルを消ã›ã¾ã›ã‚“" -#: ../fileio.c:3672 msgid "" "\n" "WARNING: Original file may be lost or damaged\n" @@ -2289,134 +1838,105 @@ msgstr "" "\n" "è¦å‘Š: 原本ファイルãŒå¤±ã‚れãŸã‹å¤‰æ›´ã•れã¾ã—ãŸ\n" -#: ../fileio.c:3675 msgid "don't quit the editor until the file is successfully written!" msgstr "ファイルã®ä¿å˜ã«æˆåŠŸã™ã‚‹ã¾ã§ã‚¨ãƒ‡ã‚£ã‚¿ã‚’終了ã—ãªã„ã§ãã ã•ã„!" -#: ../fileio.c:3795 msgid "[dos]" msgstr "[dos]" -#: ../fileio.c:3795 msgid "[dos format]" msgstr "[dosフォーマット]" -#: ../fileio.c:3801 msgid "[mac]" msgstr "[mac]" -#: ../fileio.c:3801 msgid "[mac format]" msgstr "[macフォーマット]" -#: ../fileio.c:3807 msgid "[unix]" msgstr "[unix]" -#: ../fileio.c:3807 msgid "[unix format]" msgstr "[unixフォーマット]" -#: ../fileio.c:3831 msgid "1 line, " msgstr "1 行, " -#: ../fileio.c:3833 #, c-format -msgid "%<PRId64> lines, " -msgstr "%<PRId64> 行, " +msgid "%ld lines, " +msgstr "%ld 行, " -#: ../fileio.c:3836 msgid "1 character" msgstr "1 æ–‡å—" -#: ../fileio.c:3838 #, c-format -msgid "%<PRId64> characters" -msgstr "%<PRId64> æ–‡å—" +msgid "%lld characters" +msgstr "%lld æ–‡å—" -#: ../fileio.c:3849 msgid "[noeol]" msgstr "[noeol]" -#: ../fileio.c:3849 msgid "[Incomplete last line]" msgstr "[最終行ãŒä¸å®Œå…¨]" #. don't overwrite messages here #. must give this prompt #. don't use emsg() here, don't want to flush the buffers -#: ../fileio.c:3865 msgid "WARNING: The file has been changed since reading it!!!" msgstr "è¦å‘Š: èªè¾¼ã‚“ã 後ã«ãƒ•ァイルã«å¤‰æ›´ãŒã‚りã¾ã—ãŸ!!!" -#: ../fileio.c:3867 msgid "Do you really want to write to it" msgstr "本当ã«ä¸Šæ›¸ãã—ã¾ã™ã‹" -#: ../fileio.c:4648 #, c-format msgid "E208: Error writing to \"%s\"" msgstr "E208: \"%s\" を書込ã¿ä¸ã®ã‚¨ãƒ©ãƒ¼ã§ã™" -#: ../fileio.c:4655 #, c-format msgid "E209: Error closing \"%s\"" msgstr "E209: \"%s\" ã‚’é–‰ã˜ã‚‹æ™‚ã«ã‚¨ãƒ©ãƒ¼ã§ã™" -#: ../fileio.c:4657 #, c-format msgid "E210: Error reading \"%s\"" msgstr "E210: \"%s\" ã‚’èªè¾¼ä¸ã®ã‚¨ãƒ©ãƒ¼ã§ã™" -#: ../fileio.c:4883 msgid "E246: FileChangedShell autocommand deleted buffer" msgstr "E246: autocommand ã® FileChangedShell ãŒãƒãƒƒãƒ•ァを削除ã—ã¾ã—ãŸ" -#: ../fileio.c:4894 #, c-format msgid "E211: File \"%s\" no longer available" msgstr "E211: ファイル \"%s\" ã¯æ—¢ã«å˜åœ¨ã—ã¾ã›ã‚“" -#: ../fileio.c:4906 #, c-format msgid "" "W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as " "well" msgstr "W12: è¦å‘Š: ファイル \"%s\" ãŒå¤‰æ›´ã•れVimã®ãƒãƒƒãƒ•ァも変更ã•れã¾ã—ãŸ" -#: ../fileio.c:4907 msgid "See \":help W12\" for more info." msgstr "詳細㯠\":help W12\" ã‚’å‚ç…§ã—ã¦ãã ã•ã„" -#: ../fileio.c:4910 #, c-format msgid "W11: Warning: File \"%s\" has changed since editing started" msgstr "W11: è¦å‘Š: ファイル \"%s\" ã¯ç·¨é›†é–‹å§‹å¾Œã«å¤‰æ›´ã•れã¾ã—ãŸ" -#: ../fileio.c:4911 msgid "See \":help W11\" for more info." msgstr "詳細㯠\":help W11\" ã‚’å‚ç…§ã—ã¦ãã ã•ã„" -#: ../fileio.c:4914 #, c-format msgid "W16: Warning: Mode of file \"%s\" has changed since editing started" msgstr "W16: è¦å‘Š: ファイル \"%s\" ã®ãƒ¢ãƒ¼ãƒ‰ãŒç·¨é›†é–‹å§‹å¾Œã«å¤‰æ›´ã•れã¾ã—ãŸ" -#: ../fileio.c:4915 msgid "See \":help W16\" for more info." msgstr "詳細㯠\":help W16\" ã‚’å‚ç…§ã—ã¦ãã ã•ã„" -#: ../fileio.c:4927 #, c-format msgid "W13: Warning: File \"%s\" has been created after editing started" msgstr "W13: è¦å‘Š: ファイル \"%s\" ã¯ç·¨é›†é–‹å§‹å¾Œã«ä½œæˆã•れã¾ã—ãŸ" -#: ../fileio.c:4947 msgid "Warning" msgstr "è¦å‘Š" -#: ../fileio.c:4948 msgid "" "&OK\n" "&Load File" @@ -2424,48 +1944,45 @@ msgstr "" "&OK\n" "ファイルèªè¾¼(&L)" -#: ../fileio.c:5065 #, c-format msgid "E462: Could not prepare for reloading \"%s\"" msgstr "E462: \"%s\" をリãƒãƒ¼ãƒ‰ã™ã‚‹æº–å‚™ãŒã§ãã¾ã›ã‚“ã§ã—ãŸ" -#: ../fileio.c:5078 #, c-format msgid "E321: Could not reload \"%s\"" msgstr "E321: \"%s\" ã¯ãƒªãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§ã—ãŸ" -#: ../fileio.c:5601 msgid "--Deleted--" msgstr "--削除済--" -#: ../fileio.c:5732 #, c-format msgid "auto-removing autocommand: %s <buffer=%d>" msgstr "autocommand: %s <ãƒãƒƒãƒ•ã‚¡=%d> ãŒè‡ªå‹•çš„ã«å‰Šé™¤ã•れã¾ã™" #. the group doesn't exist -#: ../fileio.c:5772 #, c-format msgid "E367: No such group: \"%s\"" msgstr "E367: ãã®ã‚°ãƒ«ãƒ¼ãƒ—ã¯ã‚りã¾ã›ã‚“: \"%s\"" -#: ../fileio.c:5897 +msgid "E936: Cannot delete the current group" +msgstr "E936: ç¾åœ¨ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¯å‰Šé™¤ã§ãã¾ã›ã‚“" + +msgid "W19: Deleting augroup that is still in use" +msgstr "W19: 使用ä¸ã® augroup を消ãã†ã¨ã—ã¦ã„ã¾ã™" + #, c-format msgid "E215: Illegal character after *: %s" msgstr "E215: * ã®å¾Œã«ä¸æ£ãªæ–‡å—ãŒã‚りã¾ã—ãŸ: %s" -#: ../fileio.c:5905 #, c-format msgid "E216: No such event: %s" msgstr "E216: ãã®ã‚ˆã†ãªã‚¤ãƒ™ãƒ³ãƒˆã¯ã‚りã¾ã›ã‚“: %s" -#: ../fileio.c:5907 #, c-format msgid "E216: No such group or event: %s" msgstr "E216: ãã®ã‚ˆã†ãªã‚°ãƒ«ãƒ¼ãƒ—ã‚‚ã—ãã¯ã‚¤ãƒ™ãƒ³ãƒˆã¯ã‚りã¾ã›ã‚“: %s" #. Highlight title -#: ../fileio.c:6090 msgid "" "\n" "--- Auto-Commands ---" @@ -2473,756 +1990,555 @@ msgstr "" "\n" "--- Auto-Commands ---" -#: ../fileio.c:6293 #, c-format msgid "E680: <buffer=%d>: invalid buffer number " msgstr "E680: <ãƒãƒƒãƒ•ã‚¡=%d>: 無効ãªãƒãƒƒãƒ•ァ番å·ã§ã™ " -#: ../fileio.c:6370 msgid "E217: Can't execute autocommands for ALL events" msgstr "E217: å…¨ã¦ã®ã‚¤ãƒ™ãƒ³ãƒˆã«å¯¾ã—ã¦ã®autocommandã¯å®Ÿè¡Œã§ãã¾ã›ã‚“" -#: ../fileio.c:6393 msgid "No matching autocommands" msgstr "該当ã™ã‚‹autocommandã¯å˜åœ¨ã—ã¾ã›ã‚“" -#: ../fileio.c:6831 msgid "E218: autocommand nesting too deep" msgstr "E218: autocommandã®å…¥ã‚ŒåãŒæ·±éŽãŽã¾ã™" -#: ../fileio.c:7143 #, c-format msgid "%s Auto commands for \"%s\"" msgstr "%s Auto commands for \"%s\"" -#: ../fileio.c:7149 #, c-format msgid "Executing %s" msgstr "%s を実行ã—ã¦ã„ã¾ã™" -#: ../fileio.c:7211 #, c-format msgid "autocommand %s" msgstr "autocommand %s" -#: ../fileio.c:7795 msgid "E219: Missing {." msgstr "E219: { ãŒã‚りã¾ã›ã‚“." -#: ../fileio.c:7797 msgid "E220: Missing }." msgstr "E220: } ãŒã‚りã¾ã›ã‚“." -#: ../fold.c:93 msgid "E490: No fold found" msgstr "E490: 折畳ã¿ãŒã‚りã¾ã›ã‚“" -#: ../fold.c:544 msgid "E350: Cannot create fold with current 'foldmethod'" msgstr "E350: ç¾åœ¨ã® 'foldmethod' ã§ã¯æŠ˜ç•³ã¿ã‚’作æˆã§ãã¾ã›ã‚“" -#: ../fold.c:546 msgid "E351: Cannot delete fold with current 'foldmethod'" msgstr "E351: ç¾åœ¨ã® 'foldmethod' ã§ã¯æŠ˜ç•³ã¿ã‚’削除ã§ãã¾ã›ã‚“" -#: ../fold.c:1784 #, c-format -msgid "+--%3ld lines folded " -msgstr "+--%3ld è¡ŒãŒæŠ˜ç•³ã¾ã‚Œã¾ã—㟠" +msgid "+--%3ld line folded " +msgid_plural "+--%3ld lines folded " +msgstr[0] "+--%3ld è¡ŒãŒæŠ˜ç•³ã¾ã‚Œã¾ã—㟠" -#. buffer has already been read -#: ../getchar.c:273 msgid "E222: Add to read buffer" msgstr "E222: èªè¾¼ãƒãƒƒãƒ•ã‚¡ã¸è¿½åŠ " -#: ../getchar.c:2040 msgid "E223: recursive mapping" msgstr "E223: å†å¸°çš„マッピング" -#: ../getchar.c:2849 #, c-format msgid "E224: global abbreviation already exists for %s" msgstr "E224: %s ã¨ã„ã†ã‚°ãƒãƒ¼ãƒãƒ«çŸç¸®å…¥åŠ›ã¯æ—¢ã«å˜åœ¨ã—ã¾ã™" -#: ../getchar.c:2852 #, c-format msgid "E225: global mapping already exists for %s" msgstr "E225: %s ã¨ã„ã†ã‚°ãƒãƒ¼ãƒãƒ«ãƒžãƒƒãƒ”ãƒ³ã‚°ã¯æ—¢ã«å˜åœ¨ã—ã¾ã™" -#: ../getchar.c:2952 #, c-format msgid "E226: abbreviation already exists for %s" msgstr "E226: %s ã¨ã„ã†çŸç¸®å…¥åŠ›ã¯æ—¢ã«å˜åœ¨ã—ã¾ã™" -#: ../getchar.c:2955 #, c-format msgid "E227: mapping already exists for %s" msgstr "E227: %s ã¨ã„ã†ãƒžãƒƒãƒ”ãƒ³ã‚°ã¯æ—¢ã«å˜åœ¨ã—ã¾ã™" -#: ../getchar.c:3008 msgid "No abbreviation found" msgstr "çŸç¸®å…¥åŠ›ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ" -#: ../getchar.c:3010 msgid "No mapping found" msgstr "マッピングã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ" -#: ../getchar.c:3974 msgid "E228: makemap: Illegal mode" msgstr "E228: makemap: 䏿£ãªãƒ¢ãƒ¼ãƒ‰" -#. key value of 'cedit' option -#. type of cmdline window or 0 -#. result of cmdline window or 0 -#: ../globals.h:924 -msgid "--No lines in buffer--" -msgstr "--ãƒãƒƒãƒ•ã‚¡ã«è¡ŒãŒã‚りã¾ã›ã‚“--" +msgid "E851: Failed to create a new process for the GUI" +msgstr "E851: GUI用ã®ãƒ—ãƒã‚»ã‚¹ã®èµ·å‹•ã«å¤±æ•—ã—ã¾ã—ãŸ" -#. -#. * The error messages that can be shared are included here. -#. * Excluded are errors that are only used once and debugging messages. -#. -#: ../globals.h:996 -msgid "E470: Command aborted" -msgstr "E470: コマンドãŒä¸æ–ã•れã¾ã—ãŸ" +msgid "E852: The child process failed to start the GUI" +msgstr "E852: åプãƒã‚»ã‚¹ãŒGUIã®èµ·å‹•ã«å¤±æ•—ã—ã¾ã—ãŸ" -#: ../globals.h:997 -msgid "E471: Argument required" -msgstr "E471: 引数ãŒå¿…è¦ã§ã™" +msgid "E229: Cannot start the GUI" +msgstr "E229: GUIã‚’é–‹å§‹ã§ãã¾ã›ã‚“" -#: ../globals.h:998 -msgid "E10: \\ should be followed by /, ? or &" -msgstr "E10: \\ ã®å¾Œã¯ / ã‹ ? ã‹ & ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" +#, c-format +msgid "E230: Cannot read from \"%s\"" +msgstr "E230: \"%s\"ã‹ã‚‰èªè¾¼ã‚€ã“ã¨ãŒã§ãã¾ã›ã‚“" -#: ../globals.h:1000 -msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" -msgstr "E11: コマンドラインã§ã¯ç„¡åйã§ã™; <CR>ã§å®Ÿè¡Œ, CTRL-Cã§ã‚„ã‚ã‚‹" +msgid "E665: Cannot start GUI, no valid font found" +msgstr "E665: 有効ãªãƒ•ォントãŒè¦‹ã¤ã‹ã‚‰ãªã„ã®ã§, GUIã‚’é–‹å§‹ã§ãã¾ã›ã‚“" -#: ../globals.h:1002 -msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" -msgstr "" -"E12: ç¾åœ¨ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚„タグ検索ã§ã¯exrc/vimrcã®ã‚³ãƒžãƒ³ãƒ‰ã¯è¨±å¯ã•れã¾ã›ã‚“" +msgid "E231: 'guifontwide' invalid" +msgstr "E231: 'guifontwide' ãŒç„¡åйã§ã™" -#: ../globals.h:1003 -msgid "E171: Missing :endif" -msgstr "E171: :endif ãŒã‚りã¾ã›ã‚“" +msgid "E599: Value of 'imactivatekey' is invalid" +msgstr "E599: 'imactivatekey' ã«è¨å®šã•れãŸå€¤ãŒç„¡åйã§ã™" -#: ../globals.h:1004 -msgid "E600: Missing :endtry" -msgstr "E600: :endtry ãŒã‚りã¾ã›ã‚“" +#, c-format +msgid "E254: Cannot allocate color %s" +msgstr "E254: %s ã®è‰²ã‚’割り当ã¦ã‚‰ã‚Œã¾ã›ã‚“" -#: ../globals.h:1005 -msgid "E170: Missing :endwhile" -msgstr "E170: :endwhile ãŒã‚りã¾ã›ã‚“" +msgid "No match at cursor, finding next" +msgstr "カーソルã®ä½ç½®ã«ãƒžãƒƒãƒã¯ã‚りã¾ã›ã‚“, 次を検索ã—ã¦ã„ã¾ã™" -#: ../globals.h:1006 -msgid "E170: Missing :endfor" -msgstr "E170: :endfor ãŒã‚りã¾ã›ã‚“" - -#: ../globals.h:1007 -msgid "E588: :endwhile without :while" -msgstr "E588: :while ã®ãªã„ :endwhile ãŒã‚りã¾ã™" +msgid "<cannot open> " +msgstr "<é–‹ã‘ã¾ã›ã‚“> " -#: ../globals.h:1008 -msgid "E588: :endfor without :for" -msgstr "E588: :endfor ã®ãªã„ :for ãŒã‚りã¾ã™" +#, c-format +msgid "E616: vim_SelFile: can't get font %s" +msgstr "E616: vim_SelFile: フォント %s ã‚’å–å¾—ã§ãã¾ã›ã‚“" -#: ../globals.h:1009 -msgid "E13: File exists (add ! to override)" -msgstr "E13: ファイルãŒå˜åœ¨ã—ã¾ã™ (! ã‚’è¿½åŠ ã§ä¸Šæ›¸)" +msgid "E614: vim_SelFile: can't return to current directory" +msgstr "E614: vim_SelFile: ç¾åœ¨ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«æˆ»ã‚Œã¾ã›ã‚“" -#: ../globals.h:1010 -msgid "E472: Command failed" -msgstr "E472: コマンドãŒå¤±æ•—ã—ã¾ã—ãŸ" +msgid "Pathname:" +msgstr "パスå:" -#: ../globals.h:1011 -msgid "E473: Internal error" -msgstr "E473: 内部エラーã§ã™" +msgid "E615: vim_SelFile: can't get current directory" +msgstr "E615: vim_SelFile: ç¾åœ¨ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’å–å¾—ã§ãã¾ã›ã‚“" -#: ../globals.h:1012 -msgid "Interrupted" -msgstr "割込ã¾ã‚Œã¾ã—ãŸ" +msgid "OK" +msgstr "OK" -#: ../globals.h:1013 -msgid "E14: Invalid address" -msgstr "E14: 無効ãªã‚¢ãƒ‰ãƒ¬ã‚¹ã§ã™" +msgid "Cancel" +msgstr "ã‚ャンセル" -#: ../globals.h:1014 -msgid "E474: Invalid argument" -msgstr "E474: 無効ãªå¼•æ•°ã§ã™" +msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." +msgstr "スクãƒãƒ¼ãƒ«ãƒãƒ¼: ç”»åƒã‚’å–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸ." -#: ../globals.h:1015 -#, c-format -msgid "E475: Invalid argument: %s" -msgstr "E475: 無効ãªå¼•æ•°ã§ã™: %s" +msgid "Vim dialog" +msgstr "Vim ダイアãƒã‚°" -#: ../globals.h:1016 -#, c-format -msgid "E15: Invalid expression: %s" -msgstr "E15: 無効ãªå¼ã§ã™: %s" +msgid "E232: Cannot create BalloonEval with both message and callback" +msgstr "E232: メッセージã¨ã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯ã®ã‚ã‚‹ BalloonEval を作æˆã§ãã¾ã›ã‚“" -#: ../globals.h:1017 -msgid "E16: Invalid range" -msgstr "E16: 無効ãªç¯„囲ã§ã™" +msgid "_Cancel" +msgstr "ã‚ャンセル(_C)" -#: ../globals.h:1018 -msgid "E476: Invalid command" -msgstr "E476: 無効ãªã‚³ãƒžãƒ³ãƒ‰ã§ã™" +msgid "_Save" +msgstr "ä¿å˜(_S)" -#: ../globals.h:1019 -#, c-format -msgid "E17: \"%s\" is a directory" -msgstr "E17: \"%s\" ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã§ã™" +msgid "_Open" +msgstr "é–‹ã(_O)" -#: ../globals.h:1020 -#, fuzzy -msgid "E900: Invalid job id" -msgstr "E49: 無効ãªã‚¹ã‚¯ãƒãƒ¼ãƒ«é‡ã§ã™" +msgid "_OK" +msgstr "_OK" -#: ../globals.h:1021 -msgid "E901: Job table is full" +msgid "" +"&Yes\n" +"&No\n" +"&Cancel" msgstr "" +"ã¯ã„(&Y)\n" +"ã„ã„ãˆ(&N)\n" +"ã‚ャンセル(&C)" -#: ../globals.h:1024 -#, c-format -msgid "E364: Library call failed for \"%s()\"" -msgstr "E364: \"%s\"() ã®ãƒ©ã‚¤ãƒ–ラリ呼出ã«å¤±æ•—ã—ã¾ã—ãŸ" +msgid "Yes" +msgstr "ã¯ã„" -#: ../globals.h:1026 -msgid "E19: Mark has invalid line number" -msgstr "E19: マークã«ç„¡åйãªè¡Œç•ªå·ãŒæŒ‡å®šã•れã¦ã„ã¾ã—ãŸ" +msgid "No" +msgstr "ã„ã„ãˆ" -#: ../globals.h:1027 -msgid "E20: Mark not set" -msgstr "E20: マークã¯è¨å®šã•れã¦ã„ã¾ã›ã‚“" +msgid "Input _Methods" +msgstr "インプットメソッド" -#: ../globals.h:1029 -msgid "E21: Cannot make changes, 'modifiable' is off" -msgstr "E21: 'modifiable' ãŒã‚ªãƒ•ãªã®ã§, 変更ã§ãã¾ã›ã‚“" +msgid "VIM - Search and Replace..." +msgstr "VIM - 検索ã¨ç½®æ›..." -#: ../globals.h:1030 -msgid "E22: Scripts nested too deep" -msgstr "E22: スクリプトã®å…¥ã‚ŒåãŒæ·±éŽãŽã¾ã™" +msgid "VIM - Search..." +msgstr "VIM - 検索..." -#: ../globals.h:1031 -msgid "E23: No alternate file" -msgstr "E23: 副ファイルã¯ã‚りã¾ã›ã‚“" +msgid "Find what:" +msgstr "検索文å—列:" -#: ../globals.h:1032 -msgid "E24: No such abbreviation" -msgstr "E24: ãã®ã‚ˆã†ãªçŸç¸®å…¥åŠ›ã¯ã‚りã¾ã›ã‚“" +msgid "Replace with:" +msgstr "ç½®æ›æ–‡å—列:" -#: ../globals.h:1033 -msgid "E477: No ! allowed" -msgstr "E477: ! ã¯è¨±å¯ã•れã¦ã„ã¾ã›ã‚“" +#. whole word only button +msgid "Match whole word only" +msgstr "æ£ç¢ºã«è©²å½“ã™ã‚‹ã‚‚ã®ã ã‘" -#: ../globals.h:1035 -msgid "E25: Nvim does not have a built-in GUI" -msgstr "E25: GUIã¯ä½¿ç”¨ä¸å¯èƒ½ã§ã™: コンパイル時ã«ç„¡åйã«ã•れã¦ã„ã¾ã™" +#. match case button +msgid "Match case" +msgstr "大文å—/å°æ–‡å—を区別ã™ã‚‹" -#: ../globals.h:1036 -#, c-format -msgid "E28: No such highlight group name: %s" -msgstr "E28: ãã®ã‚ˆã†ãªåã®ãƒã‚¤ãƒ©ã‚¤ãƒˆã‚°ãƒ«ãƒ¼ãƒ—ã¯ã‚りã¾ã›ã‚“: %s" +msgid "Direction" +msgstr "æ–¹å‘" -#: ../globals.h:1037 -msgid "E29: No inserted text yet" -msgstr "E29: ã¾ã テã‚ã‚¹ãƒˆãŒæŒ¿å…¥ã•れã¦ã„ã¾ã›ã‚“" +#. 'Up' and 'Down' buttons +msgid "Up" +msgstr "上" -#: ../globals.h:1038 -msgid "E30: No previous command line" -msgstr "E30: 以å‰ã«ã‚³ãƒžãƒ³ãƒ‰è¡ŒãŒã‚りã¾ã›ã‚“" +msgid "Down" +msgstr "下" -#: ../globals.h:1039 -msgid "E31: No such mapping" -msgstr "E31: ãã®ã‚ˆã†ãªãƒžãƒƒãƒ”ングã¯ã‚りã¾ã›ã‚“" +msgid "Find Next" +msgstr "次を検索" -#: ../globals.h:1040 -msgid "E479: No match" -msgstr "E479: 該当ã¯ã‚りã¾ã›ã‚“" +msgid "Replace" +msgstr "ç½®æ›" -#: ../globals.h:1041 -#, c-format -msgid "E480: No match: %s" -msgstr "E480: 該当ã¯ã‚りã¾ã›ã‚“: %s" +msgid "Replace All" +msgstr "å…¨ã¦ç½®æ›" -#: ../globals.h:1042 -msgid "E32: No file name" -msgstr "E32: ファイルåãŒã‚りã¾ã›ã‚“" +msgid "_Close" +msgstr "é–‰ã˜ã‚‹(_C)" -#: ../globals.h:1044 -msgid "E33: No previous substitute regular expression" -msgstr "E33: æ£è¦è¡¨ç¾ç½®æ›ãŒã¾ã 実行ã•れã¦ã„ã¾ã›ã‚“" +msgid "Vim: Received \"die\" request from session manager\n" +msgstr "Vim: セッションマãƒãƒ¼ã‚¸ãƒ£ã‹ã‚‰ \"die\" è¦æ±‚ã‚’å—ã‘å–りã¾ã—ãŸ\n" -#: ../globals.h:1045 -msgid "E34: No previous command" -msgstr "E34: コマンドãŒã¾ã 実行ã•れã¦ã„ã¾ã›ã‚“" +msgid "Close tab" +msgstr "タブページを閉ã˜ã‚‹" -#: ../globals.h:1046 -msgid "E35: No previous regular expression" -msgstr "E35: æ£è¦è¡¨ç¾ãŒã¾ã 実行ã•れã¦ã„ã¾ã›ã‚“" +msgid "New tab" +msgstr "æ–°è¦ã‚¿ãƒ–ページ" -#: ../globals.h:1047 -msgid "E481: No range allowed" -msgstr "E481: 範囲指定ã¯è¨±å¯ã•れã¦ã„ã¾ã›ã‚“" +msgid "Open Tab..." +msgstr "タブページを開ã..." -#: ../globals.h:1048 -msgid "E36: Not enough room" -msgstr "E36: ウィンドウã«å分ãªé«˜ã•ã‚‚ã—ãã¯å¹…ãŒã‚りã¾ã›ã‚“" +msgid "Vim: Main window unexpectedly destroyed\n" +msgstr "Vim: メインウィンドウãŒä¸æ„ã«ç ´å£Šã•れã¾ã—ãŸ\n" -#: ../globals.h:1049 -#, c-format -msgid "E482: Can't create file %s" -msgstr "E482: ファイル %s を作æˆã§ãã¾ã›ã‚“" +msgid "&Filter" +msgstr "フィルタ(&F)" -#: ../globals.h:1050 -msgid "E483: Can't get temp file name" -msgstr "E483: 一時ファイルã®åå‰ã‚’å–å¾—ã§ãã¾ã›ã‚“" +msgid "&Cancel" +msgstr "ã‚ャンセル(&C)" -#: ../globals.h:1051 -#, c-format -msgid "E484: Can't open file %s" -msgstr "E484: ファイル \"%s\" ã‚’é–‹ã‘ã¾ã›ã‚“" +msgid "Directories" +msgstr "ディレクトリ" -#: ../globals.h:1052 -#, c-format -msgid "E485: Can't read file %s" -msgstr "E485: ファイル %s ã‚’èªè¾¼ã‚ã¾ã›ã‚“" +msgid "Filter" +msgstr "フィルタ" -#: ../globals.h:1054 -msgid "E37: No write since last change (add ! to override)" -msgstr "E37: 最後ã®å¤‰æ›´ãŒä¿å˜ã•れã¦ã„ã¾ã›ã‚“ (! ã‚’è¿½åŠ ã§å¤‰æ›´ã‚’ç ´æ£„)" +msgid "&Help" +msgstr "ヘルプ(&H)" -#: ../globals.h:1055 -msgid "E37: No write since last change" -msgstr "E37: 最後ã®å¤‰æ›´ãŒä¿å˜ã•れã¦ã„ã¾ã›ã‚“" +msgid "Files" +msgstr "ファイル" -#: ../globals.h:1056 -msgid "E38: Null argument" -msgstr "E38: 引数ãŒç©ºã§ã™" +msgid "&OK" +msgstr "&OK" -#: ../globals.h:1057 -msgid "E39: Number expected" -msgstr "E39: 数値ãŒè¦æ±‚ã•れã¦ã„ã¾ã™" +msgid "Selection" +msgstr "é¸æŠž" -#: ../globals.h:1058 -#, c-format -msgid "E40: Can't open errorfile %s" -msgstr "E40: エラーファイル %s ã‚’é–‹ã‘ã¾ã›ã‚“" +msgid "Find &Next" +msgstr "次を検索(&N)" -#: ../globals.h:1059 -msgid "E41: Out of memory!" -msgstr "E41: メモリãŒå°½ãæžœã¦ã¾ã—ãŸ!" +msgid "&Replace" +msgstr "ç½®æ›(&R)" -#: ../globals.h:1060 -msgid "Pattern not found" -msgstr "パターンã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ" +msgid "Replace &All" +msgstr "å…¨ã¦ç½®æ›(&A)" -#: ../globals.h:1061 -#, c-format -msgid "E486: Pattern not found: %s" -msgstr "E486: パターンã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ: %s" +msgid "&Undo" +msgstr "アンドゥ(&U)" -#: ../globals.h:1062 -msgid "E487: Argument must be positive" -msgstr "E487: å¼•æ•°ã¯æ£ã®å€¤ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" +msgid "Open tab..." +msgstr "タブページを開ã" -#: ../globals.h:1064 -msgid "E459: Cannot go back to previous directory" -msgstr "E459: å‰ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«æˆ»ã‚Œã¾ã›ã‚“" +msgid "Find string (use '\\\\' to find a '\\')" +msgstr "検索文å—列 ('\\' を検索ã™ã‚‹ã«ã¯ '\\\\')" -#: ../globals.h:1066 -msgid "E42: No Errors" -msgstr "E42: エラーã¯ã‚りã¾ã›ã‚“" +msgid "Find & Replace (use '\\\\' to find a '\\')" +msgstr "æ¤œç´¢ãƒ»ç½®æ› ('\\' を検索ã™ã‚‹ã«ã¯ '\\\\')" -#: ../globals.h:1067 -msgid "E776: No location list" -msgstr "E776: ãƒã‚±ãƒ¼ã‚·ãƒ§ãƒ³ãƒªã‚¹ãƒˆã¯ã‚りã¾ã›ã‚“" - -#: ../globals.h:1068 -msgid "E43: Damaged match string" -msgstr "E43: 該当文å—列ãŒç ´æã—ã¦ã„ã¾ã™" +#. We fake this: Use a filter that doesn't select anything and a default +#. * file name that won't be used. +msgid "Not Used" +msgstr "使ã‚れã¾ã›ã‚“" -#: ../globals.h:1069 -msgid "E44: Corrupted regexp program" -msgstr "E44: 䏿£ãªæ£è¦è¡¨ç¾ãƒ—ãƒã‚°ãƒ©ãƒ ã§ã™" +msgid "Directory\t*.nothing\n" +msgstr "ディレクトリ\t*.nothing\n" -#: ../globals.h:1071 -msgid "E45: 'readonly' option is set (add ! to override)" -msgstr "E45: 'readonly' オプションãŒè¨å®šã•れã¦ã„ã¾ã™ (! ã‚’è¿½åŠ ã§ä¸Šæ›¸ã)" - -#: ../globals.h:1073 #, c-format -msgid "E46: Cannot change read-only variable \"%s\"" -msgstr "E46: èªå–専用変数 \"%s\" ã«ã¯å€¤ã‚’è¨å®šã§ãã¾ã›ã‚“" +msgid "E671: Cannot find window title \"%s\"" +msgstr "E671: タイトル㌠\"%s\" ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../globals.h:1075 #, c-format -msgid "E794: Cannot set variable in the sandbox: \"%s\"" -msgstr "E794: サンドボックスã§ã¯å¤‰æ•° \"%s\" ã«å€¤ã‚’è¨å®šã§ãã¾ã›ã‚“" - -#: ../globals.h:1076 -msgid "E47: Error while reading errorfile" -msgstr "E47: エラーファイルã®èªè¾¼ä¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ" - -#: ../globals.h:1078 -msgid "E48: Not allowed in sandbox" -msgstr "E48: サンドボックスã§ã¯è¨±ã•れã¾ã›ã‚“" - -#: ../globals.h:1080 -msgid "E523: Not allowed here" -msgstr "E523: ã“ã“ã§ã¯è¨±å¯ã•れã¾ã›ã‚“" +msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." +msgstr "E243: 引数ã¯ã‚µãƒãƒ¼ãƒˆã•れã¾ã›ã‚“: \"-%s\"; OLE版を使用ã—ã¦ãã ã•ã„." -#: ../globals.h:1082 -msgid "E359: Screen mode setting not supported" -msgstr "E359: スクリーンモードã®è¨å®šã«ã¯å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“" +msgid "E672: Unable to open window inside MDI application" +msgstr "E672: MDIアプリã®ä¸ã§ã¯ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’é–‹ã‘ã¾ã›ã‚“" -#: ../globals.h:1083 -msgid "E49: Invalid scroll size" -msgstr "E49: 無効ãªã‚¹ã‚¯ãƒãƒ¼ãƒ«é‡ã§ã™" +msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" +msgstr "Vim E458: è‰²æŒ‡å®šãŒæ£ã—ããªã„ã®ã§ã‚¨ãƒ³ãƒˆãƒªã‚’割り当ã¦ã‚‰ã‚Œã¾ã›ã‚“" -#: ../globals.h:1084 -msgid "E91: 'shell' option is empty" -msgstr "E91: 'shell' オプションãŒç©ºã§ã™" +#, c-format +msgid "E250: Fonts for the following charsets are missing in fontset %s:" +msgstr "E250: ä»¥ä¸‹ã®æ–‡å—セットã®ãƒ•ォントãŒã‚りã¾ã›ã‚“ %s:" -#: ../globals.h:1085 -msgid "E255: Couldn't read in sign data!" -msgstr "E255: sign ã®ãƒ‡ãƒ¼ã‚¿ã‚’èªè¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸ" +#, c-format +msgid "E252: Fontset name: %s" +msgstr "E252: フォントセットå: %s" -#: ../globals.h:1086 -msgid "E72: Close error on swap file" -msgstr "E72: スワップファイルã®ã‚¯ãƒãƒ¼ã‚ºæ™‚エラーã§ã™" +#, c-format +msgid "Font '%s' is not fixed-width" +msgstr "フォント '%s' ã¯å›ºå®šå¹…ã§ã¯ã‚りã¾ã›ã‚“" -#: ../globals.h:1087 -msgid "E73: tag stack empty" -msgstr "E73: タグスタックãŒç©ºã§ã™" +#, c-format +msgid "E253: Fontset name: %s" +msgstr "E253: フォントセットå: %s" -#: ../globals.h:1088 -msgid "E74: Command too complex" -msgstr "E74: コマンドãŒè¤‡é›‘éŽãŽã¾ã™" +#, c-format +msgid "Font0: %s" +msgstr "フォント0: %s" -#: ../globals.h:1089 -msgid "E75: Name too long" -msgstr "E75: åå‰ãŒé•·éŽãŽã¾ã™" +#, c-format +msgid "Font1: %s" +msgstr "フォント1: %s" -#: ../globals.h:1090 -msgid "E76: Too many [" -msgstr "E76: [ ãŒå¤šéŽãŽã¾ã™" +#, c-format +msgid "Font%ld width is not twice that of font0" +msgstr "フォント%ld ã®å¹…ãŒãƒ•ォント0ã®2å€ã§ã¯ã‚りã¾ã›ã‚“" -#: ../globals.h:1091 -msgid "E77: Too many file names" -msgstr "E77: ファイルåãŒå¤šéŽãŽã¾ã™" +#, c-format +msgid "Font0 width: %ld" +msgstr "フォント0ã®å¹…: %ld" -#: ../globals.h:1092 -msgid "E488: Trailing characters" -msgstr "E488: ä½™åˆ†ãªæ–‡å—ãŒå¾Œã‚ã«ã‚りã¾ã™" +#, c-format +msgid "Font1 width: %ld" +msgstr "フォント1ã®å¹…: %ld" -#: ../globals.h:1093 -msgid "E78: Unknown mark" -msgstr "E78: 未知ã®ãƒžãƒ¼ã‚¯" +msgid "Invalid font specification" +msgstr "無効ãªãƒ•ォント指定ã§ã™" -#: ../globals.h:1094 -msgid "E79: Cannot expand wildcards" -msgstr "E79: ワイルドカードを展開ã§ãã¾ã›ã‚“" +msgid "&Dismiss" +msgstr "å´ä¸‹ã™ã‚‹(&D)" -#: ../globals.h:1096 -msgid "E591: 'winheight' cannot be smaller than 'winminheight'" -msgstr "E591: 'winheight' 㯠'winminheight' よりå°ã•ãã§ãã¾ã›ã‚“" +msgid "no specific match" +msgstr "マッãƒã™ã‚‹ã‚‚ã®ãŒã‚りã¾ã›ã‚“" -#: ../globals.h:1098 -msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" -msgstr "E592: 'winwidth' 㯠'winminwidth' よりå°ã•ãã§ãã¾ã›ã‚“" +msgid "Vim - Font Selector" +msgstr "Vim - ãƒ•ã‚©ãƒ³ãƒˆé¸æŠž" -#: ../globals.h:1099 -msgid "E80: Error while writing" -msgstr "E80: 書込ã¿ä¸ã®ã‚¨ãƒ©ãƒ¼" +msgid "Name:" +msgstr "åå‰:" -#: ../globals.h:1100 -msgid "Zero count" -msgstr "ゼãƒã‚«ã‚¦ãƒ³ãƒˆ" +#. create toggle button +msgid "Show size in Points" +msgstr "サイズをãƒã‚¤ãƒ³ãƒˆã§è¡¨ç¤ºã™ã‚‹" -#: ../globals.h:1101 -msgid "E81: Using <SID> not in a script context" -msgstr "E81: スクリプト以外ã§<SID>ãŒä½¿ã‚れã¾ã—ãŸ" +msgid "Encoding:" +msgstr "エンコード:" -#: ../globals.h:1102 -#, c-format -msgid "E685: Internal error: %s" -msgstr "E685: 内部エラーã§ã™: %s" +msgid "Font:" +msgstr "フォント:" -#: ../globals.h:1104 -msgid "E363: pattern uses more memory than 'maxmempattern'" -msgstr "E363: パターン㌠'maxmempattern' 以上ã®ãƒ¡ãƒ¢ãƒªã‚’使用ã—ã¾ã™" +msgid "Style:" +msgstr "スタイル:" -#: ../globals.h:1105 -msgid "E749: empty buffer" -msgstr "E749: ãƒãƒƒãƒ•ã‚¡ãŒç©ºã§ã™" +msgid "Size:" +msgstr "サイズ:" -#: ../globals.h:1108 -msgid "E682: Invalid search pattern or delimiter" -msgstr "E682: 検索パターンã‹åŒºåˆ‡ã‚Šè¨˜å·ãŒä¸æ£ã§ã™" +msgid "E256: Hangul automata ERROR" +msgstr "E256: ãƒãƒ³ã‚°ãƒ«ã‚ªãƒ¼ãƒˆãƒžãƒˆãƒ³ã‚¨ãƒ©ãƒ¼" -#: ../globals.h:1109 -msgid "E139: File is loaded in another buffer" -msgstr "E139: åŒã˜åå‰ã®ãƒ•ァイルãŒä»–ã®ãƒãƒƒãƒ•ã‚¡ã§èªè¾¼ã¾ã‚Œã¦ã„ã¾ã™" - -#: ../globals.h:1110 -#, c-format -msgid "E764: Option '%s' is not set" -msgstr "E764: オプション '%s' ã¯è¨å®šã•れã¦ã„ã¾ã›ã‚“" - -#: ../globals.h:1111 -msgid "E850: Invalid register name" -msgstr "E850: 無効ãªãƒ¬ã‚¸ã‚¹ã‚¿åã§ã™" - -#: ../globals.h:1114 -msgid "search hit TOP, continuing at BOTTOM" -msgstr "上ã¾ã§æ¤œç´¢ã—ãŸã®ã§ä¸‹ã«æˆ»ã‚Šã¾ã™" - -#: ../globals.h:1115 -msgid "search hit BOTTOM, continuing at TOP" -msgstr "下ã¾ã§æ¤œç´¢ã—ãŸã®ã§ä¸Šã«æˆ»ã‚Šã¾ã™" - -#: ../hardcopy.c:240 msgid "E550: Missing colon" msgstr "E550: コãƒãƒ³ãŒã‚りã¾ã›ã‚“" -#: ../hardcopy.c:252 msgid "E551: Illegal component" msgstr "E551: 䏿£ãªæ§‹æ–‡è¦ç´ ã§ã™" -#: ../hardcopy.c:259 msgid "E552: digit expected" msgstr "E552: 数値ãŒå¿…è¦ã§ã™" -#: ../hardcopy.c:473 #, c-format msgid "Page %d" msgstr "%d ページ" -#: ../hardcopy.c:597 msgid "No text to be printed" msgstr "å°åˆ·ã™ã‚‹ãƒ†ã‚ストãŒã‚りã¾ã›ã‚“" -#: ../hardcopy.c:668 #, c-format msgid "Printing page %d (%d%%)" msgstr "å°åˆ·ä¸: ページ %d (%d%%)" -#: ../hardcopy.c:680 #, c-format msgid " Copy %d of %d" msgstr " コピー %d (å…¨ %d ä¸)" -#: ../hardcopy.c:733 #, c-format msgid "Printed: %s" msgstr "å°åˆ·ã—ã¾ã—ãŸ: %s" -#: ../hardcopy.c:740 msgid "Printing aborted" msgstr "å°åˆ·ãŒä¸æ¢ã•れã¾ã—ãŸ" -#: ../hardcopy.c:1365 msgid "E455: Error writing to PostScript output file" msgstr "E455: PostScriptå‡ºåŠ›ãƒ•ã‚¡ã‚¤ãƒ«ã®æ›¸è¾¼ã¿ã‚¨ãƒ©ãƒ¼ã§ã™" -#: ../hardcopy.c:1747 #, c-format msgid "E624: Can't open file \"%s\"" msgstr "E624: ファイル \"%s\" ã‚’é–‹ã‘ã¾ã›ã‚“" -#: ../hardcopy.c:1756 ../hardcopy.c:2470 #, c-format msgid "E457: Can't read PostScript resource file \"%s\"" msgstr "E457: PostScriptã®ãƒªã‚½ãƒ¼ã‚¹ãƒ•ァイル \"%s\" ã‚’èªè¾¼ã‚ã¾ã›ã‚“" -#: ../hardcopy.c:1772 #, c-format msgid "E618: file \"%s\" is not a PostScript resource file" msgstr "E618: ファイル \"%s\" 㯠PostScript リソースファイルã§ã¯ã‚りã¾ã›ã‚“" -#: ../hardcopy.c:1788 ../hardcopy.c:1805 ../hardcopy.c:1844 #, c-format msgid "E619: file \"%s\" is not a supported PostScript resource file" msgstr "E619: ファイル \"%s\" ã¯å¯¾å¿œã—ã¦ã„ãªã„ PostScript リソースファイルã§ã™" -#: ../hardcopy.c:1856 #, c-format msgid "E621: \"%s\" resource file has wrong version" msgstr "E621: リソースファイル \"%s\" ã¯ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒç•°ãªã‚Šã¾ã™" -#: ../hardcopy.c:2225 msgid "E673: Incompatible multi-byte encoding and character set." msgstr "E673: äº’æ›æ€§ã®ç„¡ã„マルãƒãƒã‚¤ãƒˆã‚¨ãƒ³ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ã¨æ–‡å—セットã§ã™" -#: ../hardcopy.c:2238 msgid "E674: printmbcharset cannot be empty with multi-byte encoding." msgstr "E674: マルãƒãƒã‚¤ãƒˆã‚¨ãƒ³ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ã§ã¯ printmbcharset を空ã«ã§ãã¾ã›ã‚“" -#: ../hardcopy.c:2254 msgid "E675: No default font specified for multi-byte printing." msgstr "" "E675: マルãƒãƒã‚¤ãƒˆæ–‡å—ã‚’å°åˆ·ã™ã‚‹ãŸã‚ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆãƒ•ã‚©ãƒ³ãƒˆãŒæŒ‡å®šã•れã¦ã„ã¾ã›ã‚“" -#: ../hardcopy.c:2426 msgid "E324: Can't open PostScript output file" msgstr "E324: PostScript出力用ã®ãƒ•ァイルを開ã‘ã¾ã›ã‚“" -#: ../hardcopy.c:2458 #, c-format msgid "E456: Can't open file \"%s\"" msgstr "E456: ファイル \"%s\" ã‚’é–‹ã‘ã¾ã›ã‚“" -#: ../hardcopy.c:2583 msgid "E456: Can't find PostScript resource file \"prolog.ps\"" msgstr "E456: PostScriptã®ãƒªã‚½ãƒ¼ã‚¹ãƒ•ァイル \"prolog.ps\" ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../hardcopy.c:2593 msgid "E456: Can't find PostScript resource file \"cidfont.ps\"" msgstr "E456: PostScriptã®ãƒªã‚½ãƒ¼ã‚¹ãƒ•ァイル \"cidfont.ps\" ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../hardcopy.c:2622 ../hardcopy.c:2639 ../hardcopy.c:2665 #, c-format msgid "E456: Can't find PostScript resource file \"%s.ps\"" msgstr "E456: PostScriptã®ãƒªã‚½ãƒ¼ã‚¹ãƒ•ァイル \"%s.ps\" ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../hardcopy.c:2654 #, c-format msgid "E620: Unable to convert to print encoding \"%s\"" msgstr "E620: å°åˆ·ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ \"%s\" ã¸å¤‰æ›ã§ãã¾ã›ã‚“" -#: ../hardcopy.c:2877 msgid "Sending to printer..." msgstr "プリンタã«é€ä¿¡ä¸..." -#: ../hardcopy.c:2881 msgid "E365: Failed to print PostScript file" msgstr "E365: PostScriptファイルã®å°åˆ·ã«å¤±æ•—ã—ã¾ã—ãŸ" -#: ../hardcopy.c:2883 msgid "Print job sent." msgstr "å°åˆ·ã‚¸ãƒ§ãƒ–ã‚’é€ä¿¡ã—ã¾ã—ãŸ." -#: ../if_cscope.c:85 msgid "Add a new database" msgstr "æ–°ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’è¿½åŠ " -#: ../if_cscope.c:87 msgid "Query for a pattern" msgstr "パターンã®ã‚¯ã‚¨ãƒªãƒ¼ã‚’è¿½åŠ " -#: ../if_cscope.c:89 msgid "Show this message" msgstr "ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã™ã‚‹" -#: ../if_cscope.c:91 msgid "Kill a connection" msgstr "接続を終了ã™ã‚‹" -#: ../if_cscope.c:93 msgid "Reinit all connections" msgstr "å…¨ã¦ã®æŽ¥ç¶šã‚’å†åˆæœŸåŒ–ã™ã‚‹" -#: ../if_cscope.c:95 msgid "Show connections" msgstr "接続を表示ã™ã‚‹" -#: ../if_cscope.c:101 #, c-format msgid "E560: Usage: cs[cope] %s" msgstr "E560: 使用方法: cs[cope] %s" -#: ../if_cscope.c:225 msgid "This cscope command does not support splitting the window.\n" msgstr "ã“ã®cscopeコマンドã¯åˆ†å‰²ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã§ã¯ã‚µãƒãƒ¼ãƒˆã•れã¾ã›ã‚“.\n" -#: ../if_cscope.c:266 msgid "E562: Usage: cstag <ident>" msgstr "E562: 使用法: cstag <ident>" -#: ../if_cscope.c:313 msgid "E257: cstag: tag not found" msgstr "E257: cstag: ã‚¿ã‚°ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../if_cscope.c:461 #, c-format msgid "E563: stat(%s) error: %d" msgstr "E563: stat(%s) エラー: %d" -#: ../if_cscope.c:551 +msgid "E563: stat error" +msgstr "E563: stat エラー" + #, c-format msgid "E564: %s is not a directory or a valid cscope database" msgstr "E564: %s ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªåŠã³æœ‰åйãªcscopeã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã§ã¯ã‚りã¾ã›ã‚“" -#: ../if_cscope.c:566 #, c-format msgid "Added cscope database %s" msgstr "cscopeデータベース %s ã‚’è¿½åŠ " -#: ../if_cscope.c:616 #, c-format -msgid "E262: error reading cscope connection %<PRId64>" -msgstr "E262: cscopeã®æŽ¥ç¶š %<PRId64> ã‚’èªè¾¼ã¿ä¸ã®ã‚¨ãƒ©ãƒ¼ã§ã™" +msgid "E262: error reading cscope connection %ld" +msgstr "E262: cscopeã®æŽ¥ç¶š %ld ã‚’èªè¾¼ã¿ä¸ã®ã‚¨ãƒ©ãƒ¼ã§ã™" -#: ../if_cscope.c:711 msgid "E561: unknown cscope search type" msgstr "E561: 未知ã®cscope検索型ã§ã™" -#: ../if_cscope.c:752 ../if_cscope.c:789 msgid "E566: Could not create cscope pipes" msgstr "E566: cscopeパイプを作æˆã§ãã¾ã›ã‚“ã§ã—ãŸ" -#: ../if_cscope.c:767 msgid "E622: Could not fork for cscope" msgstr "E622: cscopeã®èµ·å‹•準備(fork)ã«å¤±æ•—ã—ã¾ã—ãŸ" -#: ../if_cscope.c:849 msgid "cs_create_connection setpgid failed" msgstr "cs_create_connection ã¸ã® setpgid ã«å¤±æ•—ã—ã¾ã—ãŸ" -#: ../if_cscope.c:853 ../if_cscope.c:889 msgid "cs_create_connection exec failed" msgstr "cs_create_connection ã®å®Ÿè¡Œã«å¤±æ•—ã—ã¾ã—ãŸ" -#: ../if_cscope.c:863 ../if_cscope.c:902 msgid "cs_create_connection: fdopen for to_fp failed" msgstr "cs_create_connection: to_fp ã® fdopen ã«å¤±æ•—ã—ã¾ã—ãŸ" -#: ../if_cscope.c:865 ../if_cscope.c:906 msgid "cs_create_connection: fdopen for fr_fp failed" msgstr "cs_create_connection: fr_fp ã® fdopen ã«å¤±æ•—ã—ã¾ã—ãŸ" -#: ../if_cscope.c:890 msgid "E623: Could not spawn cscope process" msgstr "E623: cscopeプãƒã‚»ã‚¹ã‚’èµ·å‹•ã§ãã¾ã›ã‚“ã§ã—ãŸ" -#: ../if_cscope.c:932 msgid "E567: no cscope connections" msgstr "E567: cscope接続ã«å¤±æ•—ã—ã¾ã—ãŸ" -#: ../if_cscope.c:1009 #, c-format msgid "E469: invalid cscopequickfix flag %c for %c" msgstr "E469: 無効㪠cscopequickfix フラグ %c ã® %c ã§ã™" -#: ../if_cscope.c:1058 #, c-format msgid "E259: no matches found for cscope query %s of %s" msgstr "E259: cscopeクエリー %s of %s ã«è©²å½“ãŒã‚りã¾ã›ã‚“ã§ã—ãŸ" -#: ../if_cscope.c:1142 msgid "cscope commands:\n" msgstr "cscopeコマンド:\n" -#: ../if_cscope.c:1150 #, c-format msgid "%-5s: %s%*s (Usage: %s)" msgstr "%-5s: %s%*s (使用法: %s)" -#: ../if_cscope.c:1155 msgid "" "\n" +" a: Find assignments to this symbol\n" " c: Find functions calling this function\n" " d: Find functions called by this function\n" " e: Find this egrep pattern\n" @@ -3233,6 +2549,7 @@ msgid "" " t: Find this text string\n" msgstr "" "\n" +" a: ã“ã®ã‚·ãƒ³ãƒœãƒ«ã«å¯¾ã™ã‚‹ä»£å…¥ã‚’探ã™\n" " c: ã“ã®é–¢æ•°ã‚’呼んã§ã„る関数を探ã™\n" " d: ã“ã®é–¢æ•°ã‹ã‚‰å‘¼ã‚“ã§ã„る関数を探ã™\n" " e: ã“ã®egrepパターンを探ã™\n" @@ -3242,31 +2559,32 @@ msgstr "" " s: ã“ã®Cシンボルを探ã™\n" " t: ã“ã®ãƒ†ã‚スト文å—列を探ã™\n" -#: ../if_cscope.c:1226 +#, c-format +msgid "E625: cannot open cscope database: %s" +msgstr "E625: cscopeデータベース: %s ã‚’é–‹ãã“ã¨ãŒã§ãã¾ã›ã‚“" + +msgid "E626: cannot get cscope database information" +msgstr "E626: cscopeãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æƒ…å ±ã‚’å–å¾—ã§ãã¾ã›ã‚“" + msgid "E568: duplicate cscope database not added" msgstr "E568: é‡è¤‡ã™ã‚‹cscopeデータベースã¯è¿½åŠ ã•れã¾ã›ã‚“ã§ã—ãŸ" -#: ../if_cscope.c:1335 #, c-format msgid "E261: cscope connection %s not found" msgstr "E261: cscope接続 %s ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ" -#: ../if_cscope.c:1364 #, c-format msgid "cscope connection %s closed" msgstr "cscope接続 %s ãŒé–‰ã˜ã‚‰ã‚Œã¾ã—ãŸ" #. should not reach here -#: ../if_cscope.c:1486 msgid "E570: fatal error in cs_manage_matches" msgstr "E570: cs_manage_matches ã§è‡´å‘½çš„ãªã‚¨ãƒ©ãƒ¼ã§ã™" -#: ../if_cscope.c:1693 #, c-format msgid "Cscope tag: %s" msgstr "Cscope ã‚¿ã‚°: %s" -#: ../if_cscope.c:1711 msgid "" "\n" " # line" @@ -3274,87 +2592,300 @@ msgstr "" "\n" " # 行番å·" -#: ../if_cscope.c:1713 msgid "filename / context / line\n" msgstr "ファイルå / 文脈 / 行\n" -#: ../if_cscope.c:1809 #, c-format msgid "E609: Cscope error: %s" msgstr "E609: cscopeエラー: %s" -#: ../if_cscope.c:2053 msgid "All cscope databases reset" msgstr "å…¨ã¦ã®cscopeデータベースをリセットã—ã¾ã™" -#: ../if_cscope.c:2123 msgid "no cscope connections\n" msgstr "cscope接続ãŒã‚りã¾ã›ã‚“\n" -#: ../if_cscope.c:2126 msgid " # pid database name prepend path\n" msgstr " # pid データベースå prepend パス\n" -#: ../main.c:144 +msgid "Lua library cannot be loaded." +msgstr "Luaライブラリをãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“." + +msgid "cannot save undo information" +msgstr "ã‚¢ãƒ³ãƒ‰ã‚¥æƒ…å ±ãŒä¿å˜ã§ãã¾ã›ã‚“" + +msgid "" +"E815: Sorry, this command is disabled, the MzScheme libraries could not be " +"loaded." +msgstr "E815: ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ç„¡åйã§ã™. MzScheme ライブラリをãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“." + +msgid "" +"E895: Sorry, this command is disabled, the MzScheme's racket/base module " +"could not be loaded." +msgstr "" +"E895: ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ç„¡åйã§ã™,ã”ã‚ã‚“ãªã•ã„. MzScheme ã® racket/base モジュール" +"ãŒãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§ã—ãŸ." + +msgid "invalid expression" +msgstr "無効ãªå¼ã§ã™" + +msgid "expressions disabled at compile time" +msgstr "å¼ã¯ã‚³ãƒ³ãƒ‘イル時ã«ç„¡åйã«ã•れã¦ã„ã¾ã™" + +msgid "hidden option" +msgstr "éš ã—オプション" + +msgid "unknown option" +msgstr "未知ã®ã‚ªãƒ—ションã§ã™" + +msgid "window index is out of range" +msgstr "範囲外ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ç•ªå·ã§ã™" + +msgid "couldn't open buffer" +msgstr "ãƒãƒƒãƒ•ã‚¡ã‚’é–‹ã‘ã¾ã›ã‚“" + +msgid "cannot delete line" +msgstr "行を消ã›ã¾ã›ã‚“" + +msgid "cannot replace line" +msgstr "行を置æ›ã§ãã¾ã›ã‚“" + +msgid "cannot insert line" +msgstr "行を挿入ã§ãã¾ã›ã‚“" + +msgid "string cannot contain newlines" +msgstr "æ–‡å—列ã«ã¯æ”¹è¡Œæ–‡å—ã‚’å«ã‚られã¾ã›ã‚“" + +msgid "error converting Scheme values to Vim" +msgstr "Scheme値ã®Vimã¸ã®å¤‰æ›ã‚¨ãƒ©ãƒ¼" + +msgid "Vim error: ~a" +msgstr "Vim エラー: ~a" + +msgid "Vim error" +msgstr "Vim エラー" + +msgid "buffer is invalid" +msgstr "ãƒãƒƒãƒ•ã‚¡ã¯ç„¡åйã§ã™" + +msgid "window is invalid" +msgstr "ウィンドウã¯ç„¡åйã§ã™" + +msgid "linenr out of range" +msgstr "範囲外ã®è¡Œç•ªå·ã§ã™" + +msgid "not allowed in the Vim sandbox" +msgstr "サンドボックスã§ã¯è¨±ã•れã¾ã›ã‚“" + +msgid "E836: This Vim cannot execute :python after using :py3" +msgstr "E836: ã“ã®Vimã§ã¯ :py3 を使ã£ãŸå¾Œã« :python を使ãˆã¾ã›ã‚“" + +msgid "" +"E263: Sorry, this command is disabled, the Python library could not be " +"loaded." +msgstr "" +"E263: ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ç„¡åйã§ã™,ã”ã‚ã‚“ãªã•ã„: Pythonライブラリをãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“" +"ã§ã—ãŸ." + +msgid "" +"E887: Sorry, this command is disabled, the Python's site module could not be " +"loaded." +msgstr "" +"E887: ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ç„¡åйã§ã™,ã”ã‚ã‚“ãªã•ã„. Python ã® site モジュールをãƒãƒ¼ãƒ‰" +"ã§ãã¾ã›ã‚“ã§ã—ãŸ." + +# Added at 07-Feb-2004. +msgid "E659: Cannot invoke Python recursively" +msgstr "E659: Python ã‚’å†å¸°çš„ã«å®Ÿè¡Œã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“" + +msgid "E837: This Vim cannot execute :py3 after using :python" +msgstr "E837: ã“ã®Vimã§ã¯ :python を使ã£ãŸå¾Œã« :py3 を使ãˆã¾ã›ã‚“" + +msgid "E265: $_ must be an instance of String" +msgstr "E265: $_ ã¯æ–‡å—列ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" + +msgid "" +"E266: Sorry, this command is disabled, the Ruby library could not be loaded." +msgstr "" +"E266: ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ç„¡åйã§ã™,ã”ã‚ã‚“ãªã•ã„: Rubyライブラリをãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§" +"ã—ãŸ." + +msgid "E267: unexpected return" +msgstr "E267: 予期ã›ã¬ return ã§ã™" + +msgid "E268: unexpected next" +msgstr "E268: 予期ã›ã¬ next ã§ã™" + +msgid "E269: unexpected break" +msgstr "E269: 予期ã›ã¬ break ã§ã™" + +msgid "E270: unexpected redo" +msgstr "E270: 予期ã›ã¬ redo ã§ã™" + +msgid "E271: retry outside of rescue clause" +msgstr "E271: rescue ã®å¤–ã® retry ã§ã™" + +msgid "E272: unhandled exception" +msgstr "E272: å–り扱ã‚れãªã‹ã£ãŸä¾‹å¤–ãŒã‚りã¾ã™" + +#, c-format +msgid "E273: unknown longjmp status %d" +msgstr "E273: 未知ã®longjmp状態: %d" + +msgid "invalid buffer number" +msgstr "無効ãªãƒãƒƒãƒ•ァ番å·ã§ã™" + +msgid "not implemented yet" +msgstr "ã¾ã 実装ã•れã¦ã„ã¾ã›ã‚“" + +#. ??? +msgid "cannot set line(s)" +msgstr "行をè¨å®šã§ãã¾ã›ã‚“" + +msgid "invalid mark name" +msgstr "無効ãªãƒžãƒ¼ã‚¯åã§ã™" + +msgid "mark not set" +msgstr "マークã¯è¨å®šã•れã¦ã„ã¾ã›ã‚“" + +#, c-format +msgid "row %d column %d" +msgstr "行 %d 列 %d" + +msgid "cannot insert/append line" +msgstr "è¡Œã®æŒ¿å…¥/è¿½åŠ ã‚’ã§ãã¾ã›ã‚“" + +msgid "line number out of range" +msgstr "範囲外ã®è¡Œç•ªå·ã§ã™" + +msgid "unknown flag: " +msgstr "未知ã®ãƒ•ラグ: " + +msgid "unknown vimOption" +msgstr "未知㮠vimOption ã§ã™" + +msgid "keyboard interrupt" +msgstr "ã‚ーボード割込ã¿" + +msgid "vim error" +msgstr "vim エラー" + +msgid "cannot create buffer/window command: object is being deleted" +msgstr "" +"ãƒãƒƒãƒ•ã‚¡/ウィンドウ作æˆã‚³ãƒžãƒ³ãƒ‰ã‚’作æˆã§ãã¾ã›ã‚“: ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆãŒæ¶ˆåŽ»ã•れã¦ã„ã¾" +"ã—ãŸ" + +msgid "" +"cannot register callback command: buffer/window is already being deleted" +msgstr "" +"コールãƒãƒƒã‚¯ã‚³ãƒžãƒ³ãƒ‰ã‚’登録ã§ãã¾ã›ã‚“: ãƒãƒƒãƒ•ã‚¡/ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãŒæ—¢ã«æ¶ˆåŽ»ã•れã¾ã—ãŸ" + +#. This should never happen. Famous last word? +msgid "" +"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim." +"org" +msgstr "" +"E280: TCL 致命的エラー: reflist 汚染!? vim-dev@vim.org ã«å ±å‘Šã—ã¦ãã ã•ã„" + +msgid "cannot register callback command: buffer/window reference not found" +msgstr "" +"コールãƒãƒƒã‚¯ã‚³ãƒžãƒ³ãƒ‰ã‚’登録ã§ãã¾ã›ã‚“: ãƒãƒƒãƒ•ã‚¡/ウィンドウã®å‚ç…§ãŒè¦‹ã¤ã‹ã‚Šã¾ã›" +"ã‚“" + +msgid "" +"E571: Sorry, this command is disabled: the Tcl library could not be loaded." +msgstr "" +"E571: ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ç„¡åйã§ã™,ã”ã‚ã‚“ãªã•ã„: Tclライブラリをãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§" +"ã—ãŸ." + +#, c-format +msgid "E572: exit code %d" +msgstr "E572: 終了コード %d" + +msgid "cannot get line" +msgstr "行をå–å¾—ã§ãã¾ã›ã‚“" + +msgid "Unable to register a command server name" +msgstr "命令サーãƒãƒ¼ã®åå‰ã‚’登録ã§ãã¾ã›ã‚“" + +msgid "E248: Failed to send command to the destination program" +msgstr "E248: 目的ã®ãƒ—ãƒã‚°ãƒ©ãƒ ã¸ã®ã‚³ãƒžãƒ³ãƒ‰é€ä¿¡ã«å¤±æ•—ã—ã¾ã—ãŸ" + +#, c-format +msgid "E573: Invalid server id used: %s" +msgstr "E573: 無効ãªã‚µãƒ¼ãƒãƒ¼IDãŒä½¿ã‚れã¾ã—ãŸ: %s" + +msgid "E251: VIM instance registry property is badly formed. Deleted!" +msgstr "E251: VIM 実体ã®ç™»éŒ²ãƒ—ãƒãƒ‘ティãŒä¸æ£ã§ã™. 消去ã—ã¾ã—ãŸ!" + +#, c-format +msgid "E696: Missing comma in List: %s" +msgstr "E696: リスト型ã«ã‚«ãƒ³ãƒžãŒã‚りã¾ã›ã‚“: %s" + +#, c-format +msgid "E697: Missing end of List ']': %s" +msgstr "E697: ãƒªã‚¹ãƒˆåž‹ã®æœ€å¾Œã« ']' ãŒã‚りã¾ã›ã‚“: %s" + msgid "Unknown option argument" msgstr "未知ã®ã‚ªãƒ—ション引数ã§ã™" -#: ../main.c:146 msgid "Too many edit arguments" msgstr "編集引数ãŒå¤šéŽãŽã¾ã™" -#: ../main.c:148 msgid "Argument missing after" msgstr "引数ãŒã‚りã¾ã›ã‚“" -#: ../main.c:150 msgid "Garbage after option argument" msgstr "オプション引数ã®å¾Œã«ã‚´ãƒŸãŒã‚りã¾ã™" -#: ../main.c:152 msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments" msgstr "\"+command\", \"-c command\", \"--cmd command\" ã®å¼•æ•°ãŒå¤šéŽãŽã¾ã™" -#: ../main.c:154 msgid "Invalid argument for" msgstr "無効ãªå¼•æ•°ã§ã™: " -#: ../main.c:294 #, c-format msgid "%d files to edit\n" msgstr "%d 個ã®ãƒ•ァイルãŒç·¨é›†ã‚’控ãˆã¦ã„ã¾ã™\n" -#: ../main.c:1342 +msgid "netbeans is not supported with this GUI\n" +msgstr "netbeans ã¯ã“ã®GUIã§ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“\n" + +msgid "'-nb' cannot be used: not enabled at compile time\n" +msgstr "'-nb' 使用ä¸å¯èƒ½ã§ã™: コンパイル時ã«ç„¡åйã«ã•れã¦ã„ã¾ã™\n" + +msgid "This Vim was not compiled with the diff feature." +msgstr "ã“ã®Vimã«ã¯diff機能ãŒã‚りã¾ã›ã‚“(コンパイル時è¨å®š)." + msgid "Attempt to open script file again: \"" msgstr "スクリプトファイルをå†ã³é–‹ã„ã¦ã¿ã¾ã™: \"" -#: ../main.c:1350 msgid "Cannot open for reading: \"" msgstr "èªè¾¼ç”¨ã¨ã—ã¦é–‹ã‘ã¾ã›ã‚“" -#: ../main.c:1393 msgid "Cannot open for script output: \"" msgstr "スクリプト出力用を開ã‘ã¾ã›ã‚“" -#: ../main.c:1622 +msgid "Vim: Error: Failure to start gvim from NetBeans\n" +msgstr "Vim: エラー: NetBeansã‹ã‚‰gvimをスタートã§ãã¾ã›ã‚“\n" + +msgid "Vim: Error: This version of Vim does not run in a Cygwin terminal\n" +msgstr "Vim: エラー: ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®Vimã¯Cygwin端末ã§ã¯å‹•作ã—ã¾ã›ã‚“\n" + msgid "Vim: Warning: Output is not to a terminal\n" msgstr "Vim: è¦å‘Š: 端末ã¸ã®å‡ºåŠ›ã§ã¯ã‚りã¾ã›ã‚“\n" -#: ../main.c:1624 msgid "Vim: Warning: Input is not from a terminal\n" msgstr "Vim: è¦å‘Š: 端末ã‹ã‚‰ã®å…¥åŠ›ã§ã¯ã‚りã¾ã›ã‚“\n" #. just in case.. -#: ../main.c:1891 msgid "pre-vimrc command line" msgstr "vimrcå‰ã®ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³" -#: ../main.c:1964 #, c-format msgid "E282: Cannot read from \"%s\"" msgstr "E282: \"%s\"ã‹ã‚‰èªè¾¼ã‚€ã“ã¨ãŒã§ãã¾ã›ã‚“" -#: ../main.c:2149 msgid "" "\n" "More info with: \"vim -h\"\n" @@ -3362,23 +2893,18 @@ msgstr "" "\n" "ã‚ˆã‚Šè©³ç´°ãªæƒ…å ±ã¯: \"vim -h\"\n" -#: ../main.c:2178 msgid "[file ..] edit specified file(s)" msgstr "[ファイル..] ã‚るファイルを編集ã™ã‚‹" -#: ../main.c:2179 msgid "- read text from stdin" msgstr "- 標準入力ã‹ã‚‰ãƒ†ã‚ストをèªè¾¼ã‚€" -#: ../main.c:2180 msgid "-t tag edit file where tag is defined" msgstr "-t ã‚¿ã‚° ã‚¿ã‚°ãŒå®šç¾©ã•れãŸã¨ã“ã‚ã‹ã‚‰ç·¨é›†ã™ã‚‹" -#: ../main.c:2181 msgid "-q [errorfile] edit file with first error" msgstr "-q [errorfile] 最åˆã®ã‚¨ãƒ©ãƒ¼ã§ç·¨é›†ã™ã‚‹" -#: ../main.c:2187 msgid "" "\n" "\n" @@ -3388,11 +2914,9 @@ msgstr "" "\n" "使用法:" -#: ../main.c:2189 msgid " vim [arguments] " msgstr " vim [引数] " -#: ../main.c:2193 msgid "" "\n" " or:" @@ -3400,7 +2924,13 @@ msgstr "" "\n" " ã‚‚ã—ãã¯:" -#: ../main.c:2196 +msgid "" +"\n" +"Where case is ignored prepend / to make flag upper case" +msgstr "" +"\n" +"大尿–‡å—ãŒç„¡è¦–ã•ã‚Œã‚‹å ´åˆã¯å¤§æ–‡å—ã«ã™ã‚‹ãŸã‚ã« / ã‚’å‰ç½®ã—ã¦ãã ã•ã„" + msgid "" "\n" "\n" @@ -3410,189 +2940,319 @@ msgstr "" "\n" "引数:\n" -#: ../main.c:2197 msgid "--\t\t\tOnly file names after this" msgstr "--\t\t\tã“ã®ã‚ã¨ã«ã¯ãƒ•ァイルåã ã‘" -#: ../main.c:2199 msgid "--literal\t\tDon't expand wildcards" msgstr "--literal\t\tワイルドカードを展開ã—ãªã„" -#: ../main.c:2201 +msgid "-register\t\tRegister this gvim for OLE" +msgstr "-register\t\tã“ã®gvimã‚’OLEã¨ã—ã¦ç™»éŒ²ã™ã‚‹" + +msgid "-unregister\t\tUnregister gvim for OLE" +msgstr "-unregister\t\tgvimã®OLE登録を解除ã™ã‚‹" + +msgid "-g\t\t\tRun using GUI (like \"gvim\")" +msgstr "-g\t\t\tGUIã§èµ·å‹•ã™ã‚‹ (\"gvim\" ã¨åŒã˜)" + +msgid "-f or --nofork\tForeground: Don't fork when starting GUI" +msgstr "-f or --nofork\tフォアグラウンド: GUIã‚’å§‹ã‚ã‚‹ã¨ãã«forkã—ãªã„" + msgid "-v\t\t\tVi mode (like \"vi\")" msgstr "-v\t\t\tViモード (\"vi\" ã¨åŒã˜)" -#: ../main.c:2202 msgid "-e\t\t\tEx mode (like \"ex\")" msgstr "-e\t\t\tExモード (\"ex\" ã¨åŒã˜)" -#: ../main.c:2203 msgid "-E\t\t\tImproved Ex mode" msgstr "-E\t\t\t改良Exモード" -#: ../main.c:2204 msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")" msgstr "-s\t\t\tサイレント(ãƒãƒƒãƒ)モード (\"ex\" 専用)" -#: ../main.c:2205 msgid "-d\t\t\tDiff mode (like \"vimdiff\")" msgstr "-d\t\t\t差分モード (\"vidiff\" ã¨åŒã˜)" -#: ../main.c:2206 msgid "-y\t\t\tEasy mode (like \"evim\", modeless)" msgstr "-y\t\t\tイージーモード (\"evim\" ã¨åŒã˜, モード無)" -#: ../main.c:2207 msgid "-R\t\t\tReadonly mode (like \"view\")" msgstr "-R\t\t\tèªè¾¼å°‚用モード (\"view\" ã¨åŒã˜)" -#: ../main.c:2208 msgid "-Z\t\t\tRestricted mode (like \"rvim\")" msgstr "-Z\t\t\t制é™ãƒ¢ãƒ¼ãƒ‰ (\"rvim\" ã¨åŒã˜)" -#: ../main.c:2209 msgid "-m\t\t\tModifications (writing files) not allowed" msgstr "-m\t\t\t変更 (ファイルä¿å˜æ™‚) ã‚’ã§ããªã„よã†ã«ã™ã‚‹" -#: ../main.c:2210 msgid "-M\t\t\tModifications in text not allowed" msgstr "-M\t\t\tテã‚ストã®ç·¨é›†ã‚’行ãªãˆãªã„よã†ã«ã™ã‚‹" -#: ../main.c:2211 msgid "-b\t\t\tBinary mode" msgstr "-b\t\t\tãƒã‚¤ãƒŠãƒªãƒ¢ãƒ¼ãƒ‰" -#: ../main.c:2212 msgid "-l\t\t\tLisp mode" msgstr "-l\t\t\tLispモード" -#: ../main.c:2213 msgid "-C\t\t\tCompatible with Vi: 'compatible'" msgstr "-C\t\t\tVi互æ›ãƒ¢ãƒ¼ãƒ‰: 'compatible'" -#: ../main.c:2214 msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'" msgstr "-N\t\t\tViéžäº’æ›ãƒ¢ãƒ¼ãƒ‰: 'nocompatible" -#: ../main.c:2215 msgid "-V[N][fname]\t\tBe verbose [level N] [log messages to fname]" msgstr "-V[N][fname]\t\tãƒã‚°å‡ºåŠ›è¨å®š [レベル N] [ãƒã‚°ãƒ•ァイルå fname]" -#: ../main.c:2216 msgid "-D\t\t\tDebugging mode" msgstr "-D\t\t\tデãƒãƒƒã‚°ãƒ¢ãƒ¼ãƒ‰" -#: ../main.c:2217 msgid "-n\t\t\tNo swap file, use memory only" msgstr "-n\t\t\tスワップファイルを使用ã›ãšãƒ¡ãƒ¢ãƒªã ã‘" -#: ../main.c:2218 msgid "-r\t\t\tList swap files and exit" msgstr "-r\t\t\tスワップファイルを列挙ã—終了" -#: ../main.c:2219 msgid "-r (with file name)\tRecover crashed session" msgstr "-r (ファイルå)\tクラッシュã—ãŸã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’復帰" -#: ../main.c:2220 msgid "-L\t\t\tSame as -r" msgstr "-L\t\t\t-rã¨åŒã˜" -#: ../main.c:2221 +msgid "-f\t\t\tDon't use newcli to open window" +msgstr "-f\t\t\tウィンドウを開ãã®ã« newcli を使用ã—ãªã„" + +msgid "-dev <device>\t\tUse <device> for I/O" +msgstr "-dev <device>\t\tI/Oã« <device> を使用ã™ã‚‹" + msgid "-A\t\t\tstart in Arabic mode" msgstr "-A\t\t\tアラビア語モードã§èµ·å‹•ã™ã‚‹" -#: ../main.c:2222 msgid "-H\t\t\tStart in Hebrew mode" msgstr "-H\t\t\tヘブライ語モードã§èµ·å‹•ã™ã‚‹" -#: ../main.c:2223 msgid "-F\t\t\tStart in Farsi mode" msgstr "-F\t\t\tペルシア語モードã§èµ·å‹•ã™ã‚‹" -#: ../main.c:2224 msgid "-T <terminal>\tSet terminal type to <terminal>" msgstr "-T <terminal>\t端末を <terminal> ã«è¨å®šã™ã‚‹" -#: ../main.c:2225 +msgid "--not-a-term\t\tSkip warning for input/output not being a terminal" +msgstr "--not-a-term\t\t入出力ãŒç«¯æœ«ã§ãªã„ã¨ã®è¦å‘Šã‚’スã‚ップã™ã‚‹" + msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc" msgstr "-u <vimrc>\t\t.vimrcã®ä»£ã‚り㫠<vimrc> を使ã†" -#: ../main.c:2226 +msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" +msgstr "-U <gvimrc>\t\t.gvimrcã®ä»£ã‚り㫠<gvimrc> を使ã†" + msgid "--noplugin\t\tDon't load plugin scripts" msgstr "--noplugin\t\tプラグインスクリプトをãƒãƒ¼ãƒ‰ã—ãªã„" -#: ../main.c:2227 msgid "-p[N]\t\tOpen N tab pages (default: one for each file)" msgstr "-p[N]\t\tN 個タブページを開ã(çœç•¥å€¤: ファイルã«ã¤ã1個)" -#: ../main.c:2228 msgid "-o[N]\t\tOpen N windows (default: one for each file)" msgstr "-o[N]\t\tN 個ウィンドウを開ã(çœç•¥å€¤: ファイルã«ã¤ã1個)" -#: ../main.c:2229 msgid "-O[N]\t\tLike -o but split vertically" msgstr "-O[N]\t\t-oã¨åŒã˜ã ãŒåž‚直分割" -#: ../main.c:2230 msgid "+\t\t\tStart at end of file" msgstr "+\t\t\tãƒ•ã‚¡ã‚¤ãƒ«ã®æœ€å¾Œã‹ã‚‰ã¯ã˜ã‚ã‚‹" -#: ../main.c:2231 msgid "+<lnum>\t\tStart at line <lnum>" msgstr "+<lnum>\t\t<lnum> 行ã‹ã‚‰ã¯ã˜ã‚ã‚‹" -#: ../main.c:2232 msgid "--cmd <command>\tExecute <command> before loading any vimrc file" msgstr "--cmd <command>\tvimrcã‚’ãƒãƒ¼ãƒ‰ã™ã‚‹å‰ã« <command> を実行ã™ã‚‹" -#: ../main.c:2233 msgid "-c <command>\t\tExecute <command> after loading the first file" msgstr "-c <command>\t\t最åˆã®ãƒ•ァイルをãƒãƒ¼ãƒ‰å¾Œ <command> を実行ã™ã‚‹" -#: ../main.c:2235 msgid "-S <session>\t\tSource file <session> after loading the first file" msgstr "-S <session>\t\t最åˆã®ãƒ•ァイルをãƒãƒ¼ãƒ‰å¾Œãƒ•ァイル <session> ã‚’å–込む" -#: ../main.c:2236 msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>" msgstr "-s <scriptin>\tファイル <scriptin> ã‹ã‚‰ãƒŽãƒ¼ãƒžãƒ«ã‚³ãƒžãƒ³ãƒ‰ã‚’èªè¾¼ã‚€" -#: ../main.c:2237 msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>" msgstr "-w <scriptout>\t入力ã—ãŸå…¨ã‚³ãƒžãƒ³ãƒ‰ã‚’ファイル <scriptout> ã«è¿½åŠ ã™ã‚‹" -#: ../main.c:2238 msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>" msgstr "-W <scriptout>\t入力ã—ãŸå…¨ã‚³ãƒžãƒ³ãƒ‰ã‚’ファイル <scriptout> ã«ä¿å˜ã™ã‚‹" -#: ../main.c:2240 +msgid "-x\t\t\tEdit encrypted files" +msgstr "-x\t\t\tæš—å·åŒ–ã•れãŸãƒ•ァイルを編集ã™ã‚‹" + +msgid "-display <display>\tConnect vim to this particular X-server" +msgstr "-display <display>\tvimを指定ã—㟠X サーãƒãƒ¼ã«æŽ¥ç¶šã™ã‚‹" + +msgid "-X\t\t\tDo not connect to X server" +msgstr "-X\t\t\tXサーãƒãƒ¼ã«æŽ¥ç¶šã—ãªã„" + +msgid "--remote <files>\tEdit <files> in a Vim server if possible" +msgstr "--remote <files>\tå¯èƒ½ãªã‚‰ã°Vimサーãƒãƒ¼ã§ <files> を編集ã™ã‚‹" + +msgid "--remote-silent <files> Same, don't complain if there is no server" +msgstr "--remote-silent <files> åŒä¸Š, サーãƒãƒ¼ãŒç„¡ãã¦ã‚‚è¦å‘Šæ–‡ã‚’出力ã—ãªã„" + +msgid "" +"--remote-wait <files> As --remote but wait for files to have been edited" +msgstr "--remote-wait <files>\t--remote後 ファイルã®ç·¨é›†ãŒçµ‚ã‚ã‚‹ã®ã‚’å¾…ã¤" + +msgid "" +"--remote-wait-silent <files> Same, don't complain if there is no server" +msgstr "" +"--remote-wait-silent <files> åŒä¸Š, サーãƒãƒ¼ãŒç„¡ãã¦ã‚‚è¦å‘Šæ–‡ã‚’出力ã—ãªã„" + +msgid "" +"--remote-tab[-wait][-silent] <files> As --remote but use tab page per file" +msgstr "" +"--remote-tab[-wait][-silent] <files> --remoteã§ãƒ•ァイル1ã¤ã«ã¤ã1ã¤ã®ã‚¿ãƒ–" +"ページを開ã" + +msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" +msgstr "--remote-send <keys>\tVimサーãƒãƒ¼ã« <keys> ã‚’é€ä¿¡ã—ã¦çµ‚了ã™ã‚‹" + +msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" +msgstr "--remote-expr <expr>\tサーãƒãƒ¼ã§ <expr> を実行ã—ã¦çµæžœã‚’表示ã™ã‚‹" + +msgid "--serverlist\t\tList available Vim server names and exit" +msgstr "--serverlist\t\tVimサーãƒãƒ¼åã®ä¸€è¦§ã‚’表示ã—ã¦çµ‚了ã™ã‚‹" + +msgid "--servername <name>\tSend to/become the Vim server <name>" +msgstr "--servername <name>\tVimサーãƒãƒ¼ <name> ã«é€ä¿¡/åå‰è¨å®šã™ã‚‹" + msgid "--startuptime <file>\tWrite startup timing messages to <file>" msgstr "--startuptime <file>\tèµ·å‹•ã«ã‹ã‹ã£ãŸæ™‚é–“ã®è©³ç´°ã‚’ <file> ã¸å‡ºåŠ›ã™ã‚‹" -#: ../main.c:2242 msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo" msgstr "-i <viminfo>\t\t.viminfoã®ä»£ã‚り㫠<viminfo> を使ã†" -#: ../main.c:2243 msgid "-h or --help\tPrint Help (this message) and exit" msgstr "-h or --help\tヘルプ(ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸)を表示ã—終了ã™ã‚‹" -#: ../main.c:2244 msgid "--version\t\tPrint version information and exit" msgstr "--version\t\tãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã‚’è¡¨ç¤ºã—終了ã™ã‚‹" -#: ../mark.c:676 +msgid "" +"\n" +"Arguments recognised by gvim (Motif version):\n" +msgstr "" +"\n" +"gvimã«ã‚ˆã£ã¦è§£é‡ˆã•れる引数(Motifãƒãƒ¼ã‚¸ãƒ§ãƒ³):\n" + +msgid "" +"\n" +"Arguments recognised by gvim (neXtaw version):\n" +msgstr "" +"\n" +"gvimã«ã‚ˆã£ã¦è§£é‡ˆã•れる引数(neXtawãƒãƒ¼ã‚¸ãƒ§ãƒ³):\n" + +msgid "" +"\n" +"Arguments recognised by gvim (Athena version):\n" +msgstr "" +"\n" +"gvimã«ã‚ˆã£ã¦è§£é‡ˆã•れる引数(Athenaãƒãƒ¼ã‚¸ãƒ§ãƒ³):\n" + +msgid "-display <display>\tRun vim on <display>" +msgstr "-display <display>\t<display> ã§vimを実行ã™ã‚‹" + +msgid "-iconic\t\tStart vim iconified" +msgstr "-iconic\t\t最å°åŒ–ã—ãŸçŠ¶æ…‹ã§vimã‚’èµ·å‹•ã™ã‚‹" + +msgid "-background <color>\tUse <color> for the background (also: -bg)" +msgstr "-background <color>\t背景色㫠<color> を使ã†(åŒç¾©: -bg)" + +msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" +msgstr "-foreground <color>\t剿™¯è‰²ã« <color> を使ã†(åŒç¾©: -fg)" + +msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" +msgstr "-font <font>\t\tテã‚スト表示㫠<font> を使ã†(åŒç¾©: -fn)" + +msgid "-boldfont <font>\tUse <font> for bold text" +msgstr "-boldfont <font>\t太å—ã« <font> を使ã†" + +msgid "-italicfont <font>\tUse <font> for italic text" +msgstr "-italicfont <for>\t斜体å—ã« <font> を使ã†" + +msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" +msgstr "-geometry <geom>\tåˆæœŸé…置㫠<geom> を使ã†(åŒç¾©: -geom)" + +msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" +msgstr "-borderwidth <width>\t境界ã®å¹…ã‚’ <width> ã«ã™ã‚‹(åŒç¾©: -bw)" + +msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" +msgstr "" +"-scrollbarwidth <width> スクãƒãƒ¼ãƒ«ãƒãƒ¼ã®å¹…ã‚’ <width> ã«ã™ã‚‹(åŒç¾©: -sw)" + +msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" +msgstr "-menuheight <height>\tメニューãƒãƒ¼ã®é«˜ã•ã‚’ <height> ã«ã™ã‚‹(åŒç¾©: -mh)" + +msgid "-reverse\t\tUse reverse video (also: -rv)" +msgstr "-reverse\t\tåè»¢æ˜ åƒã‚’使用ã™ã‚‹(åŒç¾©: -rv)" + +msgid "+reverse\t\tDon't use reverse video (also: +rv)" +msgstr "+reverse\t\tåè»¢æ˜ åƒã‚’使用ã—ãªã„(åŒç¾©: +rv)" + +msgid "-xrm <resource>\tSet the specified resource" +msgstr "-xrm <resource>\t特定ã®ãƒªã‚½ãƒ¼ã‚¹ã‚’使用ã™ã‚‹" + +msgid "" +"\n" +"Arguments recognised by gvim (GTK+ version):\n" +msgstr "" +"\n" +"gvimã«ã‚ˆã£ã¦è§£é‡ˆã•れる引数(GTK+ãƒãƒ¼ã‚¸ãƒ§ãƒ³):\n" + +msgid "-display <display>\tRun vim on <display> (also: --display)" +msgstr "-display <display>\t<display> ã§vimを実行ã™ã‚‹(åŒç¾©: --display)" + +msgid "--role <role>\tSet a unique role to identify the main window" +msgstr "--role <role>\tメインウィンドウをè˜åˆ¥ã™ã‚‹ä¸€æ„ãªå½¹å‰²(role)ã‚’è¨å®šã™ã‚‹" + +msgid "--socketid <xid>\tOpen Vim inside another GTK widget" +msgstr "--socketid <xid>\tç•°ãªã‚‹GTK widgetã§Vimã‚’é–‹ã" + +msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" +msgstr "--echo-wid\t\tウィンドウIDを標準出力ã«å‡ºåŠ›ã™ã‚‹" + +msgid "-P <parent title>\tOpen Vim inside parent application" +msgstr "-P <親ã®ã‚¿ã‚¤ãƒˆãƒ«>\tVimを親アプリケーションã®ä¸ã§èµ·å‹•ã™ã‚‹" + +msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" +msgstr "--windowid <HWND>\tç•°ãªã‚‹Win32 widgetã®å†…部ã«Vimã‚’é–‹ã" + +msgid "No display" +msgstr "ディスプレイãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + +#. Failed to send, abort. +msgid ": Send failed.\n" +msgstr ": é€ä¿¡ã«å¤±æ•—ã—ã¾ã—ãŸ.\n" + +#. Let vim start normally. +msgid ": Send failed. Trying to execute locally\n" +msgstr ": é€ä¿¡ã«å¤±æ•—ã—ã¾ã—ãŸ. ãƒãƒ¼ã‚«ãƒ«ã§ã®å®Ÿè¡Œã‚’試ã¿ã¦ã„ã¾ã™\n" + +#, c-format +msgid "%d of %d edited" +msgstr "%d 個 (%d 個ä¸) ã®ãƒ•ァイルを編集ã—ã¾ã—ãŸ" + +msgid "No display: Send expression failed.\n" +msgstr "ディスプレイãŒã‚りã¾ã›ã‚“: å¼ã®é€ä¿¡ã«å¤±æ•—ã—ã¾ã—ãŸ.\n" + +msgid ": Send expression failed.\n" +msgstr ": å¼ã®é€ä¿¡ã«å¤±æ•—ã—ã¾ã—ãŸ.\n" + msgid "No marks set" msgstr "マークãŒè¨å®šã•れã¦ã„ã¾ã›ã‚“" -#: ../mark.c:678 #, c-format msgid "E283: No marks matching \"%s\"" msgstr "E283: \"%s\" ã«è©²å½“ã™ã‚‹ãƒžãƒ¼ã‚¯ãŒã‚りã¾ã›ã‚“" #. Highlight title -#: ../mark.c:687 msgid "" "\n" "mark line col file/text" @@ -3601,7 +3261,6 @@ msgstr "" "mark 行 列 ファイル/テã‚スト" #. Highlight title -#: ../mark.c:789 msgid "" "\n" " jump line col file/text" @@ -3610,7 +3269,6 @@ msgstr "" " jump 行 列 ファイル/テã‚スト" #. Highlight title -#: ../mark.c:831 msgid "" "\n" "change line col text" @@ -3618,7 +3276,6 @@ msgstr "" "\n" "変更 行 列 テã‚スト" -#: ../mark.c:1238 msgid "" "\n" "# File marks:\n" @@ -3627,7 +3284,6 @@ msgstr "" "# ファイルマーク:\n" #. Write the jumplist with -' -#: ../mark.c:1271 msgid "" "\n" "# Jumplist (newest first):\n" @@ -3635,7 +3291,6 @@ msgstr "" "\n" "# ジャンプリスト (æ–°ã—ã„ã‚‚ã®ãŒå…ˆ):\n" -#: ../mark.c:1352 msgid "" "\n" "# History of marks within files (newest to oldest):\n" @@ -3643,84 +3298,88 @@ msgstr "" "\n" "# ファイル内マークã®å±¥æ´ (æ–°ã—ã„ã‚‚ã®ã‹ã‚‰å¤ã„ã‚‚ã®):\n" -#: ../mark.c:1431 msgid "Missing '>'" msgstr "'>' ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../memfile.c:426 +msgid "E543: Not a valid codepage" +msgstr "E543: 無効ãªã‚³ãƒ¼ãƒ‰ãƒšãƒ¼ã‚¸ã§ã™" + +msgid "E284: Cannot set IC values" +msgstr "E284: ICã®å€¤ã‚’è¨å®šã§ãã¾ã›ã‚“" + +msgid "E285: Failed to create input context" +msgstr "E285: インプットコンテã‚ストã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸ" + +msgid "E286: Failed to open input method" +msgstr "E286: インプットメソッドã®ã‚ªãƒ¼ãƒ—ンã«å¤±æ•—ã—ã¾ã—ãŸ" + +msgid "E287: Warning: Could not set destroy callback to IM" +msgstr "E287: è¦å‘Š: IMã®ç ´å£Šã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯ã‚’è¨å®šã§ãã¾ã›ã‚“ã§ã—ãŸ" + +msgid "E288: input method doesn't support any style" +msgstr "E288: インプットメソッドã¯ã©ã‚“ãªã‚¹ã‚¿ã‚¤ãƒ«ã‚‚サãƒãƒ¼ãƒˆã—ã¾ã›ã‚“" + +msgid "E289: input method doesn't support my preedit type" +msgstr "E289: インプットメソッド㯠my preedit type をサãƒãƒ¼ãƒˆã—ã¾ã›ã‚“" + msgid "E293: block was not locked" msgstr "E293: ブãƒãƒƒã‚¯ãŒãƒãƒƒã‚¯ã•れã¦ã„ã¾ã›ã‚“" -#: ../memfile.c:799 msgid "E294: Seek error in swap file read" msgstr "E294: スワップファイルèªè¾¼æ™‚ã«ã‚·ãƒ¼ã‚¯ã‚¨ãƒ©ãƒ¼ã§ã™" -#: ../memfile.c:803 msgid "E295: Read error in swap file" msgstr "E295: スワップファイルã®èªè¾¼ã¿ã‚¨ãƒ©ãƒ¼ã§ã™" -#: ../memfile.c:849 msgid "E296: Seek error in swap file write" msgstr "E296: ã‚¹ãƒ¯ãƒƒãƒ—ãƒ•ã‚¡ã‚¤ãƒ«æ›¸è¾¼ã¿æ™‚ã«ã‚·ãƒ¼ã‚¯ã‚¨ãƒ©ãƒ¼ã§ã™" -#: ../memfile.c:865 msgid "E297: Write error in swap file" msgstr "E297: ã‚¹ãƒ¯ãƒƒãƒ—ãƒ•ã‚¡ã‚¤ãƒ«ã®æ›¸è¾¼ã¿ã‚¨ãƒ©ãƒ¼ã§ã™" -#: ../memfile.c:1036 msgid "E300: Swap file already exists (symlink attack?)" msgstr "E300: ã‚¹ãƒ¯ãƒƒãƒ—ãƒ•ã‚¡ã‚¤ãƒ«ãŒæ—¢ã«å˜åœ¨ã—ã¾ã™ (symlinkã«ã‚ˆã‚‹æ”»æ’ƒ?)" -#: ../memline.c:318 msgid "E298: Didn't get block nr 0?" msgstr "E298: ブãƒãƒƒã‚¯ 0 ã‚’å–å¾—ã§ãã¾ã›ã‚“?" -#: ../memline.c:361 msgid "E298: Didn't get block nr 1?" msgstr "E298: ブãƒãƒƒã‚¯ 1 ã‚’å–å¾—ã§ãã¾ã›ã‚“?" -#: ../memline.c:377 msgid "E298: Didn't get block nr 2?" msgstr "E298: ブãƒãƒƒã‚¯ 2 ã‚’å–å¾—ã§ãã¾ã›ã‚“?" +msgid "E843: Error while updating swap file crypt" +msgstr "E843: ã‚¹ãƒ¯ãƒƒãƒ—ãƒ•ã‚¡ã‚¤ãƒ«ã®æš—å·ã‚’æ›´æ–°ä¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ" + #. could not (re)open the swap file, what can we do???? -#: ../memline.c:465 msgid "E301: Oops, lost the swap file!!!" msgstr "E301: ãŠã£ã¨, スワップファイルãŒå¤±ã‚れã¾ã—ãŸ!!!" -#: ../memline.c:477 msgid "E302: Could not rename swap file" msgstr "E302: スワップファイルã®åå‰ã‚’変ãˆã‚‰ã‚Œã¾ã›ã‚“" -#: ../memline.c:554 #, c-format msgid "E303: Unable to open swap file for \"%s\", recovery impossible" msgstr "E303: \"%s\" ã®ã‚¹ãƒ¯ãƒƒãƒ—ファイルを開ã‘ãªã„ã®ã§ãƒªã‚«ãƒãƒªã¯ä¸å¯èƒ½ã§ã™" -#: ../memline.c:666 msgid "E304: ml_upd_block0(): Didn't get block 0??" msgstr "E304: ml_upd_block0(): ブãƒãƒƒã‚¯ 0 ã‚’å–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸ??" -#. no swap files found -#: ../memline.c:830 #, c-format msgid "E305: No swap file found for %s" msgstr "E305: %s ã«ã¯ã‚¹ãƒ¯ãƒƒãƒ—ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../memline.c:839 msgid "Enter number of swap file to use (0 to quit): " msgstr "使用ã™ã‚‹ã‚¹ãƒ¯ãƒƒãƒ—ファイルã®ç•ªå·ã‚’入力ã—ã¦ãã ã•ã„(0 ã§çµ‚了): " -#: ../memline.c:879 #, c-format msgid "E306: Cannot open %s" msgstr "E306: %s ã‚’é–‹ã‘ã¾ã›ã‚“" -#: ../memline.c:897 msgid "Unable to read block 0 from " msgstr "ブãƒãƒƒã‚¯ 0 ã‚’èªè¾¼ã‚ã¾ã›ã‚“ " -#: ../memline.c:900 msgid "" "\n" "Maybe no changes were made or Vim did not update the swap file." @@ -3728,28 +3387,22 @@ msgstr "" "\n" "æã‚‰ã変更ãŒã•れã¦ã„ãªã„ã‹VimãŒã‚¹ãƒ¯ãƒƒãƒ—ファイルを更新ã—ã¦ã„ã¾ã›ã‚“." -#: ../memline.c:909 msgid " cannot be used with this version of Vim.\n" msgstr " Vimã®ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“.\n" -#: ../memline.c:911 msgid "Use Vim version 3.0.\n" msgstr "Vimã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³3.0を使用ã—ã¦ãã ã•ã„.\n" -#: ../memline.c:916 #, c-format msgid "E307: %s does not look like a Vim swap file" msgstr "E307: %s ã¯Vimã®ã‚¹ãƒ¯ãƒƒãƒ—ファイルã§ã¯ãªã„よã†ã§ã™" -#: ../memline.c:922 msgid " cannot be used on this computer.\n" msgstr " ã“ã®ã‚³ãƒ³ãƒ”ュータã§ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“.\n" -#: ../memline.c:924 msgid "The file was created on " msgstr "ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯æ¬¡ã®å ´æ‰€ã§ä½œã‚‰ã‚Œã¾ã—㟠" -#: ../memline.c:928 msgid "" ",\n" "or the file has been damaged." @@ -3757,85 +3410,104 @@ msgstr "" ",\n" "ã‚‚ã—ãã¯ãƒ•ã‚¡ã‚¤ãƒ«ãŒæå‚·ã—ã¦ã„ã¾ã™." -#: ../memline.c:945 +#, c-format +msgid "" +"E833: %s is encrypted and this version of Vim does not support encryption" +msgstr "" +"E833: %s ã¯ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®Vimã§ã‚µãƒãƒ¼ãƒˆã—ã¦ã„ãªã„å½¢å¼ã§æš—å·åŒ–ã•れã¦ã„ã¾ã™" + msgid " has been damaged (page size is smaller than minimum value).\n" msgstr " ã¯æå‚·ã—ã¦ã„ã¾ã™ (ãƒšãƒ¼ã‚¸ã‚µã‚¤ã‚ºãŒæœ€å°å€¤ã‚’下回ã£ã¦ã„ã¾ã™).\n" -#: ../memline.c:974 #, c-format msgid "Using swap file \"%s\"" msgstr "スワップファイル \"%s\" を使用ä¸" -#: ../memline.c:980 #, c-format msgid "Original file \"%s\"" msgstr "原本ファイル \"%s\"" -#: ../memline.c:995 msgid "E308: Warning: Original file may have been changed" msgstr "E308: è¦å‘Š: 原本ファイルãŒå¤‰æ›´ã•れã¦ã„ã¾ã™" -#: ../memline.c:1061 +#, c-format +msgid "Swap file is encrypted: \"%s\"" +msgstr "ã‚¹ãƒ¯ãƒƒãƒ—ãƒ•ã‚¡ã‚¤ãƒ«ã¯æš—å·åŒ–ã•れã¦ã„ã¾ã™: \"%s\"" + +msgid "" +"\n" +"If you entered a new crypt key but did not write the text file," +msgstr "" +"\n" +"æ–°ã—ã„æš—å·ã‚ーを入力ã—ãŸã‚ã¨ã«ãƒ†ã‚ストファイルをä¿å˜ã—ã¦ã„ãªã„å ´åˆã¯," + +msgid "" +"\n" +"enter the new crypt key." +msgstr "" +"\n" +"æ–°ã—ã„æš—å·ã‚ーを入力ã—ã¦ãã ã•ã„." + +msgid "" +"\n" +"If you wrote the text file after changing the crypt key press enter" +msgstr "" +"\n" +"æš—å·ã‚ーを変ãˆãŸã‚ã¨ã«ãƒ†ã‚ストファイルをä¿å˜ã—ãŸå ´åˆã¯, テã‚ストファイルã¨" + +msgid "" +"\n" +"to use the same key for text file and swap file" +msgstr "" +"\n" +"スワップファイルã«åŒã˜æš—å·ã‚ーを使ã†ãŸã‚ã«enterã ã‘を押ã—ã¦ãã ã•ã„." + #, c-format msgid "E309: Unable to read block 1 from %s" msgstr "E309: %s ã‹ã‚‰ãƒ–ãƒãƒƒã‚¯ 1 ã‚’èªè¾¼ã‚ã¾ã›ã‚“" -#: ../memline.c:1065 msgid "???MANY LINES MISSING" msgstr "???多ãã®è¡ŒãŒå¤±ã‚れã¦ã„ã¾ã™" -#: ../memline.c:1076 msgid "???LINE COUNT WRONG" msgstr "???行数ãŒé–“é•ã£ã¦ã„ã¾ã™" -#: ../memline.c:1082 msgid "???EMPTY BLOCK" msgstr "???ブãƒãƒƒã‚¯ãŒç©ºã§ã™" -#: ../memline.c:1103 msgid "???LINES MISSING" msgstr "???行ãŒå¤±ã‚れã¦ã„ã¾ã™" -#: ../memline.c:1128 #, c-format msgid "E310: Block 1 ID wrong (%s not a .swp file?)" msgstr "E310: ブãƒãƒƒã‚¯ 1 ã®IDãŒé–“é•ã£ã¦ã„ã¾ã™(%s ãŒ.swpファイルã§ãªã„?)" -#: ../memline.c:1133 msgid "???BLOCK MISSING" msgstr "???ブãƒãƒƒã‚¯ãŒã‚りã¾ã›ã‚“" -#: ../memline.c:1147 msgid "??? from here until ???END lines may be messed up" msgstr "??? ã“ã“ã‹ã‚‰ ???END ã¾ã§ã®è¡ŒãŒç ´å£Šã•れã¦ã„るよã†ã§ã™" -#: ../memline.c:1164 msgid "??? from here until ???END lines may have been inserted/deleted" msgstr "??? ã“ã“ã‹ã‚‰ ???END ã¾ã§ã®è¡ŒãŒæŒ¿å…¥ã‹å‰Šé™¤ã•れãŸã‚ˆã†ã§ã™" -#: ../memline.c:1181 msgid "???END" msgstr "???END" -#: ../memline.c:1238 msgid "E311: Recovery Interrupted" msgstr "E311: リカãƒãƒªãŒå‰²è¾¼ã¾ã‚Œã¾ã—ãŸ" -#: ../memline.c:1243 msgid "" "E312: Errors detected while recovering; look for lines starting with ???" msgstr "" "E312: リカãƒãƒªã®æœ€ä¸ã«ã‚¨ãƒ©ãƒ¼ãŒæ¤œå‡ºã•れã¾ã—ãŸ; ???ã§å§‹ã¾ã‚‹è¡Œã‚’å‚ç…§ã—ã¦ãã ã•ã„" -#: ../memline.c:1245 msgid "See \":help E312\" for more information." msgstr "詳細㯠\":help E312\" ã‚’å‚ç…§ã—ã¦ãã ã•ã„" -#: ../memline.c:1249 msgid "Recovery completed. You should check if everything is OK." msgstr "リカãƒãƒªãŒçµ‚了ã—ã¾ã—ãŸ. å…¨ã¦ãŒæ£ã—ã„ã‹ãƒã‚§ãƒƒã‚¯ã—ã¦ãã ã•ã„." -#: ../memline.c:1251 msgid "" "\n" "(You might want to write out this file under another name\n" @@ -3843,15 +3515,12 @@ msgstr "" "\n" "(変更をãƒã‚§ãƒƒã‚¯ã™ã‚‹ãŸã‚ã«, ã“ã®ãƒ•ァイルを別ã®åå‰ã§ä¿å˜ã—ãŸä¸Šã§\n" -#: ../memline.c:1252 msgid "and run diff with the original file to check for changes)" msgstr "原本ファイルã¨ã® diff を実行ã™ã‚‹ã¨è‰¯ã„ã§ã—ょã†)" -#: ../memline.c:1254 msgid "Recovery completed. Buffer contents equals file contents." msgstr "復元完了. ãƒãƒƒãƒ•ã‚¡ã®å†…容ã¯ãƒ•ァイルã¨åŒã˜ã«ãªã‚Šã¾ã—ãŸ." -#: ../memline.c:1255 msgid "" "\n" "You may want to delete the .swp file now.\n" @@ -3861,52 +3530,43 @@ msgstr "" "å…ƒã®.swpファイルã¯å‰Šé™¤ã—ã¦ã‚‚æ§‹ã„ã¾ã›ã‚“\n" "\n" +msgid "Using crypt key from swap file for the text file.\n" +msgstr "スワップファイルã‹ã‚‰å–å¾—ã—ãŸæš—å·ã‚ーをテã‚ストファイルã«ä½¿ã„ã¾ã™.\n" + #. use msg() to start the scrolling properly -#: ../memline.c:1327 msgid "Swap files found:" msgstr "スワップファイルãŒè¤‡æ•°è¦‹ã¤ã‹ã‚Šã¾ã—ãŸ:" -#: ../memline.c:1446 msgid " In current directory:\n" msgstr " ç¾åœ¨ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒª:\n" -#: ../memline.c:1448 msgid " Using specified name:\n" msgstr " 以下ã®åå‰ã‚’使用ä¸:\n" -#: ../memline.c:1450 msgid " In directory " msgstr " ディレクトリ " -#: ../memline.c:1465 msgid " -- none --\n" msgstr " -- ãªã— --\n" -#: ../memline.c:1527 msgid " owned by: " msgstr " 所有者: " -#: ../memline.c:1529 msgid " dated: " msgstr " 日付: " -#: ../memline.c:1532 ../memline.c:3231 msgid " dated: " msgstr " 日付: " -#: ../memline.c:1548 msgid " [from Vim version 3.0]" msgstr " [from Vim version 3.0]" -#: ../memline.c:1550 msgid " [does not look like a Vim swap file]" msgstr " [Vimã®ã‚¹ãƒ¯ãƒƒãƒ—ファイルã§ã¯ãªã„よã†ã§ã™]" -#: ../memline.c:1552 msgid " file name: " msgstr " ファイルå: " -#: ../memline.c:1558 msgid "" "\n" " modified: " @@ -3914,15 +3574,12 @@ msgstr "" "\n" " 変更状態: " -#: ../memline.c:1559 msgid "YES" msgstr "ã‚り" -#: ../memline.c:1559 msgid "no" msgstr "ãªã—" -#: ../memline.c:1562 msgid "" "\n" " user name: " @@ -3930,11 +3587,9 @@ msgstr "" "\n" " ユーザーå: " -#: ../memline.c:1568 msgid " host name: " msgstr " ホストå: " -#: ../memline.c:1570 msgid "" "\n" " host name: " @@ -3942,7 +3597,6 @@ msgstr "" "\n" " ホストå: " -#: ../memline.c:1575 msgid "" "\n" " process ID: " @@ -3950,11 +3604,16 @@ msgstr "" "\n" " プãƒã‚»ã‚¹ID: " -#: ../memline.c:1579 msgid " (still running)" msgstr " (ã¾ã 実行ä¸)" -#: ../memline.c:1586 +msgid "" +"\n" +" [not usable with this version of Vim]" +msgstr "" +"\n" +" [ã“ã®Vimãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“]" + msgid "" "\n" " [not usable on this computer]" @@ -3962,97 +3621,75 @@ msgstr "" "\n" " [ã“ã®ã‚³ãƒ³ãƒ”ュータã§ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“]" -#: ../memline.c:1590 msgid " [cannot be read]" msgstr " [èªè¾¼ã‚ã¾ã›ã‚“]" -#: ../memline.c:1593 msgid " [cannot be opened]" msgstr " [é–‹ã‘ã¾ã›ã‚“]" -#: ../memline.c:1698 msgid "E313: Cannot preserve, there is no swap file" msgstr "E313: スワップファイルãŒç„¡ã„ã®ã§ç¶æŒã§ãã¾ã›ã‚“" -#: ../memline.c:1747 msgid "File preserved" msgstr "ファイルãŒç¶æŒã•れã¾ã™" -#: ../memline.c:1749 msgid "E314: Preserve failed" msgstr "E314: ç¶æŒã«å¤±æ•—ã—ã¾ã—ãŸ" -#: ../memline.c:1819 #, c-format -msgid "E315: ml_get: invalid lnum: %<PRId64>" -msgstr "E315: ml_get: 無効ãªlnumã§ã™: %<PRId64>" +msgid "E315: ml_get: invalid lnum: %ld" +msgstr "E315: ml_get: 無効ãªlnumã§ã™: %ld" -#: ../memline.c:1851 #, c-format -msgid "E316: ml_get: cannot find line %<PRId64>" -msgstr "E316: ml_get: 行 %<PRId64> を見ã¤ã‘られã¾ã›ã‚“" +msgid "E316: ml_get: cannot find line %ld" +msgstr "E316: ml_get: 行 %ld を見ã¤ã‘られã¾ã›ã‚“" -#: ../memline.c:2236 msgid "E317: pointer block id wrong 3" msgstr "E317: ãƒã‚¤ãƒ³ã‚¿ãƒ–ãƒãƒƒã‚¯ã®IDãŒé–“é•ã£ã¦ã„ã¾ã™ 3" -#: ../memline.c:2311 msgid "stack_idx should be 0" msgstr "stack_idx 㯠0 ã§ã‚ã‚‹ã¹ãã§ã™" -#: ../memline.c:2369 msgid "E318: Updated too many blocks?" msgstr "E318: æ›´æ–°ã•れãŸãƒ–ãƒãƒƒã‚¯ãŒå¤šéŽãŽã‚‹ã‹ã‚‚?" -#: ../memline.c:2511 msgid "E317: pointer block id wrong 4" msgstr "E317: ãƒã‚¤ãƒ³ã‚¿ãƒ–ãƒãƒƒã‚¯ã®IDãŒé–“é•ã£ã¦ã„ã¾ã™ 4" -#: ../memline.c:2536 msgid "deleted block 1?" msgstr "ブãƒãƒƒã‚¯ 1 ã¯æ¶ˆã•れãŸ?" -#: ../memline.c:2707 #, c-format -msgid "E320: Cannot find line %<PRId64>" -msgstr "E320: 行 %<PRId64> ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" +msgid "E320: Cannot find line %ld" +msgstr "E320: 行 %ld ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../memline.c:2916 msgid "E317: pointer block id wrong" msgstr "E317: ãƒã‚¤ãƒ³ã‚¿ãƒ–ãƒãƒƒã‚¯ã®IDãŒé–“é•ã£ã¦ã„ã¾ã™" -#: ../memline.c:2930 msgid "pe_line_count is zero" msgstr "pe_line_count ãŒã‚¼ãƒã§ã™" -#: ../memline.c:2955 #, c-format -msgid "E322: line number out of range: %<PRId64> past the end" -msgstr "E322: 行番å·ãŒç¯„囲外ã§ã™: %<PRId64> è¶…ãˆã¦ã„ã¾ã™" +msgid "E322: line number out of range: %ld past the end" +msgstr "E322: 行番å·ãŒç¯„囲外ã§ã™: %ld è¶…ãˆã¦ã„ã¾ã™" -#: ../memline.c:2959 #, c-format -msgid "E323: line count wrong in block %<PRId64>" -msgstr "E323: ブãƒãƒƒã‚¯ %<PRId64> ã®è¡Œã‚«ã‚¦ãƒ³ãƒˆãŒé–“é•ã£ã¦ã„ã¾ã™" +msgid "E323: line count wrong in block %ld" +msgstr "E323: ブãƒãƒƒã‚¯ %ld ã®è¡Œã‚«ã‚¦ãƒ³ãƒˆãŒé–“é•ã£ã¦ã„ã¾ã™" -#: ../memline.c:2999 msgid "Stack size increases" msgstr "スタックサイズãŒå¢—ãˆã¾ã™" -#: ../memline.c:3038 msgid "E317: pointer block id wrong 2" msgstr "E317: ãƒã‚¤ãƒ³ã‚¿ãƒ–ãƒãƒƒã‚¯ã®IDãŒé–“é•ã£ã¦ã„ã¾ã™ 2" -#: ../memline.c:3070 #, c-format msgid "E773: Symlink loop for \"%s\"" msgstr "E773: \"%s\" ã®ã‚·ãƒ³ãƒœãƒªãƒƒã‚¯ãƒªãƒ³ã‚¯ãŒãƒ«ãƒ¼ãƒ—ã«ãªã£ã¦ã„ã¾ã™" -#: ../memline.c:3221 msgid "E325: ATTENTION" msgstr "E325: 注æ„" -#: ../memline.c:3222 msgid "" "\n" "Found a swap file by the name \"" @@ -4060,39 +3697,32 @@ msgstr "" "\n" "次ã®åå‰ã§ã‚¹ãƒ¯ãƒƒãƒ—ファイルを見ã¤ã‘ã¾ã—㟠\"" -#: ../memline.c:3226 msgid "While opening file \"" msgstr "次ã®ãƒ•ァイルを開ã„ã¦ã„ã‚‹æœ€ä¸ \"" -#: ../memline.c:3239 msgid " NEWER than swap file!\n" msgstr " スワップファイルよりも新ã—ã„ã§ã™!\n" -#: ../memline.c:3244 +#. Some of these messages are long to allow translation to +#. * other languages. msgid "" "\n" "(1) Another program may be editing the same file. If this is the case,\n" " be careful not to end up with two different instances of the same\n" -" file when making changes." +" file when making changes. Quit, or continue with caution.\n" msgstr "" "\n" "(1) 別ã®ãƒ—ãƒã‚°ãƒ©ãƒ ãŒåŒã˜ãƒ•ァイルを編集ã—ã¦ã„ã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“.\n" " ã“ã®å ´åˆã«ã¯, 変更をã—ã¦ã—ã¾ã†ã¨1ã¤ã®ãƒ•ァイルã«å¯¾ã—ã¦ç•°ãªã‚‹2ã¤ã®\n" -" インスタンスãŒã§ãã¦ã—ã¾ã†ã®ã§, ãã†ã—ãªã„よã†ã«æ°—ã‚’ã¤ã‘ã¦ãã ã•ã„." - -#: ../memline.c:3245 -msgid " Quit, or continue with caution.\n" -msgstr " 終了ã™ã‚‹ã‹, 注æ„ã—ãªãŒã‚‰ç¶šã‘ã¦ãã ã•ã„.\n" +" インスタンスãŒã§ãã¦ã—ã¾ã†ã®ã§, ãã†ã—ãªã„よã†ã«æ°—ã‚’ã¤ã‘ã¦ãã ã•ã„.\n" +" 終了ã™ã‚‹ã‹, 注æ„ã—ãªãŒã‚‰ç¶šã‘ã¦ãã ã•ã„.\n" -#: ../memline.c:3246 msgid "(2) An edit session for this file crashed.\n" msgstr "(2) ã“ã®ãƒ•ァイルã®ç·¨é›†ã‚»ãƒƒã‚·ãƒ§ãƒ³ãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ãŸ.\n" -#: ../memline.c:3247 msgid " If this is the case, use \":recover\" or \"vim -r " msgstr " ã“ã®å ´åˆã«ã¯ \":recover\" ã‹ \"vim -r " -#: ../memline.c:3249 msgid "" "\"\n" " to recover the changes (see \":help recovery\").\n" @@ -4100,11 +3730,9 @@ msgstr "" "\"\n" " を使用ã—ã¦å¤‰æ›´ã‚’リカãƒãƒ¼ã—ã¾ã™(\":help recovery\" ã‚’å‚ç…§).\n" -#: ../memline.c:3250 msgid " If you did this already, delete the swap file \"" msgstr " æ—¢ã«ã“れを行ãªã£ãŸã®ãªã‚‰ã°, スワップファイル \"" -#: ../memline.c:3252 msgid "" "\"\n" " to avoid this message.\n" @@ -4112,23 +3740,18 @@ msgstr "" "\"\n" " を消ã›ã°ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’回é¿ã§ãã¾ã™.\n" -#: ../memline.c:3450 ../memline.c:3452 msgid "Swap file \"" msgstr "スワップファイル \"" -#: ../memline.c:3451 ../memline.c:3455 msgid "\" already exists!" msgstr "\" ãŒæ—¢ã«ã‚りã¾ã™!" -#: ../memline.c:3457 msgid "VIM - ATTENTION" msgstr "VIM - 注æ„" -#: ../memline.c:3459 msgid "Swap file already exists!" msgstr "ã‚¹ãƒ¯ãƒƒãƒ—ãƒ•ã‚¡ã‚¤ãƒ«ãŒæ—¢ã«å˜åœ¨ã—ã¾ã™!" -#: ../memline.c:3464 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4142,7 +3765,6 @@ msgstr "" "終了ã™ã‚‹(&Q)\n" "䏿¢ã™ã‚‹(&A)" -#: ../memline.c:3467 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4158,56 +3780,34 @@ msgstr "" "終了ã™ã‚‹(&Q)\n" "䏿¢ã™ã‚‹(&A)" -#. -#. * Change the ".swp" extension to find another file that can be used. -#. * First decrement the last char: ".swo", ".swn", etc. -#. * If that still isn't enough decrement the last but one char: ".svz" -#. * Can happen when editing many "No Name" buffers. -#. -#. ".s?a" -#. ".saa": tried enough, give up -#: ../memline.c:3528 msgid "E326: Too many swap files found" msgstr "E326: スワップファイルãŒå¤šæ•°è¦‹ã¤ã‹ã‚Šã¾ã—ãŸ" -#: ../memory.c:227 -#, c-format -msgid "E342: Out of memory! (allocating %<PRIu64> bytes)" -msgstr "E342: メモリãŒè¶³ã‚Šã¾ã›ã‚“! (%<PRIu64> ãƒã‚¤ãƒˆã‚’å‰²å½“è¦æ±‚)" - -#: ../menu.c:62 msgid "E327: Part of menu-item path is not sub-menu" msgstr "E327: メニューアイテムã®ãƒ‘スã®éƒ¨åˆ†ãŒã‚µãƒ–メニューã§ã¯ã‚りã¾ã›ã‚“" -#: ../menu.c:63 msgid "E328: Menu only exists in another mode" msgstr "E328: メニューã¯ä»–ã®ãƒ¢ãƒ¼ãƒ‰ã«ã ã‘ã‚りã¾ã™" -#: ../menu.c:64 #, c-format msgid "E329: No menu \"%s\"" msgstr "E329: \"%s\" ã¨ã„ã†ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã¯ã‚りã¾ã›ã‚“" #. Only a mnemonic or accelerator is not valid. -#: ../menu.c:329 msgid "E792: Empty menu name" msgstr "E792: メニューåãŒç©ºã§ã™" -#: ../menu.c:340 msgid "E330: Menu path must not lead to a sub-menu" msgstr "E330: メニューパスã¯ã‚µãƒ–メニューを生ã˜ã‚‹ã¹ãã§ã¯ã‚りã¾ã›ã‚“" -#: ../menu.c:365 msgid "E331: Must not add menu items directly to menu bar" msgstr "E331: メニューãƒãƒ¼ã«ã¯ç›´æŽ¥ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚¢ã‚¤ãƒ†ãƒ ã‚’è¿½åŠ ã§ãã¾ã›ã‚“" -#: ../menu.c:370 msgid "E332: Separator cannot be part of a menu path" msgstr "E332: 区切りã¯ãƒ¡ãƒ‹ãƒ¥ãƒ¼ãƒ‘スã®ä¸€éƒ¨ã§ã¯ã‚りã¾ã›ã‚“" #. Now we have found the matching menu, and we list the mappings #. Highlight title -#: ../menu.c:762 msgid "" "\n" "--- Menus ---" @@ -4215,69 +3815,60 @@ msgstr "" "\n" "--- メニュー ---" -#: ../menu.c:1313 +msgid "Tear off this menu" +msgstr "ã“ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚’切りå–ã‚‹" + msgid "E333: Menu path must lead to a menu item" msgstr "E333: メニューパスã¯ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚¢ã‚¤ãƒ†ãƒ を生ã˜ãªã‘れã°ã„ã‘ã¾ã›ã‚“" -#: ../menu.c:1330 #, c-format msgid "E334: Menu not found: %s" msgstr "E334: メニューãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“: %s" -#: ../menu.c:1396 #, c-format msgid "E335: Menu not defined for %s mode" msgstr "E335: %s ã«ã¯ãƒ¡ãƒ‹ãƒ¥ãƒ¼ãŒå®šç¾©ã•れã¦ã„ã¾ã›ã‚“" -#: ../menu.c:1426 msgid "E336: Menu path must lead to a sub-menu" msgstr "E336: メニューパスã¯ã‚µãƒ–メニューを生ã˜ãªã‘れã°ã„ã‘ã¾ã›ã‚“" -#: ../menu.c:1447 msgid "E337: Menu not found - check menu names" msgstr "E337: メニューãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ - メニューåを確èªã—ã¦ãã ã•ã„" -#: ../message.c:423 #, c-format msgid "Error detected while processing %s:" msgstr "%s ã®å‡¦ç†ä¸ã«ã‚¨ãƒ©ãƒ¼ãŒæ¤œå‡ºã•れã¾ã—ãŸ:" -#: ../message.c:445 #, c-format msgid "line %4ld:" msgstr "行 %4ld:" -#: ../message.c:617 #, c-format msgid "E354: Invalid register name: '%s'" msgstr "E354: 無効ãªãƒ¬ã‚¸ã‚¹ã‚¿å: '%s'" -#: ../message.c:986 +msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>" +msgstr "日本語メッセージ翻訳/監修: æ‘岡 太郎 <koron.kaoriya@gmail.com>" + msgid "Interrupt: " msgstr "割込ã¿: " -#: ../message.c:988 msgid "Press ENTER or type command to continue" msgstr "ç¶šã‘ã‚‹ã«ã¯ENTERを押ã™ã‹ã‚³ãƒžãƒ³ãƒ‰ã‚’入力ã—ã¦ãã ã•ã„" -#: ../message.c:1843 #, c-format -msgid "%s line %<PRId64>" -msgstr "%s 行 %<PRId64>" +msgid "%s line %ld" +msgstr "%s 行 %ld" -#: ../message.c:2392 msgid "-- More --" msgstr "-- 継続 --" -#: ../message.c:2398 msgid " SPACE/d/j: screen/page/line down, b/u/k: up, q: quit " msgstr " SPACE/d/j: ç”»é¢/ページ/行 下, b/u/k: 上, q: 終了 " -#: ../message.c:3021 ../message.c:3031 msgid "Question" msgstr "質å•" -#: ../message.c:3023 msgid "" "&Yes\n" "&No" @@ -4285,17 +3876,6 @@ msgstr "" "ã¯ã„(&Y)\n" "ã„ã„ãˆ(&N)" -#: ../message.c:3033 -msgid "" -"&Yes\n" -"&No\n" -"&Cancel" -msgstr "" -"ã¯ã„(&Y)\n" -"ã„ã„ãˆ(&N)\n" -"ã‚ャンセル(&C)" - -#: ../message.c:3045 msgid "" "&Yes\n" "&No\n" @@ -4309,175 +3889,247 @@ msgstr "" "å…¨ã¦æ”¾æ£„(&D)\n" "ã‚ャンセル(&C)" -#: ../message.c:3058 +msgid "Select Directory dialog" +msgstr "ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªé¸æŠžãƒ€ã‚¤ã‚¢ãƒã‚°" + +msgid "Save File dialog" +msgstr "ファイルä¿å˜ãƒ€ã‚¤ã‚¢ãƒã‚°" + +msgid "Open File dialog" +msgstr "ファイルèªè¾¼ãƒ€ã‚¤ã‚¢ãƒã‚°" + +#. TODO: non-GUI file selector here +msgid "E338: Sorry, no file browser in console mode" +msgstr "E338: コンソールモードã§ã¯ãƒ•ァイルブラウザを使ãˆã¾ã›ã‚“, ã”ã‚ã‚“ãªã•ã„" + msgid "E766: Insufficient arguments for printf()" msgstr "E766: printf() ã®å¼•æ•°ãŒä¸å分ã§ã™" -#: ../message.c:3119 msgid "E807: Expected Float argument for printf()" msgstr "E807: printf() ã®å¼•æ•°ã«ã¯æµ®å‹•å°‘æ•°ç‚¹æ•°ãŒæœŸå¾…ã•れã¦ã„ã¾ã™" -#: ../message.c:3873 msgid "E767: Too many arguments to printf()" msgstr "E767: printf() ã®å¼•æ•°ãŒå¤šéŽãŽã¾ã™" -#: ../misc1.c:2256 msgid "W10: Warning: Changing a readonly file" msgstr "W10: è¦å‘Š: èªè¾¼å°‚用ファイルを変更ã—ã¾ã™" -#: ../misc1.c:2537 msgid "Type number and <Enter> or click with mouse (empty cancels): " msgstr "" "番å·ã¨<Enter>を入力ã™ã‚‹ã‹ãƒžã‚¦ã‚¹ã§ã‚¯ãƒªãƒƒã‚¯ã—ã¦ãã ã•ã„ (空ã§ã‚ャンセル): " -#: ../misc1.c:2539 msgid "Type number and <Enter> (empty cancels): " msgstr "番å·ã¨<Enter>を入力ã—ã¦ãã ã•ã„ (空ã§ã‚ャンセル): " -#: ../misc1.c:2585 msgid "1 more line" msgstr "1 行 è¿½åŠ ã—ã¾ã—ãŸ" -#: ../misc1.c:2588 msgid "1 line less" msgstr "1 行 削除ã—ã¾ã—ãŸ" -#: ../misc1.c:2593 #, c-format -msgid "%<PRId64> more lines" -msgstr "%<PRId64> 行 è¿½åŠ ã—ã¾ã—ãŸ" +msgid "%ld more lines" +msgstr "%ld 行 è¿½åŠ ã—ã¾ã—ãŸ" -#: ../misc1.c:2596 #, c-format -msgid "%<PRId64> fewer lines" -msgstr "%<PRId64> 行 削除ã—ã¾ã—ãŸ" +msgid "%ld fewer lines" +msgstr "%ld 行 削除ã—ã¾ã—ãŸ" -#: ../misc1.c:2599 msgid " (Interrupted)" msgstr " (割込ã¾ã‚Œã¾ã—ãŸ)" -#: ../misc1.c:2635 msgid "Beep!" msgstr "ビーッ!" -#: ../misc2.c:738 +msgid "ERROR: " +msgstr "エラー: " + +#, c-format +msgid "" +"\n" +"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n" +msgstr "" +"\n" +"[メモリ(ãƒã‚¤ãƒˆ)] ç·å‰²å½“-è§£æ”¾é‡ %lu-%lu, ä½¿ç”¨é‡ %lu, ピーク時 %lu\n" + +#, c-format +msgid "" +"[calls] total re/malloc()'s %lu, total free()'s %lu\n" +"\n" +msgstr "" +"[呼出] ç· re/malloc() 回数 %lu, ç· free() 回数 %lu\n" +"\n" + +msgid "E340: Line is becoming too long" +msgstr "E340: 行ãŒé•·ããªã‚ŠéŽãŽã¾ã—ãŸ" + +#, c-format +msgid "E341: Internal error: lalloc(%ld, )" +msgstr "E341: 内部エラー: lalloc(%ld,)" + +#, c-format +msgid "E342: Out of memory! (allocating %lu bytes)" +msgstr "E342: メモリãŒè¶³ã‚Šã¾ã›ã‚“! (%lu ãƒã‚¤ãƒˆã‚’å‰²å½“è¦æ±‚)" + #, c-format msgid "Calling shell to execute: \"%s\"" msgstr "実行ã®ãŸã‚ã«ã‚·ã‚§ãƒ«ã‚’呼出ã—ä¸: \"%s\"" -#: ../normal.c:183 +msgid "E545: Missing colon" +msgstr "E545: コãƒãƒ³ãŒã‚りã¾ã›ã‚“" + +msgid "E546: Illegal mode" +msgstr "E546: 䏿£ãªãƒ¢ãƒ¼ãƒ‰ã§ã™" + +msgid "E547: Illegal mouseshape" +msgstr "E547: 䏿£ãª 'mouseshape' ã§ã™" + +msgid "E548: digit expected" +msgstr "E548: 数値ãŒå¿…è¦ã§ã™" + +msgid "E549: Illegal percentage" +msgstr "E549: 䏿£ãªãƒ‘ーセンテージã§ã™" + +msgid "E854: path too long for completion" +msgstr "E854: パスãŒé•·éŽãŽã¦è£œå®Œã§ãã¾ã›ã‚“" + +#, c-format +msgid "" +"E343: Invalid path: '**[number]' must be at the end of the path or be " +"followed by '%s'." +msgstr "" +"E343: 無効ãªãƒ‘スã§ã™: '**[数値]' ã¯pathã®æœ€å¾Œã‹ '%s' ãŒç¶šã„ã¦ãªã„ã¨ã„ã‘ã¾ã›" +"ã‚“." + +#, c-format +msgid "E344: Can't find directory \"%s\" in cdpath" +msgstr "E344: cdpathã«ã¯ \"%s\" ã¨ã„ã†ãƒ•ァイルãŒã‚りã¾ã›ã‚“" + +#, c-format +msgid "E345: Can't find file \"%s\" in path" +msgstr "E345: pathã«ã¯ \"%s\" ã¨ã„ã†ãƒ•ァイルãŒã‚りã¾ã›ã‚“" + +#, c-format +msgid "E346: No more directory \"%s\" found in cdpath" +msgstr "E346: cdpathã«ã¯ã“れ以上 \"%s\" ã¨ã„ã†ãƒ•ァイルãŒã‚りã¾ã›ã‚“" + +#, c-format +msgid "E347: No more file \"%s\" found in path" +msgstr "E347: パスã«ã¯ã“れ以上 \"%s\" ã¨ã„ã†ãƒ•ァイルãŒã‚りã¾ã›ã‚“" + +#, c-format +msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" +msgstr "" +"E668: NetBeansã®æŽ¥ç¶šæƒ…å ±ãƒ•ã‚¡ã‚¤ãƒ«ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒ¢ãƒ¼ãƒ‰ã«å•題ãŒã‚りã¾ã™: \"%s\"" + +#, c-format +msgid "E658: NetBeans connection lost for buffer %ld" +msgstr "E658: ãƒãƒƒãƒ•ã‚¡ %ld ã® NetBeans 接続ãŒå¤±ã‚れã¾ã—ãŸ" + +msgid "E838: netbeans is not supported with this GUI" +msgstr "E838: NetBeansã¯ã“ã®GUIã«ã¯å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“" + +msgid "E511: netbeans already connected" +msgstr "E511: NetBeansã¯æ—¢ã«æŽ¥ç¶šã—ã¦ã„ã¾ã™" + +#, c-format +msgid "E505: %s is read-only (add ! to override)" +msgstr "E505: %s ã¯èªè¾¼å°‚用ã§ã™ (強制書込ã«ã¯ ! ã‚’è¿½åŠ )" + msgid "E349: No identifier under cursor" msgstr "E349: カーソルã®ä½ç½®ã«ã¯è˜åˆ¥åãŒã‚りã¾ã›ã‚“" -#: ../normal.c:1866 msgid "E774: 'operatorfunc' is empty" msgstr "E774: 'operatorfunc' オプションãŒç©ºã§ã™" -#: ../normal.c:2637 +msgid "E775: Eval feature not available" +msgstr "E775: å¼è©•価機能ãŒç„¡åйã«ãªã£ã¦ã„ã¾ã™" + msgid "Warning: terminal cannot highlight" msgstr "è¦å‘Š: 使用ã—ã¦ã„る端末ã¯ãƒã‚¤ãƒ©ã‚¤ãƒˆã§ãã¾ã›ã‚“" -#: ../normal.c:2807 msgid "E348: No string under cursor" msgstr "E348: カーソルã®ä½ç½®ã«ã¯æ–‡å—列ãŒã‚りã¾ã›ã‚“" -#: ../normal.c:3937 msgid "E352: Cannot erase folds with current 'foldmethod'" msgstr "E352: ç¾åœ¨ã® 'foldmethod' ã§ã¯æŠ˜ç•³ã¿ã‚’消去ã§ãã¾ã›ã‚“" -#: ../normal.c:5897 msgid "E664: changelist is empty" msgstr "E664: 変更リストãŒç©ºã§ã™" -#: ../normal.c:5899 msgid "E662: At start of changelist" msgstr "E662: 変更リストã®å…ˆé " -#: ../normal.c:5901 msgid "E663: At end of changelist" msgstr "E663: å¤‰æ›´ãƒªã‚¹ãƒˆã®æœ«å°¾" -#: ../normal.c:7053 -msgid "Type :quit<Enter> to exit Nvim" +msgid "Type :quit<Enter> to exit Vim" msgstr "Vimを終了ã™ã‚‹ã«ã¯ :quit<Enter> ã¨å…¥åŠ›ã—ã¦ãã ã•ã„" -#: ../ops.c:248 #, c-format msgid "1 line %sed 1 time" msgstr "1 行㌠%s ã§ 1 回処ç†ã•れã¾ã—ãŸ" -#: ../ops.c:250 #, c-format msgid "1 line %sed %d times" msgstr "1 行㌠%s ã§ %d 回処ç†ã•れã¾ã—ãŸ" -#: ../ops.c:253 #, c-format -msgid "%<PRId64> lines %sed 1 time" -msgstr "%<PRId64> 行㌠%s ã§ 1 回処ç†ã•れã¾ã—ãŸ" +msgid "%ld lines %sed 1 time" +msgstr "%ld 行㌠%s ã§ 1 回処ç†ã•れã¾ã—ãŸ" -#: ../ops.c:256 #, c-format -msgid "%<PRId64> lines %sed %d times" -msgstr "%<PRId64> 行㌠%s ã§ %d 回処ç†ã•れã¾ã—ãŸ" +msgid "%ld lines %sed %d times" +msgstr "%ld 行㌠%s ã§ %d 回処ç†ã•れã¾ã—ãŸ" -#: ../ops.c:592 #, c-format -msgid "%<PRId64> lines to indent... " -msgstr "%<PRId64> 行ãŒã‚¤ãƒ³ãƒ‡ãƒ³ãƒˆã•れã¾ã™... " +msgid "%ld lines to indent... " +msgstr "%ld 行ãŒã‚¤ãƒ³ãƒ‡ãƒ³ãƒˆã•れã¾ã™... " -#: ../ops.c:634 msgid "1 line indented " msgstr "1 行をインデントã—ã¾ã—㟠" -#: ../ops.c:636 #, c-format -msgid "%<PRId64> lines indented " -msgstr "%<PRId64> 行をインデントã—ã¾ã—㟠" +msgid "%ld lines indented " +msgstr "%ld 行をインデントã—ã¾ã—㟠" -#: ../ops.c:938 msgid "E748: No previously used register" msgstr "E748: ã¾ã レジスタを使用ã—ã¦ã„ã¾ã›ã‚“" #. must display the prompt -#: ../ops.c:1433 msgid "cannot yank; delete anyway" msgstr "ヤンクã§ãã¾ã›ã‚“; ã¨ã«ã‹ã消去" -#: ../ops.c:1929 msgid "1 line changed" msgstr "1 行ãŒå¤‰æ›´ã•れã¾ã—ãŸ" -#: ../ops.c:1931 #, c-format -msgid "%<PRId64> lines changed" -msgstr "%<PRId64> 行ãŒå¤‰æ›´ã•れã¾ã—ãŸ" +msgid "%ld lines changed" +msgstr "%ld 行ãŒå¤‰æ›´ã•れã¾ã—ãŸ" + +#, c-format +msgid "freeing %ld lines" +msgstr "%ld 行を解放ä¸" -#: ../ops.c:2521 msgid "block of 1 line yanked" msgstr "1 行ã®ãƒ–ãƒãƒƒã‚¯ãŒãƒ¤ãƒ³ã‚¯ã•れã¾ã—ãŸ" -#: ../ops.c:2523 msgid "1 line yanked" msgstr "1 行ãŒãƒ¤ãƒ³ã‚¯ã•れã¾ã—ãŸ" -#: ../ops.c:2525 #, c-format -msgid "block of %<PRId64> lines yanked" -msgstr "%<PRId64> 行ã®ãƒ–ãƒãƒƒã‚¯ãŒãƒ¤ãƒ³ã‚¯ã•れã¾ã—ãŸ" +msgid "block of %ld lines yanked" +msgstr "%ld 行ã®ãƒ–ãƒãƒƒã‚¯ãŒãƒ¤ãƒ³ã‚¯ã•れã¾ã—ãŸ" -#: ../ops.c:2528 #, c-format -msgid "%<PRId64> lines yanked" -msgstr "%<PRId64> 行ãŒãƒ¤ãƒ³ã‚¯ã•れã¾ã—ãŸ" +msgid "%ld lines yanked" +msgstr "%ld 行ãŒãƒ¤ãƒ³ã‚¯ã•れã¾ã—ãŸ" -#: ../ops.c:2710 #, c-format msgid "E353: Nothing in register %s" msgstr "E353: レジスタ %s ã«ã¯ä½•ã‚‚ã‚りã¾ã›ã‚“" #. Highlight title -#: ../ops.c:3185 msgid "" "\n" "--- Registers ---" @@ -4485,11 +4137,9 @@ msgstr "" "\n" "--- レジスタ ---" -#: ../ops.c:4455 msgid "Illegal register name" msgstr "䏿£ãªãƒ¬ã‚¸ã‚¹ã‚¿å" -#: ../ops.c:4533 msgid "" "\n" "# Registers:\n" @@ -4497,7 +4147,6 @@ msgstr "" "\n" "# レジスタ:\n" -#: ../ops.c:4575 #, c-format msgid "E574: Unknown register type %d" msgstr "E574: 未知ã®ãƒ¬ã‚¸ã‚¹ã‚¿åž‹ %d ã§ã™" @@ -4507,86 +4156,61 @@ msgid "" "lines" msgstr "E883: 検索パターンã¨å¼ãƒ¬ã‚¸ã‚¹ã‚¿ã«ã¯2行以上をå«ã‚られã¾ã›ã‚“" -#: ../ops.c:5089 #, c-format -msgid "%<PRId64> Cols; " -msgstr "%<PRId64> 列; " +msgid "%ld Cols; " +msgstr "%ld 列; " -#: ../ops.c:5097 #, c-format -msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Bytes" -msgstr "" -"é¸æŠž %s%<PRId64> / %<PRId64> 行; %<PRId64> / %<PRId64> å˜èªž; %<PRId64> / " -"%<PRId64> ãƒã‚¤ãƒˆ" +msgid "Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Bytes" +msgstr "é¸æŠž %s%ld / %ld 行; %lld / %lld å˜èªž; %lld / %lld ãƒã‚¤ãƒˆ" -#: ../ops.c:5105 #, c-format msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Chars; %<PRId64> of %<PRId64> Bytes" +"Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Chars; %lld of " +"%lld Bytes" msgstr "" -"é¸æŠž %s%<PRId64> / %<PRId64> 行; %<PRId64> / %<PRId64> å˜èªž; %<PRId64> / " -"%<PRId64> æ–‡å—; %<PRId64> / %<PRId64> ãƒã‚¤ãƒˆ" +"é¸æŠž %s%ld / %ld 行; %lld / %lld å˜èªž; %lld / %lld æ–‡å—; %lld / %lld ãƒã‚¤ãƒˆ" -#: ../ops.c:5123 #, c-format -msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Byte " -"%<PRId64> of %<PRId64>" -msgstr "" -"列 %s / %s; 行 %<PRId64> of %<PRId64>; å˜èªž %<PRId64> / %<PRId64>; ãƒã‚¤ãƒˆ " -"%<PRId64> / %<PRId64>" +msgid "Col %s of %s; Line %ld of %ld; Word %lld of %lld; Byte %lld of %lld" +msgstr "列 %s / %s; 行 %ld of %ld; å˜èªž %lld / %lld; ãƒã‚¤ãƒˆ %lld / %lld" -#: ../ops.c:5133 #, c-format msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Char " -"%<PRId64> of %<PRId64>; Byte %<PRId64> of %<PRId64>" +"Col %s of %s; Line %ld of %ld; Word %lld of %lld; Char %lld of %lld; Byte " +"%lld of %lld" msgstr "" -"列 %s / %s; 行 %<PRId64> / %<PRId64>; å˜èªž %<PRId64> / %<PRId64>; æ–‡å— " -"%<PRId64> / %<PRId64>; ãƒã‚¤ãƒˆ %<PRId64> of %<PRId64>" +"列 %s / %s; 行 %ld / %ld; å˜èªž %lld / %lld; æ–‡å— %lld / %lld; ãƒã‚¤ãƒˆ %lld of " +"%lld" -#: ../ops.c:5146 #, c-format -msgid "(+%<PRId64> for BOM)" -msgstr "(+%<PRId64> for BOM)" +msgid "(+%ld for BOM)" +msgstr "(+%ld for BOM)" -#: ../option.c:1238 msgid "%<%f%h%m%=Page %N" msgstr "%<%f%h%m%=%N ページ" -#: ../option.c:1574 msgid "Thanks for flying Vim" msgstr "Vim を使ã£ã¦ãれã¦ã‚りãŒã¨ã†" -#. found a mismatch: skip -#: ../option.c:2698 msgid "E518: Unknown option" msgstr "E518: 未知ã®ã‚ªãƒ—ションã§ã™" -#: ../option.c:2709 msgid "E519: Option not supported" msgstr "E519: オプションã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“" -#: ../option.c:2740 msgid "E520: Not allowed in a modeline" msgstr "E520: modeline ã§ã¯è¨±å¯ã•れã¾ã›ã‚“" -#: ../option.c:2815 msgid "E846: Key code not set" msgstr "E846: ã‚ーコードãŒè¨å®šã•れã¦ã„ã¾ã›ã‚“" -#: ../option.c:2924 msgid "E521: Number required after =" msgstr "E521: = ã®å¾Œã«ã¯æ•°å—ãŒå¿…è¦ã§ã™" -#: ../option.c:3226 ../option.c:3864 msgid "E522: Not found in termcap" msgstr "E522: termcap 内ã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../option.c:3335 #, c-format msgid "E539: Illegal character <%s>" msgstr "E539: 䏿£ãªæ–‡å—ã§ã™ <%s>" @@ -4595,93 +4219,99 @@ msgstr "E539: 䏿£ãªæ–‡å—ã§ã™ <%s>" msgid "For option %s" msgstr "オプション: %s" -#: ../option.c:3862 msgid "E529: Cannot set 'term' to empty string" msgstr "E529: 'term' ã«ã¯ç©ºæ–‡å—列をè¨å®šã§ãã¾ã›ã‚“" -#: ../option.c:3885 +msgid "E530: Cannot change term in GUI" +msgstr "E530: GUIã§ã¯ 'term' を変更ã§ãã¾ã›ã‚“" + +msgid "E531: Use \":gui\" to start the GUI" +msgstr "E531: GUIをスタートã™ã‚‹ã«ã¯ \":gui\" を使用ã—ã¦ãã ã•ã„" + msgid "E589: 'backupext' and 'patchmode' are equal" msgstr "E589: 'backupext' 㨠'patchmode' ãŒåŒã˜ã§ã™" -#: ../option.c:3964 msgid "E834: Conflicts with value of 'listchars'" msgstr "E834: 'listchars'ã®å€¤ã«çŸ›ç›¾ãŒã‚りã¾ã™" -#: ../option.c:3966 msgid "E835: Conflicts with value of 'fillchars'" msgstr "E835: 'fillchars'ã®å€¤ã«çŸ›ç›¾ãŒã‚りã¾ã™" -#: ../option.c:4163 +msgid "E617: Cannot be changed in the GTK+ 2 GUI" +msgstr "E617: GTK+2 GUIã§ã¯å¤‰æ›´ã§ãã¾ã›ã‚“" + msgid "E524: Missing colon" msgstr "E524: コãƒãƒ³ãŒã‚りã¾ã›ã‚“" -#: ../option.c:4165 msgid "E525: Zero length string" msgstr "E525: æ–‡å—列ã®é•·ã•ãŒã‚¼ãƒã§ã™" -#: ../option.c:4220 #, c-format msgid "E526: Missing number after <%s>" msgstr "E526: <%s> ã®å¾Œã«æ•°å—ãŒã‚りã¾ã›ã‚“" -#: ../option.c:4232 msgid "E527: Missing comma" msgstr "E527: カンマãŒã‚りã¾ã›ã‚“" -#: ../option.c:4239 msgid "E528: Must specify a ' value" msgstr "E528: ' ã®å€¤ã‚’指定ã—ãªã‘れã°ãªã‚Šã¾ã›ã‚“" -#: ../option.c:4271 msgid "E595: contains unprintable or wide character" msgstr "E595: 表示ã§ããªã„æ–‡å—ã‹ãƒ¯ã‚¤ãƒ‰æ–‡å—ã‚’å«ã‚“ã§ã„ã¾ã™" -#: ../option.c:4469 +msgid "E596: Invalid font(s)" +msgstr "E596: 無効ãªãƒ•ォントã§ã™" + +msgid "E597: can't select fontset" +msgstr "E597: ãƒ•ã‚©ãƒ³ãƒˆã‚»ãƒƒãƒˆã‚’é¸æŠžã§ãã¾ã›ã‚“" + +msgid "E598: Invalid fontset" +msgstr "E598: 無効ãªãƒ•ォントセットã§ã™" + +msgid "E533: can't select wide font" +msgstr "E533: ãƒ¯ã‚¤ãƒ‰ãƒ•ã‚©ãƒ³ãƒˆã‚’é¸æŠžã§ãã¾ã›ã‚“" + +msgid "E534: Invalid wide font" +msgstr "E534: 無効ãªãƒ¯ã‚¤ãƒ‰ãƒ•ォントã§ã™" + #, c-format msgid "E535: Illegal character after <%c>" msgstr "E535: <%c> ã®å¾Œã«ä¸æ£ãªæ–‡å—ãŒã‚りã¾ã™" -#: ../option.c:4534 msgid "E536: comma required" msgstr "E536: カンマãŒå¿…è¦ã§ã™" -#: ../option.c:4543 #, c-format msgid "E537: 'commentstring' must be empty or contain %s" msgstr "E537: 'commentstring' ã¯ç©ºã§ã‚ã‚‹ã‹ %s ã‚’å«ã‚€å¿…è¦ãŒã‚りã¾ã™" -#: ../option.c:4928 +msgid "E538: No mouse support" +msgstr "E538: マウスã¯ã‚µãƒãƒ¼ãƒˆã•れã¾ã›ã‚“" + msgid "E540: Unclosed expression sequence" msgstr "E540: å¼ãŒçµ‚了ã—ã¦ã„ã¾ã›ã‚“" -#: ../option.c:4932 msgid "E541: too many items" msgstr "E541: è¦ç´ ãŒå¤šéŽãŽã¾ã™" -#: ../option.c:4934 msgid "E542: unbalanced groups" msgstr "E542: グループãŒé‡£åˆã„ã¾ã›ã‚“" -#: ../option.c:5148 msgid "E590: A preview window already exists" msgstr "E590: ãƒ—ãƒ¬ãƒ“ãƒ¥ãƒ¼ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãŒæ—¢ã«å˜åœ¨ã—ã¾ã™" -#: ../option.c:5311 msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'" msgstr "" "W17: アラビア文å—ã«ã¯UTF-8ãŒå¿…è¦ãªã®ã§, ':set encoding=utf-8' ã—ã¦ãã ã•ã„" -#: ../option.c:5623 #, c-format msgid "E593: Need at least %d lines" msgstr "E593: 最低 %d ã®è¡Œæ•°ãŒå¿…è¦ã§ã™" -#: ../option.c:5631 #, c-format msgid "E594: Need at least %d columns" msgstr "E594: 最低 %d ã®ã‚«ãƒ©ãƒ å¹…ãŒå¿…è¦ã§ã™" -#: ../option.c:6011 #, c-format msgid "E355: Unknown option: %s" msgstr "E355: 未知ã®ã‚ªãƒ—ションã§ã™: %s" @@ -4689,12 +4319,10 @@ msgstr "E355: 未知ã®ã‚ªãƒ—ションã§ã™: %s" #. 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. -#: ../option.c:6037 #, c-format msgid "E521: Number required: &%s = '%s'" msgstr "E521: æ•°å—ãŒå¿…è¦ã§ã™: &%s = '%s'" -#: ../option.c:6149 msgid "" "\n" "--- Terminal codes ---" @@ -4702,7 +4330,6 @@ msgstr "" "\n" "--- 端末コード ---" -#: ../option.c:6151 msgid "" "\n" "--- Global option values ---" @@ -4710,7 +4337,6 @@ msgstr "" "\n" "--- ã‚°ãƒãƒ¼ãƒãƒ«ã‚ªãƒ—ション値 ---" -#: ../option.c:6153 msgid "" "\n" "--- Local option values ---" @@ -4718,7 +4344,6 @@ msgstr "" "\n" "--- ãƒãƒ¼ã‚«ãƒ«ã‚ªãƒ—ション値 ---" -#: ../option.c:6155 msgid "" "\n" "--- Options ---" @@ -4726,37 +4351,119 @@ msgstr "" "\n" "--- オプション ---" -#: ../option.c:6816 msgid "E356: get_varp ERROR" msgstr "E356: get_varp エラー" -#: ../option.c:7696 #, c-format msgid "E357: 'langmap': Matching character missing for %s" msgstr "E357: 'langmap': %s ã«å¯¾å¿œã™ã‚‹æ–‡å—ãŒã‚りã¾ã›ã‚“" -#: ../option.c:7715 #, c-format msgid "E358: 'langmap': Extra characters after semicolon: %s" msgstr "E358: 'langmap': セミコãƒãƒ³ã®å¾Œã«ä½™åˆ†ãªæ–‡å—ãŒã‚りã¾ã™: %s" -#: ../os/shell.c:194 -msgid "" -"\n" -"Cannot execute shell " -msgstr "" -"\n" -"シェルを実行ã§ãã¾ã›ã‚“ " +msgid "cannot open " +msgstr "é–‹ã‘ã¾ã›ã‚“ " + +msgid "VIM: Can't open window!\n" +msgstr "VIM: ウィンドウを開ã‘ã¾ã›ã‚“!\n" + +msgid "Need Amigados version 2.04 or later\n" +msgstr "Amigadosã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 2.04ã‹ãれ以é™ãŒå¿…è¦ã§ã™\n" + +#, c-format +msgid "Need %s version %ld\n" +msgstr "%s ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ %ld ãŒå¿…è¦ã§ã™\n" + +msgid "Cannot open NIL:\n" +msgstr "NILã‚’é–‹ã‘ã¾ã›ã‚“:\n" + +msgid "Cannot create " +msgstr "作æˆã§ãã¾ã›ã‚“ " + +#, c-format +msgid "Vim exiting with %d\n" +msgstr "Vim㯠%d ã§çµ‚了ã—ã¾ã™\n" + +msgid "cannot change console mode ?!\n" +msgstr "コンソールモードを変更ã§ãã¾ã›ã‚“?!\n" + +msgid "mch_get_shellsize: not a console??\n" +msgstr "mch_get_shellsize: コンソールã§ã¯ãªã„??\n" + +#. if Vim opened a window: Executing a shell may cause crashes +msgid "E360: Cannot execute shell with -f option" +msgstr "E360: -f オプションã§ã‚·ã‚§ãƒ«ã‚’実行ã§ãã¾ã›ã‚“" + +msgid "Cannot execute " +msgstr "実行ã§ãã¾ã›ã‚“ " + +msgid "shell " +msgstr "シェル " + +msgid " returned\n" +msgstr " 戻りã¾ã—ãŸ\n" + +msgid "ANCHOR_BUF_SIZE too small." +msgstr "ANCHOR_BUF_SIZE ãŒå°ã•éŽãŽã¾ã™." + +msgid "I/O ERROR" +msgstr "入出力エラー" + +msgid "Message" +msgstr "メッセージ" + +msgid "'columns' is not 80, cannot execute external commands" +msgstr "'columns' ㌠80 ã§ã¯ãªã„ãŸã‚ã€å¤–部コマンドを実行ã§ãã¾ã›ã‚“" + +msgid "E237: Printer selection failed" +msgstr "E237: プリンタã®é¸æŠžã«å¤±æ•—ã—ã¾ã—ãŸ" + +#, c-format +msgid "to %s on %s" +msgstr "%s 㸠(%s 上ã®)" + +#, c-format +msgid "E613: Unknown printer font: %s" +msgstr "E613: 未知ã®ãƒ—リンタオプションã§ã™: %s" + +#, c-format +msgid "E238: Print error: %s" +msgstr "E238: å°åˆ·ã‚¨ãƒ©ãƒ¼: %s" + +#, c-format +msgid "Printing '%s'" +msgstr "å°åˆ·ã—ã¦ã„ã¾ã™: '%s'" + +#, c-format +msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" +msgstr "E244: æ–‡å—セットå \"%s\" ã¯ä¸æ£ã§ã™ (フォントå \"%s\")" + +#, c-format +msgid "E244: Illegal quality name \"%s\" in font name \"%s\"" +msgstr "E244: å“質å \"%s\" ã¯ä¸æ£ã§ã™ (フォントå \"%s\")" + +#, c-format +msgid "E245: Illegal char '%c' in font name \"%s\"" +msgstr "E245: '%c' ã¯ä¸æ£ãªæ–‡å—ã§ã™ (フォントå \"%s\")" + +#, c-format +msgid "Opening the X display took %ld msec" +msgstr "Xサーãƒãƒ¼ã¸ã®æŽ¥ç¶šã« %ld ミリ秒ã‹ã‹ã‚Šã¾ã—ãŸ" -#: ../os/shell.c:439 msgid "" "\n" -"shell returned " +"Vim: Got X error\n" msgstr "" "\n" -"シェルãŒå€¤ã‚’è¿”ã—ã¾ã—㟠" +"Vim: X ã®ã‚¨ãƒ©ãƒ¼ã‚’検出ã—ã¾ã—ãŸr\n" + +msgid "Testing the X display failed" +msgstr "X display ã®ãƒã‚§ãƒƒã‚¯ã«å¤±æ•—ã—ã¾ã—ãŸ" + +msgid "Opening the X display timed out" +msgstr "X display ã® open ãŒã‚¿ã‚¤ãƒ アウトã—ã¾ã—ãŸ" -#: ../os_unix.c:465 ../os_unix.c:471 msgid "" "\n" "Could not get security context for " @@ -4764,7 +4471,6 @@ msgstr "" "\n" "ã‚»ã‚ュリティコンテã‚ストをå–å¾—ã§ãã¾ã›ã‚“ " -#: ../os_unix.c:479 msgid "" "\n" "Could not set security context for " @@ -4780,223 +4486,293 @@ msgstr "ã‚»ã‚ュリティコンテã‚スト %s ã‚’ %s ã«è¨å®šã§ãã¾ã›ã‚“" msgid "Could not get security context %s for %s. Removing it!" msgstr "ã‚»ã‚ュリティコンテã‚スト %s ã‚’ %s ã‹ã‚‰å–å¾—ã§ãã¾ã›ã‚“. 削除ã—ã¾ã™!" -#: ../os_unix.c:1558 ../os_unix.c:1647 +msgid "" +"\n" +"Cannot execute shell sh\n" +msgstr "" +"\n" +"sh シェルを実行ã§ãã¾ã›ã‚“\n" + +msgid "" +"\n" +"shell returned " +msgstr "" +"\n" +"シェルãŒå€¤ã‚’è¿”ã—ã¾ã—㟠" + +msgid "" +"\n" +"Cannot create pipes\n" +msgstr "" +"\n" +"パイプを作æˆã§ãã¾ã›ã‚“\n" + +msgid "" +"\n" +"Cannot fork\n" +msgstr "" +"\n" +"fork ã§ãã¾ã›ã‚“\n" + +msgid "" +"\n" +"Cannot execute shell " +msgstr "" +"\n" +"シェルを実行ã§ãã¾ã›ã‚“ " + +msgid "" +"\n" +"Command terminated\n" +msgstr "" +"\n" +"ã‚³ãƒžãƒ³ãƒ‰ã‚’ä¸æ–ã—ã¾ã—ãŸ\n" + +msgid "XSMP lost ICE connection" +msgstr "XSMP ãŒICE接続を失ã„ã¾ã—ãŸ" + #, c-format msgid "dlerror = \"%s\"" msgstr "dlerror = \"%s\"" -#: ../path.c:1449 +msgid "Opening the X display failed" +msgstr "X display ã® open ã«å¤±æ•—ã—ã¾ã—ãŸ" + +msgid "XSMP handling save-yourself request" +msgstr "XSMP ãŒsave-yourselfè¦æ±‚を処ç†ã—ã¦ã„ã¾ã™" + +msgid "XSMP opening connection" +msgstr "XSMP ãŒæŽ¥ç¶šã‚’é–‹å§‹ã—ã¦ã„ã¾ã™" + +msgid "XSMP ICE connection watch failed" +msgstr "XSMP ICE接続ãŒå¤±æ•—ã—ãŸã‚ˆã†ã§ã™" + #, c-format -msgid "E447: Can't find file \"%s\" in path" -msgstr "E447: pathã«ã¯ \"%s\" ã¨ã„ã†ãƒ•ァイルãŒã‚りã¾ã›ã‚“" +msgid "XSMP SmcOpenConnection failed: %s" +msgstr "XSMP SmcOpenConnectionãŒå¤±æ•—ã—ã¾ã—ãŸ: %s" + +msgid "At line" +msgstr "行" + +msgid "Could not load vim32.dll!" +msgstr "vim32.dll ã‚’ãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§ã—ãŸ" + +msgid "VIM Error" +msgstr "VIMエラー" + +msgid "Could not fix up function pointers to the DLL!" +msgstr "DLLã‹ã‚‰é–¢æ•°ãƒã‚¤ãƒ³ã‚¿ã‚’å–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸ" + +#, c-format +msgid "Vim: Caught %s event\n" +msgstr "Vim: イベント %s を検知\n" + +msgid "close" +msgstr "é–‰ã˜ã‚‹" + +msgid "logoff" +msgstr "ãƒã‚°ã‚ªãƒ•" + +msgid "shutdown" +msgstr "シャットダウン" + +msgid "E371: Command not found" +msgstr "E371: コマンドãŒã‚りã¾ã›ã‚“" + +msgid "" +"VIMRUN.EXE not found in your $PATH.\n" +"External commands will not pause after completion.\n" +"See :help win32-vimrun for more information." +msgstr "" +"VIMRUN.EXE㌠$PATH ã®ä¸ã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“.\n" +"外部コマンドã®çµ‚了後ã«ä¸€æ™‚åœæ¢ã‚’ã—ã¾ã›ã‚“.\n" +"詳細㯠:help win32-vimrun ã‚’å‚ç…§ã—ã¦ãã ã•ã„." + +msgid "Vim Warning" +msgstr "Vimã®è¦å‘Š" + +#, c-format +msgid "shell returned %d" +msgstr "シェルãŒã‚³ãƒ¼ãƒ‰ %d ã§çµ‚了ã—ã¾ã—ãŸ" -#: ../quickfix.c:359 #, c-format msgid "E372: Too many %%%c in format string" msgstr "E372: フォーマット文å—列㫠%%%c ãŒå¤šéŽãŽã¾ã™" -#: ../quickfix.c:371 #, c-format msgid "E373: Unexpected %%%c in format string" msgstr "E373: フォーマット文å—列ã«äºˆæœŸã›ã¬ %%%c ãŒã‚りã¾ã—ãŸ" -#: ../quickfix.c:420 msgid "E374: Missing ] in format string" msgstr "E374: フォーマット文å—列㫠] ãŒã‚りã¾ã›ã‚“" -#: ../quickfix.c:431 #, c-format msgid "E375: Unsupported %%%c in format string" msgstr "E375: フォーマット文å—列ã§ã¯ %%%c ã¯ã‚µãƒãƒ¼ãƒˆã•れã¾ã›ã‚“" -#: ../quickfix.c:448 #, c-format msgid "E376: Invalid %%%c in format string prefix" msgstr "E376: フォーマット文å—列ã®å‰ç½®ã«ç„¡åŠ¹ãª %%%c ãŒã‚りã¾ã™" -#: ../quickfix.c:454 #, c-format msgid "E377: Invalid %%%c in format string" msgstr "E377: フォーマット文å—列ã«ç„¡åŠ¹ãª %%%c ãŒã‚りã¾ã™" #. nothing found -#: ../quickfix.c:477 msgid "E378: 'errorformat' contains no pattern" msgstr "E378: 'errorformat' ã«ãƒ‘ã‚¿ãƒ¼ãƒ³ãŒæŒ‡å®šã•れã¦ã„ã¾ã›ã‚“" -#: ../quickfix.c:695 msgid "E379: Missing or empty directory name" msgstr "E379: ディレクトリåãŒç„¡ã„ã‹ç©ºã§ã™" -#: ../quickfix.c:1305 msgid "E553: No more items" msgstr "E553: è¦ç´ ãŒã‚‚ã†ã‚りã¾ã›ã‚“" -#: ../quickfix.c:1674 +msgid "E924: Current window was closed" +msgstr "E924: ç¾åœ¨ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãŒé–‰ã˜ã‚‰ã‚Œã¾ã—ãŸ" + +msgid "E925: Current quickfix was changed" +msgstr "E925: ç¾åœ¨ã® quickfix ãŒå¤‰æ›´ã•れã¾ã—ãŸ" + +msgid "E926: Current location list was changed" +msgstr "E926: ç¾åœ¨ã®ãƒã‚±ãƒ¼ã‚·ãƒ§ãƒ³ãƒªã‚¹ãƒˆãŒå¤‰æ›´ã•れã¾ã—ãŸ" + #, c-format msgid "(%d of %d)%s%s: " msgstr "(%d of %d)%s%s: " -#: ../quickfix.c:1676 msgid " (line deleted)" msgstr " (行ãŒå‰Šé™¤ã•れã¾ã—ãŸ)" -#: ../quickfix.c:1863 +#, c-format +msgid "%serror list %d of %d; %d errors " +msgstr "%s エラー一覧 %d of %d; %d 個エラー" + msgid "E380: At bottom of quickfix stack" msgstr "E380: quickfix ã‚¹ã‚¿ãƒƒã‚¯ã®æœ«å°¾ã§ã™" -#: ../quickfix.c:1869 msgid "E381: At top of quickfix stack" msgstr "E381: quickfix スタックã®å…ˆé ã§ã™" -#: ../quickfix.c:1880 -#, c-format -msgid "error list %d of %d; %d errors" -msgstr "エラー一覧 %d of %d; %d 個エラー" +msgid "No entries" +msgstr "エントリãŒã‚りã¾ã›ã‚“" -#: ../quickfix.c:2427 msgid "E382: Cannot write, 'buftype' option is set" msgstr "E382: 'buftype' オプションãŒè¨å®šã•れã¦ã„ã‚‹ã®ã§æ›¸è¾¼ã¿ã¾ã›ã‚“" -#: ../quickfix.c:2812 +msgid "Error file" +msgstr "エラーファイル" + msgid "E683: File name missing or invalid pattern" msgstr "E683: ファイルåãŒç„¡ã„ã‹ç„¡åйãªãƒ‘ターンã§ã™" -#: ../quickfix.c:2911 #, c-format msgid "Cannot open file \"%s\"" msgstr "ファイル \"%s\" ã‚’é–‹ã‘ã¾ã›ã‚“" -#: ../quickfix.c:3429 msgid "E681: Buffer is not loaded" msgstr "E681: ãƒãƒƒãƒ•ã‚¡ã¯èªã¿è¾¼ã¾ã‚Œã¾ã›ã‚“ã§ã—ãŸ" -#: ../quickfix.c:3487 msgid "E777: String or List expected" msgstr "E777: æ–‡å—列ã‹ãƒªã‚¹ãƒˆãŒå¿…è¦ã§ã™" -#: ../regexp.c:359 #, c-format msgid "E369: invalid item in %s%%[]" msgstr "E369: 無効ãªé …ç›®ã§ã™: %s%%[]" # -#: ../regexp.c:374 #, c-format msgid "E769: Missing ] after %s[" msgstr "E769: %s[ ã®å¾Œã« ] ãŒã‚りã¾ã›ã‚“" -#: ../regexp.c:375 #, c-format msgid "E53: Unmatched %s%%(" msgstr "E53: %s%%( ãŒé‡£ã‚Šåˆã£ã¦ã„ã¾ã›ã‚“" -#: ../regexp.c:376 #, c-format msgid "E54: Unmatched %s(" msgstr "E54: %s( ãŒé‡£ã‚Šåˆã£ã¦ã„ã¾ã›ã‚“" -#: ../regexp.c:377 #, c-format msgid "E55: Unmatched %s)" msgstr "E55: %s) ãŒé‡£ã‚Šåˆã£ã¦ã„ã¾ã›ã‚“" # -#: ../regexp.c:378 msgid "E66: \\z( not allowed here" msgstr "E66: \\z( ã¯ã‚³ã‚³ã§ã¯è¨±å¯ã•れã¦ã„ã¾ã›ã‚“" # -#: ../regexp.c:379 msgid "E67: \\z1 et al. not allowed here" msgstr "E67: \\z1 ãã®ä»–ã¯ã‚³ã‚³ã§ã¯è¨±å¯ã•れã¦ã„ã¾ã›ã‚“" # -#: ../regexp.c:380 #, c-format msgid "E69: Missing ] after %s%%[" msgstr "E69: %s%%[ ã®å¾Œã« ] ãŒã‚りã¾ã›ã‚“" -#: ../regexp.c:381 #, c-format msgid "E70: Empty %s%%[]" msgstr "E70: %s%%[] ãŒç©ºã§ã™" -#: ../regexp.c:1209 ../regexp.c:1224 msgid "E339: Pattern too long" msgstr "E339: パターンãŒé•·éŽãŽã¾ã™" -#: ../regexp.c:1371 msgid "E50: Too many \\z(" msgstr "E50: \\z( ãŒå¤šéŽãŽã¾ã™" -#: ../regexp.c:1378 #, c-format msgid "E51: Too many %s(" msgstr "E51: %s( ãŒå¤šéŽãŽã¾ã™" -#: ../regexp.c:1427 msgid "E52: Unmatched \\z(" msgstr "E52: \\z( ãŒé‡£ã‚Šåˆã£ã¦ã„ã¾ã›ã‚“" -#: ../regexp.c:1637 #, c-format msgid "E59: invalid character after %s@" msgstr "E59: %s@ ã®å¾Œã«ä¸æ£ãªæ–‡å—ãŒã‚りã¾ã—ãŸ" -#: ../regexp.c:1672 #, c-format msgid "E60: Too many complex %s{...}s" msgstr "E60: 複雑㪠%s{...} ãŒå¤šéŽãŽã¾ã™" -#: ../regexp.c:1687 #, c-format msgid "E61: Nested %s*" msgstr "E61:%s* ãŒå…¥ã‚Œåã«ãªã£ã¦ã„ã¾ã™" -#: ../regexp.c:1690 #, c-format msgid "E62: Nested %s%c" msgstr "E62:%s%c ãŒå…¥ã‚Œåã«ãªã£ã¦ã„ã¾ã™" # -#: ../regexp.c:1800 msgid "E63: invalid use of \\_" msgstr "E63: \\_ ã®ç„¡åйãªä½¿ç”¨æ–¹æ³•ã§ã™" -#: ../regexp.c:1850 #, c-format msgid "E64: %s%c follows nothing" msgstr "E64:%s%c ã®å¾Œã«ãªã«ã‚‚ã‚りã¾ã›ã‚“" # -#: ../regexp.c:1902 msgid "E65: Illegal back reference" msgstr "E65: 䏿£ãªå¾Œæ–¹å‚ç…§ã§ã™" # -#: ../regexp.c:1943 msgid "E68: Invalid character after \\z" msgstr "E68: \\z ã®å¾Œã«ä¸æ£ãªæ–‡å—ãŒã‚りã¾ã—ãŸ" # -#: ../regexp.c:2049 ../regexp_nfa.c:1296 #, c-format msgid "E678: Invalid character after %s%%[dxouU]" msgstr "E678: %s%%[dxouU] ã®å¾Œã«ä¸æ£ãªæ–‡å—ãŒã‚りã¾ã—ãŸ" # -#: ../regexp.c:2107 #, c-format msgid "E71: Invalid character after %s%%" msgstr "E71: %s%% ã®å¾Œã«ä¸æ£ãªæ–‡å—ãŒã‚りã¾ã—ãŸ" -#: ../regexp.c:3017 #, c-format msgid "E554: Syntax error in %s{...}" msgstr "E554: %s{...} å†…ã«æ–‡æ³•エラーãŒã‚りã¾ã™" -#: ../regexp.c:3805 msgid "External submatches:\n" msgstr "外部ã®éƒ¨åˆ†è©²å½“:\n" @@ -5004,7 +4780,6 @@ msgstr "外部ã®éƒ¨åˆ†è©²å½“:\n" msgid "E888: (NFA regexp) cannot repeat %s" msgstr "E888: (NFA æ£è¦è¡¨ç¾) 繰り返ã›ã¾ã›ã‚“ %s" -#: ../regexp.c:7022 msgid "" "E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be " "used " @@ -5015,62 +4790,54 @@ msgstr "" msgid "Switching to backtracking RE engine for pattern: " msgstr "次ã®ãƒ‘ターンã«ãƒãƒƒã‚¯ãƒˆãƒ©ãƒƒã‚ング RE エンジンをé©ç”¨ã—ã¾ã™: " -#: ../regexp_nfa.c:239 msgid "E865: (NFA) Regexp end encountered prematurely" msgstr "E865: (NFA) æœŸå¾…ã‚ˆã‚Šæ—©ãæ£è¦è¡¨ç¾ã®çµ‚端ã«åˆ°é”ã—ã¾ã—ãŸ" -#: ../regexp_nfa.c:240 #, c-format msgid "E866: (NFA regexp) Misplaced %c" msgstr "E866: (NFA æ£è¦è¡¨ç¾) ä½ç½®ãŒèª¤ã£ã¦ã„ã¾ã™: %c" -#: ../regexp_nfa.c:242 +# #, c-format -msgid "E877: (NFA regexp) Invalid character class: %<PRId64>" -msgstr "E877: (NFA æ£è¦è¡¨ç¾) ç„¡åŠ¹ãªæ–‡å—クラス: %<PRId64>" +msgid "E877: (NFA regexp) Invalid character class: %ld" +msgstr "E877: (NFA æ£è¦è¡¨ç¾) ç„¡åŠ¹ãªæ–‡å—クラス: %ld" -#: ../regexp_nfa.c:1261 #, c-format msgid "E867: (NFA) Unknown operator '\\z%c'" msgstr "E867: (NFA) 未知ã®ã‚ªãƒšãƒ¬ãƒ¼ã‚¿ã§ã™: '\\z%c'" -#: ../regexp_nfa.c:1387 #, c-format msgid "E867: (NFA) Unknown operator '\\%%%c'" msgstr "E867: (NFA) 未知ã®ã‚ªãƒšãƒ¬ãƒ¼ã‚¿ã§ã™: '\\%%%c'" -#: ../regexp_nfa.c:1802 +#. should never happen +msgid "E868: Error building NFA with equivalence class!" +msgstr "E868: ç‰ä¾¡ã‚¯ãƒ©ã‚¹ã‚’å«ã‚€NFA構築ã«å¤±æ•—ã—ã¾ã—ãŸ!" + #, c-format msgid "E869: (NFA) Unknown operator '\\@%c'" msgstr "E869: (NFA) 未知ã®ã‚ªãƒšãƒ¬ãƒ¼ã‚¿ã§ã™: '\\@%c'" -#: ../regexp_nfa.c:1831 msgid "E870: (NFA regexp) Error reading repetition limits" msgstr "E870: (NFA æ£è¦è¡¨ç¾) 繰り返ã—ã®åˆ¶é™å›žæ•°ã‚’èªè¾¼ä¸ã«ã‚¨ãƒ©ãƒ¼" #. Can't have a multi follow a multi. -#: ../regexp_nfa.c:1895 msgid "E871: (NFA regexp) Can't have a multi follow a multi !" msgstr "E871: (NFA æ£è¦è¡¨ç¾) 繰り返㗠ã®å¾Œã« 繰り返㗠ã¯ã§ãã¾ã›ã‚“!" #. Too many `(' -#: ../regexp_nfa.c:2037 msgid "E872: (NFA regexp) Too many '('" msgstr "E872: (NFA æ£è¦è¡¨ç¾) '(' ãŒå¤šéŽãŽã¾ã™" -#: ../regexp_nfa.c:2042 msgid "E879: (NFA regexp) Too many \\z(" msgstr "E879: (NFA æ£è¦è¡¨ç¾) \\z( ãŒå¤šéŽãŽã¾ã™" -#: ../regexp_nfa.c:2066 msgid "E873: (NFA regexp) proper termination error" msgstr "E873: (NFA æ£è¦è¡¨ç¾) 終端記å·ãŒã‚りã¾ã›ã‚“" -#: ../regexp_nfa.c:2599 msgid "E874: (NFA) Could not pop the stack !" msgstr "E874: (NFA) スタックをãƒãƒƒãƒ—ã§ãã¾ã›ã‚“!" -#: ../regexp_nfa.c:3298 msgid "" "E875: (NFA regexp) (While converting from postfix to NFA), too many states " "left on stack" @@ -5078,177 +4845,136 @@ msgstr "" "E875: (NFA æ£è¦è¡¨ç¾) (後置文å—列をNFAã«å¤‰æ›ä¸ã«) ã‚¹ã‚¿ãƒƒã‚¯ã«æ®‹ã•れãŸã‚¹ãƒ†ãƒ¼ãƒˆãŒ" "多éŽãŽã¾ã™" -#: ../regexp_nfa.c:3302 msgid "E876: (NFA regexp) Not enough space to store the whole NFA " msgstr "E876: (NFA æ£è¦è¡¨ç¾) NFA全体をä¿å˜ã™ã‚‹ã«ã¯ç©ºãスペースãŒè¶³ã‚Šã¾ã›ã‚“" -#: ../regexp_nfa.c:4571 ../regexp_nfa.c:4869 +msgid "E878: (NFA) Could not allocate memory for branch traversal!" +msgstr "E878: (NFA) ç¾åœ¨æ¨ªæ–ä¸ã®ãƒ–ランãƒã«å分ãªãƒ¡ãƒ¢ãƒªã‚’割り当ã¦ã‚‰ã‚Œã¾ã›ã‚“!" + msgid "" "Could not open temporary log file for writing, displaying on stderr ... " msgstr "" "NFAæ£è¦è¡¨ç¾ã‚¨ãƒ³ã‚¸ãƒ³ç”¨ã®ãƒã‚°ãƒ•ァイルを書込用ã¨ã—ã¦é–‹ã‘ã¾ã›ã‚“。ãƒã‚°ã¯æ¨™æº–出力ã«" "出力ã—ã¾ã™ã€‚" -#: ../regexp_nfa.c:4840 #, c-format msgid "(NFA) COULD NOT OPEN %s !" msgstr "(NFA) ãƒã‚°ãƒ•ァイル %s ã‚’é–‹ã‘ã¾ã›ã‚“!" -#: ../regexp_nfa.c:6049 msgid "Could not open temporary log file for writing " msgstr "NFAæ£è¦è¡¨ç¾ã‚¨ãƒ³ã‚¸ãƒ³ç”¨ã®ãƒã‚°ãƒ•ァイルを書込用ã¨ã—ã¦é–‹ã‘ã¾ã›ã‚“。" -#: ../screen.c:7435 msgid " VREPLACE" msgstr " 仮想置æ›" -#: ../screen.c:7437 msgid " REPLACE" msgstr " ç½®æ›" -#: ../screen.c:7440 msgid " REVERSE" msgstr " å転" -#: ../screen.c:7441 msgid " INSERT" msgstr " 挿入" -#: ../screen.c:7443 msgid " (insert)" msgstr " (挿入)" -#: ../screen.c:7445 msgid " (replace)" msgstr " (ç½®æ›)" -#: ../screen.c:7447 msgid " (vreplace)" msgstr " (仮想置æ›)" -#: ../screen.c:7449 msgid " Hebrew" msgstr " ヘブライ" -#: ../screen.c:7454 msgid " Arabic" msgstr " アラビア" -#: ../screen.c:7456 -msgid " (lang)" -msgstr " (言語)" - -#: ../screen.c:7459 msgid " (paste)" msgstr " (貼り付ã‘)" -#: ../screen.c:7469 msgid " VISUAL" msgstr " ビジュアル" -#: ../screen.c:7470 msgid " VISUAL LINE" msgstr " ビジュアル 行" -#: ../screen.c:7471 msgid " VISUAL BLOCK" msgstr " ビジュアル 矩形" -#: ../screen.c:7472 msgid " SELECT" msgstr " セレクト" -#: ../screen.c:7473 msgid " SELECT LINE" msgstr " 行指å‘é¸æŠž" -#: ../screen.c:7474 msgid " SELECT BLOCK" msgstr " çŸ©å½¢é¸æŠž" -#: ../screen.c:7486 ../screen.c:7541 msgid "recording" msgstr "記録ä¸" -#: ../search.c:487 #, c-format msgid "E383: Invalid search string: %s" msgstr "E383: ç„¡åŠ¹ãªæ¤œç´¢æ–‡å—列ã§ã™: %s" -#: ../search.c:832 #, c-format msgid "E384: search hit TOP without match for: %s" msgstr "E384: 上ã¾ã§æ¤œç´¢ã—ã¾ã—ãŸãŒè©²å½“箇所ã¯ã‚りã¾ã›ã‚“: %s" -#: ../search.c:835 #, c-format msgid "E385: search hit BOTTOM without match for: %s" msgstr "E385: 下ã¾ã§æ¤œç´¢ã—ã¾ã—ãŸãŒè©²å½“箇所ã¯ã‚りã¾ã›ã‚“: %s" -#: ../search.c:1200 msgid "E386: Expected '?' or '/' after ';'" msgstr "E386: ';' ã®ã‚ã¨ã«ã¯ '?' ã‹ '/' ãŒæœŸå¾…ã•れã¦ã„ã‚‹" -#: ../search.c:4085 msgid " (includes previously listed match)" msgstr " (å‰ã«åˆ—挙ã—ãŸè©²å½“箇所をå«ã‚€)" #. cursor at status line -#: ../search.c:4104 msgid "--- Included files " msgstr "--- インクルードã•れãŸãƒ•ァイル " -#: ../search.c:4106 msgid "not found " msgstr "見ã¤ã‹ã‚Šã¾ã›ã‚“ " -#: ../search.c:4107 msgid "in path ---\n" msgstr "パス㫠----\n" -#: ../search.c:4168 msgid " (Already listed)" msgstr " (æ—¢ã«åˆ—挙)" -#: ../search.c:4170 msgid " NOT FOUND" msgstr " 見ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../search.c:4211 #, c-format msgid "Scanning included file: %s" msgstr "インクルードã•れãŸãƒ•ァイルをスã‚ャンä¸: %s" -#: ../search.c:4216 #, c-format msgid "Searching included file %s" msgstr "インクルードã•れãŸãƒ•ァイルをスã‚ãƒ£ãƒ³ä¸ %s" -#: ../search.c:4405 msgid "E387: Match is on current line" msgstr "E387: ç¾åœ¨è¡Œã«è©²å½“ãŒã‚りã¾ã™" -#: ../search.c:4517 msgid "All included files were found" msgstr "å…¨ã¦ã®ã‚¤ãƒ³ã‚¯ãƒ«ãƒ¼ãƒ‰ã•れãŸãƒ•ァイルãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ" -#: ../search.c:4519 msgid "No included files" msgstr "インクルードファイルã¯ã‚りã¾ã›ã‚“" -#: ../search.c:4527 msgid "E388: Couldn't find definition" msgstr "E388: 定義を見ã¤ã‘られã¾ã›ã‚“" -#: ../search.c:4529 msgid "E389: Couldn't find pattern" msgstr "E389: パターンを見ã¤ã‘られã¾ã›ã‚“" -#: ../search.c:4668 msgid "Substitute " msgstr "Substitute " -#: ../search.c:4681 #, c-format msgid "" "\n" @@ -5259,99 +4985,131 @@ msgstr "" "# 最後㮠%s検索パターン:\n" "~" -#: ../spell.c:951 -msgid "E759: Format error in spell file" -msgstr "E759: ã‚¹ãƒšãƒ«ãƒ•ã‚¡ã‚¤ãƒ«ã®æ›¸å¼ã‚¨ãƒ©ãƒ¼ã§ã™" +msgid "E756: Spell checking is not enabled" +msgstr "E756: スペルãƒã‚§ãƒƒã‚¯ã¯ç„¡åŠ¹åŒ–ã•れã¦ã„ã¾ã™" + +#, c-format +msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" +msgstr "" +"è¦å‘Š: å˜èªžãƒªã‚¹ãƒˆ \"%s_%s.spl\" ãŠã‚ˆã³ \"%s_ascii.spl\" ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + +#, c-format +msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" +msgstr "" +"è¦å‘Š: å˜èªžãƒªã‚¹ãƒˆ \"%s.%s.spl\" ãŠã‚ˆã³ \"%s.ascii.spl\" ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + +msgid "E797: SpellFileMissing autocommand deleted buffer" +msgstr "E797: autocommand ã® SpellFileMissing ãŒãƒãƒƒãƒ•ァを削除ã—ã¾ã—ãŸ" + +#, c-format +msgid "Warning: region %s not supported" +msgstr "è¦å‘Š9: %s ã¨ã„ã†ç¯„囲ã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“" + +msgid "Sorry, no suggestions" +msgstr "残念ã§ã™ãŒ, ä¿®æ£å€™è£œã¯ã‚りã¾ã›ã‚“" + +#, c-format +msgid "Sorry, only %ld suggestions" +msgstr "残念ã§ã™ãŒ, ä¿®æ£å€™è£œã¯ %ld 個ã—ã‹ã‚りã¾ã›ã‚“" + +#. for when 'cmdheight' > 1 +#. avoid more prompt +#, c-format +msgid "Change \"%.*s\" to:" +msgstr "\"%.*s\" を次ã¸å¤‰æ›:" + +#, c-format +msgid " < \"%.*s\"" +msgstr " < \"%.*s\"" + +msgid "E752: No previous spell replacement" +msgstr "E752: スペル置æ›ãŒã¾ã 実行ã•れã¦ã„ã¾ã›ã‚“" + +#, c-format +msgid "E753: Not found: %s" +msgstr "E753: 見ã¤ã‹ã‚Šã¾ã›ã‚“: %s" -#: ../spell.c:952 msgid "E758: Truncated spell file" msgstr "E758: スペルファイルãŒåˆ‡å–られã¦ã„るよã†ã§ã™" -#: ../spell.c:953 #, c-format msgid "Trailing text in %s line %d: %s" msgstr "%s (%d 行目) ã«ç¶šãテã‚スト: %s" -#: ../spell.c:954 #, c-format msgid "Affix name too long in %s line %d: %s" msgstr "%s (%d 行目) ã® affix åãŒé•·éŽãŽã¾ã™: %s" -#: ../spell.c:955 msgid "E761: Format error in affix file FOL, LOW or UPP" msgstr "" "E761: affixファイル㮠FOL, LOW ã‚‚ã—ã㯠UPP ã®ãƒ•ォーマットã«ã‚¨ãƒ©ãƒ¼ãŒã‚りã¾ã™" -#: ../spell.c:957 msgid "E762: Character in FOL, LOW or UPP is out of range" msgstr "E762: FOL, LOW ã‚‚ã—ã㯠UPP ã®æ–‡å—ãŒç¯„囲外ã§ã™" -#: ../spell.c:958 msgid "Compressing word tree..." msgstr "å˜èªžãƒ„リーを圧縮ã—ã¦ã„ã¾ã™..." -#: ../spell.c:1951 -msgid "E756: Spell checking is not enabled" -msgstr "E756: スペルãƒã‚§ãƒƒã‚¯ã¯ç„¡åŠ¹åŒ–ã•れã¦ã„ã¾ã™" - -#: ../spell.c:2249 -#, c-format -msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" -msgstr "" -"è¦å‘Š: å˜èªžãƒªã‚¹ãƒˆ \"%s.%s.spl\" ãŠã‚ˆã³ \"%s.ascii.spl\" ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" - -#: ../spell.c:2473 #, c-format msgid "Reading spell file \"%s\"" msgstr "スペルファイル \"%s\" ã‚’èªè¾¼ä¸" -#: ../spell.c:2496 msgid "E757: This does not look like a spell file" msgstr "E757: スペルファイルã§ã¯ãªã„よã†ã§ã™" -#: ../spell.c:2501 msgid "E771: Old spell file, needs to be updated" msgstr "E771: å¤ã„スペルファイルãªã®ã§, アップデートã—ã¦ãã ã•ã„" -#: ../spell.c:2504 msgid "E772: Spell file is for newer version of Vim" msgstr "E772: より新ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® Vim 用ã®ã‚¹ãƒšãƒ«ãƒ•ァイルã§ã™" -#: ../spell.c:2602 msgid "E770: Unsupported section in spell file" msgstr "E770: スペルファイルã«ã‚µãƒãƒ¼ãƒˆã—ã¦ã„ãªã„セクションãŒã‚りã¾ã™" -#: ../spell.c:3762 #, c-format -msgid "Warning: region %s not supported" -msgstr "è¦å‘Š9: %s ã¨ã„ã†ç¯„囲ã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“" +msgid "E778: This does not look like a .sug file: %s" +msgstr "E778: .sug ファイルã§ã¯ãªã„よã†ã§ã™: %s" + +#, c-format +msgid "E779: Old .sug file, needs to be updated: %s" +msgstr "E779: å¤ã„ .sug ファイルãªã®ã§, アップデートã—ã¦ãã ã•ã„: %s" + +#, c-format +msgid "E780: .sug file is for newer version of Vim: %s" +msgstr "E780: より新ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® Vim 用㮠.sug ファイルã§ã™: %s" + +#, c-format +msgid "E781: .sug file doesn't match .spl file: %s" +msgstr "E781: .sug ファイル㌠.spl ファイルã¨ä¸€è‡´ã—ã¾ã›ã‚“: %s" + +#, c-format +msgid "E782: error while reading .sug file: %s" +msgstr "E782: .sug ファイルã®èªè¾¼ä¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ: %s" -#: ../spell.c:4550 #, c-format msgid "Reading affix file %s ..." msgstr "affix ファイル %s ã‚’èªè¾¼ä¸..." -#: ../spell.c:4589 ../spell.c:5635 ../spell.c:6140 #, c-format msgid "Conversion failure for word in %s line %d: %s" msgstr "%s (%d 行目) ã®å˜èªžã‚’変æ›ã§ãã¾ã›ã‚“ã§ã—ãŸ: %s" -#: ../spell.c:4630 ../spell.c:6170 #, c-format msgid "Conversion in %s not supported: from %s to %s" msgstr "%s å†…ã®æ¬¡ã®å¤‰æ›ã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“: %s ã‹ã‚‰ %s ã¸" -#: ../spell.c:4642 +#, c-format +msgid "Conversion in %s not supported" +msgstr "%s 内ã®å¤‰æ›ã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“" + #, c-format msgid "Invalid value for FLAG in %s line %d: %s" msgstr "%s 内㮠%d 行目㮠FLAG ã«ç„¡åйãªå€¤ãŒã‚りã¾ã™: %s" -#: ../spell.c:4655 #, c-format msgid "FLAG after using flags in %s line %d: %s" msgstr "%s 内㮠%d 行目ã«ãƒ•ラグã®äºŒé‡ä½¿ç”¨ãŒã‚りã¾ã™: %s" -#: ../spell.c:4723 #, c-format msgid "" "Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line " @@ -5360,7 +5118,6 @@ msgstr "" "%s ã® %d 行目㮠PFX é …ç›®ã®å¾Œã® COMPOUNDFORBIDFLAG ã®å®šç¾©ã¯èª¤ã£ãŸçµæžœã‚’生ã˜ã‚‹" "ã“ã¨ãŒã‚りã¾ã™" -#: ../spell.c:4731 #, c-format msgid "" "Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line " @@ -5369,43 +5126,35 @@ msgstr "" "%s ã® %d 行目㮠PFX é …ç›®ã®å¾Œã® COMPOUNDPERMITFLAG ã®å®šç¾©ã¯èª¤ã£ãŸçµæžœã‚’生ã˜ã‚‹" "ã“ã¨ãŒã‚りã¾ã™" -#: ../spell.c:4747 #, c-format msgid "Wrong COMPOUNDRULES value in %s line %d: %s" msgstr "COMPOUNDRULES ã®å€¤ã«èª¤ã‚ŠãŒã‚りã¾ã™. ファイル %s ã® %d 行目: %s" -#: ../spell.c:4771 #, c-format msgid "Wrong COMPOUNDWORDMAX value in %s line %d: %s" msgstr "%s ã® %d 行目㮠COMPOUNDWORDMAX ã®å€¤ã«èª¤ã‚ŠãŒã‚りã¾ã™: %s" -#: ../spell.c:4777 #, c-format msgid "Wrong COMPOUNDMIN value in %s line %d: %s" msgstr "%s ã® %d 行目㮠COMPOUNDMIN ã®å€¤ã«èª¤ã‚ŠãŒã‚りã¾ã™: %s" -#: ../spell.c:4783 #, c-format msgid "Wrong COMPOUNDSYLMAX value in %s line %d: %s" msgstr "%s ã® %d 行目㮠COMPOUNDSYLMAX ã®å€¤ã«èª¤ã‚ŠãŒã‚りã¾ã™: %s" -#: ../spell.c:4795 #, c-format msgid "Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s" msgstr "%s ã® %d 行目㮠CHECKCOMPOUNDPATTERN ã®å€¤ã«èª¤ã‚ŠãŒã‚りã¾ã™: %s" -#: ../spell.c:4847 #, c-format msgid "Different combining flag in continued affix block in %s line %d: %s" msgstr "" "%s ã® %d 行目㮠連続 affix ブãƒãƒƒã‚¯ã®ãƒ•ラグã®çµ„åˆã›ã«é•ã„ãŒã‚りã¾ã™: %s" -#: ../spell.c:4850 #, c-format msgid "Duplicate affix in %s line %d: %s" msgstr "%s ã® %d 行目㫠é‡è¤‡ã—㟠affix を検出ã—ã¾ã—ãŸ: %s" -#: ../spell.c:4871 #, c-format msgid "" "Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in %s " @@ -5414,308 +5163,206 @@ msgstr "" "%s ã® %d 行目㮠affix 㯠BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST " "ã«ä½¿ç”¨ã—ã¦ãã ã•ã„: %s" -#: ../spell.c:4893 #, c-format msgid "Expected Y or N in %s line %d: %s" msgstr "%s ã® %d 行目ã§ã¯ Y ã‹ N ãŒå¿…è¦ã§ã™: %s" -#: ../spell.c:4968 #, c-format msgid "Broken condition in %s line %d: %s" msgstr "%s ã® %d 行目㮠æ¡ä»¶ã¯å£Šã‚Œã¦ã„ã¾ã™: %s" -#: ../spell.c:5091 #, c-format msgid "Expected REP(SAL) count in %s line %d" msgstr "%s ã® %d 行目ã«ã¯ REP(SAL) ã®å›žæ•°ãŒå¿…è¦ã§ã™" -#: ../spell.c:5120 #, c-format msgid "Expected MAP count in %s line %d" msgstr "%s ã® %d 行目ã«ã¯ MAP ã®å›žæ•°ãŒå¿…è¦ã§ã™" -#: ../spell.c:5132 #, c-format msgid "Duplicate character in MAP in %s line %d" msgstr "%s ã® %d 行目㮠MAP ã«é‡è¤‡ã—ãŸæ–‡å—ãŒã‚りã¾ã™" -#: ../spell.c:5176 #, c-format msgid "Unrecognized or duplicate item in %s line %d: %s" msgstr "%s ã® %d 行目㫠èªè˜ã§ããªã„ã‹é‡è¤‡ã—ãŸé …ç›®ãŒã‚りã¾ã™: %s" -#: ../spell.c:5197 #, c-format msgid "Missing FOL/LOW/UPP line in %s" msgstr "%s 行目㫠FOL/LOW/UPP ãŒã‚りã¾ã›ã‚“" -#: ../spell.c:5220 msgid "COMPOUNDSYLMAX used without SYLLABLE" msgstr "SYLLABLE ãŒæŒ‡å®šã•れãªã„ COMPOUNDSYLMAX" -#: ../spell.c:5236 msgid "Too many postponed prefixes" msgstr "é…延後置åãŒå¤šéŽãŽã¾ã™" -#: ../spell.c:5238 msgid "Too many compound flags" msgstr "複åˆãƒ•ラグãŒå¤šéŽãŽã¾ã™" -#: ../spell.c:5240 msgid "Too many postponed prefixes and/or compound flags" msgstr "é…延後置å ã¨/ã‚‚ã—ã㯠複åˆãƒ•ラグãŒå¤šéŽãŽã¾ã™" -#: ../spell.c:5250 #, c-format msgid "Missing SOFO%s line in %s" msgstr "SOFO%s 行㌠%s ã«ã‚りã¾ã›ã‚“" -#: ../spell.c:5253 #, c-format msgid "Both SAL and SOFO lines in %s" msgstr "SAL行 㨠SOFO行 ㌠%s ã§ä¸¡æ–¹æŒ‡å®šã•れã¦ã„ã¾ã™" -#: ../spell.c:5331 #, c-format msgid "Flag is not a number in %s line %d: %s" msgstr "%s ã® %d è¡Œã® ãƒ•ãƒ©ã‚°ãŒæ•°å€¤ã§ã¯ã‚りã¾ã›ã‚“: %s" -#: ../spell.c:5334 #, c-format msgid "Illegal flag in %s line %d: %s" msgstr "%s ã® %d 行目㮠フラグãŒä¸æ£ã§ã™: %s" -#: ../spell.c:5493 ../spell.c:5501 #, c-format msgid "%s value differs from what is used in another .aff file" msgstr "値 %s ã¯ä»–ã® .aff ファイルã§ä½¿ç”¨ã•れãŸã®ã¨ç•°ãªã‚Šã¾ã™" -#: ../spell.c:5602 #, c-format msgid "Reading dictionary file %s ..." msgstr "辞書ファイル %s をスã‚ャンä¸..." -#: ../spell.c:5611 #, c-format msgid "E760: No word count in %s" msgstr "E760: %s ã«ã¯å˜èªžæ•°ãŒã‚りã¾ã›ã‚“" -#: ../spell.c:5669 #, c-format msgid "line %6d, word %6d - %s" msgstr "行 %6d, å˜èªž %6d - %s" -#: ../spell.c:5691 #, c-format msgid "Duplicate word in %s line %d: %s" msgstr "%s ã® %d 行目㧠é‡è¤‡å˜èªžãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ: %s" -#: ../spell.c:5694 #, c-format msgid "First duplicate word in %s line %d: %s" msgstr "é‡è¤‡ã®ã†ã¡æœ€åˆã®å˜èªžã¯ %s ã® %d 行目ã§ã™: %s" -#: ../spell.c:5746 #, c-format msgid "%d duplicate word(s) in %s" msgstr "%d 個ã®å˜èªžãŒè¦‹ã¤ã‹ã‚Šã¾ã—㟠(%s 内)" -#: ../spell.c:5748 #, c-format msgid "Ignored %d word(s) with non-ASCII characters in %s" msgstr "éžASCIIæ–‡å—ã‚’å«ã‚€ %d 個ã®å˜èªžã‚’無視ã—ã¾ã—㟠(%s 内)" -#: ../spell.c:6115 #, c-format msgid "Reading word file %s ..." msgstr "標準入力ã‹ã‚‰èªè¾¼ã¿ä¸ %s ..." -#: ../spell.c:6155 #, c-format msgid "Duplicate /encoding= line ignored in %s line %d: %s" msgstr "%s ã® %d 行目㮠é‡è¤‡ã—㟠/encoding= 行を無視ã—ã¾ã—ãŸ: %s" -#: ../spell.c:6159 #, c-format msgid "/encoding= line after word ignored in %s line %d: %s" msgstr "%s ã® %d 行目㮠å˜èªžã®å¾Œã® /encoding= 行を無視ã—ã¾ã—ãŸ: %s" -#: ../spell.c:6180 #, c-format msgid "Duplicate /regions= line ignored in %s line %d: %s" msgstr "%s ã® %d 行目㮠é‡è¤‡ã—㟠/regions= 行を無視ã—ã¾ã—ãŸ: %s" -#: ../spell.c:6185 #, c-format msgid "Too many regions in %s line %d: %s" msgstr "%s ã® %d 行目, 範囲指定ãŒå¤šéŽãŽã¾ã™: %s" -#: ../spell.c:6198 #, c-format msgid "/ line ignored in %s line %d: %s" msgstr "%s ã® %d 行目㮠é‡è¤‡ã—㟠/ 行を無視ã—ã¾ã—ãŸ: %s" -#: ../spell.c:6224 #, c-format msgid "Invalid region nr in %s line %d: %s" msgstr "%s ã® %d 行目 無効㪠nr é ˜åŸŸã§ã™: %s" -#: ../spell.c:6230 #, c-format msgid "Unrecognized flags in %s line %d: %s" msgstr "%s ã® %d 行目 èªè˜ä¸èƒ½ãªãƒ•ラグã§ã™: %s" -#: ../spell.c:6257 #, c-format msgid "Ignored %d words with non-ASCII characters" msgstr "éžASCIIæ–‡å—ã‚’å«ã‚€ %d 個ã®å˜èªžã‚’無視ã—ã¾ã—ãŸ" -#: ../spell.c:6656 +msgid "E845: Insufficient memory, word list will be incomplete" +msgstr "E845: メモリãŒè¶³ã‚Šãªã„ã®ã§ã€å˜èªžãƒªã‚¹ãƒˆã¯ä¸å®Œå…¨ã§ã™" + #, c-format msgid "Compressed %d of %d nodes; %d (%d%%) remaining" msgstr "ノード %d 個(å…¨ %d 個ä¸) を圧縮ã—ã¾ã—ãŸ; 残り %d (%d%%)" -#: ../spell.c:7340 msgid "Reading back spell file..." msgstr "スペルファイルを逆èªè¾¼ä¸" -#. Go through the trie of good words, soundfold each word and add it to -#. the soundfold trie. -#: ../spell.c:7357 +#. +#. * Go through the trie of good words, soundfold each word and add it to +#. * the soundfold trie. +#. msgid "Performing soundfolding..." msgstr "音声畳込ã¿ã‚’実行ä¸..." -#: ../spell.c:7368 #, c-format -msgid "Number of words after soundfolding: %<PRId64>" -msgstr "音声畳込ã¿å¾Œã®ç·å˜èªžæ•°: %<PRId64>" +msgid "Number of words after soundfolding: %ld" +msgstr "音声畳込ã¿å¾Œã®ç·å˜èªžæ•°: %ld" -#: ../spell.c:7476 #, c-format msgid "Total number of words: %d" msgstr "ç·å˜èªžæ•°: %d" -#: ../spell.c:7655 #, c-format msgid "Writing suggestion file %s ..." msgstr "ä¿®æ£å€™è£œãƒ•ァイル \"%s\" を書込ã¿ä¸..." -#: ../spell.c:7707 ../spell.c:7927 #, c-format msgid "Estimated runtime memory use: %d bytes" msgstr "推定メモリ使用é‡: %d ãƒã‚¤ãƒˆ" -#: ../spell.c:7820 msgid "E751: Output file name must not have region name" msgstr "E751: 出力ファイルåã«ã¯ç¯„囲åã‚’å«ã‚られã¾ã›ã‚“" -#: ../spell.c:7822 msgid "E754: Only up to 8 regions supported" msgstr "E754: 範囲㯠8 個ã¾ã§ã—ã‹ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“" -#: ../spell.c:7846 #, c-format msgid "E755: Invalid region in %s" msgstr "E755: 無効ãªç¯„囲ã§ã™: %s" -#: ../spell.c:7907 msgid "Warning: both compounding and NOBREAK specified" msgstr "è¦å‘Š: 複åˆãƒ•ラグ㨠NOBREAK ãŒä¸¡æ–¹ã¨ã‚‚指定ã•れã¾ã—ãŸ" -#: ../spell.c:7920 #, c-format msgid "Writing spell file %s ..." msgstr "スペルファイル %s を書込ã¿ä¸..." -#: ../spell.c:7925 msgid "Done!" msgstr "実行ã—ã¾ã—ãŸ!" -#: ../spell.c:8034 #, c-format -msgid "E765: 'spellfile' does not have %<PRId64> entries" -msgstr "E765: 'spellfile' ã«ã¯ %<PRId64> 個ã®ã‚¨ãƒ³ãƒˆãƒªã¯ã‚りã¾ã›ã‚“" +msgid "E765: 'spellfile' does not have %ld entries" +msgstr "E765: 'spellfile' ã«ã¯ %ld 個ã®ã‚¨ãƒ³ãƒˆãƒªã¯ã‚りã¾ã›ã‚“" -#: ../spell.c:8074 #, c-format msgid "Word '%.*s' removed from %s" msgstr "å˜èªž '%.*s' ㌠%s ã‹ã‚‰å‰Šé™¤ã•れã¾ã—ãŸ" -#: ../spell.c:8117 #, c-format msgid "Word '%.*s' added to %s" msgstr "å˜èªž '%.*s' ㌠%s ã¸è¿½åŠ ã•れã¾ã—ãŸ" -#: ../spell.c:8381 msgid "E763: Word characters differ between spell files" msgstr "E763: å˜èªžã®æ–‡å—ãŒã‚¹ãƒšãƒ«ãƒ•ァイルã¨ç•°ãªã‚Šã¾ã™" -#: ../spell.c:8684 -msgid "Sorry, no suggestions" -msgstr "残念ã§ã™ãŒ, ä¿®æ£å€™è£œã¯ã‚りã¾ã›ã‚“" - -#: ../spell.c:8687 -#, c-format -msgid "Sorry, only %<PRId64> suggestions" -msgstr "残念ã§ã™ãŒ, ä¿®æ£å€™è£œã¯ %<PRId64> 個ã—ã‹ã‚りã¾ã›ã‚“" - -#. for when 'cmdheight' > 1 -#. avoid more prompt -#: ../spell.c:8704 -#, c-format -msgid "Change \"%.*s\" to:" -msgstr "\"%.*s\" を次ã¸å¤‰æ›:" - -#: ../spell.c:8737 -#, c-format -msgid " < \"%.*s\"" -msgstr " < \"%.*s\"" - -#: ../spell.c:8882 -msgid "E752: No previous spell replacement" -msgstr "E752: スペル置æ›ãŒã¾ã 実行ã•れã¦ã„ã¾ã›ã‚“" - -#: ../spell.c:8925 -#, c-format -msgid "E753: Not found: %s" -msgstr "E753: 見ã¤ã‹ã‚Šã¾ã›ã‚“: %s" - -#: ../spell.c:9276 -#, c-format -msgid "E778: This does not look like a .sug file: %s" -msgstr "E778: .sug ファイルã§ã¯ãªã„よã†ã§ã™: %s" - -#: ../spell.c:9282 -#, c-format -msgid "E779: Old .sug file, needs to be updated: %s" -msgstr "E779: å¤ã„ .sug ファイルãªã®ã§, アップデートã—ã¦ãã ã•ã„: %s" - -#: ../spell.c:9286 -#, c-format -msgid "E780: .sug file is for newer version of Vim: %s" -msgstr "E780: より新ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® Vim 用㮠.sug ファイルã§ã™: %s" - -#: ../spell.c:9295 -#, c-format -msgid "E781: .sug file doesn't match .spl file: %s" -msgstr "E781: .sug ファイル㌠.spl ファイルã¨ä¸€è‡´ã—ã¾ã›ã‚“: %s" - -#: ../spell.c:9305 -#, c-format -msgid "E782: error while reading .sug file: %s" -msgstr "E782: .sug ファイルã®èªè¾¼ä¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ: %s" - #. This should have been checked when generating the .spl -#. file. -#: ../spell.c:11575 +#. * file. msgid "E783: duplicate char in MAP entry" msgstr "E783: MAP エントリã«é‡è¤‡æ–‡å—ãŒå˜åœ¨ã—ã¾ã™" -#: ../syntax.c:266 msgid "No Syntax items defined for this buffer" msgstr "ã“ã®ãƒãƒƒãƒ•ã‚¡ã«å®šç¾©ã•ã‚ŒãŸæ§‹æ–‡è¦ç´ ã¯ã‚りã¾ã›ã‚“" -#: ../syntax.c:3083 ../syntax.c:3104 ../syntax.c:3127 #, c-format msgid "E390: Illegal argument: %s" msgstr "E390: 䏿£ãªå¼•æ•°ã§ã™: %s" @@ -5723,28 +5370,22 @@ msgstr "E390: 䏿£ãªå¼•æ•°ã§ã™: %s" msgid "syntax iskeyword " msgstr "シンタックス用 iskeyword " -#: ../syntax.c:3299 #, c-format msgid "E391: No such syntax cluster: %s" msgstr "E391: ãã®ã‚ˆã†ãªæ§‹æ–‡ã‚¯ãƒ©ã‚¹ã‚¿ã¯ã‚りã¾ã›ã‚“: %s" -#: ../syntax.c:3433 msgid "syncing on C-style comments" msgstr "C言語風コメントã‹ã‚‰åŒæœŸä¸" -#: ../syntax.c:3439 msgid "no syncing" msgstr "éžåŒæœŸ" -#: ../syntax.c:3441 msgid "syncing starts " msgstr "åŒæœŸé–‹å§‹ " -#: ../syntax.c:3443 ../syntax.c:3506 msgid " lines before top line" msgstr " 行å‰(トップ行よりも)" -#: ../syntax.c:3448 msgid "" "\n" "--- Syntax sync items ---" @@ -5752,7 +5393,6 @@ msgstr "" "\n" "--- æ§‹æ–‡åŒæœŸè¦ç´ ---" -#: ../syntax.c:3452 msgid "" "\n" "syncing on items" @@ -5760,7 +5400,6 @@ msgstr "" "\n" "è¦ç´ 上ã§åŒæœŸä¸" -#: ../syntax.c:3457 msgid "" "\n" "--- Syntax items ---" @@ -5768,53 +5407,41 @@ msgstr "" "\n" "--- æ§‹æ–‡è¦ç´ ---" -#: ../syntax.c:3475 #, c-format msgid "E392: No such syntax cluster: %s" msgstr "E392: ãã®ã‚ˆã†ãªæ§‹æ–‡ã‚¯ãƒ©ã‚¹ã‚¿ã¯ã‚りã¾ã›ã‚“: %s" -#: ../syntax.c:3497 msgid "minimal " msgstr "minimal " -#: ../syntax.c:3503 msgid "maximal " msgstr "maximal " -#: ../syntax.c:3513 msgid "; match " msgstr "; 該当 " -#: ../syntax.c:3515 msgid " line breaks" msgstr " å€‹ã®æ”¹è¡Œ" -#: ../syntax.c:4076 msgid "E395: contains argument not accepted here" msgstr "E395: ã“ã®å ´æ‰€ã§ã¯å¼•æ•°containsã¯è¨±å¯ã•れã¦ã„ã¾ã›ã‚“" -#: ../syntax.c:4096 msgid "E844: invalid cchar value" msgstr "E844: 無効ãªccharã®å€¤ã§ã™" -#: ../syntax.c:4107 msgid "E393: group[t]here not accepted here" msgstr "E393: ã“ã“ã§ã¯ã‚°ãƒ«ãƒ¼ãƒ—ã¯è¨±å¯ã•れã¾ã›ã‚“" -#: ../syntax.c:4126 #, c-format msgid "E394: Didn't find region item for %s" msgstr "E394: %s ã®ç¯„囲è¦ç´ ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../syntax.c:4188 msgid "E397: Filename required" msgstr "E397: ファイルåãŒå¿…è¦ã§ã™" -#: ../syntax.c:4221 msgid "E847: Too many syntax includes" msgstr "E847: æ§‹æ–‡ã®å–り込ã¿(include)ãŒå¤šéŽãŽã¾ã™" -#: ../syntax.c:4303 #, c-format msgid "E789: Missing ']': %s" msgstr "E789: ']' ãŒã‚りã¾ã›ã‚“: %s" @@ -5823,221 +5450,173 @@ msgstr "E789: ']' ãŒã‚りã¾ã›ã‚“: %s" msgid "E890: trailing char after ']': %s]%s" msgstr "E890: ']' ã®å¾Œã‚ã«ä½™åˆ†ãªæ–‡å—ãŒã‚りã¾ã™: %s]%s" -#: ../syntax.c:4531 #, c-format msgid "E398: Missing '=': %s" msgstr "E398: '=' ãŒã‚りã¾ã›ã‚“: %s" -#: ../syntax.c:4666 #, c-format msgid "E399: Not enough arguments: syntax region %s" msgstr "E399: 引数ãŒè¶³ã‚Šã¾ã›ã‚“: 構文範囲 %s" -#: ../syntax.c:4870 msgid "E848: Too many syntax clusters" msgstr "E848: 構文クラスタãŒå¤šéŽãŽã¾ã™" -#: ../syntax.c:4954 msgid "E400: No cluster specified" msgstr "E400: ã‚¯ãƒ©ã‚¹ã‚¿ãŒæŒ‡å®šã•れã¦ã„ã¾ã›ã‚“" -#. end delimiter not found -#: ../syntax.c:4986 #, c-format msgid "E401: Pattern delimiter not found: %s" msgstr "E401: パターン区切りãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“: %s" -#: ../syntax.c:5049 #, c-format msgid "E402: Garbage after pattern: %s" msgstr "E402: パターンã®ã‚ã¨ã«ã‚´ãƒŸãŒã‚りã¾ã™: %s" -#: ../syntax.c:5120 msgid "E403: syntax sync: line continuations pattern specified twice" msgstr "E403: æ§‹æ–‡åŒæœŸ: 連続行パターンãŒ2度指定ã•れã¾ã—ãŸ" -#: ../syntax.c:5169 #, c-format msgid "E404: Illegal arguments: %s" msgstr "E404: 䏿£ãªå¼•æ•°ã§ã™: %s" -#: ../syntax.c:5217 #, c-format msgid "E405: Missing equal sign: %s" msgstr "E405: ç‰å·ãŒã‚りã¾ã›ã‚“: %s" -#: ../syntax.c:5222 #, c-format msgid "E406: Empty argument: %s" msgstr "E406: 空ã®å¼•æ•°: %s" -#: ../syntax.c:5240 #, c-format msgid "E407: %s not allowed here" msgstr "E407: %s ã¯ã‚³ã‚³ã§ã¯è¨±å¯ã•れã¦ã„ã¾ã›ã‚“" -#: ../syntax.c:5246 #, c-format msgid "E408: %s must be first in contains list" msgstr "E408: %s ã¯å†…容リストã®å…ˆé ã§ãªã‘れã°ãªã‚‰ãªã„" -#: ../syntax.c:5304 #, c-format msgid "E409: Unknown group name: %s" msgstr "E409: 未知ã®ã‚°ãƒ«ãƒ¼ãƒ—å: %s" -#: ../syntax.c:5512 #, c-format msgid "E410: Invalid :syntax subcommand: %s" msgstr "E410: 無効㪠:syntax ã®ã‚µãƒ–コマンド: %s" -#: ../syntax.c:5854 msgid "" " TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN" msgstr "" " TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN" -#: ../syntax.c:6146 msgid "E679: recursive loop loading syncolor.vim" msgstr "E679: syncolor.vim ã®å†å¸°å‘¼ã³å‡ºã—を検出ã—ã¾ã—ãŸ" -#: ../syntax.c:6256 #, c-format msgid "E411: highlight group not found: %s" msgstr "E411: ãƒã‚¤ãƒ©ã‚¤ãƒˆã‚°ãƒ«ãƒ¼ãƒ—ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“: %s" -#: ../syntax.c:6278 #, c-format msgid "E412: Not enough arguments: \":highlight link %s\"" msgstr "E412: 引数ãŒå……分ã§ã¯ãªã„: \":highlight link %s\"" -#: ../syntax.c:6284 #, c-format msgid "E413: Too many arguments: \":highlight link %s\"" msgstr "E413: 引数ãŒå¤šéŽãŽã¾ã™: \":highlight link %s\"" -#: ../syntax.c:6302 msgid "E414: group has settings, highlight link ignored" msgstr "E414: グループãŒè¨å®šã•れã¦ã„ã‚‹ã®ã§ãƒã‚¤ãƒ©ã‚¤ãƒˆãƒªãƒ³ã‚¯ã¯ç„¡è¦–ã•れã¾ã™" -#: ../syntax.c:6367 #, c-format msgid "E415: unexpected equal sign: %s" msgstr "E415: 予期ã›ã¬ç‰å·ã§ã™: %s" -#: ../syntax.c:6395 #, c-format msgid "E416: missing equal sign: %s" msgstr "E416: ç‰å·ãŒã‚りã¾ã›ã‚“: %s" -#: ../syntax.c:6418 #, c-format msgid "E417: missing argument: %s" msgstr "E417: 引数ãŒã‚りã¾ã›ã‚“: %s" -#: ../syntax.c:6446 #, c-format msgid "E418: Illegal value: %s" msgstr "E418: 䏿£ãªå€¤ã§ã™: %s" -#: ../syntax.c:6496 msgid "E419: FG color unknown" msgstr "E419: 未知ã®å‰æ™¯è‰²ã§ã™" -#: ../syntax.c:6504 msgid "E420: BG color unknown" msgstr "E420: 未知ã®èƒŒæ™¯è‰²ã§ã™" -#: ../syntax.c:6564 #, c-format msgid "E421: Color name or number not recognized: %s" msgstr "E421: カラーåや番å·ã‚’èªè˜ã§ãã¾ã›ã‚“: %s" -#: ../syntax.c:6714 #, c-format msgid "E422: terminal code too long: %s" msgstr "E422: 終端コードãŒé•·éŽãŽã¾ã™: %s" -#: ../syntax.c:6753 #, c-format msgid "E423: Illegal argument: %s" msgstr "E423: 䏿£ãªå¼•æ•°ã§ã™: %s" -#: ../syntax.c:6925 msgid "E424: Too many different highlighting attributes in use" msgstr "E424: 多ãã®ç•°ãªã‚‹ãƒã‚¤ãƒ©ã‚¤ãƒˆå±žæ€§ãŒä½¿ã‚れéŽãŽã¦ã„ã¾ã™" -#: ../syntax.c:7427 msgid "E669: Unprintable character in group name" msgstr "E669: グループåã«å°åˆ·ä¸å¯èƒ½ãªæ–‡å—ãŒã‚りã¾ã™" -#: ../syntax.c:7434 msgid "W18: Invalid character in group name" msgstr "W18: グループåã«ä¸æ£ãªæ–‡å—ãŒã‚りã¾ã™" -#: ../syntax.c:7448 msgid "E849: Too many highlight and syntax groups" msgstr "E849: ãƒã‚¤ãƒ©ã‚¤ãƒˆã¨æ§‹æ–‡ã‚°ãƒ«ãƒ¼ãƒ—ãŒå¤šéŽãŽã¾ã™" -#: ../tag.c:104 msgid "E555: at bottom of tag stack" msgstr "E555: ã‚¿ã‚°ã‚¹ã‚¿ãƒƒã‚¯ã®æœ«å°¾ã§ã™" -#: ../tag.c:105 msgid "E556: at top of tag stack" msgstr "E556: タグスタックã®å…ˆé ã§ã™" -#: ../tag.c:380 msgid "E425: Cannot go before first matching tag" msgstr "E425: 最åˆã®è©²å½“ã‚¿ã‚°ã‚’è¶…ãˆã¦æˆ»ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“" -#: ../tag.c:504 #, c-format msgid "E426: tag not found: %s" msgstr "E426: ã‚¿ã‚°ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“: %s" -#: ../tag.c:528 msgid " # pri kind tag" msgstr " # pri kind tag" -#: ../tag.c:531 msgid "file\n" msgstr "ファイル\n" -#: ../tag.c:829 msgid "E427: There is only one matching tag" msgstr "E427: 該当タグãŒ1ã¤ã ã‘ã—ã‹ã‚りã¾ã›ã‚“" -#: ../tag.c:831 msgid "E428: Cannot go beyond last matching tag" msgstr "E428: 最後ã«è©²å½“ã™ã‚‹ã‚¿ã‚°ã‚’è¶…ãˆã¦é€²ã‚€ã“ã¨ã¯ã§ãã¾ã›ã‚“" -#: ../tag.c:850 #, c-format msgid "File \"%s\" does not exist" msgstr "ファイル \"%s\" ãŒã‚りã¾ã›ã‚“" #. Give an indication of the number of matching tags -#: ../tag.c:859 #, c-format msgid "tag %d of %d%s" msgstr "ã‚¿ã‚° %d (å…¨%d%s)" -#: ../tag.c:862 msgid " or more" msgstr " ã‹ãれ以上" -#: ../tag.c:864 msgid " Using tag with different case!" msgstr " ã‚¿ã‚°ã‚’ç•°ãªã‚‹caseã§ä½¿ç”¨ã—ã¾ã™!" -#: ../tag.c:909 #, c-format msgid "E429: File \"%s\" does not exist" msgstr "E429: ファイル \"%s\" ãŒã‚りã¾ã›ã‚“" #. Highlight title -#: ../tag.c:960 msgid "" "\n" " # TO tag FROM line in file/text" @@ -6045,79 +5624,66 @@ msgstr "" "\n" " # TO ã‚¿ã‚° FROM 行 in file/text" -#: ../tag.c:1303 #, c-format msgid "Searching tags file %s" msgstr "タグファイル %s を検索ä¸" -#: ../tag.c:1545 +#, c-format +msgid "E430: Tag file path truncated for %s\n" +msgstr "E430: タグファイルã®ãƒ‘ス㌠%s ã«åˆ‡ã‚Šæ¨ã¦ã‚‰ã‚Œã¾ã—ãŸ\n" + msgid "Ignoring long line in tags file" msgstr "タグファイル内ã®é•·ã„行を無視ã—ã¾ã™" -#: ../tag.c:1915 #, c-format msgid "E431: Format error in tags file \"%s\"" msgstr "E431: タグファイル \"%s\" ã®ãƒ•ォーマットã«ã‚¨ãƒ©ãƒ¼ãŒã‚りã¾ã™" -#: ../tag.c:1917 #, c-format -msgid "Before byte %<PRId64>" -msgstr "ç›´å‰ã® %<PRId64> ãƒã‚¤ãƒˆ" +msgid "Before byte %ld" +msgstr "ç›´å‰ã® %ld ãƒã‚¤ãƒˆ" -#: ../tag.c:1929 #, c-format msgid "E432: Tags file not sorted: %s" msgstr "E432: タグファイルãŒã‚½ãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“: %s" #. never opened any tags file -#: ../tag.c:1960 msgid "E433: No tags file" msgstr "E433: タグファイルãŒã‚りã¾ã›ã‚“" -#: ../tag.c:2536 msgid "E434: Can't find tag pattern" msgstr "E434: タグパターンを見ã¤ã‘られã¾ã›ã‚“" -#: ../tag.c:2544 msgid "E435: Couldn't find tag, just guessing!" msgstr "E435: タグを見ã¤ã‘られãªã„ã®ã§å˜ã«æŽ¨æ¸¬ã—ã¾ã™!" -#: ../tag.c:2797 #, c-format msgid "Duplicate field name: %s" msgstr "é‡è¤‡ã—ãŸãƒ•ィールドå: %s" -#: ../term.c:1442 msgid "' not known. Available builtin terminals are:" msgstr "' ã¯æœªçŸ¥ã§ã™. ç¾è¡Œã®çµ„ã¿è¾¼ã¿ç«¯æœ«ã¯æ¬¡ã®ã¨ãŠã‚Šã§ã™:" -#: ../term.c:1463 msgid "defaulting to '" msgstr "çœç•¥å€¤ã‚’次ã®ã‚ˆã†ã«è¨å®šã—ã¾ã™ '" -#: ../term.c:1731 msgid "E557: Cannot open termcap file" msgstr "E557: termcapファイルを開ã‘ã¾ã›ã‚“" -#: ../term.c:1735 msgid "E558: Terminal entry not found in terminfo" msgstr "E558: terminfoã«ç«¯æœ«ã‚¨ãƒ³ãƒˆãƒªã‚’見ã¤ã‘られã¾ã›ã‚“" -#: ../term.c:1737 msgid "E559: Terminal entry not found in termcap" msgstr "E559: termcapã«ç«¯æœ«ã‚¨ãƒ³ãƒˆãƒªã‚’見ã¤ã‘られã¾ã›ã‚“" -#: ../term.c:1878 #, c-format msgid "E436: No \"%s\" entry in termcap" msgstr "E436: termcapã« \"%s\" ã®ã‚¨ãƒ³ãƒˆãƒªãŒã‚りã¾ã›ã‚“" -#: ../term.c:2249 msgid "E437: terminal capability \"cm\" required" msgstr "E437: 端末㫠\"cm\" 機能ãŒå¿…è¦ã§ã™" #. Highlight title -#: ../term.c:4376 msgid "" "\n" "--- Terminal keys ---" @@ -6125,168 +5691,347 @@ msgstr "" "\n" "--- 端末ã‚ー ---" -#: ../ui.c:481 +msgid "Cannot open $VIMRUNTIME/rgb.txt" +msgstr "$VIMRUNTIME/rgb.txtã‚’é–‹ã‘ã¾ã›ã‚“" + +msgid "new shell started\n" +msgstr "æ–°ã—ã„シェルを起動ã—ã¾ã™\n" + msgid "Vim: Error reading input, exiting...\n" msgstr "Vim: 入力をèªè¾¼ã¿ä¸ã®ã‚¨ãƒ©ãƒ¼ã«ã‚ˆã‚Šçµ‚了ã—ã¾ã™...\n" +msgid "Used CUT_BUFFER0 instead of empty selection" +msgstr "空ã®é¸æŠžé ˜åŸŸã®ã‹ã‚りã«CUT_BUFFER0ãŒä½¿ç”¨ã•れã¾ã—ãŸ" + #. This happens when the FileChangedRO autocommand changes the #. * file in a way it becomes shorter. -#: ../undo.c:379 msgid "E881: Line count changed unexpectedly" msgstr "E881: 予期ã›ãšè¡Œã‚«ã‚¦ãƒ³ãƒˆãŒå¤‰ã‚りã¾ã—ãŸ" -#: ../undo.c:627 +#. must display the prompt +msgid "No undo possible; continue anyway" +msgstr "å¯èƒ½ãªã‚¢ãƒ³ãƒ‰ã‚¥ã¯ã‚りã¾ã›ã‚“: ã¨ã‚Šã‚ãˆãšç¶šã‘ã¾ã™" + #, c-format msgid "E828: Cannot open undo file for writing: %s" msgstr "E828: 書込ã¿ç”¨ã«ã‚¢ãƒ³ãƒ‰ã‚¥ãƒ•ァイルを開ã‘ã¾ã›ã‚“: %s" -#: ../undo.c:717 #, c-format msgid "E825: Corrupted undo file (%s): %s" msgstr "E825: アンドゥファイルãŒå£Šã‚Œã¦ã„ã¾ã™ (%s): %s" -#: ../undo.c:1039 msgid "Cannot write undo file in any directory in 'undodir'" msgstr "'undodir'ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã‚¢ãƒ³ãƒ‰ã‚¥ãƒ•ァイルを書ãè¾¼ã‚ã¾ã›ã‚“" -#: ../undo.c:1074 #, c-format msgid "Will not overwrite with undo file, cannot read: %s" msgstr "アンドゥファイルã¨ã—ã¦èªã¿è¾¼ã‚ãªã„ã®ã§ä¸Šæ›¸ãã—ã¾ã›ã‚“: %s" -#: ../undo.c:1092 #, c-format msgid "Will not overwrite, this is not an undo file: %s" msgstr "アンドゥファイルã§ã¯ãªã„ã®ã§ä¸Šæ›¸ãã—ã¾ã›ã‚“: %s" -#: ../undo.c:1108 msgid "Skipping undo file write, nothing to undo" msgstr "対象ãŒãªã„ã®ã§ã‚¢ãƒ³ãƒ‰ã‚¥ãƒ•ã‚¡ã‚¤ãƒ«ã®æ›¸ãè¾¼ã¿ã‚’スã‚ップã—ã¾ã™" -#: ../undo.c:1121 #, c-format msgid "Writing undo file: %s" msgstr "アンドゥファイル書ãè¾¼ã¿ä¸: %s" -#: ../undo.c:1213 #, c-format msgid "E829: write error in undo file: %s" msgstr "E829: ã‚¢ãƒ³ãƒ‰ã‚¥ãƒ•ã‚¡ã‚¤ãƒ«ã®æ›¸ãè¾¼ã¿ã‚¨ãƒ©ãƒ¼ã§ã™: %s" -#: ../undo.c:1280 #, c-format msgid "Not reading undo file, owner differs: %s" msgstr "オーナーãŒç•°ãªã‚‹ã®ã§ã‚¢ãƒ³ãƒ‰ã‚¥ãƒ•ァイルをèªã¿è¾¼ã¿ã¾ã›ã‚“: %s" -#: ../undo.c:1292 #, c-format msgid "Reading undo file: %s" msgstr "アンドゥファイルèªè¾¼ä¸: %s" -#: ../undo.c:1299 #, c-format msgid "E822: Cannot open undo file for reading: %s" msgstr "E822: アンドゥファイルをèªè¾¼ç”¨ã¨ã—ã¦é–‹ã‘ã¾ã›ã‚“: %s" -#: ../undo.c:1308 #, c-format msgid "E823: Not an undo file: %s" msgstr "E823: アンドゥファイルã§ã¯ã‚りã¾ã›ã‚“: %s" -#: ../undo.c:1313 +#, c-format +msgid "E832: Non-encrypted file has encrypted undo file: %s" +msgstr "E832: éžæš—å·åŒ–ãƒ•ã‚¡ã‚¤ãƒ«ãŒæš—å·åŒ–ã•れãŸã‚¢ãƒ³ãƒ‰ã‚¥ãƒ•ァイルを使ã£ã¦ã¾ã™: %s" + +#, c-format +msgid "E826: Undo file decryption failed: %s" +msgstr "E826: æš—å·åŒ–ã•れãŸã‚¢ãƒ³ãƒ‰ã‚¥ãƒ•ァイルã®è§£èªã«å¤±æ•—ã—ã¾ã—ãŸ: %s" + +#, c-format +msgid "E827: Undo file is encrypted: %s" +msgstr "E827: ã‚¢ãƒ³ãƒ‰ã‚¥ãƒ•ã‚¡ã‚¤ãƒ«ãŒæš—å·åŒ–ã•れã¦ã„ã¾ã™: %s" + #, c-format msgid "E824: Incompatible undo file: %s" msgstr "E824: äº’æ›æ€§ã®ç„¡ã„アンドゥファイルã§ã™: %s" -#: ../undo.c:1328 msgid "File contents changed, cannot use undo info" msgstr "ファイルã®å†…容ãŒå¤‰ã‚ã£ã¦ã„ã‚‹ãŸã‚ã€ã‚¢ãƒ³ãƒ‰ã‚¥æƒ…å ±ã‚’åˆ©ç”¨ã§ãã¾ã›ã‚“" -#: ../undo.c:1497 #, c-format msgid "Finished reading undo file %s" msgstr "アンドゥファイル %s ã®å–込を完了" -#: ../undo.c:1586 ../undo.c:1812 msgid "Already at oldest change" msgstr "æ—¢ã«ä¸€ç•ªå¤ã„変更ã§ã™" -#: ../undo.c:1597 ../undo.c:1814 msgid "Already at newest change" msgstr "æ—¢ã«ä¸€ç•ªæ–°ã—ã„変更ã§ã™" -#: ../undo.c:1806 #, c-format -msgid "E830: Undo number %<PRId64> not found" -msgstr "E830: ã‚¢ãƒ³ãƒ‰ã‚¥ç•ªå· %<PRId64> ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" +msgid "E830: Undo number %ld not found" +msgstr "E830: ã‚¢ãƒ³ãƒ‰ã‚¥ç•ªå· %ld ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" -#: ../undo.c:1979 msgid "E438: u_undo: line numbers wrong" msgstr "E438: u_undo: 行番å·ãŒé–“é•ã£ã¦ã„ã¾ã™" -#: ../undo.c:2183 msgid "more line" msgstr "行 è¿½åŠ ã—ã¾ã—ãŸ" -#: ../undo.c:2185 msgid "more lines" msgstr "行 è¿½åŠ ã—ã¾ã—ãŸ" -#: ../undo.c:2187 msgid "line less" msgstr "行 削除ã—ã¾ã—ãŸ" -#: ../undo.c:2189 msgid "fewer lines" msgstr "行 削除ã—ã¾ã—ãŸ" -#: ../undo.c:2193 msgid "change" msgstr "箇所変更ã—ã¾ã—ãŸ" -#: ../undo.c:2195 msgid "changes" msgstr "箇所変更ã—ã¾ã—ãŸ" -#: ../undo.c:2225 #, c-format -msgid "%<PRId64> %s; %s #%<PRId64> %s" -msgstr "%<PRId64> %s; %s #%<PRId64> %s" +msgid "%ld %s; %s #%ld %s" +msgstr "%ld %s; %s #%ld %s" -#: ../undo.c:2228 msgid "before" msgstr "剿–¹" -#: ../undo.c:2228 msgid "after" msgstr "後方" -#: ../undo.c:2325 msgid "Nothing to undo" msgstr "アンドゥ対象ãŒã‚りã¾ã›ã‚“" -#: ../undo.c:2330 msgid "number changes when saved" msgstr "通番 変更数 変更時期 ä¿å˜æ¸ˆ" -#: ../undo.c:2360 #, c-format -msgid "%<PRId64> seconds ago" -msgstr "%<PRId64> 秒経éŽã—ã¦ã„ã¾ã™" +msgid "%ld seconds ago" +msgstr "%ld 秒経éŽã—ã¦ã„ã¾ã™" -#: ../undo.c:2372 msgid "E790: undojoin is not allowed after undo" msgstr "E790: undo ã®ç›´å¾Œã« undojoin ã¯ã§ãã¾ã›ã‚“" -#: ../undo.c:2466 msgid "E439: undo list corrupt" msgstr "E439: アンドゥリストãŒå£Šã‚Œã¦ã„ã¾ã™" -#: ../undo.c:2495 msgid "E440: undo line missing" msgstr "E440: アンドゥ行ãŒã‚りã¾ã›ã‚“" -#: ../version.c:600 +#, c-format +msgid "E122: Function %s already exists, add ! to replace it" +msgstr "E122: 関数 %s ã¯å®šç¾©æ¸ˆã§ã™, å†å®šç¾©ã™ã‚‹ã«ã¯ ! ã‚’è¿½åŠ ã—ã¦ãã ã•ã„" + +msgid "E717: Dictionary entry already exists" +msgstr "E717: 辞書型内ã«ã‚¨ãƒ³ãƒˆãƒªãŒæ—¢ã«å˜åœ¨ã—ã¾ã™" + +msgid "E718: Funcref required" +msgstr "E718: 関数å‚ç…§åž‹ãŒè¦æ±‚ã•れã¾ã™" + +#, c-format +msgid "E130: Unknown function: %s" +msgstr "E130: 未知ã®é–¢æ•°ã§ã™: %s" + +#, c-format +msgid "E125: Illegal argument: %s" +msgstr "E125: 䏿£ãªå¼•æ•°ã§ã™: %s" + +#, c-format +msgid "E853: Duplicate argument name: %s" +msgstr "E853: 引数åãŒé‡è¤‡ã—ã¦ã„ã¾ã™: %s" + +#, c-format +msgid "E740: Too many arguments for function %s" +msgstr "E740: 関数ã®å¼•æ•°ãŒå¤šéŽãŽã¾ã™: %s" + +#, c-format +msgid "E116: Invalid arguments for function %s" +msgstr "E116: 関数ã®ç„¡åйãªå¼•æ•°ã§ã™: %s" + +msgid "E132: Function call depth is higher than 'maxfuncdepth'" +msgstr "E132: 関数呼出ã®å…¥ã‚Œå数㌠'maxfuncdepth' ã‚’è¶…ãˆã¾ã—ãŸ" + +#, c-format +msgid "calling %s" +msgstr "%s を実行ä¸ã§ã™" + +#, c-format +msgid "%s aborted" +msgstr "%s ãŒä¸æ–ã•れã¾ã—ãŸ" + +#, c-format +msgid "%s returning #%ld" +msgstr "%s ㌠#%ld ã‚’è¿”ã—ã¾ã—ãŸ" + +#, c-format +msgid "%s returning %s" +msgstr "%s ㌠%s ã‚’è¿”ã—ã¾ã—ãŸ" + +msgid "E699: Too many arguments" +msgstr "E699: 引数ãŒå¤šéŽãŽã¾ã™" + +#, c-format +msgid "E117: Unknown function: %s" +msgstr "E117: 未知ã®é–¢æ•°ã§ã™: %s" + +#, c-format +msgid "E933: Function was deleted: %s" +msgstr "E933: 関数ã¯å‰Šé™¤ã•れã¾ã—ãŸ: %s" + +#, c-format +msgid "E119: Not enough arguments for function: %s" +msgstr "E119: 関数ã®å¼•æ•°ãŒè¶³ã‚Šã¾ã›ã‚“: %s" + +#, c-format +msgid "E120: Using <SID> not in a script context: %s" +msgstr "E120: スクリプト以外ã§<SID>ãŒä½¿ã‚れã¾ã—ãŸ: %s" + +#, c-format +msgid "E725: Calling dict function without Dictionary: %s" +msgstr "E725: 辞書用関数ãŒå‘¼ã°ã‚Œã¾ã—ãŸãŒè¾žæ›¸ãŒã‚りã¾ã›ã‚“: %s" + +msgid "E129: Function name required" +msgstr "E129: 関数åãŒè¦æ±‚ã•れã¾ã™" + +#, c-format +msgid "E128: Function name must start with a capital or \"s:\": %s" +msgstr "E128: 関数åã¯å¤§æ–‡å—ã‹ \"s:\" ã§å§‹ã¾ã‚‰ãªã‘れã°ãªã‚Šã¾ã›ã‚“: %s" + +#, c-format +msgid "E884: Function name cannot contain a colon: %s" +msgstr "E884: 関数åã«ã¯ã‚³ãƒãƒ³ã¯å«ã‚られã¾ã›ã‚“: %s" + +#, c-format +msgid "E123: Undefined function: %s" +msgstr "E123: 未定義ã®é–¢æ•°ã§ã™: %s" + +#, c-format +msgid "E124: Missing '(': %s" +msgstr "E124: '(' ãŒã‚りã¾ã›ã‚“: %s" + +msgid "E862: Cannot use g: here" +msgstr "E862: ã“ã“ã§ã¯ g: ã¯ä½¿ãˆã¾ã›ã‚“" + +#, c-format +msgid "E932: Closure function should not be at top level: %s" +msgstr "E932: クãƒãƒ¼ã‚¸ãƒ£ãƒ¼é–¢æ•°ã¯ãƒˆãƒƒãƒ—レベルã«è¨˜è¿°ã§ãã¾ã›ã‚“: %s" + +msgid "E126: Missing :endfunction" +msgstr "E126: :endfunction ãŒã‚りã¾ã›ã‚“" + +#, c-format +msgid "E707: Function name conflicts with variable: %s" +msgstr "E707: 関数åãŒå¤‰æ•°åã¨è¡çªã—ã¾ã™: %s" + +#, c-format +msgid "E127: Cannot redefine function %s: It is in use" +msgstr "E127: 関数 %s ã‚’å†å®šç¾©ã§ãã¾ã›ã‚“: 使用ä¸ã§ã™" + +#, c-format +msgid "E746: Function name does not match script file name: %s" +msgstr "E746: 関数åãŒã‚¹ã‚¯ãƒªãƒ—トã®ãƒ•ァイルåã¨ä¸€è‡´ã—ã¾ã›ã‚“: %s" + +#, c-format +msgid "E131: Cannot delete function %s: It is in use" +msgstr "E131: 関数 %s を削除ã§ãã¾ã›ã‚“: 使用ä¸ã§ã™" + +msgid "E133: :return not inside a function" +msgstr "E133: 関数外㫠:return ãŒã‚りã¾ã—ãŸ" + +#, c-format +msgid "E107: Missing parentheses: %s" +msgstr "E107: カッコ '(' ãŒã‚りã¾ã›ã‚“: %s" + +#. Only MS VC 4.1 and earlier can do Win32s +msgid "" +"\n" +"MS-Windows 16/32-bit GUI version" +msgstr "" +"\n" +"MS-Windows 16/32 ビット GUI 版" + +msgid "" +"\n" +"MS-Windows 64-bit GUI version" +msgstr "" +"\n" +"MS-Windows 64 ビット GUI 版" + +msgid "" +"\n" +"MS-Windows 32-bit GUI version" +msgstr "" +"\n" +"MS-Windows 32 ビット GUI 版" + +msgid " with OLE support" +msgstr " with OLE サãƒãƒ¼ãƒˆ" + +msgid "" +"\n" +"MS-Windows 64-bit console version" +msgstr "" +"\n" +"MS-Windows 64 ビット コンソール 版" + +msgid "" +"\n" +"MS-Windows 32-bit console version" +msgstr "" +"\n" +"MS-Windows 32 ビット コンソール 版" + +msgid "" +"\n" +"MacOS X (unix) version" +msgstr "" +"\n" +"MacOS X (unix) 版" + +msgid "" +"\n" +"MacOS X version" +msgstr "" +"\n" +"MacOS X 版" + +msgid "" +"\n" +"MacOS version" +msgstr "" +"\n" +"MacOS 版" + +msgid "" +"\n" +"OpenVMS version" +msgstr "" +"\n" +"OpenVMS 版" + msgid "" "\n" "Included patches: " @@ -6294,7 +6039,6 @@ msgstr "" "\n" "é©ç”¨æ¸ˆãƒ‘ッãƒ: " -#: ../version.c:627 msgid "" "\n" "Extra patches: " @@ -6302,11 +6046,9 @@ msgstr "" "\n" "è¿½åŠ æ‹¡å¼µãƒ‘ãƒƒãƒ: " -#: ../version.c:639 ../version.c:864 msgid "Modified by " msgstr "Modified by " -#: ../version.c:646 msgid "" "\n" "Compiled " @@ -6314,11 +6056,9 @@ msgstr "" "\n" "Compiled " -#: ../version.c:649 msgid "by " msgstr "by " -#: ../version.c:660 msgid "" "\n" "Huge version " @@ -6326,1886 +6066,926 @@ msgstr "" "\n" "Huge 版 " -#: ../version.c:661 +msgid "" +"\n" +"Big version " +msgstr "" +"\n" +"Big 版 " + +msgid "" +"\n" +"Normal version " +msgstr "" +"\n" +"通常 版 " + +msgid "" +"\n" +"Small version " +msgstr "" +"\n" +"Small 版 " + +msgid "" +"\n" +"Tiny version " +msgstr "" +"\n" +"Tiny 版 " + msgid "without GUI." msgstr "without GUI." -#: ../version.c:662 +msgid "with GTK3 GUI." +msgstr "with GTK3 GUI." + +msgid "with GTK2-GNOME GUI." +msgstr "with GTK2-GNOME GUI." + +msgid "with GTK2 GUI." +msgstr "with GTK2 GUI." + +msgid "with X11-Motif GUI." +msgstr "with X11-Motif GUI." + +msgid "with X11-neXtaw GUI." +msgstr "with X11-neXtaw GUI." + +msgid "with X11-Athena GUI." +msgstr "with X11-Athena GUI." + +msgid "with Photon GUI." +msgstr "with Photon GUI." + +msgid "with GUI." +msgstr "with GUI." + +msgid "with Carbon GUI." +msgstr "with Carbon GUI." + +msgid "with Cocoa GUI." +msgstr "with Cocoa GUI." + +msgid "with (classic) GUI." +msgstr "with (クラシック) GUI." + msgid " Features included (+) or not (-):\n" msgstr " 機能ã®ä¸€è¦§ 有効(+)/無効(-)\n" -#: ../version.c:667 msgid " system vimrc file: \"" msgstr " システムvimrc: \"" -#: ../version.c:672 msgid " user vimrc file: \"" msgstr " ユーザー vimrc: \"" -#: ../version.c:677 msgid " 2nd user vimrc file: \"" msgstr " 第2ユーザー vimrc: \"" -#: ../version.c:682 msgid " 3rd user vimrc file: \"" msgstr " 第3ユーザー vimrc: \"" -#: ../version.c:687 msgid " user exrc file: \"" msgstr " ユーザー exrc: \"" -#: ../version.c:692 msgid " 2nd user exrc file: \"" msgstr " 第2ユーザー exrc: \"" -#: ../version.c:699 +msgid " system gvimrc file: \"" +msgstr " システムgvimrc: \"" + +msgid " user gvimrc file: \"" +msgstr " ユーザー gvimrc: \"" + +msgid "2nd user gvimrc file: \"" +msgstr " 第2ユーザー gvimrc: \"" + +msgid "3rd user gvimrc file: \"" +msgstr " 第3ユーザー gvimrc: \"" + +msgid " defaults file: \"" +msgstr " デフォルトファイル: \"" + +msgid " system menu file: \"" +msgstr " システムメニュー: \"" + msgid " fall-back for $VIM: \"" msgstr " çœç•¥æ™‚ã® $VIM: \"" -#: ../version.c:705 msgid " f-b for $VIMRUNTIME: \"" msgstr "çœç•¥æ™‚ã® $VIMRUNTIME: \"" -#: ../version.c:709 msgid "Compilation: " msgstr "コンパイル: " -#: ../version.c:712 +msgid "Compiler: " +msgstr "コンパイラ: " + msgid "Linking: " msgstr "リンク: " -#: ../version.c:717 msgid " DEBUG BUILD" msgstr "デãƒãƒƒã‚°ãƒ“ルド" -#: ../version.c:767 msgid "VIM - Vi IMproved" msgstr "VIM - Vi IMproved" -#: ../version.c:769 msgid "version " msgstr "version " -#: ../version.c:770 msgid "by Bram Moolenaar et al." msgstr "by Bram Moolenaar ä»–." -#: ../version.c:774 msgid "Vim is open source and freely distributable" msgstr "Vim ã¯ã‚ªãƒ¼ãƒ—ンソースã§ã‚り自由ã«é…布å¯èƒ½ã§ã™" -#: ../version.c:776 msgid "Help poor children in Uganda!" msgstr "ã‚¦ã‚¬ãƒ³ãƒ€ã®æµã¾ã‚Œãªã„åä¾›ãŸã¡ã«æ´åŠ©ã‚’!" -#: ../version.c:777 msgid "type :help iccf<Enter> for information " msgstr "è©³ç´°ãªæƒ…å ±ã¯ :help iccf<Enter> " -#: ../version.c:779 msgid "type :q<Enter> to exit " msgstr "終了ã™ã‚‹ã«ã¯ :q<Enter> " -#: ../version.c:780 msgid "type :help<Enter> or <F1> for on-line help" msgstr "オンラインヘルプ㯠:help<Enter> ã‹ <F1> " -#: ../version.c:781 -msgid "type :help version7<Enter> for version info" -msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã¯ :help version7<Enter> " +msgid "type :help version8<Enter> for version info" +msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã¯ :help version8<Enter> " -#: ../version.c:784 msgid "Running in Vi compatible mode" msgstr "Vi互æ›ãƒ¢ãƒ¼ãƒ‰ã§å‹•作ä¸" -#: ../version.c:785 msgid "type :set nocp<Enter> for Vim defaults" msgstr "Vim推奨値ã«ã™ã‚‹ã«ã¯ :set nocp<Enter> " -#: ../version.c:786 msgid "type :help cp-default<Enter> for info on this" msgstr "è©³ç´°ãªæƒ…å ±ã¯ :help cp-default<Enter>" -#: ../version.c:827 +msgid "menu Help->Orphans for information " +msgstr "詳細ã¯ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã® ヘルプ->å¤å… ã‚’å‚ç…§ã—ã¦ä¸‹ã•ã„ " + +msgid "Running modeless, typed text is inserted" +msgstr "モード無ã§å®Ÿè¡Œä¸, タイプã—ãŸæ–‡å—ãŒæŒ¿å…¥ã•れã¾ã™" + +msgid "menu Edit->Global Settings->Toggle Insert Mode " +msgstr "メニュー㮠編集->全体è¨å®š->挿入(åˆå¿ƒè€…)モード切替 " + +msgid " for two modes " +msgstr " ã§ãƒ¢ãƒ¼ãƒ‰æœ‰ã« " + +msgid "menu Edit->Global Settings->Toggle Vi Compatible" +msgstr "メニュー㮠編集->全体è¨å®š->Vi互æ›ãƒ¢ãƒ¼ãƒ‰åˆ‡æ›¿ " + +msgid " for Vim defaults " +msgstr " ã§Vimã¨ã—ã¦å‹•作 " + msgid "Sponsor Vim development!" msgstr "Vimã®é–‹ç™ºã‚’応æ´ã—ã¦ãã ã•ã„!" -#: ../version.c:828 msgid "Become a registered Vim user!" msgstr "Vimã®ç™»éŒ²ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ãªã£ã¦ãã ã•ã„!" -#: ../version.c:831 msgid "type :help sponsor<Enter> for information " msgstr "è©³ç´°ãªæƒ…å ±ã¯ :help sponsor<Enter> " -#: ../version.c:832 msgid "type :help register<Enter> for information " msgstr "è©³ç´°ãªæƒ…å ±ã¯ :help register<Enter> " -#: ../version.c:834 msgid "menu Help->Sponsor/Register for information " msgstr "詳細ã¯ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã® ヘルプ->スãƒãƒ³ã‚µãƒ¼/登録 ã‚’å‚ç…§ã—ã¦ä¸‹ã•ã„" -#: ../window.c:119 +msgid "WARNING: Windows 95/98/ME detected" +msgstr "è¦å‘Š: Windows 95/98/ME を検出ã—ã¾ã—ãŸ" + +msgid "type :help windows95<Enter> for info on this" +msgstr "è©³ç´°ãªæƒ…å ±ã¯ :help windows95<Enter>" + msgid "Already only one window" msgstr "æ—¢ã«ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã¯1ã¤ã—ã‹ã‚りã¾ã›ã‚“" -#: ../window.c:224 msgid "E441: There is no preview window" msgstr "E441: プレビューウィンドウãŒã‚りã¾ã›ã‚“" -#: ../window.c:559 msgid "E442: Can't split topleft and botright at the same time" msgstr "E442: 左上ã¨å³ä¸‹ã‚’åŒæ™‚ã«åˆ†å‰²ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“" -#: ../window.c:1228 msgid "E443: Cannot rotate when another window is split" msgstr "E443: ä»–ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãŒåˆ†å‰²ã•れã¦ã„る時ã«ã¯é †å›žã§ãã¾ã›ã‚“" -#: ../window.c:1803 msgid "E444: Cannot close last window" msgstr "E444: 最後ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’é–‰ã˜ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“" -#: ../window.c:1810 msgid "E813: Cannot close autocmd window" msgstr "E813: autocmdウィンドウã¯é–‰ã˜ã‚‰ã‚Œã¾ã›ã‚“" -#: ../window.c:1814 msgid "E814: Cannot close window, only autocmd window would remain" msgstr "E814: autocmdウィンドウã—ã‹æ®‹ã‚‰ãªã„ãŸã‚ã€ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã¯é–‰ã˜ã‚‰ã‚Œã¾ã›ã‚“" -#: ../window.c:2717 msgid "E445: Other window contains changes" msgstr "E445: ä»–ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã«ã¯å¤‰æ›´ãŒã‚りã¾ã™" -#: ../window.c:4805 msgid "E446: No file name under cursor" msgstr "E446: カーソルã®ä¸‹ã«ãƒ•ァイルåãŒã‚りã¾ã›ã‚“" -msgid "List or number required" -msgstr "ãƒªã‚¹ãƒˆã‹æ•°å€¤ãŒå¿…è¦ã§ã™" - -#~ msgid "E831: bf_key_init() called with empty password" -#~ msgstr "E831: bf_key_init() ãŒç©ºãƒ‘スワードã§å‘¼ã³å‡ºã•れã¾ã—ãŸ" - -#~ msgid "E820: sizeof(uint32_t) != 4" -#~ msgstr "E820: sizeof(uint32_t) != 4" - -#~ msgid "E817: Blowfish big/little endian use wrong" -#~ msgstr "E817: Blowfishæš—å·ã®ãƒ“ッグ/リトルエンディアンãŒé–“é•ã£ã¦ã„ã¾ã™" - -#~ msgid "E818: sha256 test failed" -#~ msgstr "E818: sha256ã®ãƒ†ã‚¹ãƒˆã«å¤±æ•—ã—ã¾ã—ãŸ" - -#~ msgid "E819: Blowfish test failed" -#~ msgstr "E819: Blowfishæš—å·ã®ãƒ†ã‚¹ãƒˆã«å¤±æ•—ã—ã¾ã—ãŸ" - -#~ msgid "Patch file" -#~ msgstr "パッãƒãƒ•ァイル" - -#~ msgid "" -#~ "&OK\n" -#~ "&Cancel" -#~ msgstr "" -#~ "決定(&O)\n" -#~ "ã‚ャンセル(&C)" - -#~ msgid "E240: No connection to Vim server" -#~ msgstr "E240: Vim サーãƒã¸ã®æŽ¥ç¶šãŒã‚りã¾ã›ã‚“" - -#~ msgid "E241: Unable to send to %s" -#~ msgstr "E241: %s ã¸é€ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“" - -#~ msgid "E277: Unable to read a server reply" -#~ msgstr "E277: サーãƒã®å¿œç”ãŒã‚りã¾ã›ã‚“" - -#~ msgid "E258: Unable to send to client" -#~ msgstr "E258: クライアントã¸é€ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“" - -#~ msgid "Save As" -#~ msgstr "別åã§ä¿å˜" - -#~ msgid "Edit File" -#~ msgstr "ファイルを編集" - -# Added at 27-Jan-2004. -#~ msgid " (NOT FOUND)" -#~ msgstr " (見ã¤ã‹ã‚Šã¾ã›ã‚“)" - -#~ msgid "Source Vim script" -#~ msgstr "Vimスクリプトã®å–è¾¼ã¿" - -#~ msgid "unknown" -#~ msgstr "䏿˜Ž" - -#~ msgid "Edit File in new window" -#~ msgstr "æ–°ã—ã„ウィンドウã§ãƒ•ァイルを編集ã—ã¾ã™" - -#~ msgid "Append File" -#~ msgstr "è¿½åŠ ãƒ•ã‚¡ã‚¤ãƒ«" - -#~ msgid "Window position: X %d, Y %d" -#~ msgstr "ウィンドウä½ç½®: X %d, Y %d" - -#~ msgid "Save Redirection" -#~ msgstr "リダイレクトをä¿å˜ã—ã¾ã™" - -#~ msgid "Save View" -#~ msgstr "ビューをä¿å˜ã—ã¾ã™" - -#~ msgid "Save Session" -#~ msgstr "ã‚»ãƒƒã‚·ãƒ§ãƒ³æƒ…å ±ã‚’ä¿å˜ã—ã¾ã™" - -#~ msgid "Save Setup" -#~ msgstr "è¨å®šã‚’ä¿å˜ã—ã¾ã™" - -#~ msgid "E809: #< is not available without the +eval feature" -#~ msgstr "E809: #< 㯠+eval 機能ãŒç„¡ã„ã¨åˆ©ç”¨ã§ãã¾ã›ã‚“" - -#~ msgid "E196: No digraphs in this version" -#~ msgstr "E196: ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«åˆå—ã¯ã‚りã¾ã›ã‚“" - -#~ msgid "is a device (disabled with 'opendevice' option)" -#~ msgstr " ã¯ãƒ‡ãƒã‚¤ã‚¹ã§ã™ ('opendevice' オプションã§å›žé¿ã§ãã¾ã™)" - -#~ msgid "Reading from stdin..." -#~ msgstr "標準入力ã‹ã‚‰èªè¾¼ã¿ä¸..." - -#~ msgid "[blowfish]" -#~ msgstr "[blowfishæš—å·åŒ–]" - -#~ msgid "[crypted]" -#~ msgstr "[æš—å·åŒ–]" - -#~ msgid "E821: File is encrypted with unknown method" -#~ msgstr "E821: ãƒ•ã‚¡ã‚¤ãƒ«ãŒæœªçŸ¥ã®æ–¹æ³•ã§æš—å·åŒ–ã•れã¦ã„ã¾ã™" - -# Added at 19-Jan-2004. -#~ msgid "NetBeans disallows writes of unmodified buffers" -#~ msgstr "NetBeansã¯æœªå¤‰æ›´ã®ãƒãƒƒãƒ•ァを上書ã™ã‚‹ã“ã¨ã¯è¨±å¯ã—ã¦ã„ã¾ã›ã‚“" - -#~ msgid "Partial writes disallowed for NetBeans buffers" -#~ msgstr "NetBeansãƒãƒƒãƒ•ã‚¡ã®ä¸€éƒ¨ã‚’書ã出ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“" - -#~ msgid "writing to device disabled with 'opendevice' option" -#~ msgstr "'opendevice' オプションã«ã‚ˆã‚Šãƒ‡ãƒã‚¤ã‚¹ã¸ã®æ›¸ãè¾¼ã¿ã¯ã§ãã¾ã›ã‚“" - -#~ msgid "E460: The resource fork would be lost (add ! to override)" -#~ msgstr "E460: リソースフォークãŒå¤±ã‚れるã‹ã‚‚ã—れã¾ã›ã‚“ (! ã‚’è¿½åŠ ã§å¼·åˆ¶)" - -#~ msgid "E851: Failed to create a new process for the GUI" -#~ msgstr "E851: GUI用ã®ãƒ—ãƒã‚»ã‚¹ã®èµ·å‹•ã«å¤±æ•—ã—ã¾ã—ãŸ" - -#~ msgid "E852: The child process failed to start the GUI" -#~ msgstr "E852: åプãƒã‚»ã‚¹ãŒGUIã®èµ·å‹•ã«å¤±æ•—ã—ã¾ã—ãŸ" - -#~ msgid "E229: Cannot start the GUI" -#~ msgstr "E229: GUIã‚’é–‹å§‹ã§ãã¾ã›ã‚“" - -#~ msgid "E230: Cannot read from \"%s\"" -#~ msgstr "E230: \"%s\"ã‹ã‚‰èªè¾¼ã‚€ã“ã¨ãŒã§ãã¾ã›ã‚“" - -#~ msgid "E665: Cannot start GUI, no valid font found" -#~ msgstr "E665: 有効ãªãƒ•ォントãŒè¦‹ã¤ã‹ã‚‰ãªã„ã®ã§, GUIã‚’é–‹å§‹ã§ãã¾ã›ã‚“" - -#~ msgid "E231: 'guifontwide' invalid" -#~ msgstr "E231: 'guifontwide' ãŒç„¡åйã§ã™" - -#~ msgid "E599: Value of 'imactivatekey' is invalid" -#~ msgstr "E599: 'imactivatekey' ã«è¨å®šã•れãŸå€¤ãŒç„¡åйã§ã™" - -#~ msgid "E254: Cannot allocate color %s" -#~ msgstr "E254: %s ã®è‰²ã‚’割り当ã¦ã‚‰ã‚Œã¾ã›ã‚“" - -#~ msgid "No match at cursor, finding next" -#~ msgstr "カーソルã®ä½ç½®ã«ãƒžãƒƒãƒã¯ã‚りã¾ã›ã‚“, 次を検索ã—ã¦ã„ã¾ã™" - -#~ msgid "<cannot open> " -#~ msgstr "<é–‹ã‘ã¾ã›ã‚“> " - -#~ msgid "E616: vim_SelFile: can't get font %s" -#~ msgstr "E616: vim_SelFile: フォント %s ã‚’å–å¾—ã§ãã¾ã›ã‚“" - -#~ msgid "E614: vim_SelFile: can't return to current directory" -#~ msgstr "E614: vim_SelFile: ç¾åœ¨ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«æˆ»ã‚Œã¾ã›ã‚“" - -#~ msgid "Pathname:" -#~ msgstr "パスå:" - -#~ msgid "E615: vim_SelFile: can't get current directory" -#~ msgstr "E615: vim_SelFile: ç¾åœ¨ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’å–å¾—ã§ãã¾ã›ã‚“" - -#~ msgid "OK" -#~ msgstr "OK" - -#~ msgid "Cancel" -#~ msgstr "ã‚ャンセル" - -#~ msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." -#~ msgstr "スクãƒãƒ¼ãƒ«ãƒãƒ¼: ç”»åƒã‚’å–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸ." - -#~ msgid "Vim dialog" -#~ msgstr "Vim ダイアãƒã‚°" - -#~ msgid "E232: Cannot create BalloonEval with both message and callback" -#~ msgstr "E232: メッセージã¨ã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯ã®ã‚ã‚‹ BalloonEval を作æˆã§ãã¾ã›ã‚“" - -#~ msgid "Input _Methods" -#~ msgstr "インプットメソッド" - -#~ msgid "VIM - Search and Replace..." -#~ msgstr "VIM - 検索ã¨ç½®æ›..." - -#~ msgid "VIM - Search..." -#~ msgstr "VIM - 検索..." - -#~ msgid "Find what:" -#~ msgstr "検索文å—列:" - -#~ msgid "Replace with:" -#~ msgstr "ç½®æ›æ–‡å—列:" - -#~ msgid "Match whole word only" -#~ msgstr "æ£ç¢ºã«è©²å½“ã™ã‚‹ã‚‚ã®ã ã‘" - -#~ msgid "Match case" -#~ msgstr "大文å—/å°æ–‡å—を区別ã™ã‚‹" - -#~ msgid "Direction" -#~ msgstr "æ–¹å‘" - -#~ msgid "Up" -#~ msgstr "上" - -#~ msgid "Down" -#~ msgstr "下" - -#~ msgid "Find Next" -#~ msgstr "次を検索" - -#~ msgid "Replace" -#~ msgstr "ç½®æ›" - -#~ msgid "Replace All" -#~ msgstr "å…¨ã¦ç½®æ›" - -#~ msgid "Vim: Received \"die\" request from session manager\n" -#~ msgstr "Vim: セッションマãƒãƒ¼ã‚¸ãƒ£ã‹ã‚‰ \"die\" è¦æ±‚ã‚’å—ã‘å–りã¾ã—ãŸ\n" - -#~ msgid "Close" -#~ msgstr "é–‰ã˜ã‚‹" - -#~ msgid "New tab" -#~ msgstr "æ–°è¦ã‚¿ãƒ–ページ" - -#~ msgid "Open Tab..." -#~ msgstr "タブページを開ã..." - -#~ msgid "Vim: Main window unexpectedly destroyed\n" -#~ msgstr "Vim: メインウィンドウãŒä¸æ„ã«ç ´å£Šã•れã¾ã—ãŸ\n" - -#~ msgid "&Filter" -#~ msgstr "フィルタ(&F)" - -#~ msgid "&Cancel" -#~ msgstr "ã‚ャンセル(&C)" - -#~ msgid "Directories" -#~ msgstr "ディレクトリ" - -#~ msgid "Filter" -#~ msgstr "フィルタ" - -#~ msgid "&Help" -#~ msgstr "ヘルプ(&H)" - -#~ msgid "Files" -#~ msgstr "ファイル" - -#~ msgid "&OK" -#~ msgstr "&OK" - -#~ msgid "Selection" -#~ msgstr "é¸æŠž" - -#~ msgid "Find &Next" -#~ msgstr "次を検索(&N)" - -#~ msgid "&Replace" -#~ msgstr "ç½®æ›(&R)" - -#~ msgid "Replace &All" -#~ msgstr "å…¨ã¦ç½®æ›(&A)" - -#~ msgid "&Undo" -#~ msgstr "アンドゥ(&U)" - -#~ msgid "E671: Cannot find window title \"%s\"" -#~ msgstr "E671: タイトル㌠\"%s\" ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" - -#~ msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." -#~ msgstr "E243: 引数ã¯ã‚µãƒãƒ¼ãƒˆã•れã¾ã›ã‚“: \"-%s\"; OLE版を使用ã—ã¦ãã ã•ã„." - -#~ msgid "E672: Unable to open window inside MDI application" -#~ msgstr "E672: MDIアプリã®ä¸ã§ã¯ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’é–‹ã‘ã¾ã›ã‚“" - -#~ msgid "Close tab" -#~ msgstr "タブページを閉ã˜ã‚‹" - -#~ msgid "Open tab..." -#~ msgstr "タブページを開ã" - -#~ msgid "Find string (use '\\\\' to find a '\\')" -#~ msgstr "検索文å—列 ('\\' を検索ã™ã‚‹ã«ã¯ '\\\\')" - -#~ msgid "Find & Replace (use '\\\\' to find a '\\')" -#~ msgstr "æ¤œç´¢ãƒ»ç½®æ› ('\\' を検索ã™ã‚‹ã«ã¯ '\\\\')" - -#~ msgid "Not Used" -#~ msgstr "使ã‚れã¾ã›ã‚“" - -#~ msgid "Directory\t*.nothing\n" -#~ msgstr "ディレクトリ\t*.nothing\n" - -#~ msgid "" -#~ "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" -#~ msgstr "Vim E458: è‰²æŒ‡å®šãŒæ£ã—ããªã„ã®ã§ã‚¨ãƒ³ãƒˆãƒªã‚’割り当ã¦ã‚‰ã‚Œã¾ã›ã‚“" - -#~ msgid "E250: Fonts for the following charsets are missing in fontset %s:" -#~ msgstr "E250: ä»¥ä¸‹ã®æ–‡å—セットã®ãƒ•ォントãŒã‚りã¾ã›ã‚“ %s:" - -#~ msgid "E252: Fontset name: %s" -#~ msgstr "E252: フォントセットå: %s" - -#~ msgid "Font '%s' is not fixed-width" -#~ msgstr "フォント '%s' ã¯å›ºå®šå¹…ã§ã¯ã‚りã¾ã›ã‚“" - -#~ msgid "E253: Fontset name: %s" -#~ msgstr "E253: フォントセットå: %s" - -#~ msgid "Font0: %s" -#~ msgstr "フォント0: %s" - -#~ msgid "Font1: %s" -#~ msgstr "フォント1: %s" - -#~ msgid "Font%<PRId64> width is not twice that of font0" -#~ msgstr "フォント%<PRId64> ã®å¹…ãŒãƒ•ォント0ã®2å€ã§ã¯ã‚りã¾ã›ã‚“" - -#~ msgid "Font0 width: %<PRId64>" -#~ msgstr "フォント0ã®å¹…: %<PRId64>" - -#~ msgid "Font1 width: %<PRId64>" -#~ msgstr "フォント1ã®å¹…: %<PRId64>" - -#~ msgid "Invalid font specification" -#~ msgstr "無効ãªãƒ•ォント指定ã§ã™" - -#~ msgid "&Dismiss" -#~ msgstr "å´ä¸‹ã™ã‚‹(&D)" - -#~ msgid "no specific match" -#~ msgstr "マッãƒã™ã‚‹ã‚‚ã®ãŒã‚りã¾ã›ã‚“" - -#~ msgid "Vim - Font Selector" -#~ msgstr "Vim - ãƒ•ã‚©ãƒ³ãƒˆé¸æŠž" - -#~ msgid "Name:" -#~ msgstr "åå‰:" - -#~ msgid "Show size in Points" -#~ msgstr "サイズをãƒã‚¤ãƒ³ãƒˆã§è¡¨ç¤ºã™ã‚‹" - -#~ msgid "Encoding:" -#~ msgstr "エンコード:" - -#~ msgid "Font:" -#~ msgstr "フォント:" - -#~ msgid "Style:" -#~ msgstr "スタイル:" - -#~ msgid "Size:" -#~ msgstr "サイズ:" - -#~ msgid "E256: Hangul automata ERROR" -#~ msgstr "E256: ãƒãƒ³ã‚°ãƒ«ã‚ªãƒ¼ãƒˆãƒžãƒˆãƒ³ã‚¨ãƒ©ãƒ¼" - -#~ msgid "E563: stat error" -#~ msgstr "E563: stat エラー" - -#~ msgid "E625: cannot open cscope database: %s" -#~ msgstr "E625: cscopeデータベース: %s ã‚’é–‹ãã“ã¨ãŒã§ãã¾ã›ã‚“" - -#~ msgid "E626: cannot get cscope database information" -#~ msgstr "E626: cscopeãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æƒ…å ±ã‚’å–å¾—ã§ãã¾ã›ã‚“" - -#~ msgid "Lua library cannot be loaded." -#~ msgstr "Luaライブラリをãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“." - -#~ msgid "cannot save undo information" -#~ msgstr "ã‚¢ãƒ³ãƒ‰ã‚¥æƒ…å ±ãŒä¿å˜ã§ãã¾ã›ã‚“" - -#~ msgid "" -#~ "E815: Sorry, this command is disabled, the MzScheme libraries could not " -#~ "be loaded." -#~ msgstr "" -#~ "E815: ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ç„¡åйã§ã™. MzScheme ライブラリをãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“." - -#~ msgid "invalid expression" -#~ msgstr "無効ãªå¼ã§ã™" - -#~ msgid "expressions disabled at compile time" -#~ msgstr "å¼ã¯ã‚³ãƒ³ãƒ‘イル時ã«ç„¡åйã«ã•れã¦ã„ã¾ã™" - -#~ msgid "hidden option" -#~ msgstr "éš ã—オプション" - -#~ msgid "unknown option" -#~ msgstr "未知ã®ã‚ªãƒ—ションã§ã™" - -#~ msgid "window index is out of range" -#~ msgstr "範囲外ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ç•ªå·ã§ã™" - -#~ msgid "couldn't open buffer" -#~ msgstr "ãƒãƒƒãƒ•ã‚¡ã‚’é–‹ã‘ã¾ã›ã‚“" - -#~ msgid "cannot delete line" -#~ msgstr "行を消ã›ã¾ã›ã‚“" - -#~ msgid "cannot replace line" -#~ msgstr "行を置æ›ã§ãã¾ã›ã‚“" - -#~ msgid "cannot insert line" -#~ msgstr "行を挿入ã§ãã¾ã›ã‚“" - -#~ msgid "string cannot contain newlines" -#~ msgstr "æ–‡å—列ã«ã¯æ”¹è¡Œæ–‡å—ã‚’å«ã‚られã¾ã›ã‚“" - -#~ msgid "error converting Scheme values to Vim" -#~ msgstr "Scheme値ã®Vimã¸ã®å¤‰æ›ã‚¨ãƒ©ãƒ¼" - -#~ msgid "Vim error: ~a" -#~ msgstr "Vim エラー: ~a" - -#~ msgid "Vim error" -#~ msgstr "Vim エラー" - -#~ msgid "buffer is invalid" -#~ msgstr "ãƒãƒƒãƒ•ã‚¡ã¯ç„¡åйã§ã™" - -#~ msgid "window is invalid" -#~ msgstr "ウィンドウã¯ç„¡åйã§ã™" - -#~ msgid "linenr out of range" -#~ msgstr "範囲外ã®è¡Œç•ªå·ã§ã™" - -#~ msgid "not allowed in the Vim sandbox" -#~ msgstr "サンドボックスã§ã¯è¨±ã•れã¾ã›ã‚“" - -#~ msgid "E370: Could not load library %s" -#~ msgstr "E370: ライブラリ %s ã‚’ãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§ã—ãŸ" - -#~ msgid "" -#~ "Sorry, this command is disabled: the Perl library could not be loaded." -#~ msgstr "" -#~ "ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ç„¡åйã§ã™, ã”ã‚ã‚“ãªã•ã„: Perlライブラリをãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§ã—" -#~ "ãŸ." - -#~ msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" -#~ msgstr "" -#~ "E299: サンドボックスã§ã¯ Safe モジュールを使用ã—ãªã„Perlスクリプトã¯ç¦ã˜ã‚‰" -#~ "れã¦ã„ã¾ã™" - -#~ msgid "E836: This Vim cannot execute :python after using :py3" -#~ msgstr "E836: ã“ã®Vimã§ã¯ :py3 を使ã£ãŸå¾Œã« :python を使ãˆã¾ã›ã‚“" - -#~ msgid "" -#~ "E263: Sorry, this command is disabled, the Python library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E263: ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ç„¡åйã§ã™,ã”ã‚ã‚“ãªã•ã„: Pythonライブラリをãƒãƒ¼ãƒ‰ã§ãã¾" -#~ "ã›ã‚“ã§ã—ãŸ." - -# Added at 07-Feb-2004. -#~ msgid "E659: Cannot invoke Python recursively" -#~ msgstr "E659: Python ã‚’å†å¸°çš„ã«å®Ÿè¡Œã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“" - -#~ msgid "E837: This Vim cannot execute :py3 after using :python" -#~ msgstr "E837: ã“ã®Vimã§ã¯ :python を使ã£ãŸå¾Œã« :py3 を使ãˆã¾ã›ã‚“" - -#~ msgid "E265: $_ must be an instance of String" -#~ msgstr "E265: $_ ã¯æ–‡å—列ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" - -#~ msgid "" -#~ "E266: Sorry, this command is disabled, the Ruby library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E266: ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ç„¡åйã§ã™,ã”ã‚ã‚“ãªã•ã„: Rubyライブラリをãƒãƒ¼ãƒ‰ã§ãã¾ã›" -#~ "ã‚“ã§ã—ãŸ." - -#~ msgid "E267: unexpected return" -#~ msgstr "E267: 予期ã›ã¬ return ã§ã™" - -#~ msgid "E268: unexpected next" -#~ msgstr "E268: 予期ã›ã¬ next ã§ã™" - -#~ msgid "E269: unexpected break" -#~ msgstr "E269: 予期ã›ã¬ break ã§ã™" - -#~ msgid "E270: unexpected redo" -#~ msgstr "E270: 予期ã›ã¬ redo ã§ã™" - -#~ msgid "E271: retry outside of rescue clause" -#~ msgstr "E271: rescue ã®å¤–ã® retry ã§ã™" - -#~ msgid "E272: unhandled exception" -#~ msgstr "E272: å–り扱ã‚れãªã‹ã£ãŸä¾‹å¤–ãŒã‚りã¾ã™" - -#~ msgid "E273: unknown longjmp status %d" -#~ msgstr "E273: 未知ã®longjmp状態: %d" - -#~ msgid "Toggle implementation/definition" -#~ msgstr "実装ã¨å®šç¾©ã‚’切り替ãˆã‚‹" - -#~ msgid "Show base class of" -#~ msgstr "次ã®ã‚¯ãƒ©ã‚¹ã®åŸºåº•を表示" - -#~ msgid "Show overridden member function" -#~ msgstr "オーãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã•れãŸãƒ¡ãƒ³ãƒé–¢æ•°ã‚’表示" - -#~ msgid "Retrieve from file" -#~ msgstr "ファイルã‹ã‚‰å›žå¾©ã™ã‚‹" - -#~ msgid "Retrieve from project" -#~ msgstr "プãƒã‚¸ã‚§ã‚¯ãƒˆã‹ã‚‰å›žå¾©ã™ã‚‹" - -#~ msgid "Retrieve from all projects" -#~ msgstr "å…¨ã¦ã®ãƒ—ãƒã‚¸ã‚§ã‚¯ãƒˆã‹ã‚‰å›žå¾©ã™ã‚‹" - -#~ msgid "Retrieve" -#~ msgstr "回復" - -#~ msgid "Show source of" -#~ msgstr "次ã®ã‚½ãƒ¼ã‚¹ã‚’表示ã™ã‚‹" - -#~ msgid "Find symbol" -#~ msgstr "見ã¤ã‘ãŸã‚·ãƒ³ãƒœãƒ«" - -#~ msgid "Browse class" -#~ msgstr "クラスをå‚ç…§" - -#~ msgid "Show class in hierarchy" -#~ msgstr "階層ã§ã‚¯ãƒ©ã‚¹ã‚’表示" - -#~ msgid "Show class in restricted hierarchy" -#~ msgstr "é™å®šã•れãŸéšŽå±¤ã§ã‚¯ãƒ©ã‚¹ã‚’表示" - -#~ msgid "Xref refers to" -#~ msgstr "Xref ã®å‚ç…§å…ˆ" - -#~ msgid "Xref referred by" -#~ msgstr "Xref ãŒå‚ç…§ã•れる" - -#~ msgid "Xref has a" -#~ msgstr "Xref ãŒæ¬¡ã®ã‚‚ã®ã‚’ã‚‚ã£ã¦ã„ã¾ã™" - -#~ msgid "Xref used by" -#~ msgstr "Xref ãŒä½¿ç”¨ã•れる" - -#~ msgid "Show docu of" -#~ msgstr "æ¬¡ã®æ–‡ç« を表示" - -#~ msgid "Generate docu for" -#~ msgstr "æ¬¡ã®æ–‡ç« を生æˆ" - -#~ msgid "" -#~ "Cannot connect to SNiFF+. Check environment (sniffemacs must be found in " -#~ "$PATH).\n" -#~ msgstr "" -#~ "SNiFF+ã«æŽ¥ç¶šã§ãã¾ã›ã‚“. 環境をãƒã‚§ãƒƒã‚¯ã—ã¦ãã ã•ã„(sniffemacs ㌠$PATH ã«" -#~ "ãªã‘れã°ãªã‚Šã¾ã›ã‚“).\n" - -#~ msgid "E274: Sniff: Error during read. Disconnected" -#~ msgstr "E274: Sniff: èªè¾¼ä¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ. 切æ–ã—ã¾ã—ãŸ" - -#~ msgid "SNiFF+ is currently " -#~ msgstr "ç¾åœ¨SNiFF+ ã®çŠ¶æ…‹ã¯ã€Œ" - -#~ msgid "not " -#~ msgstr "未" - -#~ msgid "connected" -#~ msgstr "接続ã€ã§ã™" - -#~ msgid "E275: Unknown SNiFF+ request: %s" -#~ msgstr "E275: 未知㮠SNiFF+ リクエストã§ã™: %s" - -#~ msgid "E276: Error connecting to SNiFF+" -#~ msgstr "E276: SNiFF+ ã¸ã®æŽ¥ç¶šä¸ã®ã‚¨ãƒ©ãƒ¼ã§ã™" - -#~ msgid "E278: SNiFF+ not connected" -#~ msgstr "E278: SNiFF+ ã«æŽ¥ç¶šã•れã¦ã„ã¾ã›ã‚“" - -#~ msgid "E279: Not a SNiFF+ buffer" -#~ msgstr "E279: SNiFF+ ãƒãƒƒãƒ•ã‚¡ãŒã‚りã¾ã›ã‚“" - -#~ msgid "Sniff: Error during write. Disconnected" -#~ msgstr "Sniff: 書込ã¿ä¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ãŸã®ã§åˆ‡æ–ã—ã¾ã—ãŸ" - -#~ msgid "invalid buffer number" -#~ msgstr "無効ãªãƒãƒƒãƒ•ァ番å·ã§ã™" - -#~ msgid "not implemented yet" -#~ msgstr "ã¾ã 実装ã•れã¦ã„ã¾ã›ã‚“" - -#~ msgid "cannot set line(s)" -#~ msgstr "行をè¨å®šã§ãã¾ã›ã‚“" - -#~ msgid "invalid mark name" -#~ msgstr "無効ãªãƒžãƒ¼ã‚¯åã§ã™" - -#~ msgid "mark not set" -#~ msgstr "マークã¯è¨å®šã•れã¦ã„ã¾ã›ã‚“" - -#~ msgid "row %d column %d" -#~ msgstr "行 %d 列 %d" - -#~ msgid "cannot insert/append line" -#~ msgstr "è¡Œã®æŒ¿å…¥/è¿½åŠ ã‚’ã§ãã¾ã›ã‚“" - -#~ msgid "line number out of range" -#~ msgstr "範囲外ã®è¡Œç•ªå·ã§ã™" - -#~ msgid "unknown flag: " -#~ msgstr "未知ã®ãƒ•ラグ: " - -#~ msgid "unknown vimOption" -#~ msgstr "未知㮠vimOption ã§ã™" - -#~ msgid "keyboard interrupt" -#~ msgstr "ã‚ーボード割込ã¿" - -#~ msgid "vim error" -#~ msgstr "vim エラー" - -#~ msgid "cannot create buffer/window command: object is being deleted" -#~ msgstr "" -#~ "ãƒãƒƒãƒ•ã‚¡/ウィンドウ作æˆã‚³ãƒžãƒ³ãƒ‰ã‚’作æˆã§ãã¾ã›ã‚“: ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆãŒæ¶ˆåŽ»ã•れã¦" -#~ "ã„ã¾ã—ãŸ" - -#~ msgid "" -#~ "cannot register callback command: buffer/window is already being deleted" -#~ msgstr "" -#~ "コールãƒãƒƒã‚¯ã‚³ãƒžãƒ³ãƒ‰ã‚’登録ã§ãã¾ã›ã‚“: ãƒãƒƒãƒ•ã‚¡/ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãŒæ—¢ã«æ¶ˆåŽ»ã•れã¾" -#~ "ã—ãŸ" - -#~ msgid "" -#~ "E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-" -#~ "dev@vim.org" -#~ msgstr "" -#~ "E280: TCL 致命的エラー: reflist 汚染!? vim-dev@vim.org ã«å ±å‘Šã—ã¦ãã ã•ã„" - -#~ msgid "cannot register callback command: buffer/window reference not found" -#~ msgstr "" -#~ "コールãƒãƒƒã‚¯ã‚³ãƒžãƒ³ãƒ‰ã‚’登録ã§ãã¾ã›ã‚“: ãƒãƒƒãƒ•ã‚¡/ウィンドウã®å‚ç…§ãŒè¦‹ã¤ã‹ã‚Š" -#~ "ã¾ã›ã‚“" - -#~ msgid "" -#~ "E571: Sorry, this command is disabled: the Tcl library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E571: ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ç„¡åйã§ã™,ã”ã‚ã‚“ãªã•ã„: Tclライブラリをãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“" -#~ "ã§ã—ãŸ." - -#~ msgid "E572: exit code %d" -#~ msgstr "E572: 終了コード %d" - -#~ msgid "cannot get line" -#~ msgstr "行をå–å¾—ã§ãã¾ã›ã‚“" - -#~ msgid "Unable to register a command server name" -#~ msgstr "命令サーãƒã®åå‰ã‚’登録ã§ãã¾ã›ã‚“" - -#~ msgid "E248: Failed to send command to the destination program" -#~ msgstr "E248: 目的ã®ãƒ—ãƒã‚°ãƒ©ãƒ ã¸ã®ã‚³ãƒžãƒ³ãƒ‰é€ä¿¡ã«å¤±æ•—ã—ã¾ã—ãŸ" - -#~ msgid "E573: Invalid server id used: %s" -#~ msgstr "E573: 無効ãªã‚µãƒ¼ãƒIDãŒä½¿ã‚れã¾ã—ãŸ: %s" - -#~ msgid "E251: VIM instance registry property is badly formed. Deleted!" -#~ msgstr "E251: VIM 実体ã®ç™»éŒ²ãƒ—ãƒãƒ‘ティãŒä¸æ£ã§ã™. 消去ã—ã¾ã—ãŸ!" - -#~ msgid "netbeans is not supported with this GUI\n" -#~ msgstr "netbeans ã¯ã“ã®GUIã§ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“\n" - -#~ msgid "This Vim was not compiled with the diff feature." -#~ msgstr "ã“ã®Vimã«ã¯diff機能ãŒã‚りã¾ã›ã‚“(コンパイル時è¨å®š)." - -#~ msgid "'-nb' cannot be used: not enabled at compile time\n" -#~ msgstr "'-nb' 使用ä¸å¯èƒ½ã§ã™: コンパイル時ã«ç„¡åйã«ã•れã¦ã„ã¾ã™\n" - -#~ msgid "Vim: Error: Failure to start gvim from NetBeans\n" -#~ msgstr "Vim: エラー: NetBeansã‹ã‚‰gvimをスタートã§ãã¾ã›ã‚“\n" - -#~ msgid "" -#~ "\n" -#~ "Where case is ignored prepend / to make flag upper case" -#~ msgstr "" -#~ "\n" -#~ "大尿–‡å—ãŒç„¡è¦–ã•ã‚Œã‚‹å ´åˆã¯å¤§æ–‡å—ã«ã™ã‚‹ãŸã‚ã« / ã‚’å‰ç½®ã—ã¦ãã ã•ã„" - -#~ msgid "-register\t\tRegister this gvim for OLE" -#~ msgstr "-register\t\tã“ã®gvimã‚’OLEã¨ã—ã¦ç™»éŒ²ã™ã‚‹" - -#~ msgid "-unregister\t\tUnregister gvim for OLE" -#~ msgstr "-unregister\t\tgvimã®OLE登録を解除ã™ã‚‹" - -#~ msgid "-g\t\t\tRun using GUI (like \"gvim\")" -#~ msgstr "-g\t\t\tGUIã§èµ·å‹•ã™ã‚‹ (\"gvim\" ã¨åŒã˜)" - -#~ msgid "-f or --nofork\tForeground: Don't fork when starting GUI" -#~ msgstr "-f or --nofork\tフォアグラウンド: GUIã‚’å§‹ã‚ã‚‹ã¨ãã«forkã—ãªã„" - -#~ msgid "-f\t\t\tDon't use newcli to open window" -#~ msgstr "-f\t\t\tウィンドウを開ãã®ã« newcli を使用ã—ãªã„" - -#~ msgid "-dev <device>\t\tUse <device> for I/O" -#~ msgstr "-dev <device>\t\tI/Oã« <device> を使用ã™ã‚‹" - -#~ msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" -#~ msgstr "-U <gvimrc>\t\t.gvimrcã®ä»£ã‚り㫠<gvimrc> を使ã†" - -#~ msgid "-x\t\t\tEdit encrypted files" -#~ msgstr "-x\t\t\tæš—å·åŒ–ã•れãŸãƒ•ァイルを編集ã™ã‚‹" - -#~ msgid "-display <display>\tConnect vim to this particular X-server" -#~ msgstr "-display <display>\tvimを指定ã—㟠X サーãƒã«æŽ¥ç¶šã™ã‚‹" - -#~ msgid "-X\t\t\tDo not connect to X server" -#~ msgstr "-X\t\t\tXサーãƒã«æŽ¥ç¶šã—ãªã„" - -#~ msgid "--remote <files>\tEdit <files> in a Vim server if possible" -#~ msgstr "--remote <files>\tå¯èƒ½ãªã‚‰ã°Vimサーãƒã§ <files> を編集ã™ã‚‹" - -#~ msgid "--remote-silent <files> Same, don't complain if there is no server" -#~ msgstr "--remote-silent <files> åŒä¸Š, サーãƒãŒç„¡ãã¦ã‚‚è¦å‘Šæ–‡ã‚’出力ã—ãªã„" - -#~ msgid "" -#~ "--remote-wait <files> As --remote but wait for files to have been edited" -#~ msgstr "--remote-wait <files>\t--remote後 ファイルã®ç·¨é›†ãŒçµ‚ã‚ã‚‹ã®ã‚’å¾…ã¤" - -#~ msgid "" -#~ "--remote-wait-silent <files> Same, don't complain if there is no server" -#~ msgstr "" -#~ "--remote-wait-silent <files> åŒä¸Š, サーãƒãŒç„¡ãã¦ã‚‚è¦å‘Šæ–‡ã‚’出力ã—ãªã„" - -#~ msgid "" -#~ "--remote-tab[-wait][-silent] <files> As --remote but use tab page per " -#~ "file" -#~ msgstr "" -#~ "--remote-tab[-wait][-silent] <files> --remoteã§ãƒ•ァイル1ã¤ã«ã¤ã1ã¤ã®ã‚¿ãƒ–" -#~ "ページを開ã" - -#~ msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" -#~ msgstr "--remote-send <keys>\tVimサーãƒã« <keys> ã‚’é€ä¿¡ã—ã¦çµ‚了ã™ã‚‹" - -#~ msgid "" -#~ "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" -#~ msgstr "--remote-expr <expr>\tサーãƒã§ <expr> を実行ã—ã¦çµæžœã‚’表示ã™ã‚‹" - -#~ msgid "--serverlist\t\tList available Vim server names and exit" -#~ msgstr "--serverlist\t\tVimサーãƒåã®ä¸€è¦§ã‚’表示ã—ã¦çµ‚了ã™ã‚‹" - -#~ msgid "--servername <name>\tSend to/become the Vim server <name>" -#~ msgstr "--servername <name>\tVimサーム<name> ã«é€ä¿¡/åå‰è¨å®šã™ã‚‹" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (Motif version):\n" -#~ msgstr "" -#~ "\n" -#~ "gvimã«ã‚ˆã£ã¦è§£é‡ˆã•れる引数(Motifãƒãƒ¼ã‚¸ãƒ§ãƒ³):\n" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (neXtaw version):\n" -#~ msgstr "" -#~ "\n" -#~ "gvimã«ã‚ˆã£ã¦è§£é‡ˆã•れる引数(neXtawãƒãƒ¼ã‚¸ãƒ§ãƒ³):\n" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (Athena version):\n" -#~ msgstr "" -#~ "\n" -#~ "gvimã«ã‚ˆã£ã¦è§£é‡ˆã•れる引数(Athenaãƒãƒ¼ã‚¸ãƒ§ãƒ³):\n" - -#~ msgid "-display <display>\tRun vim on <display>" -#~ msgstr "-display <display>\t<display> ã§vimを実行ã™ã‚‹" - -#~ msgid "-iconic\t\tStart vim iconified" -#~ msgstr "-iconic\t\t最å°åŒ–ã—ãŸçŠ¶æ…‹ã§vimã‚’èµ·å‹•ã™ã‚‹" - -#~ msgid "-background <color>\tUse <color> for the background (also: -bg)" -#~ msgstr "-background <color>\t背景色㫠<color> を使ã†(åŒç¾©: -bg)" - -#~ msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" -#~ msgstr "-foreground <color>\t剿™¯è‰²ã« <color> を使ã†(åŒç¾©: -fg)" - -#~ msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" -#~ msgstr "-font <font>\t\tテã‚スト表示㫠<font> を使ã†(åŒç¾©: -fn)" - -#~ msgid "-boldfont <font>\tUse <font> for bold text" -#~ msgstr "-boldfont <font>\t太å—ã« <font> を使ã†" - -#~ msgid "-italicfont <font>\tUse <font> for italic text" -#~ msgstr "-italicfont <for>\t斜体å—ã« <font> を使ã†" - -#~ msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" -#~ msgstr "-geometry <geom>\tåˆæœŸé…置㫠<geom> を使ã†(åŒç¾©: -geom)" - -#~ msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" -#~ msgstr "-borderwidth <width>\t境界ã®å¹…ã‚’ <width> ã«ã™ã‚‹(åŒç¾©: -bw)" - -#~ msgid "" -#~ "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" -#~ msgstr "" -#~ "-scrollbarwidth <width> スクãƒãƒ¼ãƒ«ãƒãƒ¼ã®å¹…ã‚’ <width> ã«ã™ã‚‹(åŒç¾©: -sw)" - -#~ msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" -#~ msgstr "" -#~ "-menuheight <height>\tメニューãƒãƒ¼ã®é«˜ã•ã‚’ <height> ã«ã™ã‚‹(åŒç¾©: -mh)" - -#~ msgid "-reverse\t\tUse reverse video (also: -rv)" -#~ msgstr "-reverse\t\tåè»¢æ˜ åƒã‚’使用ã™ã‚‹(åŒç¾©: -rv)" - -#~ msgid "+reverse\t\tDon't use reverse video (also: +rv)" -#~ msgstr "+reverse\t\tåè»¢æ˜ åƒã‚’使用ã—ãªã„(åŒç¾©: +rv)" - -#~ msgid "-xrm <resource>\tSet the specified resource" -#~ msgstr "-xrm <resource>\t特定ã®ãƒªã‚½ãƒ¼ã‚¹ã‚’使用ã™ã‚‹" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (GTK+ version):\n" -#~ msgstr "" -#~ "\n" -#~ "gvimã«ã‚ˆã£ã¦è§£é‡ˆã•れる引数(GTK+ãƒãƒ¼ã‚¸ãƒ§ãƒ³):\n" - -#~ msgid "-display <display>\tRun vim on <display> (also: --display)" -#~ msgstr "-display <display>\t<display> ã§vimを実行ã™ã‚‹(åŒç¾©: --display)" - -#~ msgid "--role <role>\tSet a unique role to identify the main window" -#~ msgstr "--role <role>\tメインウィンドウをè˜åˆ¥ã™ã‚‹ä¸€æ„ãªå½¹å‰²(role)ã‚’è¨å®šã™ã‚‹" - -#~ msgid "--socketid <xid>\tOpen Vim inside another GTK widget" -#~ msgstr "--socketid <xid>\tç•°ãªã‚‹GTK widgetã§Vimã‚’é–‹ã" - -#~ msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" -#~ msgstr "--echo-wid\t\tウィンドウIDを標準出力ã«å‡ºåŠ›ã™ã‚‹" - -#~ msgid "-P <parent title>\tOpen Vim inside parent application" -#~ msgstr "-P <親ã®ã‚¿ã‚¤ãƒˆãƒ«>\tVimを親アプリケーションã®ä¸ã§èµ·å‹•ã™ã‚‹" - -#~ msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" -#~ msgstr "--windowid <HWND>\tç•°ãªã‚‹Win32 widgetã®å†…部ã«Vimã‚’é–‹ã" - -#~ msgid "No display" -#~ msgstr "ディスプレイãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" - -#~ msgid ": Send failed.\n" -#~ msgstr ": é€ä¿¡ã«å¤±æ•—ã—ã¾ã—ãŸ.\n" - -#~ msgid ": Send failed. Trying to execute locally\n" -#~ msgstr ": é€ä¿¡ã«å¤±æ•—ã—ã¾ã—ãŸ. ãƒãƒ¼ã‚«ãƒ«ã§ã®å®Ÿè¡Œã‚’試ã¿ã¦ã„ã¾ã™\n" - -#~ msgid "%d of %d edited" -#~ msgstr "%d 個 (%d 個ä¸) ã®ãƒ•ァイルを編集ã—ã¾ã—ãŸ" - -#~ msgid "No display: Send expression failed.\n" -#~ msgstr "ディスプレイãŒã‚りã¾ã›ã‚“: å¼ã®é€ä¿¡ã«å¤±æ•—ã—ã¾ã—ãŸ.\n" - -#~ msgid ": Send expression failed.\n" -#~ msgstr ": å¼ã®é€ä¿¡ã«å¤±æ•—ã—ã¾ã—ãŸ.\n" - -#~ msgid "E543: Not a valid codepage" -#~ msgstr "E543: 無効ãªã‚³ãƒ¼ãƒ‰ãƒšãƒ¼ã‚¸ã§ã™" - -#~ msgid "E284: Cannot set IC values" -#~ msgstr "E284: ICã®å€¤ã‚’è¨å®šã§ãã¾ã›ã‚“" - -#~ msgid "E285: Failed to create input context" -#~ msgstr "E285: インプットコンテã‚ストã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸ" - -#~ msgid "E286: Failed to open input method" -#~ msgstr "E286: インプットメソッドã®ã‚ªãƒ¼ãƒ—ンã«å¤±æ•—ã—ã¾ã—ãŸ" - -#~ msgid "E287: Warning: Could not set destroy callback to IM" -#~ msgstr "E287: è¦å‘Š: IMã®ç ´å£Šã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯ã‚’è¨å®šã§ãã¾ã›ã‚“ã§ã—ãŸ" - -#~ msgid "E288: input method doesn't support any style" -#~ msgstr "E288: インプットメソッドã¯ã©ã‚“ãªã‚¹ã‚¿ã‚¤ãƒ«ã‚‚サãƒãƒ¼ãƒˆã—ã¾ã›ã‚“" - -#~ msgid "E289: input method doesn't support my preedit type" -#~ msgstr "E289: インプットメソッド㯠my preedit type をサãƒãƒ¼ãƒˆã—ã¾ã›ã‚“" +#, c-format +msgid "E447: Can't find file \"%s\" in path" +msgstr "E447: pathã«ã¯ \"%s\" ã¨ã„ã†ãƒ•ァイルãŒã‚りã¾ã›ã‚“" -#~ msgid "E843: Error while updating swap file crypt" -#~ msgstr "E843: ã‚¹ãƒ¯ãƒƒãƒ—ãƒ•ã‚¡ã‚¤ãƒ«ã®æš—å·ã‚’æ›´æ–°ä¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ" +#, c-format +msgid "E799: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E799: 無効㪠ID: %ld (1 以上ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“)" -#~ msgid "" -#~ "E833: %s is encrypted and this version of Vim does not support encryption" -#~ msgstr "" -#~ "E833: %s ã¯ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®Vimã§ã‚µãƒãƒ¼ãƒˆã—ã¦ã„ãªã„å½¢å¼ã§æš—å·åŒ–ã•れã¦ã„ã¾ã™" +#, c-format +msgid "E801: ID already taken: %ld" +msgstr "E801: ID ã¯ã™ã§ã«åˆ©ç”¨ä¸ã§ã™: %ld" -#~ msgid "Swap file is encrypted: \"%s\"" -#~ msgstr "ã‚¹ãƒ¯ãƒƒãƒ—ãƒ•ã‚¡ã‚¤ãƒ«ã¯æš—å·åŒ–ã•れã¦ã„ã¾ã™: \"%s\"" +msgid "List or number required" +msgstr "ãƒªã‚¹ãƒˆã‹æ•°å€¤ãŒå¿…è¦ã§ã™" -#~ msgid "" -#~ "\n" -#~ "If you entered a new crypt key but did not write the text file," -#~ msgstr "" -#~ "\n" -#~ "æ–°ã—ã„æš—å·ã‚ーを入力ã—ãŸã‚ã¨ã«ãƒ†ã‚ストファイルをä¿å˜ã—ã¦ã„ãªã„å ´åˆã¯," +#, c-format +msgid "E802: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E802: 無効㪠ID: %ld (1 以上ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“)" -#~ msgid "" -#~ "\n" -#~ "enter the new crypt key." -#~ msgstr "" -#~ "\n" -#~ "æ–°ã—ã„æš—å·ã‚ーを入力ã—ã¦ãã ã•ã„." +#, c-format +msgid "E803: ID not found: %ld" +msgstr "E803: ID ã¯ã‚りã¾ã›ã‚“: %ld" -#~ msgid "" -#~ "\n" -#~ "If you wrote the text file after changing the crypt key press enter" -#~ msgstr "" -#~ "\n" -#~ "æš—å·ã‚ーを変ãˆãŸã‚ã¨ã«ãƒ†ã‚ストファイルをä¿å˜ã—ãŸå ´åˆã¯, テã‚ストファイルã¨" +#, c-format +msgid "E370: Could not load library %s" +msgstr "E370: ライブラリ %s ã‚’ãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§ã—ãŸ" -#~ msgid "" -#~ "\n" -#~ "to use the same key for text file and swap file" -#~ msgstr "" -#~ "\n" -#~ "スワップファイルã«åŒã˜æš—å·ã‚ーを使ã†ãŸã‚ã«enterã ã‘を押ã—ã¦ãã ã•ã„." +msgid "Sorry, this command is disabled: the Perl library could not be loaded." +msgstr "" +"ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ç„¡åйã§ã™, ã”ã‚ã‚“ãªã•ã„: Perlライブラリをãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§ã—ãŸ." -#~ msgid "Using crypt key from swap file for the text file.\n" -#~ msgstr "スワップファイルã‹ã‚‰å–å¾—ã—ãŸæš—å·ã‚ーをテã‚ストファイルã«ä½¿ã„ã¾ã™.\n" +msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" +msgstr "" +"E299: サンドボックスã§ã¯ Safe モジュールを使用ã—ãªã„Perlスクリプトã¯ç¦ã˜ã‚‰ã‚Œ" +"ã¦ã„ã¾ã™" -#~ msgid "" -#~ "\n" -#~ " [not usable with this version of Vim]" -#~ msgstr "" -#~ "\n" -#~ " [ã“ã®Vimãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“]" +msgid "Edit with &multiple Vims" +msgstr "複数ã®Vimã§ç·¨é›†ã™ã‚‹ (&M)" -#~ msgid "Tear off this menu" -#~ msgstr "ã“ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚’切りå–ã‚‹" +msgid "Edit with single &Vim" +msgstr "1ã¤ã®Vimã§ç·¨é›†ã™ã‚‹ (&V)" -#~ msgid "Select Directory dialog" -#~ msgstr "ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªé¸æŠžãƒ€ã‚¤ã‚¢ãƒã‚°" +msgid "Diff with Vim" +msgstr "Vimã§å·®åˆ†ã‚’表示ã™ã‚‹" -#~ msgid "Save File dialog" -#~ msgstr "ファイルä¿å˜ãƒ€ã‚¤ã‚¢ãƒã‚°" +msgid "Edit with &Vim" +msgstr "Vimã§ç·¨é›†ã™ã‚‹ (&V)" -#~ msgid "Open File dialog" -#~ msgstr "ファイルèªè¾¼ãƒ€ã‚¤ã‚¢ãƒã‚°" +#. Now concatenate +msgid "Edit with existing Vim - " +msgstr "起動済ã®Vimã§ç·¨é›†ã™ã‚‹ - " -#~ msgid "E338: Sorry, no file browser in console mode" -#~ msgstr "" -#~ "E338: コンソールモードã§ã¯ãƒ•ァイルブラウザを使ãˆã¾ã›ã‚“, ã”ã‚ã‚“ãªã•ã„" +msgid "Edits the selected file(s) with Vim" +msgstr "é¸æŠžã—ãŸãƒ•ァイルをVimã§ç·¨é›†ã™ã‚‹" -#~ msgid "Vim: preserving files...\n" -#~ msgstr "Vim: ファイルをä¿å˜ä¸...\n" +msgid "Error creating process: Check if gvim is in your path!" +msgstr "プãƒã‚»ã‚¹ã®ä½œæˆã«å¤±æ•—: gvimãŒç’°å¢ƒå¤‰æ•°PATH上ã«ã‚ã‚‹ã‹ç¢ºèªã—ã¦ãã ã•ã„!" -#~ msgid "Vim: Finished.\n" -#~ msgstr "Vim: 終了ã—ã¾ã—ãŸ.\n" +msgid "gvimext.dll error" +msgstr "gvimext.dll エラー" -#~ msgid "ERROR: " -#~ msgstr "エラー: " +msgid "Path length too long!" +msgstr "パスãŒé•·éŽãŽã¾ã™!" -#~ msgid "" -#~ "\n" -#~ "[bytes] total alloc-freed %<PRIu64>-%<PRIu64>, in use %<PRIu64>, peak use " -#~ "%<PRIu64>\n" -#~ msgstr "" -#~ "\n" -#~ "[メモリ(ãƒã‚¤ãƒˆ)] ç·å‰²å½“-è§£æ”¾é‡ %<PRIu64>-%<PRIu64>, ä½¿ç”¨é‡ %<PRIu64>, ピー" -#~ "ク時 %<PRIu64>\n" +msgid "--No lines in buffer--" +msgstr "--ãƒãƒƒãƒ•ã‚¡ã«è¡ŒãŒã‚りã¾ã›ã‚“--" -#~ msgid "" -#~ "[calls] total re/malloc()'s %<PRIu64>, total free()'s %<PRIu64>\n" -#~ "\n" -#~ msgstr "" -#~ "[呼出] ç· re/malloc() 回数 %<PRIu64>, ç· free() 回数 %<PRIu64>\n" -#~ "\n" +#. +#. * The error messages that can be shared are included here. +#. * Excluded are errors that are only used once and debugging messages. +#. +msgid "E470: Command aborted" +msgstr "E470: コマンドãŒä¸æ–ã•れã¾ã—ãŸ" -#~ msgid "E340: Line is becoming too long" -#~ msgstr "E340: 行ãŒé•·ããªã‚ŠéŽãŽã¾ã—ãŸ" +msgid "E471: Argument required" +msgstr "E471: 引数ãŒå¿…è¦ã§ã™" -#~ msgid "E341: Internal error: lalloc(%<PRId64>, )" -#~ msgstr "E341: 内部エラー: lalloc(%<PRId64>,)" +msgid "E10: \\ should be followed by /, ? or &" +msgstr "E10: \\ ã®å¾Œã¯ / ã‹ ? ã‹ & ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" -#~ msgid "E547: Illegal mouseshape" -#~ msgstr "E547: 䏿£ãª 'mouseshape' ã§ã™" +msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" +msgstr "E11: コマンドラインã§ã¯ç„¡åйã§ã™; <CR>ã§å®Ÿè¡Œ, CTRL-Cã§ã‚„ã‚ã‚‹" -#~ msgid "Enter encryption key: " -#~ msgstr "æš—å·åŒ–用ã®ã‚ーを入力ã—ã¦ãã ã•ã„: " +msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" +msgstr "" +"E12: ç¾åœ¨ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚„タグ検索ã§ã¯exrc/vimrcã®ã‚³ãƒžãƒ³ãƒ‰ã¯è¨±å¯ã•れã¾ã›ã‚“" -#~ msgid "Enter same key again: " -#~ msgstr "ã‚‚ã†ä¸€åº¦åŒã˜ã‚ーを入力ã—ã¦ãã ã•ã„: " +msgid "E171: Missing :endif" +msgstr "E171: :endif ãŒã‚りã¾ã›ã‚“" -#~ msgid "Keys don't match!" -#~ msgstr "ã‚ーãŒä¸€è‡´ã—ã¾ã›ã‚“" +msgid "E600: Missing :endtry" +msgstr "E600: :endtry ãŒã‚りã¾ã›ã‚“" -#~ msgid "Cannot connect to Netbeans #2" -#~ msgstr "Netbeans #2 ã«æŽ¥ç¶šã§ãã¾ã›ã‚“" +msgid "E170: Missing :endwhile" +msgstr "E170: :endwhile ãŒã‚りã¾ã›ã‚“" -#~ msgid "Cannot connect to Netbeans" -#~ msgstr "Netbeans ã«æŽ¥ç¶šã§ãã¾ã›ã‚“" +msgid "E170: Missing :endfor" +msgstr "E170: :endfor ãŒã‚りã¾ã›ã‚“" -#~ msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" -#~ msgstr "" -#~ "E668: NetBeansã®æŽ¥ç¶šæƒ…å ±ãƒ•ã‚¡ã‚¤ãƒ«ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒ¢ãƒ¼ãƒ‰ã«å•題ãŒã‚りã¾ã™: \"%s\"" +msgid "E588: :endwhile without :while" +msgstr "E588: :while ã®ãªã„ :endwhile ãŒã‚りã¾ã™" -#~ msgid "read from Netbeans socket" -#~ msgstr "Netbeans ã®ã‚½ã‚±ãƒƒãƒˆã‚’èªè¾¼ã¿" +msgid "E588: :endfor without :for" +msgstr "E588: :endfor ã®ãªã„ :for ãŒã‚りã¾ã™" -#~ msgid "E658: NetBeans connection lost for buffer %<PRId64>" -#~ msgstr "E658: ãƒãƒƒãƒ•ã‚¡ %<PRId64> ã® NetBeans 接続ãŒå¤±ã‚れã¾ã—ãŸ" +msgid "E13: File exists (add ! to override)" +msgstr "E13: ファイルãŒå˜åœ¨ã—ã¾ã™ (! ã‚’è¿½åŠ ã§ä¸Šæ›¸)" -#~ msgid "E838: netbeans is not supported with this GUI" -#~ msgstr "E838: NetBeansã¯ã“ã®GUIã«ã¯å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“" +msgid "E472: Command failed" +msgstr "E472: コマンドãŒå¤±æ•—ã—ã¾ã—ãŸ" -#~ msgid "E511: netbeans already connected" -#~ msgstr "E511: NetBeansã¯æ—¢ã«æŽ¥ç¶šã—ã¦ã„ã¾ã™" +#, c-format +msgid "E234: Unknown fontset: %s" +msgstr "E234: 未知ã®ãƒ•ォントセット: %s" -#~ msgid "E505: %s is read-only (add ! to override)" -#~ msgstr "E505: %s ã¯èªè¾¼å°‚用ã§ã™ (強制書込ã«ã¯ ! ã‚’è¿½åŠ )" +#, c-format +msgid "E235: Unknown font: %s" +msgstr "E235: 未知ã®ãƒ•ォント: %s" -#~ msgid "E775: Eval feature not available" -#~ msgstr "E775: å¼è©•価機能ãŒç„¡åйã«ãªã£ã¦ã„ã¾ã™" +#, c-format +msgid "E236: Font \"%s\" is not fixed-width" +msgstr "E236: フォント \"%s\" ã¯å›ºå®šå¹…ã§ã¯ã‚りã¾ã›ã‚“" -#~ msgid "freeing %<PRId64> lines" -#~ msgstr "%<PRId64> 行を解放ä¸" +msgid "E473: Internal error" +msgstr "E473: 内部エラーã§ã™" -#~ msgid "E530: Cannot change term in GUI" -#~ msgstr "E530: GUIã§ã¯ 'term' を変更ã§ãã¾ã›ã‚“" +msgid "Interrupted" +msgstr "割込ã¾ã‚Œã¾ã—ãŸ" -#~ msgid "E531: Use \":gui\" to start the GUI" -#~ msgstr "E531: GUIをスタートã™ã‚‹ã«ã¯ \":gui\" を使用ã—ã¦ãã ã•ã„" +msgid "E14: Invalid address" +msgstr "E14: 無効ãªã‚¢ãƒ‰ãƒ¬ã‚¹ã§ã™" -#~ msgid "E617: Cannot be changed in the GTK+ 2 GUI" -#~ msgstr "E617: GTK+2 GUIã§ã¯å¤‰æ›´ã§ãã¾ã›ã‚“" +msgid "E474: Invalid argument" +msgstr "E474: 無効ãªå¼•æ•°ã§ã™" -#~ msgid "E596: Invalid font(s)" -#~ msgstr "E596: 無効ãªãƒ•ォントã§ã™" +#, c-format +msgid "E475: Invalid argument: %s" +msgstr "E475: 無効ãªå¼•æ•°ã§ã™: %s" -#~ msgid "E597: can't select fontset" -#~ msgstr "E597: ãƒ•ã‚©ãƒ³ãƒˆã‚»ãƒƒãƒˆã‚’é¸æŠžã§ãã¾ã›ã‚“" +#, c-format +msgid "E15: Invalid expression: %s" +msgstr "E15: 無効ãªå¼ã§ã™: %s" -#~ msgid "E598: Invalid fontset" -#~ msgstr "E598: 無効ãªãƒ•ォントセットã§ã™" +msgid "E16: Invalid range" +msgstr "E16: 無効ãªç¯„囲ã§ã™" -#~ msgid "E533: can't select wide font" -#~ msgstr "E533: ãƒ¯ã‚¤ãƒ‰ãƒ•ã‚©ãƒ³ãƒˆã‚’é¸æŠžã§ãã¾ã›ã‚“" +msgid "E476: Invalid command" +msgstr "E476: 無効ãªã‚³ãƒžãƒ³ãƒ‰ã§ã™" -#~ msgid "E534: Invalid wide font" -#~ msgstr "E534: 無効ãªãƒ¯ã‚¤ãƒ‰ãƒ•ォントã§ã™" +#, c-format +msgid "E17: \"%s\" is a directory" +msgstr "E17: \"%s\" ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã§ã™" -#~ msgid "E538: No mouse support" -#~ msgstr "E538: マウスã¯ã‚µãƒãƒ¼ãƒˆã•れã¾ã›ã‚“" +#, c-format +msgid "E364: Library call failed for \"%s()\"" +msgstr "E364: \"%s\"() ã®ãƒ©ã‚¤ãƒ–ラリ呼出ã«å¤±æ•—ã—ã¾ã—ãŸ" -#~ msgid "cannot open " -#~ msgstr "é–‹ã‘ã¾ã›ã‚“ " +#, c-format +msgid "E448: Could not load library function %s" +msgstr "E448: ライブラリã®é–¢æ•° %s ã‚’ãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§ã—ãŸ" -#~ msgid "VIM: Can't open window!\n" -#~ msgstr "VIM: ウィンドウを開ã‘ã¾ã›ã‚“!\n" +msgid "E19: Mark has invalid line number" +msgstr "E19: マークã«ç„¡åйãªè¡Œç•ªå·ãŒæŒ‡å®šã•れã¦ã„ã¾ã—ãŸ" -#~ msgid "Need Amigados version 2.04 or later\n" -#~ msgstr "Amigadosã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 2.04ã‹ãれ以é™ãŒå¿…è¦ã§ã™\n" +msgid "E20: Mark not set" +msgstr "E20: マークã¯è¨å®šã•れã¦ã„ã¾ã›ã‚“" -#~ msgid "Need %s version %<PRId64>\n" -#~ msgstr "%s ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ %<PRId64> ãŒå¿…è¦ã§ã™\n" +msgid "E21: Cannot make changes, 'modifiable' is off" +msgstr "E21: 'modifiable' ãŒã‚ªãƒ•ãªã®ã§, 変更ã§ãã¾ã›ã‚“" -#~ msgid "Cannot open NIL:\n" -#~ msgstr "NILã‚’é–‹ã‘ã¾ã›ã‚“:\n" +msgid "E22: Scripts nested too deep" +msgstr "E22: スクリプトã®å…¥ã‚ŒåãŒæ·±éŽãŽã¾ã™" -#~ msgid "Cannot create " -#~ msgstr "作æˆã§ãã¾ã›ã‚“ " +msgid "E23: No alternate file" +msgstr "E23: 副ファイルã¯ã‚りã¾ã›ã‚“" -#~ msgid "Vim exiting with %d\n" -#~ msgstr "Vim㯠%d ã§çµ‚了ã—ã¾ã™\n" +msgid "E24: No such abbreviation" +msgstr "E24: ãã®ã‚ˆã†ãªçŸç¸®å…¥åŠ›ã¯ã‚りã¾ã›ã‚“" -#~ msgid "cannot change console mode ?!\n" -#~ msgstr "コンソールモードを変更ã§ãã¾ã›ã‚“?!\n" +msgid "E477: No ! allowed" +msgstr "E477: ! ã¯è¨±å¯ã•れã¦ã„ã¾ã›ã‚“" -#~ msgid "mch_get_shellsize: not a console??\n" -#~ msgstr "mch_get_shellsize: コンソールã§ã¯ãªã„??\n" +msgid "E25: GUI cannot be used: Not enabled at compile time" +msgstr "E25: GUIã¯ä½¿ç”¨ä¸å¯èƒ½ã§ã™: コンパイル時ã«ç„¡åйã«ã•れã¦ã„ã¾ã™" -#~ msgid "E360: Cannot execute shell with -f option" -#~ msgstr "E360: -f オプションã§ã‚·ã‚§ãƒ«ã‚’実行ã§ãã¾ã›ã‚“" +msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" +msgstr "E26: ヘブライ語ã¯ä½¿ç”¨ä¸å¯èƒ½ã§ã™: コンパイル時ã«ç„¡åйã«ã•れã¦ã„ã¾ã™\n" -#~ msgid "Cannot execute " -#~ msgstr "実行ã§ãã¾ã›ã‚“ " +msgid "E27: Farsi cannot be used: Not enabled at compile time\n" +msgstr "E27: ペルシア語ã¯ä½¿ç”¨ä¸å¯èƒ½ã§ã™: コンパイル時ã«ç„¡åйã«ã•れã¦ã„ã¾ã™\n" -#~ msgid "shell " -#~ msgstr "シェル " +msgid "E800: Arabic cannot be used: Not enabled at compile time\n" +msgstr "E800: アラビア語ã¯ä½¿ç”¨ä¸å¯èƒ½ã§ã™: コンパイル時ã«ç„¡åйã«ã•れã¦ã„ã¾ã™\n" -#~ msgid " returned\n" -#~ msgstr " 戻りã¾ã—ãŸ\n" +#, c-format +msgid "E28: No such highlight group name: %s" +msgstr "E28: ãã®ã‚ˆã†ãªåã®ãƒã‚¤ãƒ©ã‚¤ãƒˆã‚°ãƒ«ãƒ¼ãƒ—ã¯ã‚りã¾ã›ã‚“: %s" -#~ msgid "ANCHOR_BUF_SIZE too small." -#~ msgstr "ANCHOR_BUF_SIZE ãŒå°ã•éŽãŽã¾ã™." +msgid "E29: No inserted text yet" +msgstr "E29: ã¾ã テã‚ã‚¹ãƒˆãŒæŒ¿å…¥ã•れã¦ã„ã¾ã›ã‚“" -#~ msgid "I/O ERROR" -#~ msgstr "入出力エラー" +msgid "E30: No previous command line" +msgstr "E30: 以å‰ã«ã‚³ãƒžãƒ³ãƒ‰è¡ŒãŒã‚りã¾ã›ã‚“" -#~ msgid "Message" -#~ msgstr "メッセージ" +msgid "E31: No such mapping" +msgstr "E31: ãã®ã‚ˆã†ãªãƒžãƒƒãƒ”ングã¯ã‚りã¾ã›ã‚“" -#~ msgid "'columns' is not 80, cannot execute external commands" -#~ msgstr "'columns' ãŒ80ã§ã¯ãªã„ãŸã‚, 外部コマンドを実行ã§ãã¾ã›ã‚“" +msgid "E479: No match" +msgstr "E479: 該当ã¯ã‚りã¾ã›ã‚“" -#~ msgid "E237: Printer selection failed" -#~ msgstr "E237: プリンタã®é¸æŠžã«å¤±æ•—ã—ã¾ã—ãŸ" +#, c-format +msgid "E480: No match: %s" +msgstr "E480: 該当ã¯ã‚りã¾ã›ã‚“: %s" -#~ msgid "to %s on %s" -#~ msgstr "%s 㸠(%s 上ã®)" +msgid "E32: No file name" +msgstr "E32: ファイルåãŒã‚りã¾ã›ã‚“" -#~ msgid "E613: Unknown printer font: %s" -#~ msgstr "E613: 未知ã®ãƒ—リンタオプションã§ã™: %s" +msgid "E33: No previous substitute regular expression" +msgstr "E33: æ£è¦è¡¨ç¾ç½®æ›ãŒã¾ã 実行ã•れã¦ã„ã¾ã›ã‚“" -#~ msgid "E238: Print error: %s" -#~ msgstr "E238: å°åˆ·ã‚¨ãƒ©ãƒ¼: %s" +msgid "E34: No previous command" +msgstr "E34: コマンドãŒã¾ã 実行ã•れã¦ã„ã¾ã›ã‚“" -#~ msgid "Printing '%s'" -#~ msgstr "å°åˆ·ã—ã¦ã„ã¾ã™: '%s'" +msgid "E35: No previous regular expression" +msgstr "E35: æ£è¦è¡¨ç¾ãŒã¾ã 実行ã•れã¦ã„ã¾ã›ã‚“" -#~ msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" -#~ msgstr "E244: æ–‡å—セットå \"%s\" ã¯ä¸æ£ã§ã™ (フォントå \"%s\")" +msgid "E481: No range allowed" +msgstr "E481: 範囲指定ã¯è¨±å¯ã•れã¦ã„ã¾ã›ã‚“" -#~ msgid "E245: Illegal char '%c' in font name \"%s\"" -#~ msgstr "E245: '%c' ã¯ä¸æ£ãªæ–‡å—ã§ã™ (フォントå \"%s\")" +msgid "E36: Not enough room" +msgstr "E36: ウィンドウã«å分ãªé«˜ã•ã‚‚ã—ãã¯å¹…ãŒã‚りã¾ã›ã‚“" -#~ msgid "Vim: Double signal, exiting\n" -#~ msgstr "Vim: 2é‡ã®ã‚·ã‚°ãƒŠãƒ«ã®ãŸã‚, 終了ã—ã¾ã™\n" +#, c-format +msgid "E247: no registered server named \"%s\"" +msgstr "E247: %s ã¨ã„ã†åå‰ã®ç™»éŒ²ã•れãŸã‚µãƒ¼ãƒãƒ¼ã¯ã‚りã¾ã›ã‚“" -#~ msgid "Vim: Caught deadly signal %s\n" -#~ msgstr "Vim: 致命的シグナル %s を検知ã—ã¾ã—ãŸ\n" +#, c-format +msgid "E482: Can't create file %s" +msgstr "E482: ファイル %s を作æˆã§ãã¾ã›ã‚“" -#~ msgid "Vim: Caught deadly signal\n" -#~ msgstr "Vim: 致命的シグナルを検知ã—ã¾ã—ãŸ\n" +msgid "E483: Can't get temp file name" +msgstr "E483: 一時ファイルã®åå‰ã‚’å–å¾—ã§ãã¾ã›ã‚“" -#~ msgid "Opening the X display took %<PRId64> msec" -#~ msgstr "Xサーãƒã¸ã®æŽ¥ç¶šã« %<PRId64> ミリ秒ã‹ã‹ã‚Šã¾ã—ãŸ" +#, c-format +msgid "E484: Can't open file %s" +msgstr "E484: ファイル \"%s\" ã‚’é–‹ã‘ã¾ã›ã‚“" -#~ msgid "" -#~ "\n" -#~ "Vim: Got X error\n" -#~ msgstr "" -#~ "\n" -#~ "Vim: X ã®ã‚¨ãƒ©ãƒ¼ã‚’検出ã—ã¾ã—ãŸr\n" +#, c-format +msgid "E485: Can't read file %s" +msgstr "E485: ファイル %s ã‚’èªè¾¼ã‚ã¾ã›ã‚“" -#~ msgid "Testing the X display failed" -#~ msgstr "X display ã®ãƒã‚§ãƒƒã‚¯ã«å¤±æ•—ã—ã¾ã—ãŸ" +msgid "E37: No write since last change (add ! to override)" +msgstr "E37: 最後ã®å¤‰æ›´ãŒä¿å˜ã•れã¦ã„ã¾ã›ã‚“ (! ã‚’è¿½åŠ ã§å¤‰æ›´ã‚’ç ´æ£„)" -#~ msgid "Opening the X display timed out" -#~ msgstr "X display ã® open ãŒã‚¿ã‚¤ãƒ アウトã—ã¾ã—ãŸ" +msgid "E37: No write since last change" +msgstr "E37: 最後ã®å¤‰æ›´ãŒä¿å˜ã•れã¦ã„ã¾ã›ã‚“" -#~ msgid "" -#~ "\n" -#~ "Cannot execute shell sh\n" -#~ msgstr "" -#~ "\n" -#~ "sh シェルを実行ã§ãã¾ã›ã‚“\n" +msgid "E38: Null argument" +msgstr "E38: 引数ãŒç©ºã§ã™" -#~ msgid "" -#~ "\n" -#~ "Cannot create pipes\n" -#~ msgstr "" -#~ "\n" -#~ "パイプを作æˆã§ãã¾ã›ã‚“\n" +msgid "E39: Number expected" +msgstr "E39: 数値ãŒè¦æ±‚ã•れã¦ã„ã¾ã™" -#~ msgid "" -#~ "\n" -#~ "Cannot fork\n" -#~ msgstr "" -#~ "\n" -#~ "fork ã§ãã¾ã›ã‚“\n" +#, c-format +msgid "E40: Can't open errorfile %s" +msgstr "E40: エラーファイル %s ã‚’é–‹ã‘ã¾ã›ã‚“" -#~ msgid "" -#~ "\n" -#~ "Command terminated\n" -#~ msgstr "" -#~ "\n" -#~ "ã‚³ãƒžãƒ³ãƒ‰ã‚’ä¸æ–ã—ã¾ã—ãŸ\n" +msgid "E233: cannot open display" +msgstr "E233: ディスプレイを開ã‘ã¾ã›ã‚“" -#~ msgid "XSMP lost ICE connection" -#~ msgstr "XSMP ãŒICE接続を失ã„ã¾ã—ãŸ" +msgid "E41: Out of memory!" +msgstr "E41: メモリãŒå°½ãæžœã¦ã¾ã—ãŸ!" -#~ msgid "Opening the X display failed" -#~ msgstr "X display ã® open ã«å¤±æ•—ã—ã¾ã—ãŸ" +msgid "Pattern not found" +msgstr "パターンã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ" -#~ msgid "XSMP handling save-yourself request" -#~ msgstr "XSMP ãŒsave-yourselfè¦æ±‚を処ç†ã—ã¦ã„ã¾ã™" +#, c-format +msgid "E486: Pattern not found: %s" +msgstr "E486: パターンã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ: %s" -#~ msgid "XSMP opening connection" -#~ msgstr "XSMP ãŒæŽ¥ç¶šã‚’é–‹å§‹ã—ã¦ã„ã¾ã™" +msgid "E487: Argument must be positive" +msgstr "E487: å¼•æ•°ã¯æ£ã®å€¤ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" -#~ msgid "XSMP ICE connection watch failed" -#~ msgstr "XSMP ICE接続ãŒå¤±æ•—ã—ãŸã‚ˆã†ã§ã™" +msgid "E459: Cannot go back to previous directory" +msgstr "E459: å‰ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«æˆ»ã‚Œã¾ã›ã‚“" -#~ msgid "XSMP SmcOpenConnection failed: %s" -#~ msgstr "XSMP SmcOpenConnectionãŒå¤±æ•—ã—ã¾ã—ãŸ: %s" +msgid "E42: No Errors" +msgstr "E42: エラーã¯ã‚りã¾ã›ã‚“" -#~ msgid "At line" -#~ msgstr "行" +msgid "E776: No location list" +msgstr "E776: ãƒã‚±ãƒ¼ã‚·ãƒ§ãƒ³ãƒªã‚¹ãƒˆã¯ã‚りã¾ã›ã‚“" -#~ msgid "Could not load vim32.dll!" -#~ msgstr "vim32.dll ã‚’ãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§ã—ãŸ" +msgid "E43: Damaged match string" +msgstr "E43: 該当文å—列ãŒç ´æã—ã¦ã„ã¾ã™" -#~ msgid "VIM Error" -#~ msgstr "VIMエラー" +msgid "E44: Corrupted regexp program" +msgstr "E44: 䏿£ãªæ£è¦è¡¨ç¾ãƒ—ãƒã‚°ãƒ©ãƒ ã§ã™" -#~ msgid "Could not fix up function pointers to the DLL!" -#~ msgstr "DLLã‹ã‚‰é–¢æ•°ãƒã‚¤ãƒ³ã‚¿ã‚’å–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸ" +msgid "E45: 'readonly' option is set (add ! to override)" +msgstr "E45: 'readonly' オプションãŒè¨å®šã•れã¦ã„ã¾ã™ (! ã‚’è¿½åŠ ã§ä¸Šæ›¸ã)" -#~ msgid "shell returned %d" -#~ msgstr "シェルãŒã‚³ãƒ¼ãƒ‰ %d ã§çµ‚了ã—ã¾ã—ãŸ" +#, c-format +msgid "E46: Cannot change read-only variable \"%s\"" +msgstr "E46: èªå–専用変数 \"%s\" ã«ã¯å€¤ã‚’è¨å®šã§ãã¾ã›ã‚“" -#~ msgid "Vim: Caught %s event\n" -#~ msgstr "Vim: イベント %s を検知\n" +#, c-format +msgid "E794: Cannot set variable in the sandbox: \"%s\"" +msgstr "E794: サンドボックスã§ã¯å¤‰æ•° \"%s\" ã«å€¤ã‚’è¨å®šã§ãã¾ã›ã‚“" -#~ msgid "close" -#~ msgstr "é–‰ã˜ã‚‹" +msgid "E713: Cannot use empty key for Dictionary" +msgstr "E713: 辞書型ã«ç©ºã®ã‚ーを使ã†ã“ã¨ã¯ã§ãã¾ã›ã‚“" -#~ msgid "logoff" -#~ msgstr "ãƒã‚°ã‚ªãƒ•" +msgid "E715: Dictionary required" +msgstr "E715: 辞書型ãŒå¿…è¦ã§ã™" -#~ msgid "shutdown" -#~ msgstr "シャットダウン" +#, c-format +msgid "E684: list index out of range: %ld" +msgstr "E684: リストã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ãŒç¯„囲外ã§ã™: %ld" -#~ msgid "E371: Command not found" -#~ msgstr "E371: コマンドãŒã‚りã¾ã›ã‚“" - -#~ msgid "" -#~ "VIMRUN.EXE not found in your $PATH.\n" -#~ "External commands will not pause after completion.\n" -#~ "See :help win32-vimrun for more information." -#~ msgstr "" -#~ "VIMRUN.EXE㌠$PATH ã®ä¸ã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“.\n" -#~ "外部コマンドã®çµ‚了後ã«ä¸€æ™‚åœæ¢ã‚’ã—ã¾ã›ã‚“.\n" -#~ "詳細㯠:help win32-vimrun ã‚’å‚ç…§ã—ã¦ãã ã•ã„." - -#~ msgid "Vim Warning" -#~ msgstr "Vimã®è¦å‘Š" - -#~ msgid "Error file" -#~ msgstr "エラーファイル" - -#~ msgid "E868: Error building NFA with equivalence class!" -#~ msgstr "E868: ç‰ä¾¡ã‚¯ãƒ©ã‚¹ã‚’å«ã‚€NFA構築ã«å¤±æ•—ã—ã¾ã—ãŸ!" - -#~ msgid "E878: (NFA) Could not allocate memory for branch traversal!" -#~ msgstr "E878: (NFA) ç¾åœ¨æ¨ªæ–ä¸ã®ãƒ–ランãƒã«å分ãªãƒ¡ãƒ¢ãƒªã‚’割り当ã¦ã‚‰ã‚Œã¾ã›ã‚“!" - -#~ msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" -#~ msgstr "" -#~ "è¦å‘Š: å˜èªžãƒªã‚¹ãƒˆ \"%s_%s.spl\" ãŠã‚ˆã³ \"%s_ascii.spl\" ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" - -#~ msgid "Conversion in %s not supported" -#~ msgstr "%s 内ã®å¤‰æ›ã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“" - -#~ msgid "E845: Insufficient memory, word list will be incomplete" -#~ msgstr "E845: メモリãŒè¶³ã‚Šãªã„ã®ã§ã€å˜èªžãƒªã‚¹ãƒˆã¯ä¸å®Œå…¨ã§ã™" - -#~ msgid "E430: Tag file path truncated for %s\n" -#~ msgstr "E430: タグファイルã®ãƒ‘ス㌠%s ã«åˆ‡ã‚Šæ¨ã¦ã‚‰ã‚Œã¾ã—ãŸ\n" - -#~ msgid "new shell started\n" -#~ msgstr "æ–°ã—ã„シェルを起動ã—ã¾ã™\n" - -#~ msgid "Used CUT_BUFFER0 instead of empty selection" -#~ msgstr "空ã®é¸æŠžé ˜åŸŸã®ã‹ã‚りã«CUT_BUFFER0ãŒä½¿ç”¨ã•れã¾ã—ãŸ" - -#~ msgid "No undo possible; continue anyway" -#~ msgstr "å¯èƒ½ãªã‚¢ãƒ³ãƒ‰ã‚¥ã¯ã‚りã¾ã›ã‚“: ã¨ã‚Šã‚ãˆãšç¶šã‘ã¾ã™" - -#~ msgid "E832: Non-encrypted file has encrypted undo file: %s" -#~ msgstr "" -#~ "E832: éžæš—å·åŒ–ãƒ•ã‚¡ã‚¤ãƒ«ãŒæš—å·åŒ–ã•れãŸã‚¢ãƒ³ãƒ‰ã‚¥ãƒ•ァイルを使ã£ã¦ã¾ã™: %s" - -#~ msgid "E826: Undo file decryption failed: %s" -#~ msgstr "E826: æš—å·åŒ–ã•れãŸã‚¢ãƒ³ãƒ‰ã‚¥ãƒ•ァイルã®è§£èªã«å¤±æ•—ã—ã¾ã—ãŸ: %s" - -#~ msgid "E827: Undo file is encrypted: %s" -#~ msgstr "E827: ã‚¢ãƒ³ãƒ‰ã‚¥ãƒ•ã‚¡ã‚¤ãƒ«ãŒæš—å·åŒ–ã•れã¦ã„ã¾ã™: %s" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16/32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 16/32 ビット GUI 版" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 64 ビット GUI 版" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 32 ビット GUI 版" - -#~ msgid " in Win32s mode" -#~ msgstr " in Win32s モード" - -#~ msgid " with OLE support" -#~ msgstr " with OLE サãƒãƒ¼ãƒˆ" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit console version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 64 ビット コンソール 版" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit console version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 32 ビット コンソール 版" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16-bit version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 16 ビット 版" - -#~ msgid "" -#~ "\n" -#~ "32-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "32 ビット MS-DOS 版" - -#~ msgid "" -#~ "\n" -#~ "16-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "16 ビット MS-DOS 版" - -#~ msgid "" -#~ "\n" -#~ "MacOS X (unix) version" -#~ msgstr "" -#~ "\n" -#~ "MacOS X (unix) 版" - -#~ msgid "" -#~ "\n" -#~ "MacOS X version" -#~ msgstr "" -#~ "\n" -#~ "MacOS X 版" - -#~ msgid "" -#~ "\n" -#~ "MacOS version" -#~ msgstr "" -#~ "\n" -#~ "MacOS 版" - -#~ msgid "" -#~ "\n" -#~ "OpenVMS version" -#~ msgstr "" -#~ "\n" -#~ "OpenVMS 版" - -#~ msgid "" -#~ "\n" -#~ "Big version " -#~ msgstr "" -#~ "\n" -#~ "Big 版 " - -#~ msgid "" -#~ "\n" -#~ "Normal version " -#~ msgstr "" -#~ "\n" -#~ "通常 版 " - -#~ msgid "" -#~ "\n" -#~ "Small version " -#~ msgstr "" -#~ "\n" -#~ "Small 版 " - -#~ msgid "" -#~ "\n" -#~ "Tiny version " -#~ msgstr "" -#~ "\n" -#~ "Tiny 版 " - -#~ msgid "with GTK2-GNOME GUI." -#~ msgstr "with GTK2-GNOME GUI." +#, c-format +msgid "E118: Too many arguments for function: %s" +msgstr "E118: 関数ã®å¼•æ•°ãŒå¤šéŽãŽã¾ã™: %s" -#~ msgid "with GTK2 GUI." -#~ msgstr "with GTK2 GUI." +#, c-format +msgid "E716: Key not present in Dictionary: %s" +msgstr "E716: 辞書型ã«ã‚ーãŒå˜åœ¨ã—ã¾ã›ã‚“: %s" -#~ msgid "with X11-Motif GUI." -#~ msgstr "with X11-Motif GUI." +msgid "E714: List required" +msgstr "E714: リスト型ãŒå¿…è¦ã§ã™" -#~ msgid "with X11-neXtaw GUI." -#~ msgstr "with X11-neXtaw GUI." +#, c-format +msgid "E712: Argument of %s must be a List or Dictionary" +msgstr "E712: %s ã®å¼•æ•°ã¯ãƒªã‚¹ãƒˆåž‹ã¾ãŸã¯è¾žæ›¸åž‹ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" -#~ msgid "with X11-Athena GUI." -#~ msgstr "with X11-Athena GUI." +msgid "E47: Error while reading errorfile" +msgstr "E47: エラーファイルã®èªè¾¼ä¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ" -#~ msgid "with Photon GUI." -#~ msgstr "with Photon GUI." +msgid "E48: Not allowed in sandbox" +msgstr "E48: サンドボックスã§ã¯è¨±ã•れã¾ã›ã‚“" -#~ msgid "with GUI." -#~ msgstr "with GUI." +msgid "E523: Not allowed here" +msgstr "E523: ã“ã“ã§ã¯è¨±å¯ã•れã¾ã›ã‚“" -#~ msgid "with Carbon GUI." -#~ msgstr "with Carbon GUI." +msgid "E359: Screen mode setting not supported" +msgstr "E359: スクリーンモードã®è¨å®šã«ã¯å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“" -#~ msgid "with Cocoa GUI." -#~ msgstr "with Cocoa GUI." +msgid "E49: Invalid scroll size" +msgstr "E49: 無効ãªã‚¹ã‚¯ãƒãƒ¼ãƒ«é‡ã§ã™" -#~ msgid "with (classic) GUI." -#~ msgstr "with (クラシック) GUI." +msgid "E91: 'shell' option is empty" +msgstr "E91: 'shell' オプションãŒç©ºã§ã™" -#~ msgid " system gvimrc file: \"" -#~ msgstr " システムgvimrc: \"" +msgid "E255: Couldn't read in sign data!" +msgstr "E255: sign ã®ãƒ‡ãƒ¼ã‚¿ã‚’èªè¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸ" -#~ msgid " user gvimrc file: \"" -#~ msgstr " ユーザ gvimrc: \"" +msgid "E72: Close error on swap file" +msgstr "E72: スワップファイルã®ã‚¯ãƒãƒ¼ã‚ºæ™‚エラーã§ã™" -#~ msgid "2nd user gvimrc file: \"" -#~ msgstr " 第2ユーザ gvimrc: \"" +msgid "E73: tag stack empty" +msgstr "E73: タグスタックãŒç©ºã§ã™" -#~ msgid "3rd user gvimrc file: \"" -#~ msgstr " 第3ユーザ gvimrc: \"" +msgid "E74: Command too complex" +msgstr "E74: コマンドãŒè¤‡é›‘éŽãŽã¾ã™" -#~ msgid " system menu file: \"" -#~ msgstr " システムメニュー: \"" +msgid "E75: Name too long" +msgstr "E75: åå‰ãŒé•·éŽãŽã¾ã™" -#~ msgid "Compiler: " -#~ msgstr "コンパイラ: " +msgid "E76: Too many [" +msgstr "E76: [ ãŒå¤šéŽãŽã¾ã™" -#~ msgid "menu Help->Orphans for information " -#~ msgstr "詳細ã¯ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã® ヘルプ→å¤å… ã‚’å‚ç…§ã—ã¦ä¸‹ã•ã„ " +msgid "E77: Too many file names" +msgstr "E77: ファイルåãŒå¤šéŽãŽã¾ã™" -#~ msgid "Running modeless, typed text is inserted" -#~ msgstr "モード無ã§å®Ÿè¡Œä¸, タイプã—ãŸæ–‡å—ãŒæŒ¿å…¥ã•れã¾ã™" +msgid "E488: Trailing characters" +msgstr "E488: ä½™åˆ†ãªæ–‡å—ãŒå¾Œã‚ã«ã‚りã¾ã™" -#~ msgid "menu Edit->Global Settings->Toggle Insert Mode " -#~ msgstr "メニュー㮠編集→全体è¨å®šâ†’挿入(åˆå¿ƒè€…)モード切替 " +msgid "E78: Unknown mark" +msgstr "E78: 未知ã®ãƒžãƒ¼ã‚¯" -#~ msgid " for two modes " -#~ msgstr " ã§ãƒ¢ãƒ¼ãƒ‰æœ‰ã« " +msgid "E79: Cannot expand wildcards" +msgstr "E79: ワイルドカードを展開ã§ãã¾ã›ã‚“" -#~ msgid "menu Edit->Global Settings->Toggle Vi Compatible" -#~ msgstr "メニュー㮠編集→全体è¨å®šâ†’Vi互æ›ãƒ¢ãƒ¼ãƒ‰åˆ‡æ›¿ " +msgid "E591: 'winheight' cannot be smaller than 'winminheight'" +msgstr "E591: 'winheight' 㯠'winminheight' よりå°ã•ãã§ãã¾ã›ã‚“" -#~ msgid " for Vim defaults " -#~ msgstr " ã§Vimã¨ã—ã¦å‹•作 " +msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" +msgstr "E592: 'winwidth' 㯠'winminwidth' よりå°ã•ãã§ãã¾ã›ã‚“" -#~ msgid "WARNING: Windows 95/98/ME detected" -#~ msgstr " è¦å‘Š: Windows 95/98/Me を検出 " +msgid "E80: Error while writing" +msgstr "E80: 書込ã¿ä¸ã®ã‚¨ãƒ©ãƒ¼" -#~ msgid "type :help windows95<Enter> for info on this" -#~ msgstr " è©³ç´°ãªæƒ…å ±ã¯ :help windows95<Enter> " +msgid "Zero count" +msgstr "ゼãƒã‚«ã‚¦ãƒ³ãƒˆ" -#~ msgid "Edit with &multiple Vims" -#~ msgstr "複数ã®Vimã§ç·¨é›†ã™ã‚‹ (&M)" +msgid "E81: Using <SID> not in a script context" +msgstr "E81: スクリプト以外ã§<SID>ãŒä½¿ã‚れã¾ã—ãŸ" -#~ msgid "Edit with single &Vim" -#~ msgstr "1ã¤ã®Vimã§ç·¨é›†ã™ã‚‹ (&V)" +msgid "E449: Invalid expression received" +msgstr "E449: 無効ãªå¼ã‚’å—ã‘å–りã¾ã—ãŸ" -#~ msgid "Diff with Vim" -#~ msgstr "Vimã§å·®åˆ†ã‚’表示ã™ã‚‹" +msgid "E463: Region is guarded, cannot modify" +msgstr "E463: é ˜åŸŸãŒä¿è·ã•れã¦ã„ã‚‹ã®ã§, 変更ã§ãã¾ã›ã‚“" -#~ msgid "Edit with &Vim" -#~ msgstr "Vimã§ç·¨é›†ã™ã‚‹ (&V)" +msgid "E744: NetBeans does not allow changes in read-only files" +msgstr "E744: NetBeans ã¯èªè¾¼å°‚用ファイルを変更ã™ã‚‹ã“ã¨ã‚’許ã—ã¾ã›ã‚“" -#~ msgid "Edit with existing Vim - " -#~ msgstr "起動済ã®Vimã§ç·¨é›†ã™ã‚‹ - " +#, c-format +msgid "E685: Internal error: %s" +msgstr "E685: 内部エラーã§ã™: %s" -#~ msgid "Edits the selected file(s) with Vim" -#~ msgstr "é¸æŠžã—ãŸãƒ•ァイルをVimã§ç·¨é›†ã™ã‚‹" +msgid "E363: pattern uses more memory than 'maxmempattern'" +msgstr "E363: パターン㌠'maxmempattern' 以上ã®ãƒ¡ãƒ¢ãƒªã‚’使用ã—ã¾ã™" -#~ msgid "Error creating process: Check if gvim is in your path!" -#~ msgstr "プãƒã‚»ã‚¹ã®ä½œæˆã«å¤±æ•—: gvimãŒç’°å¢ƒå¤‰æ•°PATH上ã«ã‚ã‚‹ã‹ç¢ºèªã—ã¦ãã ã•ã„!" +msgid "E749: empty buffer" +msgstr "E749: ãƒãƒƒãƒ•ã‚¡ãŒç©ºã§ã™" -#~ msgid "gvimext.dll error" -#~ msgstr "gvimext.dll エラー" +#, c-format +msgid "E86: Buffer %ld does not exist" +msgstr "E86: ãƒãƒƒãƒ•ã‚¡ %ld ã¯ã‚りã¾ã›ã‚“" -#~ msgid "Path length too long!" -#~ msgstr "パスãŒé•·ã™ãŽã¾ã™!" +msgid "E682: Invalid search pattern or delimiter" +msgstr "E682: 検索パターンã‹åŒºåˆ‡ã‚Šè¨˜å·ãŒä¸æ£ã§ã™" -#~ msgid "E234: Unknown fontset: %s" -#~ msgstr "E234: 未知ã®ãƒ•ォントセット: %s" +msgid "E139: File is loaded in another buffer" +msgstr "E139: åŒã˜åå‰ã®ãƒ•ァイルãŒä»–ã®ãƒãƒƒãƒ•ã‚¡ã§èªè¾¼ã¾ã‚Œã¦ã„ã¾ã™" -#~ msgid "E235: Unknown font: %s" -#~ msgstr "E235: 未知ã®ãƒ•ォント: %s" +#, c-format +msgid "E764: Option '%s' is not set" +msgstr "E764: オプション '%s' ã¯è¨å®šã•れã¦ã„ã¾ã›ã‚“" -#~ msgid "E236: Font \"%s\" is not fixed-width" -#~ msgstr "E236: フォント \"%s\" ã¯å›ºå®šå¹…ã§ã¯ã‚りã¾ã›ã‚“" +msgid "E850: Invalid register name" +msgstr "E850: 無効ãªãƒ¬ã‚¸ã‚¹ã‚¿åã§ã™" -#~ msgid "E448: Could not load library function %s" -#~ msgstr "E448: ライブラリã®é–¢æ•° %s ã‚’ãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§ã—ãŸ" +#, c-format +msgid "E919: Directory not found in '%s': \"%s\"" +msgstr "E919: ディレクトリ㌠'%s' ã®ä¸ã«ã‚りã¾ã›ã‚“: \"%s\"" -#~ msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" -#~ msgstr "E26: ヘブライ語ã¯ä½¿ç”¨ä¸å¯èƒ½ã§ã™: コンパイル時ã«ç„¡åйã«ã•れã¦ã„ã¾ã™\n" +msgid "search hit TOP, continuing at BOTTOM" +msgstr "上ã¾ã§æ¤œç´¢ã—ãŸã®ã§ä¸‹ã«æˆ»ã‚Šã¾ã™" -#~ msgid "E27: Farsi cannot be used: Not enabled at compile time\n" -#~ msgstr "E27: ペルシア語ã¯ä½¿ç”¨ä¸å¯èƒ½ã§ã™: コンパイル時ã«ç„¡åйã«ã•れã¦ã„ã¾ã™\n" +msgid "search hit BOTTOM, continuing at TOP" +msgstr "下ã¾ã§æ¤œç´¢ã—ãŸã®ã§ä¸Šã«æˆ»ã‚Šã¾ã™" -#~ msgid "E800: Arabic cannot be used: Not enabled at compile time\n" -#~ msgstr "" -#~ "E800: アラビア語ã¯ä½¿ç”¨ä¸å¯èƒ½ã§ã™: コンパイル時ã«ç„¡åйã«ã•れã¦ã„ã¾ã™\n" +#, c-format +msgid "Need encryption key for \"%s\"" +msgstr "æš—å·ã‚ーãŒå¿…è¦ã§ã™: \"%s\"" -#~ msgid "E247: no registered server named \"%s\"" -#~ msgstr "E247: %s ã¨ã„ã†åå‰ã®ç™»éŒ²ã•れãŸã‚µãƒ¼ãƒã¯ã‚りã¾ã›ã‚“" +msgid "empty keys are not allowed" +msgstr "空ã®ã‚ーã¯è¨±å¯ã•れã¦ã„ã¾ã›ã‚“" -#~ msgid "E233: cannot open display" -#~ msgstr "E233: ディスプレイを開ã‘ã¾ã›ã‚“" +msgid "dictionary is locked" +msgstr "辞書ã¯ãƒãƒƒã‚¯ã•れã¦ã„ã¾ã™" -#~ msgid "E449: Invalid expression received" -#~ msgstr "E449: 無効ãªå¼ã‚’å—ã‘å–りã¾ã—ãŸ" +msgid "list is locked" +msgstr "リストã¯ãƒãƒƒã‚¯ã•れã¦ã„ã¾ã™" -#~ msgid "E463: Region is guarded, cannot modify" -#~ msgstr "E463: é ˜åŸŸãŒä¿è·ã•れã¦ã„ã‚‹ã®ã§, 変更ã§ãã¾ã›ã‚“" +#, c-format +msgid "failed to add key '%s' to dictionary" +msgstr "辞書ã«ã‚ー '%s' ã‚’è¿½åŠ ã™ã‚‹ã®ã«å¤±æ•—ã—ã¾ã—ãŸ" -#~ msgid "E744: NetBeans does not allow changes in read-only files" -#~ msgstr "E744: NetBeans ã¯èªè¾¼å°‚用ファイルを変更ã™ã‚‹ã“ã¨ã‚’許ã—ã¾ã›ã‚“" +#, c-format +msgid "index must be int or slice, not %s" +msgstr "インデックス㯠%s ã§ã¯ãªãæ•´æ•°ã‹ã‚¹ãƒ©ã‚¤ã‚¹ã«ã—ã¦ãã ã•ã„" -#~ msgid "Need encryption key for \"%s\"" -#~ msgstr "æš—å·ã‚ーãŒå¿…è¦ã§ã™: \"%s\"" +#, c-format +msgid "expected str() or unicode() instance, but got %s" +msgstr "str() ã‚‚ã—ã㯠unicode() ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ãŒæœŸå¾…ã•れã¦ã„ã‚‹ã®ã« %s ã§ã—ãŸ" -#~ msgid "empty keys are not allowed" -#~ msgstr "空ã®ã‚ーã¯è¨±å¯ã•れã¦ã„ã¾ã›ã‚“" +#, c-format +msgid "expected bytes() or str() instance, but got %s" +msgstr "bytes() ã‚‚ã—ã㯠str() ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ãŒæœŸå¾…ã•れã¦ã„ã‚‹ã®ã« %s ã§ã—ãŸ" -#~ msgid "dictionary is locked" -#~ msgstr "辞書ã¯ãƒãƒƒã‚¯ã•れã¦ã„ã¾ã™" +#, c-format +msgid "" +"expected int(), long() or something supporting coercing to long(), but got %s" +msgstr "long() ã‹ãれã¸å¤‰æ›å¯èƒ½ãªã‚‚ã®ãŒæœŸå¾…ã•れã¦ã„ã‚‹ã®ã« %s ã§ã—ãŸ" -#~ msgid "list is locked" -#~ msgstr "リストã¯ãƒãƒƒã‚¯ã•れã¦ã„ã¾ã™" +#, c-format +msgid "expected int() or something supporting coercing to int(), but got %s" +msgstr "int() ã‹ãれã¸å¤‰æ›å¯èƒ½ãªã‚‚ã®ãŒæœŸå¾…ã•れã¦ã„ã‚‹ã®ã« %s ã§ã—ãŸ" -#~ msgid "failed to add key '%s' to dictionary" -#~ msgstr "辞書ã«ã‚ー '%s' ã‚’è¿½åŠ ã™ã‚‹ã®ã«å¤±æ•—ã—ã¾ã—ãŸ" +msgid "value is too large to fit into C int type" +msgstr "C言語㮠int åž‹ã¨ã—ã¦ã¯å€¤ãŒå¤§ãéŽãŽã¾ã™" -#~ msgid "index must be int or slice, not %s" -#~ msgstr "インデックス㯠%s ã§ã¯ãªãæ•´æ•°ã‹ã‚¹ãƒ©ã‚¤ã‚¹ã«ã—ã¦ãã ã•ã„" +msgid "value is too small to fit into C int type" +msgstr "C言語㮠int åž‹ã¨ã—ã¦ã¯å€¤ãŒå°ã•éŽãŽã¾ã™" -#~ msgid "expected str() or unicode() instance, but got %s" -#~ msgstr "" -#~ "str() ã‚‚ã—ã㯠unicode() ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ãŒæœŸå¾…ã•れã¦ã„ã‚‹ã®ã« %s ã§ã—ãŸ" +msgid "number must be greater than zero" +msgstr "数値㯠0 より大ãããªã‘れã°ãªã‚Šã¾ã›ã‚“" -#~ msgid "expected bytes() or str() instance, but got %s" -#~ msgstr "bytes() ã‚‚ã—ã㯠str() ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ãŒæœŸå¾…ã•れã¦ã„ã‚‹ã®ã« %s ã§ã—ãŸ" +msgid "number must be greater or equal to zero" +msgstr "数値㯠0 ã‹ãれ以上ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" -#~ msgid "" -#~ "expected int(), long() or something supporting coercing to long(), but " -#~ "got %s" -#~ msgstr "long() ã‹ãれã¸å¤‰æ›å¯èƒ½ãªã‚‚ã®ãŒæœŸå¾…ã•れã¦ã„ã‚‹ã®ã« %s ã§ã—ãŸ" +msgid "can't delete OutputObject attributes" +msgstr "OutputObject属性を消ã›ã¾ã›ã‚“" -#~ msgid "expected int() or something supporting coercing to int(), but got %s" -#~ msgstr "int() ã‹ãれã¸å¤‰æ›å¯èƒ½ãªã‚‚ã®ãŒæœŸå¾…ã•れã¦ã„ã‚‹ã®ã« %s ã§ã—ãŸ" +#, c-format +msgid "invalid attribute: %s" +msgstr "無効ãªå±žæ€§ã§ã™: %s" -#~ msgid "value is too large to fit into C int type" -#~ msgstr "C言語㮠int åž‹ã¨ã—ã¦ã¯å€¤ãŒå¤§ãéŽãŽã¾ã™" +msgid "E264: Python: Error initialising I/O objects" +msgstr "E264: Python: I/Oオブジェクトã®åˆæœŸåŒ–エラー" -#~ msgid "value is too small to fit into C int type" -#~ msgstr "C言語㮠int åž‹ã¨ã—ã¦ã¯å€¤ãŒå°ã•éŽãŽã¾ã™" +msgid "failed to change directory" +msgstr "辞書ã®å¤‰æ›´ã«å¤±æ•—ã—ã¾ã—ãŸ" -#~ msgid "number must be greater then zero" -#~ msgstr "数値㯠0 より大ãããªã‘れã°ãªã‚Šã¾ã›ã‚“" +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got %s" +msgstr "imp.find_module() ㌠%s ã‚’è¿”ã—ã¾ã—㟠(期待値: 3 è¦ç´ ã®ã‚¿ãƒ—ル)" -#~ msgid "number must be greater or equal to zero" -#~ msgstr "数値㯠0 ã‹ãれ以上ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got tuple of size %d" +msgstr "imp.find_module() ㌠%d è¦ç´ ã®ã‚¿ãƒ—ルを返ã—ã¾ã—㟠(期待値: 3)" -#~ msgid "can't delete OutputObject attributes" -#~ msgstr "OutputObject属性を消ã›ã¾ã›ã‚“" +msgid "internal error: imp.find_module returned tuple with NULL" +msgstr "内部エラー: imp.find_module ㌠NULL ã‚’å«ã‚€ã‚¿ãƒ—ルを返ã—ã¾ã—ãŸ" -#~ msgid "invalid attribute: %s" -#~ msgstr "無効ãªå±žæ€§ã§ã™: %s" +msgid "cannot delete vim.Dictionary attributes" +msgstr "vim.Dictionaryå±žæ€§ã¯æ¶ˆã›ã¾ã›ã‚“" -#~ msgid "E264: Python: Error initialising I/O objects" -#~ msgstr "E264: Python: I/Oオブジェクトã®åˆæœŸåŒ–エラー" +msgid "cannot modify fixed dictionary" +msgstr "固定ã•れãŸè¾žæ›¸ã¯å¤‰æ›´ã§ãã¾ã›ã‚“" -#~ msgid "failed to change directory" -#~ msgstr "辞書ã®å¤‰æ›´ã«å¤±æ•—ã—ã¾ã—ãŸ" +#, c-format +msgid "cannot set attribute %s" +msgstr "属性 %s ã¯è¨å®šã§ãã¾ã›ã‚“" -#~ msgid "expected 3-tuple as imp.find_module() result, but got %s" -#~ msgstr "imp.find_module() ㌠%s ã‚’è¿”ã—ã¾ã—㟠(期待値: 2 è¦ç´ ã®ã‚¿ãƒ—ル)" +msgid "hashtab changed during iteration" +msgstr "イテレーションä¸ã« hashtab ãŒå¤‰æ›´ã•れã¾ã—ãŸ" -#~ msgid "" -#~ "expected 3-tuple as imp.find_module() result, but got tuple of size %d" -#~ msgstr "impl.find_module() ㌠%d è¦ç´ ã®ã‚¿ãƒ—ルを返ã—ã¾ã—㟠(期待値: 2)" +#, c-format +msgid "expected sequence element of size 2, but got sequence of size %d" +msgstr "シーケンスã®è¦ç´ æ•°ã«ã¯ 2 ãŒæœŸå¾…ã•れã¦ã„ã¾ã—ãŸãŒ %d ã§ã—ãŸ" -#~ msgid "internal error: imp.find_module returned tuple with NULL" -#~ msgstr "内部エラー: imp.find_module ㌠NULL ã‚’å«ã‚€ã‚¿ãƒ—ルを返ã—ã¾ã—ãŸ" +msgid "list constructor does not accept keyword arguments" +msgstr "リストã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ã¯ã‚ーワード引数をå—ã‘付ã‘ã¾ã›ã‚“" -#~ msgid "cannot delete vim.Dictionary attributes" -#~ msgstr "vim.Dictionaryå±žæ€§ã¯æ¶ˆã›ã¾ã›ã‚“" +msgid "list index out of range" +msgstr "リスト範囲外ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã§ã™" -#~ msgid "cannot modify fixed dictionary" -#~ msgstr "固定ã•れãŸè¾žæ›¸ã¯å¤‰æ›´ã§ãã¾ã›ã‚“" +#. No more suitable format specifications in python-2.3 +#, c-format +msgid "internal error: failed to get vim list item %d" +msgstr "内部エラー: vimã®ãƒªã‚¹ãƒˆè¦ç´ %d ã®å–å¾—ã«å¤±æ•—ã—ã¾ã—ãŸ" -#~ msgid "cannot set attribute %s" -#~ msgstr "属性 %s ã¯è¨å®šã§ãã¾ã›ã‚“" +msgid "slice step cannot be zero" +msgstr "スライスã®ã‚¹ãƒ†ãƒƒãƒ—ã« 0 ã¯æŒ‡å®šã§ãã¾ã›ã‚“" -#~ msgid "hashtab changed during iteration" -#~ msgstr "イテレーションä¸ã« hashtab ãŒå¤‰æ›´ã•れã¾ã—ãŸ" +#, c-format +msgid "attempt to assign sequence of size greater than %d to extended slice" +msgstr "é•·ã• %d ã®æ‹¡å¼µã‚¹ãƒ©ã‚¤ã‚¹ã«ã€ã‚ˆã‚Šé•·ã„スライスを割り当ã¦ã‚ˆã†ã¨ã—ã¾ã—ãŸ" -#~ msgid "expected sequence element of size 2, but got sequence of size %d" -#~ msgstr "シーケンスã®è¦ç´ æ•°ã«ã¯ 2 ãŒæœŸå¾…ã•れã¦ã„ã¾ã—ãŸãŒ %d ã§ã—ãŸ" +#, c-format +msgid "internal error: no vim list item %d" +msgstr "内部エラー: vimã®ãƒªã‚¹ãƒˆè¦ç´ %d ã¯ã‚りã¾ã›ã‚“" -#~ msgid "list constructor does not accept keyword arguments" -#~ msgstr "リストã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ã¯ã‚ーワード引数をå—ã‘付ã‘ã¾ã›ã‚“" +msgid "internal error: not enough list items" +msgstr "内部エラー: リストã«å分ãªè¦ç´ ãŒã‚りã¾ã›ã‚“" -#~ msgid "list index out of range" -#~ msgstr "リスト範囲外ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã§ã™" +msgid "internal error: failed to add item to list" +msgstr "内部エラー: リストã¸ã®è¦ç´ è¿½åŠ ã«å¤±æ•—ã—ã¾ã—ãŸ" -#~ msgid "internal error: failed to get vim list item %d" -#~ msgstr "内部エラー: vimã®ãƒªã‚¹ãƒˆè¦ç´ %d ã®å–å¾—ã«å¤±æ•—ã—ã¾ã—ãŸ" +#, c-format +msgid "attempt to assign sequence of size %d to extended slice of size %d" +msgstr "é•·ã• %d ã®ã‚¹ãƒ©ã‚¤ã‚¹ã‚’ %d ã®æ‹¡å¼µã‚¹ãƒ©ã‚¤ã‚¹ã«å‰²ã‚Šå½“ã¦ã‚ˆã†ã¨ã—ã¾ã—ãŸ" -#~ msgid "failed to add item to list" -#~ msgstr "リストã¸ã®è¦ç´ è¿½åŠ ã«å¤±æ•—ã—ã¾ã—ãŸ" +msgid "failed to add item to list" +msgstr "リストã¸ã®è¦ç´ è¿½åŠ ã«å¤±æ•—ã—ã¾ã—ãŸ" -#~ msgid "internal error: no vim list item %d" -#~ msgstr "内部エラー: vimã®ãƒªã‚¹ãƒˆè¦ç´ %d ã¯ã‚りã¾ã›ã‚“" +msgid "cannot delete vim.List attributes" +msgstr "vim.List å±žæ€§ã¯æ¶ˆã›ã¾ã›ã‚“" -#~ msgid "internal error: failed to add item to list" -#~ msgstr "内部エラー: リストã¸ã®è¦ç´ è¿½åŠ ã«å¤±æ•—ã—ã¾ã—ãŸ" +msgid "cannot modify fixed list" +msgstr "固定ã•れãŸãƒªã‚¹ãƒˆã¯å¤‰æ›´ã§ãã¾ã›ã‚“" -#~ msgid "cannot delete vim.List attributes" -#~ msgstr "vim.List å±žæ€§ã¯æ¶ˆã›ã¾ã›ã‚“" +#, c-format +msgid "unnamed function %s does not exist" +msgstr "ç„¡å関数 %s ã¯å˜åœ¨ã—ã¾ã›ã‚“" -#~ msgid "cannot modify fixed list" -#~ msgstr "固定ã•れãŸãƒªã‚¹ãƒˆã¯å¤‰æ›´ã§ãã¾ã›ã‚“" +#, c-format +msgid "function %s does not exist" +msgstr "関数 %s ãŒã‚りã¾ã›ã‚“" -#~ msgid "unnamed function %s does not exist" -#~ msgstr "ç„¡å関数 %s ã¯å˜åœ¨ã—ã¾ã›ã‚“" +#, c-format +msgid "failed to run function %s" +msgstr "関数 %s ã®å®Ÿè¡Œã«å¤±æ•—ã—ã¾ã—ãŸ" -#~ msgid "function %s does not exist" -#~ msgstr "関数 %s ãŒã‚りã¾ã›ã‚“" +msgid "unable to get option value" +msgstr "オプションã®å€¤ã¯å–å¾—ã§ãã¾ã›ã‚“" -#~ msgid "function constructor does not accept keyword arguments" -#~ msgstr "関数ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ã¯ã‚ーワード引数をå—ã‘付ã‘ã¾ã›ã‚“" +msgid "internal error: unknown option type" +msgstr "内部エラー: 未知ã®ã‚ªãƒ—ション型ã§ã™" -#~ msgid "failed to run function %s" -#~ msgstr "関数 %s ã®å®Ÿè¡Œã«å¤±æ•—ã—ã¾ã—ãŸ" +msgid "problem while switching windows" +msgstr "ウィンドウを切æ›ä¸ã«å•題ãŒç™ºç”Ÿã—ã¾ã—ãŸ" -#~ msgid "problem while switching windows" -#~ msgstr "ウィンドウを切æ›ä¸ã«å•題ãŒç™ºç”Ÿã—ã¾ã—ãŸ" +#, c-format +msgid "unable to unset global option %s" +msgstr "ã‚°ãƒãƒ¼ãƒãƒ«ã‚ªãƒ—ション %s ã®è¨å®šè§£é™¤ã¯ã§ãã¾ã›ã‚“" -#~ msgid "unable to unset global option %s" -#~ msgstr "ã‚°ãƒãƒ¼ãƒãƒ«ã‚ªãƒ—ション %s ã®è¨å®šè§£é™¤ã¯ã§ãã¾ã›ã‚“" +#, c-format +msgid "unable to unset option %s which does not have global value" +msgstr "ã‚°ãƒãƒ¼ãƒãƒ«ãªå€¤ã®ç„¡ã„オプション %s ã®è¨å®šè§£é™¤ã¯ã§ãã¾ã›ã‚“" -#~ msgid "unable to unset option %s which does not have global value" -#~ msgstr "ã‚°ãƒãƒ¼ãƒãƒ«ãªå€¤ã®ç„¡ã„オプション %s ã®è¨å®šè§£é™¤ã¯ã§ãã¾ã›ã‚“" +msgid "attempt to refer to deleted tab page" +msgstr "削除ã•れãŸã‚¿ãƒ–ã‚’å‚ç…§ã—よã†ã¨ã—ã¾ã—ãŸ" -#~ msgid "attempt to refer to deleted tab page" -#~ msgstr "削除ã•れãŸã‚¿ãƒ–ã‚’å‚ç…§ã—よã†ã¨ã—ã¾ã—ãŸ" +msgid "no such tab page" +msgstr "ãã®ã‚ˆã†ãªã‚¿ãƒ–ページã¯ã‚りã¾ã›ã‚“" -#~ msgid "no such tab page" -#~ msgstr "ãã®ã‚ˆã†ãªã‚¿ãƒ–ページã¯ã‚りã¾ã›ã‚“" +msgid "attempt to refer to deleted window" +msgstr "削除ã•れãŸã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’å‚ç…§ã—よã†ã¨ã—ã¾ã—ãŸ" -#~ msgid "attempt to refer to deleted window" -#~ msgstr "削除ã•れãŸã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’å‚ç…§ã—よã†ã¨ã—ã¾ã—ãŸ" +msgid "readonly attribute: buffer" +msgstr "èªè¾¼å°‚用属性: ãƒãƒƒãƒ•ァー" -#~ msgid "readonly attribute: buffer" -#~ msgstr "èªè¾¼å°‚用属性: ãƒãƒƒãƒ•ァー" +msgid "cursor position outside buffer" +msgstr "カーソルä½ç½®ãŒãƒãƒƒãƒ•ã‚¡ã®å¤–å´ã§ã™" -#~ msgid "cursor position outside buffer" -#~ msgstr "カーソルä½ç½®ãŒãƒãƒƒãƒ•ã‚¡ã®å¤–å´ã§ã™" +msgid "no such window" +msgstr "ãã®ã‚ˆã†ãªã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã¯ã‚りã¾ã›ã‚“" -#~ msgid "no such window" -#~ msgstr "ãã®ã‚ˆã†ãªã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã¯ã‚りã¾ã›ã‚“" +msgid "attempt to refer to deleted buffer" +msgstr "削除ã•れãŸãƒãƒƒãƒ•ã‚¡ã‚’å‚ç…§ã—よã†ã¨ã—ã¾ã—ãŸ" -#~ msgid "attempt to refer to deleted buffer" -#~ msgstr "削除ã•れãŸãƒãƒƒãƒ•ã‚¡ã‚’å‚ç…§ã—よã†ã¨ã—ã¾ã—ãŸ" +msgid "failed to rename buffer" +msgstr "ãƒãƒƒãƒ•ã‚¡åã®å¤‰æ›´ã«å¤±æ•—ã—ã¾ã—ãŸ" -#~ msgid "failed to rename buffer" -#~ msgstr "ãƒãƒƒãƒ•ã‚¡åã®å¤‰æ›´ã«å¤±æ•—ã—ã¾ã—ãŸ" +msgid "mark name must be a single character" +msgstr "マークåã¯1æ–‡å—ã®ã‚¢ãƒ«ãƒ•ァベットã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" -#~ msgid "mark name must be a single character" -#~ msgstr "マークåã¯1æ–‡å—ã®ã‚¢ãƒ«ãƒ•ァベットã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" +#, c-format +msgid "expected vim.Buffer object, but got %s" +msgstr "vim.Bufferã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆãŒæœŸå¾…ã•れã¦ã„ã‚‹ã®ã« %s ã§ã—ãŸ" -#~ msgid "expected vim.Buffer object, but got %s" -#~ msgstr "vim.Bufferã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆãŒæœŸå¾…ã•れã¦ã„ã‚‹ã®ã« %s ã§ã—ãŸ" +#, c-format +msgid "failed to switch to buffer %d" +msgstr "指定ã•れãŸãƒãƒƒãƒ•ã‚¡ %d ã¸ã®åˆ‡ã‚Šæ›¿ãˆã«å¤±æ•—ã—ã¾ã—ãŸ" -#~ msgid "failed to switch to buffer %d" -#~ msgstr "指定ã•れãŸãƒãƒƒãƒ•ã‚¡ %d ã¸ã®åˆ‡ã‚Šæ›¿ãˆã«å¤±æ•—ã—ã¾ã—ãŸ" +#, c-format +msgid "expected vim.Window object, but got %s" +msgstr "vim.Windowã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆãŒæœŸå¾…ã•れã¦ã„ã‚‹ã®ã« %s ã§ã—ãŸ" -#~ msgid "expected vim.Window object, but got %s" -#~ msgstr "vim.Windowã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆãŒæœŸå¾…ã•れã¦ã„ã‚‹ã®ã« %s ã§ã—ãŸ" +msgid "failed to find window in the current tab page" +msgstr "ç¾åœ¨ã®ã‚¿ãƒ–ã«ã¯æŒ‡å®šã•れãŸã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãŒã‚りã¾ã›ã‚“ã§ã—ãŸ" -#~ msgid "failed to find window in the current tab page" -#~ msgstr "ç¾åœ¨ã®ã‚¿ãƒ–ã«ã¯æŒ‡å®šã•れãŸã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãŒã‚りã¾ã›ã‚“ã§ã—ãŸ" +msgid "did not switch to the specified window" +msgstr "指定ã•れãŸã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã«åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“ã§ã—ãŸ" -#~ msgid "did not switch to the specified window" -#~ msgstr "指定ã•れãŸã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã«åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“ã§ã—ãŸ" +#, c-format +msgid "expected vim.TabPage object, but got %s" +msgstr "vim.TabPageã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆãŒæœŸå¾…ã•れã¦ã„ã‚‹ã®ã« %s ã§ã—ãŸ" -#~ msgid "expected vim.TabPage object, but got %s" -#~ msgstr "vim.TabPageã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆãŒæœŸå¾…ã•れã¦ã„ã‚‹ã®ã« %s ã§ã—ãŸ" +msgid "did not switch to the specified tab page" +msgstr "指定ã•れãŸã‚¿ãƒ–ページã«åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“ã§ã—ãŸ" -#~ msgid "did not switch to the specified tab page" -#~ msgstr "指定ã•れãŸã‚¿ãƒ–ページã«åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“ã§ã—ãŸ" +msgid "failed to run the code" +msgstr "コードã®å®Ÿè¡Œã«å¤±æ•—ã—ã¾ã—ãŸ" -#~ msgid "failed to run the code" -#~ msgstr "コードã®å®Ÿè¡Œã«å¤±æ•—ã—ã¾ã—ãŸ" +msgid "E858: Eval did not return a valid python object" +msgstr "E858: å¼è©•ä¾¡ã¯æœ‰åйãªpythonオブジェクトを返ã—ã¾ã›ã‚“ã§ã—ãŸ" -#~ msgid "E858: Eval did not return a valid python object" -#~ msgstr "E858: å¼è©•ä¾¡ã¯æœ‰åйãªpythonオブジェクトを返ã—ã¾ã›ã‚“ã§ã—ãŸ" +msgid "E859: Failed to convert returned python object to vim value" +msgstr "E859: è¿”ã•れãŸpythonオブジェクトをvimã®å€¤ã«å¤‰æ›ã§ãã¾ã›ã‚“ã§ã—ãŸ" -#~ msgid "E859: Failed to convert returned python object to vim value" -#~ msgstr "E859: è¿”ã•れãŸpythonオブジェクトをvimã®å€¤ã«å¤‰æ›ã§ãã¾ã›ã‚“ã§ã—ãŸ" +#, c-format +msgid "unable to convert %s to vim dictionary" +msgstr "%s vimã®è¾žæ›¸åž‹ã«å¤‰æ›ã§ãã¾ã›ã‚“" -#~ msgid "unable to convert %s to vim dictionary" -#~ msgstr "%s vimã®è¾žæ›¸åž‹ã«å¤‰æ›ã§ãã¾ã›ã‚“" +#, c-format +msgid "unable to convert %s to vim list" +msgstr "%s ã‚’vimã®ãƒªã‚¹ãƒˆã«å¤‰æ›ã§ãã¾ã›ã‚“" -#~ msgid "unable to convert %s to vim structure" -#~ msgstr "%s ã‚’vimã®æ§‹é€ 体ã«å¤‰æ›ã§ãã¾ã›ã‚“" +#, c-format +msgid "unable to convert %s to vim structure" +msgstr "%s ã‚’vimã®æ§‹é€ 体ã«å¤‰æ›ã§ãã¾ã›ã‚“" -#~ msgid "internal error: NULL reference passed" -#~ msgstr "内部エラー: NULLå‚ç…§ãŒæ¸¡ã•れã¾ã—ãŸ" +msgid "internal error: NULL reference passed" +msgstr "内部エラー: NULLå‚ç…§ãŒæ¸¡ã•れã¾ã—ãŸ" -#~ msgid "internal error: invalid value type" -#~ msgstr "内部エラー: 無効ãªå€¤åž‹ã§ã™" +msgid "internal error: invalid value type" +msgstr "内部エラー: 無効ãªå€¤åž‹ã§ã™" -#~ msgid "" -#~ "Failed to set path hook: sys.path_hooks is not a list\n" -#~ "You should now do the following:\n" -#~ "- append vim.path_hook to sys.path_hooks\n" -#~ "- append vim.VIM_SPECIAL_PATH to sys.path\n" -#~ msgstr "" -#~ "パスフックã®è¨å®šã«å¤±æ•—ã—ã¾ã—ãŸ: sys.path_hooks ãŒãƒªã‚¹ãƒˆã§ã¯ã‚りã¾ã›ã‚“\n" -#~ "ã™ãã«ä¸‹è¨˜ã‚’実施ã—ã¦ãã ã•ã„:\n" -#~ "- vim.path_hooks ã‚’ sys.path_hooks ã¸è¿½åŠ \n" -#~ "- vim.VIM_SPECIAL_PATH ã‚’ sys.path ã¸è¿½åŠ \n" +msgid "" +"Failed to set path hook: sys.path_hooks is not a list\n" +"You should now do the following:\n" +"- append vim.path_hook to sys.path_hooks\n" +"- append vim.VIM_SPECIAL_PATH to sys.path\n" +msgstr "" +"パスフックã®è¨å®šã«å¤±æ•—ã—ã¾ã—ãŸ: sys.path_hooks ãŒãƒªã‚¹ãƒˆã§ã¯ã‚りã¾ã›ã‚“\n" +"ã™ãã«ä¸‹è¨˜ã‚’実施ã—ã¦ãã ã•ã„:\n" +"- vim.path_hooks ã‚’ sys.path_hooks ã¸è¿½åŠ \n" +"- vim.VIM_SPECIAL_PATH ã‚’ sys.path ã¸è¿½åŠ \n" -#~ msgid "" -#~ "Failed to set path: sys.path is not a list\n" -#~ "You should now append vim.VIM_SPECIAL_PATH to sys.path" -#~ msgstr "" -#~ "パスã®è¨å®šã«å¤±æ•—ã—ã¾ã—ãŸ: sys.path ãŒãƒªã‚¹ãƒˆã§ã¯ã‚りã¾ã›ã‚“\n" -#~ "ã™ãã« vim.VIM_SPECIAL_PATH ã‚’ sys.path ã«è¿½åŠ ã—ã¦ãã ã•ã„" +msgid "" +"Failed to set path: sys.path is not a list\n" +"You should now append vim.VIM_SPECIAL_PATH to sys.path" +msgstr "" +"パスã®è¨å®šã«å¤±æ•—ã—ã¾ã—ãŸ: sys.path ãŒãƒªã‚¹ãƒˆã§ã¯ã‚りã¾ã›ã‚“\n" +"ã™ãã« vim.VIM_SPECIAL_PATH ã‚’ sys.path ã«è¿½åŠ ã—ã¦ãã ã•ã„" diff --git a/src/nvim/po/uk.po b/src/nvim/po/uk.po index cff140508b..2c203f808f 100644 --- a/src/nvim/po/uk.po +++ b/src/nvim/po/uk.po @@ -82,7 +82,7 @@ msgid "Key length is too high" msgstr "Довжина ключа завелика" #, c-format -msgid "Key \"%s\" doesn't exist" +msgid "Key does not exist: %s" msgstr "Ключ «%s» не Ñ–Ñнує" msgid "Empty option name" @@ -3719,7 +3719,7 @@ msgid "Calling shell to execute: \"%s\"" msgstr "ВикликаєтьÑÑ Ð¾Ð±Ð¾Ð»Ð¾Ð½ÐºÐ° щоб виконати: «%s»" #, c-format -msgid "Invalid channel \"%<PRIu64>\"" +msgid "Invalid channel: %<PRIu64>" msgstr "Ðекоректний канал «%<PRIu64>»" msgid "Message is not an array" @@ -3734,7 +3734,7 @@ msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¼Ð°Ñ” бути цілим чиÑлом" msgid "Unknown message type" msgstr "Ðевідомий тип повідомленнÑ" -msgid "Request array size should be 4 (request) or 3 (notification)" +msgid "Request array size must be 4 (request) or 3 (notification)" msgstr "Розмір маÑиву запиту має бути 4 (запит) чи 3 (повідомленнÑ)" msgid "ID must be a positive integer" diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c index 89180f76de..2462975c9b 100644 --- a/src/nvim/popupmnu.c +++ b/src/nvim/popupmnu.c @@ -1,3 +1,6 @@ +// 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 + /// @file popupmnu.c /// /// Popup menu (PUM) @@ -38,9 +41,7 @@ static int pum_row; // top row of pum static int pum_col; // left column of pum static bool pum_is_visible = false; - static bool pum_external = false; -static bool pum_wants_external = false; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "popupmnu.c.generated.h" @@ -73,12 +74,11 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed) int above_row; int below_row; int redo_count = 0; - win_T *pvwin; if (!pum_is_visible) { // To keep the code simple, we only allow changing the // draw mode when the popup menu is not being displayed - pum_external = pum_wants_external; + pum_external = ui_is_external(kUIPopupmenu); } redo: @@ -98,7 +98,6 @@ redo: } if (pum_external) { - Array args = ARRAY_DICT_INIT; if (array_changed) { Array arr = ARRAY_DICT_INIT; for (i = 0; i < size; i++) { @@ -109,14 +108,9 @@ redo: ADD(item, STRING_OBJ(cstr_to_string((char *)array[i].pum_info))); ADD(arr, ARRAY_OBJ(item)); } - ADD(args, ARRAY_OBJ(arr)); - ADD(args, INTEGER_OBJ(selected)); - ADD(args, INTEGER_OBJ(row)); - ADD(args, INTEGER_OBJ(col)); - ui_event("popupmenu_show", args); + ui_call_popupmenu_show(arr, selected, row, col); } else { - ADD(args, INTEGER_OBJ(selected)); - ui_event("popupmenu_select", args); + ui_call_popupmenu_select(selected); } return; } @@ -126,8 +120,10 @@ redo: kind_width = 0; extra_width = 0; - FOR_ALL_WINDOWS(pvwin) { - if (pvwin->w_p_pvw) { + win_T *pvwin = NULL; + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + if (wp->w_p_pvw) { + pvwin = wp; break; } } @@ -311,10 +307,10 @@ void pum_redraw(void) { int row = pum_row; int col; - int attr_norm = highlight_attr[HLF_PNI]; - int attr_select = highlight_attr[HLF_PSI]; - int attr_scroll = highlight_attr[HLF_PSB]; - int attr_thumb = highlight_attr[HLF_PST]; + int attr_norm = win_hl_attr(curwin, HLF_PNI); + int attr_select = win_hl_attr(curwin, HLF_PSI); + int attr_scroll = win_hl_attr(curwin, HLF_PSB); + int attr_thumb = win_hl_attr(curwin, HLF_PST); int attr; int i; int idx; @@ -609,13 +605,10 @@ static int pum_set_selected(int n, int repeat) if (res == OK) { // Edit a new, empty buffer. Set options for a "wipeout" // buffer. - set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL); - set_option_value((char_u *)"bt", 0L, - (char_u *)"nofile", OPT_LOCAL); - set_option_value((char_u *)"bh", 0L, - (char_u *)"wipe", OPT_LOCAL); - set_option_value((char_u *)"diff", 0L, - NULL, OPT_LOCAL); + set_option_value("swf", 0L, NULL, OPT_LOCAL); + set_option_value("bt", 0L, "nofile", OPT_LOCAL); + set_option_value("bh", 0L, "wipe", OPT_LOCAL); + set_option_value("diff", 0L, NULL, OPT_LOCAL); } } @@ -714,8 +707,7 @@ void pum_undisplay(void) pum_array = NULL; if (pum_external) { - Array args = ARRAY_DICT_INIT; - ui_event("popupmenu_hide", args); + ui_call_popupmenu_hide(); } else { redraw_all_later(SOME_VALID); redraw_tabline = true; @@ -750,8 +742,3 @@ int pum_get_height(void) { return pum_height; } - -void pum_set_external(bool external) -{ - pum_wants_external = external; -} diff --git a/src/nvim/popupmnu.h b/src/nvim/popupmnu.h index 2b181f2c4a..7e1588dbdd 100644 --- a/src/nvim/popupmnu.h +++ b/src/nvim/popupmnu.h @@ -1,6 +1,8 @@ #ifndef NVIM_POPUPMNU_H #define NVIM_POPUPMNU_H +#include "nvim/types.h" + /// Used for popup menu items. typedef struct { char_u *pum_text; // main menu text diff --git a/src/nvim/pos.h b/src/nvim/pos.h index 864f3fe866..966255e6a4 100644 --- a/src/nvim/pos.h +++ b/src/nvim/pos.h @@ -2,6 +2,8 @@ #define NVIM_POS_H typedef long linenr_T; // line number type +/// Format used to print values which have linenr_T type +#define PRIdLINENR "ld" /// Column number type typedef int colnr_T; diff --git a/src/nvim/profile.c b/src/nvim/profile.c index 97d7d77359..8fb8e92add 100644 --- a/src/nvim/profile.c +++ b/src/nvim/profile.c @@ -1,3 +1,6 @@ +// 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 <stdio.h> #include <math.h> #include <assert.h> diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 33a84660c1..e6b1e7b95a 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -1,3 +1,6 @@ +// 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 + /* * quickfix.c: functions for quickfix mode, using a file with error messages */ @@ -137,6 +140,40 @@ struct efm_S { int conthere; /* %> used */ }; +enum { + QF_FAIL = 0, + QF_OK = 1, + QF_END_OF_INPUT = 2, + QF_NOMEM = 3, + QF_IGNORE_LINE = 4 +}; + +typedef struct { + char_u *linebuf; + size_t linelen; + char_u *growbuf; + size_t growbufsiz; + FILE *fd; + typval_T *tv; + char_u *p_str; + listitem_T *p_li; + buf_T *buf; + linenr_T buflnum; + linenr_T lnumlast; +} qfstate_T; + +typedef struct { + char_u *namebuf; + char_u *errmsg; + size_t errmsglen; + long lnum; + int col; + bool use_viscol; + char_u *pattern; + int enr; + char_u type; + bool valid; +} qffields_T; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "quickfix.c.generated.h" @@ -151,6 +188,11 @@ struct efm_S { */ #define GET_LOC_LIST(wp) (IS_LL_WINDOW(wp) ? wp->w_llist_ref : wp->w_llist) +// Looking up a buffer can be slow if there are many. Remember the last one +// to make this a lot faster if there are multiple matches in the same file. +static char_u *qf_last_bufname = NULL; +static bufref_T qf_last_bufref = { NULL, 0, 0 }; + /* * Read the errorfile "efile" into memory, line by line, building the error * list. Set the error list's title to qf_title. @@ -179,22 +221,6 @@ qf_init ( // Maximum number of bytes allowed per line while reading an errorfile. static const size_t LINE_MAXLEN = 4096; -static char_u *qf_grow_linebuf(char_u **growbuf, size_t *growbufsiz, - size_t newsz, size_t *allocsz) -{ - // If the line exceeds LINE_MAXLEN exclude the last - // byte since it's not a NL character. - *allocsz = newsz > LINE_MAXLEN ? LINE_MAXLEN - 1 : newsz; - if (*growbuf == NULL) { - *growbuf = xmalloc(*allocsz + 1); - *growbufsiz = *allocsz; - } else if (*allocsz > *growbufsiz) { - *growbuf = xrealloc(*growbuf, *allocsz + 1); - *growbufsiz = *allocsz; - } - return *growbuf; -} - static struct fmtpattern { char_u convchar; @@ -357,6 +383,8 @@ static int efm_to_regpat(char_u *efm, int len, efm_T *fmt_ptr, return 0; } +static efm_T *fmt_start = NULL; // cached across qf_parse_line() calls + static void free_efm_list(efm_T **efm_first) { for (efm_T *efm_ptr = *efm_first; efm_ptr != NULL; efm_ptr = *efm_first) { @@ -364,6 +392,8 @@ static void free_efm_list(efm_T **efm_first) vim_regfree(efm_ptr->prog); xfree(efm_ptr); } + + fmt_start = NULL; } // Parse 'errorformat' option @@ -428,6 +458,495 @@ parse_efm_end: return fmt_first; } +static char_u *qf_grow_linebuf(qfstate_T *state, size_t newsz) +{ + // If the line exceeds LINE_MAXLEN exclude the last + // byte since it's not a NL character. + state->linelen = newsz > LINE_MAXLEN ? LINE_MAXLEN - 1 : newsz; + if (state->growbuf == NULL) { + state->growbuf = xmalloc(state->linelen + 1); + state->growbufsiz = state->linelen; + } else if (state->linelen > state->growbufsiz) { + state->growbuf = xrealloc(state->growbuf, state->linelen + 1); + state->growbufsiz = state->linelen; + } + return state->growbuf; +} + +/// Get the next string (separated by newline) from state->p_str. +static int qf_get_next_str_line(qfstate_T *state) +{ + // Get the next line from the supplied string + char_u *p_str = state->p_str; + char_u *p; + size_t len; + + if (*p_str == NUL) { // Reached the end of the string + return QF_END_OF_INPUT; + } + + p = vim_strchr(p_str, '\n'); + if (p != NULL) { + len = (size_t)(p - p_str) + 1; + } else { + len = STRLEN(p_str); + } + + if (len > IOSIZE - 2) { + state->linebuf = qf_grow_linebuf(state, len); + } else { + state->linebuf = IObuff; + state->linelen = len; + } + STRLCPY(state->linebuf, p_str, state->linelen + 1); + + // Increment using len in order to discard the rest of the line if it + // exceeds LINE_MAXLEN. + p_str += len; + state->p_str = p_str; + + return QF_OK; +} + +/// Get the next string from state->p_Li. +static int qf_get_next_list_line(qfstate_T *state) +{ + listitem_T *p_li = state->p_li; + size_t len; + + // Get the next line from the supplied list + while (p_li != NULL + && (p_li->li_tv.v_type != VAR_STRING + || p_li->li_tv.vval.v_string == NULL)) { + p_li = p_li->li_next; // Skip non-string items + } + + if (p_li == NULL) { // End of the list + state->p_li = NULL; + return QF_END_OF_INPUT; + } + + len = STRLEN(p_li->li_tv.vval.v_string); + if (len > IOSIZE - 2) { + state->linebuf = qf_grow_linebuf(state, len); + } else { + state->linebuf = IObuff; + state->linelen = len; + } + + STRLCPY(state->linebuf, p_li->li_tv.vval.v_string, state->linelen + 1); + + state->p_li = p_li->li_next; // next item + return QF_OK; +} + +/// Get the next string from state->buf. +static int qf_get_next_buf_line(qfstate_T *state) +{ + char_u *p_buf = NULL; + size_t len; + + // Get the next line from the supplied buffer + if (state->buflnum > state->lnumlast) { + return QF_END_OF_INPUT; + } + p_buf = ml_get_buf(state->buf, state->buflnum, false); + state->buflnum += 1; + + len = STRLEN(p_buf); + if (len > IOSIZE - 2) { + state->linebuf = qf_grow_linebuf(state, len); + } else { + state->linebuf = IObuff; + state->linelen = len; + } + STRLCPY(state->linebuf, p_buf, state->linelen + 1); + + return QF_OK; +} + +/// Get the next string from file state->fd. +static int qf_get_next_file_line(qfstate_T *state) +{ + size_t growbuflen; + + if (fgets((char *)IObuff, IOSIZE, state->fd) == NULL) { + return QF_END_OF_INPUT; + } + + bool discard = false; + state->linelen = STRLEN(IObuff); + if (state->linelen == IOSIZE - 1 + && !(IObuff[state->linelen - 1] == '\n')) { + // The current line exceeds IObuff, continue reading using growbuf + // until EOL or LINE_MAXLEN bytes is read. + if (state->growbuf == NULL) { + state->growbufsiz = 2 * (IOSIZE - 1); + state->growbuf = xmalloc(state->growbufsiz); + } + + // Copy the read part of the line, excluding null-terminator + memcpy(state->growbuf, IObuff, IOSIZE - 1); + growbuflen = state->linelen; + + for (;;) { + if (fgets((char *)state->growbuf + growbuflen, + (int)(state->growbufsiz - growbuflen), state->fd) == NULL) { + break; + } + state->linelen = STRLEN(state->growbuf + growbuflen); + growbuflen += state->linelen; + if (state->growbuf[growbuflen - 1] == '\n') { + break; + } + if (state->growbufsiz == LINE_MAXLEN) { + discard = true; + break; + } + + state->growbufsiz = (2 * state->growbufsiz < LINE_MAXLEN) + ? 2 * state->growbufsiz : LINE_MAXLEN; + state->growbuf = xrealloc(state->growbuf, state->growbufsiz); + } + + while (discard) { + // The current line is longer than LINE_MAXLEN, continue reading but + // discard everything until EOL or EOF is reached. + if (fgets((char *)IObuff, IOSIZE, state->fd) == NULL + || STRLEN(IObuff) < IOSIZE - 1 + || IObuff[IOSIZE - 1] == '\n') { + break; + } + } + + state->linebuf = state->growbuf; + state->linelen = growbuflen; + } else { + state->linebuf = IObuff; + } + return QF_OK; +} + +/// Get the next string from a file/buffer/list/string. +static int qf_get_nextline(qfstate_T *state) +{ + int status = QF_FAIL; + + if (state->fd == NULL) { + if (state->tv != NULL) { + if (state->tv->v_type == VAR_STRING) { + // Get the next line from the supplied string + status = qf_get_next_str_line(state); + } else if (state->tv->v_type == VAR_LIST) { + // Get the next line from the supplied list + status = qf_get_next_list_line(state); + } + } else { + // Get the next line from the supplied buffer + status = qf_get_next_buf_line(state); + } + } else { + // Get the next line from the supplied file + status = qf_get_next_file_line(state); + } + + if (status != QF_OK) { + return status; + } + + if (state->linelen > 0 && state->linebuf[state->linelen - 1] == '\n') { + state->linebuf[state->linelen - 1] = NUL; +#ifdef USE_CRNL + if (state->linelen > 1 && state->linebuf[state->linelen - 2] == '\r') { + state->linebuf[state->linelen - 2] = NUL; + } +#endif + } + + remove_bom(state->linebuf); + + return QF_OK; +} + + +/// Parse a line and get the quickfix fields. +/// Return the QF_ status. +static int qf_parse_line(qf_info_T *qi, char_u *linebuf, size_t linelen, + efm_T *fmt_first, qffields_T *fields) +{ + efm_T *fmt_ptr; + size_t len; + int i; + int idx = 0; + char_u *tail = NULL; + regmatch_T regmatch; + + + // Always ignore case when looking for a matching error. + regmatch.rm_ic = true; + + // If there was no %> item start at the first pattern + if (fmt_start == NULL) { + fmt_ptr = fmt_first; + } else { + fmt_ptr = fmt_start; + fmt_start = NULL; + } + + // Try to match each part of 'errorformat' until we find a complete + // match or no match. + fields->valid = true; +restofline: + for (; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next) { + idx = fmt_ptr->prefix; + if (qi->qf_multiscan && vim_strchr((char_u *)"OPQ", idx) == NULL) { + continue; + } + fields->namebuf[0] = NUL; + fields->pattern[0] = NUL; + if (!qi->qf_multiscan) { + fields->errmsg[0] = NUL; + } + fields->lnum = 0; + fields->col = 0; + fields->use_viscol = false; + fields->enr = -1; + fields->type = 0; + tail = NULL; + + regmatch.regprog = fmt_ptr->prog; + int r = vim_regexec(®match, linebuf, (colnr_T)0); + fmt_ptr->prog = regmatch.regprog; + if (r) { + if ((idx == 'C' || idx == 'Z') && !qi->qf_multiline) { + continue; + } + if (vim_strchr((char_u *)"EWI", idx) != NULL) { + fields->type = (char_u)idx; + } else { + fields->type = 0; + } + // Extract error message data from matched line. + // We check for an actual submatch, because "\[" and "\]" in + // the 'errorformat' may cause the wrong submatch to be used. + if ((i = (int)fmt_ptr->addr[0]) > 0) { // %f + if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) { + continue; + } + // Expand ~/file and $HOME/file to full path. + char_u c = *regmatch.endp[i]; + *regmatch.endp[i] = NUL; + expand_env(regmatch.startp[i], fields->namebuf, CMDBUFFSIZE); + *regmatch.endp[i] = c; + + if (vim_strchr((char_u *)"OPQ", idx) != NULL + && !os_path_exists(fields->namebuf)) { + continue; + } + } + if ((i = (int)fmt_ptr->addr[1]) > 0) { // %n + if (regmatch.startp[i] == NULL) { + continue; + } + fields->enr = (int)atol((char *)regmatch.startp[i]); + } + if ((i = (int)fmt_ptr->addr[2]) > 0) { // %l + if (regmatch.startp[i] == NULL) { + continue; + } + fields->lnum = atol((char *)regmatch.startp[i]); + } + if ((i = (int)fmt_ptr->addr[3]) > 0) { // %c + if (regmatch.startp[i] == NULL) { + continue; + } + fields->col = (int)atol((char *)regmatch.startp[i]); + } + if ((i = (int)fmt_ptr->addr[4]) > 0) { // %t + if (regmatch.startp[i] == NULL) { + continue; + } + fields->type = *regmatch.startp[i]; + } + if (fmt_ptr->flags == '+' && !qi->qf_multiscan) { // %+ + if (linelen > fields->errmsglen) { + // linelen + null terminator + fields->errmsg = xrealloc(fields->errmsg, linelen + 1); + fields->errmsglen = linelen + 1; + } + STRLCPY(fields->errmsg, linebuf, linelen + 1); + } else if ((i = (int)fmt_ptr->addr[5]) > 0) { // %m + if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) { + continue; + } + len = (size_t)(regmatch.endp[i] - regmatch.startp[i]); + if (len > fields->errmsglen) { + // len + null terminator + fields->errmsg = xrealloc(fields->errmsg, len + 1); + fields->errmsglen = len + 1; + } + STRLCPY(fields->errmsg, regmatch.startp[i], len + 1); + } + if ((i = (int)fmt_ptr->addr[6]) > 0) { // %r + if (regmatch.startp[i] == NULL) { + continue; + } + tail = regmatch.startp[i]; + } + if ((i = (int)fmt_ptr->addr[7]) > 0) { // %p + char_u *match_ptr; + + if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) { + continue; + } + fields->col = 0; + for (match_ptr = regmatch.startp[i]; + match_ptr != regmatch.endp[i]; match_ptr++) { + fields->col++; + if (*match_ptr == TAB) { + fields->col += 7; + fields->col -= fields->col % 8; + } + } + fields->col++; + fields->use_viscol = true; + } + if ((i = (int)fmt_ptr->addr[8]) > 0) { // %v + if (regmatch.startp[i] == NULL) { + continue; + } + fields->col = (int)atol((char *)regmatch.startp[i]); + fields->use_viscol = true; + } + if ((i = (int)fmt_ptr->addr[9]) > 0) { // %s + if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) { + continue; + } + len = (size_t)(regmatch.endp[i] - regmatch.startp[i]); + if (len > CMDBUFFSIZE - 5) { + len = CMDBUFFSIZE - 5; + } + STRCPY(fields->pattern, "^\\V"); + xstrlcat((char *)fields->pattern, (char *)regmatch.startp[i], + CMDBUFFSIZE+1); + fields->pattern[len + 3] = '\\'; + fields->pattern[len + 4] = '$'; + fields->pattern[len + 5] = NUL; + } + break; + } + } + qi->qf_multiscan = false; + + if (fmt_ptr == NULL || idx == 'D' || idx == 'X') { + if (fmt_ptr != NULL) { + if (idx == 'D') { // enter directory + if (*fields->namebuf == NUL) { + EMSG(_("E379: Missing or empty directory name")); + return QF_FAIL; + } + qi->qf_directory = qf_push_dir(fields->namebuf, &qi->qf_dir_stack, + false); + if (qi->qf_directory == NULL) { + return QF_FAIL; + } + } else if (idx == 'X') { // leave directory + qi->qf_directory = qf_pop_dir(&qi->qf_dir_stack); + } + } + fields->namebuf[0] = NUL; // no match found, remove file name + fields->lnum = 0; // don't jump to this line + fields->valid = false; + if (linelen > fields->errmsglen) { + // linelen + null terminator + fields->errmsg = xrealloc(fields->errmsg, linelen + 1); + fields->errmsglen = linelen + 1; + } + // copy whole line to error message + STRLCPY(fields->errmsg, linebuf, linelen + 1); + if (fmt_ptr == NULL) { + qi->qf_multiline = qi->qf_multiignore = false; + } + } else { + // honor %> item + if (fmt_ptr->conthere) { + fmt_start = fmt_ptr; + } + + if (vim_strchr((char_u *)"AEWI", idx) != NULL) { + qi->qf_multiline = true; // start of a multi-line message + qi->qf_multiignore = false; // reset continuation + } else if (vim_strchr((char_u *)"CZ", idx) + != NULL) { // continuation of multi-line msg + if (!qi->qf_multiignore) { + qfline_T *qfprev = qi->qf_lists[qi->qf_curlist].qf_last; + if (qfprev == NULL) { + return QF_FAIL; + } + if (*fields->errmsg && !qi->qf_multiignore) { + size_t len = STRLEN(qfprev->qf_text); + qfprev->qf_text = xrealloc(qfprev->qf_text, + len + STRLEN(fields->errmsg) + 2); + qfprev->qf_text[len] = '\n'; + STRCPY(qfprev->qf_text + len + 1, fields->errmsg); + } + if (qfprev->qf_nr == -1) { + qfprev->qf_nr = fields->enr; + } + if (vim_isprintc(fields->type) && !qfprev->qf_type) { + qfprev->qf_type = fields->type; // only printable chars allowed + } + if (!qfprev->qf_lnum) { + qfprev->qf_lnum = fields->lnum; + } + if (!qfprev->qf_col) { + qfprev->qf_col = fields->col; + } + qfprev->qf_viscol = fields->use_viscol; + if (!qfprev->qf_fnum) { + qfprev->qf_fnum = qf_get_fnum(qi, qi->qf_directory, + *fields->namebuf || qi->qf_directory + ? fields->namebuf + : qi->qf_currfile && fields->valid + ? qi->qf_currfile : 0); + } + } + if (idx == 'Z') { + qi->qf_multiline = qi->qf_multiignore = false; + } + + line_breakcheck(); + return QF_IGNORE_LINE; + } else if (vim_strchr((char_u *)"OPQ", idx) != NULL) { + // global file names + fields->valid = false; + if (*fields->namebuf == NUL || os_path_exists(fields->namebuf)) { + if (*fields->namebuf && idx == 'P') { + qi->qf_currfile = qf_push_dir(fields->namebuf, &qi->qf_file_stack, + true); + } else if (idx == 'Q') { + qi->qf_currfile = qf_pop_dir(&qi->qf_file_stack); + } + *fields->namebuf = NUL; + if (tail && *tail) { + STRMOVE(IObuff, skipwhite(tail)); + qi->qf_multiscan = true; + goto restofline; + } + } + } + if (fmt_ptr->flags == '-') { // generally exclude this line + if (qi->qf_multiline) { + // also exclude continuation lines + qi->qf_multiignore = true; + } + return QF_IGNORE_LINE; + } + } + + return QF_OK; +} + // Read the errorfile "efile" into memory, line by line, building the error // list. // Alternative: when "efile" is NULL read errors from buffer "buf". @@ -449,45 +968,27 @@ qf_init_ext( char_u *qf_title ) { - char_u *namebuf; - char_u *errmsg; - size_t errmsglen; - char_u *pattern; - char_u *growbuf = NULL; - size_t growbuflen; - size_t growbufsiz = 0; - char_u *linebuf = NULL; - size_t linelen = 0; - bool discard; - int col = 0; - bool use_viscol = false; - char_u type = 0; - linenr_T buflnum = lnumfirst; - long lnum = 0L; - int enr = 0; - FILE *fd = NULL; + qfstate_T state = { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, + NULL, 0, 0 }; + qffields_T fields = { NULL, NULL, 0, 0L, 0, false, NULL, 0, 0, 0 }; qfline_T *old_last = NULL; + bool adding = false; static efm_T *fmt_first = NULL; - efm_T *fmt_ptr; - efm_T *fmt_start = NULL; char_u *efm; static char_u *last_efm = NULL; - size_t len; - int i; - int idx = 0; int retval = -1; // default: return error flag - char_u *tail = NULL; - char_u *p_buf = NULL; - char_u *p_str = NULL; - listitem_T *p_li = NULL; - regmatch_T regmatch; + int status; - namebuf = xmalloc(CMDBUFFSIZE + 1); - errmsglen = CMDBUFFSIZE + 1; - errmsg = xmalloc(errmsglen); - pattern = xmalloc(CMDBUFFSIZE + 1); + // Do not used the cached buffer, it may have been wiped out. + xfree(qf_last_bufname); + qf_last_bufname = NULL; - if (efile != NULL && (fd = mch_fopen((char *)efile, "r")) == NULL) { + fields.namebuf = xmalloc(CMDBUFFSIZE + 1); + fields.errmsglen = CMDBUFFSIZE + 1; + fields.errmsg = xmalloc(fields.errmsglen); + fields.pattern = xmalloc(CMDBUFFSIZE + 1); + + if (efile != NULL && (state.fd = mch_fopen((char *)efile, "r")) == NULL) { EMSG2(_(e_openerrf), efile); goto qf_init_end; } @@ -497,18 +998,16 @@ qf_init_ext( qf_new_list(qi, qf_title); } else if (qi->qf_lists[qi->qf_curlist].qf_count > 0) { // Adding to existing list, use last entry. + adding = true; old_last = qi->qf_lists[qi->qf_curlist].qf_last; } - /* - * Each part of the format string is copied and modified from errorformat to - * regex prog. Only a few % characters are allowed. - */ - /* Use the local value of 'errorformat' if it's set. */ - if (errorformat == p_efm && tv == NULL && *buf->b_p_efm != NUL) + // Use the local value of 'errorformat' if it's set. + if (errorformat == p_efm && tv == NULL && buf && *buf->b_p_efm != NUL) { efm = buf->b_p_efm; - else + } else { efm = errorformat; + } // If we are not adding or adding to another list: clear the state. if (newlist || qi->qf_curlist != qi->qf_dir_curlist) { @@ -547,424 +1046,57 @@ qf_init_ext( */ got_int = FALSE; - /* Always ignore case when looking for a matching error. */ - regmatch.rm_ic = TRUE; - if (tv != NULL) { - if (tv->v_type == VAR_STRING) - p_str = tv->vval.v_string; - else if (tv->v_type == VAR_LIST) - p_li = tv->vval.v_list->lv_first; + if (tv->v_type == VAR_STRING) { + state.p_str = tv->vval.v_string; + } else if (tv->v_type == VAR_LIST) { + state.p_li = tv->vval.v_list->lv_first; + } + state.tv = tv; } + state.buf = buf; + state.buflnum = lnumfirst; + state.lnumlast = lnumlast; /* * Read the lines in the error file one by one. * Try to recognize one of the error formats in each line. */ while (!got_int) { - /* Get the next line. */ - if (fd == NULL) { - if (tv != NULL) { - if (tv->v_type == VAR_STRING) { - /* Get the next line from the supplied string */ - char_u *p; - - if (*p_str == NUL) { // Reached the end of the string - break; - } - - p = vim_strchr(p_str, '\n'); - if (p != NULL) { - len = (size_t)(p - p_str) + 1; - } else { - len = STRLEN(p_str); - } - - if (len > IOSIZE - 2) { - linebuf = qf_grow_linebuf(&growbuf, &growbufsiz, len, &linelen); - } else { - linebuf = IObuff; - linelen = len; - } - STRLCPY(linebuf, p_str, linelen + 1); - - // Increment using len in order to discard the rest of the line if it - // exceeds LINE_MAXLEN. - p_str += len; - } else if (tv->v_type == VAR_LIST) { - // Get the next line from the supplied list - while (p_li != NULL - && (p_li->li_tv.v_type != VAR_STRING - || p_li->li_tv.vval.v_string == NULL)) { - p_li = p_li->li_next; // Skip non-string items - } - - if (p_li == NULL) { // End of the list - break; - } - - len = STRLEN(p_li->li_tv.vval.v_string); - if (len > IOSIZE - 2) { - linebuf = qf_grow_linebuf(&growbuf, &growbufsiz, len, &linelen); - } else { - linebuf = IObuff; - linelen = len; - } - - STRLCPY(linebuf, p_li->li_tv.vval.v_string, linelen + 1); - - p_li = p_li->li_next; /* next item */ - } - } else { - /* Get the next line from the supplied buffer */ - if (buflnum > lnumlast) - break; - p_buf = ml_get_buf(buf, buflnum++, false); - len = STRLEN(p_buf); - if (len > IOSIZE - 2) { - linebuf = qf_grow_linebuf(&growbuf, &growbufsiz, len, &linelen); - } else { - linebuf = IObuff; - linelen = len; - } - STRLCPY(linebuf, p_buf, linelen + 1); - } - } else { - if (fgets((char *)IObuff, IOSIZE, fd) == NULL) { - break; - } - - discard = false; - linelen = STRLEN(IObuff); - if (linelen == IOSIZE - 1 && !(IObuff[linelen - 1] == '\n' -#ifdef USE_CRNL - || IObuff[linelen - 1] == '\r' -#endif - )) { // NOLINT(whitespace/parens) - // The current line exceeds IObuff, continue reading using growbuf - // until EOL or LINE_MAXLEN bytes is read. - if (growbuf == NULL) { - growbufsiz = 2 * (IOSIZE - 1); - growbuf = xmalloc(growbufsiz); - } - - // Copy the read part of the line, excluding null-terminator - memcpy(growbuf, IObuff, IOSIZE - 1); - growbuflen = linelen; - - for (;;) { - if (fgets((char *)growbuf + growbuflen, - (int)(growbufsiz - growbuflen), fd) == NULL) { - break; - } - linelen = STRLEN(growbuf + growbuflen); - growbuflen += linelen; - if (growbuf[growbuflen - 1] == '\n' -#ifdef USE_CRNL - || growbuf[growbuflen - 1] == '\r' -#endif - ) { - break; - } - if (growbufsiz == LINE_MAXLEN) { - discard = true; - break; - } - - growbufsiz = (2 * growbufsiz < LINE_MAXLEN) - ? 2 * growbufsiz : LINE_MAXLEN; - growbuf = xrealloc(growbuf, 2 * growbufsiz); - } - - while (discard) { - // The current line is longer than LINE_MAXLEN, continue reading but - // discard everything until EOL or EOF is reached. - if (fgets((char *)IObuff, IOSIZE, fd) == NULL - || STRLEN(IObuff) < IOSIZE - 1 - || IObuff[IOSIZE - 1] == '\n' -#ifdef USE_CRNL - || IObuff[IOSIZE - 1] == '\r' -#endif - ) { - break; - } - } - - linebuf = growbuf; - linelen = growbuflen; - } else { - linebuf = IObuff; - } - } - - if (linelen > 0 && linebuf[linelen - 1] == '\n') { - linebuf[linelen - 1] = NUL; - } -#ifdef USE_CRNL - if (linelen > 0 && linebuf[linelen - 1] == '\r') { - linebuf[linelen - 1] = NUL; - } -#endif - - remove_bom(linebuf); - - /* If there was no %> item start at the first pattern */ - if (fmt_start == NULL) - fmt_ptr = fmt_first; - else { - fmt_ptr = fmt_start; - fmt_start = NULL; + // Get the next line from a file/buffer/list/string + status = qf_get_nextline(&state); + if (status == QF_END_OF_INPUT) { // end of input + break; } - // Try to match each part of 'errorformat' until we find a complete - // match or no match. - bool valid = true; -restofline: - for (; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next) { - idx = fmt_ptr->prefix; - if (qi->qf_multiscan && vim_strchr((char_u *)"OPQ", idx) == NULL) { - continue; - } - namebuf[0] = NUL; - pattern[0] = NUL; - if (!qi->qf_multiscan) { - errmsg[0] = NUL; - } - lnum = 0; - col = 0; - use_viscol = false; - enr = -1; - type = 0; - tail = NULL; - - regmatch.regprog = fmt_ptr->prog; - int r = vim_regexec(®match, linebuf, (colnr_T)0); - fmt_ptr->prog = regmatch.regprog; - if (r) { - if ((idx == 'C' || idx == 'Z') && !qi->qf_multiline) { - continue; - } - if (vim_strchr((char_u *)"EWI", idx) != NULL) { - type = (char_u)idx; - } else { - type = 0; - } - // Extract error message data from matched line. - // We check for an actual submatch, because "\[" and "\]" in - // the 'errorformat' may cause the wrong submatch to be used. - if ((i = (int)fmt_ptr->addr[0]) > 0) { // %f - if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) { - continue; - } - // Expand ~/file and $HOME/file to full path. - char_u c = *regmatch.endp[i]; - *regmatch.endp[i] = NUL; - expand_env(regmatch.startp[i], namebuf, CMDBUFFSIZE); - *regmatch.endp[i] = c; - - if (vim_strchr((char_u *)"OPQ", idx) != NULL - && !os_path_exists(namebuf)) { - continue; - } - } - if ((i = (int)fmt_ptr->addr[1]) > 0) { /* %n */ - if (regmatch.startp[i] == NULL) - continue; - enr = (int)atol((char *)regmatch.startp[i]); - } - if ((i = (int)fmt_ptr->addr[2]) > 0) { /* %l */ - if (regmatch.startp[i] == NULL) - continue; - lnum = atol((char *)regmatch.startp[i]); - } - if ((i = (int)fmt_ptr->addr[3]) > 0) { /* %c */ - if (regmatch.startp[i] == NULL) - continue; - col = (int)atol((char *)regmatch.startp[i]); - } - if ((i = (int)fmt_ptr->addr[4]) > 0) { /* %t */ - if (regmatch.startp[i] == NULL) - continue; - type = *regmatch.startp[i]; - } - if (fmt_ptr->flags == '+' && !qi->qf_multiscan) { // %+ - if (linelen > errmsglen) { - // linelen + null terminator - errmsg = xrealloc(errmsg, linelen + 1); - errmsglen = linelen + 1; - } - STRLCPY(errmsg, linebuf, linelen + 1); - } else if ((i = (int)fmt_ptr->addr[5]) > 0) { // %m - if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) { - continue; - } - len = (size_t)(regmatch.endp[i] - regmatch.startp[i]); - if (len > errmsglen) { - // len + null terminator - errmsg = xrealloc(errmsg, len + 1); - errmsglen = len + 1; - } - STRLCPY(errmsg, regmatch.startp[i], len + 1); - } - if ((i = (int)fmt_ptr->addr[6]) > 0) { /* %r */ - if (regmatch.startp[i] == NULL) - continue; - tail = regmatch.startp[i]; - } - if ((i = (int)fmt_ptr->addr[7]) > 0) { /* %p */ - char_u *match_ptr; - - if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) - continue; - col = 0; - for (match_ptr = regmatch.startp[i]; - match_ptr != regmatch.endp[i]; ++match_ptr) { - ++col; - if (*match_ptr == TAB) { - col += 7; - col -= col % 8; - } - } - col++; - use_viscol = true; - } - if ((i = (int)fmt_ptr->addr[8]) > 0) { /* %v */ - if (regmatch.startp[i] == NULL) - continue; - col = (int)atol((char *)regmatch.startp[i]); - use_viscol = true; - } - if ((i = (int)fmt_ptr->addr[9]) > 0) { /* %s */ - if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) - continue; - len = (size_t)(regmatch.endp[i] - regmatch.startp[i]); - if (len > CMDBUFFSIZE - 5) { - len = CMDBUFFSIZE - 5; - } - STRCPY(pattern, "^\\V"); - STRNCAT(pattern, regmatch.startp[i], len); - pattern[len + 3] = '\\'; - pattern[len + 4] = '$'; - pattern[len + 5] = NUL; - } - break; - } + status = qf_parse_line(qi, state.linebuf, state.linelen, fmt_first, + &fields); + if (status == QF_FAIL) { + goto error2; } - qi->qf_multiscan = false; - - if (fmt_ptr == NULL || idx == 'D' || idx == 'X') { - if (fmt_ptr != NULL) { - if (idx == 'D') { /* enter directory */ - if (*namebuf == NUL) { - EMSG(_("E379: Missing or empty directory name")); - goto error2; - } - qi->qf_directory = qf_push_dir(namebuf, &qi->qf_dir_stack, false); - if (qi->qf_directory == NULL) { - goto error2; - } - } else if (idx == 'X') { // leave directory - qi->qf_directory = qf_pop_dir(&qi->qf_dir_stack); - } - } - namebuf[0] = NUL; // no match found, remove file name - lnum = 0; // don't jump to this line - valid = false; - if (linelen > errmsglen) { - // linelen + null terminator - errmsg = xrealloc(errmsg, linelen + 1); - } - // copy whole line to error message - STRLCPY(errmsg, linebuf, linelen + 1); - if (fmt_ptr == NULL) { - qi->qf_multiline = qi->qf_multiignore = false; - } - } else if (fmt_ptr != NULL) { - /* honor %> item */ - if (fmt_ptr->conthere) - fmt_start = fmt_ptr; - - if (vim_strchr((char_u *)"AEWI", idx) != NULL) { - qi->qf_multiline = true; // start of a multi-line message - qi->qf_multiignore = false; // reset continuation - } else if (vim_strchr((char_u *)"CZ", idx) - != NULL) { // continuation of multi-line msg - qfline_T *qfprev = qi->qf_lists[qi->qf_curlist].qf_last; - if (qfprev == NULL) { - goto error2; - } - if (*errmsg && !qi->qf_multiignore) { - size_t len = STRLEN(qfprev->qf_text); - qfprev->qf_text = xrealloc(qfprev->qf_text, len + STRLEN(errmsg) + 2); - qfprev->qf_text[len] = '\n'; - STRCPY(qfprev->qf_text + len + 1, errmsg); - } - if (qfprev->qf_nr == -1) - qfprev->qf_nr = enr; - if (vim_isprintc(type) && !qfprev->qf_type) - qfprev->qf_type = type; /* only printable chars allowed */ - if (!qfprev->qf_lnum) - qfprev->qf_lnum = lnum; - if (!qfprev->qf_col) - qfprev->qf_col = col; - qfprev->qf_viscol = use_viscol; - if (!qfprev->qf_fnum) { - qfprev->qf_fnum = qf_get_fnum(qi, qi->qf_directory, - *namebuf - || qi->qf_directory - ? namebuf : qi->qf_currfile - && valid ? qi->qf_currfile : 0); - } - if (idx == 'Z') { - qi->qf_multiline = qi->qf_multiignore = false; - } - line_breakcheck(); - continue; - } else if (vim_strchr((char_u *)"OPQ", idx) != NULL) { - // global file names - valid = false; - if (*namebuf == NUL || os_path_exists(namebuf)) { - if (*namebuf && idx == 'P') { - qi->qf_currfile = qf_push_dir(namebuf, &qi->qf_file_stack, true); - } else if (idx == 'Q') { - qi->qf_currfile = qf_pop_dir(&qi->qf_file_stack); - } - *namebuf = NUL; - if (tail && *tail) { - STRMOVE(IObuff, skipwhite(tail)); - qi->qf_multiscan = true; - goto restofline; - } - } - } - if (fmt_ptr->flags == '-') { // generally exclude this line - if (qi->qf_multiline) { - // also exclude continuation lines - qi->qf_multiignore = true; - } - continue; - } + if (status == QF_IGNORE_LINE) { + continue; } if (qf_add_entry(qi, qi->qf_directory, - (*namebuf || qi->qf_directory) - ? namebuf : ((qi->qf_currfile && valid) - ? qi->qf_currfile : (char_u *)NULL), + (*fields.namebuf || qi->qf_directory) + ? fields.namebuf : ((qi->qf_currfile && fields.valid) + ? qi->qf_currfile : (char_u *)NULL), 0, - errmsg, - lnum, - col, - use_viscol, - pattern, - enr, - type, - valid) == FAIL) { + fields.errmsg, + fields.lnum, + fields.col, + fields.use_viscol, + fields.pattern, + fields.enr, + fields.type, + fields.valid) == FAIL) { goto error2; } line_breakcheck(); } - if (fd == NULL || !ferror(fd)) { + if (state.fd == NULL || !ferror(state.fd)) { if (qi->qf_lists[qi->qf_curlist].qf_index == 0) { /* no valid entry found */ qi->qf_lists[qi->qf_curlist].qf_ptr = @@ -983,19 +1115,21 @@ restofline: } EMSG(_(e_readerrf)); error2: - qf_free(qi, qi->qf_curlist); - qi->qf_listcount--; - if (qi->qf_curlist > 0) { - qi->qf_curlist--; + if (!adding) { + qf_free(qi, qi->qf_curlist); + qi->qf_listcount--; + if (qi->qf_curlist > 0) { + qi->qf_curlist--; + } } qf_init_end: - if (fd != NULL) { - fclose(fd); + if (state.fd != NULL) { + fclose(state.fd); } - xfree(namebuf); - xfree(errmsg); - xfree(pattern); - xfree(growbuf); + xfree(fields.namebuf); + xfree(fields.errmsg); + xfree(fields.pattern); + xfree(state.growbuf); qf_update_buffer(qi, old_last); @@ -1105,7 +1239,8 @@ static int qf_add_entry(qf_info_T *qi, char_u *dir, char_u *fname, int bufnum, qfp->qf_fnum = bufnum; if (buf != NULL) { - buf->b_has_qf_entry = true; + buf->b_has_qf_entry |= + (qi == &ql_info) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY; } } else { qfp->qf_fnum = qf_get_fnum(qi, dir, fname); @@ -1122,7 +1257,7 @@ static int qf_add_entry(qf_info_T *qi, char_u *dir, char_u *fname, int bufnum, qfp->qf_nr = nr; if (type != 1 && !vim_isprintc(type)) /* only printable chars allowed */ type = 0; - qfp->qf_type = type; + qfp->qf_type = (char_u)type; qfp->qf_valid = valid; lastp = &qi->qf_lists[qi->qf_curlist].qf_last; @@ -1282,11 +1417,12 @@ void copy_loclist(win_T *from, win_T *to) to->w_llist->qf_curlist = qi->qf_curlist; /* current list */ } -// Get buffer number for file "dir.name". +// Get buffer number for file "directory/fname". // Also sets the b_has_qf_entry flag. static int qf_get_fnum(qf_info_T *qi, char_u *directory, char_u *fname) { - char_u *ptr; + char_u *ptr = NULL; + char_u *bufname; buf_T *buf; if (fname == NULL || *fname == NUL) { // no file name return 0; @@ -1313,16 +1449,28 @@ static int qf_get_fnum(qf_info_T *qi, char_u *directory, char_u *fname) ptr = vim_strsave(fname); } } - // Use concatenated directory name and file name - buf = buflist_new(ptr, NULL, (linenr_T)0, 0); + // Use concatenated directory name and file name. + bufname = ptr; + } else { + bufname = fname; + } + + if (qf_last_bufname != NULL + && STRCMP(bufname, qf_last_bufname) == 0 + && bufref_valid(&qf_last_bufref)) { + buf = qf_last_bufref.br_buf; xfree(ptr); } else { - buf = buflist_new(fname, NULL, (linenr_T)0, 0); + xfree(qf_last_bufname); + buf = buflist_new(bufname, NULL, (linenr_T)0, BLN_NOOPT); + qf_last_bufname = (bufname == ptr) ? bufname : vim_strsave(bufname); + set_bufref(&qf_last_bufref, buf); } if (buf == NULL) { return 0; } - buf->b_has_qf_entry = true; + buf->b_has_qf_entry = + (qi == &ql_info) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY; return buf->b_fnum; } @@ -1730,7 +1878,7 @@ win_found: * If there is only one window and it is the quickfix window, create a * new one above the quickfix window. */ - if (((firstwin == lastwin) && bt_quickfix(curbuf)) || !usable_win) { + if ((ONE_WINDOW && bt_quickfix(curbuf)) || !usable_win) { flags = WSP_ABOVE; if (ll_ref != NULL) flags |= WSP_NEWLOC; @@ -1843,7 +1991,7 @@ win_found: ok = buflist_getfile(qf_ptr->qf_fnum, (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit); - if (qi != &ql_info && !win_valid(oldwin)) { + if (qi != &ql_info && !win_valid_any_tab(oldwin)) { EMSG(_("E924: Current window was closed")); is_abort = true; opened_window = false; @@ -2049,21 +2197,20 @@ void qf_list(exarg_T *eap) if (qfp->qf_lnum == 0) { IObuff[0] = NUL; } else if (qfp->qf_col == 0) { - vim_snprintf((char *)IObuff, IOSIZE, ":%" PRId64, - (int64_t)qfp->qf_lnum); + vim_snprintf((char *)IObuff, IOSIZE, ":%" PRIdLINENR, qfp->qf_lnum); } else { - vim_snprintf((char *)IObuff, IOSIZE, ":%" PRId64 " col %d", - (int64_t)qfp->qf_lnum, qfp->qf_col); + vim_snprintf((char *)IObuff, IOSIZE, ":%" PRIdLINENR " col %d", + qfp->qf_lnum, qfp->qf_col); } vim_snprintf((char *)IObuff + STRLEN(IObuff), IOSIZE, "%s:", (char *)qf_types(qfp->qf_type, qfp->qf_nr)); - msg_puts_attr(IObuff, hl_attr(HLF_N)); + msg_puts_attr((const char *)IObuff, hl_attr(HLF_N)); if (qfp->qf_pattern != NULL) { qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE); - STRCAT(IObuff, ":"); - msg_puts(IObuff); + xstrlcat((char *)IObuff, ":", IOSIZE); + msg_puts((const char *)IObuff); } - msg_puts((char_u *)" "); + msg_puts(" "); /* Remove newlines and leading whitespace from the text. For an * unrecognized line keep the indent, the compiler may mark a word @@ -2105,6 +2252,31 @@ static void qf_fmt_text(char_u *text, char_u *buf, int bufsize) buf[i] = NUL; } +static void qf_msg(qf_info_T *qi, int which, char *lead) +{ + char *title = (char *)qi->qf_lists[which].qf_title; + int count = qi->qf_lists[which].qf_count; + char_u buf[IOSIZE]; + + vim_snprintf((char *)buf, IOSIZE, _("%serror list %d of %d; %d errors "), + lead, + which + 1, + qi->qf_listcount, + count); + + if (title != NULL) { + size_t len = STRLEN(buf); + + if (len < 34) { + memset(buf + len, ' ', 34 - len); + buf[34] = NUL; + } + xstrlcat((char *)buf, title, IOSIZE); + } + trunc_string(buf, buf, (int)Columns - 1, IOSIZE); + msg(buf); +} + /* * ":colder [count]": Up in the quickfix stack. * ":cnewer [count]": Down in the quickfix stack. @@ -2145,20 +2317,29 @@ void qf_age(exarg_T *eap) ++qi->qf_curlist; } } - qf_msg(qi); + qf_msg(qi, qi->qf_curlist, ""); + qf_update_buffer(qi, NULL); } -static void qf_msg(qf_info_T *qi) +void qf_history(exarg_T *eap) { - smsg(_("error list %d of %d; %d errors"), - qi->qf_curlist + 1, qi->qf_listcount, - qi->qf_lists[qi->qf_curlist].qf_count); - qf_update_buffer(qi, NULL); + qf_info_T *qi = &ql_info; + int i; + + if (eap->cmdidx == CMD_lhistory) { + qi = GET_LOC_LIST(curwin); + } + if (qi == NULL || (qi->qf_listcount == 0 + && qi->qf_lists[qi->qf_curlist].qf_count == 0)) { + MSG(_("No entries")); + } else { + for (i = 0; i < qi->qf_listcount; i++) { + qf_msg(qi, i, i == qi->qf_curlist ? "> " : " "); + } + } } -/* - * Free error list "idx". - */ +/// Free all the entries in the error list "idx". static void qf_free(qf_info_T *qi, int idx) { qfline_T *qfp; @@ -2190,7 +2371,9 @@ static void qf_free(qf_info_T *qi, int idx) qi->qf_lists[idx].qf_index = 0; qf_clean_dir_stack(&qi->qf_dir_stack); + qi->qf_directory = NULL; qf_clean_dir_stack(&qi->qf_file_stack); + qi->qf_currfile = NULL; } /* @@ -2203,8 +2386,9 @@ void qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long int idx; qf_info_T *qi = &ql_info; bool found_one = false; + int buf_has_flag = wp == NULL ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY; - if (!curbuf->b_has_qf_entry) { + if (!(curbuf->b_has_qf_entry & buf_has_flag)) { return; } if (wp != NULL) { @@ -2231,7 +2415,7 @@ void qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long } if (!found_one) { - curbuf->b_has_qf_entry = false; + curbuf->b_has_qf_entry &= ~buf_has_flag; } } @@ -2413,15 +2597,13 @@ void ex_copen(exarg_T *eap) else { /* Create a new quickfix buffer */ (void)do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, oldwin); - /* switch off 'swapfile' */ - set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL); - set_option_value((char_u *)"bt", 0L, (char_u *)"quickfix", - OPT_LOCAL); - set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL); + // Switch off 'swapfile'. + set_option_value("swf", 0L, NULL, OPT_LOCAL); + set_option_value("bt", 0L, "quickfix", OPT_LOCAL); + set_option_value("bh", 0L, "wipe", OPT_LOCAL); RESET_BINDING(curwin); - curwin->w_p_diff = FALSE; - set_option_value((char_u *)"fdm", 0L, (char_u *)"manual", - OPT_LOCAL); + curwin->w_p_diff = false; + set_option_value("fdm", 0L, "manual", OPT_LOCAL); } /* Only set the height when still in the same tab page and there is no @@ -2582,6 +2764,19 @@ static buf_T *qf_find_buf(qf_info_T *qi) return NULL; } +/// Update the w:quickfix_title variable in the quickfix/location list window +static void qf_update_win_titlevar(qf_info_T *qi) +{ + win_T *win; + + if ((win = qf_find_win(qi)) != NULL) { + win_T *curwin_save = curwin; + curwin = win; + qf_set_title_var(qi); + curwin = curwin_save; + } +} + /* * Find the quickfix buffer. If it exists, update the contents. */ @@ -2589,7 +2784,6 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last) { buf_T *buf; win_T *win; - win_T *curwin_save; aco_save_T aco; /* Check if a buffer for the quickfix list exists. Update it. */ @@ -2602,12 +2796,7 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last) aucmd_prepbuf(&aco, buf); } - if ((win = qf_find_win(qi)) != NULL) { - curwin_save = curwin; - curwin = win; - qf_set_title_var(qi); - curwin = curwin_save; - } + qf_update_win_titlevar(qi); qf_fill_buffer(qi, buf, old_last); @@ -2726,14 +2915,14 @@ static void qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last) } } - /* correct cursor position */ - check_lnums(TRUE); + // Correct cursor position. + check_lnums(true); if (old_last == NULL) { // Set the 'filetype' to "qf" each time after filling the buffer. This // resembles reading a file into a buffer, it's more logical when using // autocommands. - set_option_value((char_u *)"ft", 0L, (char_u *)"qf", OPT_LOCAL); + set_option_value("ft", 0L, "qf", OPT_LOCAL); curbuf->b_p_ma = false; keep_filetype = true; // don't detect 'filetype' @@ -2837,11 +3026,11 @@ void ex_make(exarg_T *eap) case CMD_lgrepadd: au_name = (char_u *)"lgrepadd"; break; default: break; } - if (au_name != NULL) { - apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, - curbuf->b_fname, TRUE, curbuf); - if (did_throw || force_abort) + if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, + curbuf->b_fname, true, curbuf)) { + if (aborting()) { return; + } } if (eap->cmdidx == CMD_lmake || eap->cmdidx == CMD_lgrep @@ -2938,7 +3127,7 @@ static char_u *get_mef_name(void) STRCPY(name, p_mef); sprintf((char *)name + (p - p_mef), "%d%d", start, off); STRCAT(name, p + 2); - // Don't accept a symbolic link, its a security risk. + // Don't accept a symbolic link, it's a security risk. FileInfo file_info; bool file_or_link_found = os_fileinfo_link((char *)name, &file_info); if (!file_or_link_found) { @@ -3111,7 +3300,6 @@ void ex_cc(exarg_T *eap) || eap->cmdidx == CMD_lrewind || eap->cmdidx == CMD_lfirst || eap->cmdidx == CMD_llast - || eap->cmdidx == CMD_llast || eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) { qi = GET_LOC_LIST(curwin); @@ -3168,7 +3356,6 @@ void ex_cnext(exarg_T *eap) || eap->cmdidx == CMD_lnfile || eap->cmdidx == CMD_lNfile || eap->cmdidx == CMD_lpfile - || eap->cmdidx == CMD_lpfile || eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) { qi = GET_LOC_LIST(curwin); @@ -3301,11 +3488,11 @@ void ex_vimgrep(exarg_T *eap) case CMD_lgrepadd: au_name = (char_u *)"lgrepadd"; break; default: break; } - if (au_name != NULL) { - apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, - curbuf->b_fname, TRUE, curbuf); - if (did_throw || force_abort) + if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, + curbuf->b_fname, true, curbuf)) { + if (aborting()) { return; + } } if (eap->cmdidx == CMD_lgrep @@ -3451,10 +3638,13 @@ void ex_vimgrep(exarg_T *eap) col = 0; while (vim_regexec_multi(®match, curwin, buf, lnum, col, NULL) > 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. if (qf_add_entry(qi, NULL, // dir fname, - 0, + duplicate_name ? 0 : buf->b_fnum, ml_get_buf(buf, regmatch.startpos[0].lnum + lnum, false), regmatch.startpos[0].lnum + lnum, @@ -3508,17 +3698,23 @@ void ex_vimgrep(exarg_T *eap) buf = NULL; } else if (buf != first_match_buf || (flags & VGR_NOJUMP)) { unload_dummy_buffer(buf, dirname_start); + // Keeping the buffer, remove the dummy flag. + buf->b_flags &= ~BF_DUMMY; buf = NULL; } } if (buf != NULL) { - /* If the buffer is still loaded we need to use the - * directory we jumped to below. */ + // Keeping the buffer, remove the dummy flag. + buf->b_flags &= ~BF_DUMMY; + + // If the buffer is still loaded we need to use the + // directory we jumped to below. if (buf == first_match_buf && target_dir == NULL - && STRCMP(dirname_start, dirname_now) != 0) + && STRCMP(dirname_start, dirname_now) != 0) { target_dir = vim_strsave(dirname_now); + } /* The buffer is still loaded, the Filetype autocommands * need to be done now, in that buffer. And the modelines @@ -3583,52 +3779,6 @@ theend: } /* - * Skip over the pattern argument of ":vimgrep /pat/[g][j]". - * Put the start of the pattern in "*s", unless "s" is NULL. - * If "flags" is not NULL put the flags in it: VGR_GLOBAL, VGR_NOJUMP. - * If "s" is not NULL terminate the pattern with a NUL. - * Return a pointer to the char just past the pattern plus flags. - */ -char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags) -{ - int c; - - if (vim_isIDc(*p)) { - /* ":vimgrep pattern fname" */ - if (s != NULL) - *s = p; - p = skiptowhite(p); - if (s != NULL && *p != NUL) - *p++ = NUL; - } else { - /* ":vimgrep /pattern/[g][j] fname" */ - if (s != NULL) - *s = p + 1; - c = *p; - p = skip_regexp(p + 1, c, TRUE, NULL); - if (*p != c) - return NULL; - - /* Truncate the pattern. */ - if (s != NULL) - *p = NUL; - ++p; - - /* Find the flags */ - while (*p == 'g' || *p == 'j') { - if (flags != NULL) { - if (*p == 'g') - *flags |= VGR_GLOBAL; - else - *flags |= VGR_NOJUMP; - } - ++p; - } - } - return p; -} - -/* * Restore current working directory to "dirname_start" if they differ, taking * into account whether it is set locally or globally. */ @@ -3669,8 +3819,9 @@ load_dummy_buffer ( ) { buf_T *newbuf; - buf_T *newbuf_to_wipe = NULL; - int failed = TRUE; + bufref_T newbufref; + bufref_T newbuf_to_wipe; + int failed = true; aco_save_T aco; // Allocate a buffer without putting it in the buffer list. @@ -3678,6 +3829,7 @@ load_dummy_buffer ( if (newbuf == NULL) { return NULL; } + set_bufref(&newbufref, newbuf); /* Init the options. */ buf_copy_options(newbuf, BCO_ENTER | BCO_NOHELP); @@ -3697,6 +3849,7 @@ load_dummy_buffer ( * work. */ curbuf->b_flags &= ~BF_DUMMY; + newbuf_to_wipe.br_buf = NULL; if (readfile(fname, NULL, (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, NULL, READ_NEW | READ_DUMMY) == OK @@ -3704,19 +3857,24 @@ load_dummy_buffer ( && !(curbuf->b_flags & BF_NEW)) { failed = FALSE; if (curbuf != newbuf) { - /* Bloody autocommands changed the buffer! Can happen when - * using netrw and editing a remote file. Use the current - * buffer instead, delete the dummy one after restoring the - * window stuff. */ - newbuf_to_wipe = newbuf; + // Bloody autocommands changed the buffer! Can happen when + // using netrw and editing a remote file. Use the current + // buffer instead, delete the dummy one after restoring the + // window stuff. + set_bufref(&newbuf_to_wipe, newbuf); newbuf = curbuf; } } - /* restore curwin/curbuf and a few other things */ + // Restore curwin/curbuf and a few other things. aucmd_restbuf(&aco); - if (newbuf_to_wipe != NULL && buf_valid(newbuf_to_wipe)) - wipe_buffer(newbuf_to_wipe, FALSE); + if (newbuf_to_wipe.br_buf != NULL && bufref_valid(&newbuf_to_wipe)) { + wipe_buffer(newbuf_to_wipe.br_buf, false); + } + + // Add back the "dummy" flag, otherwise buflist_findname_file_id() + // won't skip it. + newbuf->b_flags |= BF_DUMMY; } /* @@ -3727,8 +3885,9 @@ load_dummy_buffer ( os_dirname(resulting_dir, MAXPATHL); restore_start_dir(dirname_start); - if (!buf_valid(newbuf)) + if (!bufref_valid(&newbufref)) { return NULL; + } if (failed) { wipe_dummy_buffer(newbuf, dirname_start); return NULL; @@ -3776,13 +3935,11 @@ static void unload_dummy_buffer(buf_T *buf, char_u *dirname_start) } } -/* - * Add each quickfix error to list "list" as a dictionary. - */ -int get_errorlist(win_T *wp, list_T *list) +/// Add each quickfix error to list "list" as a dictionary. +/// If qf_idx is -1, use the current list. Otherwise, use the specified list. +int get_errorlist(win_T *wp, int qf_idx, list_T *list) { qf_info_T *qi = &ql_info; - dict_T *dict; char_u buf[2]; qfline_T *qfp; int i; @@ -3794,34 +3951,50 @@ int get_errorlist(win_T *wp, list_T *list) return FAIL; } - if (qi->qf_curlist >= qi->qf_listcount - || qi->qf_lists[qi->qf_curlist].qf_count == 0) + if (qf_idx == -1) { + qf_idx = qi->qf_curlist; + } + + if (qf_idx >= qi->qf_listcount + || qi->qf_lists[qf_idx].qf_count == 0) { return FAIL; + } - qfp = qi->qf_lists[qi->qf_curlist].qf_start; - for (i = 1; !got_int && i <= qi->qf_lists[qi->qf_curlist].qf_count; ++i) { - /* Handle entries with a non-existing buffer number. */ + qfp = qi->qf_lists[qf_idx].qf_start; + for (i = 1; !got_int && i <= qi->qf_lists[qf_idx].qf_count; i++) { + // Handle entries with a non-existing buffer number. bufnum = qfp->qf_fnum; if (bufnum != 0 && (buflist_findnr(bufnum) == NULL)) bufnum = 0; - dict = dict_alloc(); - list_append_dict(list, dict); + dict_T *const dict = tv_dict_alloc(); + tv_list_append_dict(list, dict); buf[0] = qfp->qf_type; buf[1] = NUL; - if ( dict_add_nr_str(dict, "bufnr", (long)bufnum, NULL) == FAIL - || dict_add_nr_str(dict, "lnum", (long)qfp->qf_lnum, NULL) == FAIL - || dict_add_nr_str(dict, "col", (long)qfp->qf_col, NULL) == FAIL - || dict_add_nr_str(dict, "vcol", (long)qfp->qf_viscol, NULL) == FAIL - || dict_add_nr_str(dict, "nr", (long)qfp->qf_nr, NULL) == FAIL - || dict_add_nr_str(dict, "pattern", 0L, - qfp->qf_pattern == NULL ? (char_u *)"" : qfp->qf_pattern) == FAIL - || dict_add_nr_str(dict, "text", 0L, - qfp->qf_text == NULL ? (char_u *)"" : qfp->qf_text) == FAIL - || dict_add_nr_str(dict, "type", 0L, buf) == FAIL - || dict_add_nr_str(dict, "valid", (long)qfp->qf_valid, NULL) == FAIL) - return FAIL; + if (tv_dict_add_nr(dict, S_LEN("bufnr"), (varnumber_T)bufnum) == FAIL + || (tv_dict_add_nr(dict, S_LEN("lnum"), (varnumber_T)qfp->qf_lnum) + == FAIL) + || (tv_dict_add_nr(dict, S_LEN("col"), (varnumber_T)qfp->qf_col) + == FAIL) + || (tv_dict_add_nr(dict, S_LEN("vcol"), (varnumber_T)qfp->qf_viscol) + == FAIL) + || (tv_dict_add_nr(dict, S_LEN("nr"), (varnumber_T)qfp->qf_nr) == FAIL) + || tv_dict_add_str(dict, S_LEN("pattern"), + (qfp->qf_pattern == NULL + ? "" + : (const char *)qfp->qf_pattern)) == FAIL + || tv_dict_add_str(dict, S_LEN("text"), + (qfp->qf_text == NULL + ? "" + : (const char *)qfp->qf_text)) == FAIL + || tv_dict_add_str(dict, S_LEN("type"), (const char *)buf) == FAIL + || (tv_dict_add_nr(dict, S_LEN("valid"), (varnumber_T)qfp->qf_valid) + == FAIL)) { + // tv_dict_add* fail only if key already exist, but this is a newly + // allocated dictionary which is thus guaranteed to have no existing keys. + assert(false); + } qfp = qfp->qf_next; if (qfp == NULL) { @@ -3831,22 +4004,94 @@ int get_errorlist(win_T *wp, list_T *list) return OK; } -// Populate the quickfix list with the items supplied in the list -// of dictionaries. "title" will be copied to w:quickfix_title -// "action" is 'a' for add, 'r' for replace. Otherwise create a new list. -int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) +/// Flags used by getqflist()/getloclist() to determine which fields to return. +enum { + QF_GETLIST_NONE = 0x0, + QF_GETLIST_TITLE = 0x1, + QF_GETLIST_ITEMS = 0x2, + QF_GETLIST_NR = 0x4, + QF_GETLIST_WINID = 0x8, + QF_GETLIST_ALL = 0xFF +}; + +/// Return quickfix/location list details (title) as a +/// dictionary. 'what' contains the details to return. If 'list_idx' is -1, +/// then current list is used. Otherwise the specified list is used. +int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) +{ + qf_info_T *qi = &ql_info; + + if (wp != NULL) { + qi = GET_LOC_LIST(wp); + if (qi == NULL) { + return FAIL; + } + } + + int status = OK; + dictitem_T *di; + int flags = QF_GETLIST_NONE; + + int qf_idx = qi->qf_curlist; // default is the current list + if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) { + // Use the specified quickfix/location list + if (di->di_tv.v_type == VAR_NUMBER) { + // for zero use the current list + if (di->di_tv.vval.v_number != 0) { + qf_idx = (int)di->di_tv.vval.v_number - 1; + if (qf_idx < 0 || qf_idx >= qi->qf_listcount) { + return FAIL; + } + } + flags |= QF_GETLIST_NR; + } else { + return FAIL; + } + } + + if (tv_dict_find(what, S_LEN("all")) != NULL) { + flags |= QF_GETLIST_ALL; + } + + if (tv_dict_find(what, S_LEN("title")) != NULL) { + flags |= QF_GETLIST_TITLE; + } + + if (tv_dict_find(what, S_LEN("winid")) != NULL) { + flags |= QF_GETLIST_WINID; + } + + if (flags & QF_GETLIST_TITLE) { + char_u *t = qi->qf_lists[qf_idx].qf_title; + if (t == NULL) { + t = (char_u *)""; + } + status = tv_dict_add_str(retdict, S_LEN("title"), (const char *)t); + } + if ((status == OK) && (flags & QF_GETLIST_NR)) { + status = tv_dict_add_nr(retdict, S_LEN("nr"), qf_idx + 1); + } + if ((status == OK) && (flags & QF_GETLIST_WINID)) { + win_T *win = qf_find_win(qi); + if (win != NULL) { + status = tv_dict_add_nr(retdict, S_LEN("winid"), win->handle); + } + } + + return status; +} + +/// Add list of entries to quickfix/location list. Each list entry is +/// a dictionary with item information. +static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title, + int action) { listitem_T *li; dict_T *d; qfline_T *old_last = NULL; int retval = OK; - qf_info_T *qi = &ql_info; bool did_bufnr_emsg = false; - if (wp != NULL) { - qi = ll_get_or_alloc_list(wp); - } - if (action == ' ' || qi->qf_curlist == qi->qf_listcount) { // make place for a new list qf_new_list(qi, title); @@ -3866,17 +4111,18 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) if (d == NULL) continue; - char_u *filename = get_dict_string(d, "filename", true); - int bufnum = (int)get_dict_number(d, "bufnr"); - long lnum = get_dict_number(d, "lnum"); - int col = (int)get_dict_number(d, "col"); - char_u vcol = (char_u)get_dict_number(d, "vcol"); - int nr = (int)get_dict_number(d, "nr"); - char_u *type = get_dict_string(d, "type", true); - char_u *pattern = get_dict_string(d, "pattern", true); - char_u *text = get_dict_string(d, "text", true); + char *const filename = tv_dict_get_string(d, "filename", true); + int bufnum = (int)tv_dict_get_number(d, "bufnr"); + long lnum = (long)tv_dict_get_number(d, "lnum"); + int col = (int)tv_dict_get_number(d, "col"); + char_u vcol = (char_u)tv_dict_get_number(d, "vcol"); + int nr = (int)tv_dict_get_number(d, "nr"); + const char *type_str = tv_dict_get_string(d, "type", false); + const char_u type = (char_u)(uint8_t)(type_str == NULL ? NUL : *type_str); + char *const pattern = tv_dict_get_string(d, "pattern", true); + char *text = tv_dict_get_string(d, "text", true); if (text == NULL) { - text = vim_strsave((char_u *)""); + text = xcalloc(1, 1); } bool valid = true; if ((filename == NULL && bufnum == 0) || (lnum == 0 && pattern == NULL)) { @@ -3896,21 +4142,20 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) int status = qf_add_entry(qi, NULL, // dir - filename, + (char_u *)filename, bufnum, - text, + (char_u *)text, lnum, col, vcol, // vis_col - pattern, // search pattern + (char_u *)pattern, // search pattern nr, - (char_u)(type == NULL ? NUL : *type), + type, valid); xfree(filename); xfree(pattern); xfree(text); - xfree(type); if (status == FAIL) { retval = FAIL; @@ -3937,6 +4182,71 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) return retval; } +static int qf_set_properties(qf_info_T *qi, dict_T *what, int action) +{ + dictitem_T *di; + int retval = FAIL; + int newlist = false; + + if (action == ' ' || qi->qf_curlist == qi->qf_listcount) { + newlist = true; + } + int qf_idx = qi->qf_curlist; // default is the current list + if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) { + // Use the specified quickfix/location list + if (di->di_tv.v_type == VAR_NUMBER) { + qf_idx = (int)di->di_tv.vval.v_number - 1; + if (qf_idx < 0 || qf_idx >= qi->qf_listcount) { + return FAIL; + } + } else { + return FAIL; + } + newlist = false; // use the specified list + } + + if (newlist) { + qf_new_list(qi, NULL); + qf_idx = qi->qf_curlist; + } + + if ((di = tv_dict_find(what, S_LEN("title"))) != NULL) { + if (di->di_tv.v_type == VAR_STRING) { + xfree(qi->qf_lists[qf_idx].qf_title); + qi->qf_lists[qf_idx].qf_title = (char_u *)tv_dict_get_string( + what, "title", true); + if (qf_idx == qi->qf_curlist) { + qf_update_win_titlevar(qi); + } + retval = OK; + } + } + + return retval; +} + +// Populate the quickfix list with the items supplied in the list +// of dictionaries. "title" will be copied to w:quickfix_title +// "action" is 'a' for add, 'r' for replace. Otherwise create a new list. +int set_errorlist(win_T *wp, list_T *list, int action, char_u *title, + dict_T *what) +{ + qf_info_T *qi = &ql_info; + int retval = OK; + + if (wp != NULL) { + qi = ll_get_or_alloc_list(wp); + } + + if (what != NULL) { + retval = qf_set_properties(qi, what, action); + } else { + retval = qf_add_entries(qi, list, title, action); + } + + return retval; +} + /* * ":[range]cbuffer [bufnr]" command. * ":[range]caddbuffer [bufnr]" command. @@ -3947,14 +4257,45 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) */ void ex_cbuffer(exarg_T *eap) { - buf_T *buf = NULL; - qf_info_T *qi = &ql_info; + buf_T *buf = NULL; + qf_info_T *qi = &ql_info; + const char *au_name = NULL; if (eap->cmdidx == CMD_lbuffer || eap->cmdidx == CMD_lgetbuffer || eap->cmdidx == CMD_laddbuffer) { qi = ll_get_or_alloc_list(curwin); } + switch (eap->cmdidx) { + case CMD_cbuffer: + au_name = "cbuffer"; + break; + case CMD_cgetbuffer: + au_name = "cgetbuffer"; + break; + case CMD_caddbuffer: + au_name = "caddbuffer"; + break; + case CMD_lbuffer: + au_name = "lbuffer"; + break; + case CMD_lgetbuffer: + au_name = "lgetbuffer"; + break; + case CMD_laddbuffer: + au_name = "laddbuffer"; + break; + default: + break; + } + + if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, (char_u *)au_name, + curbuf->b_fname, true, curbuf)) { + if (aborting()) { + return; + } + } + if (*eap->arg == NUL) buf = curbuf; else if (*skipwhite(skipdigits(eap->arg)) == NUL) @@ -3981,13 +4322,17 @@ void ex_cbuffer(exarg_T *eap) } if (qf_init_ext(qi, NULL, buf, NULL, p_efm, - (eap->cmdidx != CMD_caddbuffer - && eap->cmdidx != CMD_laddbuffer), - eap->line1, eap->line2, - qf_title) > 0 - && (eap->cmdidx == CMD_cbuffer - || eap->cmdidx == CMD_lbuffer)) - qf_jump(qi, 0, 0, eap->forceit); /* display first error */ + (eap->cmdidx != CMD_caddbuffer + && eap->cmdidx != CMD_laddbuffer), + eap->line1, eap->line2, qf_title) > 0) { + if (au_name != NULL) { + apply_autocmds(EVENT_QUICKFIXCMDPOST, (char_u *)au_name, + curbuf->b_fname, true, curbuf); + } + if (eap->cmdidx == CMD_cbuffer || eap->cmdidx == CMD_lbuffer) { + qf_jump(qi, 0, 0, eap->forceit); // display first error + } + } } } } @@ -3998,30 +4343,65 @@ void ex_cbuffer(exarg_T *eap) */ void ex_cexpr(exarg_T *eap) { - typval_T *tv; - qf_info_T *qi = &ql_info; + qf_info_T *qi = &ql_info; + const char *au_name = NULL; if (eap->cmdidx == CMD_lexpr || eap->cmdidx == CMD_lgetexpr || eap->cmdidx == CMD_laddexpr) { qi = ll_get_or_alloc_list(curwin); } + switch (eap->cmdidx) { + case CMD_cexpr: + au_name = "cexpr"; + break; + case CMD_cgetexpr: + au_name = "cgetexpr"; + break; + case CMD_caddexpr: + au_name = "caddexpr"; + break; + case CMD_lexpr: + au_name = "lexpr"; + break; + case CMD_lgetexpr: + au_name = "lgetexpr"; + break; + case CMD_laddexpr: + au_name = "laddexpr"; + break; + default: + break; + } + if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, (char_u *)au_name, + curbuf->b_fname, true, curbuf)) { + if (aborting()) { + return; + } + } + /* Evaluate the expression. When the result is a string or a list we can * use it to fill the errorlist. */ - tv = eval_expr(eap->arg, NULL); - if (tv != NULL) { - if ((tv->v_type == VAR_STRING && tv->vval.v_string != NULL) - || (tv->v_type == VAR_LIST && tv->vval.v_list != NULL)) { - if (qf_init_ext(qi, NULL, NULL, tv, p_efm, - (eap->cmdidx != CMD_caddexpr - && eap->cmdidx != CMD_laddexpr), - (linenr_T)0, (linenr_T)0, *eap->cmdlinep) > 0 - && (eap->cmdidx == CMD_cexpr - || eap->cmdidx == CMD_lexpr)) - qf_jump(qi, 0, 0, eap->forceit); /* display first error */ - } else + typval_T tv; + if (eval0(eap->arg, &tv, NULL, true) != FAIL) { + if ((tv.v_type == VAR_STRING && tv.vval.v_string != NULL) + || (tv.v_type == VAR_LIST && tv.vval.v_list != NULL)) { + if (qf_init_ext(qi, NULL, NULL, &tv, p_efm, + (eap->cmdidx != CMD_caddexpr + && eap->cmdidx != CMD_laddexpr), + (linenr_T)0, (linenr_T)0, *eap->cmdlinep) > 0) { + if (au_name != NULL) { + apply_autocmds(EVENT_QUICKFIXCMDPOST, (char_u *)au_name, + curbuf->b_fname, true, curbuf); + } + if (eap->cmdidx == CMD_cexpr || eap->cmdidx == CMD_lexpr) { + qf_jump(qi, 0, 0, eap->forceit); // display first error + } + } + } else { EMSG(_("E777: String or List expected")); - free_tv(tv); + } + tv_clear(&tv); } } @@ -4051,11 +4431,11 @@ void ex_helpgrep(exarg_T *eap) case CMD_lhelpgrep: au_name = (char_u *)"lhelpgrep"; break; default: break; } - if (au_name != NULL) { - apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, - curbuf->b_fname, TRUE, curbuf); - if (did_throw || force_abort) + if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, + curbuf->b_fname, true, curbuf)) { + if (aborting()) { return; + } } /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ diff --git a/src/nvim/quickfix.h b/src/nvim/quickfix.h index bb9c2c3193..fdeb8d1a2f 100644 --- a/src/nvim/quickfix.h +++ b/src/nvim/quickfix.h @@ -1,6 +1,9 @@ #ifndef NVIM_QUICKFIX_H #define NVIM_QUICKFIX_H +#include "nvim/types.h" +#include "nvim/ex_cmds_defs.h" + /* flags for skip_vimgrep_pat() */ #define VGR_GLOBAL 1 #define VGR_NOJUMP 2 diff --git a/src/nvim/rbuffer.c b/src/nvim/rbuffer.c index 111af0d0fb..18d453cbe9 100644 --- a/src/nvim/rbuffer.c +++ b/src/nvim/rbuffer.c @@ -1,3 +1,6 @@ +// 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 <stddef.h> #include <string.h> diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 6613d284d7..847b2f273e 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -1,3 +1,6 @@ +// 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 + /* * Handling of regular expressions: vim_regcomp(), vim_regexec(), vim_regsub() * @@ -2221,10 +2224,11 @@ collection: if (*regparse == '[') endc = get_coll_element(®parse); if (endc == 0) { - if (has_mbyte) - endc = mb_ptr2char_adv(®parse); - else + if (has_mbyte) { + endc = mb_ptr2char_adv((const char_u **)®parse); + } else { endc = *regparse++; + } } /* Handle \o40, \x20 and \u20AC style sequences */ @@ -2349,7 +2353,7 @@ collection: break; case CLASS_LOWER: for (cu = 1; cu <= 255; cu++) { - if (vim_islower(cu) && cu != 170 && cu != 186) { + if (mb_islower(cu) && cu != 170 && cu != 186) { regmbc(cu); } } @@ -2375,7 +2379,7 @@ collection: break; case CLASS_UPPER: for (cu = 1; cu <= 255; cu++) { - if (vim_isupper(cu)) { + if (mb_isupper(cu)) { regmbc(cu); } } @@ -2397,7 +2401,7 @@ collection: regc('\b'); break; case CLASS_ESCAPE: - regc('\033'); + regc(ESC); break; } } else { @@ -2922,13 +2926,8 @@ static void skipchr(void) else prevchr_len = 0; if (regparse[prevchr_len] != NUL) { - if (enc_utf8) - /* exclude composing chars that mb_ptr2len does include */ - prevchr_len += utf_ptr2len(regparse + prevchr_len); - else if (has_mbyte) - prevchr_len += (*mb_ptr2len)(regparse + prevchr_len); - else - ++prevchr_len; + // Exclude composing chars that utfc_ptr2len does include. + prevchr_len += utf_ptr2len(regparse + prevchr_len); } regparse += prevchr_len; prev_at_start = at_start; @@ -3051,7 +3050,7 @@ static int getoctchrs(void) int c; int i; - for (i = 0; i < 3 && nr < 040; ++i) { + for (i = 0; i < 3 && nr < 040; i++) { // -V536 c = regparse[0]; if (c < '0' || c > '7') break; @@ -3173,61 +3172,56 @@ static int need_clear_zsubexpr = FALSE; /* extmatch subexpressions int regnarrate = 0; #endif -/* - * Internal copy of 'ignorecase'. It is set at each call to vim_regexec(). - * Normally it gets the value of "rm_ic" or "rmm_ic", but when the pattern - * contains '\c' or '\C' the value is overruled. - */ -static int ireg_ic; - -/* - * Similar to ireg_ic, but only for 'combining' characters. Set with \Z flag - * in the regexp. Defaults to false, always. - */ -static int ireg_icombine; - -/* - * Copy of "rmm_maxcol": maximum column to search for a match. Zero when - * there is no maximum. - */ -static colnr_T ireg_maxcol; - -/* - * 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. - */ +// 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 unsigned reg_tofreelen; -/* - * These variables are set when executing a regexp to speed up the execution. - * Which ones are set depends on whether a single-line or multi-line match is - * done: - * single-line multi-line - * reg_match ®match_T NULL - * reg_mmatch NULL ®mmatch_T - * reg_startp reg_match->startp <invalid> - * reg_endp reg_match->endp <invalid> - * reg_startpos <invalid> reg_mmatch->startpos - * reg_endpos <invalid> reg_mmatch->endpos - * reg_win NULL window in which to search - * reg_buf curbuf buffer in which to search - * reg_firstlnum <invalid> first line in which to search - * reg_maxline 0 last line nr - * reg_line_lbr FALSE or TRUE FALSE - */ -static regmatch_T *reg_match; -static regmmatch_T *reg_mmatch; -static char_u **reg_startp = NULL; -static char_u **reg_endp = NULL; -static lpos_T *reg_startpos = NULL; -static lpos_T *reg_endpos = NULL; -static win_T *reg_win; -static buf_T *reg_buf; -static linenr_T reg_firstlnum; -static linenr_T reg_maxline; -static int reg_line_lbr; /* "\n" in string is line break */ +// Structure used to store the execution state of the regex engine. +// Which ones are set depends on whether a single-line or multi-line match is +// done: +// single-line multi-line +// reg_match ®match_T NULL +// reg_mmatch NULL ®mmatch_T +// reg_startp reg_match->startp <invalid> +// reg_endp reg_match->endp <invalid> +// reg_startpos <invalid> reg_mmatch->startpos +// reg_endpos <invalid> reg_mmatch->endpos +// reg_win NULL window in which to search +// reg_buf curbuf buffer in which to search +// reg_firstlnum <invalid> first line in which to search +// reg_maxline 0 last line nr +// reg_line_lbr false or true false +typedef struct { + regmatch_T *reg_match; + regmmatch_T *reg_mmatch; + char_u **reg_startp; + char_u **reg_endp; + lpos_T *reg_startpos; + lpos_T *reg_endpos; + win_T *reg_win; + buf_T *reg_buf; + linenr_T reg_firstlnum; + linenr_T reg_maxline; + bool reg_line_lbr; // "\n" in string is line break + + // Internal copy of 'ignorecase'. It is set at each call to vim_regexec(). + // Normally it gets the value of "rm_ic" or "rmm_ic", but when the pattern + // contains '\c' or '\C' the value is overruled. + bool reg_ic; + + // Similar to rex.reg_ic, but only for 'combining' characters. Set with \Z + // flag in the regexp. Defaults to false, always. + bool reg_icombine; + + // Copy of "rmm_maxcol": maximum column to search for a match. Zero when + // there is no maximum. + colnr_T reg_maxcol; +} regexec_T; + +static regexec_T rex; +static bool rex_in_use = false; /* * "regstack" and "backpos" are used by regmatch(). They are kept over calls @@ -3269,14 +3263,16 @@ void free_regexp_stuff(void) */ static char_u *reg_getline(linenr_T lnum) { - /* when looking behind for a match/no-match lnum is negative. But we - * can't go before line 1 */ - if (reg_firstlnum + lnum < 1) + // when looking behind for a match/no-match lnum is negative. But we + // can't go before line 1 + if (rex.reg_firstlnum + lnum < 1) { return NULL; - if (lnum > reg_maxline) - /* Must have matched the "\n" in the last line. */ + } + if (lnum > rex.reg_maxline) { + // Must have matched the "\n" in the last line. return (char_u *)""; - return ml_get_buf(reg_buf, reg_firstlnum + lnum, FALSE); + } + return ml_get_buf(rex.reg_buf, rex.reg_firstlnum + lnum, false); } static regsave_T behind_pos; @@ -3286,9 +3282,8 @@ static char_u *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 */ -/* TRUE if using multi-line regexp. */ -#define REG_MULTI (reg_match == NULL) - +// TRUE if using multi-line regexp. +#define REG_MULTI (rex.reg_match == NULL) /* * Match a regexp against a string. @@ -3306,15 +3301,15 @@ bt_regexec_nl ( bool line_lbr ) { - reg_match = rmp; - reg_mmatch = NULL; - reg_maxline = 0; - reg_line_lbr = line_lbr; - reg_buf = curbuf; - reg_win = NULL; - ireg_ic = rmp->rm_ic; - ireg_icombine = FALSE; - ireg_maxcol = 0; + rex.reg_match = rmp; + rex.reg_mmatch = NULL; + rex.reg_maxline = 0; + rex.reg_line_lbr = line_lbr; + rex.reg_buf = curbuf; + rex.reg_win = NULL; + rex.reg_ic = rmp->rm_ic; + rex.reg_icombine = false; + rex.reg_maxcol = 0; long r = bt_regexec_both(line, col, NULL); assert(r <= INT_MAX); @@ -3337,16 +3332,16 @@ bt_regexec_nl ( static long bt_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm) { - reg_match = NULL; - reg_mmatch = rmp; - reg_buf = buf; - reg_win = win; - reg_firstlnum = lnum; - reg_maxline = reg_buf->b_ml.ml_line_count - lnum; - reg_line_lbr = FALSE; - ireg_ic = rmp->rmm_ic; - ireg_icombine = FALSE; - ireg_maxcol = rmp->rmm_maxcol; + rex.reg_match = NULL; + rex.reg_mmatch = rmp; + rex.reg_buf = buf; + rex.reg_win = win; + rex.reg_firstlnum = lnum; + rex.reg_maxline = rex.reg_buf->b_ml.ml_line_count - lnum; + rex.reg_line_lbr = false; + rex.reg_ic = rmp->rmm_ic; + rex.reg_icombine = false; + rex.reg_maxcol = rmp->rmm_maxcol; return bt_regexec_both(NULL, col, tm); } @@ -3384,14 +3379,14 @@ static long bt_regexec_both(char_u *line, } if (REG_MULTI) { - prog = (bt_regprog_T *)reg_mmatch->regprog; + prog = (bt_regprog_T *)rex.reg_mmatch->regprog; line = reg_getline((linenr_T)0); - reg_startpos = reg_mmatch->startpos; - reg_endpos = reg_mmatch->endpos; + rex.reg_startpos = rex.reg_mmatch->startpos; + rex.reg_endpos = rex.reg_mmatch->endpos; } else { - prog = (bt_regprog_T *)reg_match->regprog; - reg_startp = reg_match->startp; - reg_endp = reg_match->endp; + prog = (bt_regprog_T *)rex.reg_match->regprog; + rex.reg_startp = rex.reg_match->startp; + rex.reg_endp = rex.reg_match->endp; } /* Be paranoid... */ @@ -3404,19 +3399,22 @@ static long bt_regexec_both(char_u *line, if (prog_magic_wrong()) goto theend; - /* If the start column is past the maximum column: no need to try. */ - if (ireg_maxcol > 0 && col >= ireg_maxcol) + // If the start column is past the maximum column: no need to try. + if (rex.reg_maxcol > 0 && col >= rex.reg_maxcol) { goto theend; + } - /* If pattern contains "\c" or "\C": overrule value of ireg_ic */ - if (prog->regflags & RF_ICASE) - ireg_ic = TRUE; - else if (prog->regflags & RF_NOICASE) - ireg_ic = FALSE; + // If pattern contains "\c" or "\C": overrule value of rex.reg_ic + if (prog->regflags & RF_ICASE) { + rex.reg_ic = true; + } else if (prog->regflags & RF_NOICASE) { + rex.reg_ic = false; + } - /* If pattern contains "\Z" overrule value of ireg_icombine */ - if (prog->regflags & RF_ICOMBINE) - ireg_icombine = TRUE; + // If pattern contains "\Z" overrule value of rex.reg_icombine + if (prog->regflags & RF_ICOMBINE) { + rex.reg_icombine = true; + } /* If there is a "must appear" string, look for it. */ if (prog->regmust != NULL) { @@ -3428,32 +3426,26 @@ static long bt_regexec_both(char_u *line, c = *prog->regmust; s = line + col; - /* - * This is used very often, esp. for ":global". Use three versions of - * the loop to avoid overhead of conditions. - */ - if (!ireg_ic - && !has_mbyte - ) - while ((s = vim_strbyte(s, c)) != NULL) { - if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0) - break; /* Found it. */ - ++s; - } - else if (!ireg_ic || (!enc_utf8 && mb_char2len(c) > 1)) + // 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 = vim_strchr(s, c)) != NULL) { - if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0) - break; /* Found it. */ + if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0) { + break; // Found it. + } mb_ptr_adv(s); } - else + } else { while ((s = cstrchr(s, c)) != NULL) { - if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0) - break; /* Found it. */ + if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0) { + break; // Found it. + } mb_ptr_adv(s); } - if (s == NULL) /* Not present. */ + } + if (s == NULL) { // Not present. goto theend; + } } regline = line; @@ -3470,10 +3462,10 @@ static long bt_regexec_both(char_u *line, c = regline[col]; if (prog->regstart == NUL || prog->regstart == c - || (ireg_ic + || (rex.reg_ic && (((enc_utf8 && utf_fold(prog->regstart) == utf_fold(c))) || (c < 255 && prog->regstart < 255 - && vim_tolower(prog->regstart) == vim_tolower(c))))) { + && mb_tolower(prog->regstart) == mb_tolower(c))))) { retval = regtry(prog, col); } else { retval = 0; @@ -3483,14 +3475,8 @@ static long bt_regexec_both(char_u *line, /* Messy cases: unanchored match. */ while (!got_int) { if (prog->regstart != NUL) { - /* Skip until the char we know it must start with. - * Used often, do some work to avoid call overhead. */ - if (!ireg_ic - && !has_mbyte - ) - s = vim_strbyte(regline + col, prog->regstart); - else - s = cstrchr(regline + col, prog->regstart); + // Skip until the char we know it must start with. + s = cstrchr(regline + col, prog->regstart); if (s == NULL) { retval = 0; break; @@ -3498,8 +3484,8 @@ static long bt_regexec_both(char_u *line, col = (int)(s - regline); } - /* Check for maximum column to try. */ - if (ireg_maxcol > 0 && col >= ireg_maxcol) { + // Check for maximum column to try. + if (rex.reg_maxcol > 0 && col >= rex.reg_maxcol) { retval = 0; break; } @@ -3596,21 +3582,24 @@ static long regtry(bt_regprog_T *prog, colnr_T col) cleanup_subexpr(); if (REG_MULTI) { - if (reg_startpos[0].lnum < 0) { - reg_startpos[0].lnum = 0; - reg_startpos[0].col = col; + if (rex.reg_startpos[0].lnum < 0) { + rex.reg_startpos[0].lnum = 0; + rex.reg_startpos[0].col = col; + } + if (rex.reg_endpos[0].lnum < 0) { + rex.reg_endpos[0].lnum = reglnum; + rex.reg_endpos[0].col = (int)(reginput - regline); + } else { + // Use line number of "\ze". + reglnum = rex.reg_endpos[0].lnum; } - if (reg_endpos[0].lnum < 0) { - reg_endpos[0].lnum = reglnum; - reg_endpos[0].col = (int)(reginput - regline); - } else - /* Use line number of "\ze". */ - reglnum = reg_endpos[0].lnum; } else { - if (reg_startp[0] == NULL) - reg_startp[0] = regline + col; - if (reg_endp[0] == NULL) - reg_endp[0] = reginput; + if (rex.reg_startp[0] == NULL) { + rex.reg_startp[0] = regline + col; + } + if (rex.reg_endp[0] == NULL) { + rex.reg_endp[0] = reginput; + } } /* Package any found \z(...\) matches for export. Default is none. */ unref_extmatch(re_extmatch_out); @@ -3645,34 +3634,33 @@ static long regtry(bt_regprog_T *prog, colnr_T col) } -/* - * Get class of previous character. - */ +// Get class of previous character. static int reg_prev_class(void) { - if (reginput > regline) - return mb_get_class_buf(reginput - 1 - - (*mb_head_off)(regline, reginput - 1), reg_buf); + if (reginput > regline) { + return mb_get_class_tab(reginput - 1 - (*mb_head_off)(regline, + reginput - 1), + rex.reg_buf->b_chartab); + } return -1; } -/* - * Return TRUE if the current reginput position matches the Visual area. - */ +// Return TRUE if the current reginput position matches the Visual area. static int reg_match_visual(void) { pos_T top, bot; linenr_T lnum; colnr_T col; - win_T *wp = reg_win == NULL ? curwin : reg_win; + win_T *wp = rex.reg_win == NULL ? curwin : rex.reg_win; int mode; colnr_T start, end; colnr_T start2, end2; - /* Check if the buffer is the current buffer. */ - if (reg_buf != curbuf || VIsual.lnum == 0) - return FALSE; + // Check if the buffer is the current buffer. + if (rex.reg_buf != curbuf || VIsual.lnum == 0) { + return false; + } if (VIsual_active) { if (lt(VIsual, wp->w_cursor)) { @@ -3693,9 +3681,10 @@ static int reg_match_visual(void) } mode = curbuf->b_visual.vi_mode; } - lnum = reglnum + reg_firstlnum; - if (lnum < top.lnum || lnum > bot.lnum) - return FALSE; + lnum = reglnum + rex.reg_firstlnum; + if (lnum < top.lnum || lnum > bot.lnum) { + return false; + } if (mode == 'v') { col = (colnr_T)(reginput - regline); @@ -3814,11 +3803,11 @@ regmatch ( next = regnext(scan); op = OP(scan); - /* Check for character class with NL added. */ - if (!reg_line_lbr && WITH_NL(op) && REG_MULTI - && *reginput == NUL && reglnum <= reg_maxline) { + // Check for character class with NL added. + if (!rex.reg_line_lbr && WITH_NL(op) && REG_MULTI + && *reginput == NUL && reglnum <= rex.reg_maxline) { reg_nextline(); - } else if (reg_line_lbr && WITH_NL(op) && *reginput == '\n') { + } else if (rex.reg_line_lbr && WITH_NL(op) && *reginput == '\n') { ADVANCE_REGINPUT(); } else { if (WITH_NL(op)) @@ -3839,26 +3828,29 @@ regmatch ( break; case RE_BOF: - /* We're not at the beginning of the file when below the first - * line where we started, not at the start of the line or we - * didn't start at the first line of the buffer. */ + // We're not at the beginning of the file when below the first + // line where we started, not at the start of the line or we + // didn't start at the first line of the buffer. if (reglnum != 0 || reginput != regline - || (REG_MULTI && reg_firstlnum > 1)) + || (REG_MULTI && rex.reg_firstlnum > 1)) { status = RA_NOMATCH; + } break; case RE_EOF: - if (reglnum != reg_maxline || c != NUL) + if (reglnum != rex.reg_maxline || c != NUL) { status = RA_NOMATCH; + } break; case CURSOR: - /* Check if the buffer is in a window and compare the - * reg_win->w_cursor position to the match position. */ - if (reg_win == NULL - || (reglnum + reg_firstlnum != reg_win->w_cursor.lnum) - || ((colnr_T)(reginput - regline) != reg_win->w_cursor.col)) + // Check if the buffer is in a window and compare the + // rex.reg_win->w_cursor position to the match position. + if (rex.reg_win == NULL + || (reglnum + rex.reg_firstlnum != rex.reg_win->w_cursor.lnum) + || ((colnr_T)(reginput - regline) != rex.reg_win->w_cursor.col)) { status = RA_NOMATCH; + } break; case RE_MARK: @@ -3868,19 +3860,20 @@ regmatch ( int cmp = OPERAND(scan)[1]; pos_T *pos; - pos = getmark_buf(reg_buf, mark, FALSE); - if (pos == NULL /* mark doesn't exist */ - || pos->lnum <= 0 /* mark isn't set in reg_buf */ - || (pos->lnum == reglnum + reg_firstlnum + pos = getmark_buf(rex.reg_buf, mark, false); + if (pos == NULL // mark doesn't exist + || pos->lnum <= 0 // mark isn't set in reg_buf + || (pos->lnum == reglnum + rex.reg_firstlnum ? (pos->col == (colnr_T)(reginput - regline) ? (cmp == '<' || cmp == '>') : (pos->col < (colnr_T)(reginput - regline) ? cmp != '>' : cmp != '<')) - : (pos->lnum < reglnum + reg_firstlnum + : (pos->lnum < reglnum + rex.reg_firstlnum ? cmp != '>' - : cmp != '<'))) + : cmp != '<'))) { status = RA_NOMATCH; + } } break; @@ -3890,11 +3883,12 @@ regmatch ( break; case RE_LNUM: - assert(reglnum + reg_firstlnum >= 0 - && (uintmax_t)(reglnum + reg_firstlnum) <= UINT32_MAX); - if (!REG_MULTI || !re_num_cmp((uint32_t)(reglnum + reg_firstlnum), - scan)) + assert(reglnum + rex.reg_firstlnum >= 0 + && (uintmax_t)(reglnum + rex.reg_firstlnum) <= UINT32_MAX); + if (!REG_MULTI + || !re_num_cmp((uint32_t)(reglnum + rex.reg_firstlnum), scan)) { status = RA_NOMATCH; + } break; case RE_COL: @@ -3905,11 +3899,13 @@ regmatch ( break; case RE_VCOL: - if (!re_num_cmp(win_linetabsize(reg_win == NULL ? curwin : reg_win, + if (!re_num_cmp(win_linetabsize(rex.reg_win == NULL + ? curwin : rex.reg_win, regline, (colnr_T)(reginput - regline)) + 1, - scan)) + scan)) { status = RA_NOMATCH; + } break; case BOW: /* \<word; reginput points to w */ @@ -3918,17 +3914,19 @@ regmatch ( else if (has_mbyte) { int this_class; - /* Get class of current and previous char (if it exists). */ - this_class = mb_get_class_buf(reginput, reg_buf); - if (this_class <= 1) - status = RA_NOMATCH; /* not on a word at all */ - else if (reg_prev_class() == this_class) - status = RA_NOMATCH; /* previous char is in same word */ + // Get class of current and previous char (if it exists). + this_class = mb_get_class_tab(reginput, rex.reg_buf->b_chartab); + if (this_class <= 1) { + status = RA_NOMATCH; // Not on a word at all. + } else if (reg_prev_class() == this_class) { + status = RA_NOMATCH; // Previous char is in same word. + } } else { - if (!vim_iswordc_buf(c, reg_buf) || (reginput > regline - && vim_iswordc_buf(reginput[-1 - ], reg_buf))) + if (!vim_iswordc_buf(c, rex.reg_buf) + || (reginput > regline + && vim_iswordc_buf(reginput[-1], rex.reg_buf))) { status = RA_NOMATCH; + } } break; @@ -3938,16 +3936,17 @@ regmatch ( else if (has_mbyte) { int this_class, prev_class; - /* Get class of current and previous char (if it exists). */ - this_class = mb_get_class_buf(reginput, reg_buf); + // Get class of current and previous char (if it exists). + this_class = mb_get_class_tab(reginput, rex.reg_buf->b_chartab); prev_class = reg_prev_class(); if (this_class == prev_class || prev_class == 0 || prev_class == 1) status = RA_NOMATCH; } else { - if (!vim_iswordc_buf(reginput[-1], reg_buf) - || (reginput[0] != NUL && vim_iswordc_buf(c, reg_buf))) + if (!vim_iswordc_buf(reginput[-1], rex.reg_buf) + || (reginput[0] != NUL && vim_iswordc_buf(c, rex.reg_buf))) { status = RA_NOMATCH; + } } break; /* Matched with EOW */ @@ -3974,17 +3973,20 @@ regmatch ( break; case KWORD: - if (!vim_iswordp_buf(reginput, reg_buf)) + if (!vim_iswordp_buf(reginput, rex.reg_buf)) { status = RA_NOMATCH; - else + } else { ADVANCE_REGINPUT(); + } break; case SKWORD: - if (ascii_isdigit(*reginput) || !vim_iswordp_buf(reginput, reg_buf)) + if (ascii_isdigit(*reginput) + || !vim_iswordp_buf(reginput, rex.reg_buf)) { status = RA_NOMATCH; - else + } else { ADVANCE_REGINPUT(); + } break; case FNAME: @@ -4149,16 +4151,16 @@ regmatch ( opnd = OPERAND(scan); // Inline the first byte, for speed. if (*opnd != *reginput - && (!ireg_ic + && (!rex.reg_ic || (!enc_utf8 - && vim_tolower(*opnd) != vim_tolower(*reginput)))) { + && mb_tolower(*opnd) != mb_tolower(*reginput)))) { status = RA_NOMATCH; } else if (*opnd == NUL) { // match empty string always works; happens when "~" is // empty. } else { - if (opnd[1] == NUL && !(enc_utf8 && ireg_ic)) { - len = 1; /* matched a single byte above */ + if (opnd[1] == NUL && !(enc_utf8 && rex.reg_ic)) { + len = 1; // matched a single byte above } else { // Need to match first byte again for multi-byte. len = (int)STRLEN(opnd); @@ -4170,7 +4172,7 @@ regmatch ( // follows (skips over all composing chars). if (status != RA_NOMATCH && enc_utf8 && UTF_COMPOSINGLIKE(reginput, reginput + len) - && !ireg_icombine + && !rex.reg_icombine && OP(next) != RE_COMPOSING) { // raaron: This code makes a composing character get // ignored, which is the correct behavior (sometimes) @@ -4294,9 +4296,9 @@ regmatch ( status = RA_FAIL; else { rp->rs_no = no; - save_se(&rp->rs_un.sesave, ®_startpos[no], - ®_startp[no]); - /* We simply continue and handle the result when done. */ + save_se(&rp->rs_un.sesave, &rex.reg_startpos[no], + &rex.reg_startp[no]); + // We simply continue and handle the result when done. } } break; @@ -4346,12 +4348,12 @@ regmatch ( no = op - MCLOSE; cleanup_subexpr(); rp = regstack_push(RS_MCLOSE, scan); - if (rp == NULL) + if (rp == NULL) { status = RA_FAIL; - else { + } else { rp->rs_no = no; - save_se(&rp->rs_un.sesave, ®_endpos[no], ®_endp[no]); - /* We simply continue and handle the result when done. */ + save_se(&rp->rs_un.sesave, &rex.reg_endpos[no], &rex.reg_endp[no]); + // We simply continue and handle the result when done. } } break; @@ -4394,41 +4396,40 @@ regmatch ( no = op - BACKREF; cleanup_subexpr(); - if (!REG_MULTI) { /* Single-line regexp */ - if (reg_startp[no] == NULL || reg_endp[no] == NULL) { - /* Backref was not set: Match an empty string. */ + if (!REG_MULTI) { // Single-line regexp + if (rex.reg_startp[no] == NULL || rex.reg_endp[no] == NULL) { + // Backref was not set: Match an empty string. len = 0; } else { - /* Compare current input with back-ref in the same - * line. */ - len = (int)(reg_endp[no] - reg_startp[no]); - if (cstrncmp(reg_startp[no], reginput, &len) != 0) + // Compare current input with back-ref in the same line. + len = (int)(rex.reg_endp[no] - rex.reg_startp[no]); + if (cstrncmp(rex.reg_startp[no], reginput, &len) != 0) { status = RA_NOMATCH; + } } - } else { /* Multi-line regexp */ - if (reg_startpos[no].lnum < 0 || reg_endpos[no].lnum < 0) { - /* Backref was not set: Match an empty string. */ + } else { // Multi-line regexp + if (rex.reg_startpos[no].lnum < 0 || rex.reg_endpos[no].lnum < 0) { + // Backref was not set: Match an empty string. len = 0; } else { - if (reg_startpos[no].lnum == reglnum - && reg_endpos[no].lnum == reglnum) { - /* Compare back-ref within the current line. */ - len = reg_endpos[no].col - reg_startpos[no].col; - if (cstrncmp(regline + reg_startpos[no].col, - reginput, &len) != 0) + if (rex.reg_startpos[no].lnum == reglnum + && rex.reg_endpos[no].lnum == reglnum) { + // Compare back-ref within the current line. + len = rex.reg_endpos[no].col - rex.reg_startpos[no].col; + if (cstrncmp(regline + rex.reg_startpos[no].col, + reginput, &len) != 0) { status = RA_NOMATCH; + } } else { - /* Messy situation: Need to compare between two - * lines. */ - int r = match_with_backref( - reg_startpos[no].lnum, - reg_startpos[no].col, - reg_endpos[no].lnum, - reg_endpos[no].col, - &len); - - if (r != RA_MATCH) + // Messy situation: Need to compare between two lines. + int r = match_with_backref(rex.reg_startpos[no].lnum, + rex.reg_startpos[no].col, + rex.reg_endpos[no].lnum, + rex.reg_endpos[no].col, + &len); + if (r != RA_MATCH) { status = r; + } } } } @@ -4568,13 +4569,15 @@ regmatch ( */ if (OP(next) == EXACTLY) { rst.nextb = *OPERAND(next); - if (ireg_ic) { - if (vim_isupper(rst.nextb)) - rst.nextb_ic = vim_tolower(rst.nextb); - else - rst.nextb_ic = vim_toupper(rst.nextb); - } else + if (rex.reg_ic) { + if (mb_isupper(rst.nextb)) { + rst.nextb_ic = mb_tolower(rst.nextb); + } else { + rst.nextb_ic = mb_toupper(rst.nextb); + } + } else { rst.nextb_ic = rst.nextb; + } } else { rst.nextb = NUL; rst.nextb_ic = NUL; @@ -4673,13 +4676,14 @@ regmatch ( break; case NEWL: - if ((c != NUL || !REG_MULTI || reglnum > reg_maxline - || reg_line_lbr) && (c != '\n' || !reg_line_lbr)) + if ((c != NUL || !REG_MULTI || reglnum > rex.reg_maxline + || rex.reg_line_lbr) && (c != '\n' || !rex.reg_line_lbr)) { status = RA_NOMATCH; - else if (reg_line_lbr) + } else if (rex.reg_line_lbr) { ADVANCE_REGINPUT(); - else + } else { reg_nextline(); + } break; case END: @@ -4718,10 +4722,11 @@ regmatch ( break; case RS_MOPEN: - /* Pop the state. Restore pointers when there is no match. */ - if (status == RA_NOMATCH) - restore_se(&rp->rs_un.sesave, ®_startpos[rp->rs_no], - ®_startp[rp->rs_no]); + // Pop the state. Restore pointers when there is no match. + if (status == RA_NOMATCH) { + restore_se(&rp->rs_un.sesave, &rex.reg_startpos[rp->rs_no], + &rex.reg_startp[rp->rs_no]); + } regstack_pop(&scan); break; @@ -4734,10 +4739,11 @@ regmatch ( break; case RS_MCLOSE: - /* Pop the state. Restore pointers when there is no match. */ - if (status == RA_NOMATCH) - restore_se(&rp->rs_un.sesave, ®_endpos[rp->rs_no], - ®_endp[rp->rs_no]); + // Pop the state. Restore pointers when there is no match. + if (status == RA_NOMATCH) { + restore_se(&rp->rs_un.sesave, &rex.reg_endpos[rp->rs_no], + &rex.reg_endp[rp->rs_no]); + } regstack_pop(&scan); break; @@ -5117,10 +5123,11 @@ regrepeat ( ++count; mb_ptr_adv(scan); } - if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline - || reg_line_lbr || count == maxcount) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline + || rex.reg_line_lbr || count == maxcount) { break; - ++count; /* count the line-break */ + } + count++; // count the line-break reg_nextline(); scan = reginput; if (got_int) @@ -5138,17 +5145,19 @@ regrepeat ( if (vim_isIDc(PTR2CHAR(scan)) && (testval || !ascii_isdigit(*scan))) { mb_ptr_adv(scan); } else if (*scan == NUL) { - if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline - || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline + || rex.reg_line_lbr) { break; + } reg_nextline(); scan = reginput; if (got_int) break; - } else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) - ++scan; - else + } else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) { + scan++; + } else { break; + } ++count; } break; @@ -5160,22 +5169,25 @@ regrepeat ( case SKWORD: case SKWORD + ADD_NL: while (count < maxcount) { - if (vim_iswordp_buf(scan, reg_buf) + if (vim_iswordp_buf(scan, rex.reg_buf) && (testval || !ascii_isdigit(*scan))) { mb_ptr_adv(scan); } else if (*scan == NUL) { - if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline - || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline + || rex.reg_line_lbr) { break; + } reg_nextline(); scan = reginput; - if (got_int) + if (got_int) { break; - } else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) - ++scan; - else + } + } else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) { + scan++; + } else { break; - ++count; + } + count++; } break; @@ -5189,18 +5201,21 @@ regrepeat ( if (vim_isfilec(PTR2CHAR(scan)) && (testval || !ascii_isdigit(*scan))) { mb_ptr_adv(scan); } else if (*scan == NUL) { - if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline - || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline + || rex.reg_line_lbr) { break; + } reg_nextline(); scan = reginput; - if (got_int) + if (got_int) { break; - } else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) - ++scan; - else + } + } else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) { + scan++; + } else { break; - ++count; + } + count++; } break; @@ -5212,21 +5227,24 @@ regrepeat ( case SPRINT + ADD_NL: while (count < maxcount) { if (*scan == NUL) { - if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline - || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline + || rex.reg_line_lbr) { break; + } reg_nextline(); scan = reginput; - if (got_int) + if (got_int) { break; + } } else if (vim_isprintc(PTR2CHAR(scan)) == 1 && (testval || !ascii_isdigit(*scan))) { mb_ptr_adv(scan); - } else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) - ++scan; - else + } else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) { + scan++; + } else { break; - ++count; + } + count++; } break; @@ -5237,9 +5255,10 @@ do_class: while (count < maxcount) { int l; if (*scan == NUL) { - if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline - || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline + || rex.reg_line_lbr) { break; + } reg_nextline(); scan = reginput; if (got_int) @@ -5248,12 +5267,13 @@ do_class: if (testval != 0) break; scan += l; - } else if ((class_tab[*scan] & mask) == testval) - ++scan; - else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) - ++scan; - else + } else if ((class_tab[*scan] & mask) == testval) { + scan++; + } else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) { + scan++; + } else { break; + } ++count; } break; @@ -5331,12 +5351,12 @@ do_class: { int cu, cl; - /* This doesn't do a multi-byte character, because a MULTIBYTECODE - * would have been used for it. It does handle single-byte - * characters, such as latin1. */ - if (ireg_ic) { - cu = vim_toupper(*opnd); - cl = vim_tolower(*opnd); + // This doesn't do a multi-byte character, because a MULTIBYTECODE + // would have been used for it. It does handle single-byte + // characters, such as latin1. + if (rex.reg_ic) { + cu = mb_toupper(*opnd); + cl = mb_tolower(*opnd); while (count < maxcount && (*scan == cu || *scan == cl)) { count++; scan++; @@ -5358,17 +5378,19 @@ do_class: /* Safety check (just in case 'encoding' was changed since * compiling the program). */ if ((len = (*mb_ptr2len)(opnd)) > 1) { - if (ireg_ic && enc_utf8) + if (rex.reg_ic && enc_utf8) { cf = utf_fold(utf_ptr2char(opnd)); + } while (count < maxcount && (*mb_ptr2len)(scan) >= len) { for (i = 0; i < len; ++i) { if (opnd[i] != scan[i]) { break; } } - if (i < len && (!ireg_ic || !enc_utf8 - || utf_fold(utf_ptr2char(scan)) != cf)) + if (i < len && (!rex.reg_ic || !enc_utf8 + || utf_fold(utf_ptr2char(scan)) != cf)) { break; + } scan += len; ++count; } @@ -5386,18 +5408,21 @@ do_class: while (count < maxcount) { int len; if (*scan == NUL) { - if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline - || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline + || rex.reg_line_lbr) { break; + } reg_nextline(); scan = reginput; - if (got_int) + if (got_int) { break; - } else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) - ++scan; - else if (has_mbyte && (len = (*mb_ptr2len)(scan)) > 1) { - if ((cstrchr(opnd, (*mb_ptr2char)(scan)) == NULL) == testval) + } + } else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) { + scan++; + } else if (has_mbyte && (len = (*mb_ptr2len)(scan)) > 1) { + if ((cstrchr(opnd, (*mb_ptr2char)(scan)) == NULL) == testval) { break; + } scan += len; } else { if ((cstrchr(opnd, *scan) == NULL) == testval) @@ -5410,13 +5435,14 @@ do_class: case NEWL: while (count < maxcount - && ((*scan == NUL && reglnum <= reg_maxline && !reg_line_lbr - && REG_MULTI) || (*scan == '\n' && reg_line_lbr))) { + && ((*scan == NUL && reglnum <= rex.reg_maxline && !rex.reg_line_lbr + && REG_MULTI) || (*scan == '\n' && rex.reg_line_lbr))) { count++; - if (reg_line_lbr) + if (rex.reg_line_lbr) { ADVANCE_REGINPUT(); - else + } else { reg_nextline(); + } scan = reginput; if (got_int) break; @@ -5466,10 +5492,11 @@ static int prog_magic_wrong(void) { regprog_T *prog; - prog = REG_MULTI ? reg_mmatch->regprog : reg_match->regprog; - if (prog->engine == &nfa_regengine) - /* For NFA matcher we don't check the magic */ - return FALSE; + prog = REG_MULTI ? rex.reg_mmatch->regprog : rex.reg_match->regprog; + if (prog->engine == &nfa_regengine) { + // For NFA matcher we don't check the magic + return false; + } if (UCHARAT(((bt_regprog_T *)prog)->program) != REGMAGIC) { EMSG(_(e_re_corr)); @@ -5487,12 +5514,12 @@ static void cleanup_subexpr(void) { if (need_clear_subexpr) { if (REG_MULTI) { - /* Use 0xff to set lnum to -1 */ - memset(reg_startpos, 0xff, sizeof(lpos_T) * NSUBEXP); - memset(reg_endpos, 0xff, sizeof(lpos_T) * NSUBEXP); + // 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(reg_startp, 0, sizeof(char_u *) * NSUBEXP); - memset(reg_endp, 0, sizeof(char_u *) * NSUBEXP); + memset(rex.reg_startp, 0, sizeof(char_u *) * NSUBEXP); + memset(rex.reg_endp, 0, sizeof(char_u *) * NSUBEXP); } need_clear_subexpr = FALSE; } @@ -5521,17 +5548,17 @@ static void save_subexpr(regbehind_T *bp) { int i; - /* When "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. */ + // When "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 = need_clear_subexpr; if (!need_clear_subexpr) { for (i = 0; i < NSUBEXP; ++i) { if (REG_MULTI) { - bp->save_start[i].se_u.pos = reg_startpos[i]; - bp->save_end[i].se_u.pos = reg_endpos[i]; + 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 = reg_startp[i]; - bp->save_end[i].se_u.ptr = reg_endp[i]; + bp->save_start[i].se_u.ptr = rex.reg_startp[i]; + bp->save_end[i].se_u.ptr = rex.reg_endp[i]; } } } @@ -5549,11 +5576,11 @@ static void restore_subexpr(regbehind_T *bp) if (!need_clear_subexpr) { for (i = 0; i < NSUBEXP; ++i) { if (REG_MULTI) { - reg_startpos[i] = bp->save_start[i].se_u.pos; - reg_endpos[i] = bp->save_end[i].se_u.pos; + rex.reg_startpos[i] = bp->save_start[i].se_u.pos; + rex.reg_endpos[i] = bp->save_end[i].se_u.pos; } else { - reg_startp[i] = bp->save_start[i].se_u.ptr; - reg_endp[i] = bp->save_end[i].se_u.ptr; + rex.reg_startp[i] = bp->save_start[i].se_u.ptr; + rex.reg_endp[i] = bp->save_end[i].se_u.ptr; } } } @@ -5689,10 +5716,12 @@ static int match_with_backref(linenr_T start_lnum, colnr_T start_col, linenr_T e return RA_NOMATCH; /* doesn't match */ if (bytelen != NULL) *bytelen += len; - if (clnum == end_lnum) - break; /* match and at end! */ - if (reglnum >= reg_maxline) - return RA_NOMATCH; /* text too short */ + if (clnum == end_lnum) { + break; // match and at end! + } + if (reglnum >= rex.reg_maxline) { + return RA_NOMATCH; // text too short + } /* Advance to next line. */ reg_nextline(); @@ -6240,24 +6269,22 @@ static void mb_decompose(int c, int *c1, int *c2, int *c3) } } -/* - * Compare two strings, ignore case if ireg_ic set. - * Return 0 if strings match, non-zero otherwise. - * Correct the length "*n" when composing characters are ignored. - */ +// Compare two strings, ignore case if rex.reg_ic set. +// Return 0 if strings match, non-zero otherwise. +// Correct the length "*n" when composing characters are ignored. static int cstrncmp(char_u *s1, char_u *s2, int *n) { int result; - if (!ireg_ic) + if (!rex.reg_ic) { result = STRNCMP(s1, s2, *n); - else { + } else { assert(*n >= 0); result = mb_strnicmp(s1, s2, (size_t)*n); } - /* if it failed and it's utf8 and we want to combineignore: */ - if (result != 0 && enc_utf8 && ireg_icombine) { + // if it failed and it's utf8 and we want to combineignore: + if (result != 0 && enc_utf8 && rex.reg_icombine) { char_u *str1, *str2; int c1, c2, c11, c12; int junk; @@ -6268,20 +6295,21 @@ static int cstrncmp(char_u *s1, char_u *s2, int *n) str2 = s2; c1 = c2 = 0; while ((int)(str1 - s1) < *n) { - c1 = mb_ptr2char_adv(&str1); - c2 = mb_ptr2char_adv(&str2); + c1 = mb_ptr2char_adv((const char_u **)&str1); + c2 = mb_ptr2char_adv((const char_u **)&str2); /* decompose the character if necessary, into 'base' characters * because I don't care about Arabic, I will hard-code the Hebrew * which I *do* care about! So sue me... */ - if (c1 != c2 && (!ireg_ic || utf_fold(c1) != utf_fold(c2))) { - /* decomposition necessary? */ + if (c1 != c2 && (!rex.reg_ic || utf_fold(c1) != utf_fold(c2))) { + // decomposition necessary? mb_decompose(c1, &c11, &junk, &junk); mb_decompose(c2, &c12, &junk, &junk); c1 = c11; c2 = c12; - if (c11 != c12 && (!ireg_ic || utf_fold(c11) != utf_fold(c12))) + if (c11 != c12 && (!rex.reg_ic || utf_fold(c11) != utf_fold(c12))) { break; + } } } result = c2 - c1; @@ -6295,43 +6323,37 @@ static int cstrncmp(char_u *s1, char_u *s2, int *n) /* * cstrchr: This function is used a lot for simple searches, keep it fast! */ -static char_u *cstrchr(char_u *s, int c) +static inline char_u *cstrchr(const char_u *const s, const int c) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_ALWAYS_INLINE { - char_u *p; - int cc; - - if (!ireg_ic - || (!enc_utf8 && mb_char2len(c) > 1) - ) - return vim_strchr(s, c); - - /* tolower() and toupper() can be slow, comparing twice should be a lot - * faster (esp. when using MS Visual C++!). - * For UTF-8 need to use folded case. */ - if (enc_utf8 && c > 0x80) - cc = utf_fold(c); - else if (vim_isupper(c)) - cc = vim_tolower(c); - else if (vim_islower(c)) - cc = vim_toupper(c); - else + if (!rex.reg_ic) { return vim_strchr(s, c); + } - if (has_mbyte) { - for (p = s; *p != NUL; p += (*mb_ptr2len)(p)) { - if (enc_utf8 && c > 0x80) { - if (utf_fold(utf_ptr2char(p)) == cc) - return p; - } else if (*p == c || *p == cc) - return p; + // 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(p)) { + if (utf_fold(utf_ptr2char(p)) == folded_c) { + return (char_u *)p; + } } - } else - /* Faster version for when there are no multi-byte characters. */ - for (p = s; *p != NUL; ++p) - if (*p == c || *p == cc) - return p; + return NULL; + } + + int cc; + if (ASCII_ISUPPER(c)) { + cc = TOLOWER_ASC(c); + } else if (ASCII_ISLOWER(c)) { + cc = TOUPPER_ASC(c); + } else { + return vim_strchr(s, c); + } - return NULL; + char tofind[] = { (char)c, (char)cc, NUL }; + return (char_u *)strpbrk((const char *)s, tofind); } /*************************************************************** @@ -6344,28 +6366,28 @@ static char_u *cstrchr(char_u *s, int c) static fptr_T do_upper(int *d, int c) { - *d = vim_toupper(c); + *d = mb_toupper(c); return (fptr_T)NULL; } static fptr_T do_Upper(int *d, int c) { - *d = vim_toupper(c); + *d = mb_toupper(c); return (fptr_T)do_Upper; } static fptr_T do_lower(int *d, int c) { - *d = vim_tolower(c); + *d = mb_tolower(c); return (fptr_T)NULL; } static fptr_T do_Lower(int *d, int c) { - *d = vim_tolower(c); + *d = mb_tolower(c); return (fptr_T)do_Lower; } @@ -6433,55 +6455,132 @@ char_u *regtilde(char_u *source, int magic) static int can_f_submatch = FALSE; /* TRUE when submatch() can be used */ -/* These pointers are used instead of reg_match and reg_mmatch for - * reg_submatch(). Needed for when the substitution string is an expression - * that contains a call to substitute() and submatch(). */ -static regmatch_T *submatch_match; -static regmmatch_T *submatch_mmatch; -static linenr_T submatch_firstlnum; -static linenr_T submatch_maxline; -static int submatch_line_lbr; +// These pointers are used for reg_submatch(). Needed for when the +// substitution string is an expression that contains a call to substitute() +// and submatch(). +typedef struct { + regmatch_T *sm_match; + regmmatch_T *sm_mmatch; + linenr_T sm_firstlnum; + linenr_T sm_maxline; + int sm_line_lbr; +} regsubmatch_T; + +static regsubmatch_T rsm; // can only be used when can_f_submatch is true + +/// Put the submatches in "argv[0]" which is a list passed into call_func() by +/// vim_regsub_both(). +static int fill_submatch_list(int argc, typval_T *argv, int argcount) +{ + listitem_T *li; + int i; + char_u *s; -/* - * vim_regsub() - perform substitutions after a vim_regexec() or - * vim_regexec_multi() match. - * - * If "copy" is TRUE really copy into "dest". - * If "copy" is FALSE nothing is copied, this is just to find out the length - * of the result. - * - * If "backslash" is TRUE, a backslash will be removed later, need to double - * them to keep them, and insert a backslash before a CR to avoid it being - * replaced with a line break later. - * - * Note: The matched text must not change between the call of - * vim_regexec()/vim_regexec_multi() and vim_regsub()! It would make the back - * references invalid! - * - * Returns the size of the replacement, including terminating NUL. - */ -int vim_regsub(regmatch_T *rmp, char_u *source, char_u *dest, int copy, int magic, int backslash) + if (argcount == 0) { + // called function doesn't take an argument + return 0; + } + + // Relies on sl_list to be the first item in staticList10_T. + init_static_list((staticList10_T *)(argv->vval.v_list)); + + // There are always 10 list items in staticList10_T. + li = argv->vval.v_list->lv_first; + for (i = 0; i < 10; i++) { + s = rsm.sm_match->startp[i]; + if (s == NULL || rsm.sm_match->endp[i] == NULL) { + s = NULL; + } else { + s = vim_strnsave(s, (int)(rsm.sm_match->endp[i] - s)); + } + li->li_tv.v_type = VAR_STRING; + li->li_tv.vval.v_string = s; + li = li->li_next; + } + return 1; +} + +static void clear_submatch_list(staticList10_T *sl) +{ + int i; + + for (i = 0; i < 10; i++) { + xfree(sl->sl_items[i].li_tv.vval.v_string); + } +} + +/// vim_regsub() - perform substitutions after a vim_regexec() or +/// vim_regexec_multi() match. +/// +/// If "copy" is TRUE really copy into "dest". +/// If "copy" is FALSE nothing is copied, this is just to find out the length +/// of the result. +/// +/// If "backslash" is TRUE, a backslash will be removed later, need to double +/// them to keep them, and insert a backslash before a CR to avoid it being +/// replaced with a line break later. +/// +/// Note: The matched text must not change between the call of +/// vim_regexec()/vim_regexec_multi() and vim_regsub()! It would make the back +/// 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 copy, int magic, int backslash) { - reg_match = rmp; - reg_mmatch = NULL; - reg_maxline = 0; - reg_buf = curbuf; - reg_line_lbr = TRUE; - return vim_regsub_both(source, dest, copy, magic, backslash); + regexec_T rex_save; + bool rex_in_use_save = rex_in_use; + + if (rex_in_use) { + // Being called recursively, save the state. + rex_save = rex; + } + rex_in_use = true; + + rex.reg_match = rmp; + rex.reg_mmatch = NULL; + rex.reg_maxline = 0; + rex.reg_buf = curbuf; + rex.reg_line_lbr = true; + int result = vim_regsub_both(source, expr, dest, copy, magic, backslash); + + rex_in_use = rex_in_use_save; + if (rex_in_use) { + rex = rex_save; + } + + return result; } int vim_regsub_multi(regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u *dest, int copy, int magic, int backslash) { - reg_match = NULL; - reg_mmatch = rmp; - reg_buf = curbuf; /* always works on the current buffer! */ - reg_firstlnum = lnum; - reg_maxline = curbuf->b_ml.ml_line_count - lnum; - reg_line_lbr = FALSE; - return vim_regsub_both(source, dest, copy, magic, backslash); + regexec_T rex_save; + bool rex_in_use_save = rex_in_use; + + if (rex_in_use) { + // Being called recursively, save the state. + rex_save = rex; + } + rex_in_use = true; + + rex.reg_match = NULL; + rex.reg_mmatch = rmp; + rex.reg_buf = curbuf; // always works on the current buffer! + rex.reg_firstlnum = lnum; + rex.reg_maxline = curbuf->b_ml.ml_line_count - lnum; + rex.reg_line_lbr = false; + int result = vim_regsub_both(source, NULL, dest, copy, magic, backslash); + + rex_in_use = rex_in_use_save; + if (rex_in_use) { + rex = rex_save; + } + + return result; } -static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, int backslash) +static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, + int copy, int magic, int backslash) { char_u *src; char_u *dst; @@ -6495,8 +6594,8 @@ static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, in int len = 0; /* init for GCC */ static char_u *eval_result = NULL; - /* Be paranoid... */ - if (source == NULL || dest == NULL) { + // Be paranoid... + if ((source == NULL && expr == NULL) || dest == NULL) { EMSG(_(e_null)); return 0; } @@ -6505,16 +6604,12 @@ static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, in src = source; dst = dest; - /* - * When the substitute part starts with "\=" evaluate it as an expression. - */ - if (source[0] == '\\' && source[1] == '=' - && !can_f_submatch /* can't do this recursively */ - ) { - /* To make sure that the length doesn't change between checking the - * length and copying the string, and to speed up things, the - * resulting string is saved from the call with "copy" == FALSE to the - * call with "copy" == TRUE. */ + // When the substitute part starts with "\=" evaluate it as an expression. + if (expr != NULL || (source[0] == '\\' && source[1] == '=')) { + // To make sure that the length doesn't change between checking the + // length and copying the string, and to speed up things, the + // resulting string is saved from the call with "copy" == FALSE to the + // call with "copy" == TRUE. if (copy) { if (eval_result != NULL) { STRCPY(dest, eval_result); @@ -6523,45 +6618,83 @@ static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, in eval_result = NULL; } } else { - win_T *save_reg_win; - int save_ireg_ic; + int prev_can_f_submatch = can_f_submatch; + regsubmatch_T rsm_save; xfree(eval_result); - /* The expression may contain substitute(), which calls us - * recursively. Make sure submatch() gets the text from the first - * level. Don't need to save "reg_buf", because - * vim_regexec_multi() can't be called recursively. */ - submatch_match = reg_match; - submatch_mmatch = reg_mmatch; - submatch_firstlnum = reg_firstlnum; - submatch_maxline = reg_maxline; - submatch_line_lbr = reg_line_lbr; - save_reg_win = reg_win; - save_ireg_ic = ireg_ic; - can_f_submatch = TRUE; - - eval_result = eval_to_string(source + 2, NULL, TRUE); + // The expression may contain substitute(), which calls us + // recursively. Make sure submatch() gets the text from the first + // level. + if (can_f_submatch) { + rsm_save = rsm; + } + can_f_submatch = true; + rsm.sm_match = rex.reg_match; + rsm.sm_mmatch = rex.reg_mmatch; + rsm.sm_firstlnum = rex.reg_firstlnum; + rsm.sm_maxline = rex.reg_maxline; + rsm.sm_line_lbr = rex.reg_line_lbr; + + if (expr != NULL) { + typval_T argv[2]; + int dummy; + typval_T rettv; + staticList10_T matchList; + + rettv.v_type = VAR_STRING; + rettv.vval.v_string = NULL; + argv[0].v_type = VAR_LIST; + argv[0].vval.v_list = &matchList.sl_list; + matchList.sl_list.lv_len = 0; + if (expr->v_type == VAR_FUNC) { + s = expr->vval.v_string; + call_func(s, (int)STRLEN(s), &rettv, 1, argv, + fill_submatch_list, 0L, 0L, &dummy, + true, NULL, NULL); + } else if (expr->v_type == VAR_PARTIAL) { + partial_T *partial = expr->vval.v_partial; + + s = partial_name(partial); + call_func(s, (int)STRLEN(s), &rettv, 1, argv, + fill_submatch_list, 0L, 0L, &dummy, + true, partial, NULL); + } + if (matchList.sl_list.lv_len > 0) { + // fill_submatch_list() was called. + clear_submatch_list(&matchList); + } + char buf[NUMBUFLEN]; + eval_result = (char_u *)tv_get_string_buf_chk(&rettv, buf); + if (eval_result != NULL) { + eval_result = vim_strsave(eval_result); + } + tv_clear(&rettv); + } else { + eval_result = eval_to_string(source + 2, NULL, true); + } + if (eval_result != NULL) { int had_backslash = FALSE; for (s = eval_result; *s != NUL; mb_ptr_adv(s)) { - /* Change NL to CR, so that it becomes a line break, - * unless called from vim_regexec_nl(). - * Skip over a backslashed character. */ - if (*s == NL && !submatch_line_lbr) + // Change NL to CR, so that it becomes a line break, + // unless called from vim_regexec_nl(). + // Skip over a backslashed character. + if (*s == NL && !rsm.sm_line_lbr) { *s = CAR; - else if (*s == '\\' && s[1] != NUL) { - ++s; + } else if (*s == '\\' && s[1] != NUL) { + s++; /* Change NL to CR here too, so that this works: * :s/abc\\\ndef/\="aaa\\\nbbb"/ on text: * abc\ * def * Not when called from vim_regexec_nl(). */ - if (*s == NL && !submatch_line_lbr) + if (*s == NL && !rsm.sm_line_lbr) { *s = CAR; - had_backslash = TRUE; + } + had_backslash = true; } } if (had_backslash && backslash) { @@ -6574,14 +6707,10 @@ static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, in dst += STRLEN(eval_result); } - reg_match = submatch_match; - reg_mmatch = submatch_mmatch; - reg_firstlnum = submatch_firstlnum; - reg_maxline = submatch_maxline; - reg_line_lbr = submatch_line_lbr; - reg_win = save_reg_win; - ireg_ic = save_ireg_ic; - can_f_submatch = FALSE; + can_f_submatch = prev_can_f_submatch; + if (can_f_submatch) { + rsm = rsm_save; + } } } else while ((c = *src++) != NUL) { @@ -6679,43 +6808,50 @@ static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, in dst++; } else { if (REG_MULTI) { - clnum = reg_mmatch->startpos[no].lnum; - if (clnum < 0 || reg_mmatch->endpos[no].lnum < 0) + clnum = rex.reg_mmatch->startpos[no].lnum; + if (clnum < 0 || rex.reg_mmatch->endpos[no].lnum < 0) { s = NULL; - else { - s = reg_getline(clnum) + reg_mmatch->startpos[no].col; - if (reg_mmatch->endpos[no].lnum == clnum) - len = reg_mmatch->endpos[no].col - - reg_mmatch->startpos[no].col; - else + } else { + 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; + } else { len = (int)STRLEN(s); + } } } else { - s = reg_match->startp[no]; - if (reg_match->endp[no] == NULL) + s = rex.reg_match->startp[no]; + if (rex.reg_match->endp[no] == NULL) { s = NULL; - else - len = (int)(reg_match->endp[no] - s); + } else { + len = (int)(rex.reg_match->endp[no] - s); + } } if (s != NULL) { for (;; ) { if (len == 0) { if (REG_MULTI) { - if (reg_mmatch->endpos[no].lnum == clnum) + if (rex.reg_mmatch->endpos[no].lnum == clnum) { break; - if (copy) + } + if (copy) { *dst = CAR; - ++dst; + } + dst++; s = reg_getline(++clnum); - if (reg_mmatch->endpos[no].lnum == clnum) - len = reg_mmatch->endpos[no].col; - else + if (rex.reg_mmatch->endpos[no].lnum == clnum) { + len = rex.reg_mmatch->endpos[no].col; + } else { len = (int)STRLEN(s); - } else + } + } else { break; - } else if (*s == NUL) { /* we hit NUL. */ - if (copy) + } + } else if (*s == NUL) { // we hit NUL. + if (copy) { EMSG(_(e_re_damg)); + } goto exit; } else { if (backslash && (*s == CAR || *s == '\\')) { @@ -6789,16 +6925,16 @@ exit: static char_u *reg_getline_submatch(linenr_T lnum) { char_u *s; - linenr_T save_first = reg_firstlnum; - linenr_T save_max = reg_maxline; + linenr_T save_first = rex.reg_firstlnum; + linenr_T save_max = rex.reg_maxline; - reg_firstlnum = submatch_firstlnum; - reg_maxline = submatch_maxline; + rex.reg_firstlnum = rsm.sm_firstlnum; + rex.reg_maxline = rsm.sm_maxline; s = reg_getline(lnum); - reg_firstlnum = save_first; - reg_maxline = save_max; + rex.reg_firstlnum = save_first; + rex.reg_maxline = save_max; return s; } @@ -6817,39 +6953,41 @@ char_u *reg_submatch(int no) if (!can_f_submatch || no < 0) return NULL; - if (submatch_match == NULL) { + if (rsm.sm_match == NULL) { ssize_t len; /* * First round: compute the length and allocate memory. * Second round: copy the text. */ - for (round = 1; round <= 2; ++round) { - lnum = submatch_mmatch->startpos[no].lnum; - if (lnum < 0 || submatch_mmatch->endpos[no].lnum < 0) + for (round = 1; round <= 2; round++) { + lnum = rsm.sm_mmatch->startpos[no].lnum; + if (lnum < 0 || rsm.sm_mmatch->endpos[no].lnum < 0) { return NULL; + } - s = reg_getline_submatch(lnum) + submatch_mmatch->startpos[no].col; - if (s == NULL) /* anti-crash check, cannot happen? */ + s = reg_getline_submatch(lnum) + rsm.sm_mmatch->startpos[no].col; + if (s == NULL) { // anti-crash check, cannot happen? break; - if (submatch_mmatch->endpos[no].lnum == lnum) { - /* Within one line: take form start to end col. */ - len = submatch_mmatch->endpos[no].col - - submatch_mmatch->startpos[no].col; - if (round == 2) + } + if (rsm.sm_mmatch->endpos[no].lnum == lnum) { + // Within one line: take form start to end col. + len = rsm.sm_mmatch->endpos[no].col - rsm.sm_mmatch->startpos[no].col; + if (round == 2) { STRLCPY(retval, s, len + 1); - ++len; + } + len++; } else { - /* Multiple lines: take start line from start col, middle - * lines completely and end line up to end col. */ - len = STRLEN(s); + // Multiple lines: take start line from start col, middle + // lines completely and end line up to end col. + len = (ssize_t)STRLEN(s); if (round == 2) { STRCPY(retval, s); retval[len] = '\n'; } - ++len; - ++lnum; - while (lnum < submatch_mmatch->endpos[no].lnum) { + len++; + lnum++; + while (lnum < rsm.sm_mmatch->endpos[no].lnum) { s = reg_getline_submatch(lnum++); if (round == 2) STRCPY(retval + len, s); @@ -6858,13 +6996,15 @@ char_u *reg_submatch(int no) retval[len] = '\n'; ++len; } - if (round == 2) + if (round == 2) { STRNCPY(retval + len, reg_getline_submatch(lnum), - submatch_mmatch->endpos[no].col); - len += submatch_mmatch->endpos[no].col; - if (round == 2) - retval[len] = NUL; - ++len; + rsm.sm_mmatch->endpos[no].col); + } + len += rsm.sm_mmatch->endpos[no].col; + if (round == 2) { + retval[len] = NUL; // -V595 + } + len++; } if (retval == NULL) { @@ -6872,11 +7012,12 @@ char_u *reg_submatch(int no) } } } else { - s = submatch_match->startp[no]; - if (s == NULL || submatch_match->endp[no] == NULL) + s = rsm.sm_match->startp[no]; + if (s == NULL || rsm.sm_match->endp[no] == NULL) { retval = NULL; - else - retval = vim_strnsave(s, (int)(submatch_match->endp[no] - s)); + } else { + retval = vim_strnsave(s, (int)(rsm.sm_match->endp[no] - s)); + } } return retval; @@ -6896,39 +7037,39 @@ list_T *reg_submatch_list(int no) linenr_T slnum; linenr_T elnum; list_T *list; - char_u *s; + const char *s; - if (submatch_match == NULL) { - slnum = submatch_mmatch->startpos[no].lnum; - elnum = submatch_mmatch->endpos[no].lnum; + if (rsm.sm_match == NULL) { + slnum = rsm.sm_mmatch->startpos[no].lnum; + elnum = rsm.sm_mmatch->endpos[no].lnum; if (slnum < 0 || elnum < 0) { return NULL; } - colnr_T scol = submatch_mmatch->startpos[no].col; - colnr_T ecol = submatch_mmatch->endpos[no].col; + colnr_T scol = rsm.sm_mmatch->startpos[no].col; + colnr_T ecol = rsm.sm_mmatch->endpos[no].col; - list = list_alloc(); + list = tv_list_alloc(); - s = reg_getline_submatch(slnum) + scol; + s = (const char *)reg_getline_submatch(slnum) + scol; if (slnum == elnum) { - list_append_string(list, s, ecol - scol); + tv_list_append_string(list, s, ecol - scol); } else { - list_append_string(list, s, -1); + tv_list_append_string(list, s, -1); for (int i = 1; i < elnum - slnum; i++) { - s = reg_getline_submatch(slnum + i); - list_append_string(list, s, -1); + s = (const char *)reg_getline_submatch(slnum + i); + tv_list_append_string(list, s, -1); } - s = reg_getline_submatch(elnum); - list_append_string(list, s, ecol); + s = (const char *)reg_getline_submatch(elnum); + tv_list_append_string(list, s, ecol); } } else { - s = submatch_match->startp[no]; - if (s == NULL || submatch_match->endp[no] == NULL) { + s = (const char *)rsm.sm_match->startp[no]; + if (s == NULL || rsm.sm_match->endp[no] == NULL) { return NULL; } - list = list_alloc(); - list_append_string(list, s, (int)(submatch_match->endp[no] - s)); + list = tv_list_alloc(); + tv_list_append_string(list, s, (const char *)rsm.sm_match->endp[no] - s); } return list; @@ -7082,6 +7223,19 @@ static void report_re_switch(char_u *pat) /// @return TRUE if there is a match, FALSE if not. static int vim_regexec_both(regmatch_T *rmp, char_u *line, colnr_T col, bool nl) { + regexec_T rex_save; + bool rex_in_use_save = rex_in_use; + + if (rex_in_use) { + // Being called recursively, save the state. + rex_save = rex; + } + rex_in_use = true; + rex.reg_startp = NULL; + rex.reg_endp = NULL; + rex.reg_startpos = NULL; + rex.reg_endpos = NULL; + int result = rmp->regprog->engine->regexec_nl(rmp, line, col, nl); // NFA engine aborted because it's very slow, use backtracking engine instead. @@ -7103,6 +7257,11 @@ static int vim_regexec_both(regmatch_T *rmp, char_u *line, colnr_T col, bool nl) p_re = save_p_re; } + rex_in_use = rex_in_use_save; + if (rex_in_use) { + rex = rex_save; + } + return result > 0; } @@ -7150,6 +7309,15 @@ long vim_regexec_multi( proftime_T *tm /* timeout limit or NULL */ ) { + regexec_T rex_save; + bool rex_in_use_save = rex_in_use; + + if (rex_in_use) { + // Being called recursively, save the state. + rex_save = rex; + } + rex_in_use = true; + int result = rmp->regprog->engine->regexec_multi(rmp, win, buf, lnum, col, tm); @@ -7173,5 +7341,10 @@ long vim_regexec_multi( p_re = save_p_re; } + rex_in_use = rex_in_use_save; + if (rex_in_use) { + rex = rex_save; + } + return result <= 0 ? 0 : result; } diff --git a/src/nvim/regexp.h b/src/nvim/regexp.h index 37513d8c27..97595c4d29 100644 --- a/src/nvim/regexp.h +++ b/src/nvim/regexp.h @@ -1,6 +1,10 @@ #ifndef NVIM_REGEXP_H #define NVIM_REGEXP_H +#include "nvim/types.h" +#include "nvim/buffer_defs.h" +#include "nvim/regexp_defs.h" + /* Second argument for vim_regcomp(). */ #define RE_MAGIC 1 /* 'magic' option */ #define RE_STRING 2 /* match in string instead of buffer text */ diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index 474f3df32a..93ba9ce097 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -1,3 +1,6 @@ +// 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 + /* * NFA regular expression implementation. * @@ -53,13 +56,13 @@ enum { NFA_RANGE_MIN, /* low end of a range */ NFA_RANGE_MAX, /* high end of a range */ - NFA_CONCAT, /* concatenate two previous items (postfix - * only) */ - NFA_OR, /* \| (postfix only) */ - NFA_STAR, /* greedy * (posfix only) */ - NFA_STAR_NONGREEDY, /* non-greedy * (postfix only) */ - NFA_QUEST, /* greedy \? (postfix only) */ - NFA_QUEST_NONGREEDY, /* non-greedy \? (postfix only) */ + NFA_CONCAT, // concatenate two previous items (postfix + // only) + NFA_OR, // \| (postfix only) + NFA_STAR, // greedy * (postfix only) + NFA_STAR_NONGREEDY, // non-greedy * (postfix only) + NFA_QUEST, // greedy \? (postfix only) + NFA_QUEST_NONGREEDY, // non-greedy \? (postfix only) NFA_BOL, /* ^ Begin line */ NFA_EOL, /* $ End line */ @@ -631,6 +634,7 @@ static int nfa_recognize_char_class(char_u *start, char_u *end, int extra_newl) config |= CLASS_o7; break; } + return FAIL; case 'a': if (*(p + 2) == 'z') { config |= CLASS_az; @@ -639,6 +643,7 @@ static int nfa_recognize_char_class(char_u *start, char_u *end, int extra_newl) config |= CLASS_af; break; } + return FAIL; case 'A': if (*(p + 2) == 'Z') { config |= CLASS_AZ; @@ -647,7 +652,7 @@ static int nfa_recognize_char_class(char_u *start, char_u *end, int extra_newl) config |= CLASS_AF; break; } - /* FALLTHROUGH */ + return FAIL; default: return FAIL; } @@ -1983,7 +1988,7 @@ static int nfa_regpiece(void) // The engine is very inefficient (uses too many states) when the maximum // is much larger than the minimum and when the maximum is large. Bail out // if we can use the other engine. - if ((nfa_re_flags & RE_AUTO) && (maxval > minval + 200 || maxval > 500)) { + if ((nfa_re_flags & RE_AUTO) && (maxval > 500 || maxval > minval + 200)) { return FAIL; } @@ -2772,15 +2777,10 @@ static int nfa_max_width(nfa_state_T *startstate, int depth) case NFA_ANY: case NFA_START_COLL: case NFA_START_NEG_COLL: - /* matches some character, including composing chars */ - if (enc_utf8) - len += MB_MAXBYTES; - else if (has_mbyte) - len += 2; - else - ++len; + // Matches some character, including composing chars. + len += MB_MAXBYTES; if (state->c != NFA_ANY) { - /* skip over the characters */ + // Skip over the characters. state = state->out1->out; continue; } @@ -3893,23 +3893,27 @@ state_in_list ( return FALSE; } -/* - * Add "state" and possibly what follows to state list ".". - * Returns "subs_arg", possibly copied into temp_subs. - */ +// Offset used for "off" by addstate_here(). +#define ADDSTATE_HERE_OFFSET 10 +// Add "state" and possibly what follows to state list ".". +// Returns "subs_arg", possibly copied into temp_subs. static regsubs_T * addstate ( nfa_list_T *l, /* runtime state list */ nfa_state_T *state, /* state to update */ regsubs_T *subs_arg, /* pointers to subexpressions */ nfa_pim_T *pim, /* postponed look-behind match */ - int off /* byte offset, when -1 go to next line */ -) + int off_arg) /* byte offset, when -1 go to next line */ { int subidx; + int off = off_arg; + int add_here = FALSE; + int listindex = 0; + int k; + int found = FALSE; nfa_thread_T *thread; - lpos_T save_lpos; + struct multipos save_multipos; int save_in_use; char_u *save_ptr; int i; @@ -3920,6 +3924,12 @@ addstate ( int did_print = FALSE; #endif + if (off_arg <= -ADDSTATE_HERE_OFFSET) { + add_here = true; + off = 0; + listindex = -(off_arg + ADDSTATE_HERE_OFFSET); + } + switch (state->c) { case NFA_NCLOSE: case NFA_MCLOSE: @@ -3996,13 +4006,28 @@ addstate ( * lower position is preferred. */ if (!nfa_has_backref && pim == NULL && !l->has_pim && state->c != NFA_MATCH) { + + /* When called from addstate_here() do insert before + * existing states. */ + if (add_here) { + for (k = 0; k < l->n && k < listindex; ++k) { + if (l->t[k].state->id == state->id) { + found = TRUE; + break; + } + } + } + + if (!add_here || found) { skip_add: #ifdef REGEXP_DEBUG - nfa_set_code(state->c); - fprintf(log_fd, "> Not adding state %d to list %d. char %d: %s\n", - abs(state->id), l->id, state->c, code); + nfa_set_code(state->c); + fprintf(log_fd, "> Not adding state %d to list %d. char %d: %s pim: %s has_pim: %d found: %d\n", + abs(state->id), l->id, state->c, code, + pim == NULL ? "NULL" : "yes", l->has_pim, found); #endif return subs; + } } /* Do not add the state again when it exists with the same @@ -4058,14 +4083,14 @@ skip_add: case NFA_SPLIT: /* order matters here */ - subs = addstate(l, state->out, subs, pim, off); - subs = addstate(l, state->out1, subs, pim, off); + subs = addstate(l, state->out, subs, pim, off_arg); + subs = addstate(l, state->out1, subs, pim, off_arg); break; case NFA_EMPTY: case NFA_NOPEN: case NFA_NCLOSE: - subs = addstate(l, state->out, subs, pim, off); + subs = addstate(l, state->out, subs, pim, off_arg); break; case NFA_MOPEN: @@ -4102,15 +4127,13 @@ skip_add: /* avoid compiler warnings */ save_ptr = NULL; - save_lpos.lnum = 0; - save_lpos.col = 0; + memset(&save_multipos, 0, sizeof(save_multipos)); /* Set the position (with "off" added) in the subexpression. Save * and restore it when it was in use. Otherwise fill any gap. */ if (REG_MULTI) { if (subidx < sub->in_use) { - save_lpos.lnum = sub->list.multi[subidx].start_lnum; - save_lpos.col = sub->list.multi[subidx].start_col; + save_multipos = sub->list.multi[subidx]; save_in_use = -1; } else { save_in_use = sub->in_use; @@ -4145,7 +4168,7 @@ skip_add: sub->list.line[subidx].start = reginput + off; } - subs = addstate(l, state->out, subs, pim, off); + subs = addstate(l, state->out, subs, pim, off_arg); /* "subs" may have changed, need to set "sub" again */ if (state->c >= NFA_ZOPEN && state->c <= NFA_ZOPEN9) sub = &subs->synt; @@ -4153,9 +4176,8 @@ skip_add: sub = &subs->norm; if (save_in_use == -1) { - if (REG_MULTI){ - sub->list.multi[subidx].start_lnum = save_lpos.lnum; - sub->list.multi[subidx].start_col = save_lpos.col; + if (REG_MULTI) { + sub->list.multi[subidx] = save_multipos; } else sub->list.line[subidx].start = save_ptr; @@ -4168,9 +4190,10 @@ skip_add: ? subs->norm.list.multi[0].end_lnum >= 0 : subs->norm.list.line[0].end != NULL)) { /* Do not overwrite the position set by \ze. */ - subs = addstate(l, state->out, subs, pim, off); + subs = addstate(l, state->out, subs, pim, off_arg); break; } + // fallthrough case NFA_MCLOSE1: case NFA_MCLOSE2: case NFA_MCLOSE3: @@ -4208,8 +4231,7 @@ skip_add: if (sub->in_use <= subidx) sub->in_use = subidx + 1; if (REG_MULTI) { - save_lpos.lnum = sub->list.multi[subidx].end_lnum; - save_lpos.col = sub->list.multi[subidx].end_col; + save_multipos = sub->list.multi[subidx]; if (off == -1) { sub->list.multi[subidx].end_lnum = reglnum + 1; sub->list.multi[subidx].end_col = 0; @@ -4223,21 +4245,19 @@ skip_add: } else { save_ptr = sub->list.line[subidx].end; sub->list.line[subidx].end = reginput + off; - /* avoid compiler warnings */ - save_lpos.lnum = 0; - save_lpos.col = 0; + // avoid compiler warnings + memset(&save_multipos, 0, sizeof(save_multipos)); } - subs = addstate(l, state->out, subs, pim, off); + subs = addstate(l, state->out, subs, pim, off_arg); /* "subs" may have changed, need to set "sub" again */ if (state->c >= NFA_ZCLOSE && state->c <= NFA_ZCLOSE9) sub = &subs->synt; else sub = &subs->norm; - if (REG_MULTI){ - sub->list.multi[subidx].end_lnum = save_lpos.lnum; - sub->list.multi[subidx].end_col = save_lpos.col; + if (REG_MULTI) { + sub->list.multi[subidx] = save_multipos; } else sub->list.line[subidx].end = save_ptr; @@ -4266,8 +4286,10 @@ addstate_here ( int count; int listidx = *ip; - /* first add the state(s) at the end, so that we know how many there are */ - addstate(l, state, subs, pim, 0); + /* First add the state(s) at the end, so that we know how many there are. + * Pass the listidx as offset (avoids adding another argument to + * addstate(). */ + addstate(l, state, subs, pim, -listidx - ADDSTATE_HERE_OFFSET); /* when "*ip" was at the end of the list, nothing to do */ if (listidx + 1 == tlen) @@ -4346,7 +4368,7 @@ static int check_char_class(int class, int c) return OK; break; case NFA_CLASS_LOWER: - if (vim_islower(c) && c != 170 && c != 186) { + if (mb_islower(c) && c != 170 && c != 186) { return OK; } break; @@ -4364,8 +4386,9 @@ static int check_char_class(int class, int c) return OK; break; case NFA_CLASS_UPPER: - if (vim_isupper(c)) + if (mb_isupper(c)) { return OK; + } break; case NFA_CLASS_XDIGIT: if (ascii_isxdigit(c)) @@ -4384,8 +4407,9 @@ static int check_char_class(int class, int c) return OK; break; case NFA_CLASS_ESCAPE: - if (c == '\033') + if (c == ESC) { return OK; + } break; default: @@ -4828,17 +4852,10 @@ static int failure_chance(nfa_state_T *state, int depth) */ static int skip_to_start(int c, colnr_T *colp) { - char_u *s; - - /* Used often, do some work to avoid call overhead. */ - if (!ireg_ic - && !has_mbyte - ) - s = vim_strbyte(regline + *colp, c); - else - s = cstrchr(regline + *colp, c); - if (s == NULL) + const char_u *const s = cstrchr(regline + *colp, c); + if (s == NULL) { return FAIL; + } *colp = (int)(s - regline); return OK; } @@ -4865,7 +4882,7 @@ static long find_match_text(colnr_T startcol, int regstart, char_u *match_text) int c2_len = PTR2LEN(s2); int c2 = PTR2CHAR(s2); - if ((c1 != c2 && (!ireg_ic || vim_tolower(c1) != vim_tolower(c2))) + if ((c1 != c2 && (!rex.reg_ic || mb_tolower(c1) != mb_tolower(c2))) || c1_len != c2_len) { match = false; break; @@ -4878,13 +4895,13 @@ static long find_match_text(colnr_T startcol, int regstart, char_u *match_text) && !(enc_utf8 && utf_iscomposing(PTR2CHAR(s2)))) { cleanup_subexpr(); if (REG_MULTI) { - reg_startpos[0].lnum = reglnum; - reg_startpos[0].col = col; - reg_endpos[0].lnum = reglnum; - reg_endpos[0].col = s2 - regline; + rex.reg_startpos[0].lnum = reglnum; + rex.reg_startpos[0].col = col; + rex.reg_endpos[0].lnum = reglnum; + rex.reg_endpos[0].col = s2 - regline; } else { - reg_startp[0] = regline + col; - reg_endp[0] = s2; + rex.reg_startp[0] = regline + col; + rex.reg_endp[0] = s2; } return 1L; } @@ -5099,8 +5116,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, case NFA_MATCH: { // If the match ends before a composing characters and - // ireg_icombine is not set, that is not really a match. - if (enc_utf8 && !ireg_icombine && utf_iscomposing(curc)) { + // rex.reg_icombine is not set, that is not really a match. + if (enc_utf8 && !rex.reg_icombine && utf_iscomposing(curc)) { break; } nfa_match = true; @@ -5383,15 +5400,15 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, int this_class; // Get class of current and previous char (if it exists). - this_class = mb_get_class_buf(reginput, reg_buf); + this_class = mb_get_class_tab(reginput, rex.reg_buf->b_chartab); if (this_class <= 1) { result = false; } else if (reg_prev_class() == this_class) { result = false; } - } else if (!vim_iswordc_buf(curc, reg_buf) + } else if (!vim_iswordc_buf(curc, rex.reg_buf) || (reginput > regline - && vim_iswordc_buf(reginput[-1], reg_buf))) { + && vim_iswordc_buf(reginput[-1], rex.reg_buf))) { result = false; } if (result) { @@ -5408,15 +5425,15 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, int this_class, prev_class; // Get class of current and previous char (if it exists). - this_class = mb_get_class_buf(reginput, reg_buf); + this_class = mb_get_class_tab(reginput, rex.reg_buf->b_chartab); prev_class = reg_prev_class(); if (this_class == prev_class || prev_class == 0 || prev_class == 1) { result = false; } - } else if (!vim_iswordc_buf(reginput[-1], reg_buf) + } else if (!vim_iswordc_buf(reginput[-1], rex.reg_buf) || (reginput[0] != NUL - && vim_iswordc_buf(curc, reg_buf))) { + && vim_iswordc_buf(curc, rex.reg_buf))) { result = false; } if (result) { @@ -5427,14 +5444,14 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, case NFA_BOF: if (reglnum == 0 && reginput == regline - && (!REG_MULTI || reg_firstlnum == 1)) { + && (!REG_MULTI || rex.reg_firstlnum == 1)) { add_here = true; add_state = t->state->out; } break; case NFA_EOF: - if (reglnum == reg_maxline && curc == NUL) { + if (reglnum == rex.reg_maxline && curc == NUL) { add_here = true; add_state = t->state->out; } @@ -5458,7 +5475,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, // (no preceding character). len += mb_char2len(mc); } - if (ireg_icombine && len == 0) { + if (rex.reg_icombine && len == 0) { // If \Z was present, then ignore composing characters. // When ignoring the base character this always matches. if (sta->c != curc) { @@ -5509,14 +5526,14 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, } case NFA_NEWL: - if (curc == NUL && !reg_line_lbr && REG_MULTI - && reglnum <= reg_maxline) { + if (curc == NUL && !rex.reg_line_lbr && REG_MULTI + && reglnum <= rex.reg_maxline) { go_to_nextline = true; // Pass -1 for the offset, which means taking the position // at the start of the next line. add_state = t->state->out; add_off = -1; - } else if (curc == '\n' && reg_line_lbr) { + } else if (curc == '\n' && rex.reg_line_lbr) { // match \n as if it is an ordinary character add_state = t->state->out; add_off = 1; @@ -5557,23 +5574,25 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, result = result_if_matched; break; } - if (ireg_ic) { - int curc_low = vim_tolower(curc); - int done = FALSE; + if (rex.reg_ic) { + int curc_low = mb_tolower(curc); + int done = false; - for (; c1 <= c2; ++c1) - if (vim_tolower(c1) == curc_low) { + for (; c1 <= c2; c1++) { + if (mb_tolower(c1) == curc_low) { result = result_if_matched; done = TRUE; break; } - if (done) + } + if (done) { break; + } } } else if (state->c < 0 ? check_char_class(state->c, curc) : (curc == state->c - || (ireg_ic && vim_tolower(curc) - == vim_tolower(state->c)))) { + || (rex.reg_ic && mb_tolower(curc) + == mb_tolower(state->c)))) { result = result_if_matched; break; } @@ -5620,13 +5639,13 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, break; case NFA_KWORD: // \k - result = vim_iswordp_buf(reginput, reg_buf); + result = vim_iswordp_buf(reginput, rex.reg_buf); ADD_STATE_IF_MATCH(t->state); break; case NFA_SKWORD: // \K result = !ascii_isdigit(curc) - && vim_iswordp_buf(reginput, reg_buf); + && vim_iswordp_buf(reginput, rex.reg_buf); ADD_STATE_IF_MATCH(t->state); break; @@ -5741,24 +5760,24 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, break; case NFA_LOWER_IC: // [a-z] - result = ri_lower(curc) || (ireg_ic && ri_upper(curc)); + result = ri_lower(curc) || (rex.reg_ic && ri_upper(curc)); ADD_STATE_IF_MATCH(t->state); break; case NFA_NLOWER_IC: // [^a-z] result = curc != NUL - && !(ri_lower(curc) || (ireg_ic && ri_upper(curc))); + && !(ri_lower(curc) || (rex.reg_ic && ri_upper(curc))); ADD_STATE_IF_MATCH(t->state); break; case NFA_UPPER_IC: // [A-Z] - result = ri_upper(curc) || (ireg_ic && ri_lower(curc)); + result = ri_upper(curc) || (rex.reg_ic && ri_lower(curc)); ADD_STATE_IF_MATCH(t->state); break; case NFA_NUPPER_IC: // [^A-Z] result = curc != NUL - && !(ri_upper(curc) || (ireg_ic && ri_lower(curc))); + && !(ri_upper(curc) || (rex.reg_ic && ri_lower(curc))); ADD_STATE_IF_MATCH(t->state); break; @@ -5832,13 +5851,15 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, case NFA_LNUM_GT: case NFA_LNUM_LT: assert(t->state->val >= 0 - && !((reg_firstlnum > 0 && reglnum > LONG_MAX - reg_firstlnum) - || (reg_firstlnum <0 && reglnum < LONG_MIN + reg_firstlnum)) - && reglnum + reg_firstlnum >= 0); + && !((rex.reg_firstlnum > 0 + && reglnum > LONG_MAX - rex.reg_firstlnum) + || (rex.reg_firstlnum < 0 + && reglnum < LONG_MIN + rex.reg_firstlnum)) + && reglnum + rex.reg_firstlnum >= 0); result = (REG_MULTI && nfa_re_num_cmp((uintmax_t)t->state->val, t->state->c - NFA_LNUM, - (uintmax_t)(reglnum + reg_firstlnum))); + (uintmax_t)(reglnum + rex.reg_firstlnum))); if (result) { add_here = true; add_state = t->state->out; @@ -5874,7 +5895,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, } result = false; - win_T *wp = reg_win == NULL ? curwin : reg_win; + win_T *wp = rex.reg_win == NULL ? curwin : rex.reg_win; if (op == 1 && col - 1 > t->state->val && col > 100) { long ts = wp->w_buffer->b_p_ts; @@ -5901,18 +5922,18 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, case NFA_MARK_GT: case NFA_MARK_LT: { - pos_T *pos = getmark_buf(reg_buf, t->state->val, FALSE); + pos_T *pos = getmark_buf(rex.reg_buf, t->state->val, false); // Compare the mark position to the match position. result = (pos != NULL // mark doesn't exist && pos->lnum > 0 // mark isn't set in reg_buf - && (pos->lnum == reglnum + reg_firstlnum + && (pos->lnum == reglnum + rex.reg_firstlnum ? (pos->col == (colnr_T)(reginput - regline) ? t->state->c == NFA_MARK : (pos->col < (colnr_T)(reginput - regline) ? t->state->c == NFA_MARK_GT : t->state->c == NFA_MARK_LT)) - : (pos->lnum < reglnum + reg_firstlnum + : (pos->lnum < reglnum + rex.reg_firstlnum ? t->state->c == NFA_MARK_GT : t->state->c == NFA_MARK_LT))); if (result) { @@ -5923,10 +5944,10 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, } case NFA_CURSOR: - result = (reg_win != NULL - && (reglnum + reg_firstlnum == reg_win->w_cursor.lnum) + result = (rex.reg_win != NULL + && (reglnum + rex.reg_firstlnum == rex.reg_win->w_cursor.lnum) && ((colnr_T)(reginput - regline) - == reg_win->w_cursor.col)); + == rex.reg_win->w_cursor.col)); if (result) { add_here = true; add_state = t->state->out; @@ -5976,12 +5997,13 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, #endif result = (c == curc); - if (!result && ireg_ic) - result = vim_tolower(c) == vim_tolower(curc); + if (!result && rex.reg_ic) { + result = mb_tolower(c) == mb_tolower(curc); + } - // If ireg_icombine is not set only skip over the character + // If rex.reg_icombine is not set only skip over the character // itself. When it is set skip over composing characters. - if (result && enc_utf8 && !ireg_icombine) { + if (result && enc_utf8 && !rex.reg_icombine) { clen = utf_ptr2len(reginput); } @@ -6089,8 +6111,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, && ((toplevel && reglnum == 0 && clen != 0 - && (ireg_maxcol == 0 - || (colnr_T)(reginput - regline) < ireg_maxcol)) + && (rex.reg_maxcol == 0 + || (colnr_T)(reginput - regline) < rex.reg_maxcol)) || (nfa_endp != NULL && (REG_MULTI ? (reglnum < nfa_endp->se_u.pos.lnum @@ -6125,8 +6147,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, // Checking if the required start character matches is // cheaper than adding a state that won't match. c = PTR2CHAR(reginput + clen); - if (c != prog->regstart && (!ireg_ic || vim_tolower(c) - != vim_tolower(prog->regstart))) { + if (c != prog->regstart && (!rex.reg_ic || mb_tolower(c) + != mb_tolower(prog->regstart))) { #ifdef REGEXP_DEBUG fprintf(log_fd, " Skipping start state, regstart does not match\n"); @@ -6251,34 +6273,37 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm) cleanup_subexpr(); if (REG_MULTI) { for (i = 0; i < subs.norm.in_use; i++) { - reg_startpos[i].lnum = subs.norm.list.multi[i].start_lnum; - reg_startpos[i].col = subs.norm.list.multi[i].start_col; + rex.reg_startpos[i].lnum = subs.norm.list.multi[i].start_lnum; + rex.reg_startpos[i].col = subs.norm.list.multi[i].start_col; - reg_endpos[i].lnum = subs.norm.list.multi[i].end_lnum; - reg_endpos[i].col = subs.norm.list.multi[i].end_col; + rex.reg_endpos[i].lnum = subs.norm.list.multi[i].end_lnum; + rex.reg_endpos[i].col = subs.norm.list.multi[i].end_col; } - if (reg_startpos[0].lnum < 0) { - reg_startpos[0].lnum = 0; - reg_startpos[0].col = col; + if (rex.reg_startpos[0].lnum < 0) { + rex.reg_startpos[0].lnum = 0; + rex.reg_startpos[0].col = col; + } + if (rex.reg_endpos[0].lnum < 0) { + // pattern has a \ze but it didn't match, use current end + rex.reg_endpos[0].lnum = reglnum; + rex.reg_endpos[0].col = (int)(reginput - regline); + } else { + // Use line number of "\ze". + reglnum = rex.reg_endpos[0].lnum; } - if (reg_endpos[0].lnum < 0) { - /* pattern has a \ze but it didn't match, use current end */ - reg_endpos[0].lnum = reglnum; - reg_endpos[0].col = (int)(reginput - regline); - } else - /* Use line number of "\ze". */ - reglnum = reg_endpos[0].lnum; } else { for (i = 0; i < subs.norm.in_use; i++) { - reg_startp[i] = subs.norm.list.line[i].start; - reg_endp[i] = subs.norm.list.line[i].end; + rex.reg_startp[i] = subs.norm.list.line[i].start; + rex.reg_endp[i] = subs.norm.list.line[i].end; } - if (reg_startp[0] == NULL) - reg_startp[0] = regline + col; - if (reg_endp[0] == NULL) - reg_endp[0] = reginput; + if (rex.reg_startp[0] == NULL) { + rex.reg_startp[0] = regline + col; + } + if (rex.reg_endp[0] == NULL) { + rex.reg_endp[0] = reginput; + } } /* Package any found \z(...\) matches for export. Default is none. */ @@ -6332,14 +6357,14 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm) colnr_T col = startcol; if (REG_MULTI) { - prog = (nfa_regprog_T *)reg_mmatch->regprog; - line = reg_getline((linenr_T)0); /* relative to the cursor */ - reg_startpos = reg_mmatch->startpos; - reg_endpos = reg_mmatch->endpos; + prog = (nfa_regprog_T *)rex.reg_mmatch->regprog; + line = 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 *)reg_match->regprog; - reg_startp = reg_match->startp; - reg_endp = reg_match->endp; + prog = (nfa_regprog_T *)rex.reg_match->regprog; + rex.reg_startp = rex.reg_match->startp; + rex.reg_endp = rex.reg_match->endp; } /* Be paranoid... */ @@ -6348,15 +6373,17 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm) goto theend; } - /* If pattern contains "\c" or "\C": overrule value of ireg_ic */ - if (prog->regflags & RF_ICASE) - ireg_ic = TRUE; - else if (prog->regflags & RF_NOICASE) - ireg_ic = FALSE; + // If pattern contains "\c" or "\C": overrule value of rex.reg_ic + if (prog->regflags & RF_ICASE) { + rex.reg_ic = true; + } else if (prog->regflags & RF_NOICASE) { + rex.reg_ic = false; + } - /* If pattern contains "\Z" overrule value of ireg_icombine */ - if (prog->regflags & RF_ICOMBINE) - ireg_icombine = TRUE; + // If pattern contains "\Z" overrule value of rex.reg_icombine + if (prog->regflags & RF_ICOMBINE) { + rex.reg_icombine = true; + } regline = line; reglnum = 0; /* relative to line */ @@ -6385,17 +6412,17 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm) if (skip_to_start(prog->regstart, &col) == FAIL) return 0L; - /* If match_text is set it contains the full text that must match. - * Nothing else to try. Doesn't handle combining chars well. */ - if (prog->match_text != NULL - && !ireg_icombine - ) + // If match_text is set it contains the full text that must match. + // Nothing else to try. Doesn't handle combining chars well. + if (prog->match_text != NULL && !rex.reg_icombine) { return find_match_text(col, prog->regstart, prog->match_text); + } } - /* If the start column is past the maximum column: no need to try. */ - if (ireg_maxcol > 0 && col >= ireg_maxcol) + // If the start column is past the maximum column: no need to try. + if (rex.reg_maxcol > 0 && col >= rex.reg_maxcol) { goto theend; + } nstate = prog->nstate; for (i = 0; i < nstate; ++i) { @@ -6547,15 +6574,15 @@ nfa_regexec_nl ( bool line_lbr ) { - reg_match = rmp; - reg_mmatch = NULL; - reg_maxline = 0; - reg_line_lbr = line_lbr; - reg_buf = curbuf; - reg_win = NULL; - ireg_ic = rmp->rm_ic; - ireg_icombine = FALSE; - ireg_maxcol = 0; + rex.reg_match = rmp; + rex.reg_mmatch = NULL; + rex.reg_maxline = 0; + rex.reg_line_lbr = line_lbr; + rex.reg_buf = curbuf; + rex.reg_win = NULL; + rex.reg_ic = rmp->rm_ic; + rex.reg_icombine = false; + rex.reg_maxcol = 0; return nfa_regexec_both(line, col, NULL); } @@ -6596,16 +6623,16 @@ nfa_regexec_nl ( static long nfa_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm) { - reg_match = NULL; - reg_mmatch = rmp; - reg_buf = buf; - reg_win = win; - reg_firstlnum = lnum; - reg_maxline = reg_buf->b_ml.ml_line_count - lnum; - reg_line_lbr = FALSE; - ireg_ic = rmp->rmm_ic; - ireg_icombine = FALSE; - ireg_maxcol = rmp->rmm_maxcol; + rex.reg_match = NULL; + rex.reg_mmatch = rmp; + rex.reg_buf = buf; + rex.reg_win = win; + rex.reg_firstlnum = lnum; + rex.reg_maxline = rex.reg_buf->b_ml.ml_line_count - lnum; + rex.reg_line_lbr = false; + rex.reg_ic = rmp->rmm_ic; + rex.reg_icombine = false; + rex.reg_maxcol = rmp->rmm_maxcol; return nfa_regexec_both(NULL, col, tm); } diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 41acc48f97..95973354bc 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -1,3 +1,6 @@ +// 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 + /* * screen.c: code for displaying on the screen * @@ -83,6 +86,7 @@ #include <stdbool.h> #include <string.h> +#include "nvim/log.h" #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/arabic.h" @@ -102,6 +106,7 @@ #include "nvim/indent.h" #include "nvim/getchar.h" #include "nvim/main.h" +#include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" @@ -128,6 +133,7 @@ #include "nvim/version.h" #include "nvim/window.h" #include "nvim/os/time.h" +#include "nvim/api/private/helpers.h" #define MB_FILLER_CHAR '<' /* character used when a double-width character * doesn't fit. */ @@ -150,7 +156,6 @@ static schar_T *current_ScreenLine; StlClickDefinition *tab_page_click_defs = NULL; long tab_page_click_defs_size = 0; -# define SCREEN_LINE(r, o, e, c, rl) screen_line((r), (o), (e), (c), (rl)) #ifdef INCLUDE_GENERATED_DECLARATIONS # include "screen.c.generated.h" #endif @@ -375,15 +380,24 @@ void update_screen(int type) )) curwin->w_redr_type = type; - /* Redraw the tab pages line if needed. */ - if (redraw_tabline || type >= NOT_VALID) + // Redraw the tab pages line if needed. + if (redraw_tabline || type >= NOT_VALID) { + update_window_hl(curwin, type >= NOT_VALID); + FOR_ALL_TABS(tp) { + if (tp != curtab) { + update_window_hl(tp->tp_curwin, type >= NOT_VALID); + } + } draw_tabline(); + } /* * Correct stored syntax highlighting info for changes in each displayed * buffer. Each buffer must only be done once. */ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + update_window_hl(wp, type >= NOT_VALID); + if (wp->w_buffer->b_mod_set) { win_T *wwp; @@ -487,9 +501,10 @@ void update_single_line(win_T *wp, linenr_T lnum) int j; // Don't do anything if the screen structures are (not yet) valid. - if (!screen_valid(true)) { + if (!screen_valid(true) || updating_screen) { return; } + updating_screen = true; if (lnum >= wp->w_topline && lnum < wp->w_botline && foldedCount(wp, lnum, &win_foldinfo) == 0) { @@ -506,7 +521,8 @@ void update_single_line(win_T *wp, linenr_T lnum) row += wp->w_lines[j].wl_size; } } - need_cursor_line_redraw = FALSE; + need_cursor_line_redraw = false; + updating_screen = false; } @@ -976,7 +992,7 @@ static void win_update(win_T *wp) * first. */ if (mid_start == 0) { mid_end = wp->w_height; - if (lastwin == firstwin) { + if (ONE_WINDOW) { /* Clear the screen when it was not done by win_del_lines() or * win_ins_lines() above, "screen_cleared" is FALSE or MAYBE * then. */ @@ -1013,14 +1029,10 @@ static void win_update(win_T *wp) linenr_T from, to; if (VIsual_active) { - if (VIsual_active - && (VIsual_mode != wp->w_old_visual_mode - || type == INVERTED_ALL)) { - /* - * If the type of Visual selection changed, redraw the whole - * selection. Also when the ownership of the X selection is - * gained or lost. - */ + if (VIsual_mode != wp->w_old_visual_mode || type == INVERTED_ALL) { + // If the type of Visual selection changed, redraw the whole + // selection. Also when the ownership of the X selection is + // gained or lost. if (curwin->w_cursor.lnum < VIsual.lnum) { from = curwin->w_cursor.lnum; to = VIsual.lnum; @@ -1485,11 +1497,11 @@ static void win_update(win_T *wp) // Last line isn't finished: Display "@@@" in the last screen line. screen_puts_len((char_u *)"@@", 2, scr_row, wp->w_wincol, - hl_attr(HLF_AT)); + win_hl_attr(wp, HLF_AT)); screen_fill(scr_row, scr_row + 1, (int)wp->w_wincol + 2, (int)W_ENDCOL(wp), - '@', ' ', hl_attr(HLF_AT)); + '@', ' ', win_hl_attr(wp, HLF_AT)); set_empty_rows(wp, srow); wp->w_botline = lnum; } else if (dy_flags & DY_LASTLINE) { // 'display' has "lastline" @@ -1497,7 +1509,7 @@ static void win_update(win_T *wp) screen_fill(wp->w_winrow + wp->w_height - 1, wp->w_winrow + wp->w_height, W_ENDCOL(wp) - 3, W_ENDCOL(wp), - '@', '@', hl_attr(HLF_AT)); + '@', '@', win_hl_attr(wp, HLF_AT)); set_empty_rows(wp, srow); wp->w_botline = lnum; } else { @@ -1581,6 +1593,8 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h # define FDC_OFF n int fdc = compute_foldcolumn(wp, 0); + int attr = win_hl_attr(wp, hl); + if (wp->w_p_rl) { // No check for cmdline window: should never be right-left. n = fdc; @@ -1591,7 +1605,7 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h n = wp->w_width; screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, W_ENDCOL(wp) - n, W_ENDCOL(wp), - ' ', ' ', hl_attr(HLF_FC)); + ' ', ' ', win_hl_attr(wp, HLF_FC)); } if (signcolumn_on(wp)) { @@ -1603,16 +1617,16 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h } screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, W_ENDCOL(wp) - nn, W_ENDCOL(wp) - n, - ' ', ' ', hl_attr(HLF_SC)); + ' ', ' ', win_hl_attr(wp, HLF_SC)); n = nn; } screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, wp->w_wincol, W_ENDCOL(wp) - 1 - FDC_OFF, - c2, c2, hl_attr(hl)); + c2, c2, attr); screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, W_ENDCOL(wp) - 1 - FDC_OFF, W_ENDCOL(wp) - FDC_OFF, - c1, c2, hl_attr(hl)); + c1, c2, attr); } else { if (cmdwin_type != 0 && wp == curwin) { /* draw the cmdline character in the leftmost column */ @@ -1621,7 +1635,7 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h n = wp->w_width; screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, wp->w_wincol, wp->w_wincol + n, - cmdwin_type, ' ', hl_attr(HLF_AT)); + cmdwin_type, ' ', win_hl_attr(wp, HLF_AT)); } if (fdc > 0) { int nn = n + fdc; @@ -1631,7 +1645,7 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h nn = wp->w_width; screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, wp->w_wincol + n, wp->w_wincol + nn, - ' ', ' ', hl_attr(HLF_FC)); + ' ', ' ', win_hl_attr(wp, HLF_FC)); n = nn; } @@ -1644,13 +1658,13 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h } screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, wp->w_wincol + n, wp->w_wincol + nn, - ' ', ' ', hl_attr(HLF_SC)); + ' ', ' ', win_hl_attr(wp, HLF_SC)); n = nn; } screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, wp->w_wincol + FDC_OFF, W_ENDCOL(wp), - c1, c2, hl_attr(hl)); + c1, c2, attr); } set_empty_rows(wp, row); } @@ -1685,7 +1699,7 @@ static int compute_foldcolumn(win_T *wp, int col) */ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T lnum, int row) { - char_u buf[51]; + char_u buf[FOLD_TEXT_LEN]; pos_T *top, *bot; linenr_T lnume = lnum + fold_count - 1; int len; @@ -1712,10 +1726,9 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T */ if (cmdwin_type != 0 && wp == curwin) { ScreenLines[off] = cmdwin_type; - ScreenAttrs[off] = hl_attr(HLF_AT); - if (enc_utf8) - ScreenLinesUC[off] = 0; - ++col; + ScreenAttrs[off] = win_hl_attr(wp, HLF_AT); + ScreenLinesUC[off] = 0; + col++; } // 2. Add the 'foldcolumn' @@ -1727,12 +1740,14 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T int i; copy_text_attr(off + wp->w_width - fdc - col, buf, fdc, - hl_attr(HLF_FC)); - /* reverse the fold column */ - for (i = 0; i < fdc; ++i) + win_hl_attr(wp, HLF_FC)); + // reverse the fold column + for (i = 0; i < fdc; i++) { ScreenLines[off + wp->w_width - i - 1 - col] = buf[i]; - } else - copy_text_attr(off + col, buf, fdc, hl_attr(HLF_FC)); + } + } else { + copy_text_attr(off + col, buf, fdc, win_hl_attr(wp, HLF_FC)); + } col += fdc; } @@ -1745,7 +1760,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T /* Set all attributes of the 'number' or 'relativenumber' column and the * text */ - RL_MEMSET(col, hl_attr(HLF_FL), wp->w_width - col); + RL_MEMSET(col, win_hl_attr(wp, HLF_FL), wp->w_width - col); // If signs are being displayed, add two spaces. if (signcolumn_on(wp)) { @@ -1754,7 +1769,8 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T if (len > 2) { len = 2; } - copy_text_attr(off + col, (char_u *)" ", len, hl_attr(HLF_FL)); + copy_text_attr(off + col, (char_u *)" ", len, + win_hl_attr(wp, HLF_FL)); col += len; } } @@ -1786,13 +1802,14 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T } } - sprintf((char *)buf, fmt, w, num); - if (wp->w_p_rl) - /* the line number isn't reversed */ + snprintf((char *)buf, FOLD_TEXT_LEN, fmt, w, num); + if (wp->w_p_rl) { + // the line number isn't reversed copy_text_attr(off + wp->w_width - len - col, buf, len, - hl_attr(HLF_FL)); - else - copy_text_attr(off + col, buf, len, hl_attr(HLF_FL)); + win_hl_attr(wp, HLF_FL)); + } else { + copy_text_attr(off + col, buf, len, win_hl_attr(wp, HLF_FL)); + } col += len; } } @@ -1907,10 +1924,15 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T if (fill_fold >= 0x80) { ScreenLinesUC[off + col] = fill_fold; ScreenLinesC[0][off + col] = 0; - } else + ScreenLines[off + col] = 0x80; // avoid storing zero + } else { ScreenLinesUC[off + col] = 0; + ScreenLines[off + col] = fill_fold; + } + col++; + } else { + ScreenLines[off + col++] = fill_fold; } - ScreenLines[off + col++] = fill_fold; } if (text != buf) @@ -1950,12 +1972,12 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T len = wp->w_old_cursor_lcol; else len = wp->w_width - txtcol; - RL_MEMSET(wp->w_old_cursor_fcol + txtcol, hl_attr(HLF_V), - len - (int)wp->w_old_cursor_fcol); + RL_MEMSET(wp->w_old_cursor_fcol + txtcol, win_hl_attr(wp, HLF_V), + len - (int)wp->w_old_cursor_fcol); } } else { - /* Set all attributes of the text */ - RL_MEMSET(txtcol, hl_attr(HLF_V), wp->w_width - txtcol); + // Set all attributes of the text + RL_MEMSET(txtcol, win_hl_attr(wp, HLF_V), wp->w_width - txtcol); } } } @@ -1975,7 +1997,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T } if (txtcol >= 0 && txtcol < wp->w_width) { ScreenAttrs[off + txtcol] = - hl_combine_attr(ScreenAttrs[off + txtcol], hl_attr(HLF_MC)); + hl_combine_attr(ScreenAttrs[off + txtcol], win_hl_attr(wp, HLF_MC)); } txtcol = old_txtcol; j = wp->w_p_cc_cols[++i]; @@ -1991,11 +2013,11 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T txtcol -= wp->w_leftcol; if (txtcol >= 0 && txtcol < wp->w_width) ScreenAttrs[off + txtcol] = hl_combine_attr( - ScreenAttrs[off + txtcol], hl_attr(HLF_CUC)); + ScreenAttrs[off + txtcol], win_hl_attr(wp, HLF_CUC)); } - SCREEN_LINE(row + wp->w_winrow, wp->w_wincol, wp->w_width, - wp->w_width, FALSE); + screen_line(row + wp->w_winrow, wp->w_wincol, wp->w_width, + wp->w_width, false, wp); /* * Update w_cline_height and w_cline_folded if the cursor line was @@ -2095,16 +2117,16 @@ win_line ( bool nochange /* not updating for changed text */ ) { - int col; /* visual column on screen */ - unsigned off; /* offset in ScreenLines/ScreenAttrs */ - int c = 0; /* init for GCC */ - long vcol = 0; /* virtual column (for tabs) */ + int col = 0; // visual column on screen + unsigned off; // offset in ScreenLines/ScreenAttrs + int c = 0; // init for GCC + long vcol = 0; // virtual column (for tabs) long vcol_sbr = -1; // virtual column after showbreak - long vcol_prev = -1; /* "vcol" of previous character */ - char_u *line; /* current line */ - char_u *ptr; /* current position in "line" */ - int row; /* row in the window, excl w_winrow */ - int screen_row; /* row on the screen, incl w_winrow */ + long vcol_prev = -1; // "vcol" of previous character + char_u *line; // current line + char_u *ptr; // current position in "line" + int row; // row in the window, excl w_winrow + int screen_row; // row on the screen, incl w_winrow char_u extra[18]; /* line number and 'fdc' must fit in here */ int n_extra = 0; /* number of extra chars */ @@ -2178,7 +2200,7 @@ win_line ( int change_start = MAXCOL; /* first col of changed area */ int change_end = -1; /* last col of changed area */ colnr_T trailcol = MAXCOL; /* start of trailing spaces */ - int need_showbreak = FALSE; + int need_showbreak = false; // overlong line, skip first x chars int line_attr = 0; /* attribute for the whole line */ matchitem_T *cur; /* points to the match list */ match_T *shl; /* points to search_hl or a match */ @@ -2191,9 +2213,10 @@ win_line ( int prev_c1 = 0; /* first composing char for prev_c */ int did_line_attr = 0; - bool has_bufhl = false; // this buffer has highlight matches + bool search_attr_from_match = false; // if search_attr is from :match + bool has_bufhl = false; // this buffer has highlight matches int bufhl_attr = 0; // attributes desired by bufhl - bufhl_lineinfo_T bufhl_info; // bufhl data for this line + BufhlLineInfo bufhl_info; // bufhl data for this line /* draw_state: items that are drawn in sequence: */ #define WL_START 0 /* nothing done yet */ @@ -2209,7 +2232,7 @@ win_line ( int syntax_flags = 0; int syntax_seqnr = 0; int prev_syntax_id = 0; - int conceal_attr = hl_attr(HLF_CONCEAL); + int conceal_attr = win_hl_attr(wp, HLF_CONCEAL); int is_concealing = false; int boguscols = 0; ///< nonexistent columns added to ///< force wrapping @@ -2357,8 +2380,8 @@ win_line ( /* if inverting in this line set area_highlighting */ if (fromcol >= 0) { - area_highlighting = TRUE; - attr = hl_attr(HLF_V); + area_highlighting = true; + attr = win_hl_attr(wp, HLF_V); } } /* @@ -2382,8 +2405,8 @@ win_line ( /* do at least one character; happens when past end of line */ if (fromcol == tocol) tocol = fromcol + 1; - area_highlighting = TRUE; - attr = hl_attr(HLF_I); + area_highlighting = true; + attr = win_hl_attr(wp, HLF_I); } filler_lines = diff_check(wp, lnum); @@ -2411,7 +2434,11 @@ win_line ( // Highlight the current line in the quickfix window. if (bt_quickfix(wp->w_buffer) && qf_current_entry(wp) == lnum) { - line_attr = hl_attr(HLF_QFL); + line_attr = win_hl_attr(wp, HLF_QFL); + } + + if (wp->w_hl_attr_normal != 0) { + line_attr = hl_combine_attr(wp->w_hl_attr_normal, line_attr); } if (line_attr != 0) { @@ -2445,7 +2472,7 @@ win_line ( } else { /* Long line, use only the last SPWORDLEN bytes. */ nextlinecol = v - SPWORDLEN; - memmove(nextline, line + nextlinecol, SPWORDLEN); + memmove(nextline, line + nextlinecol, SPWORDLEN); // -V512 nextline_idx = SPWORDLEN + 1; } } @@ -2500,7 +2527,11 @@ win_line ( if (vcol > v) { vcol -= c; ptr = prev_ptr; - n_skip = v - vcol; + // If the character fits on the screen, don't need to skip it. + // Except for a TAB. + if (((*mb_ptr2cells)(ptr) >= c || *ptr == TAB) && col == 0) { + n_skip = v - vcol; + } } /* @@ -2577,13 +2608,14 @@ win_line ( * Do this for both search_hl and the match list. */ cur = wp->w_match_head; - shl_flag = FALSE; - while (cur != NULL || shl_flag == FALSE) { - if (shl_flag == FALSE) { + shl_flag = false; + while (cur != NULL || !shl_flag) { + if (!shl_flag) { shl = &search_hl; - shl_flag = TRUE; - } else - shl = &cur->hl; + shl_flag = true; + } else { + shl = &cur->hl; // -V595 + } shl->startcol = MAXCOL; shl->endcol = MAXCOL; shl->attr_cur = 0; @@ -2623,6 +2655,7 @@ win_line ( if ((long)shl->startcol < v) { // match at leftcol shl->attr_cur = shl->attr; search_attr = shl->attr; + search_attr_from_match = shl != &search_hl; } area_highlighting = true; } @@ -2637,9 +2670,9 @@ win_line ( && !(wp == curwin && VIsual_active)) { if (line_attr != 0 && !(State & INSERT) && bt_quickfix(wp->w_buffer) && qf_current_entry(wp) == lnum) { - line_attr = hl_combine_attr(hl_attr(HLF_CUL), line_attr); + line_attr = hl_combine_attr(win_hl_attr(wp, HLF_CUL), line_attr); } else { - line_attr = hl_attr(HLF_CUL); + line_attr = win_hl_attr(wp, HLF_CUL); } area_highlighting = true; } @@ -2672,7 +2705,7 @@ win_line ( /* Draw the cmdline character. */ n_extra = 1; c_extra = cmdwin_type; - char_attr = hl_attr(HLF_AT); + char_attr = win_hl_attr(wp, HLF_AT); } } @@ -2681,13 +2714,16 @@ win_line ( draw_state = WL_FOLD; if (fdc > 0) { - // Draw the 'foldcolumn'. - fill_foldcolumn(extra, wp, false, lnum); + // Draw the 'foldcolumn'. Allocate a buffer, "extra" may + // already be in use. + xfree(p_extra_free); + p_extra_free = xmalloc(12 + 1); + fill_foldcolumn(p_extra_free, wp, false, lnum); n_extra = fdc; - p_extra = extra; - p_extra[n_extra] = NUL; + p_extra_free[n_extra] = NUL; + p_extra = p_extra_free; c_extra = NUL; - char_attr = hl_attr(HLF_FC); + char_attr = win_hl_attr(wp, HLF_FC); } } @@ -2700,7 +2736,7 @@ win_line ( int text_sign; /* Draw two cells with the sign value or blank. */ c_extra = ' '; - char_attr = hl_attr(HLF_SC); + char_attr = win_hl_attr(wp, HLF_SC); n_extra = 2; if (row == startrow + filler_lines && filler_todo <= 0) { @@ -2757,14 +2793,15 @@ win_line ( } else c_extra = ' '; n_extra = number_width(wp) + 1; - char_attr = hl_attr(HLF_N); - /* When 'cursorline' is set highlight the line number of - * the current line differently. - * TODO: Can we use CursorLine instead of CursorLineNr - * when CursorLineNr isn't set? */ + char_attr = win_hl_attr(wp, HLF_N); + // When 'cursorline' is set highlight the line number of + // the current line differently. + // TODO(vim): Can we use CursorLine instead of CursorLineNr + // when CursorLineNr isn't set? if ((wp->w_p_cul || wp->w_p_rnu) - && lnum == wp->w_cursor.lnum) - char_attr = hl_attr(HLF_CLN); + && lnum == wp->w_cursor.lnum) { + char_attr = win_hl_attr(wp, HLF_CLN); + } } } @@ -2780,13 +2817,15 @@ win_line ( // draw 'breakindent': indent wrapped text accodringly if (draw_state == WL_BRI - 1 && n_extra == 0) { draw_state = WL_BRI; - if (wp->w_p_bri && n_extra == 0 && row != startrow && filler_lines == 0) { - char_attr = 0; // was: hl_attr(HLF_AT); + // if need_showbreak is set, breakindent also applies + if (wp->w_p_bri && (row != startrow || need_showbreak) + && filler_lines == 0) { + char_attr = wp->w_hl_attr_normal; if (diff_hlf != (hlf_T)0) { - char_attr = hl_attr(diff_hlf); + char_attr = win_hl_attr(wp, diff_hlf); if (wp->w_p_cul && lnum == wp->w_cursor.lnum) { - char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUL)); + char_attr = hl_combine_attr(char_attr, win_hl_attr(wp, HLF_CUL)); } } p_extra = NULL; @@ -2811,15 +2850,15 @@ win_line ( n_extra = col + 1; else n_extra = wp->w_width - col; - char_attr = hl_attr(HLF_DED); + char_attr = win_hl_attr(wp, HLF_DED); } if (*p_sbr != NUL && need_showbreak) { /* Draw 'showbreak' at the start of each broken line. */ p_extra = p_sbr; c_extra = NUL; n_extra = (int)STRLEN(p_sbr); - char_attr = hl_attr(HLF_AT); - need_showbreak = FALSE; + char_attr = win_hl_attr(wp, HLF_AT); + need_showbreak = false; vcol_sbr = vcol + MB_CHARLEN(p_sbr); /* Correct end of highlighted area for 'showbreak', * required when 'linebreak' is also set. */ @@ -2827,7 +2866,7 @@ win_line ( tocol += n_extra; /* combine 'showbreak' with 'cursorline' */ if (wp->w_p_cul && lnum == wp->w_cursor.lnum) { - char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUL)); + char_attr = hl_combine_attr(char_attr, win_hl_attr(wp, HLF_CUL)); } } } @@ -2840,8 +2879,9 @@ win_line ( c_extra = saved_c_extra; p_extra = saved_p_extra; char_attr = saved_char_attr; - } else - char_attr = 0; + } else { + char_attr = wp->w_hl_attr_normal; + } } } @@ -2850,13 +2890,14 @@ win_line ( && lnum == wp->w_cursor.lnum && vcol >= (long)wp->w_virtcol && filler_todo <= 0 ) { - SCREEN_LINE(screen_row, wp->w_wincol, col, -wp->w_width, wp->w_p_rl); - /* Pretend we have finished updating the window. Except when - * 'cursorcolumn' is set. */ - if (wp->w_p_cuc) + screen_line(screen_row, wp->w_wincol, col, -wp->w_width, wp->w_p_rl, wp); + // Pretend we have finished updating the window. Except when + // 'cursorcolumn' is set. + if (wp->w_p_cuc) { row = wp->w_cline_row + wp->w_cline_height; - else + } else { row = wp->w_height; + } break; } @@ -2920,7 +2961,6 @@ win_line ( } } else if (v == (long)shl->endcol) { shl->attr_cur = 0; - prev_syntax_id = 0; next_search_hl(wp, shl, lnum, (colnr_T)v, shl == &search_hl ? NULL : cur); @@ -2961,6 +3001,7 @@ win_line ( /* Use attributes from match with highest priority among * 'search_hl' and the match list. */ + search_attr_from_match = false; search_attr = search_hl.attr_cur; cur = wp->w_match_head; shl_flag = FALSE; @@ -2973,8 +3014,10 @@ win_line ( shl_flag = TRUE; } else shl = &cur->hl; - if (shl->attr_cur != 0) + if (shl->attr_cur != 0) { search_attr = shl->attr_cur; + search_attr_from_match = shl != &search_hl; + } if (shl != &search_hl && cur != NULL) cur = cur->next; } @@ -2982,14 +3025,16 @@ win_line ( if (diff_hlf != (hlf_T)0) { if (diff_hlf == HLF_CHD && ptr - line >= change_start - && n_extra == 0) - diff_hlf = HLF_TXD; /* changed text */ + && n_extra == 0) { + diff_hlf = HLF_TXD; // changed text + } if (diff_hlf == HLF_TXD && ptr - line > change_end - && n_extra == 0) - diff_hlf = HLF_CHD; /* changed line */ - line_attr = hl_attr(diff_hlf); + && n_extra == 0) { + diff_hlf = HLF_CHD; // changed line + } + line_attr = win_hl_attr(wp, diff_hlf); if (wp->w_p_cul && lnum == wp->w_cursor.lnum) { - line_attr = hl_combine_attr(line_attr, hl_attr(HLF_CUL)); + line_attr = hl_combine_attr(line_attr, win_hl_attr(wp, HLF_CUL)); } } @@ -3005,14 +3050,15 @@ win_line ( // (area_attr may be 0 when "noinvcur" is set). else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL) || vcol < fromcol || vcol_prev < fromcol_prev - || vcol >= tocol)) + || vcol >= tocol)) { char_attr = line_attr; - else { - attr_pri = FALSE; - if (has_syntax) + } else { + attr_pri = false; + if (has_syntax) { char_attr = syntax_attr; - else - char_attr = 0; + } else { + char_attr = wp->w_hl_attr_normal; + } } } @@ -3073,12 +3119,13 @@ win_line ( c = '>'; mb_c = c; mb_l = 1; - mb_utf8 = FALSE; - multi_attr = hl_attr(HLF_AT); - /* put the pointer back to output the double-width - * character at the start of the next line. */ - ++n_extra; - --p_extra; + mb_utf8 = false; + multi_attr = win_hl_attr(wp, HLF_AT); + + // put the pointer back to output the double-width + // character at the start of the next line. + n_extra++; + p_extra--; } else { n_extra -= mb_l - 1; p_extra += mb_l - 1; @@ -3135,14 +3182,14 @@ win_line ( p_extra = extra; c = *p_extra; - mb_c = mb_ptr2char_adv(&p_extra); + mb_c = mb_ptr2char_adv((const char_u **)&p_extra); mb_utf8 = (c >= 0x80); n_extra = (int)STRLEN(p_extra); c_extra = NUL; if (area_attr == 0 && search_attr == 0) { n_attr = n_extra + 1; - extra_attr = hl_attr(HLF_8); - saved_attr2 = char_attr; /* save current attr */ + extra_attr = win_hl_attr(wp, HLF_8); + saved_attr2 = char_attr; // save current attr } } else if (mb_l == 0) /* at the NUL at end-of-line */ mb_l = 1; @@ -3194,8 +3241,8 @@ win_line ( c = *p_extra++; if (area_attr == 0 && search_attr == 0) { n_attr = n_extra + 1; - extra_attr = hl_attr(HLF_8); - saved_attr2 = char_attr; /* save current attr */ + extra_attr = win_hl_attr(wp, HLF_8); + saved_attr2 = char_attr; // save current attr } mb_c = c; } @@ -3212,12 +3259,13 @@ win_line ( mb_c = c; mb_utf8 = FALSE; mb_l = 1; - multi_attr = hl_attr(HLF_AT); - /* Put pointer back so that the character will be - * displayed at the start of the next line. */ - --ptr; - } else if (*ptr != NUL) + multi_attr = win_hl_attr(wp, HLF_AT); + // Put pointer back so that the character will be + // displayed at the start of the next line. + ptr--; + } else if (*ptr != NUL) { ptr += mb_l - 1; + } /* If a double-width char doesn't fit at the left side display * a '<' in the first column. Don't do this for unprintable @@ -3228,8 +3276,8 @@ win_line ( c = ' '; if (area_attr == 0 && search_attr == 0) { n_attr = n_extra + 1; - extra_attr = hl_attr(HLF_AT); - saved_attr2 = char_attr; /* save current attr */ + extra_attr = win_hl_attr(wp, HLF_AT); + saved_attr2 = char_attr; // save current attr } mb_c = c; mb_utf8 = FALSE; @@ -3277,7 +3325,7 @@ win_line ( else syntax_flags = get_syntax_info(&syntax_seqnr); } else if (!attr_pri) { - char_attr = 0; + char_attr = wp->w_hl_attr_normal; } /* Check spelling (unless at the end of the line). @@ -3403,7 +3451,7 @@ win_line ( || (c == ' ' && lcs_space && ptr - line <= trailcol))) { c = (c == ' ') ? lcs_space : lcs_nbsp; n_attr = 1; - extra_attr = hl_attr(HLF_8); + extra_attr = win_hl_attr(wp, HLF_0); saved_attr2 = char_attr; // save current attr mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { @@ -3418,7 +3466,7 @@ win_line ( if (trailcol != MAXCOL && ptr > line + trailcol && c == ' ') { c = lcs_trail; n_attr = 1; - extra_attr = hl_attr(HLF_8); + extra_attr = win_hl_attr(wp, HLF_0); saved_attr2 = char_attr; // save current attr mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { @@ -3476,6 +3524,7 @@ win_line ( p = xmalloc(len + 1); memset(p, ' ', len); p[len] = NUL; + xfree(p_extra_free); p_extra_free = p; for (i = 0; i < tab_len; i++) { mb_char2bytes(lcs_tab2, p); @@ -3519,8 +3568,8 @@ win_line ( c_extra = lcs_tab2; } n_attr = tab_len + 1; - extra_attr = hl_attr(HLF_8); - saved_attr2 = char_attr; /* save current attr */ + extra_attr = win_hl_attr(wp, HLF_0); + saved_attr2 = char_attr; // save current attr mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { mb_utf8 = TRUE; @@ -3566,7 +3615,7 @@ win_line ( } lcs_eol_one = -1; ptr--; // put it back at the NUL - extra_attr = hl_attr(HLF_AT); + extra_attr = win_hl_attr(wp, HLF_AT); n_attr = 1; mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { @@ -3591,13 +3640,14 @@ win_line ( memset(p, ' ', n_extra); STRNCPY(p, p_extra + 1, STRLEN(p_extra) - 1); p[n_extra] = NUL; + xfree(p_extra_free); p_extra_free = p_extra = p; } else { n_extra = byte2cells(c) - 1; c = *p_extra++; } n_attr = n_extra + 1; - extra_attr = hl_attr(HLF_8); + extra_attr = win_hl_attr(wp, HLF_8); saved_attr2 = char_attr; // save current attr mb_utf8 = false; // don't draw as UTF-8 } else if (VIsual_active @@ -3629,9 +3679,10 @@ win_line ( if (diff_hlf == HLF_TXD) { diff_hlf = HLF_CHD; if (attr == 0 || char_attr != attr) { - char_attr = hl_attr(diff_hlf); + char_attr = win_hl_attr(wp, diff_hlf); if (wp->w_p_cul && lnum == wp->w_cursor.lnum) { - char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUL)); + char_attr = hl_combine_attr(char_attr, + win_hl_attr(wp, HLF_CUL)); } } } @@ -3710,7 +3761,7 @@ win_line ( } // Don't override visual selection highlighting. - if (n_attr > 0 && draw_state == WL_LINE) { + if (n_attr > 0 && draw_state == WL_LINE && !search_attr_from_match) { char_attr = hl_combine_attr(char_attr, extra_attr); } @@ -3733,7 +3784,7 @@ win_line ( c_extra = MB_FILLER_CHAR; n_extra = 1; n_attr = 2; - extra_attr = hl_attr(HLF_AT); + extra_attr = win_hl_attr(wp, HLF_AT); } mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { @@ -3744,7 +3795,7 @@ win_line ( mb_utf8 = false; // don't draw as UTF-8 } saved_attr3 = char_attr; // save current attr - char_attr = hl_attr(HLF_AT); // later copied to char_attr + char_attr = win_hl_attr(wp, HLF_AT); // overwriting char_attr n_attr3 = 1; } @@ -3828,6 +3879,10 @@ win_line ( } } } + + if (wp->w_hl_attr_normal != 0) { + char_attr = hl_combine_attr(wp->w_hl_attr_normal, char_attr); + } ScreenAttrs[off] = char_attr; if (wp->w_p_rl) { --col; @@ -3889,6 +3944,9 @@ win_line ( if (rightmost_vcol < color_cols[i]) rightmost_vcol = color_cols[i]; + int cuc_attr = win_hl_attr(wp, HLF_CUC); + int mc_attr = win_hl_attr(wp, HLF_MC); + while (col < wp->w_width) { ScreenLines[off] = ' '; if (enc_utf8) @@ -3898,12 +3956,13 @@ win_line ( draw_color_col = advance_color_col(VCOL_HLC, &color_cols); - if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol) - ScreenAttrs[off++] = hl_attr(HLF_CUC); - else if (draw_color_col && VCOL_HLC == *color_cols) - ScreenAttrs[off++] = hl_attr(HLF_MC); - else - ScreenAttrs[off++] = 0; + if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol) { + ScreenAttrs[off++] = cuc_attr; + } else if (draw_color_col && VCOL_HLC == *color_cols) { + ScreenAttrs[off++] = mc_attr; + } else { + ScreenAttrs[off++] = wp->w_hl_attr_normal; + } if (VCOL_HLC >= rightmost_vcol) break; @@ -3912,6 +3971,7 @@ win_line ( } } + // TODO(bfredl): integrate with the common beyond-the-end-loop if (wp->w_buffer->terminal) { // terminal buffers may need to highlight beyond the end of the // logical line @@ -3924,7 +3984,7 @@ win_line ( col++; } } - SCREEN_LINE(screen_row, wp->w_wincol, col, wp->w_width, wp->w_p_rl); + screen_line(screen_row, wp->w_wincol, col, wp->w_width, wp->w_p_rl, wp); row++; /* @@ -3952,7 +4012,7 @@ win_line ( || (wp->w_p_list && lcs_eol_one > 0) || (n_extra && (c_extra != NUL || *p_extra != NUL)))) { c = lcs_ext; - char_attr = hl_attr(HLF_AT); + char_attr = win_hl_attr(wp, HLF_AT); mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { mb_utf8 = TRUE; @@ -3975,10 +4035,10 @@ win_line ( if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol && lnum != wp->w_cursor.lnum) { vcol_save_attr = char_attr; - char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUC)); + char_attr = hl_combine_attr(char_attr, win_hl_attr(wp, HLF_CUC)); } else if (draw_color_col && VCOL_HLC == *color_cols) { vcol_save_attr = char_attr; - char_attr = hl_combine_attr(char_attr, hl_attr(HLF_MC)); + char_attr = hl_combine_attr(char_attr, win_hl_attr(wp, HLF_MC)); } } @@ -4146,8 +4206,8 @@ win_line ( || (wp->w_p_list && lcs_eol != NUL && p_extra != at_end_str) || (n_extra != 0 && (c_extra != NUL || *p_extra != NUL))) ) { - SCREEN_LINE(screen_row, wp->w_wincol, col - boguscols, - wp->w_width, wp->w_p_rl); + screen_line(screen_row, wp->w_wincol, col - boguscols, + wp->w_width, wp->w_p_rl, wp); boguscols = 0; ++row; ++screen_row; @@ -4187,7 +4247,6 @@ win_line ( * (regardless of the xn,am settings). * Only do this if the cursor is on the current line * (something has been written in it). - * Don't do this for the GUI. * Don't do this for double-width characters. * Don't do this for a window not at the right screen border. */ @@ -4255,6 +4314,7 @@ win_line ( cap_col = 0; } + xfree(p_extra_free); return row; } @@ -4315,7 +4375,8 @@ static int char_needs_redraw(int off_from, int off_to, int cols) * When TRUE and "clear_width" > 0, clear columns 0 to "endcol" * When FALSE and "clear_width" > 0, clear columns "endcol" to "clear_width" */ -static void screen_line(int row, int coloff, int endcol, int clear_width, int rlflag) +static void screen_line(int row, int coloff, int endcol, + int clear_width, int rlflag, win_T *wp) { unsigned off_from; unsigned off_to; @@ -4477,11 +4538,11 @@ static void screen_line(int row, int coloff, int endcol, int clear_width, int rl } if (clear_width > 0) { - /* For a window that's left of another, draw the separator char. */ - if (col + coloff < Columns) { + // For a window that's left of another, draw the separator char. + if (col + coloff < Columns && wp->w_vsep_width > 0) { int c; - c = fillchar_vsep(&hl); + c = fillchar_vsep(wp, &hl); if (ScreenLines[off_to] != (schar_T)c || (enc_utf8 && (int)ScreenLinesUC[off_to] != (c >= 0x80 ? c : 0)) @@ -4586,8 +4647,8 @@ static void draw_vsep_win(win_T *wp, int row) int c; if (wp->w_vsep_width) { - /* draw the vertical separator right of this window */ - c = fillchar_vsep(&hl); + // draw the vertical separator right of this window + c = fillchar_vsep(wp, &hl); screen_fill(wp->w_winrow + row, wp->w_winrow + wp->w_height, W_ENDCOL(wp), W_ENDCOL(wp) + 1, c, ' ', hl); @@ -4717,7 +4778,7 @@ win_redr_status_matches ( --first_match; } - fillchar = fillchar_status(&attr, TRUE); + fillchar = fillchar_status(&attr, curwin); if (first_match == 0) { *buf = NUL; @@ -4831,11 +4892,14 @@ void win_redr_status(win_T *wp) int this_ru_col; static int busy = FALSE; - /* It's possible to get here recursively when 'statusline' (indirectly) - * invokes ":redrawstatus". Simply ignore the call then. */ - if (busy) + // May get here recursively when 'statusline' (indirectly) + // invokes ":redrawstatus". Simply ignore the call then. + if (busy + // Also ignore if wildmenu is showing. + || (wild_menu_showing != 0 && !ui_is_external(kUIWildmenu))) { return; - busy = TRUE; + } + busy = true; wp->w_redr_status = FALSE; if (wp->w_status_height == 0) { @@ -4849,7 +4913,7 @@ void win_redr_status(win_T *wp) /* redraw custom status line */ redraw_custom_statusline(wp); } else { - fillchar = fillchar_status(&attr, wp == curwin); + fillchar = fillchar_status(&attr, wp); get_trans_bufname(wp->w_buffer); p = NameBuff; @@ -4874,37 +4938,34 @@ void win_redr_status(win_T *wp) } if (wp->w_buffer->b_p_ro) { STRCPY(p + len, _("[RO]")); - len += 4; + len += (int)STRLEN(p + len); } this_ru_col = ru_col - (Columns - wp->w_width); - if (this_ru_col < (wp->w_width + 1) / 2) + if (this_ru_col < (wp->w_width + 1) / 2) { this_ru_col = (wp->w_width + 1) / 2; + } if (this_ru_col <= 1) { - p = (char_u *)"<"; /* No room for file name! */ + p = (char_u *)"<"; // No room for file name! len = 1; - } else if (has_mbyte) { + } else { int clen = 0, i; - /* Count total number of display cells. */ - clen = (int) mb_string2cells(p); + // Count total number of display cells. + clen = (int)mb_string2cells(p); - /* Find first character that will fit. - * Going from start to end is much faster for DBCS. */ + // Find first character that will fit. + // Going from start to end is much faster for DBCS. for (i = 0; p[i] != NUL && clen >= this_ru_col - 1; - i += (*mb_ptr2len)(p + i)) + i += (*mb_ptr2len)(p + i)) { clen -= (*mb_ptr2cells)(p + i); + } len = clen; if (i > 0) { p = p + i - 1; *p = '<'; ++len; } - - } else if (len > this_ru_col - 1) { - p += len - (this_ru_col - 1); - *p = '<'; - len = this_ru_col - 1; } row = wp->w_winrow + wp->w_height; @@ -4912,7 +4973,7 @@ void win_redr_status(win_T *wp) screen_fill(row, row + 1, len + wp->w_wincol, this_ru_col + wp->w_wincol, fillchar, fillchar, attr); - if (get_keymap_str(wp, NameBuff, MAXPATHL) + if (get_keymap_str(wp, (char_u *)"<%s>", NameBuff, MAXPATHL) && this_ru_col - len > (int)(STRLEN(NameBuff) + 1)) screen_puts(NameBuff, row, (int)(this_ru_col - STRLEN(NameBuff) - 1 + wp->w_wincol), attr); @@ -4924,10 +4985,11 @@ void win_redr_status(win_T *wp) * May need to draw the character below the vertical separator. */ if (wp->w_vsep_width != 0 && wp->w_status_height != 0 && redrawing()) { - if (stl_connected(wp)) - fillchar = fillchar_status(&attr, wp == curwin); - else - fillchar = fillchar_vsep(&attr); + if (stl_connected(wp)) { + fillchar = fillchar_status(&attr, wp); + } else { + fillchar = fillchar_vsep(wp, &attr); + } screen_putchar(fillchar, wp->w_winrow + wp->w_height, W_ENDCOL(wp), attr); } @@ -4993,8 +5055,9 @@ int stl_connected(win_T *wp) int get_keymap_str ( win_T *wp, - char_u *buf, /* buffer for the result */ - int len /* length of buffer */ + char_u *fmt, // format string containing one %s item + char_u *buf, // buffer for the result + int len // length of buffer ) { char_u *p; @@ -5021,10 +5084,9 @@ get_keymap_str ( else p = (char_u *)"lang"; } - if ((int)(STRLEN(p) + 3) < len) - sprintf((char *)buf, "<%s>", p); - else + if (vim_snprintf((char *)buf, len, (char *)fmt, p) > len - 1) { buf[0] = NUL; + } xfree(s); } return buf[0] != NUL; @@ -5077,7 +5139,7 @@ win_redr_custom ( use_sandbox = was_set_insecurely((char_u *)"tabline", 0); } else { row = wp->w_winrow + wp->w_height; - fillchar = fillchar_status(&attr, wp == curwin); + fillchar = fillchar_status(&attr, wp); maxwidth = wp->w_width; if (draw_ruler) { @@ -5327,43 +5389,39 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr) c = *ptr; /* check if this is the first byte of a multibyte */ if (l_has_mbyte) { - if (l_enc_utf8 && len > 0) + if (len > 0) { mbyte_blen = utfc_ptr2len_len(ptr, (int)((text + len) - ptr)); - else - mbyte_blen = (*mb_ptr2len)(ptr); - if (l_enc_dbcs == DBCS_JPNU && c == 0x8e) - mbyte_cells = 1; - else if (l_enc_dbcs != 0) - mbyte_cells = mbyte_blen; - else { /* enc_utf8 */ - if (len >= 0) - u8c = utfc_ptr2char_len(ptr, u8cc, - (int)((text + len) - ptr)); - else - u8c = utfc_ptr2char(ptr, u8cc); - mbyte_cells = utf_char2cells(u8c); - if (p_arshape && !p_tbidi && arabic_char(u8c)) { - /* Do Arabic shaping. */ - if (len >= 0 && (int)(ptr - text) + mbyte_blen >= len) { - /* Past end of string to be displayed. */ - nc = NUL; - nc1 = NUL; - } else { - nc = utfc_ptr2char_len(ptr + mbyte_blen, pcc, - (int)((text + len) - ptr - mbyte_blen)); - nc1 = pcc[0]; - } - pc = prev_c; - prev_c = u8c; - u8c = arabic_shape(u8c, &c, &u8cc[0], nc, nc1, pc); - } else - prev_c = u8c; - if (col + mbyte_cells > screen_Columns) { - /* Only 1 cell left, but character requires 2 cells: - * display a '>' in the last column to avoid wrapping. */ - c = '>'; - mbyte_cells = 1; + } else { + mbyte_blen = utfc_ptr2len(ptr); + } + if (len >= 0) { + u8c = utfc_ptr2char_len(ptr, u8cc, (int)((text + len) - ptr)); + } else { + u8c = utfc_ptr2char(ptr, u8cc); + } + mbyte_cells = utf_char2cells(u8c); + if (p_arshape && !p_tbidi && arabic_char(u8c)) { + // Do Arabic shaping. + if (len >= 0 && (int)(ptr - text) + mbyte_blen >= len) { + // Past end of string to be displayed. + nc = NUL; + nc1 = NUL; + } else { + nc = utfc_ptr2char_len(ptr + mbyte_blen, pcc, + (int)((text + len) - ptr - mbyte_blen)); + nc1 = pcc[0]; } + pc = prev_c; + prev_c = u8c; + u8c = arabic_shape(u8c, &c, &u8cc[0], nc, nc1, pc); + } else { + prev_c = u8c; + } + if (col + mbyte_cells > screen_Columns) { + // Only 1 cell left, but character requires 2 cells: + // display a '>' in the last column to avoid wrapping. */ + c = '>'; + mbyte_cells = 1; } } @@ -5371,16 +5429,11 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr) force_redraw_next = FALSE; need_redraw = ScreenLines[off] != c - || (mbyte_cells == 2 - && ScreenLines[off + 1] != (l_enc_dbcs ? ptr[1] : 0)) - || (l_enc_dbcs == DBCS_JPNU - && c == 0x8e - && ScreenLines2[off] != ptr[1]) - || (l_enc_utf8 - && (ScreenLinesUC[off] != - (u8char_T)(c < 0x80 && u8cc[0] == 0 ? 0 : u8c) - || (ScreenLinesUC[off] != 0 - && screen_comp_differs(off, u8cc)))) + || (mbyte_cells == 2 && ScreenLines[off + 1] != 0) + || (ScreenLinesUC[off] != + (u8char_T)(c < 0x80 && u8cc[0] == 0 ? 0 : u8c) + || (ScreenLinesUC[off] != 0 + && screen_comp_differs(off, u8cc))) || ScreenAttrs[off] != attr || exmode_active; @@ -5471,8 +5524,7 @@ static void start_search_hl(void) { if (p_hls && !no_hlsearch) { last_pat_prog(&search_hl.rm); - search_hl.attr = hl_attr(HLF_L); - /* Set the time limit to 'redrawtime'. */ + // Set the time limit to 'redrawtime'. search_hl.tm = profile_setlimit(p_rdt); } } @@ -5488,6 +5540,42 @@ static void end_search_hl(void) } } +static void update_window_hl(win_T *wp, bool invalid) +{ + if (!wp->w_hl_needs_update && !invalid) { + return; + } + wp->w_hl_needs_update = false; + + // determine window specific background set in 'winhighlight' + if (wp != curwin && wp->w_hl_ids[HLF_INACTIVE] > 0) { + wp->w_hl_attr_normal = syn_id2attr(wp->w_hl_ids[HLF_INACTIVE]); + } else if (wp->w_hl_id_normal > 0) { + wp->w_hl_attr_normal = syn_id2attr(wp->w_hl_id_normal); + } else { + wp->w_hl_attr_normal = 0; + } + if (wp != curwin) { + wp->w_hl_attr_normal = hl_combine_attr(hl_attr(HLF_INACTIVE), + wp->w_hl_attr_normal); + } + + for (int hlf = 0; hlf < (int)HLF_COUNT; hlf++) { + int attr; + if (wp->w_hl_ids[hlf] > 0) { + attr = syn_id2attr(wp->w_hl_ids[hlf]); + } else { + attr = hl_attr(hlf); + } + if (wp->w_hl_attr_normal != 0) { + attr = hl_combine_attr(wp->w_hl_attr_normal, attr); + } + wp->w_hl_attrs[hlf] = attr; + } +} + + + /* * Init for calling prepare_search_hl(). */ @@ -5514,7 +5602,9 @@ static void init_search_hl(win_T *wp) search_hl.buf = wp->w_buffer; search_hl.lnum = 0; search_hl.first_lnum = 0; - /* time limit is set at the toplevel, for all windows */ + search_hl.attr = win_hl_attr(wp, HLF_L); + + // time limit is set at the toplevel, for all windows } /* @@ -5534,13 +5624,14 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum) * Do this both for search_hl and the match list. */ cur = wp->w_match_head; - shl_flag = FALSE; - while (cur != NULL || shl_flag == FALSE) { - if (shl_flag == FALSE) { + shl_flag = false; + while (cur != NULL || shl_flag == false) { + if (shl_flag == false) { shl = &search_hl; - shl_flag = TRUE; - } else - shl = &cur->hl; + shl_flag = true; + } else { + shl = &cur->hl; // -V595 + } if (shl->rm.regprog != NULL && shl->lnum == 0 && re_multiline(shl->rm.regprog)) { @@ -5775,12 +5866,12 @@ static void screen_char(unsigned off, int row, int col) if (row >= screen_Rows || col >= screen_Columns) return; - /* Outputting the last character on the screen may scrollup the screen. - * Don't to it! Mark the character invalid (update it when scrolled up) */ + // Outputting the last character on the screen may scrollup the screen. + // Don't to it! Mark the character invalid (update it when scrolled up) + // FIXME: The premise here is not actually true (cf. deferred wrap). if (row == screen_Rows - 1 && col == screen_Columns - 1 - /* account for first command-line character in rightleft mode */ - && !cmdmsg_rl - ) { + // account for first command-line character in rightleft mode + && !cmdmsg_rl) { ScreenAttrs[off] = (sattr_T)-1; return; } @@ -5906,7 +5997,7 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1, col = off - LineOffset[row]; screen_stop_highlight(); ui_cursor_goto(row, col); // clear rest of this screen line - ui_eol_clear(); + ui_call_eol_clear(); col = end_col - col; while (col--) { /* clear chars in ScreenLines */ ScreenLines[off] = ' '; @@ -6099,8 +6190,7 @@ retry: if (new_ScreenLinesC[i] == NULL) break; if (new_ScreenLines == NULL - || (l_enc_utf8 && (new_ScreenLinesUC == NULL || i != p_mco)) - || (l_enc_dbcs == DBCS_JPNU && new_ScreenLines2 == NULL) + || (new_ScreenLinesUC == NULL || i != p_mco) || new_ScreenAttrs == NULL || new_LineOffset == NULL || new_LineWraps == NULL @@ -6185,13 +6275,14 @@ retry: ScreenLinesC[i] + LineOffset[old_row], (size_t)len * sizeof(u8char_T)); } - if (l_enc_dbcs == DBCS_JPNU && ScreenLines2 != NULL) + if (ScreenLines2 != NULL) { memmove(new_ScreenLines2 + new_LineOffset[new_row], - ScreenLines2 + LineOffset[old_row], - (size_t)len * sizeof(schar_T)); + ScreenLines2 + LineOffset[old_row], + (size_t)len * sizeof(schar_T)); + } memmove(new_ScreenAttrs + new_LineOffset[new_row], - ScreenAttrs + LineOffset[old_row], - (size_t)len * sizeof(sattr_T)); + ScreenAttrs + LineOffset[old_row], + (size_t)len * sizeof(sattr_T)); } } } @@ -6295,10 +6386,10 @@ static void screenclear2(void) LineWraps[i] = FALSE; } - ui_clear(); // clear the display - clear_cmdline = FALSE; - mode_displayed = FALSE; - screen_cleared = TRUE; /* can use contents of ScreenLines now */ + ui_call_clear(); // clear the display + clear_cmdline = false; + mode_displayed = false; + screen_cleared = true; // can use contents of ScreenLines now win_rest_invalid(firstwin); redraw_cmdline = TRUE; @@ -6371,13 +6462,11 @@ void setcursor(void) } } -/* - * insert 'line_count' lines at 'row' in window 'wp' - * if 'invalid' is TRUE the wp->w_lines[].wl_lnum is invalidated. - * if 'mayclear' is TRUE the screen will be cleared if it is faster than - * scrolling. - * Returns FAIL if the lines are not inserted, OK for success. - */ +/// Insert 'line_count' lines at 'row' in window 'wp'. +/// If 'invalid' is TRUE the wp->w_lines[].wl_lnum is invalidated. +/// If 'mayclear' is TRUE the screen will be cleared if it is faster than +/// scrolling. +/// Returns FAIL if the lines are not inserted, OK for success. int win_ins_lines(win_T *wp, int row, int line_count, int invalid, int mayclear) { int did_delete; @@ -6440,13 +6529,11 @@ int win_ins_lines(win_T *wp, int row, int line_count, int invalid, int mayclear) return OK; } -/* - * delete "line_count" window lines at "row" in window "wp" - * If "invalid" is TRUE curwin->w_lines[] is invalidated. - * If "mayclear" is TRUE the screen will be cleared if it is faster than - * scrolling - * Return OK for success, FAIL if the lines are not deleted. - */ +/// Delete "line_count" window lines at "row" in window "wp". +/// If "invalid" is TRUE curwin->w_lines[] is invalidated. +/// If "mayclear" is TRUE the screen will be cleared if it is faster than +/// scrolling +/// Return OK for success, FAIL if the lines are not deleted. int win_del_lines(win_T *wp, int row, int line_count, int invalid, int mayclear) { int retval; @@ -6597,7 +6684,7 @@ int screen_ins_lines ( } } - ui_append_lines(line_count); + ui_call_scroll(-line_count); return OK; } @@ -6652,7 +6739,7 @@ int screen_del_lines ( } } - ui_delete_lines(line_count); + ui_call_scroll(line_count); return OK; } @@ -6717,17 +6804,19 @@ int showmode(void) if (edit_submode_pre != NULL) length -= vim_strsize(edit_submode_pre); if (length - vim_strsize(edit_submode) > 0) { - if (edit_submode_pre != NULL) - msg_puts_attr(edit_submode_pre, attr); - msg_puts_attr(edit_submode, attr); + if (edit_submode_pre != NULL) { + msg_puts_attr((const char *)edit_submode_pre, attr); + } + msg_puts_attr((const char *)edit_submode, attr); } if (edit_submode_extra != NULL) { - MSG_PUTS_ATTR(" ", attr); /* add a space in between */ - if ((int)edit_submode_highl < (int)HLF_COUNT) - sub_attr = hl_attr(edit_submode_highl); - else + MSG_PUTS_ATTR(" ", attr); // Add a space in between. + if ((int)edit_submode_highl < (int)HLF_COUNT) { + sub_attr = win_hl_attr(curwin, edit_submode_highl); + } else { sub_attr = attr; - msg_puts_attr(edit_submode_extra, sub_attr); + } + msg_puts_attr((const char *)edit_submode_extra, sub_attr); } } } else { @@ -6752,10 +6841,12 @@ int showmode(void) if (p_fkmap) MSG_PUTS_ATTR(farsi_text_5, attr); if (State & LANGMAP) { - if (curwin->w_p_arab) + if (curwin->w_p_arab) { MSG_PUTS_ATTR(_(" Arabic"), attr); - else - MSG_PUTS_ATTR(_(" (lang)"), attr); + } else if (get_keymap_str(curwin, (char_u *)" (%s)", + NameBuff, MAXPATHL)) { + MSG_PUTS_ATTR(NameBuff, attr); + } } if ((State & INSERT) && p_paste) MSG_PUTS_ATTR(_(" (paste)"), attr); @@ -6874,7 +6965,6 @@ static void draw_tabline(void) int modified; int c; int len; - int attr_sel = hl_attr(HLF_TPS); int attr_nosel = hl_attr(HLF_TP); int attr_fill = hl_attr(HLF_TPF); char_u *p; @@ -6882,8 +6972,15 @@ static void draw_tabline(void) int use_sep_chars = (t_colors < 8 ); - redraw_tabline = FALSE; + if (ScreenLines == NULL) { + return; + } + redraw_tabline = false; + if (ui_is_external(kUITabline)) { + ui_ext_tabline_update(); + return; + } if (tabline_height() < 1) return; @@ -6929,16 +7026,6 @@ static void draw_tabline(void) scol = col; - if (tp->tp_topframe == topframe) - attr = attr_sel; - if (use_sep_chars && col > 0) - screen_putchar('|', 0, col++, attr); - - if (tp->tp_topframe != topframe) - attr = attr_nosel; - - screen_putchar(' ', 0, col++, attr); - if (tp == curtab) { cwp = curwin; wp = firstwin; @@ -6947,10 +7034,29 @@ static void draw_tabline(void) wp = tp->tp_firstwin; } - modified = FALSE; - for (wincount = 0; wp != NULL; wp = wp->w_next, ++wincount) - if (bufIsChanged(wp->w_buffer)) - modified = TRUE; + + if (tp->tp_topframe == topframe) { + attr = win_hl_attr(cwp, HLF_TPS); + } + if (use_sep_chars && col > 0) { + screen_putchar('|', 0, col++, attr); + } + + if (tp->tp_topframe != topframe) { + attr = win_hl_attr(cwp, HLF_TP); + } + + screen_putchar(' ', 0, col++, attr); + + modified = false; + + for (wincount = 0; wp != NULL; wp = wp->w_next, ++wincount) { + if (bufIsChanged(wp->w_buffer)) { + modified = true; + } + } + + if (modified || wincount > 1) { if (wincount > 1) { vim_snprintf((char *)NameBuff, MAXPATHL, "%d", wincount); @@ -6958,7 +7064,7 @@ static void draw_tabline(void) if (col + len >= Columns - 3) break; screen_puts_len(NameBuff, len, 0, col, - hl_combine_attr(attr, hl_attr(HLF_T))); + hl_combine_attr(attr, win_hl_attr(cwp, HLF_T))); col += len; } if (modified) @@ -7024,6 +7130,22 @@ static void draw_tabline(void) redraw_tabline = FALSE; } +void ui_ext_tabline_update(void) +{ + Array tabs = ARRAY_DICT_INIT; + FOR_ALL_TABS(tp) { + Dictionary tab_info = ARRAY_DICT_INIT; + PUT(tab_info, "tab", TABPAGE_OBJ(tp->handle)); + + win_T *cwp = (tp == curtab) ? curwin : tp->tp_curwin; + get_trans_bufname(cwp->w_buffer); + PUT(tab_info, "name", STRING_OBJ(cstr_to_string((char *)NameBuff))); + + ADD(tabs, DICTIONARY_OBJ(tab_info)); + } + ui_call_tabline_update(curtab->handle, tabs); +} + /* * Get buffer name for "buf" into NameBuff[]. * Takes care of special buffer names and translates special characters. @@ -7040,25 +7162,28 @@ void get_trans_bufname(buf_T *buf) /* * Get the character to use in a status line. Get its attributes in "*attr". */ -static int fillchar_status(int *attr, int is_curwin) +static int fillchar_status(int *attr, win_T *wp) { int fill; + bool is_curwin = (wp == curwin); if (is_curwin) { - *attr = hl_attr(HLF_S); + *attr = win_hl_attr(wp, HLF_S); fill = fill_stl; } else { - *attr = hl_attr(HLF_SNC); + *attr = win_hl_attr(wp, HLF_SNC); fill = fill_stlnc; } /* Use fill when there is highlighting, and highlighting of current * window differs, or the fillchars differ, or this is not the * current window */ - if (*attr != 0 && ((hl_attr(HLF_S) != hl_attr(HLF_SNC) - || !is_curwin || firstwin == lastwin) - || (fill_stl != fill_stlnc))) + if (*attr != 0 && ((win_hl_attr(wp, HLF_S) != win_hl_attr(wp, HLF_SNC) + || !is_curwin || ONE_WINDOW) + || (fill_stl != fill_stlnc))) { return fill; - if (is_curwin) + } + if (is_curwin) { return '^'; + } return '='; } @@ -7066,13 +7191,14 @@ static int fillchar_status(int *attr, int is_curwin) * Get the character to use in a separator between vertically split windows. * Get its attributes in "*attr". */ -static int fillchar_vsep(int *attr) +static int fillchar_vsep(win_T *wp, int *attr) { - *attr = hl_attr(HLF_C); - if (*attr == 0 && fill_vert == ' ') + *attr = win_hl_attr(wp, HLF_C); + if (*attr == 0 && fill_vert == ' ') { return '|'; - else + } else { return fill_vert; + } } /* @@ -7107,8 +7233,9 @@ void showruler(int always) } if ((*p_stl != NUL || *curwin->w_p_stl != NUL) && curwin->w_status_height) { redraw_custom_statusline(curwin); - } else + } else { win_redr_ruler(curwin, always); + } if (need_maketitle || (p_icon && (stl_syntax & STL_IN_ICON)) @@ -7186,7 +7313,7 @@ static void win_redr_ruler(win_T *wp, int always) if (wp->w_status_height) { row = wp->w_winrow + wp->w_height; - fillchar = fillchar_status(&attr, wp == curwin); + fillchar = fillchar_status(&attr, wp); off = wp->w_wincol; width = wp->w_width; } else { @@ -7313,23 +7440,16 @@ int number_width(win_T *wp) return n; } -/* - * Set size of the Vim shell. - * If 'mustset' is TRUE, we must set Rows and Columns, do not get the real - * window size (this is used for the :win command). - * If 'mustset' is FALSE, we may try to get the real window size and if - * it fails use 'width' and 'height'. - */ +/// Set dimensions of the Nvim application "shell". void screen_resize(int width, int height) { static int busy = FALSE; - /* - * Avoid recursiveness, can happen when setting the window size causes - * another window-changed signal. - */ - if (busy) + // Avoid recursiveness, can happen when setting the window size causes + // another window-changed signal. + if (updating_screen || busy) { return; + } if (width < 0 || height < 0) /* just checking... */ return; @@ -7405,8 +7525,8 @@ void screen_resize(int width, int height) --busy; } -// Check if the new shell size is valid, correct it if it's too small or way -// too big. +/// Check if the new Nvim application "shell" dimensions are valid. +/// Correct it if it's too small or way too big. void check_shellsize(void) { if (Rows < min_rows()) { diff --git a/src/nvim/screen.h b/src/nvim/screen.h index 81a8b9ed4c..17515d4253 100644 --- a/src/nvim/screen.h +++ b/src/nvim/screen.h @@ -3,6 +3,10 @@ #include <stdbool.h> +#include "nvim/types.h" +#include "nvim/buffer_defs.h" +#include "nvim/pos.h" + /* * flags for update_screen() * The higher the value, the higher the priority diff --git a/src/nvim/search.c b/src/nvim/search.c index 2a087276e7..1bf2317d2a 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -1,3 +1,6 @@ +// 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 + /* * search.c: code for normal mode searching commands */ @@ -282,7 +285,7 @@ void restore_search_patterns(void) static inline void free_spat(struct spat *const spat) { xfree(spat->pat); - dict_unref(spat->additional_data); + tv_dict_unref(spat->additional_data); } #if defined(EXITFREE) @@ -308,13 +311,19 @@ void free_search_patterns(void) */ int ignorecase(char_u *pat) { - int ic = p_ic; + return ignorecase_opt(pat, p_ic, p_scs); +} - if (ic && !no_smartcase && p_scs +/// As ignorecase() put pass the "ic" and "scs" flags. +int ignorecase_opt(char_u *pat, int ic_in, int scs) +{ + int ic = ic_in; + if (ic && !no_smartcase && scs && !(ctrl_x_mode && curbuf->b_p_inf) - ) + ) { ic = !pat_has_uppercase(pat); - no_smartcase = FALSE; + } + no_smartcase = false; return ic; } @@ -329,30 +338,34 @@ int pat_has_uppercase(char_u *pat) while (*p != NUL) { int l; - if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) { - if (enc_utf8 && utf_isupper(utf_ptr2char(p))) - return TRUE; + if ((l = mb_ptr2len(p)) > 1) { + if (mb_isupper(utf_ptr2char(p))) { + return true; + } p += l; } else if (*p == '\\') { - if (p[1] == '_' && p[2] != NUL) /* skip "\_X" */ + if (p[1] == '_' && p[2] != NUL) { // skip "\_X" p += 3; - else if (p[1] == '%' && p[2] != NUL) /* skip "\%X" */ + } else if (p[1] == '%' && p[2] != NUL) { // skip "\%X" p += 3; - else if (p[1] != NUL) /* skip "\X" */ + } else if (p[1] != NUL) { // skip "\X" p += 2; - else + } else { p += 1; - } else if (vim_isupper(*p)) - return TRUE; - else - ++p; + } + } else if (mb_isupper(*p)) { + return true; + } else { + p++; + } } return FALSE; } -char_u *last_csearch(void) +const char *last_csearch(void) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { - return lastc_bytes; + return (const char *)lastc_bytes; } int last_csearch_forward(void) @@ -603,7 +616,7 @@ int searchit( * otherwise "/$" will get stuck on end of line. */ while (matchpos.lnum == 0 - && ((options & SEARCH_END) && first_match + && (((options & SEARCH_END) && first_match) ? (nmatched == 1 && (int)endpos.col - 1 < (int)start_pos.col + extra_col) @@ -992,14 +1005,13 @@ int do_search( dircp = NULL; /* use previous pattern */ if (pat == NULL || *pat == NUL || *pat == dirc) { - if (spats[RE_SEARCH].pat == NULL) { /* no previous pattern */ - pat = spats[RE_SUBST].pat; - if (pat == NULL) { + if (spats[RE_SEARCH].pat == NULL) { // no previous pattern + searchstr = spats[RE_SUBST].pat; + if (searchstr == NULL) { EMSG(_(e_noprevre)); retval = 0; goto end_do_search; } - searchstr = pat; } else { /* make search_regcomp() use spats[RE_SEARCH].pat */ searchstr = (char_u *)""; @@ -1284,10 +1296,11 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, int dir, char_u *pat) * ignored because we are interested in the next line -- Acevedo */ if ((compl_cont_status & CONT_ADDING) && !(compl_cont_status & CONT_SOL)) { - if ((p_ic ? mb_stricmp(p, pat) : STRCMP(p, pat)) == 0) + if (mb_strcmp_ic((bool)p_ic, (const char *)p, (const char *)pat) == 0) { return OK; - } else if (*p != NUL) { /* ignore empty lines */ - /* expanding lines or words */ + } + } else if (*p != NUL) { // Ignore empty lines. + // Expanding lines or words. assert(compl_length >= 0); if ((p_ic ? mb_strnicmp(p, pat, (size_t)compl_length) : STRNCMP(p, pat, compl_length)) == 0) @@ -2411,32 +2424,20 @@ static int cls(void) int c; c = gchar_cursor(); - if (p_altkeymap && c == F_BLANK) - return 0; - if (c == ' ' || c == '\t' || c == NUL) + if (p_altkeymap && c == F_BLANK) { return 0; - if (enc_dbcs != 0 && c > 0xFF) { - /* If cls_bigword, report multi-byte chars as class 1. */ - if (enc_dbcs == DBCS_KOR && cls_bigword) - return 1; - - /* process code leading/trailing bytes */ - return dbcs_class(((unsigned)c >> 8), (c & 0xFF)); } - if (enc_utf8) { - c = utf_class(c); - if (c != 0 && cls_bigword) - return 1; - return c; + if (c == ' ' || c == '\t' || c == NUL) { + return 0; } - /* If cls_bigword is TRUE, report all non-blanks as class 1. */ - if (cls_bigword) - return 1; + c = utf_class(c); - if (vim_iswordc(c)) - return 2; - return 1; + // If cls_bigword is TRUE, report all non-blanks as class 1. + if (c != 0 && cls_bigword) { + return 1; + } + return c; } /* @@ -3022,7 +3023,8 @@ extend: ++curwin->w_cursor.col; VIsual = start_pos; VIsual_mode = 'v'; - redraw_curbuf_later(INVERTED); /* update the inversion */ + redraw_cmdline = true; // show mode later + redraw_curbuf_later(INVERTED); // update the inversion } else { /* include a newline after the sentence, if there is one */ if (incl(&curwin->w_cursor) == -1) @@ -4656,12 +4658,12 @@ static void show_pat_in_path(char_u *line, int type, int did_show, int action, F *(p + 1) = NUL; } if (action == ACTION_SHOW_ALL) { - sprintf((char *)IObuff, "%3ld: ", count); /* show match nr */ - msg_puts(IObuff); - sprintf((char *)IObuff, "%4ld", *lnum); /* show line nr */ - /* Highlight line numbers */ - msg_puts_attr(IObuff, hl_attr(HLF_N)); - MSG_PUTS(" "); + snprintf((char *)IObuff, IOSIZE, "%3ld: ", count); // Show match nr. + msg_puts((const char *)IObuff); + snprintf((char *)IObuff, IOSIZE, "%4ld", *lnum); // Show line nr. + // Highlight line numbers. + msg_puts_attr((const char *)IObuff, hl_attr(HLF_N)); + msg_puts(" "); } msg_prt_line(line, FALSE); ui_flush(); /* show one line at a time */ diff --git a/src/nvim/search.h b/src/nvim/search.h index d4e40cb287..cb50742990 100644 --- a/src/nvim/search.h +++ b/src/nvim/search.h @@ -4,6 +4,12 @@ #include <stdbool.h> #include <stdint.h> +#include "nvim/types.h" +#include "nvim/buffer_defs.h" +#include "nvim/eval/typval.h" +#include "nvim/normal.h" +#include "nvim/os/time.h" + /* Values for the find_pattern_in_path() function args 'type' and 'action': */ #define FIND_ANY 1 #define FIND_DEFINE 2 diff --git a/src/nvim/sha256.c b/src/nvim/sha256.c index 7670b64468..a2378cc202 100644 --- a/src/nvim/sha256.c +++ b/src/nvim/sha256.c @@ -1,3 +1,6 @@ +// 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 + /// @file sha256.c /// /// FIPS-180-2 compliant SHA-256 implementation @@ -259,11 +262,11 @@ void sha256_finish(context_sha256_T *ctx, char_u digest[SHA256_SUM_SIZE]) /// /// @returns hex digest of "buf[buf_len]" in a static array. /// if "salt" is not NULL also do "salt[salt_len]". -char_u *sha256_bytes(const char_u *restrict buf, size_t buf_len, - const char_u *restrict salt, size_t salt_len) +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]; - static char_u hexit[SHA256_BUFFER_SIZE + 1]; // buf size + NULL + static char hexit[SHA256_BUFFER_SIZE + 1]; // buf size + NULL context_sha256_T ctx; sha256_self_test(); @@ -277,7 +280,7 @@ char_u *sha256_bytes(const char_u *restrict buf, size_t buf_len, sha256_finish(&ctx, sha256sum); for (size_t j = 0; j < SHA256_SUM_SIZE; j++) { - snprintf((char *) hexit + j * SHA_STEP, SHA_STEP+1, "%02x", sha256sum[j]); + snprintf(hexit + j * SHA_STEP, SHA_STEP + 1, "%02x", sha256sum[j]); } hexit[sizeof(hexit) - 1] = '\0'; return hexit; @@ -308,7 +311,7 @@ bool sha256_self_test(void) context_sha256_T ctx; char_u buf[1000]; char_u sha256sum[SHA256_SUM_SIZE]; - char_u *hexit; + const char *hexit; static bool sha256_self_tested = false; static bool failures = false; @@ -320,8 +323,8 @@ bool sha256_self_test(void) for (size_t i = 0; i < 3; i++) { if (i < 2) { - hexit = sha256_bytes((char_u *) sha_self_test_msg[i], - STRLEN(sha_self_test_msg[i]), + hexit = sha256_bytes((uint8_t *)sha_self_test_msg[i], + strlen(sha_self_test_msg[i]), NULL, 0); STRCPY(output, hexit); } else { diff --git a/src/nvim/sha256.h b/src/nvim/sha256.h index a118826542..deb881a288 100644 --- a/src/nvim/sha256.h +++ b/src/nvim/sha256.h @@ -2,6 +2,7 @@ #define NVIM_SHA256_H #include <stdint.h> // for uint32_t +#include <stddef.h> #include "nvim/types.h" // for char_u diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 8cf5976e8b..736d6bf162 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -1,3 +1,6 @@ +// 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 <stdlib.h> #include <stddef.h> #include <stdbool.h> @@ -30,7 +33,7 @@ #include "nvim/ex_getln.h" #include "nvim/search.h" #include "nvim/regexp.h" -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" #include "nvim/version.h" #include "nvim/path.h" #include "nvim/fileio.h" @@ -73,17 +76,10 @@ KHASH_SET_INIT_STR(strset) (vim_rename((char_u *)a, (char_u *)b)) #define mb_strnicmp(a, b, c) \ (mb_strnicmp((char_u *)a, (char_u *)b, c)) -#define has_non_ascii(a) (has_non_ascii((char_u *)a)) -#define string_convert(a, b, c) \ - ((char *)string_convert((vimconv_T *)a, (char_u *)b, c)) #define path_shorten_fname_if_possible(b) \ ((char *)path_shorten_fname_if_possible((char_u *)b)) #define buflist_new(ffname, sfname, ...) \ (buflist_new((char_u *)ffname, (char_u *)sfname, __VA_ARGS__)) -#define convert_setup(vcp, from, to) \ - (convert_setup(vcp, (char_u *)from, (char_u *)to)) -#define os_getperm(f) \ - (os_getperm((char_u *) f)) #define os_isdir(f) (os_isdir((char_u *) f)) #define regtilde(s, m) ((char *) regtilde((char_u *) s, m)) #define path_tail_with_sep(f) ((char *) path_tail_with_sep((char_u *)f)) @@ -102,6 +98,7 @@ KHASH_SET_INIT_STR(strset) #define REG_KEY_TYPE "rt" #define REG_KEY_WIDTH "rw" #define REG_KEY_CONTENTS "rc" +#define REG_KEY_UNNAMED "ru" #define KEY_LNUM "l" #define KEY_COL "c" @@ -288,6 +285,7 @@ typedef struct { char name; MotionType type; char **contents; + bool is_unnamed; size_t contents_size; size_t width; dict_T *additional_data; @@ -415,8 +413,6 @@ typedef struct sd_read_def { const char *error; ///< Error message in case of error. uintmax_t fpos; ///< Current position (amount of bytes read since ///< reader structure initialization). May overflow. - vimconv_T sd_conv; ///< Structure used for converting encodings of some - ///< items. } ShaDaReadDef; struct sd_write_def; @@ -437,8 +433,6 @@ typedef struct sd_write_def { ShaDaWriteCloser close; ///< Close function. void *cookie; ///< Data describing object written to. const char *error; ///< Error message in case of error. - vimconv_T sd_conv; ///< Structure used for converting encodings of some - ///< items. } ShaDaWriteDef; #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -481,6 +475,7 @@ static const ShadaEntry sd_default_values[] = { .type = kMTCharWise, .contents = NULL, .contents_size = 0, + .is_unnamed = false, .width = 0, .additional_data = NULL), DEF_SDE(Variable, global_var, @@ -805,7 +800,7 @@ static int open_shada_file_for_reading(const char *const fname, return error; } - convert_setup(&sd_reader->sd_conv, "utf-8", p_enc); + assert(STRCMP(p_enc, "utf-8") == 0); return 0; } @@ -813,7 +808,7 @@ static int open_shada_file_for_reading(const char *const fname, /// Wrapper for closing file descriptors static void close_file(void *cookie) { - const int error = file_free(cookie); + const int error = file_free(cookie, true); if (error != 0) { emsgf(_(SERR "System error while closing ShaDa file: %s"), os_strerror(error)); @@ -1223,7 +1218,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) khash_t(fnamebufs) fname_bufs = KHASH_EMPTY_TABLE(fnamebufs); khash_t(strset) oldfiles_set = KHASH_EMPTY_TABLE(strset); if (get_old_files && (oldfiles_list == NULL || force)) { - oldfiles_list = list_alloc(); + oldfiles_list = tv_list_alloc(); set_vim_var_list(VV_OLDFILES, oldfiles_list); } ShaDaReadResult srni_ret; @@ -1285,8 +1280,6 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) if (cur_entry.data.search_pattern.is_last_used) { set_last_used_pattern( cur_entry.data.search_pattern.is_substitute_pattern); - } - if (cur_entry.data.search_pattern.is_last_used) { SET_NO_HLSEARCH(!cur_entry.data.search_pattern.highlighted); } // Do not free shada entry: its allocated memory was saved above. @@ -1345,7 +1338,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) .y_width = (colnr_T) cur_entry.data.reg.width, .timestamp = cur_entry.timestamp, .additional_data = cur_entry.data.reg.additional_data, - })) { + }, cur_entry.data.reg.is_unnamed)) { shada_free_shada_entry(&cur_entry); } // Do not free shada entry: its allocated memory was saved above. @@ -1435,8 +1428,8 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) fname = xstrdup(fname); } int kh_ret; - (void) kh_put(strset, &oldfiles_set, fname, &kh_ret); - list_append_allocated_string(oldfiles_list, fname); + (void)kh_put(strset, &oldfiles_set, fname, &kh_ret); + tv_list_append_allocated_string(oldfiles_list, fname); if (!want_marks) { // Avoid free because this string was already used. cur_entry.data.filemark.fname = NULL; @@ -1573,7 +1566,9 @@ static char *shada_filename(const char *file) do { \ const String s_ = (s); \ msgpack_pack_str(spacker, s_.size); \ - msgpack_pack_str_body(spacker, s_.data, s_.size); \ + if (s_.size) { \ + msgpack_pack_str_body(spacker, s_.data, s_.size); \ + } \ } while (0) #define PACK_BIN(s) \ do { \ @@ -1621,10 +1616,10 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, for (const hashitem_T *hi= d->dv_hashtab.ht_array; todo; hi++) { \ if (!HASHITEM_EMPTY(hi)) { \ todo--; \ - dictitem_T *const di = HI2DI(hi); \ - const size_t key_len = strlen((const char *) hi->hi_key); \ + dictitem_T *const di = TV_DICT_HI2DI(hi); \ + const size_t key_len = strlen((const char *)hi->hi_key); \ msgpack_pack_str(spacker, key_len); \ - msgpack_pack_str_body(spacker, (const char *) hi->hi_key, key_len); \ + msgpack_pack_str_body(spacker, (const char *)hi->hi_key, key_len); \ if (encode_vim_to_msgpack(spacker, &di->di_tv, \ _("additional data of ShaDa " what)) \ == FAIL) { \ @@ -1788,6 +1783,7 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, 2 // Register contents and name + ONE_IF_NOT_DEFAULT(entry, reg.type) + ONE_IF_NOT_DEFAULT(entry, reg.width) + + ONE_IF_NOT_DEFAULT(entry, reg.is_unnamed) // Additional entries, if any: + (size_t) (entry.data.reg.additional_data == NULL ? 0 @@ -1808,6 +1804,14 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, PACK_STATIC_STR(REG_KEY_WIDTH); msgpack_pack_uint64(spacker, (uint64_t) entry.data.reg.width); } + if (!CHECK_DEFAULT(entry, reg.is_unnamed)) { + PACK_STATIC_STR(REG_KEY_UNNAMED); + if (entry.data.reg.is_unnamed) { + msgpack_pack_true(spacker); + } else { + msgpack_pack_false(spacker); + } + } DUMP_ADDITIONAL_DATA(entry.data.reg.additional_data, "register item"); break; } @@ -1899,127 +1903,24 @@ shada_pack_entry_error: } #undef PACK_STRING -/// Write single ShaDa entry, converting it if needed +/// Write single ShaDa entry and free it afterwards /// -/// @warning Frees entry after packing. +/// Will not free if entry could not be freed. /// /// @param[in] packer Packer used to write entry. -/// @param[in] sd_conv Conversion definitions. -/// @param[in] entry Entry written. If entry.can_free_entry is false then -/// it assumes that entry was not converted, otherwise it -/// is assumed that entry was already converted. +/// @param[in] entry Entry written. /// @param[in] max_kbyte Maximum size of an item in KiB. Zero means no /// restrictions. -static ShaDaWriteResult shada_pack_encoded_entry(msgpack_packer *const packer, - const vimconv_T *const sd_conv, - PossiblyFreedShadaEntry entry, - const size_t max_kbyte) - FUNC_ATTR_NONNULL_ALL +static inline ShaDaWriteResult shada_pack_pfreed_entry( + msgpack_packer *const packer, PossiblyFreedShadaEntry entry, + const size_t max_kbyte) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE { ShaDaWriteResult ret = kSDWriteSuccessfull; + ret = shada_pack_entry(packer, entry.data, max_kbyte); if (entry.can_free_entry) { - ret = shada_pack_entry(packer, entry.data, max_kbyte); shada_free_shada_entry(&entry.data); - return ret; } -#define RUN_WITH_CONVERTED_STRING(cstr, code) \ - do { \ - bool did_convert = false; \ - if (sd_conv->vc_type != CONV_NONE && has_non_ascii((cstr))) { \ - char *const converted_string = string_convert(sd_conv, (cstr), NULL); \ - if (converted_string != NULL) { \ - (cstr) = converted_string; \ - did_convert = true; \ - } \ - } \ - code \ - if (did_convert) { \ - xfree((cstr)); \ - } \ - } while (0) - switch (entry.data.type) { - case kSDItemUnknown: - case kSDItemMissing: { - assert(false); - } - case kSDItemSearchPattern: { - RUN_WITH_CONVERTED_STRING(entry.data.data.search_pattern.pat, { - ret = shada_pack_entry(packer, entry.data, max_kbyte); - }); - break; - } - case kSDItemHistoryEntry: { - RUN_WITH_CONVERTED_STRING(entry.data.data.history_item.string, { - ret = shada_pack_entry(packer, entry.data, max_kbyte); - }); - break; - } - case kSDItemSubString: { - RUN_WITH_CONVERTED_STRING(entry.data.data.sub_string.sub, { - ret = shada_pack_entry(packer, entry.data, max_kbyte); - }); - break; - } - case kSDItemVariable: { - if (sd_conv->vc_type != CONV_NONE) { - typval_T tgttv; - var_item_copy(sd_conv, &entry.data.data.global_var.value, &tgttv, - true, 0); - clear_tv(&entry.data.data.global_var.value); - entry.data.data.global_var.value = tgttv; - } - ret = shada_pack_entry(packer, entry.data, max_kbyte); - break; - } - case kSDItemRegister: { - bool did_convert = false; - if (sd_conv->vc_type != CONV_NONE) { - size_t first_non_ascii = 0; - for (size_t i = 0; i < entry.data.data.reg.contents_size; i++) { - if (has_non_ascii(entry.data.data.reg.contents[i])) { - first_non_ascii = i; - did_convert = true; - break; - } - } - if (did_convert) { - entry.data.data.reg.contents = - xmemdup(entry.data.data.reg.contents, - (entry.data.data.reg.contents_size - * sizeof(entry.data.data.reg.contents))); - for (size_t i = 0; i < entry.data.data.reg.contents_size; i++) { - if (i >= first_non_ascii) { - entry.data.data.reg.contents[i] = get_converted_string( - sd_conv, - entry.data.data.reg.contents[i], - strlen(entry.data.data.reg.contents[i])); - } else { - entry.data.data.reg.contents[i] = - xstrdup(entry.data.data.reg.contents[i]); - } - } - } - } - ret = shada_pack_entry(packer, entry.data, max_kbyte); - if (did_convert) { - for (size_t i = 0; i < entry.data.data.reg.contents_size; i++) { - xfree(entry.data.data.reg.contents[i]); - } - xfree(entry.data.data.reg.contents); - } - break; - } - case kSDItemHeader: - case kSDItemGlobalMark: - case kSDItemJump: - case kSDItemBufferList: - case kSDItemLocalMark: - case kSDItemChange: { - ret = shada_pack_entry(packer, entry.data, max_kbyte); - break; - } - } -#undef RUN_WITH_CONVERTED_STRING return ret; } @@ -2156,7 +2057,7 @@ static inline ShaDaWriteResult shada_read_when_writing( } case kSDReadStatusNotShaDa: { ret = kSDWriteReadNotShada; - // fallthrough + FALLTHROUGH; } case kSDReadStatusReadError: { return ret; @@ -2429,6 +2330,48 @@ static inline void add_search_pattern(PossiblyFreedShadaEntry *const ret_pse, } } +/// Initialize registers for writing to the ShaDa file +/// +/// @param[in] wms The WriteMergerState used when writing. +/// @param[in] max_reg_lines The maximum number of register lines. +static inline void shada_initialize_registers(WriteMergerState *const wms, + int max_reg_lines) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE +{ + const void *reg_iter = NULL; + const bool limit_reg_lines = max_reg_lines >= 0; + do { + yankreg_T reg; + char name = NUL; + bool is_unnamed = false; + reg_iter = op_register_iter(reg_iter, &name, ®, &is_unnamed); + if (name == NUL) { + break; + } + if (limit_reg_lines && reg.y_size > (size_t)max_reg_lines) { + continue; + } + wms->registers[op_reg_index(name)] = (PossiblyFreedShadaEntry) { + .can_free_entry = false, + .data = { + .type = kSDItemRegister, + .timestamp = reg.timestamp, + .data = { + .reg = { + .contents = (char **)reg.y_array, + .contents_size = (size_t)reg.y_size, + .type = reg.y_type, + .width = (size_t)(reg.y_type == kMTBlockWise ? reg.y_width : 0), + .additional_data = reg.additional_data, + .name = name, + .is_unnamed = is_unnamed, + } + } + } + }; + } while (reg_iter != NULL); +} + /// Write ShaDa file /// /// @param[in] sd_writer Structure containing file writer definition. @@ -2455,7 +2398,6 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, if (max_reg_lines < 0) { max_reg_lines = get_shada_parameter('"'); } - const bool limit_reg_lines = max_reg_lines >= 0; const bool dump_registers = (max_reg_lines != 0); khash_t(bufset) removable_bufs = KHASH_EMPTY_TABLE(bufset); const size_t max_kbyte = (size_t) max_kbyte_i; @@ -2556,11 +2498,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, break; } typval_T tgttv; - if (sd_writer->sd_conv.vc_type != CONV_NONE) { - var_item_copy(&sd_writer->sd_conv, &vartv, &tgttv, true, 0); - } else { - copy_tv(&vartv, &tgttv); - } + tv_copy(&vartv, &tgttv); ShaDaWriteResult spe_ret; if ((spe_ret = shada_pack_entry(packer, (ShadaEntry) { .type = kSDItemVariable, @@ -2573,13 +2511,13 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, } } }, max_kbyte)) == kSDWriteFailed) { - clear_tv(&vartv); - clear_tv(&tgttv); + tv_clear(&vartv); + tv_clear(&tgttv); ret = kSDWriteFailed; goto shada_write_exit; } - clear_tv(&vartv); - clear_tv(&tgttv); + tv_clear(&vartv); + tv_clear(&tgttv); if (spe_ret == kSDWriteSuccessfull) { int kh_ret; (void) kh_put(strset, &wms->dumped_variables, name, &kh_ret); @@ -2702,35 +2640,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, // Initialize registers if (dump_registers) { - const void *reg_iter = NULL; - do { - yankreg_T reg; - char name = NUL; - reg_iter = op_register_iter(reg_iter, &name, ®); - if (name == NUL) { - break; - } - if (limit_reg_lines && reg.y_size > (size_t)max_reg_lines) { - continue; - } - wms->registers[op_reg_index(name)] = (PossiblyFreedShadaEntry) { - .can_free_entry = false, - .data = { - .type = kSDItemRegister, - .timestamp = reg.timestamp, - .data = { - .reg = { - .contents = (char **) reg.y_array, - .contents_size = (size_t) reg.y_size, - .type = reg.y_type, - .width = (size_t) (reg.y_type == kMTBlockWise ? reg.y_width : 0), - .additional_data = reg.additional_data, - .name = name, - } - } - } - }; - } while (reg_iter != NULL); + shada_initialize_registers(wms, max_reg_lines); } // Initialize buffers @@ -2811,9 +2721,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, do { \ for (size_t i_ = 0; i_ < ARRAY_SIZE(wms_array); i_++) { \ if (wms_array[i_].data.type != kSDItemMissing) { \ - if (shada_pack_encoded_entry(packer, &sd_writer->sd_conv, \ - wms_array[i_], \ - max_kbyte) == kSDWriteFailed) { \ + if (shada_pack_pfreed_entry(packer, wms_array[i_], max_kbyte) \ + == kSDWriteFailed) { \ ret = kSDWriteFailed; \ goto shada_write_exit; \ } \ @@ -2823,8 +2732,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, PACK_WMS_ARRAY(wms->global_marks); PACK_WMS_ARRAY(wms->registers); for (size_t i = 0; i < wms->jumps_size; i++) { - if (shada_pack_encoded_entry(packer, &sd_writer->sd_conv, wms->jumps[i], - max_kbyte) == kSDWriteFailed) { + if (shada_pack_pfreed_entry(packer, wms->jumps[i], max_kbyte) + == kSDWriteFailed) { ret = kSDWriteFailed; goto shada_write_exit; } @@ -2832,8 +2741,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, #define PACK_WMS_ENTRY(wms_entry) \ do { \ if (wms_entry.data.type != kSDItemMissing) { \ - if (shada_pack_encoded_entry(packer, &sd_writer->sd_conv, wms_entry, \ - max_kbyte) == kSDWriteFailed) { \ + if (shada_pack_pfreed_entry(packer, wms_entry, max_kbyte) \ + == kSDWriteFailed) { \ ret = kSDWriteFailed; \ goto shada_write_exit; \ } \ @@ -2860,9 +2769,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, for (size_t i = 0; i < file_markss_to_dump; i++) { PACK_WMS_ARRAY(all_file_markss[i]->marks); for (size_t j = 0; j < all_file_markss[i]->changes_size; j++) { - if (shada_pack_encoded_entry(packer, &sd_writer->sd_conv, - all_file_markss[i]->changes[j], - max_kbyte) == kSDWriteFailed) { + if (shada_pack_pfreed_entry(packer, all_file_markss[i]->changes[j], + max_kbyte) == kSDWriteFailed) { ret = kSDWriteFailed; goto shada_write_exit; } @@ -2886,8 +2794,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, if (dump_one_history[i]) { hms_insert_whole_neovim_history(&wms->hms[i]); HMS_ITER(&wms->hms[i], cur_entry, { - if (shada_pack_encoded_entry( - packer, &sd_writer->sd_conv, (PossiblyFreedShadaEntry) { + if (shada_pack_pfreed_entry( + packer, (PossiblyFreedShadaEntry) { .data = cur_entry->data, .can_free_entry = cur_entry->can_free_entry, }, max_kbyte) == kSDWriteFailed) { @@ -3038,8 +2946,6 @@ shada_write_file_nomerge: {} verbose_leave(); } - convert_setup(&sd_writer.sd_conv, p_enc, "utf-8"); - const ShaDaWriteResult sw_ret = shada_write(&sd_writer, (nomerge ? NULL : &sd_reader)); @@ -3154,17 +3060,17 @@ static void shada_free_shada_entry(ShadaEntry *const entry) case kSDItemJump: case kSDItemGlobalMark: case kSDItemLocalMark: { - dict_unref(entry->data.filemark.additional_data); + tv_dict_unref(entry->data.filemark.additional_data); xfree(entry->data.filemark.fname); break; } case kSDItemSearchPattern: { - dict_unref(entry->data.search_pattern.additional_data); + tv_dict_unref(entry->data.search_pattern.additional_data); xfree(entry->data.search_pattern.pat); break; } case kSDItemRegister: { - dict_unref(entry->data.reg.additional_data); + tv_dict_unref(entry->data.reg.additional_data); for (size_t i = 0; i < entry->data.reg.contents_size; i++) { xfree(entry->data.reg.contents[i]); } @@ -3172,25 +3078,25 @@ static void shada_free_shada_entry(ShadaEntry *const entry) break; } case kSDItemHistoryEntry: { - list_unref(entry->data.history_item.additional_elements); + tv_list_unref(entry->data.history_item.additional_elements); xfree(entry->data.history_item.string); break; } case kSDItemVariable: { - list_unref(entry->data.global_var.additional_elements); + tv_list_unref(entry->data.global_var.additional_elements); xfree(entry->data.global_var.name); - clear_tv(&entry->data.global_var.value); + tv_clear(&entry->data.global_var.value); break; } case kSDItemSubString: { - list_unref(entry->data.sub_string.additional_elements); + tv_list_unref(entry->data.sub_string.additional_elements); xfree(entry->data.sub_string.sub); break; } case kSDItemBufferList: { for (size_t i = 0; i < entry->data.buffer_list.size; i++) { xfree(entry->data.buffer_list.buffers[i].fname); - dict_unref(entry->data.buffer_list.buffers[i].additional_data); + tv_dict_unref(entry->data.buffer_list.buffers[i].additional_data); } xfree(entry->data.buffer_list.buffers); break; @@ -3327,29 +3233,6 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, return kSDReadStatusSuccess; } -/// Convert or copy and return a string -/// -/// @param[in] sd_conv Conversion definition. -/// @param[in] str String to convert. -/// @param[in] len String length. -/// -/// @return [allocated] converted string or copy of the original string. -static inline char *get_converted_string(const vimconv_T *const sd_conv, - const char *const str, - const size_t len) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT -{ - if (!has_non_ascii_len(str, len)) { - return xmemdupz(str, len); - } - size_t new_len = len; - char *const new_str = string_convert(sd_conv, str, &new_len); - if (new_str == NULL) { - return xmemdupz(str, len); - } - return new_str; -} - #define READERR(entry_name, error_desc) \ RERR "Error while reading ShaDa file: " \ entry_name " entry at position %" PRIu64 " " \ @@ -3427,10 +3310,7 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv, sizeof(*unpacked.data.via.map.ptr)); \ ad_ga.ga_len++; \ } -#define CONVERTED(str, len) ( \ - sd_reader->sd_conv.vc_type != CONV_NONE \ - ? get_converted_string(&sd_reader->sd_conv, (str), (len)) \ - : xmemdupz((str), (len))) +#define CONVERTED(str, len) (xmemdupz((str), (len))) #define BIN_CONVERTED(b) CONVERTED(b.ptr, b.size) #define SET_ADDITIONAL_DATA(tgt, name) \ do { \ @@ -3451,7 +3331,7 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv, "cannot be converted to a VimL dictionary")), \ initial_fpos); \ ga_clear(&ad_ga); \ - clear_tv(&adtv); \ + tv_clear(&adtv); \ goto shada_read_next_item_error; \ } \ tgt = adtv.vval.v_dict; \ @@ -3474,7 +3354,7 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv, if (msgpack_to_vim(obj, &aetv) == FAIL) { \ emsgf(_(READERR(name, "cannot be converted to a VimL list")), \ initial_fpos); \ - clear_tv(&aetv); \ + tv_clear(&aetv); \ goto shada_read_next_item_error; \ } \ assert(aetv.v_type == VAR_LIST); \ @@ -3533,8 +3413,16 @@ shada_read_next_item_start: return mru_ret; } - const size_t length = (size_t) length_u64; - entry->timestamp = (Timestamp) timestamp_u64; + if (length_u64 > PTRDIFF_MAX) { + emsgf(_(RCERR "Error while reading ShaDa file: " + "there is an item at position %" PRIu64 " " + "that is stated to be too long"), + initial_fpos); + return kSDReadStatusNotShaDa; + } + + const size_t length = (size_t)length_u64; + entry->timestamp = (Timestamp)timestamp_u64; if (type_u64 == 0) { // kSDItemUnknown cannot possibly pass that far because it is -1 and that @@ -3739,6 +3627,7 @@ shada_read_next_item_start: entry->data.reg.contents[i] = BIN_CONVERTED(arr.ptr[i].via.bin); } } + BOOLEAN_KEY("register", REG_KEY_UNNAMED, entry->data.reg.is_unnamed) TYPED_KEY("register", REG_KEY_TYPE, "an unsigned integer", entry->data.reg.type, POSITIVE_INTEGER, u64, TOU8) TYPED_KEY("register", KEY_NAME_CHAR, "an unsigned integer", @@ -3803,30 +3692,14 @@ shada_read_next_item_start: (char) unpacked.data.via.array.ptr[2].via.u64; } size_t strsize; - if (sd_reader->sd_conv.vc_type == CONV_NONE - || !has_non_ascii_len(unpacked.data.via.array.ptr[1].via.bin.ptr, - unpacked.data.via.array.ptr[1].via.bin.size)) { -shada_read_next_item_hist_no_conv: - strsize = ( - unpacked.data.via.array.ptr[1].via.bin.size - + 1 // Zero byte - + 1); // Separator character - entry->data.history_item.string = xmalloc(strsize); - memcpy(entry->data.history_item.string, - unpacked.data.via.array.ptr[1].via.bin.ptr, - unpacked.data.via.array.ptr[1].via.bin.size); - } else { - size_t len = unpacked.data.via.array.ptr[1].via.bin.size; - char *const converted = string_convert( - &sd_reader->sd_conv, unpacked.data.via.array.ptr[1].via.bin.ptr, - &len); - if (converted != NULL) { - strsize = len + 2; - entry->data.history_item.string = xrealloc(converted, strsize); - } else { - goto shada_read_next_item_hist_no_conv; - } - } + strsize = ( + unpacked.data.via.array.ptr[1].via.bin.size + + 1 // Zero byte + + 1); // Separator character + entry->data.history_item.string = xmalloc(strsize); + memcpy(entry->data.history_item.string, + unpacked.data.via.array.ptr[1].via.bin.ptr, + unpacked.data.via.array.ptr[1].via.bin.size); entry->data.history_item.string[strsize - 2] = 0; entry->data.history_item.string[strsize - 1] = entry->data.history_item.sep; @@ -3859,16 +3732,6 @@ shada_read_next_item_hist_no_conv: "be converted to the VimL value")), initial_fpos); goto shada_read_next_item_error; } - if (sd_reader->sd_conv.vc_type != CONV_NONE) { - typval_T tgttv; - var_item_copy(&sd_reader->sd_conv, - &entry->data.global_var.value, - &tgttv, - true, - 0); - clear_tv(&entry->data.global_var.value); - entry->data.global_var.value = tgttv; - } SET_ADDITIONAL_ELEMENTS(unpacked.data.via.array, 2, entry->data.global_var.additional_elements, "variable"); diff --git a/src/nvim/sign_defs.h b/src/nvim/sign_defs.h index 7288a48e21..3778f4287e 100644 --- a/src/nvim/sign_defs.h +++ b/src/nvim/sign_defs.h @@ -1,6 +1,8 @@ #ifndef NVIM_SIGN_DEFS_H #define NVIM_SIGN_DEFS_H +#include "nvim/pos.h" + // signs: line annotations typedef struct signlist signlist_T; diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 7119ac6dc1..42c9bcc0ee 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -1,5 +1,10 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + // spell.c: code for spell checking // +// See spellfile.c for the Vim spell file format. +// // The spell checking mechanism uses a tree (aka trie). Each node in the tree // has a list of bytes that can appear (siblings). For each byte there is a // pointer to the node with the byte that follows in the word (child). @@ -63,226 +68,6 @@ // compute the maximum word score that can be used. #define MAXSCORE(word_score, sound_score) ((4 * word_score - sound_score) / 3) -// Vim spell file format: <HEADER> -// <SECTIONS> -// <LWORDTREE> -// <KWORDTREE> -// <PREFIXTREE> -// -// <HEADER>: <fileID> <versionnr> -// -// <fileID> 8 bytes "VIMspell" -// <versionnr> 1 byte VIMSPELLVERSION -// -// -// Sections make it possible to add information to the .spl file without -// making it incompatible with previous versions. There are two kinds of -// sections: -// 1. Not essential for correct spell checking. E.g. for making suggestions. -// These are skipped when not supported. -// 2. Optional information, but essential for spell checking when present. -// E.g. conditions for affixes. When this section is present but not -// supported an error message is given. -// -// <SECTIONS>: <section> ... <sectionend> -// -// <section>: <sectionID> <sectionflags> <sectionlen> (section contents) -// -// <sectionID> 1 byte number from 0 to 254 identifying the section -// -// <sectionflags> 1 byte SNF_REQUIRED: this section is required for correct -// spell checking -// -// <sectionlen> 4 bytes length of section contents, MSB first -// -// <sectionend> 1 byte SN_END -// -// -// sectionID == SN_INFO: <infotext> -// <infotext> N bytes free format text with spell file info (version, -// website, etc) -// -// sectionID == SN_REGION: <regionname> ... -// <regionname> 2 bytes Up to 8 region names: ca, au, etc. Lower case. -// First <regionname> is region 1. -// -// sectionID == SN_CHARFLAGS: <charflagslen> <charflags> -// <folcharslen> <folchars> -// <charflagslen> 1 byte Number of bytes in <charflags> (should be 128). -// <charflags> N bytes List of flags (first one is for character 128): -// 0x01 word character CF_WORD -// 0x02 upper-case character CF_UPPER -// <folcharslen> 2 bytes Number of bytes in <folchars>. -// <folchars> N bytes Folded characters, first one is for character 128. -// -// sectionID == SN_MIDWORD: <midword> -// <midword> N bytes Characters that are word characters only when used -// in the middle of a word. -// -// sectionID == SN_PREFCOND: <prefcondcnt> <prefcond> ... -// <prefcondcnt> 2 bytes Number of <prefcond> items following. -// <prefcond> : <condlen> <condstr> -// <condlen> 1 byte Length of <condstr>. -// <condstr> N bytes Condition for the prefix. -// -// sectionID == SN_REP: <repcount> <rep> ... -// <repcount> 2 bytes number of <rep> items, MSB first. -// <rep> : <repfromlen> <repfrom> <reptolen> <repto> -// <repfromlen> 1 byte length of <repfrom> -// <repfrom> N bytes "from" part of replacement -// <reptolen> 1 byte length of <repto> -// <repto> N bytes "to" part of replacement -// -// sectionID == SN_REPSAL: <repcount> <rep> ... -// just like SN_REP but for soundfolded words -// -// sectionID == SN_SAL: <salflags> <salcount> <sal> ... -// <salflags> 1 byte flags for soundsalike conversion: -// SAL_F0LLOWUP -// SAL_COLLAPSE -// SAL_REM_ACCENTS -// <salcount> 2 bytes number of <sal> items following -// <sal> : <salfromlen> <salfrom> <saltolen> <salto> -// <salfromlen> 1 byte length of <salfrom> -// <salfrom> N bytes "from" part of soundsalike -// <saltolen> 1 byte length of <salto> -// <salto> N bytes "to" part of soundsalike -// -// sectionID == SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto> -// <sofofromlen> 2 bytes length of <sofofrom> -// <sofofrom> N bytes "from" part of soundfold -// <sofotolen> 2 bytes length of <sofoto> -// <sofoto> N bytes "to" part of soundfold -// -// sectionID == SN_SUGFILE: <timestamp> -// <timestamp> 8 bytes time in seconds that must match with .sug file -// -// sectionID == SN_NOSPLITSUGS: nothing -// -// sectionID == SN_NOCOMPOUNDSUGS: nothing -// -// sectionID == SN_WORDS: <word> ... -// <word> N bytes NUL terminated common word -// -// sectionID == SN_MAP: <mapstr> -// <mapstr> N bytes String with sequences of similar characters, -// separated by slashes. -// -// sectionID == SN_COMPOUND: <compmax> <compminlen> <compsylmax> <compoptions> -// <comppatcount> <comppattern> ... <compflags> -// <compmax> 1 byte Maximum nr of words in compound word. -// <compminlen> 1 byte Minimal word length for compounding. -// <compsylmax> 1 byte Maximum nr of syllables in compound word. -// <compoptions> 2 bytes COMP_ flags. -// <comppatcount> 2 bytes number of <comppattern> following -// <compflags> N bytes Flags from COMPOUNDRULE items, separated by -// slashes. -// -// <comppattern>: <comppatlen> <comppattext> -// <comppatlen> 1 byte length of <comppattext> -// <comppattext> N bytes end or begin chars from CHECKCOMPOUNDPATTERN -// -// sectionID == SN_NOBREAK: (empty, its presence is what matters) -// -// sectionID == SN_SYLLABLE: <syllable> -// <syllable> N bytes String from SYLLABLE item. -// -// <LWORDTREE>: <wordtree> -// -// <KWORDTREE>: <wordtree> -// -// <PREFIXTREE>: <wordtree> -// -// -// <wordtree>: <nodecount> <nodedata> ... -// -// <nodecount> 4 bytes Number of nodes following. MSB first. -// -// <nodedata>: <siblingcount> <sibling> ... -// -// <siblingcount> 1 byte Number of siblings in this node. The siblings -// follow in sorted order. -// -// <sibling>: <byte> [ <nodeidx> <xbyte> -// | <flags> [<flags2>] [<region>] [<affixID>] -// | [<pflags>] <affixID> <prefcondnr> ] -// -// <byte> 1 byte Byte value of the sibling. Special cases: -// BY_NOFLAGS: End of word without flags and for all -// regions. -// For PREFIXTREE <affixID> and -// <prefcondnr> follow. -// BY_FLAGS: End of word, <flags> follow. -// For PREFIXTREE <pflags>, <affixID> -// and <prefcondnr> follow. -// BY_FLAGS2: End of word, <flags> and <flags2> -// follow. Not used in PREFIXTREE. -// BY_INDEX: Child of sibling is shared, <nodeidx> -// and <xbyte> follow. -// -// <nodeidx> 3 bytes Index of child for this sibling, MSB first. -// -// <xbyte> 1 byte Byte value of the sibling. -// -// <flags> 1 byte Bitmask of: -// WF_ALLCAP word must have only capitals -// WF_ONECAP first char of word must be capital -// WF_KEEPCAP keep-case word -// WF_FIXCAP keep-case word, all caps not allowed -// WF_RARE rare word -// WF_BANNED bad word -// WF_REGION <region> follows -// WF_AFX <affixID> follows -// -// <flags2> 1 byte Bitmask of: -// WF_HAS_AFF >> 8 word includes affix -// WF_NEEDCOMP >> 8 word only valid in compound -// WF_NOSUGGEST >> 8 word not used for suggestions -// WF_COMPROOT >> 8 word already a compound -// WF_NOCOMPBEF >> 8 no compounding before this word -// WF_NOCOMPAFT >> 8 no compounding after this word -// -// <pflags> 1 byte Bitmask of: -// WFP_RARE rare prefix -// WFP_NC non-combining prefix -// WFP_UP letter after prefix made upper case -// -// <region> 1 byte Bitmask for regions in which word is valid. When -// omitted it's valid in all regions. -// Lowest bit is for region 1. -// -// <affixID> 1 byte ID of affix that can be used with this word. In -// PREFIXTREE used for the required prefix ID. -// -// <prefcondnr> 2 bytes Prefix condition number, index in <prefcond> list -// from HEADER. -// -// All text characters are in 'encoding', but stored as single bytes. - -// Vim .sug file format: <SUGHEADER> -// <SUGWORDTREE> -// <SUGTABLE> -// -// <SUGHEADER>: <fileID> <versionnr> <timestamp> -// -// <fileID> 6 bytes "VIMsug" -// <versionnr> 1 byte VIMSUGVERSION -// <timestamp> 8 bytes timestamp that must match with .spl file -// -// -// <SUGWORDTREE>: <wordtree> (see above, no flags or region used) -// -// -// <SUGTABLE>: <sugwcount> <sugline> ... -// -// <sugwcount> 4 bytes number of <sugline> following -// -// <sugline>: <sugnr> ... NUL -// -// <sugnr>: X bytes word number that results in this soundfolded word, -// stored as an offset to the previous number in as -// few bytes as possible, see offset2bytes()) - #include <assert.h> #include <inttypes.h> #include <limits.h> @@ -292,6 +77,9 @@ #include <stdlib.h> #include <wctype.h> +/* for offsetof() */ +#include <stddef.h> + #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/spell.h" @@ -307,6 +95,7 @@ #include "nvim/func_attr.h" #include "nvim/getchar.h" #include "nvim/hashtab.h" +#include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" @@ -320,254 +109,18 @@ #include "nvim/regexp.h" #include "nvim/screen.h" #include "nvim/search.h" +#include "nvim/spellfile.h" #include "nvim/strings.h" #include "nvim/syntax.h" -#include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/os/os.h" #include "nvim/os/input.h" -#ifndef UNIX // it's in os/unix_defs.h for Unix -# include <time.h> // for time_t -#endif - -#define MAXWLEN 254 // Assume max. word len is this many bytes. - // Some places assume a word length fits in a - // byte, thus it can't be above 255. - -// Type used for indexes in the word tree need to be at least 4 bytes. If int -// is 8 bytes we could use something smaller, but what? -typedef int idx_T; - -# define SPL_FNAME_TMPL "%s.%s.spl" -# define SPL_FNAME_ADD ".add." -# define SPL_FNAME_ASCII ".ascii." - -// Flags used for a word. Only the lowest byte can be used, the region byte -// comes above it. -#define WF_REGION 0x01 // region byte follows -#define WF_ONECAP 0x02 // word with one capital (or all capitals) -#define WF_ALLCAP 0x04 // word must be all capitals -#define WF_RARE 0x08 // rare word -#define WF_BANNED 0x10 // bad word -#define WF_AFX 0x20 // affix ID follows -#define WF_FIXCAP 0x40 // keep-case word, allcap not allowed -#define WF_KEEPCAP 0x80 // keep-case word - -// for <flags2>, shifted up one byte to be used in wn_flags -#define WF_HAS_AFF 0x0100 // word includes affix -#define WF_NEEDCOMP 0x0200 // word only valid in compound -#define WF_NOSUGGEST 0x0400 // word not to be suggested -#define WF_COMPROOT 0x0800 // already compounded word, COMPOUNDROOT -#define WF_NOCOMPBEF 0x1000 // no compounding before this word -#define WF_NOCOMPAFT 0x2000 // no compounding after this word - // only used for su_badflags #define WF_MIXCAP 0x20 // mix of upper and lower case: macaRONI #define WF_CAPMASK (WF_ONECAP | WF_ALLCAP | WF_KEEPCAP | WF_FIXCAP) -// flags for <pflags> -#define WFP_RARE 0x01 // rare prefix -#define WFP_NC 0x02 // prefix is not combining -#define WFP_UP 0x04 // to-upper prefix -#define WFP_COMPPERMIT 0x08 // prefix with COMPOUNDPERMITFLAG -#define WFP_COMPFORBID 0x10 // prefix with COMPOUNDFORBIDFLAG - -// Flags for postponed prefixes in "sl_pidxs". Must be above affixID (one -// byte) and prefcondnr (two bytes). -#define WF_RAREPFX (WFP_RARE << 24) // rare postponed prefix -#define WF_PFX_NC (WFP_NC << 24) // non-combining postponed prefix -#define WF_PFX_UP (WFP_UP << 24) // to-upper postponed prefix -#define WF_PFX_COMPPERMIT (WFP_COMPPERMIT << 24) // postponed prefix with - // COMPOUNDPERMITFLAG -#define WF_PFX_COMPFORBID (WFP_COMPFORBID << 24) // postponed prefix with - // COMPOUNDFORBIDFLAG - - -// flags for <compoptions> -#define COMP_CHECKDUP 1 // CHECKCOMPOUNDDUP -#define COMP_CHECKREP 2 // CHECKCOMPOUNDREP -#define COMP_CHECKCASE 4 // CHECKCOMPOUNDCASE -#define COMP_CHECKTRIPLE 8 // CHECKCOMPOUNDTRIPLE - -// 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... -#define BY_NOFLAGS 0 // end of word without flags or region; for - // postponed prefix: no <pflags> -#define BY_INDEX 1 // child is shared, index follows -#define BY_FLAGS 2 // end of word, <flags> byte follows; for - // postponed prefix: <pflags> follows -#define BY_FLAGS2 3 // end of word, <flags> and <flags2> bytes - // follow; never used in prefix tree -#define BY_SPECIAL BY_FLAGS2 // highest special byte value - -// Info from "REP", "REPSAL" and "SAL" entries in ".aff" file used in si_rep, -// si_repsal, sl_rep, and si_sal. Not for sl_sal! -// One replacement: from "ft_from" to "ft_to". -typedef struct fromto_S { - char_u *ft_from; - char_u *ft_to; -} fromto_T; - -// Info from "SAL" entries in ".aff" file used in sl_sal. -// 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. - 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" -} salitem_T; - -typedef int salfirst_T; - -// Values for SP_*ERROR are negative, positive values are used by -// read_cnt_string(). -#define SP_TRUNCERROR -1 // spell file truncated error -#define SP_FORMERROR -2 // format error in spell file -#define SP_OTHERERROR -3 // other error while reading spell file - -// Structure used to store words and other info for one language, loaded from -// a .spl file. -// The main access is through the tree in "sl_fbyts/sl_fidxs", storing the -// case-folded words. "sl_kbyts/sl_kidxs" is for keep-case words. -// -// The "byts" array stores the possible bytes in each tree node, preceded by -// the number of possible bytes, sorted on byte value: -// <len> <byte1> <byte2> ... -// The "idxs" array stores the index of the child node corresponding to the -// byte in "byts". -// Exception: when the byte is zero, the word may end here and "idxs" holds -// the flags, region mask and affixID for the word. There may be several -// zeros in sequence for alternative flag/region/affixID combinations. -typedef struct slang_S slang_T; - -struct slang_S { - slang_T *sl_next; // next language - char_u *sl_name; // language name "en", "en.rare", "nl", etc. - char_u *sl_fname; // name of .spl file - bool sl_add; // true if it's a .add file. - - char_u *sl_fbyts; // case-folded word bytes - idx_T *sl_fidxs; // case-folded word indexes - char_u *sl_kbyts; // keep-case word bytes - idx_T *sl_kidxs; // keep-case word indexes - char_u *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[17]; // table with up to 8 region names plus NUL - - char_u *sl_midword; // MIDWORD string or NULL - - hashtab_T sl_wordcount; // hashtable with word count, wordcount_T - - int sl_compmax; // COMPOUNDWORDMAX (default: MAXWLEN) - int sl_compminlen; // COMPOUNDMIN (default: 0) - int sl_compsylmax; // COMPOUNDSYLMAX (default: MAXWLEN) - int sl_compoptions; // COMP_* flags - 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 - 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 - - int sl_prefixcnt; // number of items in "sl_prefprog" - regprog_T **sl_prefprog; // table with regprogs for prefixes - - garray_T sl_rep; // list of fromto_T entries from REP lines - int16_t sl_rep_first[256]; // indexes where byte first appears, -1 if - // there is none - garray_T sl_sal; // list of salitem_T entries from SAL lines - salfirst_T sl_sal_first[256]; // indexes where byte first appears, -1 if - // there is none - bool sl_followup; // SAL followup - bool sl_collapse; // SAL collapse_result - bool sl_rem_accents; // SAL remove_accents - bool sl_sofo; // SOFOFROM and SOFOTO instead of SAL items: - // "sl_sal_first" maps chars, when has_mbyte - // "sl_sal" is a list of wide char lists. - garray_T sl_repsal; // list of fromto_T entries from REPSAL lines - int16_t sl_repsal_first[256]; // sl_rep_first for REPSAL lines - bool sl_nosplitsugs; // don't suggest splitting a word - bool sl_nocompoundsugs; // don't suggest compounding - - // Info from the .sug file. Loaded on demand. - time_t sl_sugtime; // timestamp for .sug file - char_u *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 - // load - - bool sl_has_map; // true, if there is a MAP line - hashtab_T sl_map_hash; // MAP for multi-byte chars - int sl_map_array[256]; // MAP for first 256 chars - hashtab_T sl_sounddone; // table with soundfolded words that have - // handled, see add_sound_suggest() -}; - -// First language that is loaded, start of the linked list of loaded -// languages. -static slang_T *first_lang = NULL; - -// Flags used in .spl file for soundsalike flags. -#define SAL_F0LLOWUP 1 -#define SAL_COLLAPSE 2 -#define SAL_REM_ACCENTS 4 - -// Structure used in "b_langp", filled from 'spelllang'. -typedef struct langp_S { - slang_T *lp_slang; // info for this language - slang_T *lp_sallang; // language used for sound folding or NULL - slang_T *lp_replang; // language used for REP items or NULL - int lp_region; // bitmask for region or REGION_ALL -} langp_T; - -#define LANGP_ENTRY(ga, i) (((langp_T *)(ga).ga_data) + (i)) - -#define REGION_ALL 0xff // word valid in all regions - -#define VIMSPELLMAGIC "VIMspell" // string at start of Vim spell file -#define VIMSPELLMAGICL 8 -#define VIMSPELLVERSION 50 - -#define VIMSUGMAGIC "VIMsug" // string at start of Vim .sug file -#define VIMSUGMAGICL 6 -#define VIMSUGVERSION 1 - -// Section IDs. Only renumber them when VIMSPELLVERSION changes! -#define SN_REGION 0 // <regionname> section -#define SN_CHARFLAGS 1 // charflags section -#define SN_MIDWORD 2 // <midword> section -#define SN_PREFCOND 3 // <prefcond> section -#define SN_REP 4 // REP items section -#define SN_SAL 5 // SAL items section -#define SN_SOFO 6 // soundfolding section -#define SN_MAP 7 // MAP items section -#define SN_COMPOUND 8 // compound words section -#define SN_SYLLABLE 9 // syllable section -#define SN_NOBREAK 10 // NOBREAK section -#define SN_SUGFILE 11 // timestamp for .sug file -#define SN_REPSAL 12 // REPSAL items section -#define SN_WORDS 13 // common words -#define SN_NOSPLITSUGS 14 // don't split word for suggestions -#define SN_INFO 15 // info section -#define SN_NOCOMPOUNDSUGS 16 // don't compound for suggestions -#define SN_END 255 // end of sections - -#define SNF_REQUIRED 1 // <sectionflags>: required section - // Result values. Lower number is accepted over higher one. #define SP_BANNED -1 #define SP_RARE 0 @@ -575,17 +128,20 @@ typedef struct langp_S { #define SP_LOCAL 2 #define SP_BAD 3 +// First language that is loaded, start of the linked list of loaded +// languages. +slang_T *first_lang = NULL; + // file used for "zG" and "zW" -static char_u *int_wordlist = NULL; +char_u *int_wordlist = NULL; typedef struct wordcount_S { uint16_t wc_count; // nr of times word was seen char_u wc_word[1]; // word, actually longer } wordcount_T; -static wordcount_T dumwc; -#define WC_KEY_OFF (unsigned)(dumwc.wc_word - (char_u *)&dumwc) -#define HI2WC(hi) ((wordcount_T *)((hi)->hi_key - WC_KEY_OFF)) +#define WC_KEY_OFF offsetof(wordcount_T, wc_word) +#define HI2WC(hi) ((wordcount_T *)((hi)->hi_key - WC_KEY_OFF)) #define MAXWORDCOUNT 0xffff // Information used when looking for suggestions. @@ -716,65 +272,6 @@ typedef struct matchinf_S { char_u *mi_end2; // "mi_end" without following word } matchinf_T; -// The tables used for recognizing word characters according to spelling. -// These are only used for the first 256 characters of 'encoding'. -typedef struct { - bool st_isw[256]; // flags: is word char - bool st_isu[256]; // flags: is uppercase char - char_u st_fold[256]; // chars: folded case - char_u st_upper[256]; // chars: upper case -} spelltab_T; - -// For finding suggestions: At each node in the tree these states are tried: -typedef enum { - STATE_START = 0, // At start of node check for NUL bytes (goodword - // ends); if badword ends there is a match, otherwise - // try splitting word. - STATE_NOPREFIX, // try without prefix - STATE_SPLITUNDO, // Undo splitting. - STATE_ENDNUL, // Past NUL bytes at start of the node. - STATE_PLAIN, // Use each byte of the node. - STATE_DEL, // Delete a byte from the bad word. - STATE_INS_PREP, // Prepare for inserting bytes. - STATE_INS, // Insert a byte in the bad word. - STATE_SWAP, // Swap two bytes. - STATE_UNSWAP, // Undo swap two characters. - STATE_SWAP3, // Swap two characters over three. - STATE_UNSWAP3, // Undo Swap two characters over three. - STATE_UNROT3L, // Undo rotate three characters left - STATE_UNROT3R, // Undo rotate three characters right - STATE_REP_INI, // Prepare for using REP items. - STATE_REP, // Use matching REP items from the .aff file. - STATE_REP_UNDO, // Undo a REP item replacement. - STATE_FINAL // End of this node. -} state_T; - -// Struct to keep the state at each level in suggest_try_change(). -typedef struct trystate_S { - state_T ts_state; // state at this level, STATE_ - int ts_score; // score - idx_T ts_arridx; // index in tree array, start of node - short ts_curi; // index in list of child nodes - char_u ts_fidx; // index in fword[], case-folded bad word - char_u ts_fidxtry; // ts_fidx at which bytes may be changed - char_u ts_twordlen; // valid length of tword[] - char_u ts_prefixdepth; // stack depth for end of prefix or - // PFD_PREFIXTREE or PFD_NOPREFIX - char_u ts_flags; // TSF_ flags - char_u ts_tcharlen; // number of bytes in tword character - char_u ts_tcharidx; // current byte index in tword character - char_u ts_isdiff; // DIFF_ values - char_u ts_fcharstart; // index in fword where badword char started - char_u ts_prewordlen; // length of word in "preword[]" - char_u ts_splitoff; // index in "tword" after last split - char_u ts_splitfidx; // "ts_fidx" at word split - char_u ts_complen; // nr of compound words used - char_u ts_compsplit; // index for "compflags" where word was spit - char_u ts_save_badflags; // su_badflags saved here - char_u ts_delidx; // index in fword for char that was deleted, - // valid when "ts_flags" has TSF_DIDDEL -} trystate_T; - // Structure used for the cookie argument of do_in_runtimepath(). typedef struct spelload_S { char_u sl_lang[MAXWLEN + 1]; // language name @@ -788,200 +285,8 @@ typedef struct syl_item_S { int sy_len; } syl_item_T; -#define MAXLINELEN 500 // Maximum length in bytes of a line in a .aff - // 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 - 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 - unsigned af_bad; // BAD ID for banned word - unsigned af_needaffix; // NEEDAFFIX ID - unsigned af_circumfix; // CIRCUMFIX ID - unsigned af_needcomp; // NEEDCOMPOUND ID - unsigned af_comproot; // COMPOUNDROOT ID - unsigned af_compforbid; // COMPOUNDFORBIDFLAG ID - unsigned af_comppermit; // COMPOUNDPERMITFLAG ID - unsigned af_nosuggest; // NOSUGGEST ID - int af_pfxpostpone; // postpone prefixes without chop string and - // without flags - bool af_ignoreextra; // IGNOREEXTRA present - hashtab_T af_pref; // hashtable for prefixes, affheader_T - hashtab_T af_suff; // hashtable for suffixes, affheader_T - hashtab_T af_comp; // hashtable for compound flags, compitem_T -} afffile_T; - -#define AFT_CHAR 0 // flags are one character -#define AFT_LONG 1 // flags are two characters -#define AFT_CAPLONG 2 // flags are one or two characters -#define AFT_NUM 3 // flags are numbers, comma separated - -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_u *ae_chop; // text to chop off basic word (can be NULL) - char_u *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 - char ae_compforbid; // COMPOUNDFORBIDFLAG found - char ae_comppermit; // COMPOUNDPERMITFLAG found -}; - -# define AH_KEY_LEN 17 // 2 x 8 bytes + NUL - -// Affix header from ".aff" file. Used for af_pref and af_suff. -typedef struct affheader_S { - char_u ah_key[AH_KEY_LEN]; // key for hashtab == name of affix - unsigned ah_flag; // affix name as number, uses "af_flagtype" - int ah_newID; // prefix ID after renumbering; 0 if not used - int ah_combine; // suffix may combine with prefix - int ah_follows; // another affix block should be following - affentry_T *ah_first; // first affix entry -} affheader_T; - -#define HI2AH(hi) ((affheader_T *)(hi)->hi_key) - -// Flag used in compound items. -typedef struct compitem_S { - char_u ci_key[AH_KEY_LEN]; // key for hashtab == name of compound - unsigned ci_flag; // affix name as number, uses "af_flagtype" - int ci_newID; // affix ID after renumbering. -} compitem_T; - -#define HI2CI(hi) ((compitem_T *)(hi)->hi_key) - -// Structure that is used to store the items in the word tree. This avoids -// the need to keep track of each allocated thing, everything is freed all at -// once after ":mkspell" is done. -// Note: "sb_next" must be just before "sb_data" to make sure the alignment of -// "sb_data" is correct for systems where pointers must be aligned on -// pointer-size boundaries and sizeof(pointer) > sizeof(int) (e.g., Sparc). -#define SBLOCKSIZE 16000 // size of sb_data -typedef struct sblock_S sblock_T; -struct sblock_S { - int sb_used; // nr of bytes already in use - sblock_T *sb_next; // next block in list - char_u sb_data[1]; // data, actually longer -}; - -// A node in the tree. -typedef struct wordnode_S wordnode_T; -struct wordnode_S { - union // shared to save space - { - char_u hashkey[6]; // the hash key, only used while compressing - int index; // index in written nodes (valid after first - // round) - } wn_u1; - union // shared to save space - { - wordnode_T *next; // next node with same hash key - wordnode_T *wnode; // parent node that will write this node - } wn_u2; - wordnode_T *wn_child; // child (next byte in word) - wordnode_T *wn_sibling; // next sibling (alternate byte in word, - // always sorted) - int wn_refs; // Nr. of references to this node. Only - // relevant for first node in a list of - // siblings, in following siblings it is - // always one. - char_u wn_byte; // Byte for this node. NUL for word end - - // Info for when "wn_byte" is NUL. - // In PREFIXTREE "wn_region" is used for the prefcondnr. - // In the soundfolded word tree "wn_flags" has the MSW of the wordnr and - // "wn_region" the LSW of the wordnr. - char_u wn_affixID; // supported/required prefix ID or 0 - uint16_t wn_flags; // WF_ flags - short wn_region; // region mask - -#ifdef SPELL_PRINTTREE - int wn_nr; // sequence nr for printing -#endif -}; - -#define WN_MASK 0xffff // mask relevant bits of "wn_flags" - -#define HI2WN(hi) (wordnode_T *)((hi)->hi_key) - -// Info used while reading the spell files. -typedef struct spellinfo_S { - wordnode_T *si_foldroot; // tree with case-folded words - long si_foldwcount; // nr of words in si_foldroot - - wordnode_T *si_keeproot; // tree with keep-case words - long si_keepwcount; // nr of words in si_keeproot - - wordnode_T *si_prefroot; // tree with postponed prefixes - - long si_sugtree; // creating the soundfolding trie - - sblock_T *si_blocks; // memory blocks used - long si_blocks_cnt; // memory blocks allocated - int si_did_emsg; // TRUE when ran out of memory - - long si_compress_cnt; // words to add before lowering - // compression limit - wordnode_T *si_first_free; // List of nodes that have been freed during - // compression, linked by "wn_child" field. - long si_free_count; // number of nodes in si_first_free -#ifdef SPELL_PRINTTREE - int si_wordnode_nr; // sequence nr for nodes -#endif - buf_T *si_spellbuf; // buffer used to store soundfold word table - - int si_ascii; // handling only ASCII words - int si_add; // addition file - int si_clear_chartab; // when TRUE clear char tables - int si_region; // region mask - vimconv_T si_conv; // for conversion to 'encoding' - int si_memtot; // runtime memory used - int si_verbose; // verbose messages - int si_msg_count; // number of words added since last message - char_u *si_info; // info text chars or NULL - int si_region_count; // number of regions supported (1 when there - // are no regions) - char_u si_region_name[17]; // region names; used only if - // si_region_count > 1) - - garray_T si_rep; // list of fromto_T entries from REP lines - garray_T si_repsal; // list of fromto_T entries from REPSAL lines - garray_T si_sal; // list of fromto_T entries from SAL lines - char_u *si_sofofr; // SOFOFROM text - char_u *si_sofoto; // SOFOTO text - int si_nosugfile; // NOSUGFILE item found - int si_nosplitsugs; // NOSPLITSUGS item found - int si_nocompoundsugs; // NOCOMPOUNDSUGS item found - int si_followup; // soundsalike: ? - int si_collapse; // soundsalike: ? - hashtab_T si_commonwords; // hashtable for common words - time_t si_sugtime; // timestamp for .sug file - int si_rem_accents; // soundsalike: remove accents - garray_T si_map; // MAP info concatenated - char_u *si_midword; // MIDWORD chars or NULL - int si_compmax; // max nr of words for compounding - int si_compminlen; // minimal length for compounding - int si_compsylmax; // max nr of syllables for compounding - int si_compoptions; // COMP_ flags - garray_T si_comppat; // CHECKCOMPOUNDPATTERN items, each stored as - // a string - char_u *si_compflags; // flags used for compounding - char_u si_nobreak; // NOBREAK - char_u *si_syllable; // syllable string - garray_T si_prefcond; // table with conditions for postponed - // prefixes, each stored as a string - int si_newprefID; // current value for ah_newID - int si_newcompID; // current value for compound ID -} spellinfo_T; - -static spelltab_T spelltab; -static int did_set_spelltab; - -#define CF_WORD 0x01 -#define CF_UPPER 0x02 +spelltab_T spelltab; +int did_set_spelltab; // structure used to store soundfolded words that add_sound_suggest() has // handled already. @@ -1023,34 +328,7 @@ typedef struct { #define FIND_COMPOUND 3 // find case-folded compound word #define FIND_KEEPCOMPOUND 4 // find keep-case compound word - -// Use our own character-case definitions, because the current locale may -// differ from what the .spl file uses. -// These must not be called with negative number! -#include <wchar.h> // for towupper() and towlower() -// Multi-byte implementation. For Unicode we can call utf_*(), but don't do -// that for ASCII, because we don't want to use 'casemap' here. Otherwise use -// the "w" library function for characters above 255. -#define SPELL_TOFOLD(c) (enc_utf8 && (c) >= 128 ? utf_fold(c) \ - : (c) < \ - 256 ? (int)spelltab.st_fold[c] : (int)towlower(c)) - -#define SPELL_TOUPPER(c) (enc_utf8 && (c) >= 128 ? utf_toupper(c) \ - : (c) < \ - 256 ? (int)spelltab.st_upper[c] : (int)towupper(c)) - -#define SPELL_ISUPPER(c) (enc_utf8 && (c) >= 128 ? utf_isupper(c) \ - : (c) < 256 ? spelltab.st_isu[c] : iswupper(c)) - - -static char *e_format = N_("E759: Format error in spell file"); -static char *e_spell_trunc = N_("E758: Truncated spell file"); -static char *e_afftrailing = N_("Trailing text in %s line %d: %s"); -static char *e_affname = N_("Affix name too long in %s line %d: %s"); -static char *e_affform = N_("E761: Format error in affix file FOL, LOW or UPP"); -static char *e_affrange = N_( - "E762: Character in FOL, LOW or UPP is out of range"); -static char *msg_compressing = N_("Compressing word tree..."); +char *e_format = N_("E759: Format error in spell file"); // Remember what "z?" replaced. static char_u *repl_from = NULL; @@ -2155,12 +1433,10 @@ spell_move_to ( // the cursor. if (dir == BACKWARD || lnum != wp->w_cursor.lnum - || (lnum == wp->w_cursor.lnum - && (wrapped - || ((colnr_T)(curline - ? p - buf + (ptrdiff_t)len - : p - buf) - > wp->w_cursor.col)))) { + || wrapped + || ((colnr_T)(curline + ? p - buf + (ptrdiff_t)len + : p - buf) > wp->w_cursor.col)) { if (has_syntax) { col = (int)(p - buf); (void)syn_get_id(wp, lnum, (colnr_T)col, @@ -2357,7 +1633,7 @@ 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). -static char_u *spell_enc(void) +char_u *spell_enc(void) { if (STRLEN(p_enc) < 60 && STRCMP(p_enc, "iso-8859-15") != 0) @@ -2375,7 +1651,7 @@ static void int_wordlist_spl(char_u *fname) // Allocate a new slang_T for language "lang". "lang" can be NULL. // Caller must fill "sl_next". -static slang_T *slang_alloc(char_u *lang) +slang_T *slang_alloc(char_u *lang) { slang_T *lp = xcalloc(1, sizeof(slang_T)); @@ -2391,7 +1667,7 @@ static slang_T *slang_alloc(char_u *lang) } // Free the contents of an slang_T and the structure itself. -static void slang_free(slang_T *lp) +void slang_free(slang_T *lp) { xfree(lp->sl_name); xfree(lp->sl_fname); @@ -2416,7 +1692,7 @@ static void free_fromto(fromto_T *ftp) { } // Clear an slang_T so that the file can be reloaded. -static void slang_clear(slang_T *lp) +void slang_clear(slang_T *lp) { garray_T *gap; @@ -2489,7 +1765,7 @@ static void slang_clear(slang_T *lp) } // Clear the info from the .sug file in "lp". -static void slang_clear_sug(slang_T *lp) +void slang_clear_sug(slang_T *lp) { xfree(lp->sl_sbyts); lp->sl_sbyts = NULL; @@ -2521,562 +1797,14 @@ static void spell_load_cb(char_u *fname, void *cookie) } } -// Load one spell file and store the info into a slang_T. -// -// This is invoked in three ways: -// - From spell_load_cb() to load a spell file for the first time. "lang" is -// the language name, "old_lp" is NULL. Will allocate an slang_T. -// - To reload a spell file that was changed. "lang" is NULL and "old_lp" -// points to the existing slang_T. -// - Just after writing a .spl file; it's read back to produce the .sug file. -// "old_lp" is NULL and "lang" is NULL. Will allocate an slang_T. -// -// Returns the slang_T the spell file was loaded into. NULL for error. -static slang_T * -spell_load_file ( - char_u *fname, - char_u *lang, - slang_T *old_lp, - bool silent // no error if file doesn't exist -) -{ - FILE *fd; - char_u buf[VIMSPELLMAGICL]; - char_u *p; - int i; - int n; - int len; - char_u *save_sourcing_name = sourcing_name; - linenr_T save_sourcing_lnum = sourcing_lnum; - slang_T *lp = NULL; - int c = 0; - int res; - - fd = mch_fopen((char *)fname, "r"); - if (fd == NULL) { - if (!silent) - EMSG2(_(e_notopen), fname); - else if (p_verbose > 2) { - verbose_enter(); - smsg((char *)e_notopen, fname); - verbose_leave(); - } - goto endFAIL; - } - if (p_verbose > 2) { - verbose_enter(); - smsg(_("Reading spell file \"%s\""), fname); - verbose_leave(); - } - - if (old_lp == NULL) { - lp = slang_alloc(lang); - - // Remember the file name, used to reload the file when it's updated. - lp->sl_fname = vim_strsave(fname); - - // Check for .add.spl. - lp->sl_add = strstr((char *)path_tail(fname), SPL_FNAME_ADD) != NULL; - } else - lp = old_lp; - - // Set sourcing_name, so that error messages mention the file name. - sourcing_name = fname; - sourcing_lnum = 0; - - // <HEADER>: <fileID> - for (i = 0; i < VIMSPELLMAGICL; ++i) - buf[i] = getc(fd); // <fileID> - if (STRNCMP(buf, VIMSPELLMAGIC, VIMSPELLMAGICL) != 0) { - EMSG(_("E757: This does not look like a spell file")); - goto endFAIL; - } - c = getc(fd); // <versionnr> - if (c < VIMSPELLVERSION) { - EMSG(_("E771: Old spell file, needs to be updated")); - goto endFAIL; - } else if (c > VIMSPELLVERSION) { - EMSG(_("E772: Spell file is for newer version of Vim")); - goto endFAIL; - } - - - // <SECTIONS>: <section> ... <sectionend> - // <section>: <sectionID> <sectionflags> <sectionlen> (section contents) - for (;; ) { - n = getc(fd); // <sectionID> or <sectionend> - if (n == SN_END) - break; - c = getc(fd); // <sectionflags> - len = get4c(fd); // <sectionlen> - if (len < 0) - goto truncerr; - - res = 0; - switch (n) { - case SN_INFO: - lp->sl_info = READ_STRING(fd, len); // <infotext> - if (lp->sl_info == NULL) - goto endFAIL; - break; - - case SN_REGION: - res = read_region_section(fd, lp, len); - break; - - case SN_CHARFLAGS: - res = read_charflags_section(fd); - break; - - case SN_MIDWORD: - lp->sl_midword = READ_STRING(fd, len); // <midword> - if (lp->sl_midword == NULL) - goto endFAIL; - break; - - case SN_PREFCOND: - res = read_prefcond_section(fd, lp); - break; - - case SN_REP: - res = read_rep_section(fd, &lp->sl_rep, lp->sl_rep_first); - break; - - case SN_REPSAL: - res = read_rep_section(fd, &lp->sl_repsal, lp->sl_repsal_first); - break; - - case SN_SAL: - res = read_sal_section(fd, lp); - break; - - case SN_SOFO: - res = read_sofo_section(fd, lp); - break; - - case SN_MAP: - p = READ_STRING(fd, len); // <mapstr> - if (p == NULL) - goto endFAIL; - set_map_str(lp, p); - xfree(p); - break; - - case SN_WORDS: - res = read_words_section(fd, lp, len); - break; - - case SN_SUGFILE: - lp->sl_sugtime = get8ctime(fd); // <timestamp> - break; - - case SN_NOSPLITSUGS: - lp->sl_nosplitsugs = true; - break; - - case SN_NOCOMPOUNDSUGS: - lp->sl_nocompoundsugs = true; - break; - - case SN_COMPOUND: - res = read_compound(fd, lp, len); - break; - - case SN_NOBREAK: - lp->sl_nobreak = true; - break; - - case SN_SYLLABLE: - lp->sl_syllable = READ_STRING(fd, len); // <syllable> - if (lp->sl_syllable == NULL) - goto endFAIL; - if (init_syl_tab(lp) == FAIL) - goto endFAIL; - break; - - default: - // Unsupported section. When it's required give an error - // message. When it's not required skip the contents. - if (c & SNF_REQUIRED) { - EMSG(_("E770: Unsupported section in spell file")); - goto endFAIL; - } - while (--len >= 0) - if (getc(fd) < 0) - goto truncerr; - break; - } -someerror: - if (res == SP_FORMERROR) { - EMSG(_(e_format)); - goto endFAIL; - } - if (res == SP_TRUNCERROR) { -truncerr: - EMSG(_(e_spell_trunc)); - goto endFAIL; - } - if (res == SP_OTHERERROR) - goto endFAIL; - } - - // <LWORDTREE> - res = spell_read_tree(fd, &lp->sl_fbyts, &lp->sl_fidxs, false, 0); - if (res != 0) - goto someerror; - - // <KWORDTREE> - res = spell_read_tree(fd, &lp->sl_kbyts, &lp->sl_kidxs, false, 0); - if (res != 0) - goto someerror; - - // <PREFIXTREE> - res = spell_read_tree(fd, &lp->sl_pbyts, &lp->sl_pidxs, true, - lp->sl_prefixcnt); - if (res != 0) - goto someerror; - - // For a new file link it in the list of spell files. - if (old_lp == NULL && lang != NULL) { - lp->sl_next = first_lang; - first_lang = lp; - } - - goto endOK; - -endFAIL: - if (lang != NULL) - // truncating the name signals the error to spell_load_lang() - *lang = NUL; - if (lp != NULL && old_lp == NULL) - slang_free(lp); - lp = NULL; - -endOK: - if (fd != NULL) - fclose(fd); - sourcing_name = save_sourcing_name; - sourcing_lnum = save_sourcing_lnum; - - return lp; -} - -// Read a length field from "fd" in "cnt_bytes" bytes. -// Allocate memory, read the string into it and add a NUL at the end. -// Returns NULL when the count is zero. -// Sets "*cntp" to SP_*ERROR when there is an error, length of the result -// otherwise. -static char_u *read_cnt_string(FILE *fd, int cnt_bytes, int *cntp) -{ - int cnt = 0; - int i; - char_u *str; - - // read the length bytes, MSB first - for (i = 0; i < cnt_bytes; ++i) - cnt = (cnt << 8) + getc(fd); - if (cnt < 0) { - *cntp = SP_TRUNCERROR; - return NULL; - } - *cntp = cnt; - if (cnt == 0) - return NULL; // nothing to read, return NULL - - str = READ_STRING(fd, cnt); - if (str == NULL) - *cntp = SP_OTHERERROR; - return str; -} - -// Read SN_REGION: <regionname> ... -// Return SP_*ERROR flags. -static int read_region_section(FILE *fd, slang_T *lp, int len) -{ - int i; - - if (len > 16) - return SP_FORMERROR; - for (i = 0; i < len; ++i) - lp->sl_regions[i] = getc(fd); // <regionname> - lp->sl_regions[len] = NUL; - return 0; -} - -// Read SN_CHARFLAGS section: <charflagslen> <charflags> -// <folcharslen> <folchars> -// Return SP_*ERROR flags. -static int read_charflags_section(FILE *fd) -{ - char_u *flags; - char_u *fol; - int flagslen, follen; - - // <charflagslen> <charflags> - flags = read_cnt_string(fd, 1, &flagslen); - if (flagslen < 0) - return flagslen; - - // <folcharslen> <folchars> - fol = read_cnt_string(fd, 2, &follen); - if (follen < 0) { - xfree(flags); - return follen; - } - - // Set the word-char flags and fill SPELL_ISUPPER() table. - if (flags != NULL && fol != NULL) - set_spell_charflags(flags, flagslen, fol); - - xfree(flags); - xfree(fol); - - // When <charflagslen> is zero then <fcharlen> must also be zero. - if ((flags == NULL) != (fol == NULL)) - return SP_FORMERROR; - return 0; -} - -// Read SN_PREFCOND section. -// Return SP_*ERROR flags. -static int read_prefcond_section(FILE *fd, slang_T *lp) -{ - int cnt; - int i; - int n; - char_u *p; - char_u buf[MAXWLEN + 1]; - - // <prefcondcnt> <prefcond> ... - cnt = get2c(fd); // <prefcondcnt> - if (cnt <= 0) - return SP_FORMERROR; - - lp->sl_prefprog = xcalloc(cnt, sizeof(regprog_T *)); - lp->sl_prefixcnt = cnt; - - for (i = 0; i < cnt; ++i) { - // <prefcond> : <condlen> <condstr> - n = getc(fd); // <condlen> - if (n < 0 || n >= MAXWLEN) - return SP_FORMERROR; - - // When <condlen> is zero we have an empty condition. Otherwise - // compile the regexp program used to check for the condition. - if (n > 0) { - buf[0] = '^'; // always match at one position only - p = buf + 1; - while (n-- > 0) - *p++ = getc(fd); // <condstr> - *p = NUL; - lp->sl_prefprog[i] = vim_regcomp(buf, RE_MAGIC + RE_STRING); - } - } - return 0; -} - -// Read REP or REPSAL items section from "fd": <repcount> <rep> ... -// Return SP_*ERROR flags. -static int read_rep_section(FILE *fd, garray_T *gap, int16_t *first) -{ - int cnt; - fromto_T *ftp; - - cnt = get2c(fd); // <repcount> - if (cnt < 0) - return SP_TRUNCERROR; - - ga_grow(gap, cnt); - - // <rep> : <repfromlen> <repfrom> <reptolen> <repto> - for (; gap->ga_len < cnt; ++gap->ga_len) { - int c; - ftp = &((fromto_T *)gap->ga_data)[gap->ga_len]; - ftp->ft_from = read_cnt_string(fd, 1, &c); - if (c < 0) - return c; - if (c == 0) - return SP_FORMERROR; - ftp->ft_to = read_cnt_string(fd, 1, &c); - if (c <= 0) { - xfree(ftp->ft_from); - if (c < 0) - return c; - return SP_FORMERROR; - } - } - - // Fill the first-index table. - for (int i = 0; i < 256; ++i) { - first[i] = -1; - } - for (int i = 0; i < gap->ga_len; ++i) { - ftp = &((fromto_T *)gap->ga_data)[i]; - if (first[*ftp->ft_from] == -1) - first[*ftp->ft_from] = i; - } - return 0; -} - -// Read SN_SAL section: <salflags> <salcount> <sal> ... -// Return SP_*ERROR flags. -static int read_sal_section(FILE *fd, slang_T *slang) -{ - int i; - int cnt; - garray_T *gap; - salitem_T *smp; - int ccnt; - char_u *p; - int c = NUL; - - slang->sl_sofo = false; - - i = getc(fd); // <salflags> - if (i & SAL_F0LLOWUP) - slang->sl_followup = true; - if (i & SAL_COLLAPSE) - slang->sl_collapse = true; - if (i & SAL_REM_ACCENTS) - slang->sl_rem_accents = true; - - cnt = get2c(fd); // <salcount> - if (cnt < 0) - return SP_TRUNCERROR; - - gap = &slang->sl_sal; - ga_init(gap, sizeof(salitem_T), 10); - ga_grow(gap, cnt + 1); - - // <sal> : <salfromlen> <salfrom> <saltolen> <salto> - for (; gap->ga_len < cnt; ++gap->ga_len) { - smp = &((salitem_T *)gap->ga_data)[gap->ga_len]; - ccnt = getc(fd); // <salfromlen> - if (ccnt < 0) - return SP_TRUNCERROR; - p = xmalloc(ccnt + 2); - smp->sm_lead = p; - - // Read up to the first special char into sm_lead. - for (i = 0; i < ccnt; ++i) { - c = getc(fd); // <salfrom> - if (vim_strchr((char_u *)"0123456789(-<^$", c) != NULL) - break; - *p++ = c; - } - smp->sm_leadlen = (int)(p - smp->sm_lead); - *p++ = NUL; - - // Put (abc) chars in sm_oneof, if any. - if (c == '(') { - smp->sm_oneof = p; - for (++i; i < ccnt; ++i) { - c = getc(fd); // <salfrom> - if (c == ')') - break; - *p++ = c; - } - *p++ = NUL; - if (++i < ccnt) - c = getc(fd); - } else - smp->sm_oneof = NULL; - - // Any following chars go in sm_rules. - smp->sm_rules = p; - if (i < ccnt) - // store the char we got while checking for end of sm_lead - *p++ = c; - for (++i; i < ccnt; ++i) - *p++ = getc(fd); // <salfrom> - *p++ = NUL; - - // <saltolen> <salto> - smp->sm_to = read_cnt_string(fd, 1, &ccnt); - if (ccnt < 0) { - xfree(smp->sm_lead); - return ccnt; - } - - if (has_mbyte) { - // convert the multi-byte strings to wide char strings - smp->sm_lead_w = mb_str2wide(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); - if (smp->sm_to == NULL) - smp->sm_to_w = NULL; - else - smp->sm_to_w = mb_str2wide(smp->sm_to); - } - } - - if (!GA_EMPTY(gap)) { - // Add one extra entry to mark the end with an empty sm_lead. Avoids - // that we need to check the index every time. - smp = &((salitem_T *)gap->ga_data)[gap->ga_len]; - p = xmalloc(1); - p[0] = NUL; - smp->sm_lead = p; - smp->sm_leadlen = 0; - smp->sm_oneof = NULL; - smp->sm_rules = p; - smp->sm_to = NULL; - if (has_mbyte) { - smp->sm_lead_w = mb_str2wide(smp->sm_lead); - smp->sm_leadlen = 0; - smp->sm_oneof_w = NULL; - smp->sm_to_w = NULL; - } - ++gap->ga_len; - } - - // Fill the first-index table. - set_sal_first(slang); - - return 0; -} - -// Read SN_WORDS: <word> ... -// Return SP_*ERROR flags. -static int read_words_section(FILE *fd, slang_T *lp, int len) -{ - int done = 0; - int i; - int c; - char_u word[MAXWLEN]; - - while (done < len) { - // Read one word at a time. - for (i = 0;; ++i) { - c = getc(fd); - if (c == EOF) - return SP_TRUNCERROR; - word[i] = c; - if (word[i] == NUL) - break; - if (i == MAXWLEN - 1) - return SP_FORMERROR; - } - - // Init the count to 10. - count_common_word(lp, word, -1, 10); - done += i + 1; - } - return 0; -} - -// Add a word to the hashtable of common words. -// If it's already there then the counter is increased. -static void -count_common_word ( - slang_T *lp, - char_u *word, - int len, // word length, -1 for upto NUL - int count // 1 to count once, 10 to init -) +/// Add a word to the hashtable of common words. +/// If it's already there then the counter is increased. +/// +/// @param[in] lp +/// @param[in] word added to common words hashtable +/// @param[in] len length of word or -1 for NUL terminated +/// @param[in] count 1 to count once, 10 to init +void count_common_word(slang_T *lp, char_u *word, int len, int count) { hash_T hash; hashitem_T *hi; @@ -3092,10 +1820,11 @@ count_common_word ( } hash = hash_hash(p); - hi = hash_lookup(&lp->sl_wordcount, p, hash); + const size_t p_len = STRLEN(p); + hi = hash_lookup(&lp->sl_wordcount, (const char *)p, p_len, hash); if (HASHITEM_EMPTY(hi)) { - wc = xmalloc(sizeof(wordcount_T) + STRLEN(p)); - STRCPY(wc->wc_word, p); + wc = xmalloc(sizeof(wordcount_T) + p_len); + memcpy(wc->wc_word, p, p_len + 1); wc->wc_count = count; hash_add_item(&lp->sl_wordcount, hi, wc->wc_word, hash); } else { @@ -3139,209 +1868,9 @@ score_wordcount_adj ( return score; } -// SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto> -// Return SP_*ERROR flags. -static int read_sofo_section(FILE *fd, slang_T *slang) -{ - int cnt; - char_u *from, *to; - int res; - - slang->sl_sofo = true; - - // <sofofromlen> <sofofrom> - from = read_cnt_string(fd, 2, &cnt); - if (cnt < 0) - return cnt; - - // <sofotolen> <sofoto> - to = read_cnt_string(fd, 2, &cnt); - if (cnt < 0) { - xfree(from); - return cnt; - } - - // Store the info in slang->sl_sal and/or slang->sl_sal_first. - if (from != NULL && to != NULL) - res = set_sofo(slang, from, to); - else if (from != NULL || to != NULL) - res = SP_FORMERROR; // only one of two strings is an error - else - res = 0; - - xfree(from); - xfree(to); - return res; -} - -// Read the compound section from the .spl file: -// <compmax> <compminlen> <compsylmax> <compoptions> <compflags> -// Returns SP_*ERROR flags. -static int read_compound(FILE *fd, slang_T *slang, int len) -{ - int todo = len; - int c; - int atstart; - char_u *pat; - char_u *pp; - char_u *cp; - char_u *ap; - char_u *crp; - int cnt; - garray_T *gap; - - if (todo < 2) - return SP_FORMERROR; // need at least two bytes - - --todo; - c = getc(fd); // <compmax> - if (c < 2) - c = MAXWLEN; - slang->sl_compmax = c; - - --todo; - c = getc(fd); // <compminlen> - if (c < 1) - c = 0; - slang->sl_compminlen = c; - - --todo; - c = getc(fd); // <compsylmax> - if (c < 1) - c = MAXWLEN; - slang->sl_compsylmax = c; - - c = getc(fd); // <compoptions> - if (c != 0) - ungetc(c, fd); // be backwards compatible with Vim 7.0b - else { - --todo; - c = getc(fd); // only use the lower byte for now - --todo; - slang->sl_compoptions = c; - - gap = &slang->sl_comppat; - c = get2c(fd); // <comppatcount> - todo -= 2; - ga_init(gap, sizeof(char_u *), c); - ga_grow(gap, c); - while (--c >= 0) { - ((char_u **)(gap->ga_data))[gap->ga_len++] = - read_cnt_string(fd, 1, &cnt); - // <comppatlen> <comppattext> - if (cnt < 0) - return cnt; - todo -= cnt + 1; - } - } - if (todo < 0) - return SP_FORMERROR; - - // Turn the COMPOUNDRULE items into a regexp pattern: - // "a[bc]/a*b+" -> "^\(a[bc]\|a*b\+\)$". - // Inserting backslashes may double the length, "^\(\)$<Nul>" is 7 bytes. - // Conversion to utf-8 may double the size. - c = todo * 2 + 7; - if (enc_utf8) - c += todo * 2; - pat = xmalloc(c); - - // We also need a list of all flags that can appear at the start and one - // for all flags. - cp = xmalloc(todo + 1); - slang->sl_compstartflags = cp; - *cp = NUL; - - ap = xmalloc(todo + 1); - slang->sl_compallflags = ap; - *ap = NUL; - - // And a list of all patterns in their original form, for checking whether - // compounding may work in match_compoundrule(). This is freed when we - // encounter a wildcard, the check doesn't work then. - crp = xmalloc(todo + 1); - slang->sl_comprules = crp; - - pp = pat; - *pp++ = '^'; - *pp++ = '\\'; - *pp++ = '('; - - atstart = 1; - while (todo-- > 0) { - c = getc(fd); // <compflags> - if (c == EOF) { - xfree(pat); - return SP_TRUNCERROR; - } - - // Add all flags to "sl_compallflags". - if (vim_strchr((char_u *)"?*+[]/", c) == NULL - && !byte_in_str(slang->sl_compallflags, c)) { - *ap++ = c; - *ap = NUL; - } - - if (atstart != 0) { - // At start of item: copy flags to "sl_compstartflags". For a - // [abc] item set "atstart" to 2 and copy up to the ']'. - if (c == '[') - atstart = 2; - else if (c == ']') - atstart = 0; - else { - if (!byte_in_str(slang->sl_compstartflags, c)) { - *cp++ = c; - *cp = NUL; - } - if (atstart == 1) - atstart = 0; - } - } - - // Copy flag to "sl_comprules", unless we run into a wildcard. - if (crp != NULL) { - if (c == '?' || c == '+' || c == '*') { - xfree(slang->sl_comprules); - slang->sl_comprules = NULL; - crp = NULL; - } else - *crp++ = c; - } - - if (c == '/') { // slash separates two items - *pp++ = '\\'; - *pp++ = '|'; - atstart = 1; - } else { // normal char, "[abc]" and '*' are copied as-is - if (c == '?' || c == '+' || c == '~') - *pp++ = '\\'; // "a?" becomes "a\?", "a+" becomes "a\+" - if (enc_utf8) - pp += mb_char2bytes(c, pp); - else - *pp++ = c; - } - } - - *pp++ = '\\'; - *pp++ = ')'; - *pp++ = '$'; - *pp = NUL; - - if (crp != NULL) - *crp = NUL; - - slang->sl_compprog = vim_regcomp(pat, RE_MAGIC + RE_STRING + RE_STRICT); - xfree(pat); - if (slang->sl_compprog == NULL) - return SP_FORMERROR; - - return 0; -} - // Returns true if byte "n" appears in "str". // Like strchr() but independent of locale. -static bool byte_in_str(char_u *str, int n) +bool byte_in_str(char_u *str, int n) { char_u *p; @@ -3353,7 +1882,7 @@ static bool byte_in_str(char_u *str, int n) // Truncate "slang->sl_syllable" at the first slash and put the following items // in "slang->sl_syl_items". -static int init_syl_tab(slang_T *slang) +int init_syl_tab(slang_T *slang) { char_u *p; char_u *s; @@ -3430,294 +1959,6 @@ static int count_syllables(slang_T *slang, char_u *word) return cnt; } -// 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) -{ - int i; - - garray_T *gap; - char_u *s; - char_u *p; - int c; - int *inp; - - if (has_mbyte) { - // Use "sl_sal" as an array with 256 pointers to a list of wide - // characters. The index is the low byte of the character. - // The list contains from-to pairs with a terminating NUL. - // sl_sal_first[] is used for latin1 "from" characters. - gap = &lp->sl_sal; - ga_init(gap, sizeof(int *), 1); - ga_grow(gap, 256); - memset(gap->ga_data, 0, sizeof(int *) * 256); - gap->ga_len = 256; - - // 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; ) { - c = mb_cptr2char_adv(&p); - mb_cptr_adv(s); - if (c >= 256) - ++lp->sl_sal_first[c & 0xff]; - } - if (*p != NUL || *s != NUL) // lengths differ - return SP_FORMERROR; - - // Allocate the lists. - for (i = 0; i < 256; ++i) - if (lp->sl_sal_first[i] > 0) { - p = xmalloc(sizeof(int) * (lp->sl_sal_first[i] * 2 + 1)); - ((int **)gap->ga_data)[i] = (int *)p; - *(int *)p = 0; - } - - // Put the characters up to 255 in sl_sal_first[] the rest in a sl_sal - // list. - memset(lp->sl_sal_first, 0, sizeof(salfirst_T) * 256); - for (p = from, s = to; *p != NUL && *s != NUL; ) { - c = mb_cptr2char_adv(&p); - i = mb_cptr2char_adv(&s); - if (c >= 256) { - // Append the from-to chars at the end of the list with - // the low byte. - inp = ((int **)gap->ga_data)[c & 0xff]; - while (*inp != 0) - ++inp; - *inp++ = c; // from char - *inp++ = i; // to char - *inp++ = NUL; // NUL at the end - } else - // mapping byte to char is done in sl_sal_first[] - lp->sl_sal_first[c] = i; - } - } else { - // mapping bytes to bytes is done in sl_sal_first[] - if (STRLEN(from) != STRLEN(to)) - return SP_FORMERROR; - - for (i = 0; to[i] != NUL; ++i) - lp->sl_sal_first[from[i]] = to[i]; - lp->sl_sal.ga_len = 1; // indicates we have soundfolding - } - - return 0; -} - -// Fill the first-index table for "lp". -static void set_sal_first(slang_T *lp) -{ - salfirst_T *sfirst; - salitem_T *smp; - int c; - garray_T *gap = &lp->sl_sal; - - sfirst = lp->sl_sal_first; - for (int i = 0; i < 256; ++i) { - sfirst[i] = -1; - } - smp = (salitem_T *)gap->ga_data; - for (int i = 0; i < gap->ga_len; ++i) { - if (has_mbyte) - // Use the lowest byte of the first character. For latin1 it's - // the character, for other encodings it should differ for most - // characters. - c = *smp[i].sm_lead_w & 0xff; - else - c = *smp[i].sm_lead; - if (sfirst[c] == -1) { - sfirst[c] = i; - if (has_mbyte) { - int n; - - // Make sure all entries with this byte are following each - // other. Move the ones that are in the wrong position. Do - // keep the same ordering! - while (i + 1 < gap->ga_len - && (*smp[i + 1].sm_lead_w & 0xff) == c) - // Skip over entry with same index byte. - ++i; - - for (n = 1; i + n < gap->ga_len; ++n) - if ((*smp[i + n].sm_lead_w & 0xff) == c) { - salitem_T tsal; - - // Move entry with same index byte after the entries - // we already found. - ++i; - --n; - tsal = smp[i + n]; - memmove(smp + i + 1, smp + i, - sizeof(salitem_T) * n); - smp[i] = tsal; - } - } - } - } -} - -// Turn a multi-byte string into a wide character string. -// Return it in allocated memory. -static int *mb_str2wide(char_u *s) -{ - int i = 0; - - int *res = xmalloc((mb_charlen(s) + 1) * sizeof(int)); - for (char_u *p = s; *p != NUL; ) - res[i++] = mb_ptr2char_adv(&p); - res[i] = NUL; - - return res; -} - -// Reads a tree from the .spl or .sug file. -// Allocates the memory and stores pointers in "bytsp" and "idxsp". -// This is skipped when the tree has zero length. -// Returns zero when OK, SP_ value for an error. -static int -spell_read_tree ( - FILE *fd, - char_u **bytsp, - idx_T **idxsp, - bool prefixtree, // true for the prefix tree - int prefixcnt // when "prefixtree" is true: prefix count -) -{ - int idx; - char_u *bp; - idx_T *ip; - - // The tree size was computed when writing the file, so that we can - // allocate it as one long block. <nodecount> - int len = get4c(fd); - if (len < 0) - return SP_TRUNCERROR; - if (len > 0) { - // Allocate the byte array. - bp = xmalloc(len); - *bytsp = bp; - - // Allocate the index array. - ip = xcalloc(len, sizeof(*ip)); - *idxsp = ip; - - // Recursively read the tree and store it in the array. - idx = read_tree_node(fd, bp, ip, len, 0, prefixtree, prefixcnt); - if (idx < 0) - return idx; - } - return 0; -} - -// Read one row of siblings from the spell file and store it in the byte array -// "byts" and index array "idxs". Recursively read the children. -// -// NOTE: The code here must match put_node()! -// -// Returns the index (>= 0) following the siblings. -// Returns SP_TRUNCERROR if the file is shorter than expected. -// Returns SP_FORMERROR if there is a format error. -static idx_T -read_tree_node ( - FILE *fd, - char_u *byts, - idx_T *idxs, - int maxidx, // size of arrays - idx_T startidx, // current index in "byts" and "idxs" - bool prefixtree, // true for reading PREFIXTREE - int maxprefcondnr // maximum for <prefcondnr> -) -{ - int len; - int i; - int n; - idx_T idx = startidx; - int c; - int c2; -#define SHARED_MASK 0x8000000 - - len = getc(fd); // <siblingcount> - if (len <= 0) - return SP_TRUNCERROR; - - if (startidx + len >= maxidx) - return SP_FORMERROR; - byts[idx++] = len; - - // Read the byte values, flag/region bytes and shared indexes. - for (i = 1; i <= len; ++i) { - c = getc(fd); // <byte> - if (c < 0) - return SP_TRUNCERROR; - if (c <= BY_SPECIAL) { - if (c == BY_NOFLAGS && !prefixtree) { - // No flags, all regions. - idxs[idx] = 0; - c = 0; - } else if (c != BY_INDEX) { - if (prefixtree) { - // Read the optional pflags byte, the prefix ID and the - // condition nr. In idxs[] store the prefix ID in the low - // byte, the condition index shifted up 8 bits, the flags - // shifted up 24 bits. - if (c == BY_FLAGS) - c = getc(fd) << 24; // <pflags> - else - c = 0; - - c |= getc(fd); // <affixID> - - n = get2c(fd); // <prefcondnr> - if (n >= maxprefcondnr) - return SP_FORMERROR; - c |= (n << 8); - } else { // c must be BY_FLAGS or BY_FLAGS2 - // Read flags and optional region and prefix ID. In - // idxs[] the flags go in the low two bytes, region above - // that and prefix ID above the region. - c2 = c; - c = getc(fd); // <flags> - if (c2 == BY_FLAGS2) - c = (getc(fd) << 8) + c; // <flags2> - if (c & WF_REGION) - c = (getc(fd) << 16) + c; // <region> - if (c & WF_AFX) - c = (getc(fd) << 24) + c; // <affixID> - } - - idxs[idx] = c; - c = 0; - } else { // c == BY_INDEX - // <nodeidx> - n = get3c(fd); - if (n < 0 || n >= maxidx) - return SP_FORMERROR; - idxs[idx] = n + SHARED_MASK; - c = getc(fd); // <xbyte> - } - } - byts[idx++] = c; - } - - // Recursively read the children for non-shared siblings. - // Skip the end-of-word ones (zero byte value) and the shared ones (and - // remove SHARED_MASK) - for (i = 1; i <= len; ++i) - if (byts[startidx + i] != 0) { - if (idxs[startidx + i] & SHARED_MASK) - idxs[startidx + i] &= ~SHARED_MASK; - else { - idxs[startidx + i] = idx; - idx = read_tree_node(fd, byts, idxs, maxidx, idx, - prefixtree, maxprefcondnr); - if (idx < 0) - break; - } - } - - return idx; -} - // Parse 'spelllang' and set w_s->b_langp accordingly. // Returns NULL if it's OK, an error message otherwise. char_u *did_set_spelllang(win_T *wp) @@ -3744,6 +1985,9 @@ char_u *did_set_spelllang(win_T *wp) char_u *ret_msg = NULL; char_u *spl_copy; + bufref_T bufref; + set_bufref(&bufref, wp->w_buffer); + // We don't want to do this recursively. May happen when a language is // not available and the SpellFileMissing autocommand opens a new buffer // in which 'spell' is set. @@ -3822,9 +2066,9 @@ char_u *did_set_spelllang(win_T *wp) spell_load_lang(lang); // SpellFileMissing autocommands may do anything, including // destroying the buffer we are using... - if (!buf_valid(wp->w_buffer)) { + if (!bufref_valid(&bufref)) { ret_msg = - (char_u *)"E797: SpellFileMissing autocommand deleted buffer"; + (char_u *)N_("E797: SpellFileMissing autocommand deleted buffer"); goto theend; } } @@ -4045,16 +2289,17 @@ static int find_region(char_u *rp, char_u *region) return i / 2; } -// Return case type of word: -// w word 0 -// Word WF_ONECAP -// W WORD WF_ALLCAP -// WoRd wOrd WF_KEEPCAP -static int -captype ( - char_u *word, - char_u *end // When NULL use up to NUL byte. -) +/// Return case type of word: +/// w word 0 +/// Word WF_ONECAP +/// W WORD WF_ALLCAP +/// WoRd wOrd WF_KEEPCAP +/// +/// @param[in] word +/// @param[in] end End of word or NULL for NUL delimited string +/// +/// @returns Case type of word +int captype(char_u *word, char_u *end) { char_u *p; int c; @@ -4066,10 +2311,11 @@ captype ( for (p = word; !spell_iswordp_nmw(p, curwin); mb_ptr_adv(p)) if (end == NULL ? *p == NUL : p >= end) return 0; // only non-word characters, illegal word - if (has_mbyte) - c = mb_ptr2char_adv(&p); - else + if (has_mbyte) { + c = mb_ptr2char_adv((const char_u **)&p); + } else { c = *p++; + } firstcap = allcap = SPELL_ISUPPER(c); // Need to check all letters to find a word with mixed upper/lower. @@ -4196,3221 +2442,6 @@ void spell_reload(void) } } -// Reload the spell file "fname" if it's loaded. -static void -spell_reload_one ( - char_u *fname, - bool added_word // invoked through "zg" -) -{ - slang_T *slang; - bool didit = false; - - for (slang = first_lang; slang != NULL; slang = slang->sl_next) { - if (path_full_compare(fname, slang->sl_fname, FALSE) == kEqualFiles) { - slang_clear(slang); - if (spell_load_file(fname, NULL, slang, false) == NULL) - // reloading failed, clear the language - slang_clear(slang); - redraw_all_later(SOME_VALID); - didit = true; - } - } - - // When "zg" was used and the file wasn't loaded yet, should redo - // 'spelllang' to load it now. - if (added_word && !didit) - did_set_spelllang(curwin); -} - - -// Functions for ":mkspell". - - -// In the postponed prefixes tree wn_flags is used to store the WFP_ flags, -// but it must be negative to indicate the prefix tree to tree_add_word(). -// Use a negative number with the lower 8 bits zero. -#define PFX_FLAGS -256 - -// flags for "condit" argument of store_aff_word() -#define CONDIT_COMB 1 // affix must combine -#define CONDIT_CFIX 2 // affix must have CIRCUMFIX flag -#define CONDIT_SUF 4 // add a suffix for matching flags -#define CONDIT_AFF 8 // word already has an affix - -// Tunable parameters for when the tree is compressed. See 'mkspellmem'. -static long compress_start = 30000; // memory / SBLOCKSIZE -static long compress_inc = 100; // memory / SBLOCKSIZE -static long compress_added = 500000; // word count - -#ifdef SPELL_PRINTTREE -// For debugging the tree code: print the current tree in a (more or less) -// readable format, so that we can see what happens when adding a word and/or -// compressing the tree. -// Based on code from Olaf Seibert. -#define PRINTLINESIZE 1000 -#define PRINTWIDTH 6 - -#define PRINTSOME(l, depth, fmt, a1, a2) vim_snprintf(l + depth * PRINTWIDTH, \ - PRINTLINESIZE - PRINTWIDTH * depth, fmt, a1, a2) - -static char line1[PRINTLINESIZE]; -static char line2[PRINTLINESIZE]; -static char line3[PRINTLINESIZE]; - -static void spell_clear_flags(wordnode_T *node) -{ - wordnode_T *np; - - for (np = node; np != NULL; np = np->wn_sibling) { - np->wn_u1.index = FALSE; - spell_clear_flags(np->wn_child); - } -} - -static void spell_print_node(wordnode_T *node, int depth) -{ - if (node->wn_u1.index) { - // Done this node before, print the reference. - PRINTSOME(line1, depth, "(%d)", node->wn_nr, 0); - PRINTSOME(line2, depth, " ", 0, 0); - PRINTSOME(line3, depth, " ", 0, 0); - msg((char_u *)line1); - msg((char_u *)line2); - msg((char_u *)line3); - } else { - node->wn_u1.index = TRUE; - - if (node->wn_byte != NUL) { - if (node->wn_child != NULL) - PRINTSOME(line1, depth, " %c -> ", node->wn_byte, 0); - else - // Cannot happen? - PRINTSOME(line1, depth, " %c ???", node->wn_byte, 0); - } else - PRINTSOME(line1, depth, " $ ", 0, 0); - - PRINTSOME(line2, depth, "%d/%d ", node->wn_nr, node->wn_refs); - - if (node->wn_sibling != NULL) - PRINTSOME(line3, depth, " | ", 0, 0); - else - PRINTSOME(line3, depth, " ", 0, 0); - - if (node->wn_byte == NUL) { - msg((char_u *)line1); - msg((char_u *)line2); - msg((char_u *)line3); - } - - // do the children - if (node->wn_byte != NUL && node->wn_child != NULL) - spell_print_node(node->wn_child, depth + 1); - - // do the siblings - if (node->wn_sibling != NULL) { - // get rid of all parent details except | - STRCPY(line1, line3); - STRCPY(line2, line3); - spell_print_node(node->wn_sibling, 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); - } -} - -#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) -{ - FILE *fd; - afffile_T *aff; - char_u rline[MAXLINELEN]; - char_u *line; - char_u *pc = NULL; -#define MAXITEMCNT 30 - char_u *(items[MAXITEMCNT]); - int itemcnt; - char_u *p; - int lnum = 0; - affheader_T *cur_aff = NULL; - bool did_postpone_prefix = false; - int aff_todo = 0; - hashtab_T *tp; - char_u *low = NULL; - char_u *fol = NULL; - char_u *upp = NULL; - int do_rep; - int do_repsal; - int do_sal; - int do_mapline; - bool found_map = false; - hashitem_T *hi; - int l; - int compminlen = 0; // COMPOUNDMIN value - int compsylmax = 0; // COMPOUNDSYLMAX value - int compoptions = 0; // COMP_ flags - int compmax = 0; // COMPOUNDWORDMAX value - char_u *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 - - // Open the file. - fd = mch_fopen((char *)fname, "r"); - if (fd == NULL) { - EMSG2(_(e_notopen), fname); - return NULL; - } - - vim_snprintf((char *)IObuff, IOSIZE, _("Reading affix file %s ..."), fname); - spell_message(spin, IObuff); - - // Only do REP lines when not done in another .aff file already. - do_rep = GA_EMPTY(&spin->si_rep); - - // Only do REPSAL lines when not done in another .aff file already. - do_repsal = GA_EMPTY(&spin->si_repsal); - - // Only do SAL lines when not done in another .aff file already. - do_sal = GA_EMPTY(&spin->si_sal); - - // Only do MAP lines when not done in another .aff file already. - do_mapline = GA_EMPTY(&spin->si_map); - - // Allocate and init the afffile_T structure. - aff = (afffile_T *)getroom(spin, sizeof(afffile_T), true); - if (aff == NULL) { - fclose(fd); - return NULL; - } - hash_init(&aff->af_pref); - hash_init(&aff->af_suff); - hash_init(&aff->af_comp); - - // Read all the lines in the file one by one. - while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int) { - line_breakcheck(); - ++lnum; - - // Skip comment lines. - if (*rline == '#') - continue; - - // Convert from "SET" to 'encoding' when needed. - xfree(pc); - if (spin->si_conv.vc_type != CONV_NONE) { - pc = string_convert(&spin->si_conv, rline, NULL); - if (pc == NULL) { - smsg(_("Conversion failure for word in %s line %d: %s"), - fname, lnum, rline); - continue; - } - line = pc; - } else { - pc = NULL; - line = rline; - } - - // Split the line up in white separated items. Put a NUL after each - // item. - itemcnt = 0; - for (p = line;; ) { - while (*p != NUL && *p <= ' ') // skip white space and CR/NL - ++p; - if (*p == NUL) - break; - if (itemcnt == MAXITEMCNT) // too many items - break; - items[itemcnt++] = p; - // A few items have arbitrary text argument, don't split them. - if (itemcnt == 2 && spell_info_item(items[0])) - while (*p >= ' ' || *p == TAB) // skip until CR/NL - ++p; - else - while (*p > ' ') // skip until white space or CR/NL - ++p; - if (*p == NUL) - break; - *p++ = NUL; - } - - // Handle non-empty lines. - 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 = enc_canonize(items[1]); - if (!spin->si_ascii - && 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); - spin->si_conv.vc_fail = true; - } else if (is_aff_rule(items, itemcnt, "FLAG", 2) - && aff->af_flagtype == AFT_CHAR) { - if (STRCMP(items[1], "long") == 0) - aff->af_flagtype = AFT_LONG; - else if (STRCMP(items[1], "num") == 0) - aff->af_flagtype = AFT_NUM; - else if (STRCMP(items[1], "caplong") == 0) - aff->af_flagtype = AFT_CAPLONG; - else - smsg(_("Invalid value for FLAG in %s line %d: %s"), - fname, lnum, items[1]); - if (aff->af_rare != 0 - || aff->af_keepcase != 0 - || aff->af_bad != 0 - || aff->af_needaffix != 0 - || aff->af_circumfix != 0 - || aff->af_needcomp != 0 - || aff->af_comproot != 0 - || aff->af_nosuggest != 0 - || compflags != NULL - || aff->af_suff.ht_used > 0 - || aff->af_pref.ht_used > 0) - smsg(_("FLAG after using flags in %s line %d: %s"), - fname, lnum, items[1]); - } else if (spell_info_item(items[0]) && itemcnt > 1) { - p = (char_u *)getroom(spin, - (spin->si_info == NULL ? 0 : STRLEN(spin->si_info)) - + STRLEN(items[0]) - + STRLEN(items[1]) + 3, false); - if (p != NULL) { - if (spin->si_info != NULL) { - STRCPY(p, spin->si_info); - STRCAT(p, "\n"); - } - STRCAT(p, items[0]); - STRCAT(p, " "); - STRCAT(p, items[1]); - spin->si_info = p; - } - } else if (is_aff_rule(items, itemcnt, "MIDWORD", 2) - && midword == NULL) { - 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 - } - // TODO: remove "RAR" later - else if ((is_aff_rule(items, itemcnt, "RAR", 2) - || is_aff_rule(items, itemcnt, "RARE", 2)) - && aff->af_rare == 0) { - aff->af_rare = affitem2flag(aff->af_flagtype, items[1], - fname, lnum); - } - // TODO: remove "KEP" later - else if ((is_aff_rule(items, itemcnt, "KEP", 2) - || is_aff_rule(items, itemcnt, "KEEPCASE", 2)) - && aff->af_keepcase == 0) { - 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, items[1], - fname, lnum); - } else if (is_aff_rule(items, itemcnt, "NEEDAFFIX", 2) - && aff->af_needaffix == 0) { - 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, items[1], - fname, lnum); - } else if (is_aff_rule(items, itemcnt, "NOSUGGEST", 2) - && aff->af_nosuggest == 0) { - 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, items[1], - fname, lnum); - } else if (is_aff_rule(items, itemcnt, "COMPOUNDROOT", 2) - && aff->af_comproot == 0) { - 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, 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, 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); - } else if (is_aff_rule(items, itemcnt, "COMPOUNDFLAG", 2) - && compflags == NULL) { - // Turn flag "c" into COMPOUNDRULE compatible string "c+", - // "Na" into "Na+", "1234" into "1234+". - p = getroom(spin, STRLEN(items[1]) + 2, false); - STRCPY(p, items[1]); - STRCAT(p, "+"); - compflags = p; - } else if (is_aff_rule(items, itemcnt, "COMPOUNDRULES", 2)) { - // We don't use the count, but do check that it's a number and - // not COMPOUNDRULE mistyped. - if (atoi((char *)items[1]) == 0) - smsg(_("Wrong COMPOUNDRULES value in %s line %d: %s"), - fname, lnum, items[1]); - } else if (is_aff_rule(items, itemcnt, "COMPOUNDRULE", 2)) { - // Don't use the first rule if it is a number. - if (compflags != NULL || *skipdigits(items[1]) != NUL) { - // Concatenate this string to previously defined ones, - // using a slash to separate them. - l = (int)STRLEN(items[1]) + 1; - if (compflags != NULL) - l += (int)STRLEN(compflags) + 1; - p = getroom(spin, l, false); - if (compflags != NULL) { - STRCPY(p, compflags); - STRCAT(p, "/"); - } - STRCAT(p, items[1]); - compflags = p; - } - } else if (is_aff_rule(items, itemcnt, "COMPOUNDWORDMAX", 2) - && compmax == 0) { - compmax = atoi((char *)items[1]); - if (compmax == 0) - smsg(_("Wrong COMPOUNDWORDMAX value in %s line %d: %s"), - fname, lnum, items[1]); - } else if (is_aff_rule(items, itemcnt, "COMPOUNDMIN", 2) - && compminlen == 0) { - compminlen = atoi((char *)items[1]); - if (compminlen == 0) - smsg(_("Wrong COMPOUNDMIN value in %s line %d: %s"), - fname, lnum, items[1]); - } else if (is_aff_rule(items, itemcnt, "COMPOUNDSYLMAX", 2) - && compsylmax == 0) { - compsylmax = atoi((char *)items[1]); - if (compsylmax == 0) - smsg(_("Wrong COMPOUNDSYLMAX value in %s line %d: %s"), - fname, lnum, items[1]); - } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDDUP", 1)) { - compoptions |= COMP_CHECKDUP; - } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDREP", 1)) { - compoptions |= COMP_CHECKREP; - } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDCASE", 1)) { - compoptions |= COMP_CHECKCASE; - } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDTRIPLE", 1)) { - compoptions |= COMP_CHECKTRIPLE; - } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 2)) { - if (atoi((char *)items[1]) == 0) - smsg(_("Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s"), - fname, lnum, items[1]); - } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 3)) { - garray_T *gap = &spin->si_comppat; - int i; - - // Only add the couple if it isn't already there. - for (i = 0; i < gap->ga_len - 1; i += 2) - if (STRCMP(((char_u **)(gap->ga_data))[i], items[1]) == 0 - && STRCMP(((char_u **)(gap->ga_data))[i + 1], - items[2]) == 0) - break; - if (i >= gap->ga_len) { - ga_grow(gap, 2); - ((char_u **)(gap->ga_data))[gap->ga_len++] - = getroom_save(spin, items[1]); - ((char_u **)(gap->ga_data))[gap->ga_len++] - = getroom_save(spin, items[2]); - } - } else if (is_aff_rule(items, itemcnt, "SYLLABLE", 2) - && syllable == NULL) { - 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)) { - spin->si_nosplitsugs = true; - } else if (is_aff_rule(items, itemcnt, "NOCOMPOUNDSUGS", 1)) { - spin->si_nocompoundsugs = true; - } else if (is_aff_rule(items, itemcnt, "NOSUGFILE", 1)) { - spin->si_nosugfile = true; - } else if (is_aff_rule(items, itemcnt, "PFXPOSTPONE", 1)) { - aff->af_pfxpostpone = true; - } else if (is_aff_rule(items, itemcnt, "IGNOREEXTRA", 1)) { - aff->af_ignoreextra = true; - } else if ((STRCMP(items[0], "PFX") == 0 - || STRCMP(items[0], "SFX") == 0) - && aff_todo == 0 - && itemcnt >= 4) { - int lasti = 4; - char_u key[AH_KEY_LEN]; - - if (*items[0] == 'P') - tp = &aff->af_pref; - else - tp = &aff->af_suff; - - // Myspell allows the same affix name to be used multiple - // times. The affix files that do this have an undocumented - // "S" flag on all but the last block, thus we check for that - // and store it in ah_follows. - STRLCPY(key, items[1], AH_KEY_LEN); - hi = hash_find(tp, key); - if (!HASHITEM_EMPTY(hi)) { - cur_aff = HI2AH(hi); - if (cur_aff->ah_combine != (*items[2] == 'Y')) - smsg(_("Different combining flag in continued affix block in %s line %d: %s"), - fname, lnum, items[1]); - if (!cur_aff->ah_follows) - smsg(_("Duplicate affix in %s line %d: %s"), - fname, lnum, items[1]); - } else { - // New affix letter. - cur_aff = (affheader_T *)getroom(spin, - sizeof(affheader_T), true); - if (cur_aff == NULL) - break; - 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; - if (cur_aff->ah_flag == aff->af_bad - || cur_aff->ah_flag == aff->af_rare - || cur_aff->ah_flag == aff->af_keepcase - || cur_aff->ah_flag == aff->af_needaffix - || cur_aff->ah_flag == aff->af_circumfix - || cur_aff->ah_flag == aff->af_nosuggest - || cur_aff->ah_flag == aff->af_needcomp - || cur_aff->ah_flag == aff->af_comproot) - smsg(_("Affix also used for " - "BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST" - "in %s line %d: %s"), - fname, lnum, items[1]); - STRCPY(cur_aff->ah_key, items[1]); - hash_add(tp, cur_aff->ah_key); - - cur_aff->ah_combine = (*items[2] == 'Y'); - } - - // Check for the "S" flag, which apparently means that another - // block with the same affix name is following. - if (itemcnt > lasti && STRCMP(items[lasti], "S") == 0) { - ++lasti; - cur_aff->ah_follows = true; - } else - cur_aff->ah_follows = false; - - // Myspell allows extra text after the item, but that might - // mean mistakes go unnoticed. Require a comment-starter, - // unless IGNOREEXTRA is used. Hunspell uses a "-" item. - if (itemcnt > lasti - && !aff->af_ignoreextra - && *items[lasti] != '#') - smsg(_(e_afftrailing), fname, lnum, items[lasti]); - - if (STRCMP(items[2], "Y") != 0 && STRCMP(items[2], "N") != 0) - smsg(_("Expected Y or N in %s line %d: %s"), - fname, lnum, items[2]); - - if (*items[0] == 'P' && aff->af_pfxpostpone) { - if (cur_aff->ah_newID == 0) { - // Use a new number in the .spl file later, to be able - // to handle multiple .aff files. - check_renumber(spin); - cur_aff->ah_newID = ++spin->si_newprefID; - - // We only really use ah_newID if the prefix is - // postponed. We know that only after handling all - // the items. - did_postpone_prefix = false; - } else - // Did use the ID in a previous block. - did_postpone_prefix = true; - } - - aff_todo = atoi((char *)items[3]); - } else if ((STRCMP(items[0], "PFX") == 0 - || STRCMP(items[0], "SFX") == 0) - && aff_todo > 0 - && STRCMP(cur_aff->ah_key, items[1]) == 0 - && itemcnt >= 5) { - affentry_T *aff_entry; - bool upper = false; - int lasti = 5; - - // Myspell allows extra text after the item, but that might - // mean mistakes go unnoticed. Require a comment-starter. - // Hunspell uses a "-" item. - if (itemcnt > lasti && *items[lasti] != '#' - && (STRCMP(items[lasti], "-") != 0 - || itemcnt != lasti + 1)) - smsg(_(e_afftrailing), fname, lnum, items[lasti]); - - // New item for an affix letter. - --aff_todo; - aff_entry = (affentry_T *)getroom(spin, - sizeof(affentry_T), true); - if (aff_entry == NULL) - break; - - if (STRCMP(items[2], "0") != 0) - aff_entry->ae_chop = getroom_save(spin, items[2]); - if (STRCMP(items[3], "0") != 0) { - aff_entry->ae_add = getroom_save(spin, items[3]); - - // Recognize flags on the affix: abcd/XYZ - 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); - } - } - - // Don't use an affix entry with non-ASCII characters when - // "spin->si_ascii" is true. - if (!spin->si_ascii || !(has_non_ascii(aff_entry->ae_chop) - || has_non_ascii(aff_entry->ae_add))) { - aff_entry->ae_next = cur_aff->ah_first; - cur_aff->ah_first = aff_entry; - - if (STRCMP(items[4], ".") != 0) { - char_u buf[MAXLINELEN]; - - aff_entry->ae_cond = getroom_save(spin, items[4]); - if (*items[0] == 'P') - sprintf((char *)buf, "^%s", items[4]); - else - sprintf((char *)buf, "%s$", items[4]); - 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]); - } - - // For postponed prefixes we need an entry in si_prefcond - // for the condition. Use an existing one if possible. - // Can't be done for an affix with flags, ignoring - // COMPOUNDFORBIDFLAG and COMPOUNDPERMITFLAG. - if (*items[0] == 'P' && aff->af_pfxpostpone - && aff_entry->ae_flags == NULL) { - // When the chop string is one lower-case letter and - // the add string ends in the upper-case letter we set - // the "upper" flag, clear "ae_chop" and remove the - // letters from "ae_add". The condition must either - // be empty or start with the same letter. - if (aff_entry->ae_chop != NULL - && aff_entry->ae_add != NULL - && aff_entry->ae_chop[(*mb_ptr2len)( - aff_entry->ae_chop)] == NUL - ) { - int c, c_up; - - c = PTR2CHAR(aff_entry->ae_chop); - c_up = SPELL_TOUPPER(c); - if (c_up != c - && (aff_entry->ae_cond == NULL - || 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 (PTR2CHAR(p) == c_up) { - upper = true; - aff_entry->ae_chop = NULL; - *p = NUL; - - // The condition is matched with the - // actual word, thus must check for the - // upper-case letter. - if (aff_entry->ae_cond != NULL) { - char_u buf[MAXLINELEN]; - if (has_mbyte) { - onecap_copy(items[4], buf, true); - aff_entry->ae_cond = getroom_save( - spin, buf); - } else - *aff_entry->ae_cond = c_up; - if (aff_entry->ae_cond != NULL) { - sprintf((char *)buf, "^%s", - aff_entry->ae_cond); - vim_regfree(aff_entry->ae_prog); - aff_entry->ae_prog = vim_regcomp( - buf, RE_MAGIC + RE_STRING); - } - } - } - } - } - - if (aff_entry->ae_chop == NULL - && aff_entry->ae_flags == NULL) { - int idx; - char_u **pp; - int n; - - // Find a previously used condition. - for (idx = spin->si_prefcond.ga_len - 1; idx >= 0; - --idx) { - p = ((char_u **)spin->si_prefcond.ga_data)[idx]; - if (str_equal(p, aff_entry->ae_cond)) - break; - } - if (idx < 0) { - // Not found, add a new condition. - idx = spin->si_prefcond.ga_len; - pp = GA_APPEND_VIA_PTR(char_u *, &spin->si_prefcond); - *pp = (aff_entry->ae_cond == NULL) ? - NULL : getroom_save(spin, aff_entry->ae_cond); - } - - // Add the prefix to the prefix tree. - if (aff_entry->ae_add == NULL) - p = (char_u *)""; - else - p = aff_entry->ae_add; - - // PFX_FLAGS is a negative number, so that - // tree_add_word() knows this is the prefix tree. - n = PFX_FLAGS; - if (!cur_aff->ah_combine) - n |= WFP_NC; - if (upper) - n |= WFP_UP; - if (aff_entry->ae_comppermit) - n |= WFP_COMPPERMIT; - if (aff_entry->ae_compforbid) - n |= WFP_COMPFORBID; - tree_add_word(spin, p, spin->si_prefroot, n, - idx, cur_aff->ah_newID); - did_postpone_prefix = true; - } - - // Didn't actually use ah_newID, backup si_newprefID. - if (aff_todo == 0 && !did_postpone_prefix) { - --spin->si_newprefID; - cur_aff->ah_newID = 0; - } - } - } - } else if (is_aff_rule(items, itemcnt, "FOL", 2) && fol == NULL) { - fol = vim_strsave(items[1]); - } else if (is_aff_rule(items, itemcnt, "LOW", 2) && low == NULL) { - low = vim_strsave(items[1]); - } else if (is_aff_rule(items, itemcnt, "UPP", 2) && upp == NULL) { - upp = vim_strsave(items[1]); - } else if (is_aff_rule(items, itemcnt, "REP", 2) - || is_aff_rule(items, itemcnt, "REPSAL", 2)) { - /* Ignore REP/REPSAL count */; - if (!isdigit(*items[1])) - smsg(_("Expected REP(SAL) count in %s line %d"), - fname, lnum); - } else if ((STRCMP(items[0], "REP") == 0 - || STRCMP(items[0], "REPSAL") == 0) - && itemcnt >= 3) { - // REP/REPSAL item - // Myspell ignores extra arguments, we require it starts with - // # to detect mistakes. - if (itemcnt > 3 && items[3][0] != '#') - smsg(_(e_afftrailing), fname, lnum, items[3]); - if (items[0][3] == 'S' ? do_repsal : do_rep) { - // Replace underscore with space (can't include a space - // directly). - for (p = items[1]; *p != NUL; mb_ptr_adv(p)) - if (*p == '_') - *p = ' '; - for (p = items[2]; *p != NUL; mb_ptr_adv(p)) - if (*p == '_') - *p = ' '; - add_fromto(spin, items[0][3] == 'S' - ? &spin->si_repsal - : &spin->si_rep, items[1], items[2]); - } - } else if (is_aff_rule(items, itemcnt, "MAP", 2)) { - // MAP item or count - if (!found_map) { - // First line contains the count. - found_map = true; - if (!isdigit(*items[1])) - smsg(_("Expected MAP count in %s line %d"), - fname, lnum); - } else if (do_mapline) { - int c; - - // Check that every character appears only once. - for (p = items[1]; *p != NUL; ) { - c = mb_ptr2char_adv(&p); - if ((!GA_EMPTY(&spin->si_map) - && vim_strchr(spin->si_map.ga_data, c) - != NULL) - || vim_strchr(p, c) != NULL) - smsg(_("Duplicate character in MAP in %s line %d"), - fname, lnum); - } - - // We simply concatenate all the MAP strings, separated by - // slashes. - ga_concat(&spin->si_map, items[1]); - ga_append(&spin->si_map, '/'); - } - } - // Accept "SAL from to" and "SAL from to #comment". - else if (is_aff_rule(items, itemcnt, "SAL", 3)) { - if (do_sal) { - // SAL item (sounds-a-like) - // Either one of the known keys or a from-to pair. - if (STRCMP(items[1], "followup") == 0) - spin->si_followup = sal_to_bool(items[2]); - else if (STRCMP(items[1], "collapse_result") == 0) - spin->si_collapse = sal_to_bool(items[2]); - else if (STRCMP(items[1], "remove_accents") == 0) - spin->si_rem_accents = sal_to_bool(items[2]); - else - // when "to" is "_" it means empty - add_fromto(spin, &spin->si_sal, items[1], - STRCMP(items[2], "_") == 0 ? (char_u *)"" - : items[2]); - } - } else if (is_aff_rule(items, itemcnt, "SOFOFROM", 2) - && sofofrom == NULL) { - sofofrom = getroom_save(spin, items[1]); - } else if (is_aff_rule(items, itemcnt, "SOFOTO", 2) - && sofoto == NULL) { - sofoto = getroom_save(spin, items[1]); - } else if (STRCMP(items[0], "COMMON") == 0) { - int i; - - for (i = 1; i < itemcnt; ++i) { - if (HASHITEM_EMPTY(hash_find(&spin->si_commonwords, - items[i]))) { - p = vim_strsave(items[i]); - hash_add(&spin->si_commonwords, p); - } - } - } else - smsg(_("Unrecognized or duplicate item in %s line %d: %s"), - fname, lnum, items[0]); - } - } - - if (fol != NULL || low != NULL || upp != NULL) { - if (spin->si_clear_chartab) { - // Clear the char type tables, don't want to use any of the - // currently used spell properties. - init_spell_chartab(); - spin->si_clear_chartab = false; - } - - // Don't write a word table for an ASCII file, so that we don't check - // for conflicts with a word table that matches 'encoding'. - // Don't write one for utf-8 either, we use utf_*() and - // mb_get_class(), the list of chars in the file will be incomplete. - if (!spin->si_ascii - && !enc_utf8 - ) { - if (fol == NULL || low == NULL || upp == NULL) - smsg(_("Missing FOL/LOW/UPP line in %s"), fname); - else - (void)set_spell_chartab(fol, low, upp); - } - - xfree(fol); - xfree(low); - xfree(upp); - } - - // Use compound specifications of the .aff file for the spell info. - if (compmax != 0) { - aff_check_number(spin->si_compmax, compmax, "COMPOUNDWORDMAX"); - spin->si_compmax = compmax; - } - - if (compminlen != 0) { - aff_check_number(spin->si_compminlen, compminlen, "COMPOUNDMIN"); - spin->si_compminlen = compminlen; - } - - if (compsylmax != 0) { - if (syllable == NULL) - smsg(_("COMPOUNDSYLMAX used without SYLLABLE")); - aff_check_number(spin->si_compsylmax, compsylmax, "COMPOUNDSYLMAX"); - spin->si_compsylmax = compsylmax; - } - - if (compoptions != 0) { - aff_check_number(spin->si_compoptions, compoptions, "COMPOUND options"); - spin->si_compoptions |= compoptions; - } - - if (compflags != NULL) - process_compflags(spin, aff, compflags); - - // Check that we didn't use too many renumbered flags. - if (spin->si_newcompID < spin->si_newprefID) { - if (spin->si_newcompID == 127 || spin->si_newcompID == 255) - MSG(_("Too many postponed prefixes")); - else if (spin->si_newprefID == 0 || spin->si_newprefID == 127) - MSG(_("Too many compound flags")); - else - MSG(_("Too many postponed prefixes and/or compound flags")); - } - - if (syllable != NULL) { - aff_check_string(spin->si_syllable, syllable, "SYLLABLE"); - spin->si_syllable = syllable; - } - - if (sofofrom != NULL || sofoto != NULL) { - if (sofofrom == NULL || sofoto == NULL) - smsg(_("Missing SOFO%s line in %s"), - sofofrom == NULL ? "FROM" : "TO", fname); - else if (!GA_EMPTY(&spin->si_sal)) - smsg(_("Both SAL and SOFO lines in %s"), fname); - else { - 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, midword, "MIDWORD"); - spin->si_midword = midword; - } - - xfree(pc); - fclose(fd); - return aff; -} - -// Returns true when items[0] equals "rulename", there are "mincount" items or -// a comment is following after item "mincount". -static bool is_aff_rule(char_u **items, int itemcnt, char *rulename, int mincount) -{ - return STRCMP(items[0], rulename) == 0 - && (itemcnt == mincount - || (itemcnt > mincount && items[mincount][0] == '#')); -} - -// For affix "entry" move COMPOUNDFORBIDFLAG and COMPOUNDPERMITFLAG from -// ae_flags to ae_comppermit and ae_compforbid. -static void aff_process_flags(afffile_T *affile, affentry_T *entry) -{ - char_u *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; - flag = get_affitem(affile->af_flagtype, &p); - if (flag == affile->af_comppermit || flag == affile->af_compforbid) { - STRMOVE(prevp, p); - p = prevp; - if (flag == affile->af_comppermit) - entry->ae_comppermit = true; - else - entry->ae_compforbid = true; - } - if (affile->af_flagtype == AFT_NUM && *p == ',') - ++p; - } - if (*entry->ae_flags == NUL) - entry->ae_flags = NULL; // nothing left - } -} - -// Returns true if "s" is the name of an info item in the affix file. -static bool spell_info_item(char_u *s) -{ - return STRCMP(s, "NAME") == 0 - || STRCMP(s, "HOME") == 0 - || STRCMP(s, "VERSION") == 0 - || STRCMP(s, "AUTHOR") == 0 - || STRCMP(s, "EMAIL") == 0 - || STRCMP(s, "COPYRIGHT") == 0; -} - -// 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) -{ - unsigned res; - char_u *p = item; - - res = get_affitem(flagtype, &p); - if (res == 0) { - if (flagtype == AFT_NUM) - smsg(_("Flag is not a number in %s line %d: %s"), - fname, lnum, item); - else - smsg(_("Illegal flag in %s line %d: %s"), - fname, lnum, item); - } - if (*p != NUL) { - smsg(_(e_affname), fname, lnum, item); - return 0; - } - - return res; -} - -// Get one affix name from "*pp" and advance the pointer. -// Returns zero for an error, still advances the pointer then. -static unsigned get_affitem(int flagtype, char_u **pp) -{ - int res; - - if (flagtype == AFT_NUM) { - if (!ascii_isdigit(**pp)) { - ++*pp; // always advance, avoid getting stuck - return 0; - } - res = getdigits_int(pp); - } else { - res = mb_ptr2char_adv(pp); - if (flagtype == AFT_LONG || (flagtype == AFT_CAPLONG - && res >= 'A' && res <= 'Z')) { - if (**pp == NUL) - return 0; - res = mb_ptr2char_adv(pp) + (res << 16); - } - } - return res; -} - -// Process the "compflags" string used in an affix file and append it to -// spin->si_compflags. -// The processing involves changing the affix names to ID numbers, so that -// they fit in one byte. -static void process_compflags(spellinfo_T *spin, afffile_T *aff, char_u *compflags) -{ - char_u *p; - char_u *prevp; - unsigned flag; - compitem_T *ci; - int id; - int len; - char_u *tp; - char_u key[AH_KEY_LEN]; - hashitem_T *hi; - - // Make room for the old and the new compflags, concatenated with a / in - // between. Processing it makes it shorter, but we don't know by how - // much, thus allocate the maximum. - len = (int)STRLEN(compflags) + 1; - if (spin->si_compflags != NULL) - len += (int)STRLEN(spin->si_compflags) + 1; - p = getroom(spin, len, false); - if (spin->si_compflags != NULL) { - STRCPY(p, spin->si_compflags); - STRCAT(p, "/"); - } - spin->si_compflags = p; - tp = p + STRLEN(p); - - for (p = compflags; *p != NUL; ) { - if (vim_strchr((char_u *)"/?*+[]", *p) != NULL) - // Copy non-flag characters directly. - *tp++ = *p++; - else { - // First get the flag number, also checks validity. - prevp = 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. - STRLCPY(key, prevp, p - prevp + 1); - hi = hash_find(&aff->af_comp, key); - if (!HASHITEM_EMPTY(hi)) - id = HI2CI(hi)->ci_newID; - else { - ci = (compitem_T *)getroom(spin, sizeof(compitem_T), true); - if (ci == NULL) - break; - STRCPY(ci->ci_key, key); - ci->ci_flag = flag; - // Avoid using a flag ID that has a special meaning in a - // regexp (also inside []). - do { - check_renumber(spin); - id = spin->si_newcompID--; - } while (vim_strchr((char_u *)"/?*+[]\\-^", id) != NULL); - ci->ci_newID = id; - hash_add(&aff->af_comp, ci->ci_key); - } - *tp++ = id; - } - if (aff->af_flagtype == AFT_NUM && *p == ',') - ++p; - } - } - - *tp = NUL; -} - -// Check that the new IDs for postponed affixes and compounding don't overrun -// each other. We have almost 255 available, but start at 0-127 to avoid -// using two bytes for utf-8. When the 0-127 range is used up go to 128-255. -// When that is used up an error message is given. -static void check_renumber(spellinfo_T *spin) -{ - if (spin->si_newprefID == spin->si_newcompID && spin->si_newcompID < 128) { - spin->si_newprefID = 127; - spin->si_newcompID = 255; - } -} - -// Returns true if flag "flag" appears in affix list "afflist". -static bool flag_in_afflist(int flagtype, char_u *afflist, unsigned flag) -{ - char_u *p; - unsigned n; - - switch (flagtype) { - case AFT_CHAR: - return vim_strchr(afflist, flag) != NULL; - - case AFT_CAPLONG: - case AFT_LONG: - for (p = afflist; *p != NUL; ) { - n = mb_ptr2char_adv(&p); - if ((flagtype == AFT_LONG || (n >= 'A' && n <= 'Z')) - && *p != NUL) - n = mb_ptr2char_adv(&p) + (n << 16); - if (n == flag) - return true; - } - break; - - case AFT_NUM: - for (p = afflist; *p != NUL; ) { - int digits = getdigits_int(&p); - assert(digits >= 0); - n = (unsigned int)digits; - if (n == flag) - return true; - if (*p != NUL) // skip over comma - ++p; - } - break; - } - return false; -} - -// Give a warning when "spinval" and "affval" numbers are set and not the same. -static void aff_check_number(int spinval, int affval, char *name) -{ - if (spinval != 0 && spinval != affval) - smsg(_("%s value differs from what is used in another .aff file"), - name); -} - -// Give a warning when "spinval" and "affval" strings are set and not the same. -static void aff_check_string(char_u *spinval, char_u *affval, char *name) -{ - if (spinval != NULL && STRCMP(spinval, affval) != 0) - smsg(_("%s value differs from what is used in another .aff file"), - name); -} - -// Returns true if strings "s1" and "s2" are equal. Also consider both being -// NULL as equal. -static bool str_equal(char_u *s1, char_u *s2) -{ - if (s1 == NULL || s2 == NULL) - return s1 == s2; - return STRCMP(s1, s2) == 0; -} - -// Add a from-to item to "gap". Used for REP and SAL items. -// They are stored case-folded. -static void add_fromto(spellinfo_T *spin, garray_T *gap, char_u *from, char_u *to) -{ - char_u word[MAXWLEN]; - - fromto_T *ftp = GA_APPEND_VIA_PTR(fromto_T, gap); - (void)spell_casefold(from, (int)STRLEN(from), word, MAXWLEN); - ftp->ft_from = getroom_save(spin, word); - (void)spell_casefold(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; -static bool sal_to_bool(char_u *s) -{ - return STRCMP(s, "1") == 0 || STRCMP(s, "true") == 0; -} - -// Free the structure filled by spell_read_aff(). -static void spell_free_aff(afffile_T *aff) -{ - hashtab_T *ht; - hashitem_T *hi; - int todo; - affheader_T *ah; - affentry_T *ae; - - xfree(aff->af_enc); - - // All this trouble to free the "ae_prog" items... - for (ht = &aff->af_pref;; ht = &aff->af_suff) { - todo = (int)ht->ht_used; - for (hi = ht->ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - ah = HI2AH(hi); - for (ae = ah->ah_first; ae != NULL; ae = ae->ae_next) - vim_regfree(ae->ae_prog); - } - } - if (ht == &aff->af_suff) - break; - } - - hash_clear(&aff->af_pref); - hash_clear(&aff->af_suff); - hash_clear(&aff->af_comp); -} - -// Read dictionary file "fname". -// Returns OK or FAIL; -static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile) -{ - hashtab_T ht; - char_u line[MAXLINELEN]; - char_u *p; - char_u *afflist; - char_u store_afflist[MAXWLEN]; - int pfxlen; - bool need_affix; - char_u *dw; - char_u *pc; - char_u *w; - int l; - hash_T hash; - hashitem_T *hi; - FILE *fd; - int lnum = 1; - int non_ascii = 0; - int retval = OK; - char_u message[MAXLINELEN + MAXWLEN]; - int flags; - int duplicate = 0; - - // Open the file. - fd = mch_fopen((char *)fname, "r"); - if (fd == NULL) { - EMSG2(_(e_notopen), fname); - return FAIL; - } - - // The hashtable is only used to detect duplicated words. - hash_init(&ht); - - vim_snprintf((char *)IObuff, IOSIZE, - _("Reading dictionary file %s ..."), fname); - spell_message(spin, IObuff); - - // start with a message for the first line - spin->si_msg_count = 999999; - - // Read and ignore the first line: word count. - (void)vim_fgets(line, MAXLINELEN, fd); - if (!ascii_isdigit(*skipwhite(line))) - EMSG2(_("E760: No word count in %s"), fname); - - // Read all the lines in the file one by one. - // The words are converted to 'encoding' here, before being added to - // the hashtable. - while (!vim_fgets(line, MAXLINELEN, fd) && !got_int) { - line_breakcheck(); - ++lnum; - if (line[0] == '#' || line[0] == '/') - continue; // comment line - - // Remove CR, LF and white space from the end. White space halfway through - // the word is kept to allow multi-word terms like "et al.". - l = (int)STRLEN(line); - while (l > 0 && line[l - 1] <= ' ') - --l; - if (l == 0) - continue; // empty line - line[l] = NUL; - - // Convert from "SET" to 'encoding' when needed. - if (spin->si_conv.vc_type != CONV_NONE) { - pc = string_convert(&spin->si_conv, line, NULL); - if (pc == NULL) { - smsg(_("Conversion failure for word in %s line %d: %s"), - fname, lnum, line); - continue; - } - w = pc; - } else { - pc = NULL; - w = line; - } - - // Truncate the word at the "/", set "afflist" to what follows. - // Replace "\/" by "/" and "\\" by "\". - afflist = NULL; - for (p = w; *p != NUL; mb_ptr_adv(p)) { - if (*p == '\\' && (p[1] == '\\' || p[1] == '/')) - STRMOVE(p, p + 1); - else if (*p == '/') { - *p = NUL; - afflist = p + 1; - break; - } - } - - // Skip non-ASCII words when "spin->si_ascii" is true. - if (spin->si_ascii && has_non_ascii(w)) { - ++non_ascii; - xfree(pc); - continue; - } - - // This takes time, print a message every 10000 words. - if (spin->si_verbose && spin->si_msg_count > 10000) { - spin->si_msg_count = 0; - vim_snprintf((char *)message, sizeof(message), - _("line %6d, word %6d - %s"), - lnum, spin->si_foldwcount + spin->si_keepwcount, w); - msg_start(); - msg_puts_long_attr(message, 0); - msg_clr_eos(); - msg_didout = FALSE; - msg_col = 0; - ui_flush(); - } - - // Store the word in the hashtable to be able to find duplicates. - dw = getroom_save(spin, w); - if (dw == NULL) { - retval = FAIL; - xfree(pc); - break; - } - - hash = hash_hash(dw); - hi = hash_lookup(&ht, dw, hash); - if (!HASHITEM_EMPTY(hi)) { - if (p_verbose > 0) - smsg(_("Duplicate word in %s line %d: %s"), - fname, lnum, dw); - else if (duplicate == 0) - smsg(_("First duplicate word in %s line %d: %s"), - fname, lnum, dw); - ++duplicate; - } else - hash_add_item(&ht, hi, dw, hash); - - flags = 0; - store_afflist[0] = NUL; - pfxlen = 0; - need_affix = false; - if (afflist != NULL) { - // Extract flags from the affix list. - flags |= get_affix_flags(affile, afflist); - - if (affile->af_needaffix != 0 && flag_in_afflist( - affile->af_flagtype, 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); - - 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); - } - - // Add the word to the word tree(s). - if (store_word(spin, dw, flags, spin->si_region, - 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, - &affile->af_suff, &affile->af_pref, - CONDIT_SUF, flags, store_afflist, pfxlen) == FAIL) - retval = FAIL; - - // Find all matching prefixes and add the resulting words. - if (store_aff_word(spin, dw, afflist, affile, - &affile->af_pref, NULL, - CONDIT_SUF, flags, store_afflist, pfxlen) == FAIL) - retval = FAIL; - } - - xfree(pc); - } - - if (duplicate > 0) - smsg(_("%d duplicate word(s) in %s"), duplicate, fname); - if (spin->si_ascii && non_ascii > 0) - smsg(_("Ignored %d word(s) with non-ASCII characters in %s"), - non_ascii, fname); - hash_clear(&ht); - - fclose(fd); - return retval; -} - -// 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) -{ - int flags = 0; - - if (affile->af_keepcase != 0 && flag_in_afflist( - affile->af_flagtype, afflist, affile->af_keepcase)) - flags |= WF_KEEPCAP | WF_FIXCAP; - if (affile->af_rare != 0 && flag_in_afflist( - affile->af_flagtype, afflist, affile->af_rare)) - flags |= WF_RARE; - if (affile->af_bad != 0 && flag_in_afflist( - affile->af_flagtype, afflist, affile->af_bad)) - flags |= WF_BANNED; - if (affile->af_needcomp != 0 && flag_in_afflist( - affile->af_flagtype, afflist, affile->af_needcomp)) - flags |= WF_NEEDCOMP; - if (affile->af_comproot != 0 && flag_in_afflist( - affile->af_flagtype, afflist, affile->af_comproot)) - flags |= WF_COMPROOT; - if (affile->af_nosuggest != 0 && flag_in_afflist( - affile->af_flagtype, afflist, affile->af_nosuggest)) - flags |= WF_NOSUGGEST; - return flags; -} - -// Get the list of prefix IDs from the affix list "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) -{ - char_u *p; - char_u *prevp; - int cnt = 0; - int id; - char_u key[AH_KEY_LEN]; - hashitem_T *hi; - - for (p = afflist; *p != NUL; ) { - prevp = p; - if (get_affitem(affile->af_flagtype, &p) != 0) { - // A flag is a postponed prefix flag if it appears in "af_pref" - // and it's ID is not zero. - STRLCPY(key, prevp, p - prevp + 1); - hi = hash_find(&affile->af_pref, key); - if (!HASHITEM_EMPTY(hi)) { - id = HI2AH(hi)->ah_newID; - if (id != 0) - store_afflist[cnt++] = id; - } - } - if (affile->af_flagtype == AFT_NUM && *p == ',') - ++p; - } - - store_afflist[cnt] = NUL; - return cnt; -} - -// 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) -{ - char_u *p; - char_u *prevp; - int cnt = 0; - char_u key[AH_KEY_LEN]; - hashitem_T *hi; - - for (p = afflist; *p != NUL; ) { - prevp = p; - if (get_affitem(affile->af_flagtype, &p) != 0) { - // A flag is a compound flag if it appears in "af_comp". - STRLCPY(key, prevp, p - prevp + 1); - hi = hash_find(&affile->af_comp, key); - if (!HASHITEM_EMPTY(hi)) - store_afflist[cnt++] = HI2CI(hi)->ci_newID; - } - if (affile->af_flagtype == AFT_NUM && *p == ',') - ++p; - } - - store_afflist[cnt] = NUL; -} - -// Apply affixes to a word and store the resulting words. -// "ht" is the hashtable with affentry_T that need to be applied, either -// prefixes or suffixes. -// "xht", when not NULL, is the prefix hashtable, to be used additionally on -// the resulting words for combining affixes. -// -// Returns FAIL when out of memory. -static int -store_aff_word ( - spellinfo_T *spin, // spell info - char_u *word, // basic word start - char_u *afflist, // list of names of supported affixes - afffile_T *affile, - hashtab_T *ht, - hashtab_T *xht, - int condit, // CONDIT_SUF et al. - int flags, // flags for the word - char_u *pfxlist, // list of prefix IDs - int pfxlen // nr of flags in "pfxlist" for prefixes, rest - // is compound flags -) -{ - int todo; - hashitem_T *hi; - affheader_T *ah; - affentry_T *ae; - char_u newword[MAXWLEN]; - int retval = OK; - int i, j; - char_u *p; - int use_flags; - char_u *use_pfxlist; - int use_pfxlen; - bool need_affix; - char_u store_afflist[MAXWLEN]; - char_u pfx_pfxlist[MAXWLEN]; - size_t wordlen = STRLEN(word); - int use_condit; - - todo = (int)ht->ht_used; - for (hi = ht->ht_array; todo > 0 && retval == OK; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - ah = HI2AH(hi); - - // Check that the affix combines, if required, and that the word - // supports this affix. - if (((condit & CONDIT_COMB) == 0 || ah->ah_combine) - && flag_in_afflist(affile->af_flagtype, afflist, - ah->ah_flag)) { - // Loop over all affix entries with this name. - for (ae = ah->ah_first; ae != NULL; ae = ae->ae_next) { - // Check the condition. It's not logical to match case - // here, but it is required for compatibility with - // Myspell. - // Another requirement from Myspell is that the chop - // string is shorter than the word itself. - // For prefixes, when "PFXPOSTPONE" was used, only do - // prefixes with a chop string and/or flags. - // When a previously added affix had CIRCUMFIX this one - // must have it too, if it had not then this one must not - // have one either. - if ((xht != NULL || !affile->af_pfxpostpone - || ae->ae_chop != NULL - || ae->ae_flags != NULL) - && (ae->ae_chop == NULL - || STRLEN(ae->ae_chop) < wordlen) - && (ae->ae_prog == NULL - || vim_regexec_prog(&ae->ae_prog, false, word, (colnr_T)0)) - && (((condit & CONDIT_CFIX) == 0) - == ((condit & CONDIT_AFF) == 0 - || ae->ae_flags == NULL - || !flag_in_afflist(affile->af_flagtype, - ae->ae_flags, affile->af_circumfix)))) { - // Match. Remove the chop and add the affix. - if (xht == NULL) { - // prefix: chop/add at the start of the word - if (ae->ae_add == NULL) - *newword = NUL; - else - STRLCPY(newword, ae->ae_add, MAXWLEN); - p = word; - if (ae->ae_chop != NULL) { - // Skip chop string. - if (has_mbyte) { - i = mb_charlen(ae->ae_chop); - for (; i > 0; --i) - mb_ptr_adv(p); - } else - p += STRLEN(ae->ae_chop); - } - STRCAT(newword, p); - } else { - // suffix: chop/add at the end of the word - STRLCPY(newword, word, MAXWLEN); - if (ae->ae_chop != NULL) { - // Remove chop string. - p = newword + STRLEN(newword); - i = (int)MB_CHARLEN(ae->ae_chop); - for (; i > 0; --i) - mb_ptr_back(newword, p); - *p = NUL; - } - if (ae->ae_add != NULL) - STRCAT(newword, ae->ae_add); - } - - use_flags = flags; - use_pfxlist = pfxlist; - use_pfxlen = pfxlen; - need_affix = false; - use_condit = condit | CONDIT_COMB | CONDIT_AFF; - if (ae->ae_flags != NULL) { - // 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)) - 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)) { - use_condit |= CONDIT_CFIX; - if ((condit & CONDIT_CFIX) == 0) - need_affix = true; - } - - if (affile->af_pfxpostpone - || 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); - else - use_pfxlen = 0; - use_pfxlist = store_afflist; - - // Combine the prefix IDs. Avoid adding the - // same ID twice. - for (i = 0; i < pfxlen; ++i) { - for (j = 0; j < use_pfxlen; ++j) - if (pfxlist[i] == use_pfxlist[j]) - break; - if (j == use_pfxlen) - use_pfxlist[use_pfxlen++] = pfxlist[i]; - } - - if (spin->si_compflags != NULL) - // Get compound IDS from the affix list. - get_compflags(affile, ae->ae_flags, - use_pfxlist + use_pfxlen); - else - use_pfxlist[use_pfxlen] = NUL; - - // Combine the list of compound flags. - // Concatenate them to the prefix IDs list. - // Avoid adding the same ID twice. - for (i = pfxlen; pfxlist[i] != NUL; ++i) { - for (j = use_pfxlen; - use_pfxlist[j] != NUL; ++j) - if (pfxlist[i] == use_pfxlist[j]) - break; - if (use_pfxlist[j] == NUL) { - use_pfxlist[j++] = pfxlist[i]; - use_pfxlist[j] = NUL; - } - } - } - } - - // Obey a "COMPOUNDFORBIDFLAG" of the affix: don't - // use the compound flags. - if (use_pfxlist != NULL && ae->ae_compforbid) { - STRLCPY(pfx_pfxlist, use_pfxlist, use_pfxlen + 1); - use_pfxlist = pfx_pfxlist; - } - - // When there are postponed prefixes... - if (spin->si_prefroot != NULL - && spin->si_prefroot->wn_sibling != NULL) { - // ... add a flag to indicate an affix was used. - use_flags |= WF_HAS_AFF; - - // ... don't use a prefix list if combining - // affixes is not allowed. But do use the - // compound flags after them. - if (!ah->ah_combine && use_pfxlist != NULL) - use_pfxlist += use_pfxlen; - } - - // When compounding is supported and there is no - // "COMPOUNDPERMITFLAG" then forbid compounding on the - // side where the affix is applied. - if (spin->si_compflags != NULL && !ae->ae_comppermit) { - if (xht != NULL) - use_flags |= WF_NOCOMPAFT; - else - use_flags |= WF_NOCOMPBEF; - } - - // Store the modified word. - if (store_word(spin, newword, use_flags, - spin->si_region, use_pfxlist, - need_affix) == FAIL) - retval = FAIL; - - // When added a prefix or a first suffix and the affix - // has flags may add a(nother) suffix. RECURSIVE! - if ((condit & CONDIT_SUF) && ae->ae_flags != NULL) - if (store_aff_word(spin, newword, ae->ae_flags, - affile, &affile->af_suff, xht, - use_condit & (xht == NULL - ? ~0 : ~CONDIT_SUF), - use_flags, use_pfxlist, pfxlen) == FAIL) - retval = FAIL; - - // When added a suffix and combining is allowed also - // try adding a prefix additionally. Both for the - // word flags and for the affix flags. RECURSIVE! - if (xht != NULL && ah->ah_combine) { - if (store_aff_word(spin, newword, - afflist, affile, - xht, NULL, use_condit, - use_flags, use_pfxlist, - pfxlen) == FAIL - || (ae->ae_flags != NULL - && store_aff_word(spin, newword, - ae->ae_flags, affile, - xht, NULL, use_condit, - use_flags, use_pfxlist, - pfxlen) == FAIL)) - retval = FAIL; - } - } - } - } - } - } - - return retval; -} - -// Read a file with a list of words. -static int spell_read_wordfile(spellinfo_T *spin, char_u *fname) -{ - FILE *fd; - long lnum = 0; - char_u rline[MAXLINELEN]; - char_u *line; - char_u *pc = NULL; - char_u *p; - int l; - int retval = OK; - bool did_word = false; - int non_ascii = 0; - int flags; - int regionmask; - - // Open the file. - fd = mch_fopen((char *)fname, "r"); - if (fd == NULL) { - EMSG2(_(e_notopen), fname); - return FAIL; - } - - vim_snprintf((char *)IObuff, IOSIZE, _("Reading word file %s ..."), fname); - spell_message(spin, IObuff); - - // Read all the lines in the file one by one. - while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int) { - line_breakcheck(); - ++lnum; - - // Skip comment lines. - if (*rline == '#') - continue; - - // Remove CR, LF and white space from the end. - l = (int)STRLEN(rline); - while (l > 0 && rline[l - 1] <= ' ') - --l; - if (l == 0) - continue; // empty or blank line - rline[l] = NUL; - - // Convert from "/encoding={encoding}" to 'encoding' when needed. - xfree(pc); - if (spin->si_conv.vc_type != CONV_NONE) { - pc = string_convert(&spin->si_conv, rline, NULL); - if (pc == NULL) { - smsg(_("Conversion failure for word in %s line %d: %s"), - fname, lnum, rline); - continue; - } - line = pc; - } else { - pc = NULL; - line = rline; - } - - if (*line == '/') { - ++line; - if (STRNCMP(line, "encoding=", 9) == 0) { - if (spin->si_conv.vc_type != CONV_NONE) - smsg(_("Duplicate /encoding= line ignored in %s line %d: %s"), - fname, lnum, line - 1); - else if (did_word) - smsg(_("/encoding= line after word ignored in %s line %d: %s"), - fname, lnum, line - 1); - else { - char_u *enc; - - // Setup for conversion to 'encoding'. - line += 9; - enc = enc_canonize(line); - if (!spin->si_ascii - && convert_setup(&spin->si_conv, enc, - p_enc) == FAIL) - smsg(_("Conversion in %s not supported: from %s to %s"), - fname, line, p_enc); - xfree(enc); - spin->si_conv.vc_fail = true; - } - continue; - } - - if (STRNCMP(line, "regions=", 8) == 0) { - if (spin->si_region_count > 1) - smsg(_("Duplicate /regions= line ignored in %s line %d: %s"), - fname, lnum, line); - else { - line += 8; - if (STRLEN(line) > 16) - smsg(_("Too many regions in %s line %d: %s"), - fname, lnum, line); - else { - spin->si_region_count = (int)STRLEN(line) / 2; - STRCPY(spin->si_region_name, line); - - // Adjust the mask for a word valid in all regions. - spin->si_region = (1 << spin->si_region_count) - 1; - } - } - continue; - } - - smsg(_("/ line ignored in %s line %d: %s"), - fname, lnum, line - 1); - continue; - } - - flags = 0; - regionmask = spin->si_region; - - // Check for flags and region after a slash. - p = vim_strchr(line, '/'); - if (p != NULL) { - *p++ = NUL; - while (*p != NUL) { - if (*p == '=') // keep-case word - flags |= WF_KEEPCAP | WF_FIXCAP; - else if (*p == '!') // Bad, bad, wicked word. - flags |= WF_BANNED; - else if (*p == '?') // Rare word. - flags |= WF_RARE; - else if (ascii_isdigit(*p)) { // region number(s) - if ((flags & WF_REGION) == 0) // first one - regionmask = 0; - flags |= WF_REGION; - - l = *p - '0'; - if (l > spin->si_region_count) { - smsg(_("Invalid region nr in %s line %d: %s"), - fname, lnum, p); - break; - } - regionmask |= 1 << (l - 1); - } else { - smsg(_("Unrecognized flags in %s line %d: %s"), - fname, lnum, p); - break; - } - ++p; - } - } - - // Skip non-ASCII words when "spin->si_ascii" is true. - if (spin->si_ascii && has_non_ascii(line)) { - ++non_ascii; - continue; - } - - // Normal word: store it. - if (store_word(spin, line, flags, regionmask, NULL, false) == FAIL) { - retval = FAIL; - break; - } - did_word = true; - } - - xfree(pc); - fclose(fd); - - if (spin->si_ascii && non_ascii > 0) { - vim_snprintf((char *)IObuff, IOSIZE, - _("Ignored %d words with non-ASCII characters"), non_ascii); - spell_message(spin, IObuff); - } - - return retval; -} - -/// Get part of an sblock_T, "len" bytes long. -/// This avoids calling free() for every little struct we use (and keeping -/// track of them). -/// The memory is cleared to all zeros. -/// -/// @param len Length needed (<= SBLOCKSIZE). -/// @param align Align for pointer. -/// @return Pointer into block data. -static void *getroom(spellinfo_T *spin, size_t len, bool align) - FUNC_ATTR_NONNULL_RET -{ - char_u *p; - sblock_T *bl = spin->si_blocks; - - assert(len <= SBLOCKSIZE); - - if (align && bl != NULL) - // Round size up for alignment. On some systems structures need to be - // aligned to the size of a pointer (e.g., SPARC). - bl->sb_used = (bl->sb_used + sizeof(char *) - 1) - & ~(sizeof(char *) - 1); - - if (bl == NULL || bl->sb_used + len > SBLOCKSIZE) { - // Allocate a block of memory. It is not freed until much later. - bl = xcalloc(1, (sizeof(sblock_T) + SBLOCKSIZE)); - bl->sb_next = spin->si_blocks; - spin->si_blocks = bl; - bl->sb_used = 0; - ++spin->si_blocks_cnt; - } - - p = bl->sb_data + bl->sb_used; - bl->sb_used += (int)len; - - return p; -} - -// Make a copy of a string into memory allocated with getroom(). -// Returns NULL when out of memory. -static char_u *getroom_save(spellinfo_T *spin, char_u *s) -{ - char_u *sc; - - sc = (char_u *)getroom(spin, STRLEN(s) + 1, false); - if (sc != NULL) - STRCPY(sc, s); - return sc; -} - - -// Free the list of allocated sblock_T. -static void free_blocks(sblock_T *bl) -{ - sblock_T *next; - - while (bl != NULL) { - next = bl->sb_next; - xfree(bl); - bl = next; - } -} - -// Allocate the root of a word tree. -// Returns NULL when out of memory. -static wordnode_T *wordtree_alloc(spellinfo_T *spin) -{ - return (wordnode_T *)getroom(spin, sizeof(wordnode_T), true); -} - -// Store a word in the tree(s). -// Always store it in the case-folded tree. For a keep-case word this is -// useful when the word can also be used with all caps (no WF_FIXCAP flag) and -// used to find suggestions. -// For a keep-case word also store it in the keep-case tree. -// When "pfxlist" is not NULL store the word for each postponed prefix ID and -// compound flag. -static int -store_word ( - spellinfo_T *spin, - char_u *word, - int flags, // extra flags, WF_BANNED - int region, // supported region(s) - char_u *pfxlist, // list of prefix IDs or NULL - bool need_affix // only store word with affix ID -) -{ - int len = (int)STRLEN(word); - int ct = captype(word, word + len); - char_u foldword[MAXWLEN]; - int res = OK; - char_u *p; - - (void)spell_casefold(word, len, foldword, MAXWLEN); - for (p = 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); - if (p == NULL || *p == NUL) - break; - } - ++spin->si_foldwcount; - - if (res == OK && (ct == WF_KEEPCAP || (flags & WF_KEEPCAP))) { - for (p = pfxlist; res == OK; ++p) { - if (!need_affix || (p != NULL && *p != NUL)) - res = tree_add_word(spin, word, spin->si_keeproot, flags, - region, p == NULL ? 0 : *p); - if (p == NULL || *p == NUL) - break; - } - ++spin->si_keepwcount; - } - return res; -} - -// Add word "word" to a word tree at "root". -// When "flags" < 0 we are adding to the prefix tree where "flags" is used for -// "rare" and "region" is the condition nr. -// Returns FAIL when out of memory. -static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int flags, int region, int affixID) -{ - wordnode_T *node = root; - wordnode_T *np; - wordnode_T *copyp, **copyprev; - wordnode_T **prev = NULL; - int i; - - // Add each byte of the word to the tree, including the NUL at the end. - for (i = 0;; ++i) { - // When there is more than one reference to this node we need to make - // a copy, so that we can modify it. Copy the whole list of siblings - // (we don't optimize for a partly shared list of siblings). - if (node != NULL && node->wn_refs > 1) { - --node->wn_refs; - copyprev = prev; - for (copyp = node; copyp != NULL; copyp = copyp->wn_sibling) { - // Allocate a new node and copy the info. - np = get_wordnode(spin); - if (np == NULL) - return FAIL; - np->wn_child = copyp->wn_child; - if (np->wn_child != NULL) - ++np->wn_child->wn_refs; // child gets extra ref - np->wn_byte = copyp->wn_byte; - if (np->wn_byte == NUL) { - np->wn_flags = copyp->wn_flags; - np->wn_region = copyp->wn_region; - np->wn_affixID = copyp->wn_affixID; - } - - // Link the new node in the list, there will be one ref. - np->wn_refs = 1; - if (copyprev != NULL) - *copyprev = np; - copyprev = &np->wn_sibling; - - // Let "node" point to the head of the copied list. - if (copyp == node) - node = np; - } - } - - // Look for the sibling that has the same character. They are sorted - // on byte value, thus stop searching when a sibling is found with a - // higher byte value. For zero bytes (end of word) the sorting is - // done on flags and then on affixID. - while (node != NULL - && (node->wn_byte < word[i] - || (node->wn_byte == NUL - && (flags < 0 - ? node->wn_affixID < (unsigned)affixID - : (node->wn_flags < (unsigned)(flags & WN_MASK) - || (node->wn_flags == (flags & WN_MASK) - && (spin->si_sugtree - ? (node->wn_region & 0xffff) < region - : node->wn_affixID - < (unsigned)affixID))))))) { - prev = &node->wn_sibling; - node = *prev; - } - if (node == NULL - || node->wn_byte != word[i] - || (word[i] == NUL - && (flags < 0 - || spin->si_sugtree - || node->wn_flags != (flags & WN_MASK) - || node->wn_affixID != affixID))) { - // Allocate a new node. - np = get_wordnode(spin); - if (np == NULL) - return FAIL; - np->wn_byte = word[i]; - - // If "node" is NULL this is a new child or the end of the sibling - // list: ref count is one. Otherwise use ref count of sibling and - // make ref count of sibling one (matters when inserting in front - // of the list of siblings). - if (node == NULL) - np->wn_refs = 1; - else { - np->wn_refs = node->wn_refs; - node->wn_refs = 1; - } - if (prev != NULL) - *prev = np; - np->wn_sibling = node; - node = np; - } - - if (word[i] == NUL) { - node->wn_flags = flags; - node->wn_region |= region; - node->wn_affixID = affixID; - break; - } - prev = &node->wn_child; - node = *prev; - } -#ifdef SPELL_PRINTTREE - smsg((char_u *)"Added \"%s\"", word); - spell_print_tree(root->wn_sibling); -#endif - - // count nr of words added since last message - ++spin->si_msg_count; - - if (spin->si_compress_cnt > 1) { - if (--spin->si_compress_cnt == 1) - // Did enough words to lower the block count limit. - spin->si_blocks_cnt += compress_inc; - } - - // When we have allocated lots of memory we need to compress the word tree - // to free up some room. But compression is slow, and we might actually - // need that room, thus only compress in the following situations: - // 1. When not compressed before (si_compress_cnt == 0): when using - // "compress_start" blocks. - // 2. When compressed before and used "compress_inc" blocks before - // adding "compress_added" words (si_compress_cnt > 1). - // 3. When compressed before, added "compress_added" words - // (si_compress_cnt == 1) and the number of free nodes drops below the - // maximum word length. -#ifndef SPELL_COMPRESS_ALLWAYS - if (spin->si_compress_cnt == 1 // NOLINT(readability/braces) - ? spin->si_free_count < MAXWLEN - : spin->si_blocks_cnt >= compress_start) -#endif - { - // Decrement the block counter. The effect is that we compress again - // when the freed up room has been used and another "compress_inc" - // blocks have been allocated. Unless "compress_added" words have - // been added, then the limit is put back again. - spin->si_blocks_cnt -= compress_inc; - spin->si_compress_cnt = compress_added; - - if (spin->si_verbose) { - msg_start(); - msg_puts((char_u *)_(msg_compressing)); - msg_clr_eos(); - msg_didout = FALSE; - msg_col = 0; - ui_flush(); - } - - // Compress both trees. Either they both have many nodes, which makes - // compression useful, or one of them is small, which means - // compression goes fast. But when filling the soundfold word tree - // there is no keep-case tree. - wordtree_compress(spin, spin->si_foldroot); - if (affixID >= 0) - wordtree_compress(spin, spin->si_keeproot); - } - - return OK; -} - -// Check the 'mkspellmem' option. Return FAIL if it's wrong. -// Sets "sps_flags". -int spell_check_msm(void) -{ - char_u *p = p_msm; - long start = 0; - long incr = 0; - long added = 0; - - if (!ascii_isdigit(*p)) - return FAIL; - // block count = (value * 1024) / SBLOCKSIZE (but avoid overflow) - start = (getdigits_long(&p) * 10) / (SBLOCKSIZE / 102); - if (*p != ',') - return FAIL; - ++p; - if (!ascii_isdigit(*p)) - return FAIL; - incr = (getdigits_long(&p) * 102) / (SBLOCKSIZE / 10); - if (*p != ',') - return FAIL; - ++p; - if (!ascii_isdigit(*p)) - return FAIL; - added = getdigits_long(&p) * 1024; - if (*p != NUL) - return FAIL; - - if (start == 0 || incr == 0 || added == 0 || incr > start) - return FAIL; - - compress_start = start; - compress_inc = incr; - compress_added = added; - return OK; -} - -// Get a wordnode_T, either from the list of previously freed nodes or -// allocate a new one. -// Returns NULL when out of memory. -static wordnode_T *get_wordnode(spellinfo_T *spin) -{ - wordnode_T *n; - - if (spin->si_first_free == NULL) - n = (wordnode_T *)getroom(spin, sizeof(wordnode_T), true); - else { - n = spin->si_first_free; - spin->si_first_free = n->wn_child; - memset(n, 0, sizeof(wordnode_T)); - --spin->si_free_count; - } -#ifdef SPELL_PRINTTREE - if (n != NULL) - n->wn_nr = ++spin->si_wordnode_nr; -#endif - return n; -} - -// Decrement the reference count on a node (which is the head of a list of -// siblings). If the reference count becomes zero free the node and its -// siblings. -// Returns the number of nodes actually freed. -static int deref_wordnode(spellinfo_T *spin, wordnode_T *node) -{ - wordnode_T *np; - int cnt = 0; - - if (--node->wn_refs == 0) { - for (np = node; np != NULL; np = np->wn_sibling) { - if (np->wn_child != NULL) - cnt += deref_wordnode(spin, np->wn_child); - free_wordnode(spin, np); - ++cnt; - } - ++cnt; // length field - } - return cnt; -} - -// Free a wordnode_T for re-use later. -// Only the "wn_child" field becomes invalid. -static void free_wordnode(spellinfo_T *spin, wordnode_T *n) -{ - n->wn_child = spin->si_first_free; - spin->si_first_free = n; - ++spin->si_free_count; -} - -// Compress a tree: find tails that are identical and can be shared. -static void wordtree_compress(spellinfo_T *spin, wordnode_T *root) -{ - hashtab_T ht; - int n; - int tot = 0; - int perc; - - // 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); - n = node_compress(spin, root->wn_sibling, &ht, &tot); - -#ifndef SPELL_PRINTTREE - 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((char *)IObuff, IOSIZE, - _("Compressed %d of %d nodes; %d (%d%%) remaining"), - n, tot, tot - n, perc); - spell_message(spin, IObuff); - } -#ifdef SPELL_PRINTTREE - spell_print_tree(root->wn_sibling); -#endif - hash_clear(&ht); - } -} - -// Compress a node, its siblings and its children, depth first. -// Returns the number of compressed nodes. -static int -node_compress ( - spellinfo_T *spin, - wordnode_T *node, - hashtab_T *ht, - int *tot // total count of nodes before compressing, - // incremented while going through the tree -) -{ - wordnode_T *np; - wordnode_T *tp; - wordnode_T *child; - hash_T hash; - hashitem_T *hi; - int len = 0; - unsigned nr, n; - int compressed = 0; - - // Go through the list of siblings. Compress each child and then try - // finding an identical child to replace it. - // Note that with "child" we mean not just the node that is pointed to, - // but the whole list of siblings of which the child node is the first. - for (np = node; np != NULL && !got_int; np = np->wn_sibling) { - ++len; - if ((child = np->wn_child) != NULL) { - // Compress the child first. This fills hashkey. - compressed += node_compress(spin, child, ht, tot); - - // Try to find an identical child. - hash = hash_hash(child->wn_u1.hashkey); - hi = hash_lookup(ht, child->wn_u1.hashkey, hash); - if (!HASHITEM_EMPTY(hi)) { - // There are children we encountered before with a hash value - // identical to the current child. Now check if there is one - // that is really identical. - for (tp = HI2WN(hi); tp != NULL; tp = tp->wn_u2.next) - if (node_equal(child, tp)) { - // Found one! Now use that child in place of the - // current one. This means the current child and all - // its siblings is unlinked from the tree. - ++tp->wn_refs; - compressed += deref_wordnode(spin, child); - np->wn_child = tp; - break; - } - if (tp == NULL) { - // No other child with this hash value equals the child of - // the node, add it to the linked list after the first - // item. - tp = HI2WN(hi); - child->wn_u2.next = tp->wn_u2.next; - tp->wn_u2.next = child; - } - } else - // No other child has this hash value, add it to the - // hashtable. - hash_add_item(ht, hi, child->wn_u1.hashkey, hash); - } - } - *tot += len + 1; // add one for the node that stores the length - - // Make a hash key for the node and its siblings, so that we can quickly - // find a lookalike node. This must be done after compressing the sibling - // list, otherwise the hash key would become invalid by the compression. - node->wn_u1.hashkey[0] = len; - nr = 0; - for (np = node; np != NULL; np = np->wn_sibling) { - if (np->wn_byte == NUL) - // end node: use wn_flags, wn_region and wn_affixID - n = np->wn_flags + (np->wn_region << 8) + (np->wn_affixID << 16); - else - // byte node: use the byte value and the child pointer - n = (unsigned)(np->wn_byte + ((uintptr_t)np->wn_child << 8)); - nr = nr * 101 + n; - } - - // Avoid NUL bytes, it terminates the hash key. - n = nr & 0xff; - node->wn_u1.hashkey[1] = n == 0 ? 1 : n; - n = (nr >> 8) & 0xff; - node->wn_u1.hashkey[2] = n == 0 ? 1 : n; - n = (nr >> 16) & 0xff; - node->wn_u1.hashkey[3] = n == 0 ? 1 : n; - n = (nr >> 24) & 0xff; - node->wn_u1.hashkey[4] = n == 0 ? 1 : n; - node->wn_u1.hashkey[5] = NUL; - - // Check for CTRL-C pressed now and then. - fast_breakcheck(); - - return compressed; -} - -// Returns true when two nodes have identical siblings and children. -static bool node_equal(wordnode_T *n1, wordnode_T *n2) -{ - wordnode_T *p1; - wordnode_T *p2; - - for (p1 = n1, p2 = n2; p1 != NULL && p2 != NULL; - p1 = p1->wn_sibling, p2 = p2->wn_sibling) - if (p1->wn_byte != p2->wn_byte - || (p1->wn_byte == NUL - ? (p1->wn_flags != p2->wn_flags - || p1->wn_region != p2->wn_region - || p1->wn_affixID != p2->wn_affixID) - : (p1->wn_child != p2->wn_child))) - break; - - return p1 == NULL && p2 == NULL; -} - - -// Function given to qsort() to sort the REP items on "from" string. -static int rep_compare(const void *s1, const void *s2) -{ - fromto_T *p1 = (fromto_T *)s1; - fromto_T *p2 = (fromto_T *)s2; - - return STRCMP(p1->ft_from, p2->ft_from); -} - -// Write the Vim .spl file "fname". -// Return OK/FAIL. -static int write_vim_spell(spellinfo_T *spin, char_u *fname) -{ - int retval = OK; - int regionmask; - - FILE *fd = mch_fopen((char *)fname, "w"); - if (fd == NULL) { - EMSG2(_(e_notopen), fname); - return FAIL; - } - - // <HEADER>: <fileID> <versionnr> - // <fileID> - size_t fwv = fwrite(VIMSPELLMAGIC, VIMSPELLMAGICL, 1, fd); - if (fwv != (size_t)1) - // Catch first write error, don't try writing more. - goto theend; - - putc(VIMSPELLVERSION, fd); // <versionnr> - - // <SECTIONS>: <section> ... <sectionend> - - // SN_INFO: <infotext> - if (spin->si_info != NULL) { - putc(SN_INFO, fd); // <sectionID> - putc(0, fd); // <sectionflags> - size_t i = STRLEN(spin->si_info); - put_bytes(fd, i, 4); // <sectionlen> - fwv &= fwrite(spin->si_info, i, 1, fd); // <infotext> - } - - // SN_REGION: <regionname> ... - // Write the region names only if there is more than one. - if (spin->si_region_count > 1) { - putc(SN_REGION, fd); // <sectionID> - putc(SNF_REQUIRED, fd); // <sectionflags> - size_t l = (size_t)spin->si_region_count * 2; - put_bytes(fd, l, 4); // <sectionlen> - fwv &= fwrite(spin->si_region_name, l, 1, fd); - // <regionname> ... - regionmask = (1 << spin->si_region_count) - 1; - } else - regionmask = 0; - - // SN_CHARFLAGS: <charflagslen> <charflags> <folcharslen> <folchars> - // - // The table with character flags and the table for case folding. - // This makes sure the same characters are recognized as word characters - // when generating an when using a spell file. - // Skip this for ASCII, the table may conflict with the one used for - // 'encoding'. - // Also skip this for an .add.spl file, the main spell file must contain - // the table (avoids that it conflicts). File is shorter too. - if (!spin->si_ascii && !spin->si_add) { - char_u folchars[128 * 8]; - int flags; - - putc(SN_CHARFLAGS, fd); // <sectionID> - putc(SNF_REQUIRED, fd); // <sectionflags> - - // Form the <folchars> string first, we need to know its length. - size_t l = 0; - for (size_t i = 128; i < 256; ++i) { - if (has_mbyte) - l += (size_t)mb_char2bytes(spelltab.st_fold[i], folchars + l); - else - folchars[l++] = spelltab.st_fold[i]; - } - put_bytes(fd, 1 + 128 + 2 + l, 4); // <sectionlen> - - fputc(128, fd); // <charflagslen> - for (size_t i = 128; i < 256; ++i) { - flags = 0; - if (spelltab.st_isw[i]) - flags |= CF_WORD; - if (spelltab.st_isu[i]) - flags |= CF_UPPER; - fputc(flags, fd); // <charflags> - } - - put_bytes(fd, l, 2); // <folcharslen> - fwv &= fwrite(folchars, l, 1, fd); // <folchars> - } - - // SN_MIDWORD: <midword> - if (spin->si_midword != NULL) { - putc(SN_MIDWORD, fd); // <sectionID> - putc(SNF_REQUIRED, fd); // <sectionflags> - - size_t i = STRLEN(spin->si_midword); - put_bytes(fd, i, 4); // <sectionlen> - fwv &= fwrite(spin->si_midword, i, 1, fd); - // <midword> - } - - // SN_PREFCOND: <prefcondcnt> <prefcond> ... - if (!GA_EMPTY(&spin->si_prefcond)) { - putc(SN_PREFCOND, fd); // <sectionID> - putc(SNF_REQUIRED, fd); // <sectionflags> - - size_t l = (size_t)write_spell_prefcond(NULL, &spin->si_prefcond); - put_bytes(fd, l, 4); // <sectionlen> - - write_spell_prefcond(fd, &spin->si_prefcond); - } - - // SN_REP: <repcount> <rep> ... - // SN_SAL: <salflags> <salcount> <sal> ... - // SN_REPSAL: <repcount> <rep> ... - - // round 1: SN_REP section - // round 2: SN_SAL section (unless SN_SOFO is used) - // round 3: SN_REPSAL section - for (unsigned int round = 1; round <= 3; ++round) { - garray_T *gap; - if (round == 1) - gap = &spin->si_rep; - else if (round == 2) { - // Don't write SN_SAL when using a SN_SOFO section - if (spin->si_sofofr != NULL && spin->si_sofoto != NULL) - continue; - gap = &spin->si_sal; - } else - gap = &spin->si_repsal; - - // Don't write the section if there are no items. - if (GA_EMPTY(gap)) - continue; - - // Sort the REP/REPSAL items. - if (round != 2) - qsort(gap->ga_data, (size_t)gap->ga_len, - sizeof(fromto_T), rep_compare); - - int i = round == 1 ? SN_REP : (round == 2 ? SN_SAL : SN_REPSAL); - putc(i, fd); // <sectionID> - - // This is for making suggestions, section is not required. - putc(0, fd); // <sectionflags> - - // Compute the length of what follows. - size_t l = 2; // count <repcount> or <salcount> - assert(gap->ga_len >= 0); - for (size_t i = 0; i < (size_t)gap->ga_len; ++i) { - fromto_T *ftp = &((fromto_T *)gap->ga_data)[i]; - l += 1 + STRLEN(ftp->ft_from); // count <*fromlen> and <*from> - l += 1 + STRLEN(ftp->ft_to); // count <*tolen> and <*to> - } - if (round == 2) - ++l; // count <salflags> - put_bytes(fd, l, 4); // <sectionlen> - - if (round == 2) { - int i = 0; - if (spin->si_followup) - i |= SAL_F0LLOWUP; - if (spin->si_collapse) - i |= SAL_COLLAPSE; - if (spin->si_rem_accents) - i |= SAL_REM_ACCENTS; - putc(i, fd); // <salflags> - } - - put_bytes(fd, (uintmax_t)gap->ga_len, 2); // <repcount> or <salcount> - for (size_t i = 0; i < (size_t)gap->ga_len; ++i) { - // <rep> : <repfromlen> <repfrom> <reptolen> <repto> - // <sal> : <salfromlen> <salfrom> <saltolen> <salto> - fromto_T *ftp = &((fromto_T *)gap->ga_data)[i]; - for (unsigned int rr = 1; rr <= 2; ++rr) { - char_u *p = rr == 1 ? ftp->ft_from : ftp->ft_to; - l = STRLEN(p); - assert(l < INT_MAX); - putc((int)l, fd); - if (l > 0) - fwv &= fwrite(p, l, 1, fd); - } - } - - } - - // SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto> - // This is for making suggestions, section is not required. - if (spin->si_sofofr != NULL && spin->si_sofoto != NULL) { - putc(SN_SOFO, fd); // <sectionID> - putc(0, fd); // <sectionflags> - - size_t l = STRLEN(spin->si_sofofr); - put_bytes(fd, l + STRLEN(spin->si_sofoto) + 4, 4); // <sectionlen> - - put_bytes(fd, l, 2); // <sofofromlen> - fwv &= fwrite(spin->si_sofofr, l, 1, fd); // <sofofrom> - - l = STRLEN(spin->si_sofoto); - put_bytes(fd, l, 2); // <sofotolen> - fwv &= fwrite(spin->si_sofoto, l, 1, fd); // <sofoto> - } - - // SN_WORDS: <word> ... - // This is for making suggestions, section is not required. - if (spin->si_commonwords.ht_used > 0) { - putc(SN_WORDS, fd); // <sectionID> - putc(0, fd); // <sectionflags> - - // round 1: count the bytes - // round 2: write the bytes - for (unsigned int round = 1; round <= 2; ++round) { - size_t todo; - size_t len = 0; - hashitem_T *hi; - - todo = spin->si_commonwords.ht_used; - for (hi = spin->si_commonwords.ht_array; todo > 0; ++hi) - if (!HASHITEM_EMPTY(hi)) { - size_t l = STRLEN(hi->hi_key) + 1; - len += l; - if (round == 2) // <word> - fwv &= fwrite(hi->hi_key, l, 1, fd); - --todo; - } - if (round == 1) - put_bytes(fd, len, 4); // <sectionlen> - } - } - - // SN_MAP: <mapstr> - // This is for making suggestions, section is not required. - if (!GA_EMPTY(&spin->si_map)) { - putc(SN_MAP, fd); // <sectionID> - putc(0, fd); // <sectionflags> - size_t l = (size_t)spin->si_map.ga_len; - put_bytes(fd, l, 4); // <sectionlen> - fwv &= fwrite(spin->si_map.ga_data, l, 1, fd); // <mapstr> - } - - // SN_SUGFILE: <timestamp> - // This is used to notify that a .sug file may be available and at the - // same time allows for checking that a .sug file that is found matches - // with this .spl file. That's because the word numbers must be exactly - // right. - if (!spin->si_nosugfile - && (!GA_EMPTY(&spin->si_sal) - || (spin->si_sofofr != NULL && spin->si_sofoto != NULL))) { - putc(SN_SUGFILE, fd); // <sectionID> - putc(0, fd); // <sectionflags> - put_bytes(fd, 8, 4); // <sectionlen> - - // Set si_sugtime and write it to the file. - spin->si_sugtime = time(NULL); - put_time(fd, spin->si_sugtime); // <timestamp> - } - - // SN_NOSPLITSUGS: nothing - // This is used to notify that no suggestions with word splits are to be - // made. - if (spin->si_nosplitsugs) { - putc(SN_NOSPLITSUGS, fd); // <sectionID> - putc(0, fd); // <sectionflags> - put_bytes(fd, 0, 4); // <sectionlen> - } - - // SN_NOCOMPUNDSUGS: nothing - // This is used to notify that no suggestions with compounds are to be - // made. - if (spin->si_nocompoundsugs) { - putc(SN_NOCOMPOUNDSUGS, fd); // <sectionID> - putc(0, fd); // <sectionflags> - put_bytes(fd, 0, 4); // <sectionlen> - } - - // SN_COMPOUND: compound info. - // We don't mark it required, when not supported all compound words will - // be bad words. - if (spin->si_compflags != NULL) { - putc(SN_COMPOUND, fd); // <sectionID> - putc(0, fd); // <sectionflags> - - size_t l = STRLEN(spin->si_compflags); - assert(spin->si_comppat.ga_len >= 0); - for (size_t i = 0; i < (size_t)spin->si_comppat.ga_len; ++i) { - l += STRLEN(((char_u **)(spin->si_comppat.ga_data))[i]) + 1; - } - put_bytes(fd, l + 7, 4); // <sectionlen> - - putc(spin->si_compmax, fd); // <compmax> - putc(spin->si_compminlen, fd); // <compminlen> - putc(spin->si_compsylmax, fd); // <compsylmax> - putc(0, fd); // for Vim 7.0b compatibility - putc(spin->si_compoptions, fd); // <compoptions> - put_bytes(fd, (uintmax_t)spin->si_comppat.ga_len, 2); // <comppatcount> - for (size_t i = 0; i < (size_t)spin->si_comppat.ga_len; ++i) { - char_u *p = ((char_u **)(spin->si_comppat.ga_data))[i]; - assert(STRLEN(p) < INT_MAX); - putc((int)STRLEN(p), fd); // <comppatlen> - fwv &= fwrite(p, STRLEN(p), 1, fd); // <comppattext> - } - // <compflags> - fwv &= fwrite(spin->si_compflags, STRLEN(spin->si_compflags), 1, fd); - } - - // SN_NOBREAK: NOBREAK flag - if (spin->si_nobreak) { - putc(SN_NOBREAK, fd); // <sectionID> - putc(0, fd); // <sectionflags> - - // It's empty, the presence of the section flags the feature. - put_bytes(fd, 0, 4); // <sectionlen> - } - - // SN_SYLLABLE: syllable info. - // We don't mark it required, when not supported syllables will not be - // counted. - if (spin->si_syllable != NULL) { - putc(SN_SYLLABLE, fd); // <sectionID> - putc(0, fd); // <sectionflags> - - size_t l = STRLEN(spin->si_syllable); - put_bytes(fd, l, 4); // <sectionlen> - fwv &= fwrite(spin->si_syllable, l, 1, fd); // <syllable> - } - - // end of <SECTIONS> - putc(SN_END, fd); // <sectionend> - - - // <LWORDTREE> <KWORDTREE> <PREFIXTREE> - spin->si_memtot = 0; - for (unsigned int round = 1; round <= 3; ++round) { - wordnode_T *tree; - if (round == 1) - tree = spin->si_foldroot->wn_sibling; - else if (round == 2) - tree = spin->si_keeproot->wn_sibling; - else - tree = spin->si_prefroot->wn_sibling; - - // Clear the index and wnode fields in the tree. - clear_node(tree); - - // Count the number of nodes. Needed to be able to allocate the - // memory when reading the nodes. Also fills in index for shared - // nodes. - size_t nodecount = (size_t)put_node(NULL, tree, 0, regionmask, round == 3); - - // number of nodes in 4 bytes - put_bytes(fd, nodecount, 4); // <nodecount> - assert(nodecount + nodecount * sizeof(int) < INT_MAX); - spin->si_memtot += (int)(nodecount + nodecount * sizeof(int)); - - // Write the nodes. - (void)put_node(fd, tree, 0, regionmask, round == 3); - } - - // Write another byte to check for errors (file system full). - if (putc(0, fd) == EOF) - retval = FAIL; -theend: - if (fclose(fd) == EOF) - retval = FAIL; - - if (fwv != (size_t)1) - retval = FAIL; - if (retval == FAIL) - EMSG(_(e_write)); - - return retval; -} - -// Clear the index and wnode fields of "node", it siblings and its -// children. This is needed because they are a union with other items to save -// space. -static void clear_node(wordnode_T *node) -{ - wordnode_T *np; - - if (node != NULL) - for (np = node; np != NULL; np = np->wn_sibling) { - np->wn_u1.index = 0; - np->wn_u2.wnode = NULL; - - if (np->wn_byte != NUL) - clear_node(np->wn_child); - } -} - - -// Dump a word tree at node "node". -// -// This first writes the list of possible bytes (siblings). Then for each -// byte recursively write the children. -// -// NOTE: The code here must match the code in read_tree_node(), since -// assumptions are made about the indexes (so that we don't have to write them -// in the file). -// -// Returns the number of nodes used. -static int -put_node ( - FILE *fd, // NULL when only counting - wordnode_T *node, - int idx, - int regionmask, - bool prefixtree // true for PREFIXTREE -) -{ - // If "node" is zero the tree is empty. - if (node == NULL) - return 0; - - // Store the index where this node is written. - node->wn_u1.index = idx; - - // Count the number of siblings. - int siblingcount = 0; - for (wordnode_T *np = node; np != NULL; np = np->wn_sibling) - ++siblingcount; - - // Write the sibling count. - if (fd != NULL) - putc(siblingcount, fd); // <siblingcount> - - // Write each sibling byte and optionally extra info. - for (wordnode_T *np = node; np != NULL; np = np->wn_sibling) { - if (np->wn_byte == 0) { - if (fd != NULL) { - // For a NUL byte (end of word) write the flags etc. - if (prefixtree) { - // In PREFIXTREE write the required affixID and the - // associated condition nr (stored in wn_region). The - // byte value is misused to store the "rare" and "not - // combining" flags - if (np->wn_flags == (uint16_t)PFX_FLAGS) - putc(BY_NOFLAGS, fd); // <byte> - else { - putc(BY_FLAGS, fd); // <byte> - putc(np->wn_flags, fd); // <pflags> - } - putc(np->wn_affixID, fd); // <affixID> - put_bytes(fd, (uintmax_t)np->wn_region, 2); // <prefcondnr> - } else { - // For word trees we write the flag/region items. - int flags = np->wn_flags; - if (regionmask != 0 && np->wn_region != regionmask) - flags |= WF_REGION; - if (np->wn_affixID != 0) - flags |= WF_AFX; - if (flags == 0) { - // word without flags or region - putc(BY_NOFLAGS, fd); // <byte> - } else { - if (np->wn_flags >= 0x100) { - putc(BY_FLAGS2, fd); // <byte> - putc(flags, fd); // <flags> - putc((int)((unsigned)flags >> 8), fd); // <flags2> - } else { - putc(BY_FLAGS, fd); // <byte> - putc(flags, fd); // <flags> - } - if (flags & WF_REGION) - putc(np->wn_region, fd); // <region> - if (flags & WF_AFX) - putc(np->wn_affixID, fd); // <affixID> - } - } - } - } else { - if (np->wn_child->wn_u1.index != 0 - && np->wn_child->wn_u2.wnode != node) { - // The child is written elsewhere, write the reference. - if (fd != NULL) { - putc(BY_INDEX, fd); // <byte> - put_bytes(fd, (uintmax_t)np->wn_child->wn_u1.index, 3); // <nodeidx> - } - } else if (np->wn_child->wn_u2.wnode == NULL) - // We will write the child below and give it an index. - np->wn_child->wn_u2.wnode = node; - - if (fd != NULL) - if (putc(np->wn_byte, fd) == EOF) { // <byte> or <xbyte> - EMSG(_(e_write)); - return 0; - } - } - } - - // Space used in the array when reading: one for each sibling and one for - // the count. - int newindex = idx + siblingcount + 1; - - // Recursively dump the children of each sibling. - for (wordnode_T *np = node; np != NULL; np = np->wn_sibling) - if (np->wn_byte != 0 && np->wn_child->wn_u2.wnode == node) - newindex = put_node(fd, np->wn_child, newindex, regionmask, - prefixtree); - - return newindex; -} - - -// ":mkspell [-ascii] outfile infile ..." -// ":mkspell [-ascii] addfile" -void ex_mkspell(exarg_T *eap) -{ - int fcount; - char_u **fnames; - char_u *arg = eap->arg; - bool ascii = false; - - if (STRNCMP(arg, "-ascii", 6) == 0) { - ascii = true; - arg = skipwhite(arg + 6); - } - - // 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); - } -} - -// Create the .sug file. -// Uses the soundfold info in "spin". -// Writes the file with the name "wfname", with ".spl" changed to ".sug". -static void spell_make_sugfile(spellinfo_T *spin, char_u *wfname) -{ - char_u *fname = NULL; - int len; - slang_T *slang; - bool free_slang = false; - - // Read back the .spl file that was written. This fills the required - // info for soundfolding. This also uses less memory than the - // pointer-linked version of the trie. And it avoids having two versions - // of the code for the soundfolding stuff. - // It might have been done already by spell_reload_one(). - for (slang = first_lang; slang != NULL; slang = slang->sl_next) - if (path_full_compare(wfname, slang->sl_fname, FALSE) == kEqualFiles) - break; - if (slang == NULL) { - spell_message(spin, (char_u *)_("Reading back spell file...")); - slang = spell_load_file(wfname, NULL, NULL, false); - if (slang == NULL) - return; - free_slang = true; - } - - // Clear the info in "spin" that is used. - spin->si_blocks = NULL; - spin->si_blocks_cnt = 0; - spin->si_compress_cnt = 0; // will stay at 0 all the time - spin->si_free_count = 0; - spin->si_first_free = NULL; - spin->si_foldwcount = 0; - - // Go through the trie of good words, soundfold each word and add it to - // the soundfold trie. - spell_message(spin, (char_u *)_("Performing soundfolding...")); - if (sug_filltree(spin, slang) == FAIL) - goto theend; - - // Create the table which links each soundfold word with a list of the - // good words it may come from. Creates buffer "spin->si_spellbuf". - // This also removes the wordnr from the NUL byte entries to make - // compression possible. - if (sug_maketable(spin) == FAIL) - goto theend; - - smsg(_("Number of words after soundfolding: %" PRId64), - (int64_t)spin->si_spellbuf->b_ml.ml_line_count); - - // Compress the soundfold trie. - spell_message(spin, (char_u *)_(msg_compressing)); - wordtree_compress(spin, spin->si_foldroot); - - // Write the .sug file. - // Make the file name by changing ".spl" to ".sug". - fname = xmalloc(MAXPATHL); - STRLCPY(fname, wfname, MAXPATHL); - len = (int)STRLEN(fname); - fname[len - 2] = 'u'; - fname[len - 1] = 'g'; - sug_write(spin, fname); - -theend: - xfree(fname); - if (free_slang) - slang_free(slang); - free_blocks(spin->si_blocks); - close_spellbuf(spin->si_spellbuf); -} - -// Build the soundfold trie for language "slang". -static int sug_filltree(spellinfo_T *spin, slang_T *slang) -{ - char_u *byts; - idx_T *idxs; - int depth; - idx_T arridx[MAXWLEN]; - int curi[MAXWLEN]; - char_u tword[MAXWLEN]; - char_u tsalword[MAXWLEN]; - int c; - idx_T n; - unsigned words_done = 0; - int wordcount[MAXWLEN]; - - // We use si_foldroot for the soundfolded trie. - spin->si_foldroot = wordtree_alloc(spin); - if (spin->si_foldroot == NULL) - return FAIL; - - // Let tree_add_word() know we're adding to the soundfolded tree - spin->si_sugtree = true; - - // Go through the whole case-folded tree, soundfold each word and put it - // in the trie. - byts = slang->sl_fbyts; - idxs = slang->sl_fidxs; - - arridx[0] = 0; - curi[0] = 1; - wordcount[0] = 0; - - depth = 0; - while (depth >= 0 && !got_int) { - if (curi[depth] > byts[arridx[depth]]) { - // Done all bytes at this node, go up one level. - idxs[arridx[depth]] = wordcount[depth]; - if (depth > 0) - wordcount[depth - 1] += wordcount[depth]; - - --depth; - line_breakcheck(); - } else { - - // Do one more byte at this node. - n = arridx[depth] + curi[depth]; - ++curi[depth]; - - c = byts[n]; - if (c == 0) { - // Sound-fold the word. - tword[depth] = NUL; - spell_soundfold(slang, tword, true, tsalword); - - // We use the "flags" field for the MSB of the wordnr, - // "region" for the LSB of the wordnr. - if (tree_add_word(spin, tsalword, spin->si_foldroot, - words_done >> 16, words_done & 0xffff, - 0) == FAIL) - return FAIL; - - ++words_done; - ++wordcount[depth]; - - // Reset the block count each time to avoid compression - // kicking in. - spin->si_blocks_cnt = 0; - - // Skip over any other NUL bytes (same word with different - // flags). - while (byts[n + 1] == 0) { - ++n; - ++curi[depth]; - } - } else { - // Normal char, go one level deeper. - tword[depth++] = c; - arridx[depth] = idxs[n]; - curi[depth] = 1; - wordcount[depth] = 0; - } - } - } - - smsg(_("Total number of words: %d"), words_done); - - return OK; -} - -// Make the table that links each word in the soundfold trie to the words it -// can be produced from. -// This is not unlike lines in a file, thus use a memfile to be able to access -// the table efficiently. -// Returns FAIL when out of memory. -static int sug_maketable(spellinfo_T *spin) -{ - garray_T ga; - int res = OK; - - // Allocate a buffer, open a memline for it and create the swap file - // (uses a temp file, not a .swp file). - spin->si_spellbuf = open_spellbuf(); - - // Use a buffer to store the line info, avoids allocating many small - // pieces of memory. - ga_init(&ga, 1, 100); - - // recursively go through the tree - if (sug_filltable(spin, spin->si_foldroot->wn_sibling, 0, &ga) == -1) - res = FAIL; - - ga_clear(&ga); - return res; -} - -// Fill the table for one node and its children. -// Returns the wordnr at the start of the node. -// Returns -1 when out of memory. -static int -sug_filltable ( - spellinfo_T *spin, - wordnode_T *node, - int startwordnr, - garray_T *gap // place to store line of numbers -) -{ - wordnode_T *p, *np; - int wordnr = startwordnr; - int nr; - int prev_nr; - - for (p = node; p != NULL; p = p->wn_sibling) { - if (p->wn_byte == NUL) { - gap->ga_len = 0; - prev_nr = 0; - for (np = p; np != NULL && np->wn_byte == NUL; np = np->wn_sibling) { - ga_grow(gap, 10); - - nr = (np->wn_flags << 16) + (np->wn_region & 0xffff); - // Compute the offset from the previous nr and store the - // offset in a way that it takes a minimum number of bytes. - // It's a bit like utf-8, but without the need to mark - // following bytes. - nr -= prev_nr; - prev_nr += nr; - gap->ga_len += offset2bytes(nr, - (char_u *)gap->ga_data + gap->ga_len); - } - - // add the NUL byte - ((char_u *)gap->ga_data)[gap->ga_len++] = NUL; - - if (ml_append_buf(spin->si_spellbuf, (linenr_T)wordnr, - gap->ga_data, gap->ga_len, TRUE) == FAIL) - return -1; - ++wordnr; - - // Remove extra NUL entries, we no longer need them. We don't - // bother freeing the nodes, the won't be reused anyway. - while (p->wn_sibling != NULL && p->wn_sibling->wn_byte == NUL) - p->wn_sibling = p->wn_sibling->wn_sibling; - - // Clear the flags on the remaining NUL node, so that compression - // works a lot better. - p->wn_flags = 0; - p->wn_region = 0; - } else { - wordnr = sug_filltable(spin, p->wn_child, wordnr, gap); - if (wordnr == -1) - return -1; - } - } - return wordnr; -} - -// Convert an offset into a minimal number of bytes. -// Similar to utf_char2byters, but use 8 bits in followup bytes and avoid NUL -// bytes. -static int offset2bytes(int nr, char_u *buf) -{ - int rem; - int b1, b2, b3, b4; - - // Split the number in parts of base 255. We need to avoid NUL bytes. - b1 = nr % 255 + 1; - rem = nr / 255; - b2 = rem % 255 + 1; - rem = rem / 255; - b3 = rem % 255 + 1; - b4 = rem / 255 + 1; - - if (b4 > 1 || b3 > 0x1f) { // 4 bytes - buf[0] = 0xe0 + b4; - buf[1] = b3; - buf[2] = b2; - buf[3] = b1; - return 4; - } - if (b3 > 1 || b2 > 0x3f ) { // 3 bytes - buf[0] = 0xc0 + b3; - buf[1] = b2; - buf[2] = b1; - return 3; - } - if (b2 > 1 || b1 > 0x7f ) { // 2 bytes - buf[0] = 0x80 + b2; - buf[1] = b1; - return 2; - } - // 1 byte - buf[0] = b1; - return 1; -} // Opposite of offset2bytes(). // "pp" points to the bytes and is advanced over it. @@ -7442,86 +2473,12 @@ static int bytes2offset(char_u **pp) return nr; } -// Write the .sug file in "fname". -static void sug_write(spellinfo_T *spin, char_u *fname) -{ - // Create the file. Note that an existing file is silently overwritten! - FILE *fd = mch_fopen((char *)fname, "w"); - if (fd == NULL) { - EMSG2(_(e_notopen), fname); - return; - } - - vim_snprintf((char *)IObuff, IOSIZE, - _("Writing suggestion file %s ..."), fname); - spell_message(spin, IObuff); - - // <SUGHEADER>: <fileID> <versionnr> <timestamp> - if (fwrite(VIMSUGMAGIC, VIMSUGMAGICL, (size_t)1, fd) != 1) { // <fileID> - EMSG(_(e_write)); - goto theend; - } - putc(VIMSUGVERSION, fd); // <versionnr> - - // Write si_sugtime to the file. - put_time(fd, spin->si_sugtime); // <timestamp> - - // <SUGWORDTREE> - spin->si_memtot = 0; - wordnode_T *tree = spin->si_foldroot->wn_sibling; - - // Clear the index and wnode fields in the tree. - clear_node(tree); - - // Count the number of nodes. Needed to be able to allocate the - // memory when reading the nodes. Also fills in index for shared - // nodes. - size_t nodecount = (size_t)put_node(NULL, tree, 0, 0, false); - - // number of nodes in 4 bytes - put_bytes(fd, nodecount, 4); // <nodecount> - assert(nodecount + nodecount * sizeof(int) < INT_MAX); - spin->si_memtot += (int)(nodecount + nodecount * sizeof(int)); - - // Write the nodes. - (void)put_node(fd, tree, 0, 0, false); - - // <SUGTABLE>: <sugwcount> <sugline> ... - linenr_T wcount = spin->si_spellbuf->b_ml.ml_line_count; - assert(wcount >= 0); - put_bytes(fd, (uintmax_t)wcount, 4); // <sugwcount> - - for (linenr_T lnum = 1; lnum <= wcount; ++lnum) { - // <sugline>: <sugnr> ... NUL - char_u *line = ml_get_buf(spin->si_spellbuf, lnum, FALSE); - size_t len = STRLEN(line) + 1; - if (fwrite(line, len, 1, fd) == 0) { - EMSG(_(e_write)); - goto theend; - } - assert((size_t)spin->si_memtot + len <= INT_MAX); - spin->si_memtot += (int)len; - } - - // Write another byte to check for errors. - if (putc(0, fd) == EOF) - EMSG(_(e_write)); - - vim_snprintf((char *)IObuff, IOSIZE, - _("Estimated runtime memory use: %d bytes"), spin->si_memtot); - spell_message(spin, IObuff); - -theend: - // close the file - fclose(fd); -} - // Open a spell buffer. This is a nameless buffer that is not in the buffer // list and only contains text lines. Can use a swapfile to reduce memory // use. // Most other fields are invalid! Esp. watch out for string options being // NULL and there is no undo info. -static buf_T *open_spellbuf(void) +buf_T *open_spellbuf(void) { buf_T *buf = xcalloc(1, sizeof(buf_T)); @@ -7534,7 +2491,7 @@ static buf_T *open_spellbuf(void) } // Close the buffer used for spell info. -static void close_spellbuf(buf_T *buf) +void close_spellbuf(buf_T *buf) { if (buf != NULL) { ml_close(buf, TRUE); @@ -7542,471 +2499,8 @@ static void close_spellbuf(buf_T *buf) } } - -// Create a Vim spell file from one or more word lists. -// "fnames[0]" is the output file name. -// "fnames[fcount - 1]" is the last input file name. -// Exception: when "fnames[0]" ends in ".add" it's used as the input file name -// and ".spl" is appended to make the output file name. -static void -mkspell ( - int fcount, - char_u **fnames, - bool ascii, // -ascii argument given - bool over_write, // overwrite existing output file - bool added_word // invoked through "zg" -) -{ - char_u *fname = NULL; - char_u *wfname; - char_u **innames; - int incount; - afffile_T *(afile[8]); - int i; - int len; - bool error = false; - spellinfo_T spin; - - memset(&spin, 0, sizeof(spin)); - spin.si_verbose = !added_word; - spin.si_ascii = ascii; - spin.si_followup = true; - spin.si_rem_accents = true; - 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); - hash_init(&spin.si_commonwords); - spin.si_newcompID = 127; // start compound ID at first maximum - - // default: fnames[0] is output file, following are input files - innames = &fnames[1]; - incount = fcount - 1; - - wfname = xmalloc(MAXPATHL); - - if (fcount >= 1) { - len = (int)STRLEN(fnames[0]); - if (fcount == 1 && len > 4 && STRCMP(fnames[0] + len - 4, ".add") == 0) { - // For ":mkspell path/en.latin1.add" output file is - // "path/en.latin1.add.spl". - innames = &fnames[0]; - incount = 1; - vim_snprintf((char *)wfname, MAXPATHL, "%s.spl", fnames[0]); - } else if (fcount == 1) { - // For ":mkspell path/vim" output file is "path/vim.latin1.spl". - innames = &fnames[0]; - incount = 1; - vim_snprintf((char *)wfname, MAXPATHL, SPL_FNAME_TMPL, - fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc()); - } else if (len > 4 && STRCMP(fnames[0] + len - 4, ".spl") == 0) { - // Name ends in ".spl", use as the file name. - STRLCPY(wfname, fnames[0], MAXPATHL); - } else - // Name should be language, make the file name from it. - vim_snprintf((char *)wfname, MAXPATHL, SPL_FNAME_TMPL, - fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc()); - - // Check for .ascii.spl. - if (strstr((char *)path_tail(wfname), SPL_FNAME_ASCII) != NULL) - spin.si_ascii = true; - - // Check for .add.spl. - if (strstr((char *)path_tail(wfname), SPL_FNAME_ADD) != NULL) - spin.si_add = true; - } - - if (incount <= 0) - EMSG(_(e_invarg)); // need at least output and input names - else if (vim_strchr(path_tail(wfname), '_') != NULL) - EMSG(_("E751: Output file name must not have region name")); - else if (incount > 8) - EMSG(_("E754: Only up to 8 regions supported")); - else { - // Check for overwriting before doing things that may take a lot of - // time. - if (!over_write && os_path_exists(wfname)) { - EMSG(_(e_exists)); - goto theend; - } - if (os_isdir(wfname)) { - EMSG2(_(e_isadir2), wfname); - goto theend; - } - - fname = xmalloc(MAXPATHL); - - // Init the aff and dic pointers. - // Get the region names if there are more than 2 arguments. - for (i = 0; i < incount; ++i) { - afile[i] = NULL; - - if (incount > 1) { - len = (int)STRLEN(innames[i]); - if (STRLEN(path_tail(innames[i])) < 5 - || innames[i][len - 3] != '_') { - EMSG2(_("E755: Invalid region in %s"), innames[i]); - goto theend; - } - spin.si_region_name[i * 2] = TOLOWER_ASC(innames[i][len - 2]); - spin.si_region_name[i * 2 + 1] = - TOLOWER_ASC(innames[i][len - 1]); - } - } - spin.si_region_count = incount; - - spin.si_foldroot = wordtree_alloc(&spin); - spin.si_keeproot = wordtree_alloc(&spin); - spin.si_prefroot = wordtree_alloc(&spin); - if (spin.si_foldroot == NULL - || spin.si_keeproot == NULL - || spin.si_prefroot == NULL) { - free_blocks(spin.si_blocks); - goto theend; - } - - // When not producing a .add.spl file clear the character table when - // we encounter one in the .aff file. This means we dump the current - // one in the .spl file if the .aff file doesn't define one. That's - // better than guessing the contents, the table will match a - // previously loaded spell file. - if (!spin.si_add) - spin.si_clear_chartab = true; - - // Read all the .aff and .dic files. - // Text is converted to 'encoding'. - // Words are stored in the case-folded and keep-case trees. - for (i = 0; i < incount && !error; ++i) { - 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(fname)) { - // Read the .aff file. Will init "spin->si_conv" based on the - // "SET" line. - afile[i] = spell_read_aff(&spin, fname); - if (afile[i] == NULL) - error = true; - else { - // Read the .dic file and store the words in the trees. - vim_snprintf((char *)fname, MAXPATHL, "%s.dic", - innames[i]); - if (spell_read_dic(&spin, fname, afile[i]) == FAIL) - error = true; - } - } else { - // No .aff file, try reading the file as a word list. Store - // the words in the trees. - if (spell_read_wordfile(&spin, innames[i]) == FAIL) - error = true; - } - - // Free any conversion stuff. - convert_setup(&spin.si_conv, NULL, NULL); - } - - if (spin.si_compflags != NULL && spin.si_nobreak) - MSG(_("Warning: both compounding and NOBREAK specified")); - - if (!error && !got_int) { - // Combine tails in the tree. - spell_message(&spin, (char_u *)_(msg_compressing)); - wordtree_compress(&spin, spin.si_foldroot); - wordtree_compress(&spin, spin.si_keeproot); - wordtree_compress(&spin, spin.si_prefroot); - } - - if (!error && !got_int) { - // Write the info in the spell file. - vim_snprintf((char *)IObuff, IOSIZE, - _("Writing spell file %s ..."), wfname); - spell_message(&spin, IObuff); - - error = write_vim_spell(&spin, wfname) == FAIL; - - spell_message(&spin, (char_u *)_("Done!")); - vim_snprintf((char *)IObuff, IOSIZE, - _("Estimated runtime memory use: %d bytes"), spin.si_memtot); - spell_message(&spin, IObuff); - - // If the file is loaded need to reload it. - if (!error) - spell_reload_one(wfname, added_word); - } - - // Free the allocated memory. - ga_clear(&spin.si_rep); - ga_clear(&spin.si_repsal); - ga_clear(&spin.si_sal); - ga_clear(&spin.si_map); - ga_clear(&spin.si_comppat); - ga_clear(&spin.si_prefcond); - hash_clear_all(&spin.si_commonwords, 0); - - // Free the .aff file structures. - for (i = 0; i < incount; ++i) - if (afile[i] != NULL) - spell_free_aff(afile[i]); - - // Free all the bits and pieces at once. - free_blocks(spin.si_blocks); - - // If there is soundfolding info and no NOSUGFILE item create the - // .sug file with the soundfolded word trie. - if (spin.si_sugtime != 0 && !error && !got_int) - spell_make_sugfile(&spin, wfname); - - } - -theend: - xfree(fname); - xfree(wfname); -} - -// Display a message for spell file processing when 'verbose' is set or using -// ":mkspell". "str" can be IObuff. -static void spell_message(spellinfo_T *spin, char_u *str) -{ - if (spin->si_verbose || p_verbose > 2) { - if (!spin->si_verbose) - verbose_enter(); - MSG(str); - ui_flush(); - if (!spin->si_verbose) - verbose_leave(); - } -} - -// ":[count]spellgood {word}" -// ":[count]spellwrong {word}" -// ":[count]spellundo {word}" -void ex_spell(exarg_T *eap) -{ - spell_add_word(eap->arg, (int)STRLEN(eap->arg), eap->cmdidx == CMD_spellwrong, - eap->forceit ? 0 : (int)eap->line2, - eap->cmdidx == CMD_spellundo); -} - -// Add "word[len]" to 'spellfile' as a good or bad word. -void -spell_add_word ( - char_u *word, - int len, - int bad, - int idx, // "zG" and "zW": zero, otherwise index in - // 'spellfile' - bool undo // true for "zug", "zuG", "zuw" and "zuW" -) -{ - FILE *fd = NULL; - buf_T *buf = NULL; - bool new_spf = false; - char_u *fname; - char_u *fnamebuf = NULL; - char_u line[MAXWLEN * 2]; - long fpos, fpos_next = 0; - int i; - char_u *spf; - - if (idx == 0) { // use internal wordlist - if (int_wordlist == NULL) { - int_wordlist = vim_tempname(); - if (int_wordlist == NULL) - return; - } - fname = int_wordlist; - } else { - // If 'spellfile' isn't set figure out a good default value. - if (*curwin->w_s->b_p_spf == NUL) { - init_spellfile(); - new_spf = true; - } - - if (*curwin->w_s->b_p_spf == NUL) { - EMSG2(_(e_notset), "spellfile"); - return; - } - fnamebuf = xmalloc(MAXPATHL); - - for (spf = curwin->w_s->b_p_spf, i = 1; *spf != NUL; ++i) { - copy_option_part(&spf, fnamebuf, MAXPATHL, ","); - if (i == idx) - break; - if (*spf == NUL) { - EMSGN(_("E765: 'spellfile' does not have %" PRId64 " entries"), idx); - xfree(fnamebuf); - return; - } - } - - // Check that the user isn't editing the .add file somewhere. - buf = buflist_findname_exp(fnamebuf); - if (buf != NULL && buf->b_ml.ml_mfp == NULL) - buf = NULL; - if (buf != NULL && bufIsChanged(buf)) { - EMSG(_(e_bufloaded)); - xfree(fnamebuf); - return; - } - - fname = fnamebuf; - } - - if (bad || undo) { - // When the word appears as good word we need to remove that one, - // since its flags sort before the one with WF_BANNED. - fd = mch_fopen((char *)fname, "r"); - if (fd != NULL) { - while (!vim_fgets(line, MAXWLEN * 2, fd)) { - fpos = fpos_next; - fpos_next = ftell(fd); - if (STRNCMP(word, line, len) == 0 - && (line[len] == '/' || line[len] < ' ')) { - // Found duplicate word. Remove it by writing a '#' at - // the start of the line. Mixing reading and writing - // doesn't work for all systems, close the file first. - fclose(fd); - fd = mch_fopen((char *)fname, "r+"); - if (fd == NULL) - break; - if (fseek(fd, fpos, SEEK_SET) == 0) { - fputc('#', fd); - if (undo) { - home_replace(NULL, fname, NameBuff, MAXPATHL, TRUE); - smsg(_("Word '%.*s' removed from %s"), - len, word, NameBuff); - } - } - fseek(fd, fpos_next, SEEK_SET); - } - } - if (fd != NULL) - fclose(fd); - } - } - - if (!undo) { - fd = mch_fopen((char *)fname, "a"); - if (fd == NULL && new_spf) { - char_u *p; - - // We just initialized the 'spellfile' option and can't open the - // file. We may need to create the "spell" directory first. We - // already checked the runtime directory is writable in - // init_spellfile(). - if (!dir_of_file_exists(fname) && (p = path_tail_with_sep(fname)) != fname) { - int c = *p; - - // The directory doesn't exist. Try creating it and opening - // the file again. - *p = NUL; - os_mkdir((char *)fname, 0755); - *p = c; - fd = mch_fopen((char *)fname, "a"); - } - } - - if (fd == NULL) - EMSG2(_(e_notopen), fname); - else { - if (bad) - fprintf(fd, "%.*s/!\n", len, word); - else - fprintf(fd, "%.*s\n", len, word); - fclose(fd); - - home_replace(NULL, fname, NameBuff, MAXPATHL, TRUE); - smsg(_("Word '%.*s' added to %s"), len, word, NameBuff); - } - } - - if (fd != NULL) { - // Update the .add.spl file. - mkspell(1, &fname, false, true, true); - - // If the .add file is edited somewhere, reload it. - if (buf != NULL) - buf_reload(buf, buf->b_orig_mode); - - redraw_all_later(SOME_VALID); - } - xfree(fnamebuf); -} - -// Initialize 'spellfile' for the current buffer. -static void init_spellfile(void) -{ - char_u *buf; - int l; - char_u *fname; - char_u *rtp; - char_u *lend; - bool aspath = false; - char_u *lstart = 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 = curwin->w_s->b_p_spl; *lend != NUL - && vim_strchr((char_u *)",._", *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 = p_rtp; - while (*rtp != NUL) { - if (aspath) - // Use directory of an entry with path, e.g., for - // "/dir/lg.utf-8.spl" use "/dir". - STRLCPY(buf, curbuf->b_s.b_p_spl, - 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((char *)buf) == 2) { - // Use the first language name from 'spelllang' and the - // encoding used in the first loaded .spl file. - if (aspath) - STRLCPY(buf, curbuf->b_s.b_p_spl, - lend - curbuf->b_s.b_p_spl + 1); - else { - // Create the "spell" directory if it doesn't exist yet. - l = (int)STRLEN(buf); - vim_snprintf((char *)buf + l, MAXPATHL - l, "/spell"); - if (os_file_is_writable((char *)buf) != 2) { - os_mkdir((char *)buf, 0755); - } - - l = (int)STRLEN(buf); - vim_snprintf((char *)buf + l, MAXPATHL - l, - "/%.*s", (int)(lend - lstart), lstart); - } - l = (int)STRLEN(buf); - fname = LANGP_ENTRY(curwin->w_s->b_langp, 0) - ->lp_slang->sl_fname; - vim_snprintf((char *)buf + l, MAXPATHL - l, ".%s.add", - fname != NULL - && strstr((char *)path_tail(fname), ".ascii.") != NULL - ? (char_u *)"ascii" : spell_enc()); - set_option_value((char_u *)"spellfile", 0L, buf, OPT_LOCAL); - break; - } - aspath = false; - } - - xfree(buf); - } -} - // Init the chartab used for spelling for ASCII. -static void clear_spell_chartab(spelltab_T *sp) +void clear_spell_chartab(spelltab_T *sp) { int i; @@ -8034,8 +2528,7 @@ static void clear_spell_chartab(spelltab_T *sp) } } -// Init the chartab used for spelling. Only depends on 'encoding'. -// Called once while starting up and when 'encoding' changes. +// Init the chartab used for spelling. Called once while starting up. // The default is to use isalpha(), but the spell file should define the word // characters to make it possible that 'encoding' differs from the current // locale. For utf-8 we don't use isalpha() but our own functions. @@ -8045,154 +2538,18 @@ void init_spell_chartab(void) did_set_spelltab = false; clear_spell_chartab(&spelltab); - if (enc_dbcs) { - // DBCS: assume double-wide characters are word characters. - for (i = 128; i <= 255; ++i) - if (MB_BYTE2LEN(i) == 2) - spelltab.st_isw[i] = true; - } else if (enc_utf8) { - for (i = 128; i < 256; ++i) { - int f = utf_fold(i); - int u = utf_toupper(i); - - spelltab.st_isu[i] = utf_isupper(i); - spelltab.st_isw[i] = spelltab.st_isu[i] || utf_islower(i); - // The folded/upper-cased value is different between latin1 and - // utf8 for 0xb5, causing E763 for no good reason. Use the latin1 - // value for utf-8 to avoid this. - spelltab.st_fold[i] = (f < 256) ? f : i; - spelltab.st_upper[i] = (u < 256) ? u : i; - } - } else { - // Rough guess: use locale-dependent library functions. - for (i = 128; i < 256; ++i) { - if (vim_isupper(i)) { - spelltab.st_isw[i] = true; - spelltab.st_isu[i] = true; - spelltab.st_fold[i] = vim_tolower(i); - } else if (vim_islower(i)) { - spelltab.st_isw[i] = true; - spelltab.st_upper[i] = vim_toupper(i); - } - } - } -} - -// Set the spell character tables from strings in the affix file. -static int set_spell_chartab(char_u *fol, char_u *low, char_u *upp) -{ - // We build the new tables here first, so that we can compare with the - // previous one. - spelltab_T new_st; - char_u *pf = fol, *pl = low, *pu = upp; - int f, l, u; - - clear_spell_chartab(&new_st); - - while (*pf != NUL) { - if (*pl == NUL || *pu == NUL) { - EMSG(_(e_affform)); - return FAIL; - } - f = mb_ptr2char_adv(&pf); - l = mb_ptr2char_adv(&pl); - u = mb_ptr2char_adv(&pu); - // Every character that appears is a word character. - if (f < 256) - new_st.st_isw[f] = true; - if (l < 256) - new_st.st_isw[l] = true; - if (u < 256) - new_st.st_isw[u] = true; - - // if "LOW" and "FOL" are not the same the "LOW" char needs - // case-folding - if (l < 256 && l != f) { - if (f >= 256) { - EMSG(_(e_affrange)); - return FAIL; - } - new_st.st_fold[l] = f; - } - - // if "UPP" and "FOL" are not the same the "UPP" char needs - // case-folding, it's upper case and the "UPP" is the upper case of - // "FOL" . - if (u < 256 && u != f) { - if (f >= 256) { - EMSG(_(e_affrange)); - return FAIL; - } - new_st.st_fold[u] = f; - new_st.st_isu[u] = true; - new_st.st_upper[f] = u; - } - } + for (i = 128; i < 256; i++) { + int f = utf_fold(i); + int u = mb_toupper(i); - if (*pl != NUL || *pu != NUL) { - EMSG(_(e_affform)); - return FAIL; + spelltab.st_isu[i] = mb_isupper(i); + spelltab.st_isw[i] = spelltab.st_isu[i] || mb_islower(i); + // The folded/upper-cased value is different between latin1 and + // utf8 for 0xb5, causing E763 for no good reason. Use the latin1 + // value for utf-8 to avoid this. + spelltab.st_fold[i] = (f < 256) ? f : i; + spelltab.st_upper[i] = (u < 256) ? u : i; } - - return set_spell_finish(&new_st); -} - -// Set the spell character tables from strings in the .spl file. -static void -set_spell_charflags ( - char_u *flags, - int cnt, // length of "flags" - char_u *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; - int c; - - clear_spell_chartab(&new_st); - - for (i = 0; i < 128; ++i) { - if (i < cnt) { - new_st.st_isw[i + 128] = (flags[i] & CF_WORD) != 0; - new_st.st_isu[i + 128] = (flags[i] & CF_UPPER) != 0; - } - - if (*p != NUL) { - c = mb_ptr2char_adv(&p); - new_st.st_fold[i + 128] = c; - if (i + 128 != c && new_st.st_isu[i + 128] && c < 256) - new_st.st_upper[c] = i + 128; - } - } - - (void)set_spell_finish(&new_st); -} - -static int set_spell_finish(spelltab_T *new_st) -{ - int i; - - if (did_set_spelltab) { - // check that it's the same table - for (i = 0; i < 256; ++i) { - if (spelltab.st_isw[i] != new_st->st_isw[i] - || spelltab.st_isu[i] != new_st->st_isu[i] - || spelltab.st_fold[i] != new_st->st_fold[i] - || spelltab.st_upper[i] != new_st->st_upper[i]) { - EMSG(_("E763: Word characters differ between spell files")); - return FAIL; - } - } - } else { - // copy the new spelltab into the one being used - spelltab = *new_st; - did_set_spelltab = true; - } - - return OK; } /// Returns true if "p" points to a word character. @@ -8233,14 +2590,15 @@ static bool spell_iswordp(char_u *p, win_T *wp) // Returns true if "p" points to a word character. // Unlike spell_iswordp() this doesn't check for "midword" characters. -static bool spell_iswordp_nmw(char_u *p, win_T *wp) +bool spell_iswordp_nmw(const char_u *p, win_T *wp) { int c; if (has_mbyte) { c = mb_ptr2char(p); - if (c > 255) + if (c > 255) { return spell_mb_isword_class(mb_get_class(p), wp); + } return spelltab.st_isw[c]; } return spelltab.st_isw[*p]; @@ -8249,7 +2607,7 @@ static bool spell_iswordp_nmw(char_u *p, win_T *wp) // Returns true if word class indicates a word character. // Only for characters above 255. // Unicode subscript and superscript are not considered word characters. -// See also dbcs_class() and utf_class() in mbyte.c. +// See also utf_class() in mbyte.c. static bool spell_mb_isword_class(int cl, win_T *wp) { if (wp->w_s->b_cjk) @@ -8272,51 +2630,16 @@ static bool spell_iswordp_w(int *p, win_T *wp) s = p; if (*s > 255) { - if (enc_utf8) - return spell_mb_isword_class(utf_class(*s), wp); - if (enc_dbcs) - return spell_mb_isword_class( - dbcs_class((unsigned)*s >> 8, *s & 0xff), wp); - return false; + return spell_mb_isword_class(utf_class(*s), wp); } return spelltab.st_isw[*s]; } -// Write the table with prefix conditions to the .spl file. -// When "fd" is NULL only count the length of what is written. -static int write_spell_prefcond(FILE *fd, garray_T *gap) -{ - assert(gap->ga_len >= 0); - - if (fd != NULL) - put_bytes(fd, (uintmax_t)gap->ga_len, 2); // <prefcondcnt> - - size_t totlen = 2 + (size_t)gap->ga_len; // <prefcondcnt> and <condlen> bytes - size_t x = 1; // collect return value of fwrite() - for (int i = 0; i < gap->ga_len; ++i) { - // <prefcond> : <condlen> <condstr> - char_u *p = ((char_u **)gap->ga_data)[i]; - if (p != NULL) { - size_t len = STRLEN(p); - if (fd != NULL) { - assert(len <= INT_MAX); - fputc((int)len, fd); - x &= fwrite(p, len, 1, fd); - } - totlen += len; - } else if (fd != NULL) - fputc(0, fd); - } - - assert(totlen <= INT_MAX); - return (int)totlen; -} - // Case-fold "str[len]" into "buf[buflen]". The result is NUL terminated. // Uses the character definitions from the .spl file. // When using a multi-byte 'encoding' the length may change! // Returns FAIL when something wrong. -static int spell_casefold(char_u *str, int len, char_u *buf, int buflen) +int spell_casefold(char_u *str, int len, char_u *buf, int buflen) { int i; @@ -8336,7 +2659,7 @@ static int spell_casefold(char_u *str, int len, char_u *buf, int buflen) buf[outi] = NUL; return FAIL; } - c = mb_cptr2char_adv(&p); + c = mb_cptr2char_adv((const char_u **)&p); outi += mb_char2bytes(SPELL_TOFOLD(c), buf + outi); } buf[outi] = NUL; @@ -8510,7 +2833,7 @@ void spell_suggest(int count) vim_snprintf((char *)IObuff, IOSIZE, ":ot \"%.*s\" egnahC", sug.su_badlen, sug.su_badptr); } - msg_puts(IObuff); + msg_puts((const char *)IObuff); msg_clr_eos(); msg_putchar('\n'); @@ -8526,18 +2849,19 @@ void spell_suggest(int count) sug.su_badptr + stp->st_orglen, sug.su_badlen - stp->st_orglen + 1); vim_snprintf((char *)IObuff, IOSIZE, "%2d", i + 1); - if (cmdmsg_rl) + if (cmdmsg_rl) { rl_mirror(IObuff); - msg_puts(IObuff); + } + msg_puts((const char *)IObuff); vim_snprintf((char *)IObuff, IOSIZE, " \"%s\"", wcopy); - msg_puts(IObuff); + msg_puts((const char *)IObuff); // The word may replace more than "su_badlen". if (sug.su_badlen < stp->st_orglen) { vim_snprintf((char *)IObuff, IOSIZE, _(" < \"%.*s\""), - stp->st_orglen, sug.su_badptr); - msg_puts(IObuff); + stp->st_orglen, sug.su_badptr); + msg_puts((const char *)IObuff); } if (p_verbose > 0) { @@ -8553,7 +2877,7 @@ void spell_suggest(int count) // Mirror the numbers, but keep the leading space. rl_mirror(IObuff + 1); msg_advance(30); - msg_puts(IObuff); + msg_puts((const char *)IObuff); } msg_putchar('\n'); } @@ -8597,7 +2921,7 @@ void spell_suggest(int count) // For redo we use a change-word command. ResetRedobuff(); - AppendToRedobuff((char_u *)"ciw"); + AppendToRedobuff("ciw"); AppendToRedobuffLit(p + c, stp->st_wordlen + sug.su_badlen - stp->st_orglen); AppendCharToRedobuff(ESC); @@ -8892,7 +3216,7 @@ static void spell_suggest_expr(suginfo_T *su, char_u *expr) list_T *list; listitem_T *li; int score; - char_u *p; + const char *p; // The work is split up in a few parts to avoid having to export // suginfo_T. @@ -8904,11 +3228,12 @@ static void spell_suggest_expr(suginfo_T *su, char_u *expr) if (li->li_tv.v_type == VAR_LIST) { // Get the word and the score from the items. score = get_spellword(li->li_tv.vval.v_list, &p); - if (score >= 0 && score <= su->su_maxscore) - add_suggestion(su, &su->su_ga, p, su->su_badlen, - score, 0, true, su->su_sallang, false); + if (score >= 0 && score <= su->su_maxscore) { + add_suggestion(su, &su->su_ga, (const char_u *)p, su->su_badlen, + score, 0, true, su->su_sallang, false); + } } - list_unref(list); + tv_list_unref(list); } // Remove bogus suggestions, sort and truncate at "maxcount". @@ -9039,174 +3364,6 @@ static void spell_suggest_intern(suginfo_T *su, bool interactive) } } -// Load the .sug files for languages that have one and weren't loaded yet. -static void suggest_load_files(void) -{ - langp_T *lp; - slang_T *slang; - char_u *dotp; - FILE *fd; - char_u buf[MAXWLEN]; - int i; - time_t timestamp; - int wcount; - int wordnr; - garray_T ga; - int c; - - // Do this for all languages that support sound folding. - for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) { - lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); - slang = lp->lp_slang; - if (slang->sl_sugtime != 0 && !slang->sl_sugloaded) { - // Change ".spl" to ".sug" and open the file. When the file isn't - // found silently skip it. Do set "sl_sugloaded" so that we - // don't try again and again. - slang->sl_sugloaded = true; - - dotp = vim_strrchr(slang->sl_fname, '.'); - if (dotp == NULL || fnamecmp(dotp, ".spl") != 0) - continue; - STRCPY(dotp, ".sug"); - fd = mch_fopen((char *)slang->sl_fname, "r"); - if (fd == NULL) - goto nextone; - - // <SUGHEADER>: <fileID> <versionnr> <timestamp> - for (i = 0; i < VIMSUGMAGICL; ++i) - buf[i] = getc(fd); // <fileID> - if (STRNCMP(buf, VIMSUGMAGIC, VIMSUGMAGICL) != 0) { - EMSG2(_("E778: This does not look like a .sug file: %s"), - slang->sl_fname); - goto nextone; - } - c = getc(fd); // <versionnr> - if (c < VIMSUGVERSION) { - EMSG2(_("E779: Old .sug file, needs to be updated: %s"), - slang->sl_fname); - goto nextone; - } else if (c > VIMSUGVERSION) { - EMSG2(_("E780: .sug file is for newer version of Vim: %s"), - slang->sl_fname); - goto nextone; - } - - // Check the timestamp, it must be exactly the same as the one in - // the .spl file. Otherwise the word numbers won't match. - timestamp = get8ctime(fd); // <timestamp> - if (timestamp != slang->sl_sugtime) { - EMSG2(_("E781: .sug file doesn't match .spl file: %s"), - slang->sl_fname); - goto nextone; - } - - // <SUGWORDTREE>: <wordtree> - // Read the trie with the soundfolded words. - if (spell_read_tree(fd, &slang->sl_sbyts, &slang->sl_sidxs, - false, 0) != 0) { -someerror: - EMSG2(_("E782: error while reading .sug file: %s"), - slang->sl_fname); - slang_clear_sug(slang); - goto nextone; - } - - // <SUGTABLE>: <sugwcount> <sugline> ... - // - // Read the table with word numbers. We use a file buffer for - // this, because it's so much like a file with lines. Makes it - // possible to swap the info and save on memory use. - slang->sl_sugbuf = open_spellbuf(); - - // <sugwcount> - wcount = get4c(fd); - if (wcount < 0) - goto someerror; - - // Read all the wordnr lists into the buffer, one NUL terminated - // list per line. - ga_init(&ga, 1, 100); - for (wordnr = 0; wordnr < wcount; ++wordnr) { - ga.ga_len = 0; - for (;; ) { - c = getc(fd); // <sugline> - if (c < 0) { - goto someerror; - } - GA_APPEND(char_u, &ga, c); - if (c == NUL) - break; - } - if (ml_append_buf(slang->sl_sugbuf, (linenr_T)wordnr, - ga.ga_data, ga.ga_len, TRUE) == FAIL) - goto someerror; - } - ga_clear(&ga); - - // 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); - -nextone: - if (fd != NULL) - fclose(fd); - STRCPY(dotp, ".spl"); - } - } -} - -// Fill in the wordcount fields for a trie. -// Returns the total number of words. -static void tree_count_words(char_u *byts, idx_T *idxs) -{ - int depth; - idx_T arridx[MAXWLEN]; - int curi[MAXWLEN]; - int c; - idx_T n; - int wordcount[MAXWLEN]; - - arridx[0] = 0; - curi[0] = 1; - wordcount[0] = 0; - depth = 0; - while (depth >= 0 && !got_int) { - if (curi[depth] > byts[arridx[depth]]) { - // Done all bytes at this node, go up one level. - idxs[arridx[depth]] = wordcount[depth]; - if (depth > 0) - wordcount[depth - 1] += wordcount[depth]; - - --depth; - fast_breakcheck(); - } else { - // Do one more byte at this node. - n = arridx[depth] + curi[depth]; - ++curi[depth]; - - c = byts[n]; - if (c == 0) { - // End of word, count it. - ++wordcount[depth]; - - // Skip over any other NUL bytes (same word with different - // flags). - while (byts[n + 1] == 0) { - ++n; - ++curi[depth]; - } - } else { - // Normal char, go one level deeper to count the words. - ++depth; - arridx[depth] = idxs[n]; - curi[depth] = 1; - wordcount[depth] = 0; - } - } - } -} - // Free the info put in "*su" by spell_find_suggest(). static void spell_find_cleanup(suginfo_T *su) { @@ -9219,32 +3376,33 @@ static void spell_find_cleanup(suginfo_T *su) hash_clear_all(&su->su_banned, 0); } -// Make a copy of "word", with the first letter upper or lower cased, to -// "wcopy[MAXWLEN]". "word" must not be empty. -// The result is NUL terminated. -static void -onecap_copy ( - char_u *word, - char_u *wcopy, - bool upper // true: first letter made upper case -) +/// Make a copy of "word", with the first letter upper or lower cased, to +/// "wcopy[MAXWLEN]". "word" must not be empty. +/// The result is NUL terminated. +/// +/// @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_u *wcopy, bool upper) { char_u *p; int c; int l; p = word; - if (has_mbyte) - c = mb_cptr2char_adv(&p); - else + if (has_mbyte) { + c = mb_cptr2char_adv((const char_u **)&p); + } else { c = *p++; - if (upper) + } + if (upper) { c = SPELL_TOUPPER(c); - else + } else { c = SPELL_TOFOLD(c); - if (has_mbyte) + } + if (has_mbyte) { l = mb_char2bytes(c, wcopy); - else { + } else { l = 1; wcopy[0] = c; } @@ -9261,10 +3419,11 @@ static void allcap_copy(char_u *word, char_u *wcopy) d = wcopy; for (s = word; *s != NUL; ) { - if (has_mbyte) - c = mb_cptr2char_adv(&s); - else + if (has_mbyte) { + c = mb_cptr2char_adv((const char_u **)&s); + } else { c = *s++; + } if (c == 0xdf) { c = 'S'; @@ -9474,7 +3633,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // word). depth = 0; sp = &stack[0]; - memset(sp, 0, sizeof(trystate_T)); + memset(sp, 0, sizeof(trystate_T)); // -V512 sp->ts_curi = 1; if (soundfold) { @@ -10330,7 +4489,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so } if (has_mbyte) { - n = mb_cptr2len(p); + n = MB_CPTR2LEN(p); c = mb_ptr2char(p); if (p[n] == NUL) c2 = NUL; @@ -10407,9 +4566,9 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // "fword" here, it's changed back afterwards at STATE_UNSWAP3. p = fword + sp->ts_fidx; if (has_mbyte) { - n = mb_cptr2len(p); + n = MB_CPTR2LEN(p); c = mb_ptr2char(p); - fl = mb_cptr2len(p + n); + fl = MB_CPTR2LEN(p + n); c2 = mb_ptr2char(p + n); if (!soundfold && !spell_iswordp(p + n + fl, curwin)) c3 = c; // don't swap non-word char @@ -10505,10 +4664,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so ++depth; p = fword + sp->ts_fidx; if (has_mbyte) { - n = mb_cptr2len(p); + n = MB_CPTR2LEN(p); c = mb_ptr2char(p); - fl = mb_cptr2len(p + n); - fl += mb_cptr2len(p + n + fl); + fl = MB_CPTR2LEN(p + n); + fl += MB_CPTR2LEN(p + n + fl); memmove(p, p + n, fl); mb_char2bytes(c, p + fl); stack[depth].ts_fidxtry = sp->ts_fidx + n + fl; @@ -10557,10 +4716,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so ++depth; p = fword + sp->ts_fidx; if (has_mbyte) { - n = mb_cptr2len(p); - n += mb_cptr2len(p + n); + n = MB_CPTR2LEN(p); + n += MB_CPTR2LEN(p + n); c = mb_ptr2char(p + n); - tl = mb_cptr2len(p + n); + tl = MB_CPTR2LEN(p + n); memmove(p + tl, p, n); mb_char2bytes(c, p); stack[depth].ts_fidxtry = sp->ts_fidx + n + tl; @@ -10803,10 +4962,11 @@ static void find_keepcap_word(slang_T *slang, char_u *fword, char_u *kword) // round[depth] == 1: Try using the folded-case character. // round[depth] == 2: Try using the upper-case character. if (has_mbyte) { - flen = mb_cptr2len(fword + fwordidx[depth]); - ulen = mb_cptr2len(uword + uwordidx[depth]); - } else + flen = MB_CPTR2LEN(fword + fwordidx[depth]); + ulen = MB_CPTR2LEN(uword + uwordidx[depth]); + } else { ulen = flen = 1; + } if (round[depth] == 1) { p = fword + fwordidx[depth]; l = flen; @@ -11177,11 +5337,13 @@ add_sound_suggest ( // the words that have a better score than before. Use a hashtable to // remember the words that have been done. hash = hash_hash(goodword); - hi = hash_lookup(&slang->sl_sounddone, goodword, hash); + 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) + STRLEN(goodword)); + sft = xmalloc(sizeof(sftword_T) + goodword_len); sft->sft_score = score; - STRCPY(sft->sft_word, goodword); + memcpy(sft->sft_word, goodword, goodword_len + 1); hash_add_item(&slang->sl_sounddone, hi, sft->sft_word, hash); } else { sft = HI2SFT(hi); @@ -11402,67 +5564,6 @@ static void make_case_word(char_u *fword, char_u *cword, int flags) STRCPY(cword, fword); } -// Use map string "map" for languages "lp". -static void set_map_str(slang_T *lp, char_u *map) -{ - char_u *p; - int headc = 0; - int c; - int i; - - if (*map == NUL) { - lp->sl_has_map = false; - return; - } - lp->sl_has_map = true; - - // Init the array and hash tables empty. - for (i = 0; i < 256; ++i) - lp->sl_map_array[i] = 0; - hash_init(&lp->sl_map_hash); - - // The similar characters are stored separated with slashes: - // "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(&p); - if (c == '/') - headc = 0; - else { - if (headc == 0) - headc = c; - - // Characters above 255 don't fit in sl_map_array[], put them in - // the hash table. Each entry is the char, a NUL the headchar and - // a NUL. - if (c >= 256) { - int cl = mb_char2len(c); - int headcl = mb_char2len(headc); - char_u *b; - hash_T hash; - hashitem_T *hi; - - b = xmalloc(cl + headcl + 2); - mb_char2bytes(c, b); - b[cl] = NUL; - mb_char2bytes(headc, b + cl + 1); - b[cl + 1 + headcl] = NUL; - hash = hash_hash(b); - hi = hash_lookup(&lp->sl_map_hash, b, hash); - if (HASHITEM_EMPTY(hi)) - hash_add_item(&lp->sl_map_hash, hi, b, hash); - else { - // This should have been checked when generating the .spl - // file. - EMSG(_("E783: duplicate char in MAP entry")); - xfree(b); - } - } else - lp->sl_map_array[c] = headc; - } - } -} - // Returns true if "c1" and "c2" are similar characters according to the MAP // lines in the .aff file. static bool similar_chars(slang_T *slang, int c1, int c2) @@ -11503,7 +5604,7 @@ static void add_suggestion ( suginfo_T *su, garray_T *gap, // either su_ga or su_sga - char_u *goodword, + const char_u *goodword, int badlenarg, // len of bad word replaced with "goodword" int score, int altscore, @@ -11517,13 +5618,11 @@ add_suggestion ( int badlen; // len of bad word changed suggest_T *stp; suggest_T new_sug; - int i; - char_u *pgood, *pbad; // Minimize "badlen" for consistency. Avoids that changing "the the" to // "thee the" is added next to changing the first "the" the "thee". - pgood = goodword + STRLEN(goodword); - pbad = su->su_badptr + badlenarg; + const char_u *pgood = goodword + STRLEN(goodword); + char_u *pbad = su->su_badptr + badlenarg; for (;; ) { goodlen = (int)(pgood - goodword); badlen = (int)(pbad - su->su_badptr); @@ -11543,9 +5642,10 @@ add_suggestion ( // the first "the" to itself. return; - if (GA_EMPTY(gap)) + int i; + if (GA_EMPTY(gap)) { i = -1; - else { + } else { // Check if the word is already there. Also check the length that is // being replaced "thes," -> "these" is a different suggestion from // "thes" -> "these". @@ -11656,9 +5756,10 @@ static void add_banned(suginfo_T *su, char_u *word) hashitem_T *hi; hash = hash_hash(word); - hi = hash_lookup(&su->su_banned, word, hash); + const size_t word_len = STRLEN(word); + hi = hash_lookup(&su->su_banned, (const char *)word, word_len, hash); if (HASHITEM_EMPTY(hi)) { - s = vim_strsave(word); + s = xmemdupz(word, word_len); hash_add_item(&su->su_banned, hi, s, hash); } } @@ -11743,46 +5844,49 @@ cleanup_suggestions ( return maxscore; } -// Soundfold a string, for soundfold(). -// Result is in allocated memory, NULL for an error. -char_u *eval_soundfold(char_u *word) +/// Soundfold a string, for soundfold() +/// +/// @param[in] word Word to soundfold. +/// +/// @return [allocated] soundfolded string or NULL in case of error. May return +/// copy of the input string if soundfolding is not +/// supported by any of the languages in &spellang. +char *eval_soundfold(const char *const word) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { - langp_T *lp; - char_u sound[MAXWLEN]; - if (curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) { // Use the sound-folding of the first language that supports it. - for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) { - lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); + for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; lpi++) { + langp_T *const lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); if (!GA_EMPTY(&lp->lp_slang->sl_sal)) { // soundfold the word - spell_soundfold(lp->lp_slang, word, false, sound); - return vim_strsave(sound); + char_u sound[MAXWLEN]; + spell_soundfold(lp->lp_slang, (char_u *)word, false, sound); + return xstrdup((const char *)sound); } } } // No language with sound folding, return word as-is. - return vim_strsave(word); + return xstrdup(word); } -// Turn "inword" into its sound-a-like equivalent in "res[MAXWLEN]". -// -// There are many ways to turn a word into a sound-a-like representation. The -// oldest is Soundex (1918!). A nice overview can be found in "Approximate -// swedish name matching - survey and test of different algorithms" by Klas -// Erikson. -// -// We support two methods: -// 1. SOFOFROM/SOFOTO do a simple character mapping. -// 2. SAL items define a more advanced sound-folding (and much slower). -static void -spell_soundfold ( - slang_T *slang, - char_u *inword, - bool folded, // "inword" is already case-folded - char_u *res -) +/// Turn "inword" into its sound-a-like equivalent in "res[MAXWLEN]". +/// +/// There are many ways to turn a word into a sound-a-like representation. The +/// oldest is Soundex (1918!). A nice overview can be found in "Approximate +/// swedish name matching - survey and test of different algorithms" by Klas +/// Erikson. +/// +/// We support two methods: +/// 1. SOFOFROM/SOFOTO do a simple character mapping. +/// 2. SAL items define a more advanced sound-folding (and much slower). +/// +/// @param[in] slang +/// @param[in] inword word to soundfold +/// @param[in] folded whether inword is already case-folded +/// @param[in,out] res destination for soundfolded word +void spell_soundfold(slang_T *slang, char_u *inword, bool folded, char_u *res) { char_u fword[MAXWLEN]; char_u *word; @@ -11821,12 +5925,12 @@ 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 (s = inword; *s != NUL; ) { - c = mb_cptr2char_adv(&s); - if (enc_utf8 ? utf_class(c) == 0 : ascii_iswhite(c)) + c = mb_cptr2char_adv((const char_u **)&s); + if (enc_utf8 ? utf_class(c) == 0 : ascii_iswhite(c)) { c = ' '; - else if (c < 256) + } else if (c < 256) { c = slang->sl_sal_first[c]; - else { + } else { ip = ((int **)slang->sl_sal.ga_data)[c & 0xff]; if (ip == NULL) // empty list, can't match c = NUL; @@ -12111,9 +6215,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res) int word[MAXWLEN]; int wres[MAXWLEN]; int l; - char_u *s; int *ws; - char_u *t; int *pf; int i, j, z; int reslen; @@ -12133,9 +6235,9 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res) // Remove accents, if wanted. We actually remove all non-word characters. // But keep white space. wordlen = 0; - for (s = inword; *s != NUL; ) { - t = s; - c = mb_cptr2char_adv(&s); + for (const char_u *s = inword; *s != NUL; ) { + const char_u *t = s; + c = mb_cptr2char_adv((const char_u **)&s); if (slang->sl_rem_accents) { if (enc_utf8 ? utf_class(c) == 0 : ascii_iswhite(c)) { if (did_white) @@ -12144,8 +6246,9 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res) did_white = true; } else { did_white = false; - if (!spell_iswordp_nmw(t, curwin)) + if (!spell_iswordp_nmw(t, curwin)) { continue; + } } } word[wordlen++] = c; @@ -12192,7 +6295,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res) continue; ++k; } - s = smp[n].sm_rules; + char_u *s = smp[n].sm_rules; pri = 5; // default priority p0 = *s; @@ -12591,25 +6694,30 @@ soundalike_score ( // support multi-byte characters. static int spell_edit_score(slang_T *slang, char_u *badword, char_u *goodword) { - int *cnt; - int badlen, goodlen; // lengths including NUL + int *cnt; int j, i; int t; int bc, gc; int pbc, pgc; - char_u *p; int wbadword[MAXWLEN]; int wgoodword[MAXWLEN]; const bool l_has_mbyte = has_mbyte; + // Lengths with NUL. + int badlen; + int goodlen; if (l_has_mbyte) { // Get the characters from the multi-byte strings and put them in an // int array for easy access. - for (p = badword, badlen = 0; *p != NUL; ) + badlen = 0; + for (const char_u *p = badword; *p != NUL; ) { wbadword[badlen++] = mb_cptr2char_adv(&p); + } wbadword[badlen++] = 0; - for (p = goodword, goodlen = 0; *p != NUL; ) + goodlen = 0; + for (const char_u *p = goodword; *p != NUL; ) { wgoodword[goodlen++] = mb_cptr2char_adv(&p); + } wgoodword[goodlen++] = 0; } else { badlen = (int)STRLEN(badword) + 1; @@ -12843,19 +6951,20 @@ static int spell_edit_score_limit_w(slang_T *slang, char_u *badword, char_u *goo int score_off; int minscore; int round; - char_u *p; int wbadword[MAXWLEN]; int wgoodword[MAXWLEN]; // Get the characters from the multi-byte strings and put them in an // int array for easy access. bi = 0; - for (p = badword; *p != NUL; ) + for (const char_u *p = badword; *p != NUL; ) { wbadword[bi++] = mb_cptr2char_adv(&p); + } wbadword[bi++] = 0; gi = 0; - for (p = goodword; *p != NUL; ) + for (const char_u *p = goodword; *p != NUL; ) { wgoodword[gi++] = mb_cptr2char_adv(&p); + } wgoodword[gi++] = 0; // The idea is to go from start to end over the words. So long as @@ -12990,19 +7099,17 @@ pop: // ":spellinfo" void ex_spellinfo(exarg_T *eap) { - langp_T *lp; - char_u *p; - - if (no_spell_checking(curwin)) + if (no_spell_checking(curwin)) { return; + } msg_start(); - for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len && !got_int; ++lpi) { - lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); - msg_puts((char_u *)"file: "); - msg_puts(lp->lp_slang->sl_fname); + for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len && !got_int; lpi++) { + langp_T *const lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); + msg_puts("file: "); + msg_puts((const char *)lp->lp_slang->sl_fname); msg_putchar('\n'); - p = lp->lp_slang->sl_info; + const char *const p = (const char *)lp->lp_slang->sl_info; if (p != NULL) { msg_puts(p); msg_putchar('\n'); @@ -13023,20 +7130,22 @@ void ex_spelldump(exarg_T *eap) char_u *spl; long dummy; - if (no_spell_checking(curwin)) + if (no_spell_checking(curwin)) { return; - get_option_value((char_u*)"spl", &dummy, &spl, OPT_LOCAL); + } + get_option_value((char_u *)"spl", &dummy, &spl, OPT_LOCAL); // Create a new empty buffer in a new window. do_cmdline_cmd("new"); // enable spelling locally in the new window - set_option_value((char_u*)"spell", true, (char_u*)"", OPT_LOCAL); - set_option_value((char_u*)"spl", dummy, spl, OPT_LOCAL); + set_option_value("spell", true, "", OPT_LOCAL); + set_option_value("spl", dummy, (char *)spl, OPT_LOCAL); xfree(spl); - if (!bufempty() || !buf_valid(curbuf)) + if (!bufempty()) { return; + } spell_dump_compl(NULL, 0, NULL, eap->forceit ? DUMPFLAG_COUNT : 0); diff --git a/src/nvim/spell.h b/src/nvim/spell.h index 3a03cb2ef6..ad66df4c5d 100644 --- a/src/nvim/spell.h +++ b/src/nvim/spell.h @@ -3,6 +3,10 @@ #include <stdbool.h> +#include "nvim/spell_defs.h" +#include "nvim/ex_cmds_defs.h" +#include "nvim/globals.h" + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "spell.h.generated.h" #endif diff --git a/src/nvim/spell_defs.h b/src/nvim/spell_defs.h new file mode 100644 index 0000000000..ddd54c724e --- /dev/null +++ b/src/nvim/spell_defs.h @@ -0,0 +1,287 @@ +#ifndef NVIM_SPELL_DEFS_H +#define NVIM_SPELL_DEFS_H + +#include <stdbool.h> +#include <stdint.h> + +#include "nvim/buffer_defs.h" +#include "nvim/garray.h" +#include "nvim/regexp_defs.h" +#include "nvim/types.h" + +#define MAXWLEN 254 // Assume max. word len is this many bytes. + // Some places assume a word length fits in a + // byte, thus it can't be above 255. + +// Type used for indexes in the word tree need to be at least 4 bytes. If int +// is 8 bytes we could use something smaller, but what? +typedef int idx_T; + +# define SPL_FNAME_TMPL "%s.%s.spl" +# define SPL_FNAME_ADD ".add." +# define SPL_FNAME_ASCII ".ascii." + +// Flags used for a word. Only the lowest byte can be used, the region byte +// comes above it. +#define WF_REGION 0x01 // region byte follows +#define WF_ONECAP 0x02 // word with one capital (or all capitals) +#define WF_ALLCAP 0x04 // word must be all capitals +#define WF_RARE 0x08 // rare word +#define WF_BANNED 0x10 // bad word +#define WF_AFX 0x20 // affix ID follows +#define WF_FIXCAP 0x40 // keep-case word, allcap not allowed +#define WF_KEEPCAP 0x80 // keep-case word + +// for <flags2>, shifted up one byte to be used in wn_flags +#define WF_HAS_AFF 0x0100 // word includes affix +#define WF_NEEDCOMP 0x0200 // word only valid in compound +#define WF_NOSUGGEST 0x0400 // word not to be suggested +#define WF_COMPROOT 0x0800 // already compounded word, COMPOUNDROOT +#define WF_NOCOMPBEF 0x1000 // no compounding before this word +#define WF_NOCOMPAFT 0x2000 // no compounding after this word + +// flags for <pflags> +#define WFP_RARE 0x01 // rare prefix +#define WFP_NC 0x02 // prefix is not combining +#define WFP_UP 0x04 // to-upper prefix +#define WFP_COMPPERMIT 0x08 // prefix with COMPOUNDPERMITFLAG +#define WFP_COMPFORBID 0x10 // prefix with COMPOUNDFORBIDFLAG + +// Flags for postponed prefixes in "sl_pidxs". Must be above affixID (one +// byte) and prefcondnr (two bytes). +#define WF_RAREPFX (WFP_RARE << 24) // rare postponed prefix +#define WF_PFX_NC (WFP_NC << 24) // non-combining postponed prefix +#define WF_PFX_UP (WFP_UP << 24) // to-upper postponed prefix +#define WF_PFX_COMPPERMIT (WFP_COMPPERMIT << 24) // postponed prefix with + // COMPOUNDPERMITFLAG +#define WF_PFX_COMPFORBID (WFP_COMPFORBID << 24) // postponed prefix with + // COMPOUNDFORBIDFLAG + + +// flags for <compoptions> +#define COMP_CHECKDUP 1 // CHECKCOMPOUNDDUP +#define COMP_CHECKREP 2 // CHECKCOMPOUNDREP +#define COMP_CHECKCASE 4 // CHECKCOMPOUNDCASE +#define COMP_CHECKTRIPLE 8 // CHECKCOMPOUNDTRIPLE + +// Info from "REP", "REPSAL" and "SAL" entries in ".aff" file used in si_rep, +// si_repsal, sl_rep, and si_sal. Not for sl_sal! +// One replacement: from "ft_from" to "ft_to". +typedef struct fromto_S { + char_u *ft_from; + char_u *ft_to; +} fromto_T; + +// Info from "SAL" entries in ".aff" file used in sl_sal. +// 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. + 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" +} salitem_T; + +typedef int salfirst_T; + +// Values for SP_*ERROR are negative, positive values are used by +// read_cnt_string(). +#define SP_TRUNCERROR -1 // spell file truncated error +#define SP_FORMERROR -2 // format error in spell file +#define SP_OTHERERROR -3 // other error while reading spell file + +// Structure used to store words and other info for one language, loaded from +// a .spl file. +// The main access is through the tree in "sl_fbyts/sl_fidxs", storing the +// case-folded words. "sl_kbyts/sl_kidxs" is for keep-case words. +// +// The "byts" array stores the possible bytes in each tree node, preceded by +// the number of possible bytes, sorted on byte value: +// <len> <byte1> <byte2> ... +// The "idxs" array stores the index of the child node corresponding to the +// byte in "byts". +// Exception: when the byte is zero, the word may end here and "idxs" holds +// the flags, region mask and affixID for the word. There may be several +// zeros in sequence for alternative flag/region/affixID combinations. +typedef struct slang_S slang_T; + +struct slang_S { + slang_T *sl_next; // next language + char_u *sl_name; // language name "en", "en.rare", "nl", etc. + char_u *sl_fname; // name of .spl file + bool sl_add; // true if it's a .add file. + + char_u *sl_fbyts; // case-folded word bytes + idx_T *sl_fidxs; // case-folded word indexes + char_u *sl_kbyts; // keep-case word bytes + idx_T *sl_kidxs; // keep-case word indexes + char_u *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[17]; // table with up to 8 region names plus NUL + + char_u *sl_midword; // MIDWORD string or NULL + + hashtab_T sl_wordcount; // hashtable with word count, wordcount_T + + int sl_compmax; // COMPOUNDWORDMAX (default: MAXWLEN) + int sl_compminlen; // COMPOUNDMIN (default: 0) + int sl_compsylmax; // COMPOUNDSYLMAX (default: MAXWLEN) + int sl_compoptions; // COMP_* flags + 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 + 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 + + int sl_prefixcnt; // number of items in "sl_prefprog" + regprog_T **sl_prefprog; // table with regprogs for prefixes + + garray_T sl_rep; // list of fromto_T entries from REP lines + int16_t sl_rep_first[256]; // indexes where byte first appears, -1 if + // there is none + garray_T sl_sal; // list of salitem_T entries from SAL lines + salfirst_T sl_sal_first[256]; // indexes where byte first appears, -1 if + // there is none + bool sl_followup; // SAL followup + bool sl_collapse; // SAL collapse_result + bool sl_rem_accents; // SAL remove_accents + bool sl_sofo; // SOFOFROM and SOFOTO instead of SAL items: + // "sl_sal_first" maps chars, when has_mbyte + // "sl_sal" is a list of wide char lists. + garray_T sl_repsal; // list of fromto_T entries from REPSAL lines + int16_t sl_repsal_first[256]; // sl_rep_first for REPSAL lines + bool sl_nosplitsugs; // don't suggest splitting a word + bool sl_nocompoundsugs; // don't suggest compounding + + // Info from the .sug file. Loaded on demand. + time_t sl_sugtime; // timestamp for .sug file + char_u *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 + // load + + bool sl_has_map; // true, if there is a MAP line + hashtab_T sl_map_hash; // MAP for multi-byte chars + int sl_map_array[256]; // MAP for first 256 chars + hashtab_T sl_sounddone; // table with soundfolded words that have + // handled, see add_sound_suggest() +}; + +// Structure used in "b_langp", filled from 'spelllang'. +typedef struct langp_S { + slang_T *lp_slang; // info for this language + slang_T *lp_sallang; // language used for sound folding or NULL + slang_T *lp_replang; // language used for REP items or NULL + int lp_region; // bitmask for region or REGION_ALL +} langp_T; + +#define LANGP_ENTRY(ga, i) (((langp_T *)(ga).ga_data) + (i)) + +#define VIMSUGMAGIC "VIMsug" // string at start of Vim .sug file +#define VIMSUGMAGICL 6 +#define VIMSUGVERSION 1 + +#define REGION_ALL 0xff // word valid in all regions + +// The tables used for recognizing word characters according to spelling. +// These are only used for the first 256 characters of 'encoding'. +typedef struct { + bool st_isw[256]; // flags: is word char + bool st_isu[256]; // flags: is uppercase char + char_u st_fold[256]; // chars: folded case + char_u st_upper[256]; // chars: upper case +} spelltab_T; + +// For finding suggestions: At each node in the tree these states are tried: +typedef enum { + STATE_START = 0, // At start of node check for NUL bytes (goodword + // ends); if badword ends there is a match, otherwise + // try splitting word. + STATE_NOPREFIX, // try without prefix + STATE_SPLITUNDO, // Undo splitting. + STATE_ENDNUL, // Past NUL bytes at start of the node. + STATE_PLAIN, // Use each byte of the node. + STATE_DEL, // Delete a byte from the bad word. + STATE_INS_PREP, // Prepare for inserting bytes. + STATE_INS, // Insert a byte in the bad word. + STATE_SWAP, // Swap two bytes. + STATE_UNSWAP, // Undo swap two characters. + STATE_SWAP3, // Swap two characters over three. + STATE_UNSWAP3, // Undo Swap two characters over three. + STATE_UNROT3L, // Undo rotate three characters left + STATE_UNROT3R, // Undo rotate three characters right + STATE_REP_INI, // Prepare for using REP items. + STATE_REP, // Use matching REP items from the .aff file. + STATE_REP_UNDO, // Undo a REP item replacement. + STATE_FINAL // End of this node. +} state_T; + +// Struct to keep the state at each level in suggest_try_change(). +typedef struct trystate_S { + state_T ts_state; // state at this level, STATE_ + int ts_score; // score + idx_T ts_arridx; // index in tree array, start of node + short ts_curi; // index in list of child nodes + char_u ts_fidx; // index in fword[], case-folded bad word + char_u ts_fidxtry; // ts_fidx at which bytes may be changed + char_u ts_twordlen; // valid length of tword[] + char_u ts_prefixdepth; // stack depth for end of prefix or + // PFD_PREFIXTREE or PFD_NOPREFIX + char_u ts_flags; // TSF_ flags + char_u ts_tcharlen; // number of bytes in tword character + char_u ts_tcharidx; // current byte index in tword character + char_u ts_isdiff; // DIFF_ values + char_u ts_fcharstart; // index in fword where badword char started + char_u ts_prewordlen; // length of word in "preword[]" + char_u ts_splitoff; // index in "tword" after last split + char_u ts_splitfidx; // "ts_fidx" at word split + char_u ts_complen; // nr of compound words used + char_u ts_compsplit; // index for "compflags" where word was spit + char_u ts_save_badflags; // su_badflags saved here + char_u ts_delidx; // index in fword for char that was deleted, + // valid when "ts_flags" has TSF_DIDDEL +} trystate_T; + +// Use our own character-case definitions, because the current locale may +// differ from what the .spl file uses. +// These must not be called with negative number! +#include <wchar.h> // for towupper() and towlower() +// Multi-byte implementation. For Unicode we can call utf_*(), but don't do +// that for ASCII, because we don't want to use 'casemap' here. Otherwise use +// the "w" library function for characters above 255. +#define SPELL_TOFOLD(c) (enc_utf8 && (c) >= 128 ? utf_fold(c) \ + : (c) < \ + 256 ? (int)spelltab.st_fold[c] : (int)towlower(c)) + +#define SPELL_TOUPPER(c) (enc_utf8 && (c) >= 128 ? mb_toupper(c) \ + : (c) < \ + 256 ? (int)spelltab.st_upper[c] : (int)towupper(c)) + +#define SPELL_ISUPPER(c) (enc_utf8 && (c) >= 128 ? mb_isupper(c) \ + : (c) < 256 ? spelltab.st_isu[c] : iswupper(c)) + +// First language that is loaded, start of the linked list of loaded +// languages. +extern slang_T *first_lang; + +// file used for "zG" and "zW" +extern char_u *int_wordlist; + +extern spelltab_T spelltab; +extern int did_set_spelltab; + +extern char *e_format; + +#endif // NVIM_SPELL_DEFS_H diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c new file mode 100644 index 0000000000..1f7f616782 --- /dev/null +++ b/src/nvim/spellfile.c @@ -0,0 +1,5741 @@ +// 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 + +// spellfile.c: code for reading and writing spell files. +// +// See spell.c for information about spell checking. + +// Vim spell file format: <HEADER> +// <SECTIONS> +// <LWORDTREE> +// <KWORDTREE> +// <PREFIXTREE> +// +// <HEADER>: <fileID> <versionnr> +// +// <fileID> 8 bytes "VIMspell" +// <versionnr> 1 byte VIMSPELLVERSION +// +// +// Sections make it possible to add information to the .spl file without +// making it incompatible with previous versions. There are two kinds of +// sections: +// 1. Not essential for correct spell checking. E.g. for making suggestions. +// These are skipped when not supported. +// 2. Optional information, but essential for spell checking when present. +// E.g. conditions for affixes. When this section is present but not +// supported an error message is given. +// +// <SECTIONS>: <section> ... <sectionend> +// +// <section>: <sectionID> <sectionflags> <sectionlen> (section contents) +// +// <sectionID> 1 byte number from 0 to 254 identifying the section +// +// <sectionflags> 1 byte SNF_REQUIRED: this section is required for correct +// spell checking +// +// <sectionlen> 4 bytes length of section contents, MSB first +// +// <sectionend> 1 byte SN_END +// +// +// sectionID == SN_INFO: <infotext> +// <infotext> N bytes free format text with spell file info (version, +// website, etc) +// +// sectionID == SN_REGION: <regionname> ... +// <regionname> 2 bytes Up to 8 region names: ca, au, etc. Lower case. +// First <regionname> is region 1. +// +// sectionID == SN_CHARFLAGS: <charflagslen> <charflags> +// <folcharslen> <folchars> +// <charflagslen> 1 byte Number of bytes in <charflags> (should be 128). +// <charflags> N bytes List of flags (first one is for character 128): +// 0x01 word character CF_WORD +// 0x02 upper-case character CF_UPPER +// <folcharslen> 2 bytes Number of bytes in <folchars>. +// <folchars> N bytes Folded characters, first one is for character 128. +// +// sectionID == SN_MIDWORD: <midword> +// <midword> N bytes Characters that are word characters only when used +// in the middle of a word. +// +// sectionID == SN_PREFCOND: <prefcondcnt> <prefcond> ... +// <prefcondcnt> 2 bytes Number of <prefcond> items following. +// <prefcond> : <condlen> <condstr> +// <condlen> 1 byte Length of <condstr>. +// <condstr> N bytes Condition for the prefix. +// +// sectionID == SN_REP: <repcount> <rep> ... +// <repcount> 2 bytes number of <rep> items, MSB first. +// <rep> : <repfromlen> <repfrom> <reptolen> <repto> +// <repfromlen> 1 byte length of <repfrom> +// <repfrom> N bytes "from" part of replacement +// <reptolen> 1 byte length of <repto> +// <repto> N bytes "to" part of replacement +// +// sectionID == SN_REPSAL: <repcount> <rep> ... +// just like SN_REP but for soundfolded words +// +// sectionID == SN_SAL: <salflags> <salcount> <sal> ... +// <salflags> 1 byte flags for soundsalike conversion: +// SAL_F0LLOWUP +// SAL_COLLAPSE +// SAL_REM_ACCENTS +// <salcount> 2 bytes number of <sal> items following +// <sal> : <salfromlen> <salfrom> <saltolen> <salto> +// <salfromlen> 1 byte length of <salfrom> +// <salfrom> N bytes "from" part of soundsalike +// <saltolen> 1 byte length of <salto> +// <salto> N bytes "to" part of soundsalike +// +// sectionID == SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto> +// <sofofromlen> 2 bytes length of <sofofrom> +// <sofofrom> N bytes "from" part of soundfold +// <sofotolen> 2 bytes length of <sofoto> +// <sofoto> N bytes "to" part of soundfold +// +// sectionID == SN_SUGFILE: <timestamp> +// <timestamp> 8 bytes time in seconds that must match with .sug file +// +// sectionID == SN_NOSPLITSUGS: nothing +// +// sectionID == SN_NOCOMPOUNDSUGS: nothing +// +// sectionID == SN_WORDS: <word> ... +// <word> N bytes NUL terminated common word +// +// sectionID == SN_MAP: <mapstr> +// <mapstr> N bytes String with sequences of similar characters, +// separated by slashes. +// +// sectionID == SN_COMPOUND: <compmax> <compminlen> <compsylmax> <compoptions> +// <comppatcount> <comppattern> ... <compflags> +// <compmax> 1 byte Maximum nr of words in compound word. +// <compminlen> 1 byte Minimal word length for compounding. +// <compsylmax> 1 byte Maximum nr of syllables in compound word. +// <compoptions> 2 bytes COMP_ flags. +// <comppatcount> 2 bytes number of <comppattern> following +// <compflags> N bytes Flags from COMPOUNDRULE items, separated by +// slashes. +// +// <comppattern>: <comppatlen> <comppattext> +// <comppatlen> 1 byte length of <comppattext> +// <comppattext> N bytes end or begin chars from CHECKCOMPOUNDPATTERN +// +// sectionID == SN_NOBREAK: (empty, its presence is what matters) +// +// sectionID == SN_SYLLABLE: <syllable> +// <syllable> N bytes String from SYLLABLE item. +// +// <LWORDTREE>: <wordtree> +// +// <KWORDTREE>: <wordtree> +// +// <PREFIXTREE>: <wordtree> +// +// +// <wordtree>: <nodecount> <nodedata> ... +// +// <nodecount> 4 bytes Number of nodes following. MSB first. +// +// <nodedata>: <siblingcount> <sibling> ... +// +// <siblingcount> 1 byte Number of siblings in this node. The siblings +// follow in sorted order. +// +// <sibling>: <byte> [ <nodeidx> <xbyte> +// | <flags> [<flags2>] [<region>] [<affixID>] +// | [<pflags>] <affixID> <prefcondnr> ] +// +// <byte> 1 byte Byte value of the sibling. Special cases: +// BY_NOFLAGS: End of word without flags and for all +// regions. +// For PREFIXTREE <affixID> and +// <prefcondnr> follow. +// BY_FLAGS: End of word, <flags> follow. +// For PREFIXTREE <pflags>, <affixID> +// and <prefcondnr> follow. +// BY_FLAGS2: End of word, <flags> and <flags2> +// follow. Not used in PREFIXTREE. +// BY_INDEX: Child of sibling is shared, <nodeidx> +// and <xbyte> follow. +// +// <nodeidx> 3 bytes Index of child for this sibling, MSB first. +// +// <xbyte> 1 byte Byte value of the sibling. +// +// <flags> 1 byte Bitmask of: +// WF_ALLCAP word must have only capitals +// WF_ONECAP first char of word must be capital +// WF_KEEPCAP keep-case word +// WF_FIXCAP keep-case word, all caps not allowed +// WF_RARE rare word +// WF_BANNED bad word +// WF_REGION <region> follows +// WF_AFX <affixID> follows +// +// <flags2> 1 byte Bitmask of: +// WF_HAS_AFF >> 8 word includes affix +// WF_NEEDCOMP >> 8 word only valid in compound +// WF_NOSUGGEST >> 8 word not used for suggestions +// WF_COMPROOT >> 8 word already a compound +// WF_NOCOMPBEF >> 8 no compounding before this word +// WF_NOCOMPAFT >> 8 no compounding after this word +// +// <pflags> 1 byte Bitmask of: +// WFP_RARE rare prefix +// WFP_NC non-combining prefix +// WFP_UP letter after prefix made upper case +// +// <region> 1 byte Bitmask for regions in which word is valid. When +// omitted it's valid in all regions. +// Lowest bit is for region 1. +// +// <affixID> 1 byte ID of affix that can be used with this word. In +// PREFIXTREE used for the required prefix ID. +// +// <prefcondnr> 2 bytes Prefix condition number, index in <prefcond> list +// from HEADER. +// +// All text characters are in 'encoding', but stored as single bytes. + +// Vim .sug file format: <SUGHEADER> +// <SUGWORDTREE> +// <SUGTABLE> +// +// <SUGHEADER>: <fileID> <versionnr> <timestamp> +// +// <fileID> 6 bytes "VIMsug" +// <versionnr> 1 byte VIMSUGVERSION +// <timestamp> 8 bytes timestamp that must match with .spl file +// +// +// <SUGWORDTREE>: <wordtree> (see above, no flags or region used) +// +// +// <SUGTABLE>: <sugwcount> <sugline> ... +// +// <sugwcount> 4 bytes number of <sugline> following +// +// <sugline>: <sugnr> ... NUL +// +// <sugnr>: X bytes word number that results in this soundfolded word, +// stored as an offset to the previous number in as +// few bytes as possible, see offset2bytes()) + +#include <stdio.h> +#include <stdint.h> +#include <wctype.h> +#include <strings.h> + +#include "nvim/vim.h" +#include "nvim/spell_defs.h" +#include "nvim/ascii.h" +#include "nvim/buffer.h" +#include "nvim/charset.h" +#include "nvim/ex_cmds2.h" +#include "nvim/fileio.h" +#include "nvim/memory.h" +#include "nvim/memline.h" +#include "nvim/misc1.h" +#include "nvim/option.h" +#include "nvim/os/os.h" +#include "nvim/path.h" +#include "nvim/regexp.h" +#include "nvim/screen.h" +#include "nvim/spell.h" +#include "nvim/spellfile.h" +#include "nvim/ui.h" +#include "nvim/undo.h" + +#ifndef UNIX // it's in os/unix_defs.h for Unix +# include <time.h> // for time_t +#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... +#define BY_NOFLAGS 0 // end of word without flags or region; for + // postponed prefix: no <pflags> +#define BY_INDEX 1 // child is shared, index follows +#define BY_FLAGS 2 // end of word, <flags> byte follows; for + // postponed prefix: <pflags> follows +#define BY_FLAGS2 3 // end of word, <flags> and <flags2> bytes + // follow; never used in prefix tree +#define BY_SPECIAL BY_FLAGS2 // highest special byte value + +// Flags used in .spl file for soundsalike flags. +#define SAL_F0LLOWUP 1 +#define SAL_COLLAPSE 2 +#define SAL_REM_ACCENTS 4 + +#define VIMSPELLMAGIC "VIMspell" // string at start of Vim spell file +#define VIMSPELLMAGICL (sizeof(VIMSPELLMAGIC) - 1) +#define VIMSPELLVERSION 50 + +// Section IDs. Only renumber them when VIMSPELLVERSION changes! +#define SN_REGION 0 // <regionname> section +#define SN_CHARFLAGS 1 // charflags section +#define SN_MIDWORD 2 // <midword> section +#define SN_PREFCOND 3 // <prefcond> section +#define SN_REP 4 // REP items section +#define SN_SAL 5 // SAL items section +#define SN_SOFO 6 // soundfolding section +#define SN_MAP 7 // MAP items section +#define SN_COMPOUND 8 // compound words section +#define SN_SYLLABLE 9 // syllable section +#define SN_NOBREAK 10 // NOBREAK section +#define SN_SUGFILE 11 // timestamp for .sug file +#define SN_REPSAL 12 // REPSAL items section +#define SN_WORDS 13 // common words +#define SN_NOSPLITSUGS 14 // don't split word for suggestions +#define SN_INFO 15 // info section +#define SN_NOCOMPOUNDSUGS 16 // don't compound for suggestions +#define SN_END 255 // end of sections + +#define SNF_REQUIRED 1 // <sectionflags>: required section + +#define CF_WORD 0x01 +#define CF_UPPER 0x02 + +static char *e_spell_trunc = N_("E758: Truncated spell file"); +static char *e_afftrailing = N_("Trailing text in %s line %d: %s"); +static char *e_affname = N_("Affix name too long in %s line %d: %s"); +static char *e_affform = N_("E761: Format error in affix file FOL, LOW or UPP"); +static char *e_affrange = N_( + "E762: Character in FOL, LOW or UPP is out of range"); +static char *msg_compressing = N_("Compressing word tree..."); + +#define MAXLINELEN 500 // Maximum length in bytes of a line in a .aff + // 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 + 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 + unsigned af_bad; // BAD ID for banned word + unsigned af_needaffix; // NEEDAFFIX ID + unsigned af_circumfix; // CIRCUMFIX ID + unsigned af_needcomp; // NEEDCOMPOUND ID + unsigned af_comproot; // COMPOUNDROOT ID + unsigned af_compforbid; // COMPOUNDFORBIDFLAG ID + unsigned af_comppermit; // COMPOUNDPERMITFLAG ID + unsigned af_nosuggest; // NOSUGGEST ID + int af_pfxpostpone; // postpone prefixes without chop string and + // without flags + bool af_ignoreextra; // IGNOREEXTRA present + hashtab_T af_pref; // hashtable for prefixes, affheader_T + hashtab_T af_suff; // hashtable for suffixes, affheader_T + hashtab_T af_comp; // hashtable for compound flags, compitem_T +} afffile_T; + +#define AFT_CHAR 0 // flags are one character +#define AFT_LONG 1 // flags are two characters +#define AFT_CAPLONG 2 // flags are one or two characters +#define AFT_NUM 3 // flags are numbers, comma separated + +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_u *ae_chop; // text to chop off basic word (can be NULL) + char_u *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 + char ae_compforbid; // COMPOUNDFORBIDFLAG found + char ae_comppermit; // COMPOUNDPERMITFLAG found +}; + +# define AH_KEY_LEN 17 // 2 x 8 bytes + NUL + +// Affix header from ".aff" file. Used for af_pref and af_suff. +typedef struct affheader_S { + char_u ah_key[AH_KEY_LEN]; // key for hashtab == name of affix + unsigned ah_flag; // affix name as number, uses "af_flagtype" + int ah_newID; // prefix ID after renumbering; 0 if not used + int ah_combine; // suffix may combine with prefix + int ah_follows; // another affix block should be following + affentry_T *ah_first; // first affix entry +} affheader_T; + +#define HI2AH(hi) ((affheader_T *)(hi)->hi_key) + +// Flag used in compound items. +typedef struct compitem_S { + char_u ci_key[AH_KEY_LEN]; // key for hashtab == name of compound + unsigned ci_flag; // affix name as number, uses "af_flagtype" + int ci_newID; // affix ID after renumbering. +} compitem_T; + +#define HI2CI(hi) ((compitem_T *)(hi)->hi_key) + +// Structure that is used to store the items in the word tree. This avoids +// the need to keep track of each allocated thing, everything is freed all at +// once after ":mkspell" is done. +// Note: "sb_next" must be just before "sb_data" to make sure the alignment of +// "sb_data" is correct for systems where pointers must be aligned on +// pointer-size boundaries and sizeof(pointer) > sizeof(int) (e.g., Sparc). +#define SBLOCKSIZE 16000 // size of sb_data +typedef struct sblock_S sblock_T; +struct sblock_S { + int sb_used; // nr of bytes already in use + sblock_T *sb_next; // next block in list + char_u sb_data[1]; // data, actually longer +}; + +// A node in the tree. +typedef struct wordnode_S wordnode_T; +struct wordnode_S { + union { // shared to save space + char_u hashkey[6]; // the hash key, only used while compressing + int index; // index in written nodes (valid after first + // round) + } wn_u1; + union { // shared to save space + wordnode_T *next; // next node with same hash key + wordnode_T *wnode; // parent node that will write this node + } wn_u2; + wordnode_T *wn_child; // child (next byte in word) + wordnode_T *wn_sibling; // next sibling (alternate byte in word, + // always sorted) + int wn_refs; // Nr. of references to this node. Only + // relevant for first node in a list of + // siblings, in following siblings it is + // always one. + char_u wn_byte; // Byte for this node. NUL for word end + + // Info for when "wn_byte" is NUL. + // In PREFIXTREE "wn_region" is used for the prefcondnr. + // In the soundfolded word tree "wn_flags" has the MSW of the wordnr and + // "wn_region" the LSW of the wordnr. + char_u wn_affixID; // supported/required prefix ID or 0 + uint16_t wn_flags; // WF_ flags + short wn_region; // region mask + +#ifdef SPELL_PRINTTREE + int wn_nr; // sequence nr for printing +#endif +}; + +#define WN_MASK 0xffff // mask relevant bits of "wn_flags" + +#define HI2WN(hi) (wordnode_T *)((hi)->hi_key) + +// Info used while reading the spell files. +typedef struct spellinfo_S { + wordnode_T *si_foldroot; // tree with case-folded words + long si_foldwcount; // nr of words in si_foldroot + + wordnode_T *si_keeproot; // tree with keep-case words + long si_keepwcount; // nr of words in si_keeproot + + wordnode_T *si_prefroot; // tree with postponed prefixes + + long si_sugtree; // creating the soundfolding trie + + sblock_T *si_blocks; // memory blocks used + long si_blocks_cnt; // memory blocks allocated + int si_did_emsg; // TRUE when ran out of memory + + long si_compress_cnt; // words to add before lowering + // compression limit + wordnode_T *si_first_free; // List of nodes that have been freed during + // compression, linked by "wn_child" field. + long si_free_count; // number of nodes in si_first_free +#ifdef SPELL_PRINTTREE + int si_wordnode_nr; // sequence nr for nodes +#endif + buf_T *si_spellbuf; // buffer used to store soundfold word table + + int si_ascii; // handling only ASCII words + int si_add; // addition file + int si_clear_chartab; // when TRUE clear char tables + int si_region; // region mask + vimconv_T si_conv; // for conversion to 'encoding' + int si_memtot; // runtime memory used + int si_verbose; // verbose messages + int si_msg_count; // number of words added since last message + char_u *si_info; // info text chars or NULL + int si_region_count; // number of regions supported (1 when there + // are no regions) + char_u si_region_name[17]; // region names; used only if + // si_region_count > 1) + + garray_T si_rep; // list of fromto_T entries from REP lines + garray_T si_repsal; // list of fromto_T entries from REPSAL lines + garray_T si_sal; // list of fromto_T entries from SAL lines + char_u *si_sofofr; // SOFOFROM text + char_u *si_sofoto; // SOFOTO text + int si_nosugfile; // NOSUGFILE item found + int si_nosplitsugs; // NOSPLITSUGS item found + int si_nocompoundsugs; // NOCOMPOUNDSUGS item found + int si_followup; // soundsalike: ? + int si_collapse; // soundsalike: ? + hashtab_T si_commonwords; // hashtable for common words + time_t si_sugtime; // timestamp for .sug file + int si_rem_accents; // soundsalike: remove accents + garray_T si_map; // MAP info concatenated + char_u *si_midword; // MIDWORD chars or NULL + int si_compmax; // max nr of words for compounding + int si_compminlen; // minimal length for compounding + int si_compsylmax; // max nr of syllables for compounding + int si_compoptions; // COMP_ flags + garray_T si_comppat; // CHECKCOMPOUNDPATTERN items, each stored as + // a string + char_u *si_compflags; // flags used for compounding + char_u si_nobreak; // NOBREAK + char_u *si_syllable; // syllable string + garray_T si_prefcond; // table with conditions for postponed + // prefixes, each stored as a string + int si_newprefID; // current value for ah_newID + int si_newcompID; // current value for compound ID +} spellinfo_T; + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "spellfile.c.generated.h" +#endif + +/// Read n bytes from fd to buf, returning on errors +/// +/// @param[out] buf Buffer to read to, must be at least n bytes long. +/// @param[in] n Amount of bytes to read. +/// @param fd FILE* to read from. +/// @param exit_code Code to run before returning. +/// +/// @return Allows to proceed if everything is OK, returns SP_TRUNCERROR if +/// there are not enough bytes, returns SP_OTHERERROR if reading failed. +#define SPELL_READ_BYTES(buf, n, fd, exit_code) \ + do { \ + const size_t n__SPRB = (n); \ + FILE *const fd__SPRB = (fd); \ + char *const buf__SPRB = (buf); \ + const size_t read_bytes__SPRB = fread(buf__SPRB, 1, n__SPRB, fd__SPRB); \ + if (read_bytes__SPRB != n__SPRB) { \ + exit_code; \ + return feof(fd__SPRB) ? SP_TRUNCERROR : SP_OTHERERROR; \ + } \ + } while (0) + +/// Like #SPELL_READ_BYTES, but also error out if NUL byte was read +/// +/// @return Allows to proceed if everything is OK, returns SP_TRUNCERROR if +/// there are not enough bytes, returns SP_OTHERERROR if reading failed, +/// returns SP_FORMERROR if read out a NUL byte. +#define SPELL_READ_NONNUL_BYTES(buf, n, fd, exit_code) \ + do { \ + const size_t n__SPRNB = (n); \ + FILE *const fd__SPRNB = (fd); \ + char *const buf__SPRNB = (buf); \ + SPELL_READ_BYTES(buf__SPRNB, n__SPRNB, fd__SPRNB, exit_code); \ + if (memchr(buf__SPRNB, NUL, (size_t)n__SPRNB)) { \ + exit_code; \ + return SP_FORMERROR; \ + } \ + } while (0) + +/// Check that spell file starts with a magic string +/// +/// Does not check for version of the file. +/// +/// @param fd File to check. +/// +/// @return 0 in case of success, SP_TRUNCERROR if file contains not enough +/// bytes, SP_FORMERROR if it does not match magic string and +/// SP_OTHERERROR if reading file failed. +static inline int spell_check_magic_string(FILE *const fd) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE +{ + char buf[VIMSPELLMAGICL]; + SPELL_READ_BYTES(buf, VIMSPELLMAGICL, fd, ;); + if (memcmp(buf, VIMSPELLMAGIC, VIMSPELLMAGICL) != 0) { + return SP_FORMERROR; + } + return 0; +} + +// Load one spell file and store the info into a slang_T. +// +// This is invoked in three ways: +// - From spell_load_cb() to load a spell file for the first time. "lang" is +// the language name, "old_lp" is NULL. Will allocate an slang_T. +// - To reload a spell file that was changed. "lang" is NULL and "old_lp" +// points to the existing slang_T. +// - Just after writing a .spl file; it's read back to produce the .sug file. +// "old_lp" is NULL and "lang" is NULL. Will allocate an slang_T. +// +// Returns the slang_T the spell file was loaded into. NULL for error. +slang_T * +spell_load_file ( + char_u *fname, + char_u *lang, + slang_T *old_lp, + bool silent // no error if file doesn't exist +) +{ + FILE *fd; + char_u *p; + int n; + int len; + char_u *save_sourcing_name = sourcing_name; + linenr_T save_sourcing_lnum = sourcing_lnum; + slang_T *lp = NULL; + int c = 0; + int res; + + fd = mch_fopen((char *)fname, "r"); + if (fd == NULL) { + if (!silent) + EMSG2(_(e_notopen), fname); + else if (p_verbose > 2) { + verbose_enter(); + smsg((char *)e_notopen, fname); + verbose_leave(); + } + goto endFAIL; + } + if (p_verbose > 2) { + verbose_enter(); + smsg(_("Reading spell file \"%s\""), fname); + verbose_leave(); + } + + if (old_lp == NULL) { + lp = slang_alloc(lang); + + // Remember the file name, used to reload the file when it's updated. + lp->sl_fname = vim_strsave(fname); + + // Check for .add.spl. + lp->sl_add = strstr((char *)path_tail(fname), SPL_FNAME_ADD) != NULL; + } else + lp = old_lp; + + // Set sourcing_name, so that error messages mention the file name. + sourcing_name = fname; + sourcing_lnum = 0; + + // <HEADER>: <fileID> + const int scms_ret = spell_check_magic_string(fd); + switch (scms_ret) { + case SP_FORMERROR: + case SP_TRUNCERROR: { + emsgf(_("E757: This does not look like a spell file")); + goto endFAIL; + } + case SP_OTHERERROR: { + emsgf(_("E5042: Failed to read spell file %s: %s"), + fname, strerror(ferror(fd))); + } + case 0: { + break; + } + } + c = getc(fd); // <versionnr> + if (c < VIMSPELLVERSION) { + EMSG(_("E771: Old spell file, needs to be updated")); + goto endFAIL; + } else if (c > VIMSPELLVERSION) { + EMSG(_("E772: Spell file is for newer version of Vim")); + goto endFAIL; + } + + + // <SECTIONS>: <section> ... <sectionend> + // <section>: <sectionID> <sectionflags> <sectionlen> (section contents) + for (;; ) { + n = getc(fd); // <sectionID> or <sectionend> + if (n == SN_END) + break; + c = getc(fd); // <sectionflags> + len = get4c(fd); // <sectionlen> + if (len < 0) + goto truncerr; + + res = 0; + switch (n) { + case SN_INFO: + lp->sl_info = READ_STRING(fd, len); // <infotext> + if (lp->sl_info == NULL) + goto endFAIL; + break; + + case SN_REGION: + res = read_region_section(fd, lp, len); + break; + + case SN_CHARFLAGS: + res = read_charflags_section(fd); + break; + + case SN_MIDWORD: + lp->sl_midword = READ_STRING(fd, len); // <midword> + if (lp->sl_midword == NULL) + goto endFAIL; + break; + + case SN_PREFCOND: + res = read_prefcond_section(fd, lp); + break; + + case SN_REP: + res = read_rep_section(fd, &lp->sl_rep, lp->sl_rep_first); + break; + + case SN_REPSAL: + res = read_rep_section(fd, &lp->sl_repsal, lp->sl_repsal_first); + break; + + case SN_SAL: + res = read_sal_section(fd, lp); + break; + + case SN_SOFO: + res = read_sofo_section(fd, lp); + break; + + case SN_MAP: + p = READ_STRING(fd, len); // <mapstr> + if (p == NULL) + goto endFAIL; + set_map_str(lp, p); + xfree(p); + break; + + case SN_WORDS: + res = read_words_section(fd, lp, len); + break; + + case SN_SUGFILE: + lp->sl_sugtime = get8ctime(fd); // <timestamp> + break; + + case SN_NOSPLITSUGS: + lp->sl_nosplitsugs = true; + break; + + case SN_NOCOMPOUNDSUGS: + lp->sl_nocompoundsugs = true; + break; + + case SN_COMPOUND: + res = read_compound(fd, lp, len); + break; + + case SN_NOBREAK: + lp->sl_nobreak = true; + break; + + case SN_SYLLABLE: + lp->sl_syllable = READ_STRING(fd, len); // <syllable> + if (lp->sl_syllable == NULL) + goto endFAIL; + if (init_syl_tab(lp) == FAIL) + goto endFAIL; + break; + + default: + // Unsupported section. When it's required give an error + // message. When it's not required skip the contents. + if (c & SNF_REQUIRED) { + EMSG(_("E770: Unsupported section in spell file")); + goto endFAIL; + } + while (--len >= 0) + if (getc(fd) < 0) + goto truncerr; + break; + } +someerror: + if (res == SP_FORMERROR) { + EMSG(_(e_format)); + goto endFAIL; + } + if (res == SP_TRUNCERROR) { +truncerr: + EMSG(_(e_spell_trunc)); + goto endFAIL; + } + if (res == SP_OTHERERROR) + goto endFAIL; + } + + // <LWORDTREE> + res = spell_read_tree(fd, &lp->sl_fbyts, &lp->sl_fidxs, false, 0); + if (res != 0) + goto someerror; + + // <KWORDTREE> + res = spell_read_tree(fd, &lp->sl_kbyts, &lp->sl_kidxs, false, 0); + if (res != 0) + goto someerror; + + // <PREFIXTREE> + res = spell_read_tree(fd, &lp->sl_pbyts, &lp->sl_pidxs, true, + lp->sl_prefixcnt); + if (res != 0) + goto someerror; + + // For a new file link it in the list of spell files. + if (old_lp == NULL && lang != NULL) { + lp->sl_next = first_lang; + first_lang = lp; + } + + goto endOK; + +endFAIL: + if (lang != NULL) + // truncating the name signals the error to spell_load_lang() + *lang = NUL; + if (lp != NULL && old_lp == NULL) + slang_free(lp); + lp = NULL; + +endOK: + if (fd != NULL) + fclose(fd); + sourcing_name = save_sourcing_name; + sourcing_lnum = save_sourcing_lnum; + + return lp; +} + +// Fill in the wordcount fields for a trie. +// Returns the total number of words. +static void tree_count_words(char_u *byts, idx_T *idxs) +{ + int depth; + idx_T arridx[MAXWLEN]; + int curi[MAXWLEN]; + int c; + idx_T n; + int wordcount[MAXWLEN]; + + arridx[0] = 0; + curi[0] = 1; + wordcount[0] = 0; + depth = 0; + while (depth >= 0 && !got_int) { + if (curi[depth] > byts[arridx[depth]]) { + // Done all bytes at this node, go up one level. + idxs[arridx[depth]] = wordcount[depth]; + if (depth > 0) + wordcount[depth - 1] += wordcount[depth]; + + --depth; + fast_breakcheck(); + } else { + // Do one more byte at this node. + n = arridx[depth] + curi[depth]; + ++curi[depth]; + + c = byts[n]; + if (c == 0) { + // End of word, count it. + ++wordcount[depth]; + + // Skip over any other NUL bytes (same word with different + // flags). + while (byts[n + 1] == 0) { + ++n; + ++curi[depth]; + } + } else { + // Normal char, go one level deeper to count the words. + ++depth; + arridx[depth] = idxs[n]; + curi[depth] = 1; + wordcount[depth] = 0; + } + } + } +} + +// Load the .sug files for languages that have one and weren't loaded yet. +void suggest_load_files(void) +{ + langp_T *lp; + slang_T *slang; + char_u *dotp; + FILE *fd; + char_u buf[MAXWLEN]; + int i; + time_t timestamp; + int wcount; + int wordnr; + garray_T ga; + int c; + + // Do this for all languages that support sound folding. + for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) { + lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); + slang = lp->lp_slang; + if (slang->sl_sugtime != 0 && !slang->sl_sugloaded) { + // Change ".spl" to ".sug" and open the file. When the file isn't + // found silently skip it. Do set "sl_sugloaded" so that we + // don't try again and again. + slang->sl_sugloaded = true; + + dotp = vim_strrchr(slang->sl_fname, '.'); + if (dotp == NULL || fnamecmp(dotp, ".spl") != 0) + continue; + STRCPY(dotp, ".sug"); + fd = mch_fopen((char *)slang->sl_fname, "r"); + if (fd == NULL) + goto nextone; + + // <SUGHEADER>: <fileID> <versionnr> <timestamp> + for (i = 0; i < VIMSUGMAGICL; ++i) + buf[i] = getc(fd); // <fileID> + if (STRNCMP(buf, VIMSUGMAGIC, VIMSUGMAGICL) != 0) { + EMSG2(_("E778: This does not look like a .sug file: %s"), + slang->sl_fname); + goto nextone; + } + c = getc(fd); // <versionnr> + if (c < VIMSUGVERSION) { + EMSG2(_("E779: Old .sug file, needs to be updated: %s"), + slang->sl_fname); + goto nextone; + } else if (c > VIMSUGVERSION) { + EMSG2(_("E780: .sug file is for newer version of Vim: %s"), + slang->sl_fname); + goto nextone; + } + + // Check the timestamp, it must be exactly the same as the one in + // the .spl file. Otherwise the word numbers won't match. + timestamp = get8ctime(fd); // <timestamp> + if (timestamp != slang->sl_sugtime) { + EMSG2(_("E781: .sug file doesn't match .spl file: %s"), + slang->sl_fname); + goto nextone; + } + + // <SUGWORDTREE>: <wordtree> + // Read the trie with the soundfolded words. + if (spell_read_tree(fd, &slang->sl_sbyts, &slang->sl_sidxs, + false, 0) != 0) { +someerror: + EMSG2(_("E782: error while reading .sug file: %s"), + slang->sl_fname); + slang_clear_sug(slang); + goto nextone; + } + + // <SUGTABLE>: <sugwcount> <sugline> ... + // + // Read the table with word numbers. We use a file buffer for + // this, because it's so much like a file with lines. Makes it + // possible to swap the info and save on memory use. + slang->sl_sugbuf = open_spellbuf(); + + // <sugwcount> + wcount = get4c(fd); + if (wcount < 0) + goto someerror; + + // Read all the wordnr lists into the buffer, one NUL terminated + // list per line. + ga_init(&ga, 1, 100); + for (wordnr = 0; wordnr < wcount; ++wordnr) { + ga.ga_len = 0; + for (;; ) { + c = getc(fd); // <sugline> + if (c < 0) { + goto someerror; + } + GA_APPEND(char_u, &ga, c); + if (c == NUL) + break; + } + if (ml_append_buf(slang->sl_sugbuf, (linenr_T)wordnr, + ga.ga_data, ga.ga_len, TRUE) == FAIL) + goto someerror; + } + ga_clear(&ga); + + // 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); + +nextone: + if (fd != NULL) + fclose(fd); + STRCPY(dotp, ".spl"); + } + } +} + + +// Read a length field from "fd" in "cnt_bytes" bytes. +// Allocate memory, read the string into it and add a NUL at the end. +// Returns NULL when the count is zero. +// Sets "*cntp" to SP_*ERROR when there is an error, length of the result +// otherwise. +static char_u *read_cnt_string(FILE *fd, int cnt_bytes, int *cntp) +{ + int cnt = 0; + int i; + char_u *str; + + // read the length bytes, MSB first + for (i = 0; i < cnt_bytes; ++i) + cnt = (cnt << 8) + getc(fd); + if (cnt < 0) { + *cntp = SP_TRUNCERROR; + return NULL; + } + *cntp = cnt; + if (cnt == 0) + return NULL; // nothing to read, return NULL + + str = READ_STRING(fd, cnt); + if (str == NULL) + *cntp = SP_OTHERERROR; + return str; +} + +// Read SN_REGION: <regionname> ... +// Return SP_*ERROR flags. +static int read_region_section(FILE *fd, slang_T *lp, int len) +{ + if (len > 16) { + return SP_FORMERROR; + } + SPELL_READ_NONNUL_BYTES((char *)lp->sl_regions, (size_t)len, fd, ;); + lp->sl_regions[len] = NUL; + return 0; +} + +// Read SN_CHARFLAGS section: <charflagslen> <charflags> +// <folcharslen> <folchars> +// Return SP_*ERROR flags. +static int read_charflags_section(FILE *fd) +{ + char_u *flags; + char_u *fol; + int flagslen, follen; + + // <charflagslen> <charflags> + flags = read_cnt_string(fd, 1, &flagslen); + if (flagslen < 0) + return flagslen; + + // <folcharslen> <folchars> + fol = read_cnt_string(fd, 2, &follen); + if (follen < 0) { + xfree(flags); + return follen; + } + + // Set the word-char flags and fill SPELL_ISUPPER() table. + if (flags != NULL && fol != NULL) + set_spell_charflags(flags, flagslen, fol); + + xfree(flags); + xfree(fol); + + // When <charflagslen> is zero then <fcharlen> must also be zero. + if ((flags == NULL) != (fol == NULL)) + return SP_FORMERROR; + return 0; +} + +// Read SN_PREFCOND section. +// Return SP_*ERROR flags. +static int read_prefcond_section(FILE *fd, slang_T *lp) +{ + // <prefcondcnt> <prefcond> ... + const int cnt = get2c(fd); // <prefcondcnt> + if (cnt <= 0) { + return SP_FORMERROR; + } + + lp->sl_prefprog = xcalloc(cnt, sizeof(regprog_T *)); + lp->sl_prefixcnt = cnt; + + for (int i = 0; i < cnt; i++) { + // <prefcond> : <condlen> <condstr> + const int n = getc(fd); // <condlen> + if (n < 0 || n >= MAXWLEN) { + return SP_FORMERROR; + } + + // When <condlen> is zero we have an empty condition. Otherwise + // compile the regexp program used to check for the condition. + if (n > 0) { + char buf[MAXWLEN + 1]; + buf[0] = '^'; // always match at one position only + SPELL_READ_NONNUL_BYTES(buf + 1, (size_t)n, fd, ;); + buf[n + 1] = NUL; + lp->sl_prefprog[i] = vim_regcomp((char_u *)buf, RE_MAGIC | RE_STRING); + } + } + return 0; +} + +// Read REP or REPSAL items section from "fd": <repcount> <rep> ... +// Return SP_*ERROR flags. +static int read_rep_section(FILE *fd, garray_T *gap, int16_t *first) +{ + int cnt; + fromto_T *ftp; + + cnt = get2c(fd); // <repcount> + if (cnt < 0) + return SP_TRUNCERROR; + + ga_grow(gap, cnt); + + // <rep> : <repfromlen> <repfrom> <reptolen> <repto> + for (; gap->ga_len < cnt; ++gap->ga_len) { + int c; + ftp = &((fromto_T *)gap->ga_data)[gap->ga_len]; + ftp->ft_from = read_cnt_string(fd, 1, &c); + if (c < 0) + return c; + if (c == 0) + return SP_FORMERROR; + ftp->ft_to = read_cnt_string(fd, 1, &c); + if (c <= 0) { + xfree(ftp->ft_from); + if (c < 0) + return c; + return SP_FORMERROR; + } + } + + // Fill the first-index table. + for (int i = 0; i < 256; ++i) { + first[i] = -1; + } + for (int i = 0; i < gap->ga_len; ++i) { + ftp = &((fromto_T *)gap->ga_data)[i]; + if (first[*ftp->ft_from] == -1) + first[*ftp->ft_from] = i; + } + return 0; +} + +// Read SN_SAL section: <salflags> <salcount> <sal> ... +// Return SP_*ERROR flags. +static int read_sal_section(FILE *fd, slang_T *slang) +{ + int cnt; + garray_T *gap; + salitem_T *smp; + int ccnt; + char_u *p; + int c = NUL; + + slang->sl_sofo = false; + + const int flags = getc(fd); // <salflags> + if (flags & SAL_F0LLOWUP) { + slang->sl_followup = true; + } + if (flags & SAL_COLLAPSE) { + slang->sl_collapse = true; + } + if (flags & SAL_REM_ACCENTS) { + slang->sl_rem_accents = true; + } + + cnt = get2c(fd); // <salcount> + if (cnt < 0) + return SP_TRUNCERROR; + + gap = &slang->sl_sal; + ga_init(gap, sizeof(salitem_T), 10); + ga_grow(gap, cnt + 1); + + // <sal> : <salfromlen> <salfrom> <saltolen> <salto> + for (; gap->ga_len < cnt; ++gap->ga_len) { + smp = &((salitem_T *)gap->ga_data)[gap->ga_len]; + ccnt = getc(fd); // <salfromlen> + if (ccnt < 0) + return SP_TRUNCERROR; + p = xmalloc(ccnt + 2); + smp->sm_lead = p; + + // Read up to the first special char into sm_lead. + int i = 0; + for (; i < ccnt; ++i) { + c = getc(fd); // <salfrom> + if (vim_strchr((char_u *)"0123456789(-<^$", c) != NULL) + break; + *p++ = c; + } + smp->sm_leadlen = (int)(p - smp->sm_lead); + *p++ = NUL; + + // Put (abc) chars in sm_oneof, if any. + if (c == '(') { + smp->sm_oneof = p; + for (++i; i < ccnt; ++i) { + c = getc(fd); // <salfrom> + if (c == ')') + break; + *p++ = c; + } + *p++ = NUL; + if (++i < ccnt) + c = getc(fd); + } else + smp->sm_oneof = NULL; + + // Any following chars go in sm_rules. + smp->sm_rules = p; + if (i < ccnt) { + // store the char we got while checking for end of sm_lead + *p++ = c; + } + i++; + if (i < ccnt) { + SPELL_READ_NONNUL_BYTES( // <salfrom> + (char *)p, (size_t)(ccnt - i), fd, xfree(smp->sm_lead)); + p += (ccnt - i); + i = ccnt; + } + *p++ = NUL; + + // <saltolen> <salto> + smp->sm_to = read_cnt_string(fd, 1, &ccnt); + if (ccnt < 0) { + xfree(smp->sm_lead); + return ccnt; + } + + if (has_mbyte) { + // convert the multi-byte strings to wide char strings + smp->sm_lead_w = mb_str2wide(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); + if (smp->sm_to == NULL) + smp->sm_to_w = NULL; + else + smp->sm_to_w = mb_str2wide(smp->sm_to); + } + } + + if (!GA_EMPTY(gap)) { + // Add one extra entry to mark the end with an empty sm_lead. Avoids + // that we need to check the index every time. + smp = &((salitem_T *)gap->ga_data)[gap->ga_len]; + p = xmalloc(1); + p[0] = NUL; + smp->sm_lead = p; + smp->sm_leadlen = 0; + smp->sm_oneof = NULL; + smp->sm_rules = p; + smp->sm_to = NULL; + if (has_mbyte) { + smp->sm_lead_w = mb_str2wide(smp->sm_lead); + smp->sm_leadlen = 0; + smp->sm_oneof_w = NULL; + smp->sm_to_w = NULL; + } + ++gap->ga_len; + } + + // Fill the first-index table. + set_sal_first(slang); + + return 0; +} + +// Read SN_WORDS: <word> ... +// Return SP_*ERROR flags. +static int read_words_section(FILE *fd, slang_T *lp, int len) +{ + int done = 0; + int i; + int c; + char_u word[MAXWLEN]; + + while (done < len) { + // Read one word at a time. + for (i = 0;; ++i) { + c = getc(fd); + if (c == EOF) + return SP_TRUNCERROR; + word[i] = c; + if (word[i] == NUL) + break; + if (i == MAXWLEN - 1) + return SP_FORMERROR; + } + + // Init the count to 10. + count_common_word(lp, word, -1, 10); + done += i + 1; + } + return 0; +} + +// SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto> +// Return SP_*ERROR flags. +static int read_sofo_section(FILE *fd, slang_T *slang) +{ + int cnt; + char_u *from, *to; + int res; + + slang->sl_sofo = true; + + // <sofofromlen> <sofofrom> + from = read_cnt_string(fd, 2, &cnt); + if (cnt < 0) + return cnt; + + // <sofotolen> <sofoto> + to = read_cnt_string(fd, 2, &cnt); + if (cnt < 0) { + xfree(from); + return cnt; + } + + // Store the info in slang->sl_sal and/or slang->sl_sal_first. + if (from != NULL && to != NULL) + res = set_sofo(slang, from, to); + else if (from != NULL || to != NULL) + res = SP_FORMERROR; // only one of two strings is an error + else + res = 0; + + xfree(from); + xfree(to); + return res; +} + +// Read the compound section from the .spl file: +// <compmax> <compminlen> <compsylmax> <compoptions> <compflags> +// Returns SP_*ERROR flags. +static int read_compound(FILE *fd, slang_T *slang, int len) +{ + int todo = len; + int c; + int atstart; + char_u *pat; + char_u *pp; + char_u *cp; + char_u *ap; + char_u *crp; + int cnt; + garray_T *gap; + + if (todo < 2) + return SP_FORMERROR; // need at least two bytes + + --todo; + c = getc(fd); // <compmax> + if (c < 2) + c = MAXWLEN; + slang->sl_compmax = c; + + --todo; + c = getc(fd); // <compminlen> + if (c < 1) + c = 0; + slang->sl_compminlen = c; + + --todo; + c = getc(fd); // <compsylmax> + if (c < 1) + c = MAXWLEN; + slang->sl_compsylmax = c; + + c = getc(fd); // <compoptions> + if (c != 0) + ungetc(c, fd); // be backwards compatible with Vim 7.0b + else { + --todo; + c = getc(fd); // only use the lower byte for now + --todo; + slang->sl_compoptions = c; + + gap = &slang->sl_comppat; + c = get2c(fd); // <comppatcount> + todo -= 2; + ga_init(gap, sizeof(char_u *), c); + ga_grow(gap, c); + while (--c >= 0) { + ((char_u **)(gap->ga_data))[gap->ga_len++] = + read_cnt_string(fd, 1, &cnt); + // <comppatlen> <comppattext> + if (cnt < 0) + return cnt; + todo -= cnt + 1; + } + } + if (todo < 0) + return SP_FORMERROR; + + // Turn the COMPOUNDRULE items into a regexp pattern: + // "a[bc]/a*b+" -> "^\(a[bc]\|a*b\+\)$". + // Inserting backslashes may double the length, "^\(\)$<Nul>" is 7 bytes. + // Conversion to utf-8 may double the size. + c = todo * 2 + 7; + if (enc_utf8) + c += todo * 2; + pat = xmalloc(c); + + // We also need a list of all flags that can appear at the start and one + // for all flags. + cp = xmalloc(todo + 1); + slang->sl_compstartflags = cp; + *cp = NUL; + + ap = xmalloc(todo + 1); + slang->sl_compallflags = ap; + *ap = NUL; + + // And a list of all patterns in their original form, for checking whether + // compounding may work in match_compoundrule(). This is freed when we + // encounter a wildcard, the check doesn't work then. + crp = xmalloc(todo + 1); + slang->sl_comprules = crp; + + pp = pat; + *pp++ = '^'; + *pp++ = '\\'; + *pp++ = '('; + + atstart = 1; + while (todo-- > 0) { + c = getc(fd); // <compflags> + if (c == EOF) { + xfree(pat); + return SP_TRUNCERROR; + } + + // Add all flags to "sl_compallflags". + if (vim_strchr((char_u *)"?*+[]/", c) == NULL + && !byte_in_str(slang->sl_compallflags, c)) { + *ap++ = c; + *ap = NUL; + } + + if (atstart != 0) { + // At start of item: copy flags to "sl_compstartflags". For a + // [abc] item set "atstart" to 2 and copy up to the ']'. + if (c == '[') + atstart = 2; + else if (c == ']') + atstart = 0; + else { + if (!byte_in_str(slang->sl_compstartflags, c)) { + *cp++ = c; + *cp = NUL; + } + if (atstart == 1) + atstart = 0; + } + } + + // Copy flag to "sl_comprules", unless we run into a wildcard. + if (crp != NULL) { + if (c == '?' || c == '+' || c == '*') { + xfree(slang->sl_comprules); + slang->sl_comprules = NULL; + crp = NULL; + } else + *crp++ = c; + } + + if (c == '/') { // slash separates two items + *pp++ = '\\'; + *pp++ = '|'; + atstart = 1; + } else { // normal char, "[abc]" and '*' are copied as-is + if (c == '?' || c == '+' || c == '~') + *pp++ = '\\'; // "a?" becomes "a\?", "a+" becomes "a\+" + if (enc_utf8) + pp += mb_char2bytes(c, pp); + else + *pp++ = c; + } + } + + *pp++ = '\\'; + *pp++ = ')'; + *pp++ = '$'; + *pp = NUL; + + if (crp != NULL) + *crp = NUL; + + slang->sl_compprog = vim_regcomp(pat, RE_MAGIC + RE_STRING + RE_STRICT); + xfree(pat); + if (slang->sl_compprog == NULL) + return SP_FORMERROR; + + return 0; +} + +// 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) +{ + int i; + + garray_T *gap; + char_u *s; + char_u *p; + int c; + int *inp; + + if (has_mbyte) { + // Use "sl_sal" as an array with 256 pointers to a list of wide + // characters. The index is the low byte of the character. + // The list contains from-to pairs with a terminating NUL. + // sl_sal_first[] is used for latin1 "from" characters. + gap = &lp->sl_sal; + ga_init(gap, sizeof(int *), 1); + ga_grow(gap, 256); + memset(gap->ga_data, 0, sizeof(int *) * 256); + gap->ga_len = 256; + + // 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; ) { + c = mb_cptr2char_adv((const char_u **)&p); + mb_cptr_adv(s); + if (c >= 256) + ++lp->sl_sal_first[c & 0xff]; + } + if (*p != NUL || *s != NUL) // lengths differ + return SP_FORMERROR; + + // Allocate the lists. + for (i = 0; i < 256; ++i) + if (lp->sl_sal_first[i] > 0) { + p = xmalloc(sizeof(int) * (lp->sl_sal_first[i] * 2 + 1)); + ((int **)gap->ga_data)[i] = (int *)p; + *(int *)p = 0; + } + + // Put the characters up to 255 in sl_sal_first[] the rest in a sl_sal + // list. + memset(lp->sl_sal_first, 0, sizeof(salfirst_T) * 256); + for (p = from, s = to; *p != NUL && *s != NUL; ) { + c = mb_cptr2char_adv((const char_u **)&p); + i = mb_cptr2char_adv((const char_u **)&s); + if (c >= 256) { + // Append the from-to chars at the end of the list with + // the low byte. + inp = ((int **)gap->ga_data)[c & 0xff]; + while (*inp != 0) + ++inp; + *inp++ = c; // from char + *inp++ = i; // to char + *inp++ = NUL; // NUL at the end + } else + // mapping byte to char is done in sl_sal_first[] + lp->sl_sal_first[c] = i; + } + } else { + // mapping bytes to bytes is done in sl_sal_first[] + if (STRLEN(from) != STRLEN(to)) + return SP_FORMERROR; + + for (i = 0; to[i] != NUL; ++i) + lp->sl_sal_first[from[i]] = to[i]; + lp->sl_sal.ga_len = 1; // indicates we have soundfolding + } + + return 0; +} + +// Fill the first-index table for "lp". +static void set_sal_first(slang_T *lp) +{ + salfirst_T *sfirst; + salitem_T *smp; + int c; + garray_T *gap = &lp->sl_sal; + + sfirst = lp->sl_sal_first; + for (int i = 0; i < 256; ++i) { + sfirst[i] = -1; + } + smp = (salitem_T *)gap->ga_data; + for (int i = 0; i < gap->ga_len; ++i) { + if (has_mbyte) + // Use the lowest byte of the first character. For latin1 it's + // the character, for other encodings it should differ for most + // characters. + c = *smp[i].sm_lead_w & 0xff; + else + c = *smp[i].sm_lead; + if (sfirst[c] == -1) { + sfirst[c] = i; + if (has_mbyte) { + int n; + + // Make sure all entries with this byte are following each + // other. Move the ones that are in the wrong position. Do + // keep the same ordering! + while (i + 1 < gap->ga_len + && (*smp[i + 1].sm_lead_w & 0xff) == c) + // Skip over entry with same index byte. + ++i; + + for (n = 1; i + n < gap->ga_len; ++n) + if ((*smp[i + n].sm_lead_w & 0xff) == c) { + salitem_T tsal; + + // Move entry with same index byte after the entries + // we already found. + ++i; + --n; + tsal = smp[i + n]; + memmove(smp + i + 1, smp + i, + sizeof(salitem_T) * n); + smp[i] = tsal; + } + } + } + } +} + +// Turn a multi-byte string into a wide character string. +// Return it in allocated memory. +static int *mb_str2wide(char_u *s) +{ + int i = 0; + + int *res = xmalloc((mb_charlen(s) + 1) * sizeof(int)); + for (char_u *p = s; *p != NUL; ) { + res[i++] = mb_ptr2char_adv((const char_u **)&p); + } + res[i] = NUL; + + return res; +} + +// Reads a tree from the .spl or .sug file. +// Allocates the memory and stores pointers in "bytsp" and "idxsp". +// This is skipped when the tree has zero length. +// Returns zero when OK, SP_ value for an error. +static int +spell_read_tree ( + FILE *fd, + char_u **bytsp, + idx_T **idxsp, + bool prefixtree, // true for the prefix tree + int prefixcnt // when "prefixtree" is true: prefix count +) +{ + int idx; + char_u *bp; + idx_T *ip; + + // The tree size was computed when writing the file, so that we can + // allocate it as one long block. <nodecount> + long len = get4c(fd); + if (len < 0) { + return SP_TRUNCERROR; + } + if ((size_t)len >= SIZE_MAX / sizeof(int)) { + // Invalid length, multiply with sizeof(int) would overflow. + return SP_FORMERROR; + } + if (len > 0) { + // Allocate the byte array. + bp = xmalloc(len); + *bytsp = bp; + + // Allocate the index array. + ip = xcalloc(len, sizeof(*ip)); + *idxsp = ip; + + // Recursively read the tree and store it in the array. + idx = read_tree_node(fd, bp, ip, len, 0, prefixtree, prefixcnt); + if (idx < 0) + return idx; + } + return 0; +} + +// Read one row of siblings from the spell file and store it in the byte array +// "byts" and index array "idxs". Recursively read the children. +// +// NOTE: The code here must match put_node()! +// +// Returns the index (>= 0) following the siblings. +// Returns SP_TRUNCERROR if the file is shorter than expected. +// Returns SP_FORMERROR if there is a format error. +static idx_T +read_tree_node ( + FILE *fd, + char_u *byts, + idx_T *idxs, + int maxidx, // size of arrays + idx_T startidx, // current index in "byts" and "idxs" + bool prefixtree, // true for reading PREFIXTREE + int maxprefcondnr // maximum for <prefcondnr> +) +{ + int len; + int i; + int n; + idx_T idx = startidx; + int c; + int c2; +#define SHARED_MASK 0x8000000 + + len = getc(fd); // <siblingcount> + if (len <= 0) + return SP_TRUNCERROR; + + if (startidx + len >= maxidx) + return SP_FORMERROR; + byts[idx++] = len; + + // Read the byte values, flag/region bytes and shared indexes. + for (i = 1; i <= len; ++i) { + c = getc(fd); // <byte> + if (c < 0) + return SP_TRUNCERROR; + if (c <= BY_SPECIAL) { + if (c == BY_NOFLAGS && !prefixtree) { + // No flags, all regions. + idxs[idx] = 0; + c = 0; + } else if (c != BY_INDEX) { + if (prefixtree) { + // Read the optional pflags byte, the prefix ID and the + // condition nr. In idxs[] store the prefix ID in the low + // byte, the condition index shifted up 8 bits, the flags + // shifted up 24 bits. + if (c == BY_FLAGS) + c = getc(fd) << 24; // <pflags> + else + c = 0; + + c |= getc(fd); // <affixID> + + n = get2c(fd); // <prefcondnr> + if (n >= maxprefcondnr) + return SP_FORMERROR; + c |= (n << 8); + } else { // c must be BY_FLAGS or BY_FLAGS2 + // Read flags and optional region and prefix ID. In + // idxs[] the flags go in the low two bytes, region above + // that and prefix ID above the region. + c2 = c; + c = getc(fd); // <flags> + if (c2 == BY_FLAGS2) + c = (getc(fd) << 8) + c; // <flags2> + if (c & WF_REGION) + c = (getc(fd) << 16) + c; // <region> + if (c & WF_AFX) + c = (getc(fd) << 24) + c; // <affixID> + } + + idxs[idx] = c; + c = 0; + } else { // c == BY_INDEX + // <nodeidx> + n = get3c(fd); + if (n < 0 || n >= maxidx) + return SP_FORMERROR; + idxs[idx] = n + SHARED_MASK; + c = getc(fd); // <xbyte> + } + } + byts[idx++] = c; + } + + // Recursively read the children for non-shared siblings. + // Skip the end-of-word ones (zero byte value) and the shared ones (and + // remove SHARED_MASK) + for (i = 1; i <= len; ++i) + if (byts[startidx + i] != 0) { + if (idxs[startidx + i] & SHARED_MASK) + idxs[startidx + i] &= ~SHARED_MASK; + else { + idxs[startidx + i] = idx; + idx = read_tree_node(fd, byts, idxs, maxidx, idx, + prefixtree, maxprefcondnr); + if (idx < 0) + break; + } + } + + return idx; +} + +// Reload the spell file "fname" if it's loaded. +static void +spell_reload_one ( + char_u *fname, + bool added_word // invoked through "zg" +) +{ + slang_T *slang; + bool didit = false; + + for (slang = first_lang; slang != NULL; slang = slang->sl_next) { + if (path_full_compare(fname, slang->sl_fname, FALSE) == kEqualFiles) { + slang_clear(slang); + if (spell_load_file(fname, NULL, slang, false) == NULL) + // reloading failed, clear the language + slang_clear(slang); + redraw_all_later(SOME_VALID); + didit = true; + } + } + + // When "zg" was used and the file wasn't loaded yet, should redo + // 'spelllang' to load it now. + if (added_word && !didit) + did_set_spelllang(curwin); +} + +// Functions for ":mkspell". + +// In the postponed prefixes tree wn_flags is used to store the WFP_ flags, +// but it must be negative to indicate the prefix tree to tree_add_word(). +// Use a negative number with the lower 8 bits zero. +#define PFX_FLAGS -256 + +// flags for "condit" argument of store_aff_word() +#define CONDIT_COMB 1 // affix must combine +#define CONDIT_CFIX 2 // affix must have CIRCUMFIX flag +#define CONDIT_SUF 4 // add a suffix for matching flags +#define CONDIT_AFF 8 // word already has an affix + +// Tunable parameters for when the tree is compressed. See 'mkspellmem'. +static long compress_start = 30000; // memory / SBLOCKSIZE +static long compress_inc = 100; // memory / SBLOCKSIZE +static long compress_added = 500000; // word count + +// Check the 'mkspellmem' option. Return FAIL if it's wrong. +// Sets "sps_flags". +int spell_check_msm(void) +{ + char_u *p = p_msm; + long start = 0; + long incr = 0; + long added = 0; + + if (!ascii_isdigit(*p)) + return FAIL; + // block count = (value * 1024) / SBLOCKSIZE (but avoid overflow) + start = (getdigits_long(&p) * 10) / (SBLOCKSIZE / 102); + if (*p != ',') + return FAIL; + ++p; + if (!ascii_isdigit(*p)) + return FAIL; + incr = (getdigits_long(&p) * 102) / (SBLOCKSIZE / 10); + if (*p != ',') + return FAIL; + ++p; + if (!ascii_isdigit(*p)) + return FAIL; + added = getdigits_long(&p) * 1024; + if (*p != NUL) + return FAIL; + + if (start == 0 || incr == 0 || added == 0 || incr > start) + return FAIL; + + compress_start = start; + compress_inc = incr; + compress_added = added; + return OK; +} + +#ifdef SPELL_PRINTTREE +// For debugging the tree code: print the current tree in a (more or less) +// readable format, so that we can see what happens when adding a word and/or +// compressing the tree. +// Based on code from Olaf Seibert. +#define PRINTLINESIZE 1000 +#define PRINTWIDTH 6 + +#define PRINTSOME(l, depth, fmt, a1, a2) vim_snprintf(l + depth * PRINTWIDTH, \ + PRINTLINESIZE - PRINTWIDTH * depth, fmt, a1, a2) + +static char line1[PRINTLINESIZE]; +static char line2[PRINTLINESIZE]; +static char line3[PRINTLINESIZE]; + +static void spell_clear_flags(wordnode_T *node) +{ + wordnode_T *np; + + for (np = node; np != NULL; np = np->wn_sibling) { + np->wn_u1.index = FALSE; + spell_clear_flags(np->wn_child); + } +} + +static void spell_print_node(wordnode_T *node, int depth) +{ + if (node->wn_u1.index) { + // Done this node before, print the reference. + PRINTSOME(line1, depth, "(%d)", node->wn_nr, 0); + PRINTSOME(line2, depth, " ", 0, 0); + PRINTSOME(line3, depth, " ", 0, 0); + msg((char_u *)line1); + msg((char_u *)line2); + msg((char_u *)line3); + } else { + node->wn_u1.index = TRUE; + + if (node->wn_byte != NUL) { + if (node->wn_child != NULL) + PRINTSOME(line1, depth, " %c -> ", node->wn_byte, 0); + else + // Cannot happen? + PRINTSOME(line1, depth, " %c ???", node->wn_byte, 0); + } else + PRINTSOME(line1, depth, " $ ", 0, 0); + + PRINTSOME(line2, depth, "%d/%d ", node->wn_nr, node->wn_refs); + + if (node->wn_sibling != NULL) + PRINTSOME(line3, depth, " | ", 0, 0); + else + PRINTSOME(line3, depth, " ", 0, 0); + + if (node->wn_byte == NUL) { + msg((char_u *)line1); + msg((char_u *)line2); + msg((char_u *)line3); + } + + // do the children + if (node->wn_byte != NUL && node->wn_child != NULL) + spell_print_node(node->wn_child, depth + 1); + + // do the siblings + if (node->wn_sibling != NULL) { + // get rid of all parent details except | + STRCPY(line1, line3); + STRCPY(line2, line3); + spell_print_node(node->wn_sibling, 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); + } +} + +#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) +{ + FILE *fd; + afffile_T *aff; + char_u rline[MAXLINELEN]; + char_u *line; + char_u *pc = NULL; +#define MAXITEMCNT 30 + char_u *(items[MAXITEMCNT]); + int itemcnt; + char_u *p; + int lnum = 0; + affheader_T *cur_aff = NULL; + bool did_postpone_prefix = false; + int aff_todo = 0; + hashtab_T *tp; + char_u *low = NULL; + char_u *fol = NULL; + char_u *upp = NULL; + int do_rep; + int do_repsal; + int do_sal; + int do_mapline; + bool found_map = false; + hashitem_T *hi; + int l; + int compminlen = 0; // COMPOUNDMIN value + int compsylmax = 0; // COMPOUNDSYLMAX value + int compoptions = 0; // COMP_ flags + int compmax = 0; // COMPOUNDWORDMAX value + char_u *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 + + // Open the file. + fd = mch_fopen((char *)fname, "r"); + if (fd == NULL) { + EMSG2(_(e_notopen), fname); + return NULL; + } + + vim_snprintf((char *)IObuff, IOSIZE, _("Reading affix file %s ..."), fname); + spell_message(spin, IObuff); + + // Only do REP lines when not done in another .aff file already. + do_rep = GA_EMPTY(&spin->si_rep); + + // Only do REPSAL lines when not done in another .aff file already. + do_repsal = GA_EMPTY(&spin->si_repsal); + + // Only do SAL lines when not done in another .aff file already. + do_sal = GA_EMPTY(&spin->si_sal); + + // Only do MAP lines when not done in another .aff file already. + do_mapline = GA_EMPTY(&spin->si_map); + + // Allocate and init the afffile_T structure. + aff = (afffile_T *)getroom(spin, sizeof(afffile_T), true); + if (aff == NULL) { + fclose(fd); + return NULL; + } + hash_init(&aff->af_pref); + hash_init(&aff->af_suff); + hash_init(&aff->af_comp); + + // Read all the lines in the file one by one. + while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int) { + line_breakcheck(); + ++lnum; + + // Skip comment lines. + if (*rline == '#') + continue; + + // Convert from "SET" to 'encoding' when needed. + xfree(pc); + if (spin->si_conv.vc_type != CONV_NONE) { + pc = string_convert(&spin->si_conv, rline, NULL); + if (pc == NULL) { + smsg(_("Conversion failure for word in %s line %d: %s"), + fname, lnum, rline); + continue; + } + line = pc; + } else { + pc = NULL; + line = rline; + } + + // Split the line up in white separated items. Put a NUL after each + // item. + itemcnt = 0; + for (p = line;; ) { + while (*p != NUL && *p <= ' ') // skip white space and CR/NL + ++p; + if (*p == NUL) + break; + if (itemcnt == MAXITEMCNT) // too many items + break; + items[itemcnt++] = p; + // A few items have arbitrary text argument, don't split them. + if (itemcnt == 2 && spell_info_item(items[0])) + while (*p >= ' ' || *p == TAB) // skip until CR/NL + ++p; + else + while (*p > ' ') // skip until white space or CR/NL + ++p; + if (*p == NUL) + break; + *p++ = NUL; + } + + // Handle non-empty lines. + 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 = enc_canonize(items[1]); + if (!spin->si_ascii + && 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); + spin->si_conv.vc_fail = true; + } else if (is_aff_rule(items, itemcnt, "FLAG", 2) + && aff->af_flagtype == AFT_CHAR) { + if (STRCMP(items[1], "long") == 0) + aff->af_flagtype = AFT_LONG; + else if (STRCMP(items[1], "num") == 0) + aff->af_flagtype = AFT_NUM; + else if (STRCMP(items[1], "caplong") == 0) + aff->af_flagtype = AFT_CAPLONG; + else + smsg(_("Invalid value for FLAG in %s line %d: %s"), + fname, lnum, items[1]); + if (aff->af_rare != 0 + || aff->af_keepcase != 0 + || aff->af_bad != 0 + || aff->af_needaffix != 0 + || aff->af_circumfix != 0 + || aff->af_needcomp != 0 + || aff->af_comproot != 0 + || aff->af_nosuggest != 0 + || compflags != NULL + || aff->af_suff.ht_used > 0 + || aff->af_pref.ht_used > 0) + smsg(_("FLAG after using flags in %s line %d: %s"), + fname, lnum, items[1]); + } else if (spell_info_item(items[0]) && itemcnt > 1) { + p = (char_u *)getroom(spin, + (spin->si_info == NULL ? 0 : STRLEN(spin->si_info)) + + STRLEN(items[0]) + + STRLEN(items[1]) + 3, false); + if (p != NULL) { + if (spin->si_info != NULL) { + STRCPY(p, spin->si_info); + STRCAT(p, "\n"); + } + STRCAT(p, items[0]); + STRCAT(p, " "); + STRCAT(p, items[1]); + spin->si_info = p; + } + } else if (is_aff_rule(items, itemcnt, "MIDWORD", 2) + && midword == NULL) { + 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 + } + // TODO: remove "RAR" later + else if ((is_aff_rule(items, itemcnt, "RAR", 2) + || is_aff_rule(items, itemcnt, "RARE", 2)) + && aff->af_rare == 0) { + aff->af_rare = affitem2flag(aff->af_flagtype, items[1], + fname, lnum); + } + // TODO: remove "KEP" later + else if ((is_aff_rule(items, itemcnt, "KEP", 2) + || is_aff_rule(items, itemcnt, "KEEPCASE", 2)) + && aff->af_keepcase == 0) { + 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, items[1], + fname, lnum); + } else if (is_aff_rule(items, itemcnt, "NEEDAFFIX", 2) + && aff->af_needaffix == 0) { + 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, items[1], + fname, lnum); + } else if (is_aff_rule(items, itemcnt, "NOSUGGEST", 2) + && aff->af_nosuggest == 0) { + 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, items[1], + fname, lnum); + } else if (is_aff_rule(items, itemcnt, "COMPOUNDROOT", 2) + && aff->af_comproot == 0) { + 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, 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, 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); + } else if (is_aff_rule(items, itemcnt, "COMPOUNDFLAG", 2) + && compflags == NULL) { + // Turn flag "c" into COMPOUNDRULE compatible string "c+", + // "Na" into "Na+", "1234" into "1234+". + p = getroom(spin, STRLEN(items[1]) + 2, false); + STRCPY(p, items[1]); + STRCAT(p, "+"); + compflags = p; + } else if (is_aff_rule(items, itemcnt, "COMPOUNDRULES", 2)) { + // We don't use the count, but do check that it's a number and + // not COMPOUNDRULE mistyped. + if (atoi((char *)items[1]) == 0) + smsg(_("Wrong COMPOUNDRULES value in %s line %d: %s"), + fname, lnum, items[1]); + } else if (is_aff_rule(items, itemcnt, "COMPOUNDRULE", 2)) { + // Don't use the first rule if it is a number. + if (compflags != NULL || *skipdigits(items[1]) != NUL) { + // Concatenate this string to previously defined ones, + // using a slash to separate them. + l = (int)STRLEN(items[1]) + 1; + if (compflags != NULL) + l += (int)STRLEN(compflags) + 1; + p = getroom(spin, l, false); + if (compflags != NULL) { + STRCPY(p, compflags); + STRCAT(p, "/"); + } + STRCAT(p, items[1]); + compflags = p; + } + } else if (is_aff_rule(items, itemcnt, "COMPOUNDWORDMAX", 2) + && compmax == 0) { + compmax = atoi((char *)items[1]); + if (compmax == 0) + smsg(_("Wrong COMPOUNDWORDMAX value in %s line %d: %s"), + fname, lnum, items[1]); + } else if (is_aff_rule(items, itemcnt, "COMPOUNDMIN", 2) + && compminlen == 0) { + compminlen = atoi((char *)items[1]); + if (compminlen == 0) + smsg(_("Wrong COMPOUNDMIN value in %s line %d: %s"), + fname, lnum, items[1]); + } else if (is_aff_rule(items, itemcnt, "COMPOUNDSYLMAX", 2) + && compsylmax == 0) { + compsylmax = atoi((char *)items[1]); + if (compsylmax == 0) + smsg(_("Wrong COMPOUNDSYLMAX value in %s line %d: %s"), + fname, lnum, items[1]); + } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDDUP", 1)) { + compoptions |= COMP_CHECKDUP; + } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDREP", 1)) { + compoptions |= COMP_CHECKREP; + } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDCASE", 1)) { + compoptions |= COMP_CHECKCASE; + } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDTRIPLE", 1)) { + compoptions |= COMP_CHECKTRIPLE; + } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 2)) { + if (atoi((char *)items[1]) == 0) + smsg(_("Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s"), + fname, lnum, items[1]); + } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 3)) { + garray_T *gap = &spin->si_comppat; + int i; + + // Only add the couple if it isn't already there. + for (i = 0; i < gap->ga_len - 1; i += 2) + if (STRCMP(((char_u **)(gap->ga_data))[i], items[1]) == 0 + && STRCMP(((char_u **)(gap->ga_data))[i + 1], + items[2]) == 0) + break; + if (i >= gap->ga_len) { + ga_grow(gap, 2); + ((char_u **)(gap->ga_data))[gap->ga_len++] + = getroom_save(spin, items[1]); + ((char_u **)(gap->ga_data))[gap->ga_len++] + = getroom_save(spin, items[2]); + } + } else if (is_aff_rule(items, itemcnt, "SYLLABLE", 2) + && syllable == NULL) { + 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)) { + spin->si_nosplitsugs = true; + } else if (is_aff_rule(items, itemcnt, "NOCOMPOUNDSUGS", 1)) { + spin->si_nocompoundsugs = true; + } else if (is_aff_rule(items, itemcnt, "NOSUGFILE", 1)) { + spin->si_nosugfile = true; + } else if (is_aff_rule(items, itemcnt, "PFXPOSTPONE", 1)) { + aff->af_pfxpostpone = true; + } else if (is_aff_rule(items, itemcnt, "IGNOREEXTRA", 1)) { + aff->af_ignoreextra = true; + } else if ((STRCMP(items[0], "PFX") == 0 + || STRCMP(items[0], "SFX") == 0) + && aff_todo == 0 + && itemcnt >= 4) { + int lasti = 4; + char_u key[AH_KEY_LEN]; + + if (*items[0] == 'P') + tp = &aff->af_pref; + else + tp = &aff->af_suff; + + // Myspell allows the same affix name to be used multiple + // times. The affix files that do this have an undocumented + // "S" flag on all but the last block, thus we check for that + // and store it in ah_follows. + STRLCPY(key, items[1], AH_KEY_LEN); + hi = hash_find(tp, key); + if (!HASHITEM_EMPTY(hi)) { + cur_aff = HI2AH(hi); + if (cur_aff->ah_combine != (*items[2] == 'Y')) + smsg(_("Different combining flag in continued affix block in %s line %d: %s"), + fname, lnum, items[1]); + if (!cur_aff->ah_follows) + smsg(_("Duplicate affix in %s line %d: %s"), + fname, lnum, items[1]); + } else { + // New affix letter. + cur_aff = (affheader_T *)getroom(spin, + sizeof(affheader_T), true); + if (cur_aff == NULL) + break; + 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; + if (cur_aff->ah_flag == aff->af_bad + || cur_aff->ah_flag == aff->af_rare + || cur_aff->ah_flag == aff->af_keepcase + || cur_aff->ah_flag == aff->af_needaffix + || cur_aff->ah_flag == aff->af_circumfix + || cur_aff->ah_flag == aff->af_nosuggest + || cur_aff->ah_flag == aff->af_needcomp + || cur_aff->ah_flag == aff->af_comproot) + smsg(_("Affix also used for " + "BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST" + "in %s line %d: %s"), + fname, lnum, items[1]); + STRCPY(cur_aff->ah_key, items[1]); + hash_add(tp, cur_aff->ah_key); + + cur_aff->ah_combine = (*items[2] == 'Y'); + } + + // Check for the "S" flag, which apparently means that another + // block with the same affix name is following. + if (itemcnt > lasti && STRCMP(items[lasti], "S") == 0) { + ++lasti; + cur_aff->ah_follows = true; + } else + cur_aff->ah_follows = false; + + // Myspell allows extra text after the item, but that might + // mean mistakes go unnoticed. Require a comment-starter, + // unless IGNOREEXTRA is used. Hunspell uses a "-" item. + if (itemcnt > lasti + && !aff->af_ignoreextra + && *items[lasti] != '#') + smsg(_(e_afftrailing), fname, lnum, items[lasti]); + + if (STRCMP(items[2], "Y") != 0 && STRCMP(items[2], "N") != 0) + smsg(_("Expected Y or N in %s line %d: %s"), + fname, lnum, items[2]); + + if (*items[0] == 'P' && aff->af_pfxpostpone) { + if (cur_aff->ah_newID == 0) { + // Use a new number in the .spl file later, to be able + // to handle multiple .aff files. + check_renumber(spin); + cur_aff->ah_newID = ++spin->si_newprefID; + + // We only really use ah_newID if the prefix is + // postponed. We know that only after handling all + // the items. + did_postpone_prefix = false; + } else + // Did use the ID in a previous block. + did_postpone_prefix = true; + } + + aff_todo = atoi((char *)items[3]); + } else if ((STRCMP(items[0], "PFX") == 0 + || STRCMP(items[0], "SFX") == 0) + && aff_todo > 0 + && STRCMP(cur_aff->ah_key, items[1]) == 0 + && itemcnt >= 5) { + affentry_T *aff_entry; + bool upper = false; + int lasti = 5; + + // Myspell allows extra text after the item, but that might + // mean mistakes go unnoticed. Require a comment-starter. + // Hunspell uses a "-" item. + if (itemcnt > lasti && *items[lasti] != '#' + && (STRCMP(items[lasti], "-") != 0 + || itemcnt != lasti + 1)) + smsg(_(e_afftrailing), fname, lnum, items[lasti]); + + // New item for an affix letter. + --aff_todo; + aff_entry = (affentry_T *)getroom(spin, + sizeof(affentry_T), true); + if (aff_entry == NULL) + break; + + if (STRCMP(items[2], "0") != 0) + aff_entry->ae_chop = getroom_save(spin, items[2]); + if (STRCMP(items[3], "0") != 0) { + aff_entry->ae_add = getroom_save(spin, items[3]); + + // Recognize flags on the affix: abcd/XYZ + 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); + } + } + + // Don't use an affix entry with non-ASCII characters when + // "spin->si_ascii" is true. + if (!spin->si_ascii || !(has_non_ascii(aff_entry->ae_chop) + || has_non_ascii(aff_entry->ae_add))) { + aff_entry->ae_next = cur_aff->ah_first; + cur_aff->ah_first = aff_entry; + + if (STRCMP(items[4], ".") != 0) { + char_u buf[MAXLINELEN]; + + aff_entry->ae_cond = getroom_save(spin, items[4]); + if (*items[0] == 'P') + sprintf((char *)buf, "^%s", items[4]); + else + sprintf((char *)buf, "%s$", items[4]); + 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]); + } + + // For postponed prefixes we need an entry in si_prefcond + // for the condition. Use an existing one if possible. + // Can't be done for an affix with flags, ignoring + // COMPOUNDFORBIDFLAG and COMPOUNDPERMITFLAG. + if (*items[0] == 'P' && aff->af_pfxpostpone + && aff_entry->ae_flags == NULL) { + // When the chop string is one lower-case letter and + // the add string ends in the upper-case letter we set + // the "upper" flag, clear "ae_chop" and remove the + // letters from "ae_add". The condition must either + // be empty or start with the same letter. + if (aff_entry->ae_chop != NULL + && aff_entry->ae_add != NULL + && aff_entry->ae_chop[(*mb_ptr2len)( + aff_entry->ae_chop)] == NUL + ) { + int c, c_up; + + c = PTR2CHAR(aff_entry->ae_chop); + c_up = SPELL_TOUPPER(c); + if (c_up != c + && (aff_entry->ae_cond == NULL + || 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 (PTR2CHAR(p) == c_up) { + upper = true; + aff_entry->ae_chop = NULL; + *p = NUL; + + // The condition is matched with the + // actual word, thus must check for the + // upper-case letter. + if (aff_entry->ae_cond != NULL) { + char_u buf[MAXLINELEN]; + if (has_mbyte) { + onecap_copy(items[4], buf, true); + aff_entry->ae_cond = getroom_save( + spin, buf); + } else + *aff_entry->ae_cond = c_up; + if (aff_entry->ae_cond != NULL) { + sprintf((char *)buf, "^%s", + aff_entry->ae_cond); + vim_regfree(aff_entry->ae_prog); + aff_entry->ae_prog = vim_regcomp( + buf, RE_MAGIC + RE_STRING); + } + } + } + } + } + + if (aff_entry->ae_chop == NULL) { + int idx; + char_u **pp; + int n; + + // Find a previously used condition. + for (idx = spin->si_prefcond.ga_len - 1; idx >= 0; + --idx) { + p = ((char_u **)spin->si_prefcond.ga_data)[idx]; + if (str_equal(p, aff_entry->ae_cond)) + break; + } + if (idx < 0) { + // Not found, add a new condition. + idx = spin->si_prefcond.ga_len; + pp = GA_APPEND_VIA_PTR(char_u *, &spin->si_prefcond); + *pp = (aff_entry->ae_cond == NULL) ? + NULL : getroom_save(spin, aff_entry->ae_cond); + } + + // Add the prefix to the prefix tree. + if (aff_entry->ae_add == NULL) + p = (char_u *)""; + else + p = aff_entry->ae_add; + + // PFX_FLAGS is a negative number, so that + // tree_add_word() knows this is the prefix tree. + n = PFX_FLAGS; + if (!cur_aff->ah_combine) + n |= WFP_NC; + if (upper) + n |= WFP_UP; + if (aff_entry->ae_comppermit) + n |= WFP_COMPPERMIT; + if (aff_entry->ae_compforbid) + n |= WFP_COMPFORBID; + tree_add_word(spin, p, spin->si_prefroot, n, + idx, cur_aff->ah_newID); + did_postpone_prefix = true; + } + + // Didn't actually use ah_newID, backup si_newprefID. + if (aff_todo == 0 && !did_postpone_prefix) { + --spin->si_newprefID; + cur_aff->ah_newID = 0; + } + } + } + } else if (is_aff_rule(items, itemcnt, "FOL", 2) && fol == NULL) { + fol = vim_strsave(items[1]); + } else if (is_aff_rule(items, itemcnt, "LOW", 2) && low == NULL) { + low = vim_strsave(items[1]); + } else if (is_aff_rule(items, itemcnt, "UPP", 2) && upp == NULL) { + upp = vim_strsave(items[1]); + } else if (is_aff_rule(items, itemcnt, "REP", 2) + || is_aff_rule(items, itemcnt, "REPSAL", 2)) { + /* Ignore REP/REPSAL count */; + if (!isdigit(*items[1])) + smsg(_("Expected REP(SAL) count in %s line %d"), + fname, lnum); + } else if ((STRCMP(items[0], "REP") == 0 + || STRCMP(items[0], "REPSAL") == 0) + && itemcnt >= 3) { + // REP/REPSAL item + // Myspell ignores extra arguments, we require it starts with + // # to detect mistakes. + if (itemcnt > 3 && items[3][0] != '#') + smsg(_(e_afftrailing), fname, lnum, items[3]); + if (items[0][3] == 'S' ? do_repsal : do_rep) { + // Replace underscore with space (can't include a space + // directly). + for (p = items[1]; *p != NUL; mb_ptr_adv(p)) + if (*p == '_') + *p = ' '; + for (p = items[2]; *p != NUL; mb_ptr_adv(p)) + if (*p == '_') + *p = ' '; + add_fromto(spin, items[0][3] == 'S' + ? &spin->si_repsal + : &spin->si_rep, items[1], items[2]); + } + } else if (is_aff_rule(items, itemcnt, "MAP", 2)) { + // MAP item or count + if (!found_map) { + // First line contains the count. + found_map = true; + if (!isdigit(*items[1])) + smsg(_("Expected MAP count in %s line %d"), + fname, lnum); + } else if (do_mapline) { + int c; + + // Check that every character appears only once. + for (p = items[1]; *p != NUL; ) { + c = mb_ptr2char_adv((const char_u **)&p); + if ((!GA_EMPTY(&spin->si_map) + && vim_strchr(spin->si_map.ga_data, c) + != NULL) + || vim_strchr(p, c) != NULL) { + smsg(_("Duplicate character in MAP in %s line %d"), + fname, lnum); + } + } + + // We simply concatenate all the MAP strings, separated by + // slashes. + ga_concat(&spin->si_map, items[1]); + ga_append(&spin->si_map, '/'); + } + } + // Accept "SAL from to" and "SAL from to #comment". + else if (is_aff_rule(items, itemcnt, "SAL", 3)) { + if (do_sal) { + // SAL item (sounds-a-like) + // Either one of the known keys or a from-to pair. + if (STRCMP(items[1], "followup") == 0) + spin->si_followup = sal_to_bool(items[2]); + else if (STRCMP(items[1], "collapse_result") == 0) + spin->si_collapse = sal_to_bool(items[2]); + else if (STRCMP(items[1], "remove_accents") == 0) + spin->si_rem_accents = sal_to_bool(items[2]); + else + // when "to" is "_" it means empty + add_fromto(spin, &spin->si_sal, items[1], + STRCMP(items[2], "_") == 0 ? (char_u *)"" + : items[2]); + } + } else if (is_aff_rule(items, itemcnt, "SOFOFROM", 2) + && sofofrom == NULL) { + sofofrom = getroom_save(spin, items[1]); + } else if (is_aff_rule(items, itemcnt, "SOFOTO", 2) + && sofoto == NULL) { + sofoto = getroom_save(spin, items[1]); + } else if (STRCMP(items[0], "COMMON") == 0) { + int i; + + for (i = 1; i < itemcnt; ++i) { + if (HASHITEM_EMPTY(hash_find(&spin->si_commonwords, + items[i]))) { + p = vim_strsave(items[i]); + hash_add(&spin->si_commonwords, p); + } + } + } else + smsg(_("Unrecognized or duplicate item in %s line %d: %s"), + fname, lnum, items[0]); + } + } + + if (fol != NULL || low != NULL || upp != NULL) { + if (spin->si_clear_chartab) { + // Clear the char type tables, don't want to use any of the + // currently used spell properties. + init_spell_chartab(); + spin->si_clear_chartab = false; + } + + // Don't write a word table for an ASCII file, so that we don't check + // for conflicts with a word table that matches 'encoding'. + // Don't write one for utf-8 either, we use utf_*() and + // mb_get_class(), the list of chars in the file will be incomplete. + if (!spin->si_ascii + && !enc_utf8 + ) { + if (fol == NULL || low == NULL || upp == NULL) + smsg(_("Missing FOL/LOW/UPP line in %s"), fname); + else + (void)set_spell_chartab(fol, low, upp); + } + + xfree(fol); + xfree(low); + xfree(upp); + } + + // Use compound specifications of the .aff file for the spell info. + if (compmax != 0) { + aff_check_number(spin->si_compmax, compmax, "COMPOUNDWORDMAX"); + spin->si_compmax = compmax; + } + + if (compminlen != 0) { + aff_check_number(spin->si_compminlen, compminlen, "COMPOUNDMIN"); + spin->si_compminlen = compminlen; + } + + if (compsylmax != 0) { + if (syllable == NULL) + smsg(_("COMPOUNDSYLMAX used without SYLLABLE")); + aff_check_number(spin->si_compsylmax, compsylmax, "COMPOUNDSYLMAX"); + spin->si_compsylmax = compsylmax; + } + + if (compoptions != 0) { + aff_check_number(spin->si_compoptions, compoptions, "COMPOUND options"); + spin->si_compoptions |= compoptions; + } + + if (compflags != NULL) + process_compflags(spin, aff, compflags); + + // Check that we didn't use too many renumbered flags. + if (spin->si_newcompID < spin->si_newprefID) { + if (spin->si_newcompID == 127 || spin->si_newcompID == 255) + MSG(_("Too many postponed prefixes")); + else if (spin->si_newprefID == 0 || spin->si_newprefID == 127) + MSG(_("Too many compound flags")); + else + MSG(_("Too many postponed prefixes and/or compound flags")); + } + + if (syllable != NULL) { + aff_check_string(spin->si_syllable, syllable, "SYLLABLE"); + spin->si_syllable = syllable; + } + + if (sofofrom != NULL || sofoto != NULL) { + if (sofofrom == NULL || sofoto == NULL) + smsg(_("Missing SOFO%s line in %s"), + sofofrom == NULL ? "FROM" : "TO", fname); + else if (!GA_EMPTY(&spin->si_sal)) + smsg(_("Both SAL and SOFO lines in %s"), fname); + else { + 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, midword, "MIDWORD"); + spin->si_midword = midword; + } + + xfree(pc); + fclose(fd); + return aff; +} + +// Returns true when items[0] equals "rulename", there are "mincount" items or +// a comment is following after item "mincount". +static bool is_aff_rule(char_u **items, int itemcnt, char *rulename, int mincount) +{ + return STRCMP(items[0], rulename) == 0 + && (itemcnt == mincount + || (itemcnt > mincount && items[mincount][0] == '#')); +} + +// For affix "entry" move COMPOUNDFORBIDFLAG and COMPOUNDPERMITFLAG from +// ae_flags to ae_comppermit and ae_compforbid. +static void aff_process_flags(afffile_T *affile, affentry_T *entry) +{ + char_u *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; + flag = get_affitem(affile->af_flagtype, &p); + if (flag == affile->af_comppermit || flag == affile->af_compforbid) { + STRMOVE(prevp, p); + p = prevp; + if (flag == affile->af_comppermit) + entry->ae_comppermit = true; + else + entry->ae_compforbid = true; + } + if (affile->af_flagtype == AFT_NUM && *p == ',') + ++p; + } + if (*entry->ae_flags == NUL) + entry->ae_flags = NULL; // nothing left + } +} + +// Returns true if "s" is the name of an info item in the affix file. +static bool spell_info_item(char_u *s) +{ + return STRCMP(s, "NAME") == 0 + || STRCMP(s, "HOME") == 0 + || STRCMP(s, "VERSION") == 0 + || STRCMP(s, "AUTHOR") == 0 + || STRCMP(s, "EMAIL") == 0 + || STRCMP(s, "COPYRIGHT") == 0; +} + +// 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) +{ + unsigned res; + char_u *p = item; + + res = get_affitem(flagtype, &p); + if (res == 0) { + if (flagtype == AFT_NUM) + smsg(_("Flag is not a number in %s line %d: %s"), + fname, lnum, item); + else + smsg(_("Illegal flag in %s line %d: %s"), + fname, lnum, item); + } + if (*p != NUL) { + smsg(_(e_affname), fname, lnum, item); + return 0; + } + + return res; +} + +// Get one affix name from "*pp" and advance the pointer. +// Returns zero for an error, still advances the pointer then. +static unsigned get_affitem(int flagtype, char_u **pp) +{ + int res; + + if (flagtype == AFT_NUM) { + if (!ascii_isdigit(**pp)) { + ++*pp; // always advance, avoid getting stuck + return 0; + } + res = getdigits_int(pp); + } else { + res = mb_ptr2char_adv((const char_u **)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); + } + } + return res; +} + +// Process the "compflags" string used in an affix file and append it to +// spin->si_compflags. +// The processing involves changing the affix names to ID numbers, so that +// they fit in one byte. +static void process_compflags(spellinfo_T *spin, afffile_T *aff, char_u *compflags) +{ + char_u *p; + char_u *prevp; + unsigned flag; + compitem_T *ci; + int id; + int len; + char_u *tp; + char_u key[AH_KEY_LEN]; + hashitem_T *hi; + + // Make room for the old and the new compflags, concatenated with a / in + // between. Processing it makes it shorter, but we don't know by how + // much, thus allocate the maximum. + len = (int)STRLEN(compflags) + 1; + if (spin->si_compflags != NULL) + len += (int)STRLEN(spin->si_compflags) + 1; + p = getroom(spin, len, false); + if (spin->si_compflags != NULL) { + STRCPY(p, spin->si_compflags); + STRCAT(p, "/"); + } + spin->si_compflags = p; + tp = p + STRLEN(p); + + for (p = compflags; *p != NUL; ) { + if (vim_strchr((char_u *)"/?*+[]", *p) != NULL) + // Copy non-flag characters directly. + *tp++ = *p++; + else { + // First get the flag number, also checks validity. + prevp = 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. + STRLCPY(key, prevp, p - prevp + 1); + hi = hash_find(&aff->af_comp, key); + if (!HASHITEM_EMPTY(hi)) + id = HI2CI(hi)->ci_newID; + else { + ci = (compitem_T *)getroom(spin, sizeof(compitem_T), true); + if (ci == NULL) + break; + STRCPY(ci->ci_key, key); + ci->ci_flag = flag; + // Avoid using a flag ID that has a special meaning in a + // regexp (also inside []). + do { + check_renumber(spin); + id = spin->si_newcompID--; + } while (vim_strchr((char_u *)"/?*+[]\\-^", id) != NULL); + ci->ci_newID = id; + hash_add(&aff->af_comp, ci->ci_key); + } + *tp++ = id; + } + if (aff->af_flagtype == AFT_NUM && *p == ',') + ++p; + } + } + + *tp = NUL; +} + +// Check that the new IDs for postponed affixes and compounding don't overrun +// each other. We have almost 255 available, but start at 0-127 to avoid +// using two bytes for utf-8. When the 0-127 range is used up go to 128-255. +// When that is used up an error message is given. +static void check_renumber(spellinfo_T *spin) +{ + if (spin->si_newprefID == spin->si_newcompID && spin->si_newcompID < 128) { + spin->si_newprefID = 127; + spin->si_newcompID = 255; + } +} + +// Returns true if flag "flag" appears in affix list "afflist". +static bool flag_in_afflist(int flagtype, char_u *afflist, unsigned flag) +{ + char_u *p; + unsigned n; + + switch (flagtype) { + case AFT_CHAR: + return vim_strchr(afflist, flag) != NULL; + + case AFT_CAPLONG: + case AFT_LONG: + for (p = afflist; *p != NUL; ) { + n = mb_ptr2char_adv((const char_u **)&p); + if ((flagtype == AFT_LONG || (n >= 'A' && n <= 'Z')) + && *p != NUL) { + n = mb_ptr2char_adv((const char_u **)&p) + (n << 16); + } + if (n == flag) { + return true; + } + } + break; + + case AFT_NUM: + for (p = afflist; *p != NUL; ) { + int digits = getdigits_int(&p); + assert(digits >= 0); + n = (unsigned int)digits; + if (n == flag) + return true; + if (*p != NUL) // skip over comma + ++p; + } + break; + } + return false; +} + +// Give a warning when "spinval" and "affval" numbers are set and not the same. +static void aff_check_number(int spinval, int affval, char *name) +{ + if (spinval != 0 && spinval != affval) + smsg(_("%s value differs from what is used in another .aff file"), + name); +} + +// Give a warning when "spinval" and "affval" strings are set and not the same. +static void aff_check_string(char_u *spinval, char_u *affval, char *name) +{ + if (spinval != NULL && STRCMP(spinval, affval) != 0) + smsg(_("%s value differs from what is used in another .aff file"), + name); +} + +// Returns true if strings "s1" and "s2" are equal. Also consider both being +// NULL as equal. +static bool str_equal(char_u *s1, char_u *s2) +{ + if (s1 == NULL || s2 == NULL) + return s1 == s2; + return STRCMP(s1, s2) == 0; +} + +// Add a from-to item to "gap". Used for REP and SAL items. +// They are stored case-folded. +static void add_fromto(spellinfo_T *spin, garray_T *gap, char_u *from, char_u *to) +{ + char_u word[MAXWLEN]; + + fromto_T *ftp = GA_APPEND_VIA_PTR(fromto_T, gap); + (void)spell_casefold(from, (int)STRLEN(from), word, MAXWLEN); + ftp->ft_from = getroom_save(spin, word); + (void)spell_casefold(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; +static bool sal_to_bool(char_u *s) +{ + return STRCMP(s, "1") == 0 || STRCMP(s, "true") == 0; +} + +// Free the structure filled by spell_read_aff(). +static void spell_free_aff(afffile_T *aff) +{ + hashtab_T *ht; + hashitem_T *hi; + int todo; + affheader_T *ah; + affentry_T *ae; + + xfree(aff->af_enc); + + // All this trouble to free the "ae_prog" items... + for (ht = &aff->af_pref;; ht = &aff->af_suff) { + todo = (int)ht->ht_used; + for (hi = ht->ht_array; todo > 0; ++hi) { + if (!HASHITEM_EMPTY(hi)) { + --todo; + ah = HI2AH(hi); + for (ae = ah->ah_first; ae != NULL; ae = ae->ae_next) + vim_regfree(ae->ae_prog); + } + } + if (ht == &aff->af_suff) + break; + } + + hash_clear(&aff->af_pref); + hash_clear(&aff->af_suff); + hash_clear(&aff->af_comp); +} + +// Read dictionary file "fname". +// Returns OK or FAIL; +static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile) +{ + hashtab_T ht; + char_u line[MAXLINELEN]; + char_u *p; + char_u *afflist; + char_u store_afflist[MAXWLEN]; + int pfxlen; + bool need_affix; + char_u *dw; + char_u *pc; + char_u *w; + int l; + hash_T hash; + hashitem_T *hi; + FILE *fd; + int lnum = 1; + int non_ascii = 0; + int retval = OK; + char_u message[MAXLINELEN + MAXWLEN]; + int flags; + int duplicate = 0; + + // Open the file. + fd = mch_fopen((char *)fname, "r"); + if (fd == NULL) { + EMSG2(_(e_notopen), fname); + return FAIL; + } + + // The hashtable is only used to detect duplicated words. + hash_init(&ht); + + vim_snprintf((char *)IObuff, IOSIZE, + _("Reading dictionary file %s ..."), fname); + spell_message(spin, IObuff); + + // start with a message for the first line + spin->si_msg_count = 999999; + + // Read and ignore the first line: word count. + (void)vim_fgets(line, MAXLINELEN, fd); + if (!ascii_isdigit(*skipwhite(line))) + EMSG2(_("E760: No word count in %s"), fname); + + // Read all the lines in the file one by one. + // The words are converted to 'encoding' here, before being added to + // the hashtable. + while (!vim_fgets(line, MAXLINELEN, fd) && !got_int) { + line_breakcheck(); + ++lnum; + if (line[0] == '#' || line[0] == '/') + continue; // comment line + + // Remove CR, LF and white space from the end. White space halfway through + // the word is kept to allow multi-word terms like "et al.". + l = (int)STRLEN(line); + while (l > 0 && line[l - 1] <= ' ') + --l; + if (l == 0) + continue; // empty line + line[l] = NUL; + + // Convert from "SET" to 'encoding' when needed. + if (spin->si_conv.vc_type != CONV_NONE) { + pc = string_convert(&spin->si_conv, line, NULL); + if (pc == NULL) { + smsg(_("Conversion failure for word in %s line %d: %s"), + fname, lnum, line); + continue; + } + w = pc; + } else { + pc = NULL; + w = line; + } + + // Truncate the word at the "/", set "afflist" to what follows. + // Replace "\/" by "/" and "\\" by "\". + afflist = NULL; + for (p = w; *p != NUL; mb_ptr_adv(p)) { + if (*p == '\\' && (p[1] == '\\' || p[1] == '/')) + STRMOVE(p, p + 1); + else if (*p == '/') { + *p = NUL; + afflist = p + 1; + break; + } + } + + // Skip non-ASCII words when "spin->si_ascii" is true. + if (spin->si_ascii && has_non_ascii(w)) { + ++non_ascii; + xfree(pc); + continue; + } + + // This takes time, print a message every 10000 words. + if (spin->si_verbose && spin->si_msg_count > 10000) { + spin->si_msg_count = 0; + vim_snprintf((char *)message, sizeof(message), + _("line %6d, word %6d - %s"), + lnum, spin->si_foldwcount + spin->si_keepwcount, w); + msg_start(); + msg_puts_long_attr(message, 0); + msg_clr_eos(); + msg_didout = FALSE; + msg_col = 0; + ui_flush(); + } + + // Store the word in the hashtable to be able to find duplicates. + dw = getroom_save(spin, w); + if (dw == NULL) { + retval = FAIL; + xfree(pc); + break; + } + + hash = hash_hash(dw); + hi = hash_lookup(&ht, (const char *)dw, STRLEN(dw), hash); + if (!HASHITEM_EMPTY(hi)) { + if (p_verbose > 0) + smsg(_("Duplicate word in %s line %d: %s"), + fname, lnum, dw); + else if (duplicate == 0) + smsg(_("First duplicate word in %s line %d: %s"), + fname, lnum, dw); + ++duplicate; + } else + hash_add_item(&ht, hi, dw, hash); + + flags = 0; + store_afflist[0] = NUL; + pfxlen = 0; + need_affix = false; + if (afflist != NULL) { + // Extract flags from the affix list. + flags |= get_affix_flags(affile, afflist); + + if (affile->af_needaffix != 0 && flag_in_afflist( + affile->af_flagtype, 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); + + 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); + } + + // Add the word to the word tree(s). + if (store_word(spin, dw, flags, spin->si_region, + 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, + &affile->af_suff, &affile->af_pref, + CONDIT_SUF, flags, store_afflist, pfxlen) == FAIL) + retval = FAIL; + + // Find all matching prefixes and add the resulting words. + if (store_aff_word(spin, dw, afflist, affile, + &affile->af_pref, NULL, + CONDIT_SUF, flags, store_afflist, pfxlen) == FAIL) + retval = FAIL; + } + + xfree(pc); + } + + if (duplicate > 0) + smsg(_("%d duplicate word(s) in %s"), duplicate, fname); + if (spin->si_ascii && non_ascii > 0) + smsg(_("Ignored %d word(s) with non-ASCII characters in %s"), + non_ascii, fname); + hash_clear(&ht); + + fclose(fd); + return retval; +} + +// 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) +{ + int flags = 0; + + if (affile->af_keepcase != 0 && flag_in_afflist( + affile->af_flagtype, afflist, affile->af_keepcase)) + flags |= WF_KEEPCAP | WF_FIXCAP; + if (affile->af_rare != 0 && flag_in_afflist( + affile->af_flagtype, afflist, affile->af_rare)) + flags |= WF_RARE; + if (affile->af_bad != 0 && flag_in_afflist( + affile->af_flagtype, afflist, affile->af_bad)) + flags |= WF_BANNED; + if (affile->af_needcomp != 0 && flag_in_afflist( + affile->af_flagtype, afflist, affile->af_needcomp)) + flags |= WF_NEEDCOMP; + if (affile->af_comproot != 0 && flag_in_afflist( + affile->af_flagtype, afflist, affile->af_comproot)) + flags |= WF_COMPROOT; + if (affile->af_nosuggest != 0 && flag_in_afflist( + affile->af_flagtype, afflist, affile->af_nosuggest)) + flags |= WF_NOSUGGEST; + return flags; +} + +// Get the list of prefix IDs from the affix list "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) +{ + char_u *p; + char_u *prevp; + int cnt = 0; + int id; + char_u key[AH_KEY_LEN]; + hashitem_T *hi; + + for (p = afflist; *p != NUL; ) { + prevp = p; + if (get_affitem(affile->af_flagtype, &p) != 0) { + // A flag is a postponed prefix flag if it appears in "af_pref" + // and it's ID is not zero. + STRLCPY(key, prevp, p - prevp + 1); + hi = hash_find(&affile->af_pref, key); + if (!HASHITEM_EMPTY(hi)) { + id = HI2AH(hi)->ah_newID; + if (id != 0) + store_afflist[cnt++] = id; + } + } + if (affile->af_flagtype == AFT_NUM && *p == ',') + ++p; + } + + store_afflist[cnt] = NUL; + return cnt; +} + +// 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) +{ + char_u *p; + char_u *prevp; + int cnt = 0; + char_u key[AH_KEY_LEN]; + hashitem_T *hi; + + for (p = afflist; *p != NUL; ) { + prevp = p; + if (get_affitem(affile->af_flagtype, &p) != 0) { + // A flag is a compound flag if it appears in "af_comp". + STRLCPY(key, prevp, p - prevp + 1); + hi = hash_find(&affile->af_comp, key); + if (!HASHITEM_EMPTY(hi)) + store_afflist[cnt++] = HI2CI(hi)->ci_newID; + } + if (affile->af_flagtype == AFT_NUM && *p == ',') + ++p; + } + + store_afflist[cnt] = NUL; +} + +// Apply affixes to a word and store the resulting words. +// "ht" is the hashtable with affentry_T that need to be applied, either +// prefixes or suffixes. +// "xht", when not NULL, is the prefix hashtable, to be used additionally on +// the resulting words for combining affixes. +// +// Returns FAIL when out of memory. +static int +store_aff_word ( + spellinfo_T *spin, // spell info + char_u *word, // basic word start + char_u *afflist, // list of names of supported affixes + afffile_T *affile, + hashtab_T *ht, + hashtab_T *xht, + int condit, // CONDIT_SUF et al. + int flags, // flags for the word + char_u *pfxlist, // list of prefix IDs + int pfxlen // nr of flags in "pfxlist" for prefixes, rest + // is compound flags +) +{ + int todo; + hashitem_T *hi; + affheader_T *ah; + affentry_T *ae; + char_u newword[MAXWLEN]; + int retval = OK; + int i, j; + char_u *p; + int use_flags; + char_u *use_pfxlist; + int use_pfxlen; + bool need_affix; + char_u store_afflist[MAXWLEN]; + char_u pfx_pfxlist[MAXWLEN]; + size_t wordlen = STRLEN(word); + int use_condit; + + todo = (int)ht->ht_used; + for (hi = ht->ht_array; todo > 0 && retval == OK; ++hi) { + if (!HASHITEM_EMPTY(hi)) { + --todo; + ah = HI2AH(hi); + + // Check that the affix combines, if required, and that the word + // supports this affix. + if (((condit & CONDIT_COMB) == 0 || ah->ah_combine) + && flag_in_afflist(affile->af_flagtype, afflist, + ah->ah_flag)) { + // Loop over all affix entries with this name. + for (ae = ah->ah_first; ae != NULL; ae = ae->ae_next) { + // Check the condition. It's not logical to match case + // here, but it is required for compatibility with + // Myspell. + // Another requirement from Myspell is that the chop + // string is shorter than the word itself. + // For prefixes, when "PFXPOSTPONE" was used, only do + // prefixes with a chop string and/or flags. + // When a previously added affix had CIRCUMFIX this one + // must have it too, if it had not then this one must not + // have one either. + if ((xht != NULL || !affile->af_pfxpostpone + || ae->ae_chop != NULL + || ae->ae_flags != NULL) + && (ae->ae_chop == NULL + || STRLEN(ae->ae_chop) < wordlen) + && (ae->ae_prog == NULL + || vim_regexec_prog(&ae->ae_prog, false, word, (colnr_T)0)) + && (((condit & CONDIT_CFIX) == 0) + == ((condit & CONDIT_AFF) == 0 + || ae->ae_flags == NULL + || !flag_in_afflist(affile->af_flagtype, + ae->ae_flags, affile->af_circumfix)))) { + // Match. Remove the chop and add the affix. + if (xht == NULL) { + // prefix: chop/add at the start of the word + if (ae->ae_add == NULL) + *newword = NUL; + else + STRLCPY(newword, ae->ae_add, MAXWLEN); + p = word; + if (ae->ae_chop != NULL) { + // Skip chop string. + if (has_mbyte) { + i = mb_charlen(ae->ae_chop); + for (; i > 0; --i) + mb_ptr_adv(p); + } else + p += STRLEN(ae->ae_chop); + } + STRCAT(newword, p); + } else { + // suffix: chop/add at the end of the word + STRLCPY(newword, word, MAXWLEN); + if (ae->ae_chop != NULL) { + // Remove chop string. + p = newword + STRLEN(newword); + i = (int)MB_CHARLEN(ae->ae_chop); + for (; i > 0; --i) + mb_ptr_back(newword, p); + *p = NUL; + } + if (ae->ae_add != NULL) + STRCAT(newword, ae->ae_add); + } + + use_flags = flags; + use_pfxlist = pfxlist; + use_pfxlen = pfxlen; + need_affix = false; + use_condit = condit | CONDIT_COMB | CONDIT_AFF; + if (ae->ae_flags != NULL) { + // 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)) + 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)) { + use_condit |= CONDIT_CFIX; + if ((condit & CONDIT_CFIX) == 0) + need_affix = true; + } + + if (affile->af_pfxpostpone + || 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); + else + use_pfxlen = 0; + use_pfxlist = store_afflist; + + // Combine the prefix IDs. Avoid adding the + // same ID twice. + for (i = 0; i < pfxlen; ++i) { + for (j = 0; j < use_pfxlen; ++j) + if (pfxlist[i] == use_pfxlist[j]) + break; + if (j == use_pfxlen) + use_pfxlist[use_pfxlen++] = pfxlist[i]; + } + + if (spin->si_compflags != NULL) + // Get compound IDS from the affix list. + get_compflags(affile, ae->ae_flags, + use_pfxlist + use_pfxlen); + else + use_pfxlist[use_pfxlen] = NUL; + + // Combine the list of compound flags. + // Concatenate them to the prefix IDs list. + // Avoid adding the same ID twice. + for (i = pfxlen; pfxlist[i] != NUL; ++i) { + for (j = use_pfxlen; + use_pfxlist[j] != NUL; ++j) + if (pfxlist[i] == use_pfxlist[j]) + break; + if (use_pfxlist[j] == NUL) { + use_pfxlist[j++] = pfxlist[i]; + use_pfxlist[j] = NUL; + } + } + } + } + + // Obey a "COMPOUNDFORBIDFLAG" of the affix: don't + // use the compound flags. + if (use_pfxlist != NULL && ae->ae_compforbid) { + STRLCPY(pfx_pfxlist, use_pfxlist, use_pfxlen + 1); + use_pfxlist = pfx_pfxlist; + } + + // When there are postponed prefixes... + if (spin->si_prefroot != NULL + && spin->si_prefroot->wn_sibling != NULL) { + // ... add a flag to indicate an affix was used. + use_flags |= WF_HAS_AFF; + + // ... don't use a prefix list if combining + // affixes is not allowed. But do use the + // compound flags after them. + if (!ah->ah_combine && use_pfxlist != NULL) + use_pfxlist += use_pfxlen; + } + + // When compounding is supported and there is no + // "COMPOUNDPERMITFLAG" then forbid compounding on the + // side where the affix is applied. + if (spin->si_compflags != NULL && !ae->ae_comppermit) { + if (xht != NULL) + use_flags |= WF_NOCOMPAFT; + else + use_flags |= WF_NOCOMPBEF; + } + + // Store the modified word. + if (store_word(spin, newword, use_flags, + spin->si_region, use_pfxlist, + need_affix) == FAIL) + retval = FAIL; + + // When added a prefix or a first suffix and the affix + // has flags may add a(nother) suffix. RECURSIVE! + if ((condit & CONDIT_SUF) && ae->ae_flags != NULL) + if (store_aff_word(spin, newword, ae->ae_flags, + affile, &affile->af_suff, xht, + use_condit & (xht == NULL + ? ~0 : ~CONDIT_SUF), + use_flags, use_pfxlist, pfxlen) == FAIL) + retval = FAIL; + + // When added a suffix and combining is allowed also + // try adding a prefix additionally. Both for the + // word flags and for the affix flags. RECURSIVE! + if (xht != NULL && ah->ah_combine) { + if (store_aff_word(spin, newword, + afflist, affile, + xht, NULL, use_condit, + use_flags, use_pfxlist, + pfxlen) == FAIL + || (ae->ae_flags != NULL + && store_aff_word(spin, newword, + ae->ae_flags, affile, + xht, NULL, use_condit, + use_flags, use_pfxlist, + pfxlen) == FAIL)) + retval = FAIL; + } + } + } + } + } + } + + return retval; +} + +// Read a file with a list of words. +static int spell_read_wordfile(spellinfo_T *spin, char_u *fname) +{ + FILE *fd; + long lnum = 0; + char_u rline[MAXLINELEN]; + char_u *line; + char_u *pc = NULL; + char_u *p; + int l; + int retval = OK; + bool did_word = false; + int non_ascii = 0; + int flags; + int regionmask; + + // Open the file. + fd = mch_fopen((char *)fname, "r"); + if (fd == NULL) { + EMSG2(_(e_notopen), fname); + return FAIL; + } + + vim_snprintf((char *)IObuff, IOSIZE, _("Reading word file %s ..."), fname); + spell_message(spin, IObuff); + + // Read all the lines in the file one by one. + while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int) { + line_breakcheck(); + ++lnum; + + // Skip comment lines. + if (*rline == '#') + continue; + + // Remove CR, LF and white space from the end. + l = (int)STRLEN(rline); + while (l > 0 && rline[l - 1] <= ' ') + --l; + if (l == 0) + continue; // empty or blank line + rline[l] = NUL; + + // Convert from "/encoding={encoding}" to 'encoding' when needed. + xfree(pc); + if (spin->si_conv.vc_type != CONV_NONE) { + pc = string_convert(&spin->si_conv, rline, NULL); + if (pc == NULL) { + smsg(_("Conversion failure for word in %s line %d: %s"), + fname, lnum, rline); + continue; + } + line = pc; + } else { + pc = NULL; + line = rline; + } + + if (*line == '/') { + ++line; + if (STRNCMP(line, "encoding=", 9) == 0) { + if (spin->si_conv.vc_type != CONV_NONE) + smsg(_("Duplicate /encoding= line ignored in %s line %d: %s"), + fname, lnum, line - 1); + else if (did_word) + smsg(_("/encoding= line after word ignored in %s line %d: %s"), + fname, lnum, line - 1); + else { + char_u *enc; + + // Setup for conversion to 'encoding'. + line += 9; + enc = enc_canonize(line); + if (!spin->si_ascii + && convert_setup(&spin->si_conv, enc, + p_enc) == FAIL) + smsg(_("Conversion in %s not supported: from %s to %s"), + fname, line, p_enc); + xfree(enc); + spin->si_conv.vc_fail = true; + } + continue; + } + + if (STRNCMP(line, "regions=", 8) == 0) { + if (spin->si_region_count > 1) + smsg(_("Duplicate /regions= line ignored in %s line %d: %s"), + fname, lnum, line); + else { + line += 8; + if (STRLEN(line) > 16) + smsg(_("Too many regions in %s line %d: %s"), + fname, lnum, line); + else { + spin->si_region_count = (int)STRLEN(line) / 2; + STRCPY(spin->si_region_name, line); + + // Adjust the mask for a word valid in all regions. + spin->si_region = (1 << spin->si_region_count) - 1; + } + } + continue; + } + + smsg(_("/ line ignored in %s line %d: %s"), + fname, lnum, line - 1); + continue; + } + + flags = 0; + regionmask = spin->si_region; + + // Check for flags and region after a slash. + p = vim_strchr(line, '/'); + if (p != NULL) { + *p++ = NUL; + while (*p != NUL) { + if (*p == '=') // keep-case word + flags |= WF_KEEPCAP | WF_FIXCAP; + else if (*p == '!') // Bad, bad, wicked word. + flags |= WF_BANNED; + else if (*p == '?') // Rare word. + flags |= WF_RARE; + else if (ascii_isdigit(*p)) { // region number(s) + if ((flags & WF_REGION) == 0) // first one + regionmask = 0; + flags |= WF_REGION; + + l = *p - '0'; + if (l > spin->si_region_count) { + smsg(_("Invalid region nr in %s line %d: %s"), + fname, lnum, p); + break; + } + regionmask |= 1 << (l - 1); + } else { + smsg(_("Unrecognized flags in %s line %d: %s"), + fname, lnum, p); + break; + } + ++p; + } + } + + // Skip non-ASCII words when "spin->si_ascii" is true. + if (spin->si_ascii && has_non_ascii(line)) { + ++non_ascii; + continue; + } + + // Normal word: store it. + if (store_word(spin, line, flags, regionmask, NULL, false) == FAIL) { + retval = FAIL; + break; + } + did_word = true; + } + + xfree(pc); + fclose(fd); + + if (spin->si_ascii && non_ascii > 0) { + vim_snprintf((char *)IObuff, IOSIZE, + _("Ignored %d words with non-ASCII characters"), non_ascii); + spell_message(spin, IObuff); + } + + return retval; +} + +/// Get part of an sblock_T, "len" bytes long. +/// This avoids calling free() for every little struct we use (and keeping +/// track of them). +/// The memory is cleared to all zeros. +/// +/// @param len Length needed (<= SBLOCKSIZE). +/// @param align Align for pointer. +/// @return Pointer into block data. +static void *getroom(spellinfo_T *spin, size_t len, bool align) + FUNC_ATTR_NONNULL_RET +{ + char_u *p; + sblock_T *bl = spin->si_blocks; + + assert(len <= SBLOCKSIZE); + + if (align && bl != NULL) + // Round size up for alignment. On some systems structures need to be + // aligned to the size of a pointer (e.g., SPARC). + bl->sb_used = (bl->sb_used + sizeof(char *) - 1) + & ~(sizeof(char *) - 1); + + if (bl == NULL || bl->sb_used + len > SBLOCKSIZE) { + // Allocate a block of memory. It is not freed until much later. + bl = xcalloc(1, (sizeof(sblock_T) + SBLOCKSIZE)); + bl->sb_next = spin->si_blocks; + spin->si_blocks = bl; + bl->sb_used = 0; + ++spin->si_blocks_cnt; + } + + p = bl->sb_data + bl->sb_used; + bl->sb_used += (int)len; + + return p; +} + +// Make a copy of a string into memory allocated with getroom(). +// Returns NULL when out of memory. +static char_u *getroom_save(spellinfo_T *spin, char_u *s) +{ + char_u *sc; + + sc = (char_u *)getroom(spin, STRLEN(s) + 1, false); + if (sc != NULL) + STRCPY(sc, s); + return sc; +} + + +// Free the list of allocated sblock_T. +static void free_blocks(sblock_T *bl) +{ + sblock_T *next; + + while (bl != NULL) { + next = bl->sb_next; + xfree(bl); + bl = next; + } +} + +// Allocate the root of a word tree. +// Returns NULL when out of memory. +static wordnode_T *wordtree_alloc(spellinfo_T *spin) +{ + return (wordnode_T *)getroom(spin, sizeof(wordnode_T), true); +} + +// Store a word in the tree(s). +// Always store it in the case-folded tree. For a keep-case word this is +// useful when the word can also be used with all caps (no WF_FIXCAP flag) and +// used to find suggestions. +// For a keep-case word also store it in the keep-case tree. +// When "pfxlist" is not NULL store the word for each postponed prefix ID and +// compound flag. +static int +store_word ( + spellinfo_T *spin, + char_u *word, + int flags, // extra flags, WF_BANNED + int region, // supported region(s) + char_u *pfxlist, // list of prefix IDs or NULL + bool need_affix // only store word with affix ID +) +{ + int len = (int)STRLEN(word); + int ct = captype(word, word + len); + char_u foldword[MAXWLEN]; + int res = OK; + char_u *p; + + (void)spell_casefold(word, len, foldword, MAXWLEN); + for (p = 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); + if (p == NULL || *p == NUL) + break; + } + ++spin->si_foldwcount; + + if (res == OK && (ct == WF_KEEPCAP || (flags & WF_KEEPCAP))) { + for (p = pfxlist; res == OK; ++p) { + if (!need_affix || (p != NULL && *p != NUL)) + res = tree_add_word(spin, word, spin->si_keeproot, flags, + region, p == NULL ? 0 : *p); + if (p == NULL || *p == NUL) + break; + } + ++spin->si_keepwcount; + } + return res; +} + +// Add word "word" to a word tree at "root". +// When "flags" < 0 we are adding to the prefix tree where "flags" is used for +// "rare" and "region" is the condition nr. +// Returns FAIL when out of memory. +static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int flags, int region, int affixID) +{ + wordnode_T *node = root; + wordnode_T *np; + wordnode_T *copyp, **copyprev; + wordnode_T **prev = NULL; + int i; + + // Add each byte of the word to the tree, including the NUL at the end. + for (i = 0;; ++i) { + // When there is more than one reference to this node we need to make + // a copy, so that we can modify it. Copy the whole list of siblings + // (we don't optimize for a partly shared list of siblings). + if (node != NULL && node->wn_refs > 1) { + --node->wn_refs; + copyprev = prev; + for (copyp = node; copyp != NULL; copyp = copyp->wn_sibling) { + // Allocate a new node and copy the info. + np = get_wordnode(spin); + if (np == NULL) + return FAIL; + np->wn_child = copyp->wn_child; + if (np->wn_child != NULL) + ++np->wn_child->wn_refs; // child gets extra ref + np->wn_byte = copyp->wn_byte; + if (np->wn_byte == NUL) { + np->wn_flags = copyp->wn_flags; + np->wn_region = copyp->wn_region; + np->wn_affixID = copyp->wn_affixID; + } + + // Link the new node in the list, there will be one ref. + np->wn_refs = 1; + if (copyprev != NULL) + *copyprev = np; + copyprev = &np->wn_sibling; + + // Let "node" point to the head of the copied list. + if (copyp == node) + node = np; + } + } + + // Look for the sibling that has the same character. They are sorted + // on byte value, thus stop searching when a sibling is found with a + // higher byte value. For zero bytes (end of word) the sorting is + // done on flags and then on affixID. + while (node != NULL + && (node->wn_byte < word[i] + || (node->wn_byte == NUL + && (flags < 0 + ? node->wn_affixID < (unsigned)affixID + : (node->wn_flags < (unsigned)(flags & WN_MASK) + || (node->wn_flags == (flags & WN_MASK) + && (spin->si_sugtree + ? (node->wn_region & 0xffff) < region + : node->wn_affixID + < (unsigned)affixID))))))) { + prev = &node->wn_sibling; + node = *prev; + } + if (node == NULL + || node->wn_byte != word[i] + || (word[i] == NUL + && (flags < 0 + || spin->si_sugtree + || node->wn_flags != (flags & WN_MASK) + || node->wn_affixID != affixID))) { + // Allocate a new node. + np = get_wordnode(spin); + if (np == NULL) + return FAIL; + np->wn_byte = word[i]; + + // If "node" is NULL this is a new child or the end of the sibling + // list: ref count is one. Otherwise use ref count of sibling and + // make ref count of sibling one (matters when inserting in front + // of the list of siblings). + if (node == NULL) + np->wn_refs = 1; + else { + np->wn_refs = node->wn_refs; + node->wn_refs = 1; + } + if (prev != NULL) + *prev = np; + np->wn_sibling = node; + node = np; + } + + if (word[i] == NUL) { + node->wn_flags = flags; + node->wn_region |= region; + node->wn_affixID = affixID; + break; + } + prev = &node->wn_child; + node = *prev; + } +#ifdef SPELL_PRINTTREE + smsg((char_u *)"Added \"%s\"", word); + spell_print_tree(root->wn_sibling); +#endif + + // count nr of words added since last message + ++spin->si_msg_count; + + if (spin->si_compress_cnt > 1) { + if (--spin->si_compress_cnt == 1) + // Did enough words to lower the block count limit. + spin->si_blocks_cnt += compress_inc; + } + + // When we have allocated lots of memory we need to compress the word tree + // to free up some room. But compression is slow, and we might actually + // need that room, thus only compress in the following situations: + // 1. When not compressed before (si_compress_cnt == 0): when using + // "compress_start" blocks. + // 2. When compressed before and used "compress_inc" blocks before + // adding "compress_added" words (si_compress_cnt > 1). + // 3. When compressed before, added "compress_added" words + // (si_compress_cnt == 1) and the number of free nodes drops below the + // maximum word length. +#ifndef SPELL_COMPRESS_ALLWAYS + if (spin->si_compress_cnt == 1 // NOLINT(readability/braces) + ? spin->si_free_count < MAXWLEN + : spin->si_blocks_cnt >= compress_start) +#endif + { + // Decrement the block counter. The effect is that we compress again + // when the freed up room has been used and another "compress_inc" + // blocks have been allocated. Unless "compress_added" words have + // been added, then the limit is put back again. + spin->si_blocks_cnt -= compress_inc; + spin->si_compress_cnt = compress_added; + + if (spin->si_verbose) { + msg_start(); + msg_puts(_(msg_compressing)); + msg_clr_eos(); + msg_didout = FALSE; + msg_col = 0; + ui_flush(); + } + + // Compress both trees. Either they both have many nodes, which makes + // compression useful, or one of them is small, which means + // compression goes fast. But when filling the soundfold word tree + // there is no keep-case tree. + wordtree_compress(spin, spin->si_foldroot); + if (affixID >= 0) + wordtree_compress(spin, spin->si_keeproot); + } + + return OK; +} + +// Get a wordnode_T, either from the list of previously freed nodes or +// allocate a new one. +// Returns NULL when out of memory. +static wordnode_T *get_wordnode(spellinfo_T *spin) +{ + wordnode_T *n; + + if (spin->si_first_free == NULL) + n = (wordnode_T *)getroom(spin, sizeof(wordnode_T), true); + else { + n = spin->si_first_free; + spin->si_first_free = n->wn_child; + memset(n, 0, sizeof(wordnode_T)); + --spin->si_free_count; + } +#ifdef SPELL_PRINTTREE + if (n != NULL) + n->wn_nr = ++spin->si_wordnode_nr; +#endif + return n; +} + +// Decrement the reference count on a node (which is the head of a list of +// siblings). If the reference count becomes zero free the node and its +// siblings. +// Returns the number of nodes actually freed. +static int deref_wordnode(spellinfo_T *spin, wordnode_T *node) +{ + wordnode_T *np; + int cnt = 0; + + if (--node->wn_refs == 0) { + for (np = node; np != NULL; np = np->wn_sibling) { + if (np->wn_child != NULL) + cnt += deref_wordnode(spin, np->wn_child); + free_wordnode(spin, np); + ++cnt; + } + ++cnt; // length field + } + return cnt; +} + +// Free a wordnode_T for re-use later. +// Only the "wn_child" field becomes invalid. +static void free_wordnode(spellinfo_T *spin, wordnode_T *n) +{ + n->wn_child = spin->si_first_free; + spin->si_first_free = n; + ++spin->si_free_count; +} + +// Compress a tree: find tails that are identical and can be shared. +static void wordtree_compress(spellinfo_T *spin, wordnode_T *root) +{ + hashtab_T ht; + int n; + int tot = 0; + int perc; + + // 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); + n = node_compress(spin, root->wn_sibling, &ht, &tot); + +#ifndef SPELL_PRINTTREE + 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((char *)IObuff, IOSIZE, + _("Compressed %d of %d nodes; %d (%d%%) remaining"), + n, tot, tot - n, perc); + spell_message(spin, IObuff); + } +#ifdef SPELL_PRINTTREE + spell_print_tree(root->wn_sibling); +#endif + hash_clear(&ht); + } +} + +// Compress a node, its siblings and its children, depth first. +// Returns the number of compressed nodes. +static int +node_compress ( + spellinfo_T *spin, + wordnode_T *node, + hashtab_T *ht, + int *tot // total count of nodes before compressing, + // incremented while going through the tree +) +{ + wordnode_T *np; + wordnode_T *tp; + wordnode_T *child; + hash_T hash; + hashitem_T *hi; + int len = 0; + unsigned nr, n; + int compressed = 0; + + // Go through the list of siblings. Compress each child and then try + // finding an identical child to replace it. + // Note that with "child" we mean not just the node that is pointed to, + // but the whole list of siblings of which the child node is the first. + for (np = node; np != NULL && !got_int; np = np->wn_sibling) { + ++len; + if ((child = np->wn_child) != NULL) { + // Compress the child first. This fills hashkey. + compressed += node_compress(spin, child, ht, tot); + + // Try to find an identical child. + hash = hash_hash(child->wn_u1.hashkey); + hi = hash_lookup(ht, (const char *)child->wn_u1.hashkey, + STRLEN(child->wn_u1.hashkey), hash); + if (!HASHITEM_EMPTY(hi)) { + // There are children we encountered before with a hash value + // identical to the current child. Now check if there is one + // that is really identical. + for (tp = HI2WN(hi); tp != NULL; tp = tp->wn_u2.next) + if (node_equal(child, tp)) { + // Found one! Now use that child in place of the + // current one. This means the current child and all + // its siblings is unlinked from the tree. + ++tp->wn_refs; + compressed += deref_wordnode(spin, child); + np->wn_child = tp; + break; + } + if (tp == NULL) { + // No other child with this hash value equals the child of + // the node, add it to the linked list after the first + // item. + tp = HI2WN(hi); + child->wn_u2.next = tp->wn_u2.next; + tp->wn_u2.next = child; + } + } else + // No other child has this hash value, add it to the + // hashtable. + hash_add_item(ht, hi, child->wn_u1.hashkey, hash); + } + } + *tot += len + 1; // add one for the node that stores the length + + // Make a hash key for the node and its siblings, so that we can quickly + // find a lookalike node. This must be done after compressing the sibling + // list, otherwise the hash key would become invalid by the compression. + node->wn_u1.hashkey[0] = len; + nr = 0; + for (np = node; np != NULL; np = np->wn_sibling) { + if (np->wn_byte == NUL) + // end node: use wn_flags, wn_region and wn_affixID + n = np->wn_flags + (np->wn_region << 8) + (np->wn_affixID << 16); + else + // byte node: use the byte value and the child pointer + n = (unsigned)(np->wn_byte + ((uintptr_t)np->wn_child << 8)); + nr = nr * 101 + n; + } + + // Avoid NUL bytes, it terminates the hash key. + n = nr & 0xff; + node->wn_u1.hashkey[1] = n == 0 ? 1 : n; + n = (nr >> 8) & 0xff; + node->wn_u1.hashkey[2] = n == 0 ? 1 : n; + n = (nr >> 16) & 0xff; + node->wn_u1.hashkey[3] = n == 0 ? 1 : n; + n = (nr >> 24) & 0xff; + node->wn_u1.hashkey[4] = n == 0 ? 1 : n; + node->wn_u1.hashkey[5] = NUL; + + // Check for CTRL-C pressed now and then. + fast_breakcheck(); + + return compressed; +} + +// Returns true when two nodes have identical siblings and children. +static bool node_equal(wordnode_T *n1, wordnode_T *n2) +{ + wordnode_T *p1; + wordnode_T *p2; + + for (p1 = n1, p2 = n2; p1 != NULL && p2 != NULL; + p1 = p1->wn_sibling, p2 = p2->wn_sibling) + if (p1->wn_byte != p2->wn_byte + || (p1->wn_byte == NUL + ? (p1->wn_flags != p2->wn_flags + || p1->wn_region != p2->wn_region + || p1->wn_affixID != p2->wn_affixID) + : (p1->wn_child != p2->wn_child))) + break; + + return p1 == NULL && p2 == NULL; +} + + +// Function given to qsort() to sort the REP items on "from" string. +static int rep_compare(const void *s1, const void *s2) +{ + fromto_T *p1 = (fromto_T *)s1; + fromto_T *p2 = (fromto_T *)s2; + + return STRCMP(p1->ft_from, p2->ft_from); +} + +// Write the Vim .spl file "fname". +// Return OK/FAIL. +static int write_vim_spell(spellinfo_T *spin, char_u *fname) +{ + int retval = OK; + int regionmask; + + FILE *fd = mch_fopen((char *)fname, "w"); + if (fd == NULL) { + EMSG2(_(e_notopen), fname); + return FAIL; + } + + // <HEADER>: <fileID> <versionnr> + // <fileID> + size_t fwv = fwrite(VIMSPELLMAGIC, VIMSPELLMAGICL, 1, fd); + if (fwv != (size_t)1) + // Catch first write error, don't try writing more. + goto theend; + + putc(VIMSPELLVERSION, fd); // <versionnr> + + // <SECTIONS>: <section> ... <sectionend> + + // SN_INFO: <infotext> + if (spin->si_info != NULL) { + putc(SN_INFO, fd); // <sectionID> + putc(0, fd); // <sectionflags> + size_t i = STRLEN(spin->si_info); + put_bytes(fd, i, 4); // <sectionlen> + fwv &= fwrite(spin->si_info, i, 1, fd); // <infotext> + } + + // SN_REGION: <regionname> ... + // Write the region names only if there is more than one. + if (spin->si_region_count > 1) { + putc(SN_REGION, fd); // <sectionID> + putc(SNF_REQUIRED, fd); // <sectionflags> + size_t l = (size_t)spin->si_region_count * 2; + put_bytes(fd, l, 4); // <sectionlen> + fwv &= fwrite(spin->si_region_name, l, 1, fd); + // <regionname> ... + regionmask = (1 << spin->si_region_count) - 1; + } else + regionmask = 0; + + // SN_CHARFLAGS: <charflagslen> <charflags> <folcharslen> <folchars> + // + // The table with character flags and the table for case folding. + // This makes sure the same characters are recognized as word characters + // when generating an when using a spell file. + // Skip this for ASCII, the table may conflict with the one used for + // 'encoding'. + // Also skip this for an .add.spl file, the main spell file must contain + // the table (avoids that it conflicts). File is shorter too. + if (!spin->si_ascii && !spin->si_add) { + char_u folchars[128 * 8]; + int flags; + + putc(SN_CHARFLAGS, fd); // <sectionID> + putc(SNF_REQUIRED, fd); // <sectionflags> + + // Form the <folchars> string first, we need to know its length. + size_t l = 0; + for (size_t i = 128; i < 256; ++i) { + if (has_mbyte) + l += (size_t)mb_char2bytes(spelltab.st_fold[i], folchars + l); + else + folchars[l++] = spelltab.st_fold[i]; + } + put_bytes(fd, 1 + 128 + 2 + l, 4); // <sectionlen> + + fputc(128, fd); // <charflagslen> + for (size_t i = 128; i < 256; ++i) { + flags = 0; + if (spelltab.st_isw[i]) + flags |= CF_WORD; + if (spelltab.st_isu[i]) + flags |= CF_UPPER; + fputc(flags, fd); // <charflags> + } + + put_bytes(fd, l, 2); // <folcharslen> + fwv &= fwrite(folchars, l, 1, fd); // <folchars> + } + + // SN_MIDWORD: <midword> + if (spin->si_midword != NULL) { + putc(SN_MIDWORD, fd); // <sectionID> + putc(SNF_REQUIRED, fd); // <sectionflags> + + size_t i = STRLEN(spin->si_midword); + put_bytes(fd, i, 4); // <sectionlen> + fwv &= fwrite(spin->si_midword, i, 1, fd); + // <midword> + } + + // SN_PREFCOND: <prefcondcnt> <prefcond> ... + if (!GA_EMPTY(&spin->si_prefcond)) { + putc(SN_PREFCOND, fd); // <sectionID> + putc(SNF_REQUIRED, fd); // <sectionflags> + + size_t l = (size_t)write_spell_prefcond(NULL, &spin->si_prefcond); + put_bytes(fd, l, 4); // <sectionlen> + + write_spell_prefcond(fd, &spin->si_prefcond); + } + + // SN_REP: <repcount> <rep> ... + // SN_SAL: <salflags> <salcount> <sal> ... + // SN_REPSAL: <repcount> <rep> ... + + // round 1: SN_REP section + // round 2: SN_SAL section (unless SN_SOFO is used) + // round 3: SN_REPSAL section + for (unsigned int round = 1; round <= 3; ++round) { + garray_T *gap; + if (round == 1) + gap = &spin->si_rep; + else if (round == 2) { + // Don't write SN_SAL when using a SN_SOFO section + if (spin->si_sofofr != NULL && spin->si_sofoto != NULL) + continue; + gap = &spin->si_sal; + } else + gap = &spin->si_repsal; + + // Don't write the section if there are no items. + if (GA_EMPTY(gap)) + continue; + + // Sort the REP/REPSAL items. + if (round != 2) + qsort(gap->ga_data, (size_t)gap->ga_len, + sizeof(fromto_T), rep_compare); + + int i = round == 1 ? SN_REP : (round == 2 ? SN_SAL : SN_REPSAL); + putc(i, fd); // <sectionID> + + // This is for making suggestions, section is not required. + putc(0, fd); // <sectionflags> + + // Compute the length of what follows. + size_t l = 2; // count <repcount> or <salcount> + assert(gap->ga_len >= 0); + for (size_t i = 0; i < (size_t)gap->ga_len; ++i) { + fromto_T *ftp = &((fromto_T *)gap->ga_data)[i]; + l += 1 + STRLEN(ftp->ft_from); // count <*fromlen> and <*from> + l += 1 + STRLEN(ftp->ft_to); // count <*tolen> and <*to> + } + if (round == 2) + ++l; // count <salflags> + put_bytes(fd, l, 4); // <sectionlen> + + if (round == 2) { + int i = 0; + if (spin->si_followup) + i |= SAL_F0LLOWUP; + if (spin->si_collapse) + i |= SAL_COLLAPSE; + if (spin->si_rem_accents) + i |= SAL_REM_ACCENTS; + putc(i, fd); // <salflags> + } + + put_bytes(fd, (uintmax_t)gap->ga_len, 2); // <repcount> or <salcount> + for (size_t i = 0; i < (size_t)gap->ga_len; ++i) { + // <rep> : <repfromlen> <repfrom> <reptolen> <repto> + // <sal> : <salfromlen> <salfrom> <saltolen> <salto> + fromto_T *ftp = &((fromto_T *)gap->ga_data)[i]; + for (unsigned int rr = 1; rr <= 2; ++rr) { + char_u *p = rr == 1 ? ftp->ft_from : ftp->ft_to; + l = STRLEN(p); + assert(l < INT_MAX); + putc((int)l, fd); + if (l > 0) + fwv &= fwrite(p, l, 1, fd); + } + } + + } + + // SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto> + // This is for making suggestions, section is not required. + if (spin->si_sofofr != NULL && spin->si_sofoto != NULL) { + putc(SN_SOFO, fd); // <sectionID> + putc(0, fd); // <sectionflags> + + size_t l = STRLEN(spin->si_sofofr); + put_bytes(fd, l + STRLEN(spin->si_sofoto) + 4, 4); // <sectionlen> + + put_bytes(fd, l, 2); // <sofofromlen> + fwv &= fwrite(spin->si_sofofr, l, 1, fd); // <sofofrom> + + l = STRLEN(spin->si_sofoto); + put_bytes(fd, l, 2); // <sofotolen> + fwv &= fwrite(spin->si_sofoto, l, 1, fd); // <sofoto> + } + + // SN_WORDS: <word> ... + // This is for making suggestions, section is not required. + if (spin->si_commonwords.ht_used > 0) { + putc(SN_WORDS, fd); // <sectionID> + putc(0, fd); // <sectionflags> + + // round 1: count the bytes + // round 2: write the bytes + for (unsigned int round = 1; round <= 2; ++round) { + size_t todo; + size_t len = 0; + hashitem_T *hi; + + todo = spin->si_commonwords.ht_used; + for (hi = spin->si_commonwords.ht_array; todo > 0; ++hi) + if (!HASHITEM_EMPTY(hi)) { + size_t l = STRLEN(hi->hi_key) + 1; + len += l; + if (round == 2) // <word> + fwv &= fwrite(hi->hi_key, l, 1, fd); + --todo; + } + if (round == 1) + put_bytes(fd, len, 4); // <sectionlen> + } + } + + // SN_MAP: <mapstr> + // This is for making suggestions, section is not required. + if (!GA_EMPTY(&spin->si_map)) { + putc(SN_MAP, fd); // <sectionID> + putc(0, fd); // <sectionflags> + size_t l = (size_t)spin->si_map.ga_len; + put_bytes(fd, l, 4); // <sectionlen> + fwv &= fwrite(spin->si_map.ga_data, l, 1, fd); // <mapstr> + } + + // SN_SUGFILE: <timestamp> + // This is used to notify that a .sug file may be available and at the + // same time allows for checking that a .sug file that is found matches + // with this .spl file. That's because the word numbers must be exactly + // right. + if (!spin->si_nosugfile + && (!GA_EMPTY(&spin->si_sal) + || (spin->si_sofofr != NULL && spin->si_sofoto != NULL))) { + putc(SN_SUGFILE, fd); // <sectionID> + putc(0, fd); // <sectionflags> + put_bytes(fd, 8, 4); // <sectionlen> + + // Set si_sugtime and write it to the file. + spin->si_sugtime = time(NULL); + put_time(fd, spin->si_sugtime); // <timestamp> + } + + // SN_NOSPLITSUGS: nothing + // This is used to notify that no suggestions with word splits are to be + // made. + if (spin->si_nosplitsugs) { + putc(SN_NOSPLITSUGS, fd); // <sectionID> + putc(0, fd); // <sectionflags> + put_bytes(fd, 0, 4); // <sectionlen> + } + + // SN_NOCOMPUNDSUGS: nothing + // This is used to notify that no suggestions with compounds are to be + // made. + if (spin->si_nocompoundsugs) { + putc(SN_NOCOMPOUNDSUGS, fd); // <sectionID> + putc(0, fd); // <sectionflags> + put_bytes(fd, 0, 4); // <sectionlen> + } + + // SN_COMPOUND: compound info. + // We don't mark it required, when not supported all compound words will + // be bad words. + if (spin->si_compflags != NULL) { + putc(SN_COMPOUND, fd); // <sectionID> + putc(0, fd); // <sectionflags> + + size_t l = STRLEN(spin->si_compflags); + assert(spin->si_comppat.ga_len >= 0); + for (size_t i = 0; i < (size_t)spin->si_comppat.ga_len; ++i) { + l += STRLEN(((char_u **)(spin->si_comppat.ga_data))[i]) + 1; + } + put_bytes(fd, l + 7, 4); // <sectionlen> + + putc(spin->si_compmax, fd); // <compmax> + putc(spin->si_compminlen, fd); // <compminlen> + putc(spin->si_compsylmax, fd); // <compsylmax> + putc(0, fd); // for Vim 7.0b compatibility + putc(spin->si_compoptions, fd); // <compoptions> + put_bytes(fd, (uintmax_t)spin->si_comppat.ga_len, 2); // <comppatcount> + for (size_t i = 0; i < (size_t)spin->si_comppat.ga_len; ++i) { + char_u *p = ((char_u **)(spin->si_comppat.ga_data))[i]; + assert(STRLEN(p) < INT_MAX); + putc((int)STRLEN(p), fd); // <comppatlen> + fwv &= fwrite(p, STRLEN(p), 1, fd); // <comppattext> + } + // <compflags> + fwv &= fwrite(spin->si_compflags, STRLEN(spin->si_compflags), 1, fd); + } + + // SN_NOBREAK: NOBREAK flag + if (spin->si_nobreak) { + putc(SN_NOBREAK, fd); // <sectionID> + putc(0, fd); // <sectionflags> + + // It's empty, the presence of the section flags the feature. + put_bytes(fd, 0, 4); // <sectionlen> + } + + // SN_SYLLABLE: syllable info. + // We don't mark it required, when not supported syllables will not be + // counted. + if (spin->si_syllable != NULL) { + putc(SN_SYLLABLE, fd); // <sectionID> + putc(0, fd); // <sectionflags> + + size_t l = STRLEN(spin->si_syllable); + put_bytes(fd, l, 4); // <sectionlen> + fwv &= fwrite(spin->si_syllable, l, 1, fd); // <syllable> + } + + // end of <SECTIONS> + putc(SN_END, fd); // <sectionend> + + + // <LWORDTREE> <KWORDTREE> <PREFIXTREE> + spin->si_memtot = 0; + for (unsigned int round = 1; round <= 3; ++round) { + wordnode_T *tree; + if (round == 1) + tree = spin->si_foldroot->wn_sibling; + else if (round == 2) + tree = spin->si_keeproot->wn_sibling; + else + tree = spin->si_prefroot->wn_sibling; + + // Clear the index and wnode fields in the tree. + clear_node(tree); + + // Count the number of nodes. Needed to be able to allocate the + // memory when reading the nodes. Also fills in index for shared + // nodes. + size_t nodecount = (size_t)put_node(NULL, tree, 0, regionmask, round == 3); + + // number of nodes in 4 bytes + put_bytes(fd, nodecount, 4); // <nodecount> + assert(nodecount + nodecount * sizeof(int) < INT_MAX); + spin->si_memtot += (int)(nodecount + nodecount * sizeof(int)); + + // Write the nodes. + (void)put_node(fd, tree, 0, regionmask, round == 3); + } + + // Write another byte to check for errors (file system full). + if (putc(0, fd) == EOF) + retval = FAIL; +theend: + if (fclose(fd) == EOF) + retval = FAIL; + + if (fwv != (size_t)1) + retval = FAIL; + if (retval == FAIL) + EMSG(_(e_write)); + + return retval; +} + +// Clear the index and wnode fields of "node", it siblings and its +// children. This is needed because they are a union with other items to save +// space. +static void clear_node(wordnode_T *node) +{ + wordnode_T *np; + + if (node != NULL) + for (np = node; np != NULL; np = np->wn_sibling) { + np->wn_u1.index = 0; + np->wn_u2.wnode = NULL; + + if (np->wn_byte != NUL) + clear_node(np->wn_child); + } +} + + +// Dump a word tree at node "node". +// +// This first writes the list of possible bytes (siblings). Then for each +// byte recursively write the children. +// +// NOTE: The code here must match the code in read_tree_node(), since +// assumptions are made about the indexes (so that we don't have to write them +// in the file). +// +// Returns the number of nodes used. +static int +put_node ( + FILE *fd, // NULL when only counting + wordnode_T *node, + int idx, + int regionmask, + bool prefixtree // true for PREFIXTREE +) +{ + // If "node" is zero the tree is empty. + if (node == NULL) + return 0; + + // Store the index where this node is written. + node->wn_u1.index = idx; + + // Count the number of siblings. + int siblingcount = 0; + for (wordnode_T *np = node; np != NULL; np = np->wn_sibling) + ++siblingcount; + + // Write the sibling count. + if (fd != NULL) + putc(siblingcount, fd); // <siblingcount> + + // Write each sibling byte and optionally extra info. + for (wordnode_T *np = node; np != NULL; np = np->wn_sibling) { + if (np->wn_byte == 0) { + if (fd != NULL) { + // For a NUL byte (end of word) write the flags etc. + if (prefixtree) { + // In PREFIXTREE write the required affixID and the + // associated condition nr (stored in wn_region). The + // byte value is misused to store the "rare" and "not + // combining" flags + if (np->wn_flags == (uint16_t)PFX_FLAGS) + putc(BY_NOFLAGS, fd); // <byte> + else { + putc(BY_FLAGS, fd); // <byte> + putc(np->wn_flags, fd); // <pflags> + } + putc(np->wn_affixID, fd); // <affixID> + put_bytes(fd, (uintmax_t)np->wn_region, 2); // <prefcondnr> + } else { + // For word trees we write the flag/region items. + int flags = np->wn_flags; + if (regionmask != 0 && np->wn_region != regionmask) + flags |= WF_REGION; + if (np->wn_affixID != 0) + flags |= WF_AFX; + if (flags == 0) { + // word without flags or region + putc(BY_NOFLAGS, fd); // <byte> + } else { + if (np->wn_flags >= 0x100) { + putc(BY_FLAGS2, fd); // <byte> + putc(flags, fd); // <flags> + putc((int)((unsigned)flags >> 8), fd); // <flags2> + } else { + putc(BY_FLAGS, fd); // <byte> + putc(flags, fd); // <flags> + } + if (flags & WF_REGION) + putc(np->wn_region, fd); // <region> + if (flags & WF_AFX) + putc(np->wn_affixID, fd); // <affixID> + } + } + } + } else { + if (np->wn_child->wn_u1.index != 0 + && np->wn_child->wn_u2.wnode != node) { + // The child is written elsewhere, write the reference. + if (fd != NULL) { + putc(BY_INDEX, fd); // <byte> + put_bytes(fd, (uintmax_t)np->wn_child->wn_u1.index, 3); // <nodeidx> + } + } else if (np->wn_child->wn_u2.wnode == NULL) + // We will write the child below and give it an index. + np->wn_child->wn_u2.wnode = node; + + if (fd != NULL) + if (putc(np->wn_byte, fd) == EOF) { // <byte> or <xbyte> + EMSG(_(e_write)); + return 0; + } + } + } + + // Space used in the array when reading: one for each sibling and one for + // the count. + int newindex = idx + siblingcount + 1; + + // Recursively dump the children of each sibling. + for (wordnode_T *np = node; np != NULL; np = np->wn_sibling) + if (np->wn_byte != 0 && np->wn_child->wn_u2.wnode == node) + newindex = put_node(fd, np->wn_child, newindex, regionmask, + prefixtree); + + return newindex; +} + + +// ":mkspell [-ascii] outfile infile ..." +// ":mkspell [-ascii] addfile" +void ex_mkspell(exarg_T *eap) +{ + int fcount; + char_u **fnames; + char_u *arg = eap->arg; + bool ascii = false; + + if (STRNCMP(arg, "-ascii", 6) == 0) { + ascii = true; + arg = skipwhite(arg + 6); + } + + // 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); + } +} + +// Create the .sug file. +// Uses the soundfold info in "spin". +// Writes the file with the name "wfname", with ".spl" changed to ".sug". +static void spell_make_sugfile(spellinfo_T *spin, char_u *wfname) +{ + char_u *fname = NULL; + int len; + slang_T *slang; + bool free_slang = false; + + // Read back the .spl file that was written. This fills the required + // info for soundfolding. This also uses less memory than the + // pointer-linked version of the trie. And it avoids having two versions + // of the code for the soundfolding stuff. + // It might have been done already by spell_reload_one(). + for (slang = first_lang; slang != NULL; slang = slang->sl_next) + if (path_full_compare(wfname, slang->sl_fname, FALSE) == kEqualFiles) + break; + if (slang == NULL) { + spell_message(spin, (char_u *)_("Reading back spell file...")); + slang = spell_load_file(wfname, NULL, NULL, false); + if (slang == NULL) + return; + free_slang = true; + } + + // Clear the info in "spin" that is used. + spin->si_blocks = NULL; + spin->si_blocks_cnt = 0; + spin->si_compress_cnt = 0; // will stay at 0 all the time + spin->si_free_count = 0; + spin->si_first_free = NULL; + spin->si_foldwcount = 0; + + // Go through the trie of good words, soundfold each word and add it to + // the soundfold trie. + spell_message(spin, (char_u *)_("Performing soundfolding...")); + if (sug_filltree(spin, slang) == FAIL) + goto theend; + + // Create the table which links each soundfold word with a list of the + // good words it may come from. Creates buffer "spin->si_spellbuf". + // This also removes the wordnr from the NUL byte entries to make + // compression possible. + if (sug_maketable(spin) == FAIL) + goto theend; + + smsg(_("Number of words after soundfolding: %" PRId64), + (int64_t)spin->si_spellbuf->b_ml.ml_line_count); + + // Compress the soundfold trie. + spell_message(spin, (char_u *)_(msg_compressing)); + wordtree_compress(spin, spin->si_foldroot); + + // Write the .sug file. + // Make the file name by changing ".spl" to ".sug". + fname = xmalloc(MAXPATHL); + STRLCPY(fname, wfname, MAXPATHL); + len = (int)STRLEN(fname); + fname[len - 2] = 'u'; + fname[len - 1] = 'g'; + sug_write(spin, fname); + +theend: + xfree(fname); + if (free_slang) + slang_free(slang); + free_blocks(spin->si_blocks); + close_spellbuf(spin->si_spellbuf); +} + +// Build the soundfold trie for language "slang". +static int sug_filltree(spellinfo_T *spin, slang_T *slang) +{ + char_u *byts; + idx_T *idxs; + int depth; + idx_T arridx[MAXWLEN]; + int curi[MAXWLEN]; + char_u tword[MAXWLEN]; + char_u tsalword[MAXWLEN]; + int c; + idx_T n; + unsigned words_done = 0; + int wordcount[MAXWLEN]; + + // We use si_foldroot for the soundfolded trie. + spin->si_foldroot = wordtree_alloc(spin); + if (spin->si_foldroot == NULL) + return FAIL; + + // Let tree_add_word() know we're adding to the soundfolded tree + spin->si_sugtree = true; + + // Go through the whole case-folded tree, soundfold each word and put it + // in the trie. + byts = slang->sl_fbyts; + idxs = slang->sl_fidxs; + + arridx[0] = 0; + curi[0] = 1; + wordcount[0] = 0; + + depth = 0; + while (depth >= 0 && !got_int) { + if (curi[depth] > byts[arridx[depth]]) { + // Done all bytes at this node, go up one level. + idxs[arridx[depth]] = wordcount[depth]; + if (depth > 0) + wordcount[depth - 1] += wordcount[depth]; + + --depth; + line_breakcheck(); + } else { + + // Do one more byte at this node. + n = arridx[depth] + curi[depth]; + ++curi[depth]; + + c = byts[n]; + if (c == 0) { + // Sound-fold the word. + tword[depth] = NUL; + spell_soundfold(slang, tword, true, tsalword); + + // We use the "flags" field for the MSB of the wordnr, + // "region" for the LSB of the wordnr. + if (tree_add_word(spin, tsalword, spin->si_foldroot, + words_done >> 16, words_done & 0xffff, + 0) == FAIL) + return FAIL; + + ++words_done; + ++wordcount[depth]; + + // Reset the block count each time to avoid compression + // kicking in. + spin->si_blocks_cnt = 0; + + // Skip over any other NUL bytes (same word with different + // flags). + while (byts[n + 1] == 0) { + ++n; + ++curi[depth]; + } + } else { + // Normal char, go one level deeper. + tword[depth++] = c; + arridx[depth] = idxs[n]; + curi[depth] = 1; + wordcount[depth] = 0; + } + } + } + + smsg(_("Total number of words: %d"), words_done); + + return OK; +} + +// Make the table that links each word in the soundfold trie to the words it +// can be produced from. +// This is not unlike lines in a file, thus use a memfile to be able to access +// the table efficiently. +// Returns FAIL when out of memory. +static int sug_maketable(spellinfo_T *spin) +{ + garray_T ga; + int res = OK; + + // Allocate a buffer, open a memline for it and create the swap file + // (uses a temp file, not a .swp file). + spin->si_spellbuf = open_spellbuf(); + + // Use a buffer to store the line info, avoids allocating many small + // pieces of memory. + ga_init(&ga, 1, 100); + + // recursively go through the tree + if (sug_filltable(spin, spin->si_foldroot->wn_sibling, 0, &ga) == -1) + res = FAIL; + + ga_clear(&ga); + return res; +} + +// Fill the table for one node and its children. +// Returns the wordnr at the start of the node. +// Returns -1 when out of memory. +static int +sug_filltable ( + spellinfo_T *spin, + wordnode_T *node, + int startwordnr, + garray_T *gap // place to store line of numbers +) +{ + wordnode_T *p, *np; + int wordnr = startwordnr; + int nr; + int prev_nr; + + for (p = node; p != NULL; p = p->wn_sibling) { + if (p->wn_byte == NUL) { + gap->ga_len = 0; + prev_nr = 0; + for (np = p; np != NULL && np->wn_byte == NUL; np = np->wn_sibling) { + ga_grow(gap, 10); + + nr = (np->wn_flags << 16) + (np->wn_region & 0xffff); + // Compute the offset from the previous nr and store the + // offset in a way that it takes a minimum number of bytes. + // It's a bit like utf-8, but without the need to mark + // following bytes. + nr -= prev_nr; + prev_nr += nr; + gap->ga_len += offset2bytes(nr, + (char_u *)gap->ga_data + gap->ga_len); + } + + // add the NUL byte + ((char_u *)gap->ga_data)[gap->ga_len++] = NUL; + + if (ml_append_buf(spin->si_spellbuf, (linenr_T)wordnr, + gap->ga_data, gap->ga_len, TRUE) == FAIL) + return -1; + ++wordnr; + + // Remove extra NUL entries, we no longer need them. We don't + // bother freeing the nodes, the won't be reused anyway. + while (p->wn_sibling != NULL && p->wn_sibling->wn_byte == NUL) + p->wn_sibling = p->wn_sibling->wn_sibling; + + // Clear the flags on the remaining NUL node, so that compression + // works a lot better. + p->wn_flags = 0; + p->wn_region = 0; + } else { + wordnr = sug_filltable(spin, p->wn_child, wordnr, gap); + if (wordnr == -1) + return -1; + } + } + return wordnr; +} + +// Convert an offset into a minimal number of bytes. +// Similar to utf_char2byters, but use 8 bits in followup bytes and avoid NUL +// bytes. +static int offset2bytes(int nr, char_u *buf) +{ + int rem; + int b1, b2, b3, b4; + + // Split the number in parts of base 255. We need to avoid NUL bytes. + b1 = nr % 255 + 1; + rem = nr / 255; + b2 = rem % 255 + 1; + rem = rem / 255; + b3 = rem % 255 + 1; + b4 = rem / 255 + 1; + + if (b4 > 1 || b3 > 0x1f) { // 4 bytes + buf[0] = 0xe0 + b4; + buf[1] = b3; + buf[2] = b2; + buf[3] = b1; + return 4; + } + if (b3 > 1 || b2 > 0x3f ) { // 3 bytes + buf[0] = 0xc0 + b3; + buf[1] = b2; + buf[2] = b1; + return 3; + } + if (b2 > 1 || b1 > 0x7f ) { // 2 bytes + buf[0] = 0x80 + b2; + buf[1] = b1; + return 2; + } + // 1 byte + buf[0] = b1; + return 1; +} + +// Write the .sug file in "fname". +static void sug_write(spellinfo_T *spin, char_u *fname) +{ + // Create the file. Note that an existing file is silently overwritten! + FILE *fd = mch_fopen((char *)fname, "w"); + if (fd == NULL) { + EMSG2(_(e_notopen), fname); + return; + } + + vim_snprintf((char *)IObuff, IOSIZE, + _("Writing suggestion file %s ..."), fname); + spell_message(spin, IObuff); + + // <SUGHEADER>: <fileID> <versionnr> <timestamp> + if (fwrite(VIMSUGMAGIC, VIMSUGMAGICL, (size_t)1, fd) != 1) { // <fileID> + EMSG(_(e_write)); + goto theend; + } + putc(VIMSUGVERSION, fd); // <versionnr> + + // Write si_sugtime to the file. + put_time(fd, spin->si_sugtime); // <timestamp> + + // <SUGWORDTREE> + spin->si_memtot = 0; + wordnode_T *tree = spin->si_foldroot->wn_sibling; + + // Clear the index and wnode fields in the tree. + clear_node(tree); + + // Count the number of nodes. Needed to be able to allocate the + // memory when reading the nodes. Also fills in index for shared + // nodes. + size_t nodecount = (size_t)put_node(NULL, tree, 0, 0, false); + + // number of nodes in 4 bytes + put_bytes(fd, nodecount, 4); // <nodecount> + assert(nodecount + nodecount * sizeof(int) < INT_MAX); + spin->si_memtot += (int)(nodecount + nodecount * sizeof(int)); + + // Write the nodes. + (void)put_node(fd, tree, 0, 0, false); + + // <SUGTABLE>: <sugwcount> <sugline> ... + linenr_T wcount = spin->si_spellbuf->b_ml.ml_line_count; + assert(wcount >= 0); + put_bytes(fd, (uintmax_t)wcount, 4); // <sugwcount> + + for (linenr_T lnum = 1; lnum <= wcount; ++lnum) { + // <sugline>: <sugnr> ... NUL + char_u *line = ml_get_buf(spin->si_spellbuf, lnum, FALSE); + size_t len = STRLEN(line) + 1; + if (fwrite(line, len, 1, fd) == 0) { + EMSG(_(e_write)); + goto theend; + } + assert((size_t)spin->si_memtot + len <= INT_MAX); + spin->si_memtot += (int)len; + } + + // Write another byte to check for errors. + if (putc(0, fd) == EOF) + EMSG(_(e_write)); + + vim_snprintf((char *)IObuff, IOSIZE, + _("Estimated runtime memory use: %d bytes"), spin->si_memtot); + spell_message(spin, IObuff); + +theend: + // close the file + fclose(fd); +} + + +// Create a Vim spell file from one or more word lists. +// "fnames[0]" is the output file name. +// "fnames[fcount - 1]" is the last input file name. +// Exception: when "fnames[0]" ends in ".add" it's used as the input file name +// and ".spl" is appended to make the output file name. +static void +mkspell ( + int fcount, + char_u **fnames, + bool ascii, // -ascii argument given + bool over_write, // overwrite existing output file + bool added_word // invoked through "zg" +) +{ + char_u *fname = NULL; + char_u *wfname; + char_u **innames; + int incount; + afffile_T *(afile[8]); + int i; + int len; + bool error = false; + spellinfo_T spin; + + memset(&spin, 0, sizeof(spin)); + spin.si_verbose = !added_word; + spin.si_ascii = ascii; + spin.si_followup = true; + spin.si_rem_accents = true; + 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); + hash_init(&spin.si_commonwords); + spin.si_newcompID = 127; // start compound ID at first maximum + + // default: fnames[0] is output file, following are input files + innames = &fnames[1]; + incount = fcount - 1; + + wfname = xmalloc(MAXPATHL); + + if (fcount >= 1) { + len = (int)STRLEN(fnames[0]); + if (fcount == 1 && len > 4 && STRCMP(fnames[0] + len - 4, ".add") == 0) { + // For ":mkspell path/en.latin1.add" output file is + // "path/en.latin1.add.spl". + innames = &fnames[0]; + incount = 1; + vim_snprintf((char *)wfname, MAXPATHL, "%s.spl", fnames[0]); + } else if (fcount == 1) { + // For ":mkspell path/vim" output file is "path/vim.latin1.spl". + innames = &fnames[0]; + incount = 1; + vim_snprintf((char *)wfname, MAXPATHL, SPL_FNAME_TMPL, + fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc()); + } else if (len > 4 && STRCMP(fnames[0] + len - 4, ".spl") == 0) { + // Name ends in ".spl", use as the file name. + STRLCPY(wfname, fnames[0], MAXPATHL); + } else + // Name should be language, make the file name from it. + vim_snprintf((char *)wfname, MAXPATHL, SPL_FNAME_TMPL, + fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc()); + + // Check for .ascii.spl. + if (strstr((char *)path_tail(wfname), SPL_FNAME_ASCII) != NULL) + spin.si_ascii = true; + + // Check for .add.spl. + if (strstr((char *)path_tail(wfname), SPL_FNAME_ADD) != NULL) + spin.si_add = true; + } + + if (incount <= 0) + EMSG(_(e_invarg)); // need at least output and input names + else if (vim_strchr(path_tail(wfname), '_') != NULL) + EMSG(_("E751: Output file name must not have region name")); + else if (incount > 8) + EMSG(_("E754: Only up to 8 regions supported")); + else { + // Check for overwriting before doing things that may take a lot of + // time. + if (!over_write && os_path_exists(wfname)) { + EMSG(_(e_exists)); + goto theend; + } + if (os_isdir(wfname)) { + EMSG2(_(e_isadir2), wfname); + goto theend; + } + + fname = xmalloc(MAXPATHL); + + // Init the aff and dic pointers. + // Get the region names if there are more than 2 arguments. + for (i = 0; i < incount; ++i) { + afile[i] = NULL; + + if (incount > 1) { + len = (int)STRLEN(innames[i]); + if (STRLEN(path_tail(innames[i])) < 5 + || innames[i][len - 3] != '_') { + EMSG2(_("E755: Invalid region in %s"), innames[i]); + goto theend; + } + spin.si_region_name[i * 2] = TOLOWER_ASC(innames[i][len - 2]); + spin.si_region_name[i * 2 + 1] = + TOLOWER_ASC(innames[i][len - 1]); + } + } + spin.si_region_count = incount; + + spin.si_foldroot = wordtree_alloc(&spin); + spin.si_keeproot = wordtree_alloc(&spin); + spin.si_prefroot = wordtree_alloc(&spin); + if (spin.si_foldroot == NULL + || spin.si_keeproot == NULL + || spin.si_prefroot == NULL) { + free_blocks(spin.si_blocks); + goto theend; + } + + // When not producing a .add.spl file clear the character table when + // we encounter one in the .aff file. This means we dump the current + // one in the .spl file if the .aff file doesn't define one. That's + // better than guessing the contents, the table will match a + // previously loaded spell file. + if (!spin.si_add) + spin.si_clear_chartab = true; + + // Read all the .aff and .dic files. + // Text is converted to 'encoding'. + // Words are stored in the case-folded and keep-case trees. + for (i = 0; i < incount && !error; ++i) { + 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(fname)) { + // Read the .aff file. Will init "spin->si_conv" based on the + // "SET" line. + afile[i] = spell_read_aff(&spin, fname); + if (afile[i] == NULL) + error = true; + else { + // Read the .dic file and store the words in the trees. + vim_snprintf((char *)fname, MAXPATHL, "%s.dic", + innames[i]); + if (spell_read_dic(&spin, fname, afile[i]) == FAIL) + error = true; + } + } else { + // No .aff file, try reading the file as a word list. Store + // the words in the trees. + if (spell_read_wordfile(&spin, innames[i]) == FAIL) + error = true; + } + + // Free any conversion stuff. + convert_setup(&spin.si_conv, NULL, NULL); + } + + if (spin.si_compflags != NULL && spin.si_nobreak) + MSG(_("Warning: both compounding and NOBREAK specified")); + + if (!error && !got_int) { + // Combine tails in the tree. + spell_message(&spin, (char_u *)_(msg_compressing)); + wordtree_compress(&spin, spin.si_foldroot); + wordtree_compress(&spin, spin.si_keeproot); + wordtree_compress(&spin, spin.si_prefroot); + } + + if (!error && !got_int) { + // Write the info in the spell file. + vim_snprintf((char *)IObuff, IOSIZE, + _("Writing spell file %s ..."), wfname); + spell_message(&spin, IObuff); + + error = write_vim_spell(&spin, wfname) == FAIL; + + spell_message(&spin, (char_u *)_("Done!")); + vim_snprintf((char *)IObuff, IOSIZE, + _("Estimated runtime memory use: %d bytes"), spin.si_memtot); + spell_message(&spin, IObuff); + + // If the file is loaded need to reload it. + if (!error) + spell_reload_one(wfname, added_word); + } + + // Free the allocated memory. + ga_clear(&spin.si_rep); + ga_clear(&spin.si_repsal); + ga_clear(&spin.si_sal); + ga_clear(&spin.si_map); + ga_clear(&spin.si_comppat); + ga_clear(&spin.si_prefcond); + hash_clear_all(&spin.si_commonwords, 0); + + // Free the .aff file structures. + for (i = 0; i < incount; ++i) + if (afile[i] != NULL) + spell_free_aff(afile[i]); + + // Free all the bits and pieces at once. + free_blocks(spin.si_blocks); + + // If there is soundfolding info and no NOSUGFILE item create the + // .sug file with the soundfolded word trie. + if (spin.si_sugtime != 0 && !error && !got_int) + spell_make_sugfile(&spin, wfname); + + } + +theend: + xfree(fname); + xfree(wfname); +} + +// Display a message for spell file processing when 'verbose' is set or using +// ":mkspell". "str" can be IObuff. +static void spell_message(spellinfo_T *spin, char_u *str) +{ + if (spin->si_verbose || p_verbose > 2) { + if (!spin->si_verbose) + verbose_enter(); + MSG(str); + ui_flush(); + if (!spin->si_verbose) + verbose_leave(); + } +} + +// ":[count]spellgood {word}" +// ":[count]spellwrong {word}" +// ":[count]spellundo {word}" +void ex_spell(exarg_T *eap) +{ + spell_add_word(eap->arg, (int)STRLEN(eap->arg), eap->cmdidx == CMD_spellwrong, + eap->forceit ? 0 : (int)eap->line2, + eap->cmdidx == CMD_spellundo); +} + +// Add "word[len]" to 'spellfile' as a good or bad word. +void +spell_add_word ( + char_u *word, + int len, + int bad, + int idx, // "zG" and "zW": zero, otherwise index in + // 'spellfile' + bool undo // true for "zug", "zuG", "zuw" and "zuW" +) +{ + FILE *fd = NULL; + buf_T *buf = NULL; + bool new_spf = false; + char_u *fname; + char_u *fnamebuf = NULL; + char_u line[MAXWLEN * 2]; + long fpos, fpos_next = 0; + int i; + char_u *spf; + + if (idx == 0) { // use internal wordlist + if (int_wordlist == NULL) { + int_wordlist = vim_tempname(); + if (int_wordlist == NULL) + return; + } + fname = int_wordlist; + } else { + // If 'spellfile' isn't set figure out a good default value. + if (*curwin->w_s->b_p_spf == NUL) { + init_spellfile(); + new_spf = true; + } + + if (*curwin->w_s->b_p_spf == NUL) { + EMSG2(_(e_notset), "spellfile"); + return; + } + fnamebuf = xmalloc(MAXPATHL); + + for (spf = curwin->w_s->b_p_spf, i = 1; *spf != NUL; ++i) { + copy_option_part(&spf, fnamebuf, MAXPATHL, ","); + if (i == idx) + break; + if (*spf == NUL) { + EMSGN(_("E765: 'spellfile' does not have %" PRId64 " entries"), idx); + xfree(fnamebuf); + return; + } + } + + // Check that the user isn't editing the .add file somewhere. + buf = buflist_findname_exp(fnamebuf); + if (buf != NULL && buf->b_ml.ml_mfp == NULL) + buf = NULL; + if (buf != NULL && bufIsChanged(buf)) { + EMSG(_(e_bufloaded)); + xfree(fnamebuf); + return; + } + + fname = fnamebuf; + } + + if (bad || undo) { + // When the word appears as good word we need to remove that one, + // since its flags sort before the one with WF_BANNED. + fd = mch_fopen((char *)fname, "r"); + if (fd != NULL) { + while (!vim_fgets(line, MAXWLEN * 2, fd)) { + fpos = fpos_next; + fpos_next = ftell(fd); + if (STRNCMP(word, line, len) == 0 + && (line[len] == '/' || line[len] < ' ')) { + // Found duplicate word. Remove it by writing a '#' at + // the start of the line. Mixing reading and writing + // doesn't work for all systems, close the file first. + fclose(fd); + fd = mch_fopen((char *)fname, "r+"); + if (fd == NULL) + break; + if (fseek(fd, fpos, SEEK_SET) == 0) { + fputc('#', fd); + if (undo) { + home_replace(NULL, fname, NameBuff, MAXPATHL, TRUE); + smsg(_("Word '%.*s' removed from %s"), + len, word, NameBuff); + } + } + fseek(fd, fpos_next, SEEK_SET); + } + } + if (fd != NULL) + fclose(fd); + } + } + + if (!undo) { + fd = mch_fopen((char *)fname, "a"); + if (fd == NULL && new_spf) { + char_u *p; + + // We just initialized the 'spellfile' option and can't open the + // file. We may need to create the "spell" directory first. We + // already checked the runtime directory is writable in + // init_spellfile(). + if (!dir_of_file_exists(fname) && (p = path_tail_with_sep(fname)) != fname) { + int c = *p; + + // The directory doesn't exist. Try creating it and opening + // the file again. + *p = NUL; + os_mkdir((char *)fname, 0755); + *p = c; + fd = mch_fopen((char *)fname, "a"); + } + } + + if (fd == NULL) + EMSG2(_(e_notopen), fname); + else { + if (bad) + fprintf(fd, "%.*s/!\n", len, word); + else + fprintf(fd, "%.*s\n", len, word); + fclose(fd); + + home_replace(NULL, fname, NameBuff, MAXPATHL, TRUE); + smsg(_("Word '%.*s' added to %s"), len, word, NameBuff); + } + } + + if (fd != NULL) { + // Update the .add.spl file. + mkspell(1, &fname, false, true, true); + + // If the .add file is edited somewhere, reload it. + if (buf != NULL) + buf_reload(buf, buf->b_orig_mode); + + redraw_all_later(SOME_VALID); + } + xfree(fnamebuf); +} + +// Initialize 'spellfile' for the current buffer. +static void init_spellfile(void) +{ + char_u *buf; + int l; + char_u *fname; + char_u *rtp; + char_u *lend; + bool aspath = false; + char_u *lstart = 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 = curwin->w_s->b_p_spl; *lend != NUL + && vim_strchr((char_u *)",._", *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 = p_rtp; + while (*rtp != NUL) { + if (aspath) + // Use directory of an entry with path, e.g., for + // "/dir/lg.utf-8.spl" use "/dir". + STRLCPY(buf, curbuf->b_s.b_p_spl, + 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((char *)buf) == 2) { + // Use the first language name from 'spelllang' and the + // encoding used in the first loaded .spl file. + if (aspath) + STRLCPY(buf, curbuf->b_s.b_p_spl, + lend - curbuf->b_s.b_p_spl + 1); + else { + // Create the "spell" directory if it doesn't exist yet. + l = (int)STRLEN(buf); + vim_snprintf((char *)buf + l, MAXPATHL - l, "/spell"); + if (os_file_is_writable((char *)buf) != 2) { + os_mkdir((char *)buf, 0755); + } + + l = (int)STRLEN(buf); + vim_snprintf((char *)buf + l, MAXPATHL - l, + "/%.*s", (int)(lend - lstart), lstart); + } + l = (int)STRLEN(buf); + fname = LANGP_ENTRY(curwin->w_s->b_langp, 0) + ->lp_slang->sl_fname; + vim_snprintf((char *)buf + l, MAXPATHL - l, ".%s.add", + ((fname != NULL + && strstr((char *)path_tail(fname), ".ascii.") != NULL) + ? "ascii" + : (const char *)spell_enc())); + set_option_value("spellfile", 0L, (const char *)buf, OPT_LOCAL); + break; + } + aspath = false; + } + + xfree(buf); + } +} + +// Set the spell character tables from strings in the affix file. +static int set_spell_chartab(char_u *fol, char_u *low, char_u *upp) +{ + // We build the new tables here first, so that we can compare with the + // previous one. + spelltab_T new_st; + char_u *pf = fol, *pl = low, *pu = upp; + int f, l, u; + + clear_spell_chartab(&new_st); + + while (*pf != NUL) { + if (*pl == NUL || *pu == NUL) { + EMSG(_(e_affform)); + return FAIL; + } + f = mb_ptr2char_adv((const char_u **)&pf); + l = mb_ptr2char_adv((const char_u **)&pl); + u = mb_ptr2char_adv((const char_u **)&pu); + // Every character that appears is a word character. + if (f < 256) + new_st.st_isw[f] = true; + if (l < 256) + new_st.st_isw[l] = true; + if (u < 256) + new_st.st_isw[u] = true; + + // if "LOW" and "FOL" are not the same the "LOW" char needs + // case-folding + if (l < 256 && l != f) { + if (f >= 256) { + EMSG(_(e_affrange)); + return FAIL; + } + new_st.st_fold[l] = f; + } + + // if "UPP" and "FOL" are not the same the "UPP" char needs + // case-folding, it's upper case and the "UPP" is the upper case of + // "FOL" . + if (u < 256 && u != f) { + if (f >= 256) { + EMSG(_(e_affrange)); + return FAIL; + } + new_st.st_fold[u] = f; + new_st.st_isu[u] = true; + new_st.st_upper[f] = u; + } + } + + if (*pl != NUL || *pu != NUL) { + EMSG(_(e_affform)); + return FAIL; + } + + return set_spell_finish(&new_st); +} + +// Set the spell character tables from strings in the .spl file. +static void +set_spell_charflags ( + char_u *flags, + int cnt, // length of "flags" + char_u *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; + int c; + + clear_spell_chartab(&new_st); + + for (i = 0; i < 128; ++i) { + if (i < cnt) { + new_st.st_isw[i + 128] = (flags[i] & CF_WORD) != 0; + new_st.st_isu[i + 128] = (flags[i] & CF_UPPER) != 0; + } + + if (*p != NUL) { + c = mb_ptr2char_adv((const char_u **)&p); + new_st.st_fold[i + 128] = c; + if (i + 128 != c && new_st.st_isu[i + 128] && c < 256) + new_st.st_upper[c] = i + 128; + } + } + + (void)set_spell_finish(&new_st); +} + +static int set_spell_finish(spelltab_T *new_st) +{ + int i; + + if (did_set_spelltab) { + // check that it's the same table + for (i = 0; i < 256; ++i) { + if (spelltab.st_isw[i] != new_st->st_isw[i] + || spelltab.st_isu[i] != new_st->st_isu[i] + || spelltab.st_fold[i] != new_st->st_fold[i] + || spelltab.st_upper[i] != new_st->st_upper[i]) { + EMSG(_("E763: Word characters differ between spell files")); + return FAIL; + } + } + } else { + // copy the new spelltab into the one being used + spelltab = *new_st; + did_set_spelltab = true; + } + + return OK; +} + +// Write the table with prefix conditions to the .spl file. +// When "fd" is NULL only count the length of what is written. +static int write_spell_prefcond(FILE *fd, garray_T *gap) +{ + assert(gap->ga_len >= 0); + + if (fd != NULL) + put_bytes(fd, (uintmax_t)gap->ga_len, 2); // <prefcondcnt> + + size_t totlen = 2 + (size_t)gap->ga_len; // <prefcondcnt> and <condlen> bytes + size_t x = 1; // collect return value of fwrite() + for (int i = 0; i < gap->ga_len; ++i) { + // <prefcond> : <condlen> <condstr> + char_u *p = ((char_u **)gap->ga_data)[i]; + if (p != NULL) { + size_t len = STRLEN(p); + if (fd != NULL) { + assert(len <= INT_MAX); + fputc((int)len, fd); + x &= fwrite(p, len, 1, fd); + } + totlen += len; + } else if (fd != NULL) + fputc(0, fd); + } + + assert(totlen <= INT_MAX); + return (int)totlen; +} + +// Use map string "map" for languages "lp". +static void set_map_str(slang_T *lp, char_u *map) +{ + char_u *p; + int headc = 0; + int c; + int i; + + if (*map == NUL) { + lp->sl_has_map = false; + return; + } + lp->sl_has_map = true; + + // Init the array and hash tables empty. + for (i = 0; i < 256; ++i) + lp->sl_map_array[i] = 0; + hash_init(&lp->sl_map_hash); + + // The similar characters are stored separated with slashes: + // "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); + if (c == '/') { + headc = 0; + } else { + if (headc == 0) { + headc = c; + } + + // Characters above 255 don't fit in sl_map_array[], put them in + // the hash table. Each entry is the char, a NUL the headchar and + // a NUL. + if (c >= 256) { + int cl = mb_char2len(c); + int headcl = mb_char2len(headc); + char_u *b; + hash_T hash; + hashitem_T *hi; + + b = xmalloc(cl + headcl + 2); + mb_char2bytes(c, b); + b[cl] = NUL; + mb_char2bytes(headc, b + cl + 1); + b[cl + 1 + headcl] = NUL; + 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, b, hash); + } else { + // This should have been checked when generating the .spl + // file. + EMSG(_("E783: duplicate char in MAP entry")); + xfree(b); + } + } else + lp->sl_map_array[c] = headc; + } + } +} + diff --git a/src/nvim/spellfile.h b/src/nvim/spellfile.h new file mode 100644 index 0000000000..633ee014a7 --- /dev/null +++ b/src/nvim/spellfile.h @@ -0,0 +1,13 @@ +#ifndef NVIM_SPELLFILE_H +#define NVIM_SPELLFILE_H + +#include <stdbool.h> + +#include "nvim/spell_defs.h" +#include "nvim/types.h" +#include "nvim/ex_cmds_defs.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "spellfile.h.generated.h" +#endif +#endif // NVIM_SPELLFILE_H diff --git a/src/nvim/state.c b/src/nvim/state.c index 44c6441e40..eb0b590a9b 100644 --- a/src/nvim/state.c +++ b/src/nvim/state.c @@ -1,8 +1,12 @@ +// 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 "nvim/lib/kvec.h" #include "nvim/ascii.h" +#include "nvim/log.h" #include "nvim/state.h" #include "nvim/vim.h" #include "nvim/main.h" @@ -95,3 +99,52 @@ int get_real_state(void) return State; } +/// @returns[allocated] mode string +char *get_mode(void) +{ + char *buf = xcalloc(3, sizeof(char)); + + if (VIsual_active) { + if (VIsual_select) { + buf[0] = (char)(VIsual_mode + 's' - 'v'); + } else { + buf[0] = (char)VIsual_mode; + } + } else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE + || State == CONFIRM) { + buf[0] = 'r'; + if (State == ASKMORE) { + buf[1] = 'm'; + } else if (State == CONFIRM) { + buf[1] = '?'; + } + } else if (State == EXTERNCMD) { + buf[0] = '!'; + } else if (State & INSERT) { + if (State & VREPLACE_FLAG) { + buf[0] = 'R'; + buf[1] = 'v'; + } else if (State & REPLACE_FLAG) { + buf[0] = 'R'; + } else { + buf[0] = 'i'; + } + } else if (State & CMDLINE) { + buf[0] = 'c'; + if (exmode_active) { + buf[1] = 'v'; + } + } else if (exmode_active) { + buf[0] = 'c'; + buf[1] = 'e'; + } else if (State & TERM_FOCUS) { + buf[0] = 't'; + } else { + buf[0] = 'n'; + if (finish_op) { + buf[1] = 'o'; + } + } + + return buf; +} diff --git a/src/nvim/strings.c b/src/nvim/strings.c index c1800a0639..687f734742 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -1,7 +1,14 @@ +// 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 <inttypes.h> +#include <stdarg.h> #include <stdbool.h> #include <string.h> +#include <math.h> +#include <assert.h> +#include "nvim/assert.h" #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/strings.h" @@ -41,6 +48,7 @@ #include "nvim/window.h" #include "nvim/os/os.h" #include "nvim/os/shell.h" +#include "nvim/eval/encode.h" /* * Copy "string" into newly allocated memory. @@ -51,15 +59,14 @@ char_u *vim_strsave(const char_u *string) return (char_u *)xstrdup((char *)string); } -/* - * Copy up to "len" bytes of "string" into newly allocated memory and - * terminate with a NUL. - * The allocated memory always has size "len + 1", also when "string" is - * shorter. - */ +/// Copy up to `len` bytes of `string` into newly allocated memory and +/// terminate with a NUL. The allocated memory always has size `len + 1`, even +/// when `string` is shorter. char_u *vim_strnsave(const char_u *string, size_t len) FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { + // strncpy is intentional: some parts of Vim use `string` shorter than `len` + // and expect the remainder to be zeroed out. return (char_u *)strncpy(xmallocz(len), (char *)string, len); } @@ -194,8 +201,16 @@ char_u *vim_strsave_shellescape(const char_u *string, /* 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 = string; *p != NUL; mb_ptr_adv(p)) { - if (*p == '\'') - length += 3; /* ' => '\'' */ +#ifdef WIN32 + if (!p_ssl) { + if (*p == '"') { + length++; // " -> "" + } + } else +#endif + if (*p == '\'') { + length += 3; // ' => '\'' + } if ((*p == '\n' && (csh_like || do_newline)) || (*p == '!' && (csh_like || do_special))) { ++length; /* insert backslash */ @@ -212,10 +227,25 @@ char_u *vim_strsave_shellescape(const char_u *string, escaped_string = xmalloc(length); d = escaped_string; - /* add opening quote */ + // add opening quote +#ifdef WIN32 + if (!p_ssl) { + *d++ = '"'; + } else +#endif *d++ = '\''; for (const char_u *p = string; *p != NUL; ) { +#ifdef WIN32 + if (!p_ssl) { + if (*p == '"') { + *d++ = '"'; + *d++ = '"'; + p++; + continue; + } + } else +#endif if (*p == '\'') { *d++ = '\''; *d++ = '\\'; @@ -242,7 +272,12 @@ char_u *vim_strsave_shellescape(const char_u *string, MB_COPY_CHAR(p, d); } - /* add terminating quote and finish with a NUL */ + // add terminating quote and finish with a NUL +# ifdef WIN32 + if (!p_ssl) { + *d++ = '"'; + } else +# endif *d++ = '\''; *d = NUL; @@ -287,45 +322,42 @@ void vim_strup(char_u *p) } } -/* - * Make string "s" all upper-case and return it in allocated memory. - * Handles multi-byte characters as well as possible. - */ -char_u *strup_save(const char_u *orig) +/// Make given string all upper-case or all lower-case +/// +/// Handles multi-byte characters as good as possible. +/// +/// @param[in] orig Input string. +/// @param[in] upper If true make uppercase, otherwise lowercase +/// +/// @return [allocated] upper-cased string. +char *strcase_save(const char *const orig, bool upper) FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { - char_u *res = vim_strsave(orig); + char *res = xstrdup(orig); - char_u *p = res; + char *p = res; while (*p != NUL) { int l; - if (enc_utf8) { - int c = utf_ptr2char(p); - int uc = utf_toupper(c); - - /* Reallocate string when byte count changes. This is rare, - * thus it's OK to do another malloc()/free(). */ - l = utf_ptr2len(p); - int newl = utf_char2len(uc); - if (newl != l) { - // TODO(philix): use xrealloc() in strup_save() - char_u *s = xmalloc(STRLEN(res) + (size_t)(1 + newl - l)); - memcpy(s, res, (size_t)(p - res)); - STRCPY(s + (p - res) + newl, p + l); - p = s + (p - res); - xfree(res); - res = s; - } + int c = utf_ptr2char((const char_u *)p); + int uc = upper ? mb_toupper(c) : mb_tolower(c); - utf_char2bytes(uc, p); - p += newl; - } else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) - p += l; /* skip multi-byte character */ - else { - *p = (char_u) TOUPPER_LOC(*p); // note that toupper() can be a macro - p++; + // Reallocate string when byte count changes. This is rare, + // thus it's OK to do another malloc()/free(). + l = utf_ptr2len((const char_u *)p); + int newl = utf_char2len(uc); + if (newl != l) { + // TODO(philix): use xrealloc() in strup_save() + char *s = xmalloc(STRLEN(res) + (size_t)(1 + newl - l)); + memcpy(s, res, (size_t)(p - res)); + STRCPY(s + (p - res) + newl, p + l); + p = s + (p - res); + xfree(res); + res = s; } + + utf_char2bytes(uc, (char_u *)p); + p += newl; } return res; @@ -344,24 +376,6 @@ void del_trailing_spaces(char_u *ptr) *q = NUL; } -/* - * Like strcat(), but make sure the result fits in "tosize" bytes and is - * always NUL terminated. - */ -void vim_strcat(char_u *restrict to, const char_u *restrict from, - size_t tosize) - FUNC_ATTR_NONNULL_ALL -{ - size_t tolen = STRLEN(to); - size_t fromlen = STRLEN(from); - - if (tolen + fromlen + 1 > tosize) { - memcpy(to + tolen, from, tosize - tolen - 1); - to[tosize - 1] = NUL; - } else - STRCPY(to + tolen, from); -} - #if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)) /* * Compare two strings, ignoring case, using current locale. @@ -411,72 +425,27 @@ int vim_strnicmp(const char *s1, const char *s2, size_t len) } #endif -/* - * Version of strchr() and strrchr() that handle unsigned char strings - * with characters from 128 to 255 correctly. It also doesn't return a - * pointer to the NUL at the end of the string. - */ -char_u *vim_strchr(const char_u *string, int c) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE +/// strchr() version which handles multibyte strings +/// +/// @param[in] string String to search in. +/// @param[in] c Character to search for. +/// +/// @return Pointer to the first byte of the found character in string or NULL +/// if it was not found or character is invalid. NUL character is never +/// found, use `strlen()` instead. +char_u *vim_strchr(const char_u *const string, const int c) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { - int b; - - const char_u *p = string; - if (enc_utf8 && c >= 0x80) { - while (*p != NUL) { - int l = (*mb_ptr2len)(p); - - // Avoid matching an illegal byte here. - if (l > 1 && utf_ptr2char(p) == c) { - return (char_u *) p; - } - p += l; - } + if (c <= 0) { return NULL; + } else if (c < 0x80) { + return (char_u *)strchr((const char *)string, c); + } else { + char u8char[MB_MAXBYTES + 1]; + const int len = utf_char2bytes(c, (char_u *)u8char); + u8char[len] = NUL; + return (char_u *)strstr((const char *)string, u8char); } - if (enc_dbcs != 0 && c > 255) { - int n2 = c & 0xff; - - c = ((unsigned)c >> 8) & 0xff; - while ((b = *p) != NUL) { - if (b == c && p[1] == n2) - return (char_u *) p; - p += (*mb_ptr2len)(p); - } - return NULL; - } - if (has_mbyte) { - while ((b = *p) != NUL) { - if (b == c) - return (char_u *) p; - p += (*mb_ptr2len)(p); - } - return NULL; - } - while ((b = *p) != NUL) { - if (b == c) - return (char_u *) p; - ++p; - } - return NULL; -} - -/* - * Version of strchr() that only works for bytes and handles unsigned char - * strings with characters above 128 correctly. It also doesn't return a - * pointer to the NUL at the end of the string. - */ -char_u *vim_strbyte(const char_u *string, int c) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE -{ - const char_u *p = string; - - while (*p != NUL) { - if (*p == c) - return (char_u *) p; - ++p; - } - return NULL; } /* @@ -560,3 +529,905 @@ char_u *concat_str(const char_u *restrict str1, const char_u *restrict str2) return dest; } + +static const char *const e_printf = + N_("E766: Insufficient arguments for printf()"); + +/// Get number argument from idxp entry in tvs +/// +/// Will give an error message for VimL entry with invalid type or for +/// insufficient entries. +/// +/// @param[in] tvs List of VimL values. List is terminated by VAR_UNKNOWN +/// value. +/// @param[in,out] idxp Index in a list. Will be incremented. Indexing starts +/// at 1. +/// +/// @return Number value or 0 in case of error. +static varnumber_T tv_nr(typval_T *tvs, int *idxp) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + int idx = *idxp - 1; + varnumber_T n = 0; + + if (tvs[idx].v_type == VAR_UNKNOWN) { + EMSG(_(e_printf)); + } else { + (*idxp)++; + bool err = false; + n = tv_get_number_chk(&tvs[idx], &err); + if (err) { + n = 0; + } + } + return n; +} + +/// Get string argument from idxp entry in tvs +/// +/// Will give an error message for VimL entry with invalid type or for +/// insufficient entries. +/// +/// @param[in] tvs List of VimL values. List is terminated by VAR_UNKNOWN +/// value. +/// @param[in,out] idxp Index in a list. Will be incremented. +/// @param[out] tofree If the idxp entry in tvs is not a String or a Number, +/// it will be converted to String in the same format +/// as ":echo" and stored in "*tofree". The caller must +/// free "*tofree". +/// +/// @return String value or NULL in case of error. +static const char *tv_str(typval_T *tvs, int *idxp, char **const tofree) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + int idx = *idxp - 1; + const char *s = NULL; + + if (tvs[idx].v_type == VAR_UNKNOWN) { + EMSG(_(e_printf)); + } else { + (*idxp)++; + if (tvs[idx].v_type == VAR_STRING || tvs[idx].v_type == VAR_NUMBER) { + s = tv_get_string_chk(&tvs[idx]); + *tofree = NULL; + } else { + s = *tofree = encode_tv2echo(&tvs[idx], NULL); + } + } + return s; +} + +/// Get pointer argument from the next entry in tvs +/// +/// Will give an error message for VimL entry with invalid type or for +/// insufficient entries. +/// +/// @param[in] tvs List of typval_T values. +/// @param[in,out] idxp Pointer to the index of the current value. +/// +/// @return Pointer stored in typval_T or NULL. +static const void *tv_ptr(const typval_T *const tvs, int *const idxp) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ +#define OFF(attr) offsetof(union typval_vval_union, attr) + STATIC_ASSERT( + OFF(v_string) == OFF(v_list) + && OFF(v_string) == OFF(v_dict) + && OFF(v_string) == OFF(v_partial) + && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_list) + && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_dict) + && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_partial), + "Strings, dictionaries, lists and partials are expected to be pointers, " + "so that all three of them can be accessed via v_string"); +#undef OFF + const int idx = *idxp - 1; + if (tvs[idx].v_type == VAR_UNKNOWN) { + EMSG(_(e_printf)); + return NULL; + } else { + (*idxp)++; + return tvs[idx].vval.v_string; + } +} + +/// Get float argument from idxp entry in tvs +/// +/// Will give an error message for VimL entry with invalid type or for +/// insufficient entries. +/// +/// @param[in] tvs List of VimL values. List is terminated by VAR_UNKNOWN +/// value. +/// @param[in,out] idxp Index in a list. Will be incremented. +/// +/// @return Floating-point value or zero in case of error. +static float_T tv_float(typval_T *const tvs, int *const idxp) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + int idx = *idxp - 1; + float_T f = 0; + + if (tvs[idx].v_type == VAR_UNKNOWN) { + EMSG(_(e_printf)); + } else { + (*idxp)++; + if (tvs[idx].v_type == VAR_FLOAT) { + f = tvs[idx].vval.v_float; + } else if (tvs[idx].v_type == VAR_NUMBER) { + f = (float_T)tvs[idx].vval.v_number; + } else { + EMSG(_("E807: Expected Float argument for printf()")); + } + } + return f; +} + +// This code was included to provide a portable vsnprintf() and snprintf(). +// Some systems may provide their own, but we always use this one for +// consistency. +// +// This code is based on snprintf.c - a portable implementation of snprintf +// by Mark Martinec <mark.martinec@ijs.si>, Version 2.2, 2000-10-06. +// Included with permission. It was heavily modified to fit in Vim. +// The original code, including useful comments, can be found here: +// +// http://www.ijs.si/software/snprintf/ +// +// This snprintf() only supports the following conversion specifiers: +// s, c, b, B, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) +// with flags: '-', '+', ' ', '0' and '#'. +// An asterisk is supported for field width as well as precision. +// +// Limited support for floating point was added: 'f', 'e', 'E', 'g', 'G'. +// +// Length modifiers 'h' (short int), 'l' (long int) and "ll" (long long int) are +// supported. +// +// The locale is not used, the string is used as a byte string. This is only +// relevant for double-byte encodings where the second byte may be '%'. +// +// It is permitted for "str_m" to be zero, and it is permitted to specify NULL +// pointer for resulting string argument if "str_m" is zero (as per ISO C99). +// +// The return value is the number of characters which would be generated +// for the given input, excluding the trailing NUL. If this value +// is greater or equal to "str_m", not all characters from the result +// have been stored in str, output bytes beyond the ("str_m"-1) -th character +// are discarded. If "str_m" is greater than zero it is guaranteed +// the resulting string will be NUL-terminated. + +// vim_vsnprintf() can be invoked with either "va_list" or a list of +// "typval_T". When the latter is not used it must be NULL. + +/// Append a formatted value to the string +/// +/// @see vim_vsnprintf(). +int vim_snprintf_add(char *str, size_t str_m, char *fmt, ...) +{ + const size_t len = strlen(str); + size_t space; + + if (str_m <= len) { + space = 0; + } else { + space = str_m - len; + } + va_list ap; + va_start(ap, fmt); + const int str_l = vim_vsnprintf(str + len, space, fmt, ap, NULL); + va_end(ap); + return str_l; +} + +/// Write formatted value to the string +/// +/// @param[out] str String to write to. +/// @param[in] str_m String length. +/// @param[in] fmt String format. +/// +/// @return Number of bytes excluding NUL byte that would be written to the +/// string if str_m was greater or equal to the return value. +int vim_snprintf(char *str, size_t str_m, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + const int str_l = vim_vsnprintf(str, str_m, fmt, ap, NULL); + va_end(ap); + return str_l; +} + +// Return the representation of infinity for printf() function: +// "-inf", "inf", "+inf", " inf", "-INF", "INF", "+INF" or " INF". +static const char *infinity_str(bool positive, char fmt_spec, + int force_sign, int space_for_positive) +{ + static const char *table[] = { + "-inf", "inf", "+inf", " inf", + "-INF", "INF", "+INF", " INF" + }; + int idx = positive * (1 + force_sign + force_sign * space_for_positive); + if (ASCII_ISUPPER(fmt_spec)) { + idx += 4; + } + return table[idx]; +} + + +/// Write formatted value to the string +/// +/// @param[out] str String to write to. +/// @param[in] str_m String length. +/// @param[in] fmt String format. +/// @param[in] ap Values that should be formatted. Ignored if tvs is not NULL. +/// @param[in] tvs Values that should be formatted, for printf() VimL +/// function. Must be NULL in other cases. +/// +/// @return Number of bytes excluding NUL byte that would be written to the +/// string if str_m was greater or equal to the return value. +int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, + typval_T *const tvs) +{ + size_t str_l = 0; + bool str_avail = str_l < str_m; + const char *p = fmt; + int arg_idx = 1; + + if (!p) { + p = ""; + } + while (*p) { + if (*p != '%') { + // copy up to the next '%' or NUL without any changes + size_t n = (size_t)(xstrchrnul(p + 1, '%') - p); + if (str_avail) { + size_t avail = str_m - str_l; + memmove(str + str_l, p, MIN(n, avail)); + str_avail = n < avail; + } + p += n; + assert(n <= SIZE_MAX - str_l); + str_l += n; + } else { + size_t min_field_width = 0, precision = 0; + int zero_padding = 0, precision_specified = 0, justify_left = 0; + int alternate_form = 0, force_sign = 0; + + // if both ' ' and '+' flags appear, ' ' flag should be ignored + int space_for_positive = 1; + + // allowed values: \0, h, l, 2 (for ll), z, L + char length_modifier = '\0'; + + // temporary buffer for simple numeric->string conversion +# define TMP_LEN 350 // 1e308 seems reasonable as the maximum printable + char tmp[TMP_LEN]; + + // string address in case of string argument + const char *str_arg = NULL; + + // natural field width of arg without padding and sign + size_t str_arg_l; + + // unsigned char argument value (only defined for c conversion); + // standard explicitly states the char argument for the c + // conversion is unsigned + unsigned char uchar_arg; + + // number of zeros to be inserted for numeric conversions as + // required by the precision or minimal field width + size_t number_of_zeros_to_pad = 0; + + // index into tmp where zero padding is to be inserted + size_t zero_padding_insertion_ind = 0; + + // current conversion specifier character + char fmt_spec = '\0'; + + // buffer for 's' and 'S' specs + char *tofree = NULL; + + p++; // skip '%' + + // parse flags + while (true) { + switch (*p) { + case '0': zero_padding = 1; p++; continue; + case '-': justify_left = 1; p++; continue; + // if both '0' and '-' flags appear, '0' should be ignored + case '+': force_sign = 1; space_for_positive = 0; p++; continue; + case ' ': force_sign = 1; p++; continue; + // if both ' ' and '+' flags appear, ' ' should be ignored + case '#': alternate_form = 1; p++; continue; + case '\'': p++; continue; + default: break; + } + break; + } + + // parse field width + if (*p == '*') { + p++; + const int j = tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int); + if (j >= 0) { + min_field_width = (size_t)j; + } else { + min_field_width = (size_t)-j; + justify_left = 1; + } + } else if (ascii_isdigit((int)(*p))) { + // size_t could be wider than unsigned int; make sure we treat + // argument like common implementations do + unsigned int uj = (unsigned)(*p++ - '0'); + + while (ascii_isdigit((int)(*p))) { + uj = 10 * uj + (unsigned int)(*p++ - '0'); + } + min_field_width = uj; + } + + // parse precision + if (*p == '.') { + p++; + precision_specified = 1; + if (*p == '*') { + const int j = tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int); + p++; + if (j >= 0) { + precision = (size_t)j; + } else { + precision_specified = 0; + precision = 0; + } + } else if (ascii_isdigit((int)(*p))) { + // size_t could be wider than unsigned int; make sure we + // treat argument like common implementations do + unsigned int uj = (unsigned)(*p++ - '0'); + + while (ascii_isdigit((int)(*p))) { + uj = 10 * uj + (unsigned int)(*p++ - '0'); + } + precision = uj; + } + } + + // parse 'h', 'l', 'll' and 'z' length modifiers + if (*p == 'h' || *p == 'l' || *p == 'z') { + length_modifier = *p; + p++; + if (length_modifier == 'l' && *p == 'l') { // ll, encoded as 2 + length_modifier = '2'; + p++; + } + } + + fmt_spec = *p; + + // common synonyms + switch (fmt_spec) { + case 'i': fmt_spec = 'd'; break; + case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; + case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; + case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; + default: break; + } + + switch (fmt_spec) { + case 'd': case 'u': case 'o': case 'x': case 'X': + if (tvs && length_modifier == '\0') { + length_modifier = '2'; + } + } + + // get parameter value, do initial processing + switch (fmt_spec) { + // '%' and 'c' behave similar to 's' regarding flags and field widths + case '%': case 'c': case 's': case 'S': + str_arg_l = 1; + switch (fmt_spec) { + case '%': + str_arg = p; + break; + + case 'c': { + const int j = tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int); + // standard demands unsigned char + uchar_arg = (unsigned char)j; + str_arg = (char *)&uchar_arg; + break; + } + + case 's': + case 'S': + str_arg = tvs ? tv_str(tvs, &arg_idx, &tofree) + : va_arg(ap, const char *); + if (!str_arg) { + str_arg = "[NULL]"; + str_arg_l = 6; + } else if (!precision_specified) { + // make sure not to address string beyond the specified + // precision + str_arg_l = strlen(str_arg); + } else if (precision == 0) { + // truncate string if necessary as requested by precision + str_arg_l = 0; + } else { + // memchr on HP does not like n > 2^31 + // TODO(elmart): check if this still holds / is relevant + str_arg_l = (size_t)((char *)xmemscan(str_arg, + NUL, + MIN(precision, + 0x7fffffff)) + - str_arg); + } + if (fmt_spec == 'S') { + if (min_field_width != 0) { + min_field_width += (strlen(str_arg) + - mb_string2cells((char_u *)str_arg)); + } + if (precision) { + const char *p1 = str_arg; + for (size_t i = 0; i < precision && *p1; i++) { + p1 += mb_ptr2len((const char_u *)p1); + } + str_arg_l = precision = (size_t)(p1 - str_arg); + } + } + break; + + default: + break; + } + break; + + case 'd': + case 'u': + case 'b': case 'B': + case 'o': + case 'x': case 'X': + case 'p': { + // u, b, B, o, x, X and p conversion specifiers imply + // the value is unsigned; d implies a signed value + + // 0 if numeric argument is zero (or if pointer is NULL for 'p'), + // +1 if greater than zero (or non NULL for 'p'), + // -1 if negative (unsigned argument is never negative) + int arg_sign = 0; + + intmax_t arg = 0; + uintmax_t uarg = 0; + + // only defined for p conversion + const void *ptr_arg = NULL; + + if (fmt_spec == 'p') { + ptr_arg = tvs ? tv_ptr(tvs, &arg_idx) : va_arg(ap, void *); + if (ptr_arg) { + arg_sign = 1; + } + } else if (fmt_spec == 'd') { + // signed + switch (length_modifier) { + case '\0': + case 'h': { + // char and short arguments are passed as int + arg = (tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int)); + break; + } + case 'l': { + arg = (tvs ? (long)tv_nr(tvs, &arg_idx) : va_arg(ap, long)); + break; + } + case '2': { + arg = ( + tvs + ? (long long)tv_nr(tvs, &arg_idx) // NOLINT (runtime/int) + : va_arg(ap, long long)); // NOLINT (runtime/int) + break; + } + case 'z': { + arg = (tvs + ? (ptrdiff_t)tv_nr(tvs, &arg_idx) + : va_arg(ap, ptrdiff_t)); + break; + } + } + if (arg > 0) { + arg_sign = 1; + } else if (arg < 0) { + arg_sign = -1; + } + } else { + // unsigned + switch (length_modifier) { + case '\0': + case 'h': { + uarg = (tvs + ? (unsigned)tv_nr(tvs, &arg_idx) + : va_arg(ap, unsigned)); + break; + } + case 'l': { + uarg = (tvs + ? (unsigned long)tv_nr(tvs, &arg_idx) + : va_arg(ap, unsigned long)); + break; + } + case '2': { + uarg = (uintmax_t)(unsigned long long)( // NOLINT (runtime/int) + tvs + ? ((unsigned long long) // NOLINT (runtime/int) + tv_nr(tvs, &arg_idx)) + : va_arg(ap, unsigned long long)); // NOLINT (runtime/int) + break; + } + case 'z': { + uarg = (tvs + ? (size_t)tv_nr(tvs, &arg_idx) + : va_arg(ap, size_t)); + break; + } + } + arg_sign = (uarg != 0); + } + + str_arg = tmp; + str_arg_l = 0; + + // For d, i, u, o, x, and X conversions, if precision is specified, + // '0' flag should be ignored. This is so with Solaris 2.6, Digital + // UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl. + if (precision_specified) { + zero_padding = 0; + } + + if (fmt_spec == 'd') { + if (force_sign && arg_sign >= 0) { + tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; + } + // leave negative numbers for snprintf to handle, to + // avoid handling tricky cases like (short int)-32768 + } else if (alternate_form) { + if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X' + || fmt_spec == 'b' || fmt_spec == 'B')) { + tmp[str_arg_l++] = '0'; + tmp[str_arg_l++] = fmt_spec; + } + // alternate form should have no effect for p * conversion, but ... + } + + zero_padding_insertion_ind = str_arg_l; + if (!precision_specified) { + precision = 1; // default precision is 1 + } + if (precision == 0 && arg_sign == 0) { + // when zero value is formatted with an explicit precision 0, + // resulting formatted string is empty (d, i, u, b, B, o, x, X, p) + } else { + switch (fmt_spec) { + case 'p': { // pointer + str_arg_l += (size_t)snprintf(tmp + str_arg_l, + sizeof(tmp) - str_arg_l, + "%p", ptr_arg); + break; + } + case 'd': { // signed + str_arg_l += (size_t)snprintf(tmp + str_arg_l, + sizeof(tmp) - str_arg_l, + "%" PRIdMAX, arg); + break; + } + case 'b': case 'B': { // binary + size_t bits = 0; + for (bits = sizeof(uintmax_t) * 8; bits > 0; bits--) { + if ((uarg >> (bits - 1)) & 0x1) { + break; + } + } + + while (bits > 0) { + tmp[str_arg_l++] = ((uarg >> --bits) & 0x1) ? '1' : '0'; + } + break; + } + default: { // unsigned + // construct a simple format string for snprintf + char f[] = "%" PRIuMAX; + f[sizeof("%" PRIuMAX) - 1 - 1] = fmt_spec; + assert(PRIuMAX[sizeof(PRIuMAX) - 1 - 1] == 'u'); + str_arg_l += (size_t)snprintf(tmp + str_arg_l, + sizeof(tmp) - str_arg_l, + f, uarg); + break; + } + assert(str_arg_l < sizeof(tmp)); + } + + // include the optional minus sign and possible "0x" in the region + // before the zero padding insertion point + if (zero_padding_insertion_ind < str_arg_l + && tmp[zero_padding_insertion_ind] == '-') { + zero_padding_insertion_ind++; + } + if (zero_padding_insertion_ind + 1 < str_arg_l + && tmp[zero_padding_insertion_ind] == '0' + && (tmp[zero_padding_insertion_ind + 1] == 'x' + || tmp[zero_padding_insertion_ind + 1] == 'X' + || tmp[zero_padding_insertion_ind + 1] == 'b' + || tmp[zero_padding_insertion_ind + 1] == 'B')) { + zero_padding_insertion_ind += 2; + } + } + + { + size_t num_of_digits = str_arg_l - zero_padding_insertion_ind; + + if (alternate_form && fmt_spec == 'o' + // unless zero is already the first character + && !(zero_padding_insertion_ind < str_arg_l + && tmp[zero_padding_insertion_ind] == '0')) { + // assure leading zero for alternate-form octal numbers + if (!precision_specified + || precision < num_of_digits + 1) { + // precision is increased to force the first character to be + // zero, except if a zero value is formatted with an explicit + // precision of zero + precision = num_of_digits + 1; + } + } + // zero padding to specified precision? + if (num_of_digits < precision) { + number_of_zeros_to_pad = precision - num_of_digits; + } + } + // zero padding to specified minimal field width? + if (!justify_left && zero_padding) { + const int n = (int)(min_field_width - (str_arg_l + + number_of_zeros_to_pad)); + if (n > 0) { + number_of_zeros_to_pad += (size_t)n; + } + } + break; + } + + case 'f': + case 'F': + case 'e': + case 'E': + case 'g': + case 'G': + { + // floating point + char format[40]; + int remove_trailing_zeroes = false; + + double f = tvs ? tv_float(tvs, &arg_idx) : va_arg(ap, double); + double abs_f = f < 0 ? -f : f; + + if (fmt_spec == 'g' || fmt_spec == 'G') { + // can't use %g directly, cause it prints "1.0" as "1" + if ((abs_f >= 0.001 && abs_f < 10000000.0) || abs_f == 0.0) { + fmt_spec = ASCII_ISUPPER(fmt_spec) ? 'F' : 'f'; + } else { + fmt_spec = fmt_spec == 'g' ? 'e' : 'E'; + } + remove_trailing_zeroes = true; + } + + if (isinf(f) + || (strchr("fF", fmt_spec) != NULL && abs_f > 1.0e307)) { + xstrlcpy(tmp, infinity_str(f > 0.0, fmt_spec, + force_sign, space_for_positive), + sizeof(tmp)); + str_arg_l = strlen(tmp); + zero_padding = 0; + } else if (isnan(f)) { + // Not a number: nan or NAN + memmove(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan", 4); + str_arg_l = 3; + zero_padding = 0; + } else { + format[0] = '%'; + size_t l = 1; + if (force_sign) { + format[l++] = space_for_positive ? ' ' : '+'; + } + if (precision_specified) { + size_t max_prec = TMP_LEN - 10; + + // make sure we don't get more digits than we have room for + if ((fmt_spec == 'f' || fmt_spec == 'F') && abs_f > 1.0) { + max_prec -= (size_t)log10(abs_f); + } + if (precision > max_prec) { + precision = max_prec; + } + l += (size_t)snprintf(format + l, sizeof(format) - l, ".%d", + (int)precision); + } + + // Cast to char to avoid a conversion warning on Ubuntu 12.04. + format[l] = (char)(fmt_spec == 'F' ? 'f' : fmt_spec); + format[l + 1] = NUL; + + // Regular float number + assert(l + 1 < sizeof(format)); + str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); + assert(str_arg_l < sizeof(tmp)); + + if (remove_trailing_zeroes) { + int i; + char *tp; + + // using %g or %G: remove superfluous zeroes + if (fmt_spec == 'f' || fmt_spec == 'F') { + tp = tmp + str_arg_l - 1; + } else { + tp = (char *)vim_strchr((char_u *)tmp, + fmt_spec == 'e' ? 'e' : 'E'); + if (tp) { + // remove superfluous '+' and leading zeroes from exponent + if (tp[1] == '+') { + // change "1.0e+07" to "1.0e07" + STRMOVE(tp + 1, tp + 2); + str_arg_l--; + } + i = (tp[1] == '-') ? 2 : 1; + while (tp[i] == '0') { + // change "1.0e07" to "1.0e7" + STRMOVE(tp + i, tp + i + 1); + str_arg_l--; + } + tp--; + } + } + + if (tp != NULL && !precision_specified) { + // remove trailing zeroes, but keep the one just after a dot + while (tp > tmp + 2 && *tp == '0' && tp[-1] != '.') { + STRMOVE(tp, tp + 1); + tp--; + str_arg_l--; + } + } + } else { + // Be consistent: some printf("%e") use 1.0e+12 and some + // 1.0e+012; remove one zero in the last case. + char *tp = (char *)vim_strchr((char_u *)tmp, + fmt_spec == 'e' ? 'e' : 'E'); + if (tp && (tp[1] == '+' || tp[1] == '-') && tp[2] == '0' + && ascii_isdigit(tp[3]) && ascii_isdigit(tp[4])) { + STRMOVE(tp + 2, tp + 3); + str_arg_l--; + } + } + } + if (zero_padding && min_field_width > str_arg_l + && (tmp[0] == '-' || force_sign)) { + // Padding 0's should be inserted after the sign. + number_of_zeros_to_pad = min_field_width - str_arg_l; + zero_padding_insertion_ind = 1; + } + str_arg = tmp; + break; + } + + default: + // unrecognized conversion specifier, keep format string as-is + zero_padding = 0; // turn zero padding off for non-numeric conversion + justify_left = 1; + min_field_width = 0; // reset flags + + // discard the unrecognized conversion, just keep + // the unrecognized conversion character + str_arg = p; + str_arg_l = 0; + if (*p) { + str_arg_l++; // include invalid conversion specifier + } + // unchanged if not at end-of-string + break; + } + + if (*p) { + p++; // step over the just processed conversion specifier + } + + // insert padding to the left as requested by min_field_width; + // this does not include the zero padding in case of numerical conversions + if (!justify_left) { + assert(str_arg_l <= SIZE_MAX - number_of_zeros_to_pad); + if (min_field_width > str_arg_l + number_of_zeros_to_pad) { + // left padding with blank or zero + size_t pn = min_field_width - (str_arg_l + number_of_zeros_to_pad); + if (str_avail) { + size_t avail = str_m - str_l; + memset(str + str_l, zero_padding ? '0' : ' ', MIN(pn, avail)); + str_avail = pn < avail; + } + assert(pn <= SIZE_MAX - str_l); + str_l += pn; + } + } + + // zero padding as requested by the precision or by the minimal + // field width for numeric conversions required? + if (number_of_zeros_to_pad == 0) { + // will not copy first part of numeric right now, + // force it to be copied later in its entirety + zero_padding_insertion_ind = 0; + } else { + // insert first part of numerics (sign or '0x') before zero padding + if (zero_padding_insertion_ind > 0) { + size_t zn = zero_padding_insertion_ind; + if (str_avail) { + size_t avail = str_m - str_l; + memmove(str + str_l, str_arg, MIN(zn, avail)); + str_avail = zn < avail; + } + assert(zn <= SIZE_MAX - str_l); + str_l += zn; + } + + // insert zero padding as requested by precision or min field width + if (number_of_zeros_to_pad > 0) { + size_t zn = number_of_zeros_to_pad; + if (str_avail) { + size_t avail = str_m - str_l; + memset(str + str_l, '0', MIN(zn, avail)); + str_avail = zn < avail; + } + assert(zn <= SIZE_MAX - str_l); + str_l += zn; + } + } + + // insert formatted string + // (or as-is conversion specifier for unknown conversions) + if (str_arg_l > zero_padding_insertion_ind) { + size_t sn = str_arg_l - zero_padding_insertion_ind; + if (str_avail) { + size_t avail = str_m - str_l; + memmove(str + str_l, + str_arg + zero_padding_insertion_ind, + MIN(sn, avail)); + str_avail = sn < avail; + } + assert(sn <= SIZE_MAX - str_l); + str_l += sn; + } + + // insert right padding + if (justify_left) { + assert(str_arg_l <= SIZE_MAX - number_of_zeros_to_pad); + if (min_field_width > str_arg_l + number_of_zeros_to_pad) { + // right blank padding to the field width + size_t pn = min_field_width - (str_arg_l + number_of_zeros_to_pad); + if (str_avail) { + size_t avail = str_m - str_l; + memset(str + str_l, ' ', MIN(pn, avail)); + str_avail = pn < avail; + } + assert(pn <= SIZE_MAX - str_l); + str_l += pn; + } + } + + xfree(tofree); + } + } + + if (str_m > 0) { + // make sure the string is nul-terminated even at the expense of + // overwriting the last character (shouldn't happen, but just in case) + str[str_l <= str_m - 1 ? str_l : str_m - 1] = '\0'; + } + + if (tvs && tvs[arg_idx - 1].v_type != VAR_UNKNOWN) { + EMSG(_("E767: Too many arguments to printf()")); + } + + // return the number of characters formatted (excluding trailing nul + // character); that is, the number of characters that would have been + // written to the buffer if it were large enough. + return (int)str_l; +} diff --git a/src/nvim/strings.h b/src/nvim/strings.h index 3f0f0c8d6a..59b8701a3f 100644 --- a/src/nvim/strings.h +++ b/src/nvim/strings.h @@ -2,6 +2,10 @@ #define NVIM_STRINGS_H #include <stdbool.h> +#include <stdarg.h> + +#include "nvim/types.h" +#include "nvim/eval/typval.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "strings.h.generated.h" diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index aded08faee..65c0e2464a 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -1,3 +1,6 @@ +// 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 + /* * syntax.c: code for syntax highlighting */ @@ -42,39 +45,46 @@ static bool did_syntax_onoff = false; -// 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. +/// 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. struct hl_group { - char_u *sg_name; // highlight group name - char_u *sg_name_u; // uppercase of sg_name - int sg_attr; // Screen attr - int sg_link; // link to this highlight group ID - int sg_set; // combination of SG_* flags - scid_T sg_scriptID; // script in which the group was last set + char_u *sg_name; ///< highlight group name + char_u *sg_name_u; ///< uppercase of sg_name + int sg_attr; ///< Screen attr @see ATTR_ENTRY + int sg_link; ///< link to this highlight group ID + int sg_set; ///< combination of flags in \ref SG_SET + scid_T sg_scriptID; ///< script in which the group was last set // for terminal UIs - int sg_cterm; // "cterm=" highlighting attr - int sg_cterm_fg; // terminal fg color number + 1 - int sg_cterm_bg; // terminal bg color number + 1 - int sg_cterm_bold; // bold attr was set for light color + int sg_cterm; ///< "cterm=" highlighting attr + int sg_cterm_fg; ///< terminal fg color number + 1 + int sg_cterm_bg; ///< terminal bg color number + 1 + int sg_cterm_bold; ///< bold attr was set for light color // for RGB UIs - int sg_gui; // "gui=" highlighting attributes - RgbValue sg_rgb_fg; // RGB foreground color - RgbValue sg_rgb_bg; // RGB background color - RgbValue sg_rgb_sp; // RGB special color - uint8_t *sg_rgb_fg_name; // RGB foreground color name - uint8_t *sg_rgb_bg_name; // RGB background color name - uint8_t *sg_rgb_sp_name; // RGB special color name + int sg_gui; ///< "gui=" highlighting attributes + ///< (combination of \ref HL_ATTRIBUTES) + RgbValue sg_rgb_fg; ///< RGB foreground color + RgbValue sg_rgb_bg; ///< RGB background color + RgbValue sg_rgb_sp; ///< RGB special color + uint8_t *sg_rgb_fg_name; ///< RGB foreground color name + uint8_t *sg_rgb_bg_name; ///< RGB background color name + uint8_t *sg_rgb_sp_name; ///< RGB special color name }; +/// \addtogroup SG_SET +/// @{ #define SG_CTERM 2 // cterm has been set #define SG_GUI 4 // gui has been set #define SG_LINK 8 // link has been set +/// @} // highlight groups for 'highlight' option static garray_T highlight_ga = GA_EMPTY_INIT_VALUE; -#define HL_TABLE() ((struct hl_group *)((highlight_ga.ga_data))) +static inline struct hl_group * HL_TABLE(void) +{ + return ((struct hl_group *)((highlight_ga.ga_data))); +} #define MAX_HL_ID 20000 /* maximum value for a highlight ID. */ @@ -93,10 +103,8 @@ static int include_none = 0; /* when 1 include "nvim/None" */ static int include_default = 0; /* when 1 include "nvim/default" */ static int include_link = 0; /* when 2 include "nvim/link" and "clear" */ -/* - * The "term", "cterm" and "gui" arguments can be any combination of the - * following names, separated by commas (but no spaces!). - */ +/// The "term", "cterm" and "gui" arguments can be any combination of the +/// following names, separated by commas (but no spaces!). static char *(hl_name_table[]) = {"bold", "standout", "underline", "undercurl", "italic", "reverse", "inverse", "NONE"}; @@ -302,6 +310,8 @@ static keyentry_T dumkey; #define HIKEY2KE(p) ((keyentry_T *)((p) - (dumkey.keyword - (char_u *)&dumkey))) #define HI2KE(hi) HIKEY2KE((hi)->hi_key) +// -V:HI2KE:782 + /* * To reduce the time spent in keepend(), remember at which level in the state * stack the first item with "keepend" is present. When "-1", there is no @@ -1406,14 +1416,14 @@ static int syn_stack_equal(synstate_T *sp) /* If the pointer is different it can still be the * same text. Compare the strings, ignore case when * the start item has the sp_ic flag set. */ - if (bsx->matches[j] == NULL - || six->matches[j] == NULL) + if (bsx->matches[j] == NULL || six->matches[j] == NULL) { break; - if ((SYN_ITEMS(syn_block)[CUR_STATE(i).si_idx]).sp_ic - ? mb_stricmp(bsx->matches[j], - six->matches[j]) != 0 - : STRCMP(bsx->matches[j], six->matches[j]) != 0) + } + if (mb_strcmp_ic((SYN_ITEMS(syn_block)[CUR_STATE(i).si_idx]).sp_ic, + (const char *)bsx->matches[j], + (const char *)six->matches[j]) != 0) { break; + } } } if (j != NSUBEXP) @@ -1657,8 +1667,9 @@ syn_current_attr ( * If we found a match after the last column, use it. */ if (next_match_idx >= 0 && next_match_col >= (int)current_col - && next_match_col != MAXCOL) - (void)push_next_match(NULL); + && next_match_col != MAXCOL) { + (void)push_next_match(); + } current_finished = TRUE; current_state_stored = FALSE; @@ -1765,8 +1776,9 @@ syn_current_attr ( cur_si->si_trans_id = CUR_STATE( current_state.ga_len - 2).si_trans_id; } - } else + } else { cur_si->si_attr = syn_id2attr(syn_id); + } cur_si->si_cont_list = NULL; cur_si->si_next_list = next_list; check_keepend(); @@ -1976,9 +1988,10 @@ syn_current_attr ( * endless loop). */ GA_APPEND(int, &zero_width_next_ga, next_match_idx); next_match_idx = -1; - } else - cur_si = push_next_match(cur_si); - found_match = TRUE; + } else { + cur_si = push_next_match(); + } + found_match = true; } } } @@ -2158,9 +2171,10 @@ static int did_match_already(int idx, garray_T *gap) /* * Push the next match onto the stack. */ -static stateitem_T *push_next_match(stateitem_T *cur_si) +static stateitem_T *push_next_match(void) { - synpat_T *spp; + stateitem_T *cur_si; + synpat_T *spp; int save_flags; spp = &(SYN_ITEMS(syn_block)[next_match_idx]); @@ -3259,9 +3273,10 @@ static void syn_cmd_clear(exarg_T *eap, int syncing) syntax_sync_clear(); else { syntax_clear(curwin->w_s); - if (curwin->w_s == &curwin->w_buffer->b_s) - do_unlet((char_u *)"b:current_syntax", TRUE); - do_unlet((char_u *)"w:current_syntax", TRUE); + if (curwin->w_s == &curwin->w_buffer->b_s) { + do_unlet(S_LEN("b:current_syntax"), true); + } + do_unlet(S_LEN("w:current_syntax"), true); } } else { /* @@ -3337,7 +3352,7 @@ static void syn_cmd_enable(exarg_T *eap, int syncing) { set_internal_string_var((char_u *)"syntax_cmd", (char_u *)"enable"); syn_cmd_onoff(eap, "syntax"); - do_unlet((char_u *)"g:syntax_cmd", TRUE); + do_unlet(S_LEN("g:syntax_cmd"), true); } /* @@ -3350,7 +3365,7 @@ static void syn_cmd_reset(exarg_T *eap, int syncing) if (!eap->skip) { set_internal_string_var((char_u *)"syntax_cmd", (char_u *)"reset"); do_cmdline_cmd("runtime! syntax/syncolor.vim"); - do_unlet((char_u *)"g:syntax_cmd", TRUE); + do_unlet(S_LEN("g:syntax_cmd"), true); } } @@ -3377,7 +3392,7 @@ static void syn_cmd_onoff(exarg_T *eap, char *name) eap->nextcmd = check_nextcmd(eap->arg); if (!eap->skip) { char buf[100]; - strncpy(buf, "so ", 4); + memcpy(buf, "so ", 4); vim_snprintf(buf + 3, sizeof(buf) - 3, SYNTAX_FNAME, name); do_cmdline_cmd(buf); } @@ -3576,22 +3591,24 @@ syn_list_one ( } syn_list_flags(namelist1, spp->sp_flags, attr); - if (spp->sp_cont_list != NULL) - put_id_list((char_u *)"contains", spp->sp_cont_list, attr); + if (spp->sp_cont_list != NULL) { + put_id_list("contains", spp->sp_cont_list, attr); + } - if (spp->sp_syn.cont_in_list != NULL) - put_id_list((char_u *)"containedin", - spp->sp_syn.cont_in_list, attr); + if (spp->sp_syn.cont_in_list != NULL) { + put_id_list("containedin", spp->sp_syn.cont_in_list, attr); + } if (spp->sp_next_list != NULL) { - put_id_list((char_u *)"nextgroup", spp->sp_next_list, attr); + put_id_list("nextgroup", spp->sp_next_list, attr); syn_list_flags(namelist2, spp->sp_flags, attr); } if (spp->sp_flags & (HL_SYNC_HERE|HL_SYNC_THERE)) { - if (spp->sp_flags & HL_SYNC_HERE) - msg_puts_attr((char_u *)"grouphere", attr); - else - msg_puts_attr((char_u *)"groupthere", attr); + if (spp->sp_flags & HL_SYNC_HERE) { + msg_puts_attr("grouphere", attr); + } else { + msg_puts_attr("groupthere", attr); + } msg_putchar(' '); if (spp->sp_sync_idx >= 0) msg_outtrans(HL_TABLE()[SYN_ITEMS(curwin->w_s) @@ -3605,7 +3622,7 @@ syn_list_one ( /* list the link, if there is one */ if (HL_TABLE()[id - 1].sg_link && (did_header || link_only) && !got_int) { (void)syn_list_header(did_header, 999, id); - msg_puts_attr((char_u *)"links to", attr); + msg_puts_attr("links to", attr); msg_putchar(' '); msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name); } @@ -3617,7 +3634,7 @@ static void syn_list_flags(struct name_list *nlist, int flags, int attr) for (i = 0; nlist[i].flag != 0; ++i) if (flags & nlist[i].flag) { - msg_puts_attr((char_u *)nlist[i].name, attr); + msg_puts_attr(nlist[i].name, attr); msg_putchar(' '); } } @@ -3640,15 +3657,16 @@ static void syn_list_cluster(int id) msg_advance(endcol); if (SYN_CLSTR(curwin->w_s)[id].scl_list != NULL) { - put_id_list((char_u *)"cluster", SYN_CLSTR(curwin->w_s)[id].scl_list, - hl_attr(HLF_D)); + put_id_list("cluster", SYN_CLSTR(curwin->w_s)[id].scl_list, hl_attr(HLF_D)); } else { - msg_puts_attr((char_u *)"cluster", hl_attr(HLF_D)); - msg_puts((char_u *)"=NONE"); + msg_puts_attr("cluster", hl_attr(HLF_D)); + msg_puts("=NONE"); } } -static void put_id_list(char_u *name, short *list, int attr) +static void put_id_list(const char *name, + short *list, // NOLINT(runtime/int) + int attr) { short *p; @@ -3656,14 +3674,15 @@ static void put_id_list(char_u *name, short *list, int attr) msg_putchar('='); for (p = list; *p; ++p) { if (*p >= SYNID_ALLBUT && *p < SYNID_TOP) { - if (p[1]) - MSG_PUTS("ALLBUT"); - else - MSG_PUTS("ALL"); + if (p[1]) { + msg_puts("ALLBUT"); + } else { + msg_puts("ALL"); + } } else if (*p >= SYNID_TOP && *p < SYNID_CONTAINED) { - MSG_PUTS("TOP"); + msg_puts("TOP"); } else if (*p >= SYNID_CONTAINED && *p < SYNID_CLUSTER) { - MSG_PUTS("CONTAINED"); + msg_puts("CONTAINED"); } else if (*p >= SYNID_CLUSTER) { short scl_id = *p - SYNID_CLUSTER; @@ -3688,7 +3707,7 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr) /* May have to write "matchgroup=group" */ if (last_matchgroup != spp->sp_syn_match_id) { last_matchgroup = spp->sp_syn_match_id; - msg_puts_attr((char_u *)"matchgroup", attr); + msg_puts_attr("matchgroup", attr); msg_putchar('='); if (last_matchgroup == 0) msg_outtrans((char_u *)"NONE"); @@ -3697,8 +3716,8 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr) msg_putchar(' '); } - /* output the name of the pattern and an '=' or ' ' */ - msg_puts_attr((char_u *)s, attr); + // Output the name of the pattern and an '=' or ' '. + msg_puts_attr(s, attr); msg_putchar(c); /* output the pattern, in between a char that is not in the pattern */ @@ -3718,9 +3737,10 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr) if (!(spp->sp_off_flags & (mask + (mask << SPO_COUNT)))) { continue; } - if (!first) - msg_putchar(','); /* separate with commas */ - msg_puts((char_u *)spo_name_tab[i]); + if (!first) { + msg_putchar(','); // Separate with commas. + } + msg_puts(spo_name_tab[i]); n = spp->sp_offsets[i]; if (i != SPO_LC_OFF) { if (spp->sp_off_flags & mask) @@ -3792,32 +3812,31 @@ syn_list_keywords ( } did_header = TRUE; if (prev_contained != (kp->flags & HL_CONTAINED)) { - msg_puts_attr((char_u *)"contained", attr); + msg_puts_attr("contained", attr); msg_putchar(' '); prev_contained = (kp->flags & HL_CONTAINED); } if (kp->k_syn.cont_in_list != prev_cont_in_list) { - put_id_list((char_u *)"containedin", - kp->k_syn.cont_in_list, attr); + put_id_list("containedin", kp->k_syn.cont_in_list, attr); msg_putchar(' '); prev_cont_in_list = kp->k_syn.cont_in_list; } if (kp->next_list != prev_next_list) { - put_id_list((char_u *)"nextgroup", kp->next_list, attr); + put_id_list("nextgroup", kp->next_list, attr); msg_putchar(' '); prev_next_list = kp->next_list; if (kp->flags & HL_SKIPNL) { - msg_puts_attr((char_u *)"skipnl", attr); + msg_puts_attr("skipnl", attr); msg_putchar(' '); prev_skipnl = (kp->flags & HL_SKIPNL); } if (kp->flags & HL_SKIPWHITE) { - msg_puts_attr((char_u *)"skipwhite", attr); + msg_puts_attr("skipwhite", attr); msg_putchar(' '); prev_skipwhite = (kp->flags & HL_SKIPWHITE); } if (kp->flags & HL_SKIPEMPTY) { - msg_puts_attr((char_u *)"skipempty", attr); + msg_puts_attr("skipempty", attr); msg_putchar(' '); prev_skipempty = (kp->flags & HL_SKIPEMPTY); } @@ -3929,7 +3948,8 @@ static void add_keyword(char_u *name, hash_T hash = hash_hash(kp->keyword); hashtab_T *ht = (curwin->w_s->b_syn_ic) ? &curwin->w_s->b_keywtab_ic : &curwin->w_s->b_keywtab; - hashitem_T *hi = hash_lookup(ht, kp->keyword, hash); + hashitem_T *hi = hash_lookup(ht, (const char *)kp->keyword, + STRLEN(kp->keyword), hash); // even though it looks like only the kp->keyword member is // being used here, vim uses some pointer trickery to get the orignal @@ -4236,83 +4256,81 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing) if (rest != NULL) { syn_id = syn_check_group(arg, (int)(group_name_end - arg)); - if (syn_id != 0) - /* allocate a buffer, for removing backslashes in the keyword */ + if (syn_id != 0) { + // Allocate a buffer, for removing backslashes in the keyword. keyword_copy = xmalloc(STRLEN(rest) + 1); - syn_opt_arg.flags = 0; - syn_opt_arg.keyword = TRUE; - syn_opt_arg.sync_idx = NULL; - syn_opt_arg.has_cont_list = FALSE; - syn_opt_arg.cont_in_list = NULL; - syn_opt_arg.next_list = NULL; - - /* - * The options given apply to ALL keywords, so all options must be - * found before keywords can be created. - * 1: collect the options and copy the keywords to keyword_copy. - */ - cnt = 0; - p = keyword_copy; - for (; rest != NULL && !ends_excmd(*rest); rest = skipwhite(rest)) { - rest = get_syn_options(rest, &syn_opt_arg, &conceal_char); - if (rest == NULL || ends_excmd(*rest)) - break; - /* Copy the keyword, removing backslashes, and add a NUL. */ - while (*rest != NUL && !ascii_iswhite(*rest)) { - if (*rest == '\\' && rest[1] != NUL) - ++rest; - *p++ = *rest++; - } - *p++ = NUL; - ++cnt; } + if (keyword_copy != NULL) { + syn_opt_arg.flags = 0; + syn_opt_arg.keyword = true; + syn_opt_arg.sync_idx = NULL; + syn_opt_arg.has_cont_list = false; + syn_opt_arg.cont_in_list = NULL; + syn_opt_arg.next_list = NULL; + + // The options given apply to ALL keywords, so all options must be + // found before keywords can be created. + // 1: collect the options and copy the keywords to keyword_copy. + cnt = 0; + p = keyword_copy; + for (; rest != NULL && !ends_excmd(*rest); rest = skipwhite(rest)) { + rest = get_syn_options(rest, &syn_opt_arg, &conceal_char); + if (rest == NULL || ends_excmd(*rest)) { + break; + } + // Copy the keyword, removing backslashes, and add a NUL. + while (*rest != NUL && !ascii_iswhite(*rest)) { + if (*rest == '\\' && rest[1] != NUL) { + rest++; + } + *p++ = *rest++; + } + *p++ = NUL; + cnt++; + } - if (!eap->skip) { - /* Adjust flags for use of ":syn include". */ - syn_incl_toplevel(syn_id, &syn_opt_arg.flags); + if (!eap->skip) { + // Adjust flags for use of ":syn include". + syn_incl_toplevel(syn_id, &syn_opt_arg.flags); - /* - * 2: Add an entry for each keyword. - */ - for (kw = keyword_copy; --cnt >= 0; kw += STRLEN(kw) + 1) { - for (p = vim_strchr(kw, '[');; ) { - if (p != NULL) - *p = NUL; - add_keyword(kw, syn_id, syn_opt_arg.flags, - syn_opt_arg.cont_in_list, - syn_opt_arg.next_list, conceal_char); - if (p == NULL) - break; - if (p[1] == NUL) { - EMSG2(_("E789: Missing ']': %s"), kw); - goto error; - } - if (p[1] == ']') { - if (p[2] != NUL) { - EMSG3(_("E890: trailing char after ']': %s]%s"), - kw, &p[2]); + // 2: Add an entry for each keyword. + for (kw = keyword_copy; --cnt >= 0; kw += STRLEN(kw) + 1) { + for (p = vim_strchr(kw, '[');; ) { + if (p != NULL) { + *p = NUL; + } + add_keyword(kw, syn_id, syn_opt_arg.flags, + syn_opt_arg.cont_in_list, + syn_opt_arg.next_list, conceal_char); + if (p == NULL) { + break; + } + if (p[1] == NUL) { + emsgf(_("E789: Missing ']': %s"), kw); goto error; } - kw = p + 1; - break; // skip over the "]" - } - if (has_mbyte) { - int l = (*mb_ptr2len)(p + 1); + if (p[1] == ']') { + if (p[2] != NUL) { + emsgf(_("E890: trailing char after ']': %s]%s"), + kw, &p[2]); + goto error; + } + kw = p + 1; + break; // skip over the "]" + } + const int l = (*mb_ptr2len)(p + 1); memmove(p, p + 1, l); p += l; - } else { - p[0] = p[1]; - ++p; } } } - } error: - xfree(keyword_copy); - xfree(syn_opt_arg.cont_in_list); - xfree(syn_opt_arg.next_list); + xfree(keyword_copy); + xfree(syn_opt_arg.cont_in_list); + xfree(syn_opt_arg.next_list); + } } if (rest != NULL) @@ -5236,12 +5254,10 @@ get_id_list ( /* * Handle full group name. */ - if (vim_strpbrk(name + 1, (char_u *)"\\.*^$~[") == NULL) + if (vim_strpbrk(name + 1, (char_u *)"\\.*^$~[") == NULL) { id = syn_check_group(name + 1, (int)(end - p)); - else { - /* - * Handle match of regexp with group names. - */ + } else { + // Handle match of regexp with group names. *name = '^'; STRCAT(name, "$"); regmatch.regprog = vim_regcomp(name, RE_MAGIC); @@ -5516,24 +5532,26 @@ void ex_ownsyntax(exarg_T *eap) clear_string_option(&curwin->w_s->b_syn_isk); } - /* save value of b:current_syntax */ - old_value = get_var_value((char_u *)"b:current_syntax"); - if (old_value != NULL) + // Save value of b:current_syntax. + old_value = get_var_value("b:current_syntax"); + if (old_value != NULL) { old_value = vim_strsave(old_value); + } /* Apply the "syntax" autocommand event, this finds and loads the syntax * file. */ apply_autocmds(EVENT_SYNTAX, eap->arg, curbuf->b_fname, TRUE, curbuf); - /* move value of b:current_syntax to w:current_syntax */ - new_value = get_var_value((char_u *)"b:current_syntax"); - if (new_value != NULL) + // Move value of b:current_syntax to w:current_syntax. + new_value = get_var_value("b:current_syntax"); + if (new_value != NULL) { set_internal_string_var((char_u *)"w:current_syntax", new_value); + } - /* restore value of b:current_syntax */ - if (old_value == NULL) - do_unlet((char_u *)"b:current_syntax", TRUE); - else { + // Restore value of b:current_syntax. + if (old_value == NULL) { + do_unlet(S_LEN("b:current_syntax"), true); + } else { set_internal_string_var((char_u *)"b:current_syntax", old_value); xfree(old_value); } @@ -5566,43 +5584,42 @@ void reset_expand_highlight(void) * Handle command line completion for :match and :echohl command: Add "None" * as highlight group. */ -void set_context_in_echohl_cmd(expand_T *xp, char_u *arg) +void set_context_in_echohl_cmd(expand_T *xp, const char *arg) { xp->xp_context = EXPAND_HIGHLIGHT; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; include_none = 1; } /* * Handle command line completion for :syntax command. */ -void set_context_in_syntax_cmd(expand_T *xp, char_u *arg) +void set_context_in_syntax_cmd(expand_T *xp, const char *arg) { - char_u *p; - - /* Default: expand subcommands */ + // Default: expand subcommands. xp->xp_context = EXPAND_SYNTAX; expand_what = EXP_SUBCMD; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; include_link = 0; include_default = 0; /* (part of) subcommand already typed */ if (*arg != NUL) { - p = skiptowhite(arg); - if (*p != NUL) { /* past first word */ - xp->xp_pattern = skipwhite(p); - if (*skiptowhite(xp->xp_pattern) != NUL) + const char *p = (const char *)skiptowhite((const char_u *)arg); + if (*p != NUL) { // Past first word. + xp->xp_pattern = skipwhite((const char_u *)p); + if (*skiptowhite(xp->xp_pattern) != NUL) { xp->xp_context = EXPAND_NOTHING; - else if (STRNICMP(arg, "case", p - arg) == 0) + } else if (STRNICMP(arg, "case", p - arg) == 0) { expand_what = EXP_CASE; - else if ( STRNICMP(arg, "keyword", p - arg) == 0 + } else if (STRNICMP(arg, "keyword", p - arg) == 0 || STRNICMP(arg, "region", p - arg) == 0 || STRNICMP(arg, "match", p - arg) == 0 - || STRNICMP(arg, "list", p - arg) == 0) + || STRNICMP(arg, "list", p - arg) == 0) { xp->xp_context = EXPAND_HIGHLIGHT; - else + } else { xp->xp_context = EXPAND_NOTHING; + } } } } @@ -5889,6 +5906,8 @@ static void syntime_report(void) static char *highlight_init_both[] = { "Conceal ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey", + "Cursor guibg=fg guifg=bg", + "lCursor guibg=fg guifg=bg", "DiffText cterm=bold ctermbg=Red gui=bold guibg=Red", "ErrorMsg ctermbg=DarkRed ctermfg=White guibg=Red guifg=White", "IncSearch cterm=reverse gui=reverse", @@ -5905,6 +5924,7 @@ static char *highlight_init_both[] = "default link EndOfBuffer NonText", "default link QuickFixLine Search", "default link Substitute Search", + "default link Whitespace NonText", NULL }; @@ -5938,6 +5958,7 @@ static char *highlight_init_light[] = "Title ctermfg=DarkMagenta gui=bold guifg=Magenta", "Visual guibg=LightGrey", "WarningMsg ctermfg=DarkRed guifg=Red", + "Normal gui=NONE", NULL }; @@ -5971,24 +5992,26 @@ static char *highlight_init_dark[] = "Title ctermfg=LightMagenta gui=bold guifg=Magenta", "Visual guibg=DarkGrey", "WarningMsg ctermfg=LightRed guifg=Red", + "Normal gui=NONE", NULL }; -void -init_highlight ( - int both, /* include groups where 'bg' doesn't matter */ - int reset /* clear group first */ -) + +/// Load colors from a file if "g:colors_name" is set, otherwise load builtin +/// colors +/// +/// @param both include groups where 'bg' doesn't matter +/// @param reset clear groups first +void +init_highlight(int both, int reset) { int i; char **pp; static int had_both = FALSE; - /* - * Try finding the color scheme file. Used when a color file was loaded - * and 'background' or 't_Co' is changed. - */ - char_u *p = get_var_value((char_u *)"g:colors_name"); + // Try finding the color scheme file. Used when a color file was loaded + // and 'background' or 't_Co' is changed. + char_u *p = get_var_value("g:colors_name"); if (p != NULL) { // Value of g:colors_name could be freed in load_colors() and make // p invalid, so copy it. @@ -6006,33 +6029,34 @@ init_highlight ( if (both) { had_both = TRUE; pp = highlight_init_both; - for (i = 0; pp[i] != NULL; ++i) - do_highlight((char_u *)pp[i], reset, TRUE); - } else if (!had_both) - /* Don't do anything before the call with both == TRUE from main(). - * Not everything has been setup then, and that call will overrule - * everything anyway. */ + for (i = 0; pp[i] != NULL; i++) { + do_highlight((char_u *)pp[i], reset, true); + } + } else if (!had_both) { + // Don't do anything before the call with both == TRUE from main(). + // Not everything has been setup then, and that call will overrule + // everything anyway. return; + } - if (*p_bg == 'l') - pp = highlight_init_light; - else - pp = highlight_init_dark; - for (i = 0; pp[i] != NULL; ++i) - do_highlight((char_u *)pp[i], reset, TRUE); + pp = (*p_bg == 'l') ? highlight_init_light : highlight_init_dark; + + for (i = 0; pp[i] != NULL; i++) { + do_highlight((char_u *)pp[i], reset, true); + } /* Reverse looks ugly, but grey may not work for 8 colors. Thus let it * depend on the number of colors available. * With 8 colors brown is equal to yellow, need to use black for Search fg * to avoid Statement highlighted text disappears. * Clear the attributes, needed when changing the t_Co value. */ - if (t_colors > 8) + if (t_colors > 8) { do_highlight( (char_u *)(*p_bg == 'l' ? "Visual cterm=NONE ctermbg=LightGrey" - : "Visual cterm=NONE ctermbg=DarkGrey"), FALSE, - TRUE); - else { + : "Visual cterm=NONE ctermbg=DarkGrey"), false, + true); + } else { do_highlight((char_u *)"Visual cterm=reverse ctermbg=NONE", FALSE, TRUE); if (*p_bg == 'l') @@ -6042,7 +6066,7 @@ init_highlight ( /* * If syntax highlighting is enabled load the highlighting for it. */ - if (get_var_value((char_u *)"g:syntax_on") != NULL) { + if (get_var_value("g:syntax_on") != NULL) { static int recursive = 0; if (recursive >= 5) { @@ -6086,18 +6110,13 @@ int load_colors(char_u *name) return retval; } -/* - * Handle the ":highlight .." command. - * When using ":hi clear" this is called recursively for each group with - * "forceit" and "init" both TRUE. - */ -void -do_highlight ( - char_u *line, - int forceit, - int init /* TRUE when called for initializing */ -) -{ + +/// Handle the ":highlight .." command. +/// When using ":hi clear" this is called recursively for each group with +/// "forceit" and "init" both TRUE. +/// @param init TRUE when called for initializing +void +do_highlight(char_u *line, int forceit, int init) { char_u *name_end; char_u *linep; char_u *key_start; @@ -6114,15 +6133,16 @@ do_highlight ( int dolink = FALSE; int error = FALSE; int color; - int is_normal_group = FALSE; /* "Normal" group */ + bool is_normal_group = false; // "Normal" group /* * If no argument, list current highlighting. */ if (ends_excmd(*line)) { - for (int i = 1; i <= highlight_ga.ga_len && !got_int; ++i) - /* TODO: only call when the group has attributes set */ + for (int i = 1; i <= highlight_ga.ga_len && !got_int; i++) { + // todo(vim): only call when the group has attributes set highlight_list_one(i); + } return; } @@ -6224,7 +6244,7 @@ do_highlight ( */ line = linep; if (ends_excmd(*line)) { - do_unlet((char_u *)"colors_name", TRUE); + do_unlet(S_LEN("colors_name"), true); restore_cterm_colors(); /* @@ -6250,12 +6270,12 @@ do_highlight ( return; 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)) + // Return if "default" was used and the group already has settings + if (dodefault && hl_has_settings(idx, true)) { return; + } - if (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0) - is_normal_group = TRUE; + 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)) { @@ -6264,7 +6284,7 @@ do_highlight ( HL_TABLE()[idx].sg_set = 0; } - if (!doclear) + if (!doclear) { while (!ends_excmd(*linep)) { key_start = linep; if (*linep == '=') { @@ -6370,12 +6390,12 @@ do_highlight ( } } } else if (STRCMP(key, "FONT") == 0) { - /* in non-GUI fonts are simply ignored */ - } else if (STRCMP(key, - "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0) { + // in non-GUI fonts are simply ignored + } else if (STRCMP(key, "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0) { if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM)) { - if (!init) + if (!init) { HL_TABLE()[idx].sg_set |= SG_CTERM; + } /* When setting the foreground color, and previously the "bold" * flag was set for a light color, reset it now */ @@ -6469,9 +6489,10 @@ do_highlight ( * colors (on some terminals, e.g. "linux") */ if (color & 8) { HL_TABLE()[idx].sg_cterm |= HL_BOLD; - HL_TABLE()[idx].sg_cterm_bold = TRUE; - } else + HL_TABLE()[idx].sg_cterm_bold = true; + } else { HL_TABLE()[idx].sg_cterm &= ~HL_BOLD; + } } color &= 7; // truncate to 8 colors } else if (t_colors == 16 || t_colors == 88 || t_colors >= 256) { @@ -6503,16 +6524,16 @@ do_highlight ( if (!ui_rgb_attached()) { must_redraw = CLEAR; if (color >= 0) { - if (t_colors < 16) + if (t_colors < 16) { i = (color == 0 || color == 4); - else + } else { i = (color < 7 || color == 8); - /* Set the 'background' option if the value is - * wrong. */ - if (i != (*p_bg == 'd')) - set_option_value((char_u *)"bg", 0L, - i ? (char_u *)"dark" - : (char_u *)"light", 0); + } + // Set the 'background' option if the value is + // wrong. + if (i != (*p_bg == 'd')) { + set_option_value("bg", 0L, (i ? "dark" : "light"), 0); + } } } } @@ -6583,21 +6604,23 @@ do_highlight ( /* * When highlighting has been given for a group, don't link it. */ - if (!init || !(HL_TABLE()[idx].sg_set & SG_LINK)) + if (!init || !(HL_TABLE()[idx].sg_set & SG_LINK)) { HL_TABLE()[idx].sg_link = 0; + } /* * Continue with next argument. */ linep = skipwhite(linep); } + } /* * If there is an error, and it's a new entry, remove it from the table. */ - if (error && idx == highlight_ga.ga_len) + if (error && idx == highlight_ga.ga_len) { syn_unadd_group(); - else { + } else { if (is_normal_group) { HL_TABLE()[idx].sg_attr = 0; // Need to update all groups, because they might be using "bg" and/or @@ -6605,16 +6628,17 @@ do_highlight ( highlight_attr_set_all(); // If the normal group has changed, it is simpler to refresh every UI ui_refresh(); - } else + } else { set_hl_attr(idx); + } HL_TABLE()[idx].sg_scriptID = current_SID; redraw_all_later(NOT_VALID); } xfree(key); xfree(arg); - /* Only call highlight_changed() once, after sourcing a syntax file */ - need_highlight_changed = TRUE; + // Only call highlight_changed() once, after sourcing a syntax file + need_highlight_changed = true; } #if defined(EXITFREE) @@ -6687,22 +6711,21 @@ static void highlight_clear(int idx) } -/* - * Table with the specifications for an attribute number. - * Note that this table is used by ALL buffers. This is required because the - * GUI can redraw at any time for any buffer. - */ +/// Table with the specifications for an attribute number. +/// Note that this table is used by ALL buffers. This is required because the +/// GUI can redraw at any time for any buffer. static garray_T attr_table = GA_EMPTY_INIT_VALUE; -#define ATTR_ENTRY(idx) ((attrentry_T *)attr_table.ga_data)[idx] +static inline attrentry_T * ATTR_ENTRY(int idx) +{ + return &((attrentry_T *)attr_table.ga_data)[idx]; +} -/* - * Return the attr number for a set of colors and font. - * Add a new entry to the term_attr_table, attr_table or gui_attr_table - * if the combination is new. - * Return 0 for error. - */ +/// Return the attr number for a set of colors and font. +/// Add a new entry to the term_attr_table, attr_table or gui_attr_table +/// if the combination is new. +/// @return 0 for error. int get_attr_entry(attrentry_T *aep) { garray_T *table = &attr_table; @@ -6786,7 +6809,7 @@ int hl_combine_attr(int char_attr, int prim_attr) { attrentry_T *char_aep = NULL; attrentry_T *spell_aep; - attrentry_T new_en; + attrentry_T new_en = ATTRENTRY_INIT; if (char_attr == 0) { return prim_attr; @@ -6834,17 +6857,24 @@ int hl_combine_attr(int char_attr, int prim_attr) return get_attr_entry(&new_en); } +/// \note this function does not apply exclusively to cterm attr contrary +/// to what its name implies attrentry_T *syn_cterm_attr2entry(int attr) { attr -= ATTR_OFF; - if (attr >= attr_table.ga_len) /* did ":syntax clear" */ + if (attr >= attr_table.ga_len) { + // did ":syntax clear" return NULL; - return &(ATTR_ENTRY(attr)); + } + return ATTR_ENTRY(attr); } +/// \addtogroup LIST_XXX +/// @{ #define LIST_ATTR 1 #define LIST_STRING 2 #define LIST_INT 3 +/// @} static void highlight_list_one(int id) { @@ -6871,8 +6901,8 @@ static void highlight_list_one(int id) if (sgp->sg_link && !got_int) { (void)syn_list_header(didh, 9999, id); - didh = TRUE; - msg_puts_attr((char_u *)"links to", hl_attr(HLF_D)); + didh = true; + msg_puts_attr("links to", hl_attr(HLF_D)); msg_putchar(' '); msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name); } @@ -6883,7 +6913,13 @@ static void highlight_list_one(int id) last_set_msg(sgp->sg_scriptID); } -static int highlight_list_arg(int id, int didh, int type, int iarg, char_u *sarg, char *name) +/// Outputs a highlight when doing ":hi MyHighlight" +/// +/// @param type one of \ref LIST_XXX +/// @param iarg integer argument used if \p type == LIST_INT +/// @param sarg string used if \p type == LIST_STRING +static int highlight_list_arg(int id, int didh, int type, int iarg, + char_u *sarg, const char *name) { char_u buf[100]; char_u *ts; @@ -6902,8 +6938,8 @@ static int highlight_list_arg(int id, int didh, int type, int iarg, char_u *sarg for (i = 0; hl_attr_table[i] != 0; ++i) { if (iarg & hl_attr_table[i]) { if (buf[0] != NUL) - vim_strcat(buf, (char_u *)",", 100); - vim_strcat(buf, (char_u *)hl_name_table[i], 100); + xstrlcat((char *)buf, ",", 100); + xstrlcat((char *)buf, hl_name_table[i], 100); iarg &= ~hl_attr_table[i]; /* don't want "inverse" */ } } @@ -6923,21 +6959,21 @@ static int highlight_list_arg(int id, int didh, int type, int iarg, char_u *sarg return didh; } -/* - * Return "1" if highlight group "id" has attribute "flag". - * Return NULL otherwise. - */ -char_u * -highlight_has_attr ( - int id, - int flag, - int modec // 'g' for GUI, 'c' for cterm -) +/// Check whether highlight group has attribute +/// +/// @param[in] id Highlight group to check. +/// @param[in] flag Attribute to check. +/// @param[in] modec 'g' for GUI, 'c' for term. +/// +/// @return "1" if highlight group has attribute, NULL otherwise. +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) + if (id <= 0 || id > highlight_ga.ga_len) { return NULL; + } if (modec == 'g') { attr = HL_TABLE()[id - 1].sg_gui; @@ -6945,39 +6981,42 @@ highlight_has_attr ( attr = HL_TABLE()[id - 1].sg_cterm; } - if (attr & flag) - return (char_u *)"1"; - return NULL; + return (attr & flag) ? "1" : NULL; } -/* - * Return color name of highlight group "id". - */ -char_u * -highlight_color ( - int id, - char_u *what, /* "font", "fg", "bg", "sp", "fg#", "bg#" or "sp#" */ - int modec /* 'g' for GUI, 'c' for cterm, 't' for term */ -) +/// Return color name of the given highlight group +/// +/// @param[in] id Highlight group to work with. +/// @param[in] what What to return: one of "font", "fg", "bg", "sp", "fg#", +/// "bg#" or "sp#". +/// @param[in] modec 'g' for GUI, 'c' for cterm and 't' for term. +/// +/// @return color name, possibly in a static buffer. Buffer will be overwritten +/// on next highlight_color() call. May return NULL. +const char *highlight_color(const int id, const char *const what, + const int modec) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { - static char_u name[20]; + static char name[20]; int n; - int fg = FALSE; - int sp = FALSE; - int font = FALSE; + bool fg = false; + bool sp = false; + bool font = false; - if (id <= 0 || id > highlight_ga.ga_len) + if (id <= 0 || id > highlight_ga.ga_len) { return NULL; + } - if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'g') - fg = TRUE; - else if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'o' - && TOLOWER_ASC(what[2]) == 'n' && TOLOWER_ASC(what[3]) == 't') - font = TRUE; - else if (TOLOWER_ASC(what[0]) == 's' && TOLOWER_ASC(what[1]) == 'p') - sp = TRUE; - else if (!(TOLOWER_ASC(what[0]) == 'b' && TOLOWER_ASC(what[1]) == 'g')) + if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'g') { + fg = true; + } else if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'o' + && TOLOWER_ASC(what[2]) == 'n' && TOLOWER_ASC(what[3]) == 't') { + font = true; + } else if (TOLOWER_ASC(what[0]) == 's' && TOLOWER_ASC(what[1]) == 'p') { + sp = true; + } else if (!(TOLOWER_ASC(what[0]) == 'b' && TOLOWER_ASC(what[1]) == 'g')) { return NULL; + } if (modec == 'g') { if (what[2] == '#' && ui_rgb_attached()) { if (fg) { @@ -6990,19 +7029,20 @@ highlight_color ( if (n < 0 || n > 0xffffff) { return NULL; } - snprintf((char *)name, sizeof(name), "#%06x", n); + snprintf(name, sizeof(name), "#%06x", n); return name; } if (fg) { - return HL_TABLE()[id - 1].sg_rgb_fg_name; + return (const char *)HL_TABLE()[id - 1].sg_rgb_fg_name; } if (sp) { - return HL_TABLE()[id - 1].sg_rgb_sp_name; + return (const char *)HL_TABLE()[id - 1].sg_rgb_sp_name; } - return HL_TABLE()[id - 1].sg_rgb_bg_name; + return (const char *)HL_TABLE()[id - 1].sg_rgb_bg_name; } - if (font || sp) + if (font || sp) { return NULL; + } if (modec == 'c') { if (fg) { n = HL_TABLE()[id - 1].sg_cterm_fg - 1; @@ -7012,31 +7052,30 @@ highlight_color ( if (n < 0) { return NULL; } - snprintf((char *)name, sizeof(name), "%d", n); + snprintf(name, sizeof(name), "%d", n); return name; } - /* term doesn't have color */ + // term doesn't have color. return NULL; } -/* - * Output the syntax list header. - * Return TRUE when started a new line. - */ -static int -syn_list_header ( - int did_header, /* did header already */ - int outlen, /* length of string that comes */ - int id /* highlight group id */ -) +/// Output the syntax list header. +/// +/// @param did_header did header already +/// @param outlen length of string that comes +/// @param id highlight group id +/// @return true when started a new line. +static int +syn_list_header(int did_header, int outlen, int id) { int endcol = 19; int newline = TRUE; if (!did_header) { msg_putchar('\n'); - if (got_int) - return TRUE; + if (got_int) { + return true; + } msg_outtrans(HL_TABLE()[id - 1].sg_name); endcol = 15; } else if (msg_col + outlen + 1 >= Columns) { @@ -7057,7 +7096,7 @@ syn_list_header ( /* Show "xxx" with the attributes. */ if (!did_header) { - msg_puts_attr((char_u *)"xxx", syn_id2attr(id)); + msg_puts_attr("xxx", syn_id2attr(id)); msg_putchar(' '); } @@ -7073,12 +7112,13 @@ set_hl_attr ( int idx /* index in array */ ) { - attrentry_T at_en; + attrentry_T at_en = ATTRENTRY_INIT; struct hl_group *sgp = HL_TABLE() + idx; - /* The "Normal" group doesn't need an attribute number */ - if (sgp->sg_name_u != NULL && STRCMP(sgp->sg_name_u, "NORMAL") == 0) + // The "Normal" group doesn't need an attribute number + if (sgp->sg_name_u != NULL && STRCMP(sgp->sg_name_u, "NORMAL") == 0) { return; + } at_en.cterm_ae_attr = sgp->sg_cterm; at_en.cterm_fg_color = sgp->sg_cterm_fg; @@ -7102,11 +7142,11 @@ set_hl_attr ( } } -/* - * Lookup a highlight group name and return it's ID. - * If it is not found, 0 is returned. - */ -int syn_name2id(char_u *name) +/// Lookup a highlight group name and return its ID. +/// +/// @param highlight name e.g. 'Cursor', 'Normal' +/// @return the highlight id, else 0 if \p name does not exist +int syn_name2id(const char_u *name) { int i; char_u name_u[200]; @@ -7126,7 +7166,7 @@ int syn_name2id(char_u *name) /* * Return TRUE if highlight group "name" exists. */ -int highlight_exists(char_u *name) +int highlight_exists(const char_u *name) { return syn_name2id(name) > 0; } @@ -7154,12 +7194,13 @@ int syn_namen2id(char_u *linep, int len) return id; } -/* - * Find highlight group name in the table and return it's ID. - * The argument is a pointer to the name and the length of the name. - * If it doesn't exist yet, a new entry is created. - * Return 0 for failure. - */ +/// Find highlight group name in the table and return its ID. +/// If it doesn't exist yet, a new entry is created. +/// +/// @param pp Highlight group name +/// @param len length of \p pp +/// +/// @return 0 for failure else the id of the group int syn_check_group(char_u *pp, int len) { char_u *name = vim_strnsave(pp, len); @@ -7172,11 +7213,11 @@ int syn_check_group(char_u *pp, int len) return id; } -/* - * Add new highlight group and return it's ID. - * "name" must be an allocated string, it will be consumed. - * Return 0 for failure. - */ +/// Add new highlight group and return it's ID. +/// +/// @param name must be an allocated string, it will be consumed. +/// @return 0 for failure, else the allocated group id +/// @see syn_check_group syn_unadd_group static int syn_add_group(char_u *name) { char_u *p; @@ -7214,25 +7255,26 @@ static int syn_add_group(char_u *name) struct hl_group* hlgp = GA_APPEND_VIA_PTR(struct hl_group, &highlight_ga); memset(hlgp, 0, sizeof(*hlgp)); hlgp->sg_name = name; + hlgp->sg_rgb_bg = -1; + hlgp->sg_rgb_fg = -1; + hlgp->sg_rgb_sp = -1; hlgp->sg_name_u = vim_strsave_up(name); return highlight_ga.ga_len; /* ID is index plus one */ } -/* - * When, just after calling syn_add_group(), an error is discovered, this - * function deletes the new name. - */ +/// When, just after calling syn_add_group(), an error is discovered, this +/// function deletes the new name. static void syn_unadd_group(void) { - --highlight_ga.ga_len; + highlight_ga.ga_len--; xfree(HL_TABLE()[highlight_ga.ga_len].sg_name); xfree(HL_TABLE()[highlight_ga.ga_len].sg_name_u); } -/* - * Translate a group ID to highlight attributes. - */ + +/// Translate a group ID to highlight attributes. +/// @see syn_cterm_attr2entry int syn_id2attr(int hl_id) { struct hl_group *sgp; @@ -7286,110 +7328,34 @@ static void highlight_attr_set_all(void) } } -/* - * Translate the 'highlight' option into attributes in highlight_attr[] and - * set up the user highlights User1..9. A set of - * corresponding highlights to use on top of HLF_SNC is computed. - * Called only when the 'highlight' option has been changed and upon first - * screen redraw after any :highlight command. - * Return FAIL when an invalid flag is found in 'highlight'. OK otherwise. - */ -int highlight_changed(void) +/// Tranlate highlight groups into attributes in highlight_attr[] and set up +/// the user highlights User1..9. A set of corresponding highlights to use on +/// top of HLF_SNC is computed. Called only when nvim starts and upon first +/// screen redraw after any :highlight command. +void highlight_changed(void) { - int hlf; - int i; - char_u *p; int attr; - char_u *end; int id; char_u userhl[10]; int id_SNC = -1; int id_S = -1; int hlcnt; - static int hl_flags[HLF_COUNT] = HL_FLAGS; need_highlight_changed = FALSE; - /* - * Clear all attributes. - */ - for (hlf = 0; hlf < (int)HLF_COUNT; ++hlf) - highlight_attr[hlf] = 0; - - /* - * First set all attributes to their default value. - * Then use the attributes from the 'highlight' option. - */ - for (i = 0; i < 2; ++i) { - if (i) - p = p_hl; - else - p = get_highlight_default(); - if (p == NULL) /* just in case */ - continue; - - while (*p) { - for (hlf = 0; hlf < (int)HLF_COUNT; ++hlf) - if (hl_flags[hlf] == *p) - break; - ++p; - if (hlf == (int)HLF_COUNT || *p == NUL) - return FAIL; - - /* - * Allow several hl_flags to be combined, like "bu" for - * bold-underlined. - */ - attr = 0; - bool colon = false; - for (; *p && *p != ','; ++p) { // parse upto comma - if (ascii_iswhite(*p)) { // ignore white space - continue; - } - - if (colon) /* Combination with ':' is not allowed. */ - return FAIL; - - switch (*p) { - case 'b': attr |= HL_BOLD; - break; - case 'i': attr |= HL_ITALIC; - break; - case '-': - case 'n': /* no highlighting */ - break; - case 'r': attr |= HL_INVERSE; - break; - case 's': attr |= HL_STANDOUT; - break; - case 'u': attr |= HL_UNDERLINE; - break; - case 'c': attr |= HL_UNDERCURL; - break; - case ':': ++p; /* highlight group name */ - if (attr || *p == NUL) /* no combinations */ - return FAIL; - colon = true; - end = vim_strchr(p, ','); - if (end == NULL) - end = p + STRLEN(p); - id = syn_check_group(p, (int)(end - p)); - if (id == 0) - return FAIL; - attr = syn_id2attr(id); - p = end - 1; - if (hlf == (int)HLF_SNC) - id_SNC = syn_get_final_id(id); - else if (hlf == (int)HLF_S) - id_S = syn_get_final_id(id); - break; - default: return FAIL; - } - } - highlight_attr[hlf] = attr; - - p = skip_to_option_part(p); /* skip comma and spaces */ + /// Translate builtin highlight groups into attributes for quick lookup. + for (int hlf = 0; hlf < (int)HLF_COUNT; hlf++) { + id = syn_check_group((char_u *)hlf_names[hlf], STRLEN(hlf_names[hlf])); + if (id == 0) { + abort(); + } + attr = syn_id2attr(id); + if (hlf == (int)HLF_SNC) { + id_SNC = syn_get_final_id(id); + } else if (hlf == (int)HLF_S) { + id_S = syn_get_final_id(id); } + highlight_attr[hlf] = attr; } /* Setup the user highlights @@ -7454,49 +7420,47 @@ int highlight_changed(void) } } highlight_ga.ga_len = hlcnt; - - return OK; } /* * Handle command line completion for :highlight command. */ -void set_context_in_highlight_cmd(expand_T *xp, char_u *arg) +void set_context_in_highlight_cmd(expand_T *xp, const char *arg) { - char_u *p; - - /* Default: expand group names */ + // Default: expand group names. xp->xp_context = EXPAND_HIGHLIGHT; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; include_link = 2; include_default = 1; /* (part of) subcommand already typed */ if (*arg != NUL) { - p = skiptowhite(arg); - if (*p != NUL) { /* past "default" or group name */ + const char *p = (const char *)skiptowhite((const char_u *)arg); + if (*p != NUL) { // Past "default" or group name. include_default = 0; - if (STRNCMP("default", arg, p - arg) == 0) { - arg = skipwhite(p); - xp->xp_pattern = arg; - p = skiptowhite(arg); + if (strncmp("default", arg, p - arg) == 0) { + arg = (const char *)skipwhite((const char_u *)p); + xp->xp_pattern = (char_u *)arg; + p = (const char *)skiptowhite((const char_u *)arg); } if (*p != NUL) { /* past group name */ include_link = 0; - if (arg[1] == 'i' && arg[0] == 'N') + if (arg[1] == 'i' && arg[0] == 'N') { highlight_list(); - if (STRNCMP("link", arg, p - arg) == 0 - || STRNCMP("clear", arg, p - arg) == 0) { - xp->xp_pattern = skipwhite(p); - p = skiptowhite(xp->xp_pattern); - if (*p != NUL) { /* past first group name */ - xp->xp_pattern = skipwhite(p); - p = skiptowhite(xp->xp_pattern); + } + if (strncmp("link", arg, p - arg) == 0 + || strncmp("clear", arg, p - arg) == 0) { + xp->xp_pattern = skipwhite((const char_u *)p); + p = (const char *)skiptowhite(xp->xp_pattern); + if (*p != NUL) { // Past first group name. + xp->xp_pattern = skipwhite((const char_u *)p); + p = (const char *)skiptowhite(xp->xp_pattern); } } - if (*p != NUL) /* past group name(s) */ + if (*p != NUL) { // Past group name(s). xp->xp_context = EXPAND_NOTHING; + } } } } @@ -7517,7 +7481,7 @@ static void highlight_list(void) static void highlight_list_two(int cnt, int attr) { - msg_puts_attr((char_u *)&("N \bI \b! \b"[cnt / 11]), attr); + msg_puts_attr(&("N \bI \b! \b"[cnt / 11]), attr); msg_clr_eos(); ui_flush(); os_delay(cnt == 99 ? 40L : (long)cnt * 50L, false); @@ -7528,22 +7492,25 @@ static void highlight_list_two(int cnt, int attr) * Function given to ExpandGeneric() to obtain the list of group names. * Also used for synIDattr() function. */ -char_u *get_highlight_name(expand_T *xp, int idx) -{ - //TODO: 'xp' is unused - if (idx == highlight_ga.ga_len && include_none != 0) - return (char_u *)"none"; - if (idx == highlight_ga.ga_len + include_none && include_default != 0) - return (char_u *)"default"; - if (idx == highlight_ga.ga_len + include_none + include_default - && include_link != 0) - return (char_u *)"link"; - if (idx == highlight_ga.ga_len + include_none + include_default + 1 - && include_link != 0) - return (char_u *)"clear"; - if (idx < 0 || idx >= highlight_ga.ga_len) +const char *get_highlight_name(expand_T *const xp, const int idx) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + // TODO(justinmk): 'xp' is unused + if (idx == highlight_ga.ga_len && include_none != 0) { + return "none"; + } else if (idx == highlight_ga.ga_len + include_none + && include_default != 0) { + return "default"; + } else if (idx == highlight_ga.ga_len + include_none + include_default + && include_link != 0) { + return "link"; + } else if (idx == highlight_ga.ga_len + include_none + include_default + 1 + && include_link != 0) { + return "clear"; + } else if (idx < 0 || idx >= highlight_ga.ga_len) { return NULL; - return HL_TABLE()[idx].sg_name; + } + return (const char *)HL_TABLE()[idx].sg_name; } color_name_table_T color_name_table[] = { @@ -8230,7 +8197,14 @@ color_name_table_T color_name_table[] = { { NULL, 0 }, }; -RgbValue name_to_color(uint8_t *name) + +/// Translate to RgbValue if \p name is an hex value (e.g. #XXXXXX), +/// else look into color_name_table to translate a color name to its +/// hex value +/// +/// @param[in] name string value to convert to RGB +/// return the hex value or -1 if could not find a correct value +RgbValue name_to_color(const uint8_t *name) { if (name[0] == '#' && isxdigit(name[1]) && isxdigit(name[2]) diff --git a/src/nvim/syntax.h b/src/nvim/syntax.h index af2ac719c6..bb733ead30 100644 --- a/src/nvim/syntax.h +++ b/src/nvim/syntax.h @@ -4,11 +4,12 @@ #include <stdbool.h> #include "nvim/buffer_defs.h" +#include "nvim/ex_cmds_defs.h" -/* - * Terminal highlighting attribute bits. - * Attributes above HL_ALL are used for syntax highlighting. - */ +/// Terminal highlighting attribute bits. +/// Attributes above HL_ALL are used for syntax highlighting. +/// \addtogroup HL_ATTRIBUTES +/// @{ #define HL_NORMAL 0x00 #define HL_INVERSE 0x01 #define HL_BOLD 0x02 @@ -16,6 +17,7 @@ #define HL_UNDERLINE 0x08 #define HL_UNDERCURL 0x10 #define HL_STANDOUT 0x20 +/// @} #define HL_CONTAINED 0x01 /* not used on toplevel */ #define HL_TRANSP 0x02 /* has no highlighting */ diff --git a/src/nvim/syntax_defs.h b/src/nvim/syntax_defs.h index 8d207e6286..56fadbe7f6 100644 --- a/src/nvim/syntax_defs.h +++ b/src/nvim/syntax_defs.h @@ -1,10 +1,9 @@ #ifndef NVIM_SYNTAX_DEFS_H #define NVIM_SYNTAX_DEFS_H +#include "nvim/highlight_defs.h" #include "nvim/regexp_defs.h" -typedef int32_t RgbValue; - # define SST_MIN_ENTRIES 150 /* minimal size for state stack array */ # define SST_MAX_ENTRIES 1000 /* maximal size for state stack array */ # define SST_FIX_STATES 7 /* size of sst_stack[]. */ @@ -74,4 +73,14 @@ typedef struct attr_entry { int cterm_fg_color, cterm_bg_color; } attrentry_T; +#define ATTRENTRY_INIT { \ + .rgb_ae_attr = 0, \ + .cterm_ae_attr = 0, \ + .rgb_fg_color = -1, \ + .rgb_bg_color = -1, \ + .rgb_sp_color = -1, \ + .cterm_fg_color = 0, \ + .cterm_bg_color = 0, \ +} + #endif // NVIM_SYNTAX_DEFS_H diff --git a/src/nvim/tag.c b/src/nvim/tag.c index 0b76e36a6b..be9d621c7d 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -1,3 +1,6 @@ +// 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 + /* * Code to handle tags and the tag stack */ @@ -72,23 +75,18 @@ typedef struct { regmatch_T regmatch; /* regexp program, may be NULL */ } pat_T; -/* - * The matching tags are first stored in ga_match[]. In which one depends on - * the priority of the match. - * At the end, the matches from ga_match[] are concatenated, to make a list - * sorted on priority. - */ -#define MT_ST_CUR 0 /* static match in current file */ -#define MT_GL_CUR 1 /* global match in current file */ -#define MT_GL_OTH 2 /* global match in other file */ -#define MT_ST_OTH 3 /* static match in other file */ -#define MT_IC_ST_CUR 4 /* icase static match in current file */ -#define MT_IC_GL_CUR 5 /* icase global match in current file */ -#define MT_IC_GL_OTH 6 /* icase global match in other file */ -#define MT_IC_ST_OTH 7 /* icase static match in other file */ -#define MT_IC_OFF 4 /* add for icase match */ -#define MT_RE_OFF 8 /* add for regexp match */ -#define MT_MASK 7 /* mask for printing priority */ +// The matching tags are first stored in one of the hash tables. In +// which one depends on the priority of the match. +// ht_match[] is used to find duplicates, ga_match[] to keep them in sequence. +// At the end, the matches from ga_match[] are concatenated, to make a list +// sorted on priority. +#define MT_ST_CUR 0 // static match in current file +#define MT_GL_CUR 1 // global match in current file +#define MT_GL_OTH 2 // global match in other file +#define MT_ST_OTH 3 // static match in other file +#define MT_IC_OFF 4 // add for icase match +#define MT_RE_OFF 8 // add for regexp match +#define MT_MASK 7 // mask for printing priority #define MT_COUNT 16 static char *mt_names[MT_COUNT/2] = @@ -108,15 +106,6 @@ static char_u *topmsg = (char_u *)N_("E556: at top of tag stack"); static char_u *tagmatchname = NULL; /* name of last used tag */ /* - * We use ftello() here, if available. It returns off_t instead of long, - * which helps if long is 32 bit and off_t is 64 bit. - * We assume that when fseeko() is available then ftello() is too. - */ -#ifdef HAVE_FSEEKO -# define ftell ftello -#endif - -/* * Tag for preview window is remembered separately, to avoid messing up the * normal tagstack. */ @@ -210,10 +199,9 @@ do_tag ( clearpos(&saved_fmark.mark); /* shutup gcc 4.0 */ saved_fmark.fnum = 0; - /* - * Don't add a tag to the tagstack if 'tagstack' has been reset. - */ - if (!p_tgst && *tag != NUL) { + // Don't add a tag to the tagstack if 'tagstack' has been reset. + assert(tag != NULL); + if (!p_tgst && *tag != NUL) { // -V522 use_tagstack = false; new_tag = true; if (g_do_tagpreview != 0) { @@ -540,10 +528,11 @@ do_tag ( } vim_snprintf((char *)IObuff + 1, IOSIZE - 1, "%2d %s ", i + 1, mt_names[matches[i][0] & MT_MASK]); - msg_puts(IObuff); - if (tagp.tagkind != NULL) + msg_puts((const char *)IObuff); + if (tagp.tagkind != NULL) { msg_outtrans_len(tagp.tagkind, - (int)(tagp.tagkind_end - tagp.tagkind)); + (int)(tagp.tagkind_end - tagp.tagkind)); + } msg_advance(13); msg_outtrans_len_attr(tagp.tagname, (int)(tagp.tagname_end - tagp.tagname), @@ -595,7 +584,7 @@ do_tag ( } p = msg_outtrans_one(p, attr); if (*p == TAB) { - msg_puts_attr((char_u *)" ", attr); + msg_puts_attr(" ", attr); break; } if (*p == ':') @@ -678,7 +667,7 @@ do_tag ( fname = xmalloc(MAXPATHL + 1); cmd = xmalloc(CMDBUFFSIZE + 1); - list = list_alloc(); + list = tv_list_alloc(); for (i = 0; i < num_matches; ++i) { int len, cmd_len; @@ -777,20 +766,21 @@ do_tag ( cmd[len] = NUL; } - dict = dict_alloc(); - list_append_dict(list, dict); + dict = tv_dict_alloc(); + tv_list_append_dict(list, dict); - dict_add_nr_str(dict, "text", 0L, tag_name); - dict_add_nr_str(dict, "filename", 0L, fname); - dict_add_nr_str(dict, "lnum", lnum, NULL); - if (lnum == 0) - dict_add_nr_str(dict, "pattern", 0L, cmd); + tv_dict_add_str(dict, S_LEN("text"), (const char *)tag_name); + tv_dict_add_str(dict, S_LEN("filename"), (const char *)fname); + tv_dict_add_nr(dict, S_LEN("lnum"), lnum); + if (lnum == 0) { + tv_dict_add_str(dict, S_LEN("pattern"), (const char *)cmd); + } } vim_snprintf((char *)IObuff, IOSIZE, "ltag %s", tag); - set_errorlist(curwin, list, ' ', IObuff); + set_errorlist(curwin, list, ' ', IObuff, NULL); - list_free(list); + tv_list_free(list); xfree(fname); xfree(cmd); @@ -858,13 +848,15 @@ do_tag ( STRCAT(IObuff, _(" Using tag with different case!")); if ((num_matches > prev_num_matches || new_tag) && num_matches > 1) { - if (ic) - msg_attr(IObuff, hl_attr(HLF_W)); - else + if (ic) { + msg_attr((const char *)IObuff, hl_attr(HLF_W)); + } else { msg(IObuff); - msg_scroll = TRUE; /* don't overwrite this message */ - } else + } + msg_scroll = true; // Don't overwrite this message. + } else { give_warning(IObuff, ic); + } if (ic && !msg_scrolled && msg_silent == 0) { ui_flush(); os_delay(1000L, true); @@ -916,7 +908,8 @@ end_do_tag: /* Only store the new index when using the tagstack and it's valid. */ if (use_tagstack && tagstackidx <= curwin->w_tagstacklen) curwin->w_tagstackidx = tagstackidx; - postponed_split = 0; /* don't split next time */ + postponed_split = 0; // don't split next time + g_do_tagpreview = 0; // don't do tag preview next time return jumped_to_tag; } @@ -1057,6 +1050,7 @@ static void prepare_pats(pat_T *pats, int has_re) * TAG_REGEXP use "pat" as a regexp * TAG_NOIC don't always ignore case * TAG_KEEP_LANG keep language + * TAG_CSCOPE use cscope results for tags */ int find_tags ( @@ -1085,22 +1079,21 @@ find_tags ( char_u *p; char_u *s; int i; - int tag_file_sorted = NUL; /* !_TAG_FILE_SORTED value */ - struct tag_search_info /* Binary search file offsets */ - { - off_t low_offset; /* offset for first char of first line that - could match */ - off_t high_offset; /* offset of char after last line that could - match */ - off_t curr_offset; /* Current file offset in search range */ - off_t curr_offset_used; /* curr_offset used when skipping back */ - off_t match_offset; /* Where the binary search found a tag */ - int low_char; /* first char at low_offset */ - int high_char; /* first char at high_offset */ + int tag_file_sorted = NUL; // !_TAG_FILE_SORTED value + struct tag_search_info { // Binary search file offsets + off_T low_offset; // offset for first char of first line that + // could match + off_T high_offset; // offset of char after last line that could + // match + off_T curr_offset; // Current file offset in search range + off_T curr_offset_used; // curr_offset used when skipping back + off_T match_offset; // Where the binary search found a tag + int low_char; // first char at low_offset + int high_char; // first char at high_offset } search_info; - off_t filesize; + off_T filesize; int tagcmp; - off_t offset; + off_T offset; int round; enum { TS_START, /* at start of file */ @@ -1118,19 +1111,19 @@ find_tags ( int save_emsg_off; - struct match_found { - int len; /* nr of chars of match[] to be compared */ - char_u match[1]; /* actually longer */ - } *mfp, *mfp2; - garray_T ga_match[MT_COUNT]; - int match_count = 0; /* number of matches found */ + char_u *mfp; + garray_T ga_match[MT_COUNT]; // stores matches in sequence + hashtab_T ht_match[MT_COUNT]; // stores matches by key + hash_T hash = 0; + int match_count = 0; // number of matches found char_u **matches; int mtt; int help_save; int help_pri = 0; - char_u *help_lang_find = NULL; /* lang to be found */ - char_u help_lang[3]; /* lang of current tags file */ - char_u *saved_pat = NULL; /* copy of pat[] */ + char_u *help_lang_find = NULL; // lang to be found + char_u help_lang[3]; // lang of current tags file + char_u *saved_pat = NULL; // copy of pat[] + bool is_txt = false; pat_T orgpat; /* holds unconverted pattern info */ vimconv_T vimconv; @@ -1161,6 +1154,12 @@ find_tags ( case TC_MATCH: p_ic = false; break; + case TC_FOLLOWSCS: + p_ic = ignorecase(pat); + break; + case TC_SMART: + p_ic = ignorecase_opt(pat, true, true); + break; default: assert(false); } @@ -1174,16 +1173,23 @@ find_tags ( */ lbuf = xmalloc(lbuf_size); tag_fname = xmalloc(MAXPATHL + 1); - for (mtt = 0; mtt < MT_COUNT; ++mtt) - ga_init(&ga_match[mtt], (int)sizeof(struct match_found *), 100); + for (mtt = 0; mtt < MT_COUNT; mtt++) { + ga_init(&ga_match[mtt], sizeof(char_u *), 100); + hash_init(&ht_match[mtt]); + } STRCPY(tag_fname, "from cscope"); /* for error messages */ /* * Initialize a few variables */ - if (help_only) /* want tags from help file */ - curbuf->b_help = true; /* will be restored later */ + if (help_only) { // want tags from help file + curbuf->b_help = true; // will be restored later + } else if (use_cscope) { + // Make sure we don't mix help and cscope, confuses Coverity. + help_only = false; + curbuf->b_help = false; + } orgpat.len = (int)STRLEN(pat); if (curbuf->b_help) { @@ -1208,9 +1214,9 @@ find_tags ( if (has_re && orgpat.regmatch.regprog == NULL) goto findtag_end; - /* This is only to avoid a compiler warning for using search_info - * uninitialised. */ - memset(&search_info, 0, (size_t)1); + // This is only to avoid a compiler warning for using search_info + // uninitialised. + memset(&search_info, 0, 1); // -V512 /* * When finding a specified number of matches, first try with matching @@ -1222,6 +1228,14 @@ find_tags ( * When the tag file is case-fold sorted, it is either one or the other. * Only ignore case when TAG_NOIC not used or 'ignorecase' set. */ + // Set a flag if the file extension is .txt + if ((flags & TAG_KEEP_LANG) + && help_lang_find == NULL + && curbuf->b_fname != NULL + && (i = (int)STRLEN(curbuf->b_fname)) > 4 + && STRICMP(curbuf->b_fname + i - 4, ".txt") == 0) { + is_txt = true; + } orgpat.regmatch.rm_ic = ((p_ic || !noic) && (findall || orgpat.headlen == 0 || !p_tbs)); for (round = 1; round <= 2; ++round) { @@ -1237,13 +1251,19 @@ find_tags ( fp = NULL; // avoid GCC warning } else { if (curbuf->b_help) { - /* Prefer help tags according to 'helplang'. Put the - * two-letter language name in help_lang[]. */ - i = (int)STRLEN(tag_fname); - if (i > 3 && tag_fname[i - 3] == '-') - STRCPY(help_lang, tag_fname + i - 2); - else + // Keep en if the file extension is .txt + if (is_txt) { STRCPY(help_lang, "en"); + } else { + // Prefer help tags according to 'helplang'. Put the + // two-letter language name in help_lang[]. + i = (int)STRLEN(tag_fname); + if (i > 3 && tag_fname[i - 3] == '-') { + STRCPY(help_lang, tag_fname + i - 2); + } else { + STRCPY(help_lang, "en"); + } + } /* When searching for a specific language skip tags files * for other languages. */ @@ -1348,36 +1368,28 @@ find_tags ( if (state == TS_BINARY || state == TS_SKIP_BACK) { /* Adjust the search file offset to the correct position */ search_info.curr_offset_used = search_info.curr_offset; -#ifdef HAVE_FSEEKO - fseeko(fp, search_info.curr_offset, SEEK_SET); -#else - fseek(fp, (long)search_info.curr_offset, SEEK_SET); -#endif + vim_fseek(fp, search_info.curr_offset, SEEK_SET); eof = vim_fgets(lbuf, LSIZE, fp); if (!eof && search_info.curr_offset != 0) { /* The explicit cast is to work around a bug in gcc 3.4.2 * (repeated below). */ - search_info.curr_offset = ftell(fp); + search_info.curr_offset = vim_ftell(fp); if (search_info.curr_offset == search_info.high_offset) { - /* oops, gone a bit too far; try from low offset */ -#ifdef HAVE_FSEEKO - fseeko(fp, search_info.low_offset, SEEK_SET); -#else - fseek(fp, (long)search_info.low_offset, SEEK_SET); -#endif + // oops, gone a bit too far; try from low offset + vim_fseek(fp, search_info.low_offset, SEEK_SET); search_info.curr_offset = search_info.low_offset; } eof = vim_fgets(lbuf, LSIZE, fp); } /* skip empty and blank lines */ while (!eof && vim_isblankline(lbuf)) { - search_info.curr_offset = ftell(fp); + search_info.curr_offset = vim_ftell(fp); eof = vim_fgets(lbuf, LSIZE, fp); } if (eof) { /* Hit end of file. Skip backwards. */ state = TS_SKIP_BACK; - search_info.match_offset = ftell(fp); + search_info.match_offset = vim_ftell(fp); search_info.curr_offset = search_info.curr_offset_used; continue; } @@ -1493,10 +1505,10 @@ line_read_in: */ if (state == TS_BINARY) { // Get the tag file size. - if ((filesize = lseek(fileno(fp), (off_t)0L, SEEK_END)) <= 0) { + if ((filesize = vim_lseek(fileno(fp), (off_T)0L, SEEK_END)) <= 0) { state = TS_LINEAR; } else { - lseek(fileno(fp), (off_t)0L, SEEK_SET); + vim_lseek(fileno(fp), (off_T)0L, SEEK_SET); /* Calculate the first read offset in the file. Start * the search in the middle of the file. */ @@ -1534,11 +1546,7 @@ parse_line: /* Avoid getting stuck. */ linear = TRUE; state = TS_LINEAR; -# ifdef HAVE_FSEEKO - fseeko(fp, search_info.low_offset, SEEK_SET); -# else - fseek(fp, (long)search_info.low_offset, SEEK_SET); -# endif + vim_fseek(fp, search_info.low_offset, SEEK_SET); } continue; } @@ -1617,7 +1625,7 @@ parse_line: continue; } if (tagcmp < 0) { - search_info.curr_offset = ftell(fp); + search_info.curr_offset = vim_ftell(fp); if (search_info.curr_offset < search_info.high_offset) { search_info.low_offset = search_info.curr_offset; if (sortic) @@ -1653,10 +1661,11 @@ parse_line: } else if (state == TS_STEP_FORWARD) { assert(cmplen >= 0); if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0) { - if ((off_t)ftell(fp) > search_info.match_offset) - break; /* past last match */ - else - continue; /* before first match */ + if ((off_T)vim_ftell(fp) > search_info.match_offset) { + break; // past last match + } else { + continue; // before first match + } } } else /* skip this match if it can't match */ @@ -1727,10 +1736,10 @@ parse_line: match_re = TRUE; } - /* - * If a match is found, add it to ga_match[]. - */ + // If a match is found, add it to ht_match[] and ga_match[]. if (match) { + int len = 0; + if (use_cscope) { /* Don't change the ordering, always use the same table. */ mtt = MT_GL_OTH; @@ -1765,116 +1774,109 @@ parse_line: mtt += MT_RE_OFF; } - /* - * Add the found match in ga_match[mtt], avoiding duplicates. - * Store the info we need later, which depends on the kind of - * tags we are dealing with. - */ - ga_grow(&ga_match[mtt], 1); - { - int len; - - if (help_only) { + // Add the found match in ht_match[mtt] and ga_match[mtt]. + // Store the info we need later, which depends on the kind of + // tags we are dealing with. + if (help_only) { # define ML_EXTRA 3 - /* - * Append the help-heuristic number after the - * tagname, for sorting it later. - */ - *tagp.tagname_end = NUL; - len = (int)(tagp.tagname_end - tagp.tagname); - mfp = xmalloc(sizeof(struct match_found) + len + 10 + ML_EXTRA); - /* "len" includes the language and the NUL, but - * not the priority. */ - mfp->len = len + ML_EXTRA + 1; -#define ML_HELP_LEN 6 - p = mfp->match; - STRCPY(p, tagp.tagname); - p[len] = '@'; - STRCPY(p + len + 1, help_lang); - sprintf((char *)p + len + 1 + ML_EXTRA, "%06d", - help_heuristic(tagp.tagname, - match_re ? matchoff : 0, !match_no_ic) - + help_pri - ); - - *tagp.tagname_end = TAB; - } else if (name_only) { - if (get_it_again) { - char_u *temp_end = tagp.command; - - if (*temp_end == '/') - while (*temp_end && *temp_end != '\r' - && *temp_end != '\n' - && *temp_end != '$') - temp_end++; - - if (tagp.command + 2 < temp_end) { - len = (int)(temp_end - tagp.command - 2); - mfp = xmalloc(sizeof(struct match_found) + len); - mfp->len = len + 1; /* include the NUL */ - p = mfp->match; - STRLCPY(p, tagp.command + 2, len + 1); - } else - mfp = NULL; - get_it_again = FALSE; + // Append the help-heuristic number after the tagname, for + // sorting it later. The heuristic is ignored for + // detecting duplicates. + // The format is {tagname}@{lang}NUL{heuristic}NUL + *tagp.tagname_end = NUL; + len = (int)(tagp.tagname_end - tagp.tagname); + mfp = xmalloc(sizeof(char_u) + len + 10 + ML_EXTRA + 1); + + p = mfp; + STRCPY(p, tagp.tagname); + p[len] = '@'; + STRCPY(p + len + 1, help_lang); + snprintf((char *)p + len + 1 + ML_EXTRA, 10, "%06d", + help_heuristic(tagp.tagname, + match_re ? matchoff : 0, !match_no_ic) + + help_pri); + + *tagp.tagname_end = TAB; + } else if (name_only) { + if (get_it_again) { + char_u *temp_end = tagp.command; + + if (*temp_end == '/') { + while (*temp_end && *temp_end != '\r' + && *temp_end != '\n' + && *temp_end != '$') { + temp_end++; + } + } + + if (tagp.command + 2 < temp_end) { + len = (int)(temp_end - tagp.command - 2); + mfp = xmalloc(len + 2); + STRLCPY(mfp, tagp.command + 2, len + 1); } else { - len = (int)(tagp.tagname_end - tagp.tagname); - mfp = xmalloc(sizeof(struct match_found) + len); - mfp->len = len + 1; /* include the NUL */ - p = mfp->match; - STRLCPY(p, tagp.tagname, len + 1); - - /* if wanted, re-read line to get long form too */ - if (State & INSERT) - get_it_again = p_sft; + mfp = NULL; } + get_it_again = false; } else { - /* Save the tag in a buffer. - * Emacs tag: <mtt><tag_fname><NUL><ebuf><NUL><lbuf> - * other tag: <mtt><tag_fname><NUL><NUL><lbuf> - * without Emacs tags: <mtt><tag_fname><NUL><lbuf> - */ - len = (int)STRLEN(tag_fname) - + (int)STRLEN(lbuf) + 3; - mfp = xmalloc(sizeof(struct match_found) + len); - mfp->len = len; - p = mfp->match; - p[0] = mtt; - STRCPY(p + 1, tag_fname); + len = (int)(tagp.tagname_end - tagp.tagname); + mfp = xmalloc(sizeof(char_u) + len + 1); + STRLCPY(mfp, tagp.tagname, len + 1); + + // if wanted, re-read line to get long form too + if (State & INSERT) { + get_it_again = p_sft; + } + } + } else { +#define TAG_SEP 0x02 + size_t tag_fname_len = STRLEN(tag_fname); + // Save the tag in a buffer. + // Use 0x02 to separate fields (Can't use NUL, because the + // hash key is terminated by NUL). + // Emacs tag: <mtt><tag_fname><0x02><ebuf><0x02><lbuf><NUL> + // other tag: <mtt><tag_fname><0x02><0x02><lbuf><NUL> + // without Emacs tags: <mtt><tag_fname><0x02><lbuf><NUL> + // Here <mtt> is the "mtt" value plus 1 to avoid NUL. + len = (int)tag_fname_len + (int)STRLEN(lbuf) + 3; + mfp = xmalloc(sizeof(char_u) + len + 1); + p = mfp; + p[0] = mtt + 1; + STRCPY(p + 1, tag_fname); #ifdef BACKSLASH_IN_FILENAME - /* Ignore differences in slashes, avoid adding - * both path/file and path\file. */ - slash_adjust(p + 1); + // Ignore differences in slashes, avoid adding + // both path/file and path\file. + slash_adjust(p + 1); #endif - s = p + 1 + STRLEN(tag_fname) + 1; - STRCPY(s, lbuf); - } + p[tag_fname_len + 1] = TAG_SEP; + s = p + 1 + tag_fname_len + 1; + STRCPY(s, lbuf); + } - if (mfp != NULL) { - /* - * Don't add identical matches. - * This can take a lot of time when finding many - * matches, check for CTRL-C now and then. - * Add all cscope tags, because they are all listed. - */ - if (use_cscope) - i = -1; - else - for (i = ga_match[mtt].ga_len; --i >= 0 && !got_int; ) { - mfp2 = ((struct match_found **) - (ga_match[mtt].ga_data))[i]; - if (mfp2->len == mfp->len - && memcmp(mfp2->match, mfp->match, - (size_t)mfp->len) == 0) - break; - fast_breakcheck(); - } - if (i < 0) { - ((struct match_found **)(ga_match[mtt].ga_data)) + if (mfp != NULL) { + hashitem_T *hi; + + // Don't add identical matches. + // Add all cscope tags, because they are all listed. + // "mfp" is used as a hash key, there is a NUL byte to end + // the part matters for comparing, more bytes may follow + // after it. E.g. help tags store the priority after the + // NUL. + if (use_cscope) { + hash++; + } else { + hash = hash_hash(mfp); + } + hi = hash_lookup(&ht_match[mtt], (const char *)mfp, + STRLEN(mfp), hash); + if (HASHITEM_EMPTY(hi)) { + hash_add_item(&ht_match[mtt], hi, mfp, hash); + ga_grow(&ga_match[mtt], 1); + ((char_u **)(ga_match[mtt].ga_data)) [ga_match[mtt].ga_len++] = mfp; - ++match_count; - } else - xfree(mfp); + match_count++; + } else { + // duplicate tag, drop it + xfree(mfp); } } } @@ -1884,10 +1886,11 @@ parse_line: if (line_error) { EMSG2(_("E431: Format error in tags file \"%s\""), tag_fname); - if (!use_cscope) - EMSGN(_("Before byte %" PRId64), ftell(fp)); - stop_searching = TRUE; - line_error = FALSE; + if (!use_cscope) { + EMSGN(_("Before byte %" PRId64), vim_ftell(fp)); + } + stop_searching = true; + line_error = false; } if (!use_cscope) @@ -1949,21 +1952,29 @@ findtag_end: else matches = NULL; match_count = 0; - for (mtt = 0; mtt < MT_COUNT; ++mtt) { - for (int i = 0; i < ga_match[mtt].ga_len; ++i) { - mfp = ((struct match_found **)(ga_match[mtt].ga_data))[i]; - if (matches == NULL) + for (mtt = 0; mtt < MT_COUNT; mtt++) { + for (i = 0; i < ga_match[mtt].ga_len; i++) { + mfp = ((char_u **)(ga_match[mtt].ga_data))[i]; + if (matches == NULL) { xfree(mfp); - else { - /* To avoid allocating memory again we turn the struct - * match_found into a string. For help the priority was not - * included in the length. */ - memmove(mfp, mfp->match, - (size_t)(mfp->len + (help_only ? ML_HELP_LEN : 0))); + } else { + if (!name_only) { + // Change mtt back to zero-based. + *mfp = *mfp - 1; + + // change the TAG_SEP back to NUL + for (p = mfp + 1; *p != NUL; p++) { + if (*p == TAG_SEP) { + *p = NUL; + } + } + } matches[match_count++] = (char_u *)mfp; } } + ga_clear(&ga_match[mtt]); + hash_clear(&ht_match[mtt]); } *matchesp = matches; @@ -2175,7 +2186,7 @@ parse_tag_line ( * Return TRUE if it is a static tag and adjust *tagname to the real tag. * Return FALSE if it is not a static tag. */ -static int test_for_static(tagptrs_T *tagp) +static bool test_for_static(tagptrs_T *tagp) { char_u *p; @@ -2505,7 +2516,7 @@ jumpto_tag ( } } p_ws = save_p_ws; - p_ic = save_p_ic; + p_ic = save_p_ic; // -V519 p_scs = save_p_scs; /* A search command may have positioned the cursor beyond the end @@ -2740,8 +2751,8 @@ add_tag_field ( int len = 0; int retval; - /* check that the field name doesn't exist yet */ - if (dict_find(dict, (char_u *)field_name, -1) != NULL) { + // Check that the field name doesn't exist yet. + if (tv_dict_find(dict, field_name, -1) != NULL) { if (p_verbose > 0) { verbose_enter(); smsg(_("Duplicate field name: %s"), field_name); @@ -2762,26 +2773,25 @@ add_tag_field ( STRLCPY(buf, start, len + 1); } buf[len] = NUL; - retval = dict_add_nr_str(dict, field_name, 0L, buf); + retval = tv_dict_add_str(dict, field_name, STRLEN(field_name), + (const char *)buf); xfree(buf); return retval; } -/* - * Add the tags matching the specified pattern to the list "list" - * as a dictionary - */ -int get_tags(list_T *list, char_u *pat) +/// Add the tags matching the specified pattern "pat" to the list "list" +/// as a dictionary. Use "buf_fname" for priority, unless NULL. +int get_tags(list_T *list, char_u *pat, char_u *buf_fname) { int num_matches, i, ret; char_u **matches, *p; char_u *full_fname; dict_T *dict; tagptrs_T tp; - long is_static; + bool is_static; ret = find_tags(pat, &num_matches, &matches, - TAG_REGEXP | TAG_NOIC, (int)MAXCOL, NULL); + TAG_REGEXP | TAG_NOIC, (int)MAXCOL, buf_fname); if (ret == OK && num_matches > 0) { for (i = 0; i < num_matches; ++i) { int parse_result = parse_match(matches[i], &tp); @@ -2796,19 +2806,18 @@ int get_tags(list_T *list, char_u *pat) if (STRNCMP(tp.tagname, "!_TAG_", 6) == 0) continue; - dict = dict_alloc(); - 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, "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 - || dict_add_nr_str(dict, "static", is_static, NULL) == FAIL) + tp.tagkind ? tp.tagkind_end : NULL) == FAIL + || tv_dict_add_nr(dict, S_LEN("static"), is_static) == FAIL) { ret = FAIL; + } xfree(full_fname); diff --git a/src/nvim/tag.h b/src/nvim/tag.h index 5d4bcddf94..a8fddd05da 100644 --- a/src/nvim/tag.h +++ b/src/nvim/tag.h @@ -1,6 +1,9 @@ #ifndef NVIM_TAG_H #define NVIM_TAG_H +#include "nvim/types.h" +#include "nvim/ex_cmds_defs.h" + /* * Values for do_tag(). */ diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 30556a3835..3b278dc666 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -1,18 +1,20 @@ -// VT220/xterm-like terminal emulator implementation for nvim. Powered by -// libvterm (http://www.leonerd.org.uk/code/libvterm/). +// 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 + +// VT220/xterm-like terminal emulator. +// Powered by libvterm http://www.leonerd.org.uk/code/libvterm // // libvterm is a pure C99 terminal emulation library with abstract input and // display. This means that the library needs to read data from the master fd // and feed VTerm instances, which will invoke user callbacks with screen // update instructions that must be mirrored to the real display. // -// Keys are pressed in VTerm instances by calling +// Keys are sent to VTerm instances by calling // vterm_keyboard_key/vterm_keyboard_unichar, which generates byte streams that // must be fed back to the master fd. // -// This implementation uses nvim buffers as the display mechanism for both -// the visible screen and the scrollback buffer. When focused, the window -// "pins" to the bottom of the buffer and mirrors libvterm screen state. +// Nvim buffers are used as the display mechanism for both the visible screen +// and the scrollback buffer. // // When a line becomes invisible due to a decrease in screen height or because // a line was pushed up during normal terminal output, we store the line @@ -23,18 +25,17 @@ // scrollback buffer, which is mirrored in the nvim buffer displaying lines // that were previously invisible. // -// The vterm->nvim synchronization is performed in intervals of 10 -// milliseconds. This is done to minimize screen updates when receiving large -// bursts of data. +// The vterm->nvim synchronization is performed in intervals of 10 milliseconds, +// to minimize screen updates when receiving large bursts of data. // // This module is decoupled from the processes that normally feed it data, so // it's possible to use it as a general purpose console buffer (possibly as a // log/display mechanism for nvim in the future) // -// Inspired by vimshell (http://www.wana.at/vimshell/) and -// Conque (https://code.google.com/p/conque/). Libvterm usage instructions (plus -// some extra code) were taken from -// pangoterm (http://www.leonerd.org.uk/code/pangoterm/) +// Inspired by: vimshell http://www.wana.at/vimshell +// Conque https://code.google.com/p/conque +// Some code from pangoterm http://www.leonerd.org.uk/code/pangoterm + #include <assert.h> #include <stdio.h> #include <stdint.h> @@ -42,6 +43,7 @@ #include <vterm.h> +#include "nvim/log.h" #include "nvim/vim.h" #include "nvim/terminal.h" #include "nvim/message.h" @@ -80,17 +82,15 @@ typedef struct terminal_state { Terminal *term; int save_rd; // saved value of RedrawingDisabled bool close; - bool got_bs; // if the last input was <C-\> + bool got_bsl; // if the last input was <C-\> } TerminalState; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "terminal.c.generated.h" #endif -#define SCROLLBACK_BUFFER_DEFAULT_SIZE 1000 // Delay for refreshing the terminal buffer after receiving updates from -// libvterm. This is greatly improves performance when receiving large bursts -// of data. +// libvterm. Improves performance when receiving large bursts of data. #define REFRESH_DELAY 10 static TimeWatcher refresh_timer; @@ -102,27 +102,23 @@ typedef struct { } ScrollbackLine; struct terminal { - // options passed to terminal_open - TerminalOptions opts; - // libvterm structures + TerminalOptions opts; // options passed to terminal_open VTerm *vt; VTermScreen *vts; // buffer used to: // - convert VTermScreen cell arrays into utf8 strings // - receive data from libvterm as a result of key presses. char textbuf[0x1fff]; - // Scrollback buffer storage for libvterm. - // TODO(tarruda): Use a doubly-linked list - ScrollbackLine **sb_buffer; - // number of rows pushed to sb_buffer - size_t sb_current; - // sb_buffer size; - size_t sb_size; + + ScrollbackLine **sb_buffer; // Scrollback buffer storage for libvterm + size_t sb_current; // number of rows pushed to sb_buffer + size_t sb_size; // sb_buffer size // "virtual index" that points to the first sb_buffer row that we need to // push to the terminal buffer when refreshing the scrollback. When negative, // it actually points to entries that are no longer in sb_buffer (because the // window height has increased) and must be deleted from the terminal buffer int sb_pending; + // buf_T instance that acts as a "drawing surface" for libvterm // we can't store a direct reference to the buffer because the // refresh_timer_cb may be called after the buffer was freed, and there's @@ -130,20 +126,18 @@ struct terminal { handle_T buf_handle; // program exited bool closed, destroy; + // some vterm properties bool forward_mouse; - // invalid rows libvterm screen - int invalid_start, invalid_end; + int invalid_start, invalid_end; // invalid rows in libvterm screen struct { int row, col; bool visible; } cursor; - // which mouse button is pressed - int pressed_button; - // pending width/height - bool pending_resize; - // With a reference count of 0 the terminal can be freed. - size_t refcount; + int pressed_button; // which mouse button is pressed + bool pending_resize; // pending width/height + + size_t refcount; // reference count }; static VTermScreenCallbacks vterm_screen_callbacks = { @@ -174,7 +168,7 @@ void terminal_init(void) VTerm *vt = vterm_new(24, 80); VTermState *state = vterm_obtain_state(vt); - for (int color_index = 0; color_index < 256; color_index++) { + for (int color_index = 255; color_index >= 0; color_index--) { VTermColor color; // Some of the default 16 colors has the same color as the later // 240 colors. To avoid collisions, we will use the custom colors @@ -236,26 +230,26 @@ Terminal *terminal_open(TerminalOptions opts) rv->invalid_start = 0; rv->invalid_end = opts.height; refresh_screen(rv, curbuf); - set_option_value((uint8_t *)"buftype", 0, (uint8_t *)"terminal", OPT_LOCAL); - // some sane settings for terminal buffers - set_option_value((uint8_t *)"wrap", false, NULL, OPT_LOCAL); - set_option_value((uint8_t *)"number", false, NULL, OPT_LOCAL); - set_option_value((uint8_t *)"relativenumber", false, NULL, OPT_LOCAL); + set_option_value("buftype", 0, "terminal", OPT_LOCAL); // -V666 + + // Default settings for terminal buffers + curbuf->b_p_ma = false; // 'nomodifiable' + curbuf->b_p_ul = -1; // 'undolevels' + curbuf->b_p_scbk = p_scbk; // 'scrollback' + curbuf->b_p_tw = 0; // 'textwidth' + set_option_value("wrap", false, NULL, OPT_LOCAL); + set_option_value("list", false, NULL, OPT_LOCAL); buf_set_term_title(curbuf, (char *)curbuf->b_ffname); RESET_BINDING(curwin); - // Apply TermOpen autocmds so the user can configure the terminal + // Reset cursor in current window. + curwin->w_cursor = (pos_T){ .lnum = 1, .col = 0, .coladd = 0 }; + + // Apply TermOpen autocmds _before_ configuring the scrollback buffer. apply_autocmds(EVENT_TERMOPEN, NULL, NULL, false, curbuf); - // Configure the scrollback buffer. Try to get the size from: - // - // - b:terminal_scrollback_buffer_size - // - g:terminal_scrollback_buffer_size - // - SCROLLBACK_BUFFER_DEFAULT_SIZE - // - // but limit to 100k. - int size = get_config_int("terminal_scrollback_buffer_size"); - rv->sb_size = size > 0 ? (size_t)size : SCROLLBACK_BUFFER_DEFAULT_SIZE; - rv->sb_size = MIN(rv->sb_size, 100000); + // Configure the scrollback buffer. + rv->sb_size = curbuf->b_p_scbk < 0 + ? SB_MAX : (size_t)MAX(1, curbuf->b_p_scbk); rv->sb_buffer = xmalloc(sizeof(ScrollbackLine *) * rv->sb_size); if (!true_color) { @@ -307,8 +301,16 @@ void terminal_close(Terminal *term, char *msg) } term->forward_mouse = false; - term->closed = true; + + // flush any pending changes to the buffer + if (!exiting) { + block_autocmds(); + refresh_terminal(term); + unblock_autocmds(); + } + buf_T *buf = handle_get_buffer(term->buf_handle); + term->closed = true; if (!msg || exiting) { // If no msg was given, this was called by close_buffer(buffer.c). Or if @@ -334,22 +336,22 @@ void terminal_close(Terminal *term, char *msg) void terminal_resize(Terminal *term, uint16_t width, uint16_t height) { if (term->closed) { - // will be called after exited if two windows display the same terminal and - // one of the is closed as a consequence of pressing a key. + // If two windows display the same terminal and one is closed by keypress. return; } + bool force = width == UINT16_MAX || height == UINT16_MAX; int curwidth, curheight; vterm_get_size(term->vt, &curheight, &curwidth); - if (!width) { + if (force || !width) { width = (uint16_t)curwidth; } - if (!height) { + if (force || !height) { height = (uint16_t)curheight; } - if (curheight == height && curwidth == width) { + if (!force && curheight == height && curwidth == width) { return; } @@ -381,8 +383,18 @@ void terminal_enter(void) State = TERM_FOCUS; mapped_ctrl_c |= TERM_FOCUS; // Always map CTRL-C to avoid interrupt. RedrawingDisabled = false; - // go to the bottom when the terminal is focused - adjust_topline(s->term, buf, false); + + // Disable these options in terminal-mode. They are nonsense because cursor is + // placed at end of buffer to "follow" output. + win_T *save_curwin = curwin; + int save_w_p_cul = curwin->w_p_cul; + int save_w_p_cuc = curwin->w_p_cuc; + int save_w_p_rnu = curwin->w_p_rnu; + curwin->w_p_cul = false; + curwin->w_p_cuc = false; + curwin->w_p_rnu = false; + + adjust_topline(s->term, buf, 0); // scroll to end // erase the unfocused cursor invalidate_terminal(s->term, s->term->cursor.row, s->term->cursor.row + 1); showmode(); @@ -395,6 +407,12 @@ void terminal_enter(void) restart_edit = 0; State = save_state; RedrawingDisabled = s->save_rd; + if (save_curwin == curwin) { // save_curwin may be invalid (window closed)! + curwin->w_p_cul = save_w_p_cul; + curwin->w_p_cuc = save_w_p_cuc; + curwin->w_p_rnu = save_w_p_rnu; + } + // draw the unfocused cursor invalidate_terminal(s->term, s->term->cursor.row, s->term->cursor.row + 1); unshowmode(true); @@ -454,14 +472,14 @@ static int terminal_execute(VimState *state, int key) break; case Ctrl_N: - if (s->got_bs) { + if (s->got_bsl) { return 0; } // FALLTHROUGH default: - if (key == Ctrl_BSL && !s->got_bs) { - s->got_bs = true; + if (key == Ctrl_BSL && !s->got_bsl) { + s->got_bsl = true; break; } if (s->term->closed) { @@ -469,7 +487,7 @@ static int terminal_execute(VimState *state, int key) return 0; } - s->got_bs = false; + s->got_bsl = false; terminal_send_key(s->term, key); } @@ -590,8 +608,10 @@ void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, if (term->cursor.visible && term->cursor.row == row && term->cursor.col == col) { - attr_id = hl_combine_attr(attr_id, is_focused(term) && wp == curwin ? - hl_attr(HLF_TERM) : hl_attr(HLF_TERMNC)); + attr_id = hl_combine_attr(attr_id, + is_focused(term) && wp == curwin + ? win_hl_attr(wp, HLF_TERM) + : win_hl_attr(wp, HLF_TERMNC)); } term_attrs[col] = attr_id; @@ -626,15 +646,16 @@ static int term_movecursor(VTermPos new, VTermPos old, int visible, } static void buf_set_term_title(buf_T *buf, char *title) - FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_ALL { - Error err; - dict_set_value(buf->b_vars, - cstr_as_string("term_title"), - STRING_OBJ(cstr_as_string(title)), - false, - false, - &err); + Error err = ERROR_INIT; + dict_set_var(buf->b_vars, + STATIC_CSTR_AS_STRING("term_title"), + STRING_OBJ(cstr_as_string(title)), + false, + false, + &err); + api_clear_error(&err); } static int term_settermprop(VTermProp prop, VTermValue *val, void *data) @@ -669,14 +690,19 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *data) static int term_bell(void *data) { - ui_putc('\x07'); + ui_call_bell(); return 1; } -// the scrollback push/pop handlers were copied almost verbatim from pangoterm +// Scrollback push handler (from pangoterm). static int term_sb_push(int cols, const VTermScreenCell *cells, void *data) { Terminal *term = data; + + if (!term->sb_size) { + return 0; + } + // copy vterm cells into sb_buffer size_t c = (size_t)cols; ScrollbackLine *sbrow = NULL; @@ -688,10 +714,12 @@ static int term_sb_push(int cols, const VTermScreenCell *cells, void *data) xfree(term->sb_buffer[term->sb_current - 1]); } + // Make room at the start by shifting to the right. memmove(term->sb_buffer + 1, term->sb_buffer, sizeof(term->sb_buffer[0]) * (term->sb_current - 1)); } else if (term->sb_current > 0) { + // Make room at the start by shifting to the right. memmove(term->sb_buffer + 1, term->sb_buffer, sizeof(term->sb_buffer[0]) * term->sb_current); } @@ -701,6 +729,7 @@ static int term_sb_push(int cols, const VTermScreenCell *cells, void *data) sbrow->cols = c; } + // New row is added at the start of the storage buffer. term->sb_buffer[0] = sbrow; if (term->sb_current < term->sb_size) { term->sb_current++; @@ -716,6 +745,11 @@ static int term_sb_push(int cols, const VTermScreenCell *cells, void *data) return 1; } +/// Scrollback pop handler (from pangoterm). +/// +/// @param cols +/// @param cells VTerm state to update. +/// @param data Terminal static int term_sb_pop(int cols, VTermScreenCell *cells, void *data) { Terminal *term = data; @@ -728,24 +762,24 @@ static int term_sb_pop(int cols, VTermScreenCell *cells, void *data) term->sb_pending--; } - // restore vterm state - size_t c = (size_t)cols; ScrollbackLine *sbrow = term->sb_buffer[0]; term->sb_current--; + // Forget the "popped" row by shifting the rest onto it. memmove(term->sb_buffer, term->sb_buffer + 1, sizeof(term->sb_buffer[0]) * (term->sb_current)); - size_t cols_to_copy = c; + size_t cols_to_copy = (size_t)cols; if (cols_to_copy > sbrow->cols) { cols_to_copy = sbrow->cols; } // copy to vterm state memcpy(cells, sbrow->cells, sizeof(cells[0]) * cols_to_copy); - for (size_t col = cols_to_copy; col < c; col++) { + for (size_t col = cols_to_copy; col < (size_t)cols; col++) { cells[col].chars[0] = 0; cells[col].width = 1; } + xfree(sbrow); pmap_put(ptr_t)(invalidated_terminals, term, NULL); @@ -976,7 +1010,7 @@ static bool send_mouse_event(Terminal *term, int c) // terminal buffer refresh & misc {{{ -void fetch_row(Terminal *term, int row, int end_col) +static void fetch_row(Terminal *term, int row, int end_col) { int col = 0; size_t line_len = 0; @@ -1049,28 +1083,29 @@ static void refresh_terminal(Terminal *term) buf_T *buf = handle_get_buffer(term->buf_handle); bool valid = true; if (!buf || !(valid = buf_valid(buf))) { - // destroyed by `close_buffer`. Dont do anything else + // Destroyed by `close_buffer`. Do not do anything else. if (!valid) { term->buf_handle = 0; } return; } - bool pending_resize = term->pending_resize; + long ml_before = buf->b_ml.ml_line_count; WITH_BUFFER(buf, { refresh_size(term, buf); refresh_scrollback(term, buf); refresh_screen(term, buf); redraw_buf_later(buf, NOT_VALID); }); - adjust_topline(term, buf, pending_resize); + long ml_added = buf->b_ml.ml_line_count - ml_before; + adjust_topline(term, buf, ml_added); } -// libuv timer callback. This will enqueue on_refresh to be processed as an -// event. +// Calls refresh_terminal() on all invalidated_terminals. static void refresh_timer_cb(TimeWatcher *watcher, void *data) { - if (exiting) { - // bad things can happen if we redraw when exiting, and there's no need to - // update the buffer. + if (exiting // Cannot redraw (requires event loop) during teardown/exit. + // WM_LIST (^D) is not redrawn, unlike the normal wildmenu. So we must + // skip redraws to keep it visible. + || wild_menu_showing == WM_LIST) { goto end; } Terminal *term; @@ -1080,9 +1115,12 @@ static void refresh_timer_cb(TimeWatcher *watcher, void *data) map_foreach(invalidated_terminals, term, stub, { refresh_terminal(term); }); + bool any_visible = is_term_visible(); pmap_clear(ptr_t)(invalidated_terminals); unblock_autocmds(); - redraw(true); + if (any_visible) { + redraw(true); + } end: refresh_pending = false; } @@ -1101,7 +1139,37 @@ static void refresh_size(Terminal *term, buf_T *buf) term->opts.resize_cb((uint16_t)width, (uint16_t)height, term->opts.data); } -// Refresh the scrollback of a invalidated terminal +/// Adjusts scrollback storage after 'scrollback' option changed. +static void on_scrollback_option_changed(Terminal *term, buf_T *buf) +{ + const size_t scbk = curbuf->b_p_scbk < 0 + ? SB_MAX : (size_t)MAX(1, curbuf->b_p_scbk); + assert(term->sb_current < SIZE_MAX); + if (term->sb_pending > 0) { // Pending rows must be processed first. + abort(); + } + + // Delete lines exceeding the new 'scrollback' limit. + if (scbk < term->sb_current) { + size_t diff = term->sb_current - scbk; + for (size_t i = 0; i < diff; i++) { + ml_delete(1, false); + term->sb_current--; + xfree(term->sb_buffer[term->sb_current]); + } + deleted_lines(1, (long)diff); + } + + // Resize the scrollback storage. + size_t sb_region = sizeof(ScrollbackLine *) * scbk; + if (scbk != term->sb_size) { + term->sb_buffer = xrealloc(term->sb_buffer, sb_region); + } + + term->sb_size = scbk; +} + +// Refresh the scrollback of an invalidated terminal. static void refresh_scrollback(Terminal *term, buf_T *buf) { int width, height; @@ -1130,9 +1198,11 @@ static void refresh_scrollback(Terminal *term, buf_T *buf) ml_delete(buf->b_ml.ml_line_count, false); deleted_lines(buf->b_ml.ml_line_count, 1); } + + on_scrollback_option_changed(term, buf); } -// Refresh the screen(visible part of the buffer when the terminal is +// Refresh the screen (visible part of the buffer when the terminal is // focused) of a invalidated terminal static void refresh_screen(Terminal *term, buf_T *buf) { @@ -1141,8 +1211,7 @@ static void refresh_screen(Terminal *term, buf_T *buf) int height; int width; vterm_get_size(term->vt, &height, &width); - // It's possible that the terminal height decreased and `term->invalid_end` - // doesn't reflect it yet + // Terminal height may have decreased before `invalid_end` reflects it. term->invalid_end = MIN(term->invalid_end, height); for (int r = term->invalid_start, linenr = row_to_linenr(term, r); @@ -1165,6 +1234,18 @@ static void refresh_screen(Terminal *term, buf_T *buf) term->invalid_end = -1; } +/// @return true if any invalidated terminal buffer is visible to the user +static bool is_term_visible(void) +{ + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + if (wp->w_buffer->terminal + && pmap_has(ptr_t)(invalidated_terminals, wp->w_buffer->terminal)) { + return true; + } + } + return false; +} + static void redraw(bool restore_cursor) { Terminal *term = curbuf->terminal; @@ -1181,55 +1262,47 @@ static void redraw(bool restore_cursor) save_col = ui_current_col(); } block_autocmds(); - validate_cursor(); if (must_redraw) { update_screen(0); } - redraw_statuslines(); - - if (need_maketitle) { - maketitle(); - } - - showruler(false); - - if (term && is_focused(term)) { - curwin->w_wrow = term->cursor.row; - curwin->w_wcol = term->cursor.col + win_col_off(curwin); - setcursor(); - } else if (restore_cursor) { + if (restore_cursor) { ui_cursor_goto(save_row, save_col); } else if (term) { - // exiting terminal focus, put the window cursor in a valid position - int height, width; - vterm_get_size(term->vt, &height, &width); - curwin->w_wrow = height - 1; - curwin->w_wcol = 0; - setcursor(); + curwin->w_wrow = term->cursor.row; + curwin->w_wcol = term->cursor.col + win_col_off(curwin); + curwin->w_cursor.lnum = MIN(curbuf->b_ml.ml_line_count, + row_to_linenr(term, term->cursor.row)); + // Nudge cursor when returning to normal-mode. + int off = is_focused(term) ? 0 : (curwin->w_p_rl ? 1 : -1); + curwin->w_cursor.col = MAX(0, term->cursor.col + win_col_off(curwin) + off); + curwin->w_cursor.coladd = 0; + mb_check_adjust_col(curwin); } unblock_autocmds(); ui_flush(); } -static void adjust_topline(Terminal *term, buf_T *buf, bool force) +static void adjust_topline(Terminal *term, buf_T *buf, long added) { int height, width; vterm_get_size(term->vt, &height, &width); FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { if (wp->w_buffer == buf) { - // for every window that displays a terminal, ensure the cursor is in a - // valid line - wp->w_cursor.lnum = MIN(wp->w_cursor.lnum, buf->b_ml.ml_line_count); - if (force || curbuf != buf || is_focused(term)) { - // if the terminal is not in the current window or if it's focused, - // adjust topline/cursor so the window will "follow" the terminal - // output - wp->w_cursor.lnum = buf->b_ml.ml_line_count; + linenr_T ml_end = buf->b_ml.ml_line_count; + bool following = ml_end == wp->w_cursor.lnum + added; // cursor at end? + + if (following || (wp == curwin && is_focused(term))) { + // "Follow" the terminal output + wp->w_cursor.lnum = ml_end; set_topline(wp, MAX(wp->w_cursor.lnum - height + 1, 1)); + } else { + // Ensure valid cursor for each window displaying this terminal. + wp->w_cursor.lnum = MIN(wp->w_cursor.lnum, ml_end); } + mb_check_adjust_col(wp); } } } @@ -1251,12 +1324,14 @@ static bool is_focused(Terminal *term) #define GET_CONFIG_VALUE(k, o) \ do { \ - Error err; \ + Error err = ERROR_INIT; \ /* Only called from terminal_open where curbuf->terminal is the */ \ /* context */ \ o = dict_get_value(curbuf->b_vars, cstr_as_string(k), &err); \ + api_clear_error(&err); \ if (o.type == kObjectTypeNil) { \ o = dict_get_value(&globvardict, cstr_as_string(k), &err); \ + api_clear_error(&err); \ } \ } while (0) @@ -1271,17 +1346,6 @@ static char *get_config_string(char *key) return NULL; } -static int get_config_int(char *key) -{ - Object obj; - GET_CONFIG_VALUE(key, obj); - if (obj.type == kObjectTypeInteger) { - return (int)obj.data.integer; - } - api_free_object(obj); - return 0; -} - // }}} // vim: foldmethod=marker diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 814c0bc3cb..96de7224c5 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -1,14 +1,16 @@ -# +# vim: noet ts=8 # Makefile to run all tests for Vim # -export SHELL := sh - -VIMPROG := ../../../build/bin/nvim +NVIM_PRG ?= ../../../build/bin/nvim +TMPDIR ?= Xtest-tmpdir SCRIPTSOURCE := ../../../runtime -SCRIPTS := \ - test8.out \ +export SHELL := sh +export NVIM_PRG := $(NVIM_PRG) +export TMPDIR + +SCRIPTS ?= \ test13.out \ test14.out \ test17.out \ @@ -22,33 +24,60 @@ SCRIPTS := \ test52.out \ test53.out \ test64.out \ - test69.out \ test73.out \ test79.out \ - test_marks.out \ -# Tests using runtest.vim.vim. +# Tests using runtest.vim. # Keep test_alot*.res as the last one, sort the others. -NEW_TESTS = \ +NEW_TESTS ?= \ + test_autocmd.res \ test_bufwintabinfo.res \ + test_charsearch.res \ test_cmdline.res \ + test_command_count.res \ test_cscope.res \ + test_digraph.res \ test_diffmode.res \ + test_farsi.res \ + test_filter_map.res \ + test_fnameescape.res \ + test_fold.res \ + test_glob2regpat.res \ + test_gf.res \ test_gn.res \ test_hardcopy.res \ test_help_tagjump.res \ + test_hide.res \ test_history.res \ + test_hlsearch.res \ + test_increment.res \ + test_increment_dbcs.res \ + test_lambda.res \ test_langmap.res \ + test_marks.res \ test_match.res \ test_matchadd_conceal.res \ + test_matchadd_conceal_utf8.res \ + test_nested_function.res \ + test_normal.res \ test_quickfix.res \ + test_search.res \ test_signs.res \ + test_smartindent.res \ + test_stat.res \ + test_startup.res \ + test_startup_utf8.res \ + test_substitute.res \ test_syntax.res \ + test_tabpage.res \ + test_textobjects.res \ test_timers.res \ + test_undo.res \ test_usercommands.res \ - test_viml.res \ + test_vimscript.res \ test_visual.res \ test_window_id.res \ + test_writefile.res \ test_alot.res SCRIPTS_GUI := test16.out @@ -100,13 +129,13 @@ report: echo ALL DONE; \ fi" -test1.out: $(VIMPROG) +test1.out: $(NVIM_PRG) -$(SCRIPTS) $(SCRIPTS_GUI): $(VIMPROG) test1.out +$(SCRIPTS) $(SCRIPTS_GUI): $(NVIM_PRG) test1.out RM_ON_RUN := test.out X* viminfo RM_ON_START := test.ok -RUN_VIM := VIMRUNTIME=$(SCRIPTSOURCE); export VIMRUNTIME; $(TOOL) $(VIMPROG) -u unix.vim -U NONE -i viminfo --noplugin -s dotest.in +RUN_VIM := VIMRUNTIME=$(SCRIPTSOURCE); export VIMRUNTIME; $(TOOL) $(NVIM_PRG) -u unix.vim -U NONE -i viminfo --headless --noplugin -s dotest.in clean: -rm -rf *.out \ @@ -122,10 +151,12 @@ clean: .*.swp \ .*.swo \ .gdbinit \ + $(TMPDIR) \ del test1.out: .gdbinit test1.in -rm -rf $*.failed $(RM_ON_RUN) $(RM_ON_START) wrongtermsize + mkdir -p $(TMPDIR) $(RUN_VIM) $*.in @/bin/sh -c "if test -e wrongtermsize; then \ echo; \ @@ -143,6 +174,7 @@ test1.out: .gdbinit test1.in %.out: %.in .gdbinit -rm -rf $*.failed test.ok $(RM_ON_RUN) + mkdir -p $(TMPDIR) cp $*.ok test.ok # Sleep a moment to avoid that the xterm title is messed up. # 200 msec is sufficient, but only modern sleep supports a fraction of @@ -175,7 +207,7 @@ nolog: # New style of tests uses Vim script with assert calls. These are easier # to write and a lot easier to read and debug. # Limitation: Only works with the +eval feature. -RUN_VIMTEST = VIMRUNTIME=$(SCRIPTSOURCE); export VIMRUNTIME; $(VALGRIND) $(VIMPROG) -u unix.vim -U NONE --noplugin +RUN_VIMTEST = VIMRUNTIME=$(SCRIPTSOURCE); export VIMRUNTIME; $(TOOL) $(NVIM_PRG) -u unix.vim -U NONE --headless --noplugin newtests: newtestssilent @/bin/sh -c "if test -f messages && grep -q 'FAILED' messages; then \ @@ -185,4 +217,5 @@ newtests: newtestssilent newtestssilent: $(NEW_TESTS) %.res: %.vim .gdbinit + mkdir -p $(TMPDIR) $(RUN_VIMTEST) -u NONE -S runtest.vim $*.vim diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim index 20863bbaf3..39ffabc024 100644 --- a/src/nvim/testdir/runtest.vim +++ b/src/nvim/testdir/runtest.vim @@ -39,6 +39,9 @@ if &lines < 24 || &columns < 80 cquit endif +" Common with all tests on all systems. +source setup.vim + " This also enables use of line continuation. set viminfo+=nviminfo @@ -62,14 +65,25 @@ set shellslash " Make sure $HOME does not get read or written. let $HOME = '/does/not/exist' -" Align with vim defaults. +" Prepare for calling garbagecollect_for_testing(). +let v:testing = 1 + +" Align Nvim defaults to Vim. set directory^=. -set nohidden +set backspace= +set nohidden smarttab noautoindent noautoread complete-=i noruler noshowcmd +set listchars=eol:$ +" Prevent Nvim log from writing to stderr. +let $NVIM_LOG_FILE = exists($NVIM_LOG_FILE) ? $NVIM_LOG_FILE : 'Xnvim.log' -function RunTheTest(test) +func RunTheTest(test) echo 'Executing ' . a:test if exists("*SetUp") - call SetUp() + try + call SetUp() + catch + call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) + endtry endif call add(s:messages, 'Executing ' . a:test) @@ -84,16 +98,83 @@ function RunTheTest(test) endtry if exists("*TearDown") - call TearDown() + try + call TearDown() + catch + call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) + endtry endif " Close any extra windows and make the current one not modified. - while winnr('$') > 1 + while 1 + let wincount = winnr('$') + if wincount == 1 + break + endif bwipe! + if wincount == winnr('$') + " Did not manage to close a window. + only! + break + endif endwhile set nomodified endfunc +func AfterTheTest() + if len(v:errors) > 0 + let s:fail += 1 + call add(s:errors, 'Found errors in ' . s:test . ':') + call extend(s:errors, v:errors) + let v:errors = [] + endif +endfunc + +" This function can be called by a test if it wants to abort testing. +func FinishTesting() + call AfterTheTest() + + " Don't write viminfo on exit. + set viminfo= + + if s:fail == 0 + " Success, create the .res file so that make knows it's done. + exe 'split ' . fnamemodify(g:testname, ':r') . '.res' + write + endif + + if len(s:errors) > 0 + " Append errors to test.log + split test.log + call append(line('$'), '') + call append(line('$'), 'From ' . g:testname . ':') + call append(line('$'), s:errors) + write + endif + + let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test') + echo message + call add(s:messages, message) + if s:fail > 0 + let message = s:fail . ' FAILED:' + echo message + call add(s:messages, message) + call extend(s:messages, s:errors) + endif + + " Add SKIPPED messages + call extend(s:messages, s:skipped) + + " Append messages to the file "messages" + split messages + call append(line('$'), '') + call append(line('$'), 'From ' . g:testname . ':') + call append(line('$'), s:messages) + write + + qall! +endfunc + " Source the test script. First grab the file name, in case the script " navigates away. g:testname can be used by the tests. let g:testname = expand('%') @@ -102,7 +183,7 @@ let s:fail = 0 let s:errors = [] let s:messages = [] let s:skipped = [] -if expand('%') =~ 'test_viml.vim' +if expand('%') =~ 'test_vimscript.vim' " this test has intentional s:errors, don't use try/catch. source % else @@ -115,7 +196,11 @@ else endif " Names of flaky tests. -let s:flaky = [] +let s:flaky = [ + \ 'Test_with_partial_callback()', + \ 'Test_oneshot()', + \ 'Test_lambda_with_timer()', + \ ] " Locate Test_ functions and execute them. set nomore @@ -134,56 +219,14 @@ for s:test in sort(s:tests) call RunTheTest(s:test) if len(v:errors) > 0 && index(s:flaky, s:test) >= 0 - call add(s:messages, 'Flaky test failed, running it again') - let v:errors = [] - call RunTheTest(s:test) - endif - - if len(v:errors) > 0 - let s:fail += 1 - call add(s:errors, 'Found errors in ' . s:test . ':') - call extend(s:errors, v:errors) + call add(s:messages, 'Flaky test failed, running it again') let v:errors = [] + call RunTheTest(s:test) endif + call AfterTheTest() endfor -" Don't write viminfo on exit. -set viminfo= - -if s:fail == 0 - " Success, create the .res file so that make knows it's done. - exe 'split ' . fnamemodify(g:testname, ':r') . '.res' - write -endif - -if len(s:errors) > 0 - " Append errors to test.log - split test.log - call append(line('$'), '') - call append(line('$'), 'From ' . g:testname . ':') - call append(line('$'), s:errors) - write -endif - -let message = 'Executed ' . s:done . (s:done > 1 ? ' tests': ' test') -echo message -call add(s:messages, message) -if s:fail > 0 - let message = s:fail . ' FAILED' - echo message - call add(s:messages, message) - call extend(s:messages, s:errors) -endif - -" Add SKIPPED messages -call extend(s:messages, s:skipped) - -" Append messages to the file "messages" -split messages -call append(line('$'), '') -call append(line('$'), 'From ' . g:testname . ':') -call append(line('$'), s:messages) -write +call FinishTesting() -qall! +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/samples/memfile_test.c b/src/nvim/testdir/samples/memfile_test.c new file mode 100644 index 0000000000..3c8f108255 --- /dev/null +++ b/src/nvim/testdir/samples/memfile_test.c @@ -0,0 +1,146 @@ +// 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 + +/* vi:set ts=8 sts=4 sw=4 noet: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ + +/* + * memfile_test.c: Unittests for memfile.c + * Mostly by Ivan Krasilnikov. + */ + +#undef NDEBUG +#include <assert.h> + +/* Must include main.c because it contains much more than just main() */ +#define NO_VIM_MAIN +#include "main.c" + +/* This file has to be included because the tested functions are static */ +#include "memfile.c" + +#define index_to_key(i) ((i) ^ 15167) +#define TEST_COUNT 50000 + +/* + * Test mf_hash_*() functions. + */ + static void +test_mf_hash(void) +{ + mf_hashtab_T ht; + mf_hashitem_T *item; + blocknr_T key; + long_u i; + long_u num_buckets; + + mf_hash_init(&ht); + + /* insert some items and check invariants */ + for (i = 0; i < TEST_COUNT; i++) + { + assert(ht.mht_count == i); + + /* check that number of buckets is a power of 2 */ + num_buckets = ht.mht_mask + 1; + assert(num_buckets > 0 && (num_buckets & (num_buckets - 1)) == 0); + + /* check load factor */ + assert(ht.mht_count <= (num_buckets << MHT_LOG_LOAD_FACTOR)); + + if (i < (MHT_INIT_SIZE << MHT_LOG_LOAD_FACTOR)) + { + /* first expansion shouldn't have occurred yet */ + assert(num_buckets == MHT_INIT_SIZE); + assert(ht.mht_buckets == ht.mht_small_buckets); + } + else + { + assert(num_buckets > MHT_INIT_SIZE); + assert(ht.mht_buckets != ht.mht_small_buckets); + } + + key = index_to_key(i); + assert(mf_hash_find(&ht, key) == NULL); + + /* allocate and add new item */ + item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE); + assert(item != NULL); + item->mhi_key = key; + mf_hash_add_item(&ht, item); + + assert(mf_hash_find(&ht, key) == item); + + if (ht.mht_mask + 1 != num_buckets) + { + /* hash table was expanded */ + assert(ht.mht_mask + 1 == num_buckets * MHT_GROWTH_FACTOR); + assert(i + 1 == (num_buckets << MHT_LOG_LOAD_FACTOR)); + } + } + + /* check presence of inserted items */ + for (i = 0; i < TEST_COUNT; i++) + { + key = index_to_key(i); + item = mf_hash_find(&ht, key); + assert(item != NULL); + assert(item->mhi_key == key); + } + + /* delete some items */ + for (i = 0; i < TEST_COUNT; i++) + { + if (i % 100 < 70) + { + key = index_to_key(i); + item = mf_hash_find(&ht, key); + assert(item != NULL); + assert(item->mhi_key == key); + + mf_hash_rem_item(&ht, item); + assert(mf_hash_find(&ht, key) == NULL); + + mf_hash_add_item(&ht, item); + assert(mf_hash_find(&ht, key) == item); + + mf_hash_rem_item(&ht, item); + assert(mf_hash_find(&ht, key) == NULL); + + vim_free(item); + } + } + + /* check again */ + for (i = 0; i < TEST_COUNT; i++) + { + key = index_to_key(i); + item = mf_hash_find(&ht, key); + + if (i % 100 < 70) + { + assert(item == NULL); + } + else + { + assert(item != NULL); + assert(item->mhi_key == key); + } + } + + /* free hash table and all remaining items */ + mf_hash_free_all(&ht); +} + + int +main(void) +{ + test_mf_hash(); + return 0; +} diff --git a/src/nvim/testdir/setup.vim b/src/nvim/testdir/setup.vim new file mode 100644 index 0000000000..06f2199214 --- /dev/null +++ b/src/nvim/testdir/setup.vim @@ -0,0 +1,12 @@ +" Common preparations for running tests. + +set noruler +set noshowcmd +set belloff= + +" Make sure 'runtimepath' and 'packpath' does not include $HOME. +set rtp=$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after +let &packpath = &rtp + +" Make sure $HOME does not get read or written. +let $HOME = '/does/not/exist' diff --git a/src/nvim/testdir/shared.vim b/src/nvim/testdir/shared.vim new file mode 100644 index 0000000000..72cfea96c6 --- /dev/null +++ b/src/nvim/testdir/shared.vim @@ -0,0 +1,214 @@ +" Functions shared by several tests. + +" Get the name of the Python executable. +" Also keeps it in s:python. +func PythonProg() + " This test requires the Python command to run the test server. + " This most likely only works on Unix and Windows. + if has('unix') + " We also need the job feature or the pkill command to make sure the server + " can be stopped. + if !(executable('python') && (has('job') || executable('pkill'))) + return '' + endif + let s:python = 'python' + elseif has('win32') + " Use Python Launcher for Windows (py.exe) if available. + if executable('py.exe') + let s:python = 'py.exe' + elseif executable('python.exe') + let s:python = 'python.exe' + else + return '' + endif + else + return '' + endif + return s:python +endfunc + +" Run "cmd". Returns the job if using a job. +func RunCommand(cmd) + let job = 0 + if has('job') + let job = job_start(a:cmd, {"stoponexit": "hup"}) + call job_setoptions(job, {"stoponexit": "kill"}) + elseif has('win32') + exe 'silent !start cmd /c start "test_channel" ' . a:cmd + else + exe 'silent !' . a:cmd . '&' + endif + return job +endfunc + +" Read the port number from the Xportnr file. +func GetPort() + let l = [] + for i in range(200) + try + let l = readfile("Xportnr") + catch + endtry + if len(l) >= 1 + break + endif + sleep 10m + endfor + call delete("Xportnr") + + if len(l) == 0 + " Can't make the connection, give up. + return 0 + endif + return l[0] +endfunc + +" Run a Python server for "cmd" and call "testfunc". +" Always kills the server before returning. +func RunServer(cmd, testfunc, args) + " The Python program writes the port number in Xportnr. + call delete("Xportnr") + + if len(a:args) == 1 + let arg = ' ' . a:args[0] + else + let arg = '' + endif + let pycmd = s:python . " " . a:cmd . arg + + try + let g:currentJob = RunCommand(pycmd) + + " Wait for up to 2 seconds for the port number to be there. + let port = GetPort() + if port == 0 + call assert_false(1, "Can't start " . a:cmd) + return + endif + + call call(function(a:testfunc), [port]) + catch + call assert_false(1, 'Caught exception: "' . v:exception . '" in ' . v:throwpoint) + finally + call s:kill_server(a:cmd) + endtry +endfunc + +func s:kill_server(cmd) + if has('job') + if exists('g:currentJob') + call job_stop(g:currentJob) + unlet g:currentJob + endif + elseif has('win32') + let cmd = substitute(a:cmd, ".py", '', '') + call system('taskkill /IM ' . s:python . ' /T /F /FI "WINDOWTITLE eq ' . cmd . '"') + else + call system("pkill -f " . a:cmd) + endif +endfunc + +" Wait for up to a second for "expr" to become true. +" Return time slept in milliseconds. With the +reltime feature this can be +" more than the actual waiting time. Without +reltime it can also be less. +func WaitFor(expr) + " using reltime() is more accurate, but not always available + if has('reltime') + let start = reltime() + else + let slept = 0 + endif + for i in range(100) + try + if eval(a:expr) + if has('reltime') + return float2nr(reltimefloat(reltime(start)) * 1000) + endif + return slept + endif + catch + endtry + if !has('reltime') + let slept += 10 + endif + sleep 10m + endfor + return 1000 +endfunc + +" Wait for up to a given milliseconds. +" With the +timers feature this waits for key-input by getchar(), Resume() +" feeds key-input and resumes process. Return time waited in milliseconds. +" Without +timers it uses simply :sleep. +func Standby(msec) + if has('timers') + let start = reltime() + let g:_standby_timer = timer_start(a:msec, function('s:feedkeys')) + call getchar() + return float2nr(reltimefloat(reltime(start)) * 1000) + else + execute 'sleep ' a:msec . 'm' + return a:msec + endif +endfunc + +func Resume() + if exists('g:_standby_timer') + call timer_stop(g:_standby_timer) + call s:feedkeys(0) + unlet g:_standby_timer + endif +endfunc + +func s:feedkeys(timer) + call feedkeys('x', 'nt') +endfunc + +" Get the command to run Vim, with -u NONE and --headless arguments. +" Returns an empty string on error. +func GetVimCommand() + let cmd = v:progpath + let cmd = substitute(cmd, '-u \f\+', '-u NONE', '') + if cmd !~ '-u NONE' + let cmd = cmd . ' -u NONE' + endif + let cmd .= ' --headless -i NONE' + let cmd = substitute(cmd, 'VIMRUNTIME=.*VIMRUNTIME;', '', '') + return cmd +endfunc + +" Run Vim, using the "vimcmd" file and "-u NORC". +" "before" is a list of Vim commands to be executed before loading plugins. +" "after" is a list of Vim commands to be executed after loading plugins. +" Plugins are not loaded, unless 'loadplugins' is set in "before". +" Return 1 if Vim could be executed. +func RunVim(before, after, arguments) + return RunVimPiped(a:before, a:after, a:arguments, '') +endfunc + +func RunVimPiped(before, after, arguments, pipecmd) + let $NVIM_LOG_FILE = exists($NVIM_LOG_FILE) ? $NVIM_LOG_FILE : 'Xnvim.log' + let cmd = GetVimCommand() + if cmd == '' + return 0 + endif + let args = '' + if len(a:before) > 0 + call writefile(a:before, 'Xbefore.vim') + let args .= ' --cmd "so Xbefore.vim"' + endif + if len(a:after) > 0 + call writefile(a:after, 'Xafter.vim') + let args .= ' -S Xafter.vim' + endif + + exe "silent !" . a:pipecmd . cmd . args . ' ' . a:arguments + + if len(a:before) > 0 + call delete('Xbefore.vim') + endif + if len(a:after) > 0 + call delete('Xafter.vim') + endif + return 1 +endfunc diff --git a/src/nvim/testdir/test13.in b/src/nvim/testdir/test13.in deleted file mode 100644 index fa9ba312b7..0000000000 --- a/src/nvim/testdir/test13.in +++ /dev/null @@ -1,63 +0,0 @@ -Tests for autocommands on :close command - -Write three files and open them, each in a window. -Then go to next window, with autocommand that deletes the previous one. -Do this twice, writing the file. - -Also test deleting the buffer on a Unload event. If this goes wrong there -will be the ATTENTION prompt. - -Also test changing buffers in a BufDel autocommand. If this goes wrong there -are ml_line errors and/or a Crash. - -STARTTEST -:/^start of testfile/,/^end of testfile/w! Xtestje1 -:/^start of testfile/,/^end of testfile/w! Xtestje2 -:/^start of testfile/,/^end of testfile/w! Xtestje3 -:e Xtestje1 -otestje1 -:w -:sp Xtestje2 -otestje2 -:w -:sp Xtestje3 -otestje3 -:w - -:au WinLeave Xtestje2 bwipe - -:w! test.out -:au WinLeave Xtestje1 bwipe Xtestje3 -:close -:w >>test.out -:e Xtestje1 -:bwipe Xtestje2 Xtestje3 test.out -:au! -:au! BufUnload Xtestje1 bwipe -:e Xtestje3 -:w >>test.out -:e Xtestje2 -:sp Xtestje1 -:e -:w >>test.out -:au! -:only -:e Xtestje1 -:bwipe Xtestje2 Xtestje3 test.out test13.in -:au BufWipeout Xtestje1 buf Xtestje1 -:bwipe -:w >>test.out -:only -:new|set buftype=help -:wincmd w -:1quit -:$put ='Final line' -:$w >>test.out -:qa! -ENDTEST - -start of testfile - contents - contents - contents -end of testfile diff --git a/src/nvim/testdir/test13.ok b/src/nvim/testdir/test13.ok deleted file mode 100644 index 66ebce63f7..0000000000 --- a/src/nvim/testdir/test13.ok +++ /dev/null @@ -1,31 +0,0 @@ -start of testfile -testje1 - contents - contents - contents -end of testfile -start of testfile -testje1 - contents - contents - contents -end of testfile -start of testfile -testje3 - contents - contents - contents -end of testfile -start of testfile -testje2 - contents - contents - contents -end of testfile -start of testfile -testje1 - contents - contents - contents -end of testfile -Final line diff --git a/src/nvim/testdir/test17.in b/src/nvim/testdir/test17.in index 83abe17770..1a4ac6b6d1 100644 --- a/src/nvim/testdir/test17.in +++ b/src/nvim/testdir/test17.in @@ -4,13 +4,7 @@ Tests for: STARTTEST :set isfname=@,48-57,/,.,-,_,+,,,$,:,~,{,} -:function! DeleteDirectory(dir) -: if has("win16") || has("win32") || has("win64") || has("dos16") || has("dos32") -: exec "silent !rmdir /Q /S " . a:dir -: else -: exec "silent !rm -rf " . a:dir -: endif -:endfun +:" :if has("unix") :let $CDIR = "." /CDIR @@ -36,7 +30,7 @@ STARTTEST :" check for 'include' without \zs or \ze :lang C :call delete("./Xbase.a") -:call DeleteDirectory("Xdir1") +:call delete("Xdir1", "rf") :!mkdir Xdir1 :!mkdir "Xdir1/dir2" :e! Xdir1/dir2/foo.a @@ -61,7 +55,7 @@ ENDTEST STARTTEST :" check for 'include' with \zs and \ze :call delete("./Xbase.b") -:call DeleteDirectory("Xdir1") +:call delete("Xdir1", "rf") :!mkdir Xdir1 :!mkdir "Xdir1/dir2" :let &include='^\s*%inc\s*/\zs[^/]\+\ze' @@ -91,7 +85,7 @@ ENDTEST STARTTEST :" check for 'include' with \zs and no \ze :call delete("./Xbase.c") -:call DeleteDirectory("Xdir1") +:call delete("Xdir1", "rf") :!mkdir Xdir1 :!mkdir "Xdir1/dir2" :let &include='^\s*%inc\s*\%([[:upper:]][^[:space:]]*\s\+\)\?\zs\S\+\ze' diff --git a/src/nvim/testdir/test49.vim b/src/nvim/testdir/test49.vim index edd49a2b63..467abcd9b9 100644 --- a/src/nvim/testdir/test49.vim +++ b/src/nvim/testdir/test49.vim @@ -456,7 +456,7 @@ function! ExtraVim(...) " messing up the user's viminfo file. let redirect = a:0 ? \ " -c 'au VimLeave * redir END' -c 'redir\\! >" . a:1 . "'" : "" - exec "!echo '" . debug_quits . "q' | ../../../build/bin/nvim -u NONE -N -es" . redirect . + exec "!echo '" . debug_quits . "q' | $NVIM_PRG -u NONE -N -es" . redirect . \ " -c 'debuggreedy|set viminfo+=nviminfo'" . \ " -c 'let ExtraVimBegin = " . extra_begin . "'" . \ " -c 'let ExtraVimResult = \"" . resultfile . "\"'" . breakpoints . @@ -608,7 +608,7 @@ com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>) " END_OF_TEST_ENVIRONMENT - do not change or remove this line. -" Tests 1 to 15 were moved to test_viml.vim +" Tests 1 to 15 were moved to test_vimscript.vim let Xtest = 16 "------------------------------------------------------------------------------- diff --git a/src/nvim/testdir/test69.in b/src/nvim/testdir/test69.in deleted file mode 100644 index 39b360fc81..0000000000 --- a/src/nvim/testdir/test69.in +++ /dev/null @@ -1,191 +0,0 @@ -Test for multi-byte text formatting. -Also test, that 'mps' with multibyte chars works. -And test "ra" on multi-byte characters. -Also test byteidx() and byteidxcomp() - -STARTTEST -: -ENDTEST - -Results of test69: - -STARTTEST -/^{/+1 -:set tw=2 fo=t -gqgqjgqgqo -XYZ -abc XYZ -ENDTEST - -{ -XYZ -abc XYZ -} - -STARTTEST -/^{/+1 -:set tw=1 fo=tm -gqgqjgqgqjgqgqjgqgqjgqgqo -X -Xa -X a -XY -X ï¼¹ -ENDTEST - -{ -X -Xa -X a -XY -X ï¼¹ -} - -STARTTEST -/^{/+1 -:set tw=2 fo=tm -gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqo -X -Xa -X a -XY -X ï¼¹ -aX -abX -abcX -abX c -abXY -ENDTEST - -{ -X -Xa -X a -XY -X ï¼¹ -aX -abX -abcX -abX c -abXY -} - -STARTTEST -/^{/+1 -:set ai tw=2 fo=tm -gqgqjgqgqo -X -Xa -ENDTEST - -{ - X - Xa -} - -STARTTEST -/^{/+1 -:set noai tw=2 fo=tm -gqgqjgqgqo - X - Xa -ENDTEST - -{ - X - Xa -} - -STARTTEST -/^{/+1 -:set tw=2 fo=cqm comments=n:X -gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqo -X -Xa -Xaï¼¹ -XY -XYZ -X ï¼¹ -X YZ -XX -XXa -XXY -ENDTEST - -{ -X -Xa -Xaï¼¹ -XY -XYZ -X ï¼¹ -X YZ -XX -XXa -XXY -} - -STARTTEST -/^{/+1 -:set tw=2 fo=tm -RXa -ENDTEST - -{ - -} - -STARTTEST -/^{/+1 -:set mps+=u2018:u2019 -d% -ENDTEST - -{ -‘ two three ’ four -} -STARTTEST -/^ra test -jVjra -ENDTEST - -ra test -ï½bbï½ -ï½ï½b - -STARTTEST -:set whichwrap+=h -/^x -dh -:set whichwrap-=h -ENDTEST - -á -x - -STARTTEST -:let a = '.é.' " one char of two bytes -:let b = '.eÌ.' " normal e with composing char -/^byteidx -:put =string([byteidx(a, 0), byteidx(a, 1), byteidx(a, 2), byteidx(a, 3), byteidx(a, 4)]) -:put =string([byteidx(b, 0), byteidx(b, 1), byteidx(b, 2), byteidx(b, 3), byteidx(b, 4)]) -/^byteidxcomp -:put =string([byteidxcomp(a, 0), byteidxcomp(a, 1), byteidxcomp(a, 2), byteidxcomp(a, 3), byteidxcomp(a, 4)]) -:let b = '.eÌ.' -:put =string([byteidxcomp(b, 0), byteidxcomp(b, 1), byteidxcomp(b, 2), byteidxcomp(b, 3), byteidxcomp(b, 4), byteidxcomp(b, 5)]) -ENDTEST - -byteidx -byteidxcomp - -STARTTEST -/^substitute -:let y = substitute('123', '\zs', 'a', 'g') | put =y -ENDTEST - -substitute - -STARTTEST -:g/^STARTTEST/.,/^ENDTEST/d -:1;/^Results/,$wq! test.out -ENDTEST diff --git a/src/nvim/testdir/test69.ok b/src/nvim/testdir/test69.ok deleted file mode 100644 index af8befb0c7..0000000000 --- a/src/nvim/testdir/test69.ok +++ /dev/null @@ -1,166 +0,0 @@ -Results of test69: - - -{ -XYZ -abc -XYZ - -XYZ -abc -XYZ -} - - -{ -X -X -a -X -a -X -ï¼¹ -X -ï¼¹ - -X -X -a -X -a -X -ï¼¹ -X -ï¼¹ -} - - -{ -X -X -a -X -a -X -ï¼¹ -X -ï¼¹ -a -X -ab -X -abc -X -ab -X -c -ab -X -ï¼¹ - -X -X -a -X -a -X -ï¼¹ -X -ï¼¹ -a -X -ab -X -abc -X -ab -X -c -ab -X -ï¼¹ -} - - -{ - X - X - a - - X - X - a -} - - -{ - X - X -a - - X - X -a -} - - -{ -X -Xa -Xa -XY -XY -XY -XZ -X ï¼¹ -X ï¼¹ -X Z -XX -XXa -XXY - -X -Xa -Xa -XY -XY -XY -XZ -X ï¼¹ -X ï¼¹ -X Z -XX -XXa -XXY -} - - -{ -X -a -} - - -{ - four -} - -ra test -aaaa -aaa - - -áx - - -byteidx -[0, 1, 3, 4, -1] -[0, 1, 4, 5, -1] -byteidxcomp -[0, 1, 3, 4, -1] -[0, 1, 2, 4, 5, -1] - - -substitute -a1aï¼’a3a - diff --git a/src/nvim/testdir/test73.in b/src/nvim/testdir/test73.in index 7d6c7287a5..9d50f7a789 100644 --- a/src/nvim/testdir/test73.in +++ b/src/nvim/testdir/test73.in @@ -8,16 +8,9 @@ STARTTEST :" This will cause a few errors, do it silently. :set visualbell :" -:function! DeleteDirectory(dir) -: if has("win16") || has("win32") || has("win64") || has("dos16") || has("dos32") -: exec "silent !rmdir /Q /S " . a:dir -: else -: exec "silent !rm -rf " . a:dir -: endif -:endfun :" On windows a stale "Xfind" directory may exist, remove it so that :" we start from a clean state. -:call DeleteDirectory("Xfind") +:call delete("Xfind", "rf") :new :let cwd=getcwd() :let test_out = cwd . '/test.out' @@ -169,7 +162,7 @@ SVoyager 2:w :exec "w >>" . test_out :q :exec "cd " . cwd -:call DeleteDirectory("Xfind") +:call delete("Xfind", "rf") :qa! ENDTEST diff --git a/src/nvim/testdir/test8.in b/src/nvim/testdir/test8.in deleted file mode 100644 index a5e6034782..0000000000 --- a/src/nvim/testdir/test8.in +++ /dev/null @@ -1,43 +0,0 @@ -Test for BufWritePre autocommand that deletes or unloads the buffer. -Test for BufUnload autocommand that unloads all other buffers. - -STARTTEST -:au BufWritePre Xxx1 bunload -:au BufWritePre Xxx2 bwipe -/^start of -A1:.,/end of/w! Xxx1 " write test file Xxx1 -$r2:.,/end of/w! Xxx2 " write test file Xxx2 -:e! Xxx2 " edit Xxx2 -:bdel test8.in " delete this file from the buffer list -:e Xxx1 " edit Xxx1 -:w " write it, will unload it and give an error msg -:w! test.out " Write contents of this file -:e! Xxx2 " start editing Xxx2 -:bwipe test.out " remove test.out from the buffer list -:w " write it, will delete the buffer and give an error msg -:w >>test.out " Append contents of this file -:au! BufWritePre -:func CloseAll() - let i = 0 - while i <= bufnr('$') - if i != bufnr('%') && bufloaded(i) - exe i . "bunload" - endif - let i += 1 - endwhile -endfunc -:func WriteToOut() - edit! test.out - $put ='VimLeave done' - write -endfunc -:set shada='100 -:au BufUnload * call CloseAll() -:au VimLeave * call WriteToOut() -:q -:qa! -ENDTEST - -start of Xxx - test -end of Xxx diff --git a/src/nvim/testdir/test8.ok b/src/nvim/testdir/test8.ok deleted file mode 100644 index adecb2f4be..0000000000 --- a/src/nvim/testdir/test8.ok +++ /dev/null @@ -1,7 +0,0 @@ -start of Xxx2 - test -end of Xxx -start of Xxx1 - test -end of Xxx -VimLeave done diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index 60248bf430..d55170c27c 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -2,27 +2,36 @@ " This makes testing go faster, since Vim doesn't need to restart. source test_assign.vim -source test_autocmd.vim source test_cursor_func.vim source test_execute_func.vim source test_ex_undo.vim source test_expr.vim source test_expr_utf8.vim source test_feedkeys.vim +source test_filter_cmd.vim +source test_filter_map.vim +source test_float_func.vim +source test_functions.vim source test_goto.vim source test_jumps.vim -source test_match.vim -source test_matchadd_conceal_utf8.vim +source test_fileformat.vim +source test_lambda.vim source test_menu.vim +source test_mapping.vim source test_messages.vim source test_options.vim source test_partial.vim source test_popup.vim source test_regexp_utf8.vim +source test_source_utf8.vim source test_statusline.vim source test_syn_attr.vim source test_tabline.vim -source test_tabpage.vim +" source test_tabpage.vim +source test_tagcase.vim source test_tagjump.vim +source test_taglist.vim +source test_true_false.vim source test_unlet.vim +source test_utf8.vim source test_window_cmd.vim diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index 5675697dc4..835df42a10 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -1,5 +1,15 @@ " Tests for autocommands +set belloff=all + +function! s:cleanup_buffers() abort + for bnr in range(1, bufnr('$')) + if bufloaded(bnr) && bufnr('%') != bnr + execute 'bd! ' . bnr + endif + endfor +endfunction + func Test_vim_did_enter() call assert_false(v:vim_did_enter) @@ -13,6 +23,9 @@ if has('timers') endfunc func Test_cursorhold_insert() + " Need to move the cursor. + call feedkeys("ggG", "xt") + let g:triggered = 0 au CursorHoldI * let g:triggered += 1 set updatetime=20 @@ -20,6 +33,7 @@ if has('timers') call feedkeys('a', 'x!') call assert_equal(1, g:triggered) au! CursorHoldI + set updatetime& endfunc func Test_cursorhold_insert_ctrl_x() @@ -31,6 +45,7 @@ if has('timers') call feedkeys("a\<C-X>", 'x!') call assert_equal(0, g:triggered) au! CursorHoldI + set updatetime& endfunc endif @@ -64,6 +79,115 @@ function Test_bufunload() augroup! test_bufunload_group endfunc +" SEGV occurs in older versions. (At least 7.4.2005 or older) +function Test_autocmd_bufunload_with_tabnext() + tabedit + tabfirst + + augroup test_autocmd_bufunload_with_tabnext_group + autocmd! + autocmd BufUnload <buffer> tabnext + augroup END + + quit + call assert_equal(2, tabpagenr('$')) + + autocmd! test_autocmd_bufunload_with_tabnext_group + augroup! test_autocmd_bufunload_with_tabnext_group + tablast + quit +endfunc + +function Test_autocmd_bufwinleave_with_tabfirst() + tabedit + augroup sample + autocmd! + autocmd BufWinLeave <buffer> tabfirst + augroup END + call setline(1, ['a', 'b', 'c']) + edit! a.txt + tabclose +endfunc + +" SEGV occurs in older versions. (At least 7.4.2321 or older) +function Test_autocmd_bufunload_avoiding_SEGV_01() + split aa.txt + let lastbuf = bufnr('$') + + augroup test_autocmd_bufunload + autocmd! + exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!' + augroup END + + call assert_fails('edit bb.txt', 'E937:') + + autocmd! test_autocmd_bufunload + augroup! test_autocmd_bufunload + bwipe! aa.txt + bwipe! bb.txt +endfunc + +" SEGV occurs in older versions. (At least 7.4.2321 or older) +function Test_autocmd_bufunload_avoiding_SEGV_02() + setlocal buftype=nowrite + let lastbuf = bufnr('$') + + augroup test_autocmd_bufunload + autocmd! + exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!' + augroup END + + normal! i1 + call assert_fails('edit a.txt', 'E517:') + call feedkeys("\<CR>") + + autocmd! test_autocmd_bufunload + augroup! test_autocmd_bufunload + bwipe! a.txt +endfunc + +func Test_win_tab_autocmd() + let g:record = [] + + augroup testing + au WinNew * call add(g:record, 'WinNew') + au WinEnter * call add(g:record, 'WinEnter') + au WinLeave * call add(g:record, 'WinLeave') + au TabNew * call add(g:record, 'TabNew') + au TabClosed * call add(g:record, 'TabClosed') + au TabEnter * call add(g:record, 'TabEnter') + au TabLeave * call add(g:record, 'TabLeave') + augroup END + + split + tabnew + close + close + + call assert_equal([ + \ 'WinLeave', 'WinNew', 'WinEnter', + \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', + \ 'WinLeave', 'TabLeave', 'TabClosed', 'WinEnter', 'TabEnter', + \ 'WinLeave', 'WinEnter' + \ ], g:record) + + let g:record = [] + tabnew somefile + tabnext + bwipe somefile + + call assert_equal([ + \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', + \ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', + \ 'TabClosed' + \ ], g:record) + + augroup testing + au! + augroup END + unlet g:record +endfunc + func s:AddAnAutocmd() augroup vimBarTest au BufReadCmd * echo 'hello' @@ -91,3 +215,208 @@ func Test_early_bar() au! vimBarTest|echo 'hello' call assert_equal(1, len(split(execute('au vimBarTest'), "\n"))) endfunc + +func RemoveGroup() + autocmd! StartOK + augroup! StartOK +endfunc + +func Test_augroup_warning() + augroup TheWarning + au VimEnter * echo 'entering' + augroup END + call assert_true(match(execute('au VimEnter'), "TheWarning.*VimEnter") >= 0) + redir => res + augroup! TheWarning + redir END + call assert_true(match(res, "W19:") >= 0) + call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0) + + " check "Another" does not take the pace of the deleted entry + augroup Another + augroup END + call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0) + augroup! Another + + " no warning for postpone aucmd delete + augroup StartOK + au VimEnter * call RemoveGroup() + augroup END + call assert_true(match(execute('au VimEnter'), "StartOK.*VimEnter") >= 0) + redir => res + doautocmd VimEnter + redir END + call assert_true(match(res, "W19:") < 0) + au! VimEnter +endfunc + +func Test_augroup_deleted() + " This caused a crash before E936 was introduced + augroup x + call assert_fails('augroup! x', 'E936:') + au VimEnter * echo + augroup end + augroup! x + call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0) + au! VimEnter +endfunc + +" Tests for autocommands on :close command. +" This used to be in test13. +func Test_three_windows() + " Clean up buffers, because in some cases this function fails. + call s:cleanup_buffers() + + " Write three files and open them, each in a window. + " Then go to next window, with autocommand that deletes the previous one. + " Do this twice, writing the file. + e! Xtestje1 + call setline(1, 'testje1') + w + sp Xtestje2 + call setline(1, 'testje2') + w + sp Xtestje3 + call setline(1, 'testje3') + w + wincmd w + au WinLeave Xtestje2 bwipe + wincmd w + call assert_equal('Xtestje1', expand('%')) + + au WinLeave Xtestje1 bwipe Xtestje3 + close + call assert_equal('Xtestje1', expand('%')) + + " Test deleting the buffer on a Unload event. If this goes wrong there + " will be the ATTENTION prompt. + e Xtestje1 + au! + au! BufUnload Xtestje1 bwipe + call assert_fails('e Xtestje3', 'E937:') + call assert_equal('Xtestje3', expand('%')) + + e Xtestje2 + sp Xtestje1 + call assert_fails('e', 'E937:') + call assert_equal('Xtestje2', expand('%')) + + " Test changing buffers in a BufWipeout autocommand. If this goes wrong + " there are ml_line errors and/or a Crash. + au! + only + e Xanother + e Xtestje1 + bwipe Xtestje2 + bwipe Xtestje3 + au BufWipeout Xtestje1 buf Xtestje1 + bwipe + call assert_equal('Xanother', expand('%')) + + only + + helptags ALL + help + wincmd w + 1quit + call assert_equal('Xanother', expand('%')) + + au! + enew + bwipe! Xtestje1 + call delete('Xtestje1') + call delete('Xtestje2') + call delete('Xtestje3') +endfunc + +func Test_BufEnter() + au! BufEnter + au Bufenter * let val = val . '+' + let g:val = '' + split NewFile + call assert_equal('+', g:val) + bwipe! + call assert_equal('++', g:val) + + " Also get BufEnter when editing a directory + call mkdir('Xdir') + split Xdir + call assert_equal('+++', g:val) + + " On MS-Windows we can't edit the directory, make sure we wipe the right + " buffer. + bwipe! Xdir + + call delete('Xdir', 'd') + au! BufEnter +endfunc + +" Closing a window might cause an endless loop +" E814 for older Vims +function Test_autocmd_bufwipe_in_SessLoadPost() + tabnew + set noswapfile + mksession! + + let content = ['set nocp noswapfile', + \ 'let v:swapchoice="e"', + \ 'augroup test_autocmd_sessionload', + \ 'autocmd!', + \ 'autocmd SessionLoadPost * 4bw!', + \ 'augroup END', + \ '', + \ 'func WriteErrors()', + \ ' call writefile([execute("messages")], "Xerrors")', + \ 'endfunc', + \ 'au VimLeave * call WriteErrors()', + \ ] + call writefile(content, 'Xvimrc') + call system(v:progpath. ' --headless -i NONE -u Xvimrc --noplugins -S Session.vim -c cq') + let errors = join(readfile('Xerrors')) + call assert_match('E814', errors) + + set swapfile + for file in ['Session.vim', 'Xvimrc', 'Xerrors'] + call delete(file) + endfor +endfunc + +" SEGV occurs in older versions. +function Test_autocmd_bufwipe_in_SessLoadPost2() + tabnew + set noswapfile + mksession! + + let content = ['set nocp noswapfile', + \ 'function! DeleteInactiveBufs()', + \ ' tabfirst', + \ ' let tabblist = []', + \ ' for i in range(1, tabpagenr(''$''))', + \ ' call extend(tabblist, tabpagebuflist(i))', + \ ' endfor', + \ ' for b in range(1, bufnr(''$''))', + \ ' if bufexists(b) && buflisted(b) && (index(tabblist, b) == -1 || bufname(b) =~# ''^$'')', + \ ' exec ''bwipeout '' . b', + \ ' endif', + \ ' endfor', + \ ' echomsg "SessionLoadPost DONE"', + \ 'endfunction', + \ 'au SessionLoadPost * call DeleteInactiveBufs()', + \ '', + \ 'func WriteErrors()', + \ ' call writefile([execute("messages")], "Xerrors")', + \ 'endfunc', + \ 'au VimLeave * call WriteErrors()', + \ ] + call writefile(content, 'Xvimrc') + call system(v:progpath. ' --headless -i NONE -u Xvimrc --noplugins -S Session.vim -c cq') + let errors = join(readfile('Xerrors')) + " This probably only ever matches on unix. + call assert_notmatch('Caught deadly signal SEGV', errors) + call assert_match('SessionLoadPost DONE', errors) + + set swapfile + for file in ['Session.vim', 'Xvimrc', 'Xerrors'] + call delete(file) + endfor +endfunc diff --git a/src/nvim/testdir/test_breakindent.vim b/src/nvim/testdir/test_breakindent.vim new file mode 100644 index 0000000000..7deffbe452 --- /dev/null +++ b/src/nvim/testdir/test_breakindent.vim @@ -0,0 +1,298 @@ +" Test for breakindent +" +" Note: if you get strange failures when adding new tests, it might be that +" while the test is run, the breakindent cacheing gets in its way. +" It helps to change the tabstop setting and force a redraw (e.g. see +" Test_breakindent08()) +if !exists('+breakindent') + finish +endif + +source view_util.vim + +let s:input ="\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP" + +function s:screen_lines(lnum, width) abort + return ScreenLines([a:lnum, a:lnum + 2], a:width) +endfunction + +function! s:compare_lines(expect, actual) + call assert_equal(join(a:expect, "\n"), join(a:actual, "\n")) +endfunction + +function s:test_windows(...) + call NewWindow(10, 20) + setl ts=4 sw=4 sts=4 breakindent + put =s:input + exe get(a:000, 0, '') +endfunction + +function s:close_windows(...) + call CloseWindow() + exe get(a:000, 0, '') +endfunction + +function Test_breakindent01() + " simple breakindent test + call s:test_windows('setl briopt=min:0') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ " qrst", +\ " GHIJ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction + +function Test_breakindent02() + " simple breakindent test with showbreak set + call s:test_windows('setl briopt=min:0 sbr=>>') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ " >>qr", +\ " >>EF", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent03() + " simple breakindent test with showbreak set and briopt including sbr + call s:test_windows('setl briopt=sbr,min:0 sbr=++') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ "++ qrst", +\ "++ GHIJ", +\ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent04() + " breakindent set with min width 18 + call s:test_windows('setl sbr= briopt=min:18') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ " qrstuv", +\ " IJKLMN", +\ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent05() + " breakindent set and shift by 2 + call s:test_windows('setl briopt=shift:2,min:0') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ " qr", +\ " EF", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction + +function Test_breakindent06() + " breakindent set and shift by -1 + call s:test_windows('setl briopt=shift:-1,min:0') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ " qrstu", +\ " HIJKL", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction + +function Test_breakindent07() + " breakindent set and shift by 1, Number set sbr=? and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4 cpo+=n') + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ab", +\ "? m", +\ "? x", +\ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr= cpo-=n') +endfunction + +function Test_breakindent07a() + " breakindent set and shift by 1, Number set sbr=? and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4') + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ab", +\ " ? m", +\ " ? x", +\ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent08() + " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list cpo+=n ts=4') + " make sure, cache is invalidated! + set ts=8 + redraw! + set ts=4 + redraw! + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ^Iabcd", +\ "# opq", +\ "# BCD", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr= cpo-=n') +endfunction + +function Test_breakindent08a() + " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list') + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ^Iabcd", +\ " # opq", +\ " # BCD", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent09() + " breakindent set and shift by 1, Number and list set sbr=# + call s:test_windows('setl briopt=shift:1,min:0 nu nuw=4 sbr=# list') + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ^Iabcd", +\ " #op", +\ " #AB", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent10() + " breakindent set, Number set sbr=~ + call s:test_windows('setl cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0') + " make sure, cache is invalidated! + set ts=8 + redraw! + set ts=4 + redraw! + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ab", +\ "~ mn", +\ "~ yz", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr= cpo-=n') +endfunction + +function Test_breakindent11() + " test strdisplaywidth() + call s:test_windows('setl cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4') + let text=getline(2) + let width = strlen(text[1:])+indent(2)+strlen(&sbr)*3 " text wraps 3 times + call assert_equal(width, strdisplaywidth(text)) + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent12() + " test breakindent with long indent + let s:input="\t\t\t\t\t{" + call s:test_windows('setl breakindent linebreak briopt=min:10 nu numberwidth=3 ts=4 list listchars=tab:>-') + let lines=s:screen_lines(2,16) + let expect=[ +\ " 2 >--->--->--->", +\ " ---{ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set nuw=4 listchars=') +endfunction + +function Test_breakindent13() + let s:input="" + call s:test_windows('setl breakindent briopt=min:10 ts=8') + vert resize 20 + call setline(1, [" a\tb\tc\td\te", " z y x w v"]) + 1 + norm! fbgj"ayl + 2 + norm! fygj"byl + call assert_equal('d', @a) + call assert_equal('w', @b) + call s:close_windows() +endfunction + +function Test_breakindent14() + let s:input="" + call s:test_windows('setl breakindent briopt= ts=8') + vert resize 30 + norm! 3a1234567890 + norm! a abcde + exec "norm! 0\<C-V>tex" + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ "e ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction + +function Test_breakindent15() + let s:input="" + call s:test_windows('setl breakindent briopt= ts=8 sw=8') + vert resize 30 + norm! 4a1234567890 + exe "normal! >>\<C-V>3f0x" + let lines=s:screen_lines(line('.'),20) + let expect=[ +\ " 1234567890 ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction + +function Test_breakindent16() + " Check that overlong lines are indented correctly. + let s:input="" + call s:test_windows('setl breakindent briopt=min:0 ts=4') + call setline(1, "\t".repeat("1234567890", 10)) + resize 6 + norm! 1gg$ + redraw! + let lines=s:screen_lines(1,10) + let expect=[ +\ " 789012", +\ " 345678", +\ " 901234", +\ ] + call s:compare_lines(expect, lines) + let lines=s:screen_lines(4,10) + let expect=[ +\ " 567890", +\ " 123456", +\ " 7890 ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction diff --git a/src/nvim/testdir/test_bufwintabinfo.vim b/src/nvim/testdir/test_bufwintabinfo.vim index 5c916e2dd7..1c9350c416 100644 --- a/src/nvim/testdir/test_bufwintabinfo.vim +++ b/src/nvim/testdir/test_bufwintabinfo.vim @@ -87,9 +87,17 @@ function Test_get_buf_options() endfunc function Test_get_win_options() + if has('folding') + set foldlevel=999 + endif + set list let opts = getwinvar(1, '&') call assert_equal(v:t_dict, type(opts)) call assert_equal(0, opts.linebreak) + call assert_equal(1, opts.list) + if has('folding') + call assert_equal(999, opts.foldlevel) + endif if has('signs') call assert_equal('auto', opts.signcolumn) endif @@ -97,7 +105,12 @@ function Test_get_win_options() let opts = gettabwinvar(1, 1, '&') call assert_equal(v:t_dict, type(opts)) call assert_equal(0, opts.linebreak) + call assert_equal(1, opts.list) if has('signs') call assert_equal('auto', opts.signcolumn) endif + set list& + if has('folding') + set foldlevel=0 + endif endfunc diff --git a/src/nvim/testdir/test_charsearch.vim b/src/nvim/testdir/test_charsearch.vim new file mode 100644 index 0000000000..8b313b5a35 --- /dev/null +++ b/src/nvim/testdir/test_charsearch.vim @@ -0,0 +1,62 @@ + +function! Test_charsearch() + enew! + call append(0, ['Xabcdefghijkemnopqretuvwxyz', + \ 'Yabcdefghijkemnopqretuvwxyz', + \ 'Zabcdefghijkemnokqretkvwxyz']) + " check that "fe" and ";" work + 1 + normal! ylfep;;p,,p + call assert_equal('XabcdeXfghijkeXmnopqreXtuvwxyz', getline(1)) + " check that save/restore works + 2 + normal! ylfep + let csave = getcharsearch() + normal! fip + call setcharsearch(csave) + normal! ;p;p + call assert_equal('YabcdeYfghiYjkeYmnopqreYtuvwxyz', getline(2)) + + " check that setcharsearch() changes the settings. + 3 + normal! ylfep + call setcharsearch({'char': 'k'}) + normal! ;p + call setcharsearch({'forward': 0}) + normal! $;p + call setcharsearch({'until': 1}) + set cpo-=; + normal! ;;p + call assert_equal('ZabcdeZfghijkZZemnokqretkZvwxyz', getline(3)) + enew! +endfunction + +" Test for t,f,F,T movement commands and 'cpo-;' setting +function! Test_search_cmds() + enew! + call append(0, ["aaa two three four", " zzz", "yyy ", + \ "bbb yee yoo four", "ccc two three four", + \ "ddd yee yoo four"]) + set cpo-=; + 1 + normal! 0tt;D + 2 + normal! 0fz;D + 3 + normal! $Fy;D + 4 + normal! $Ty;D + set cpo+=; + 5 + normal! 0tt;;D + 6 + normal! $Ty;;D + + call assert_equal('aaa two', getline(1)) + call assert_equal(' z', getline(2)) + call assert_equal('y', getline(3)) + call assert_equal('bbb y', getline(4)) + call assert_equal('ccc', getline(5)) + call assert_equal('ddd yee y', getline(6)) + enew! +endfunction diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index 21bb057fe1..2facffb067 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -2,7 +2,7 @@ func Test_complete_tab() call writefile(['testfile'], 'Xtestfile') - call feedkeys(":e Xtest\t\r", "tx") + call feedkeys(":e Xtestf\t\r", "tx") call assert_equal('testfile', getline(1)) call delete('Xtestfile') endfunc @@ -17,7 +17,7 @@ func Test_complete_wildmenu() call writefile(['testfile1'], 'Xtestfile1') call writefile(['testfile2'], 'Xtestfile2') set wildmenu - call feedkeys(":e Xtest\t\t\r", "tx") + call feedkeys(":e Xtestf\t\t\r", "tx") call assert_equal('testfile2', getline(1)) call delete('Xtestfile1') @@ -85,6 +85,11 @@ func Test_getcompletion() let l = getcompletion('paint', 'function') call assert_equal([], l) + let Flambda = {-> 'hello'} + let l = getcompletion('', 'function') + let l = filter(l, {i, v -> v =~ 'lambda'}) + call assert_equal(0, len(l)) + let l = getcompletion('run', 'file') call assert_true(index(l, 'runtest.vim') >= 0) let l = getcompletion('walk', 'file') @@ -125,6 +130,11 @@ func Test_getcompletion() let l = getcompletion('dark', 'highlight') call assert_equal([], l) + let l = getcompletion('', 'messages') + call assert_true(index(l, 'clear') >= 0) + let l = getcompletion('not', 'messages') + call assert_equal([], l) + if has('cscope') let l = getcompletion('', 'cscope') let cmds = ['add', 'find', 'help', 'kill', 'reset', 'show'] @@ -151,6 +161,20 @@ func Test_getcompletion() call assert_equal(['Testing'], l) endif + " Command line completion tests + let l = getcompletion('cd ', 'cmdline') + call assert_true(index(l, 'sautest/') >= 0) + let l = getcompletion('cd NoMatch', 'cmdline') + call assert_equal([], l) + let l = getcompletion('let v:n', 'cmdline') + call assert_true(index(l, 'v:null') >= 0) + let l = getcompletion('let v:notexists', 'cmdline') + call assert_equal([], l) + let l = getcompletion('call tag', 'cmdline') + call assert_true(index(l, 'taglist(') >= 0) + let l = getcompletion('call paint', 'cmdline') + call assert_equal([], l) + " For others test if the name is recognized. let names = ['buffer', 'environment', 'file_in_path', \ 'mapping', 'shellcmd', 'tag', 'tag_listfiles', 'user'] @@ -182,5 +206,53 @@ func Test_expand_star_star() call writefile(['asdfasdf'], 'a/b/fileXname') call feedkeys(":find **/fileXname\<Tab>\<CR>", 'xt') call assert_equal('find a/b/fileXname', getreg(':')) + bwipe! call delete('a', 'rf') endfunc + +func Test_paste_in_cmdline() + let @a = "def" + call feedkeys(":abc \<C-R>a ghi\<C-B>\"\<CR>", 'tx') + call assert_equal('"abc def ghi', @:) + + new + call setline(1, 'asdf.x /tmp/some verylongword a;b-c*d ') + + call feedkeys(":aaa \<C-R>\<C-W> bbb\<C-B>\"\<CR>", 'tx') + call assert_equal('"aaa asdf bbb', @:) + + call feedkeys("ft:aaa \<C-R>\<C-F> bbb\<C-B>\"\<CR>", 'tx') + call assert_equal('"aaa /tmp/some bbb', @:) + + set incsearch + call feedkeys("fy:aaa veryl\<C-R>\<C-W> bbb\<C-B>\"\<CR>", 'tx') + call assert_equal('"aaa verylongword bbb', @:) + + call feedkeys("f;:aaa \<C-R>\<C-A> bbb\<C-B>\"\<CR>", 'tx') + call assert_equal('"aaa a;b-c*d bbb', @:) + + call feedkeys(":\<C-\>etoupper(getline(1))\<CR>\<C-B>\"\<CR>", 'tx') + call assert_equal('"ASDF.X /TMP/SOME VERYLONGWORD A;B-C*D ', @:) + bwipe! +endfunc + +func Test_remove_char_in_cmdline() + call feedkeys(":abc def\<S-Left>\<Del>\<C-B>\"\<CR>", 'tx') + call assert_equal('"abc ef', @:) + + call feedkeys(":abc def\<S-Left>\<BS>\<C-B>\"\<CR>", 'tx') + call assert_equal('"abcdef', @:) + + call feedkeys(":abc def ghi\<S-Left>\<C-W>\<C-B>\"\<CR>", 'tx') + call assert_equal('"abc ghi', @:) + + call feedkeys(":abc def\<S-Left>\<C-U>\<C-B>\"\<CR>", 'tx') + call assert_equal('"def', @:) +endfunc + +func Test_illegal_address() + new + 2;'( + 2;') + quit +endfunc diff --git a/src/nvim/testdir/test_command_count.vim b/src/nvim/testdir/test_command_count.vim new file mode 100644 index 0000000000..e438a8b077 --- /dev/null +++ b/src/nvim/testdir/test_command_count.vim @@ -0,0 +1,191 @@ +" Test for user command counts. + +func Test_command_count_0() + set hidden + set noswapfile + + split DoesNotExistEver + let lastbuf = bufnr('$') + call setline(1, 'asdf') + quit! + + command! -range -addr=loaded_buffers RangeLoadedBuffers :let lines = [<line1>, <line2>] + command! -range=% -addr=loaded_buffers RangeLoadedBuffersAll :let lines = [<line1>, <line2>] + command! -range -addr=buffers RangeBuffers :let lines = [<line1>, <line2>] + command! -range=% -addr=buffers RangeBuffersAll :let lines = [<line1>, <line2>] + + .,$RangeLoadedBuffers + call assert_equal([1, 1], lines) + %RangeLoadedBuffers + call assert_equal([1, 1], lines) + RangeLoadedBuffersAll + call assert_equal([1, 1], lines) + .,$RangeBuffers + call assert_equal([1, lastbuf], lines) + %RangeBuffers + call assert_equal([1, lastbuf], lines) + RangeBuffersAll + call assert_equal([1, lastbuf], lines) + + delcommand RangeLoadedBuffers + delcommand RangeLoadedBuffersAll + delcommand RangeBuffers + delcommand RangeBuffersAll + + set hidden& + set swapfile& +endfunc + +func Test_command_count_1() + silent! %argd + arga a b c d e + argdo echo "loading buffers" + argu 3 + command! -range -addr=arguments RangeArguments :let lines = [<line1>, <line2>] + command! -range=% -addr=arguments RangeArgumentsAll :let lines = [<line1>, <line2>] + .-,$-RangeArguments + call assert_equal([2, 4], lines) + %RangeArguments + call assert_equal([1, 5], lines) + RangeArgumentsAll + call assert_equal([1, 5], lines) + N + .RangeArguments + call assert_equal([2, 2], lines) + delcommand RangeArguments + delcommand RangeArgumentsAll + + split|split|split|split + 3wincmd w + command! -range -addr=windows RangeWindows :let lines = [<line1>, <line2>] + .,$RangeWindows + call assert_equal([3, 5], lines) + %RangeWindows + call assert_equal([1, 5], lines) + delcommand RangeWindows + + command! -range=% -addr=windows RangeWindowsAll :let lines = [<line1>, <line2>] + RangeWindowsAll + call assert_equal([1, 5], lines) + delcommand RangeWindowsAll + only + blast|bd + + tabe|tabe|tabe|tabe + normal 2gt + command! -range -addr=tabs RangeTabs :let lines = [<line1>, <line2>] + .,$RangeTabs + call assert_equal([2, 5], lines) + %RangeTabs + call assert_equal([1, 5], lines) + delcommand RangeTabs + + command! -range=% -addr=tabs RangeTabsAll :let lines = [<line1>, <line2>] + RangeTabsAll + call assert_equal([1, 5], lines) + delcommand RangeTabsAll + 1tabonly + + s/\n/\r\r\r\r\r/ + 2ma< + $-ma> + command! -range=% RangeLines :let lines = [<line1>, <line2>] + '<,'>RangeLines + call assert_equal([2, 5], lines) + delcommand RangeLines + + command! -range=% -buffer LocalRangeLines :let lines = [<line1>, <line2>] + '<,'>LocalRangeLines + call assert_equal([2, 5], lines) + delcommand LocalRangeLines +endfunc + +func Test_command_count_2() + silent! %argd + arga a b c d + call assert_fails('5argu', 'E16:') + + $argu + call assert_equal('d', expand('%:t')) + + 1argu + call assert_equal('a', expand('%:t')) + + call assert_fails('300b', 'E16:') + + split|split|split|split + 0close + + $wincmd w + $close + call assert_equal(3, winnr()) + + call assert_fails('$+close', 'E16:') + + $tabe + call assert_equal(2, tabpagenr()) + + call assert_fails('$+tabe', 'E16:') + + only! + e x + 0tabm + normal 1gt + call assert_equal('x', expand('%:t')) + + tabonly! + only! +endfunc + +func Test_command_count_3() + se nohidden + e aaa + let buf_aaa = bufnr('%') + e bbb + let buf_bbb = bufnr('%') + e ccc + let buf_ccc = bufnr('%') + buf 1 + call assert_equal([1, 1, 1], [buflisted(buf_aaa), buflisted(buf_bbb), buflisted(buf_ccc)]) + exe buf_bbb . "," . buf_ccc . "bdelete" + call assert_equal([1, 0, 0], [buflisted(buf_aaa), buflisted(buf_bbb), buflisted(buf_ccc)]) + exe buf_aaa . "bdelete" + call assert_equal([0, 0, 0], [buflisted(buf_aaa), buflisted(buf_bbb), buflisted(buf_ccc)]) +endfunc + +func Test_command_count_4() + %argd + let bufnr = bufnr('$') + 1 + arga aa bb cc dd ee ff + 3argu + let args = [] + .,$-argdo call add(args, expand('%')) + call assert_equal(['cc', 'dd', 'ee'], args) + + " create windows to get 5 + split|split|split|split + 2wincmd w + let windows = [] + .,$-windo call add(windows, winnr()) + call assert_equal([2, 3, 4], windows) + only! + + exe bufnr . 'buf' + let buffers = [] + .,$-bufdo call add(buffers, bufnr('%')) + call assert_equal([bufnr, bufnr + 1, bufnr + 2, bufnr + 3, bufnr + 4], buffers) + + exe (bufnr + 3) . 'bdel' + let buffers = [] + exe (bufnr + 2) . ',' . (bufnr + 5) . "bufdo call add(buffers, bufnr('%'))" + call assert_equal([bufnr + 2, bufnr + 4, bufnr + 5], buffers) + + " create tabpages to get 5 + tabe|tabe|tabe|tabe + normal! 2gt + let tabpages = [] + .,$-tabdo call add(tabpages, tabpagenr()) + call assert_equal([2, 3, 4], tabpages) + tabonly! + bwipe! +endfunc diff --git a/src/nvim/testdir/test_cscope.vim b/src/nvim/testdir/test_cscope.vim index b6d70f0765..01a9a3f9ad 100644 --- a/src/nvim/testdir/test_cscope.vim +++ b/src/nvim/testdir/test_cscope.vim @@ -1,9 +1,262 @@ " Test for cscope commands. -if !has('cscope') +if !has('cscope') || !executable('cscope') || !has('quickfix') finish endif +func CscopeSetupOrClean(setup) + if a:setup + noa sp samples/memfile_test.c + saveas! Xmemfile_test.c + call system('cscope -bk -fXcscope.out Xmemfile_test.c') + call system('cscope -bk -fXcscope2.out Xmemfile_test.c') + cscope add Xcscope.out + set cscopequickfix=s-,g-,d-,c-,t-,e-,f-,i-,a- + else + cscope kill -1 + for file in ['Xcscope.out', 'Xcscope2.out', 'Xmemfile_test.c'] + call delete(file) + endfo + endif +endfunc + +func Test_cscopeWithCscopeConnections() + call CscopeSetupOrClean(1) + " Test 0: E568: duplicate cscope database not added + try + set nocscopeverbose + cscope add Xcscope.out + set cscopeverbose + catch + call assert_report('exception thrown') + endtry + call assert_fails('cscope add', 'E560') + call assert_fails('cscope add Xcscope.out', 'E568') + call assert_fails('cscope add doesnotexist.out', 'E563') + + " Test 1: Find this C-Symbol + for cmd in ['cs find s main', 'cs find 0 main'] + let a=execute(cmd) + " Test 1.1 test where it moves the cursor + call assert_equal('main(void)', getline('.')) + " Test 1.2 test the output of the :cs command + call assert_match('\n(1 of 1): <<main>> main(void )', a) + endfor + + " Test 2: Find this definition + for cmd in ['cs find g test_mf_hash', 'cs find 1 test_mf_hash'] + exe cmd + call assert_equal(['', '/*', ' * Test mf_hash_*() functions.', ' */', ' static void', 'test_mf_hash(void)', '{'], getline(line('.')-5, line('.')+1)) + endfor + + " Test 3: Find functions called by this function + for cmd in ['cs find d test_mf_hash', 'cs find 2 test_mf_hash'] + let a=execute(cmd) + call assert_match('\n(1 of 42): <<mf_hash_init>> mf_hash_init(&ht);', a) + call assert_equal(' mf_hash_init(&ht);', getline('.')) + endfor + + " Test 4: Find functions calling this function + for cmd in ['cs find c test_mf_hash', 'cs find 3 test_mf_hash'] + let a=execute(cmd) + call assert_match('\n(1 of 1): <<main>> test_mf_hash();', a) + call assert_equal(' test_mf_hash();', getline('.')) + endfor + + " Test 5: Find this text string + for cmd in ['cs find t Bram', 'cs find 4 Bram'] + let a=execute(cmd) + call assert_match('(1 of 1): <<<unknown>>> \* VIM - Vi IMproved^Iby Bram Moolenaar', a) + call assert_equal(' * VIM - Vi IMproved by Bram Moolenaar', getline('.')) + endfor + + " Test 6: Find this egrep pattern + " test all matches returned by cscope + for cmd in ['cs find e ^\#includ.', 'cs find 6 ^\#includ.'] + let a=execute(cmd) + call assert_match('\n(1 of 3): <<<unknown>>> #include <assert.h>', a) + call assert_equal('#include <assert.h>', getline('.')) + cnext + call assert_equal('#include "main.c"', getline('.')) + cnext + call assert_equal('#include "memfile.c"', getline('.')) + call assert_fails('cnext', 'E553:') + endfor + + " Test 7: Find the same egrep pattern using lcscope this time. + let a=execute('lcs find e ^\#includ.') + call assert_match('\n(1 of 3): <<<unknown>>> #include <assert.h>', a) + call assert_equal('#include <assert.h>', getline('.')) + lnext + call assert_equal('#include "main.c"', getline('.')) + lnext + call assert_equal('#include "memfile.c"', getline('.')) + call assert_fails('lnext', 'E553:') + + " Test 8: Find this file + for cmd in ['cs find f Xmemfile_test.c', 'cs find 7 Xmemfile_test.c'] + enew + let a=execute(cmd) + call assert_true(a =~ '"Xmemfile_test.c" \d\+L, \d\+C') + call assert_equal('Xmemfile_test.c', @%) + endfor + + " Test 9: Find files #including this file + for cmd in ['cs find i assert.h', 'cs find 8 assert.h'] + enew + let a=execute(cmd) + let alines = split(a, '\n', 1) + call assert_equal('', alines[0]) + call assert_true(alines[1] =~ '"Xmemfile_test.c" \d\+L, \d\+C') + call assert_equal('(1 of 1): <<global>> #include <assert.h>', alines[2]) + call assert_equal('#include <assert.h>', getline('.')) + endfor + + " Test 10: Invalid find command + call assert_fails('cs find x', 'E560:') + + " Test 11: Find places where this symbol is assigned a value + " this needs a cscope >= 15.8 + " unfortunately, Travis has cscope version 15.7 + let cscope_version=systemlist('cscope --version')[0] + let cs_version=str2float(matchstr(cscope_version, '\d\+\(\.\d\+\)\?')) + if cs_version >= 15.8 + for cmd in ['cs find a item', 'cs find 9 item'] + let a=execute(cmd) + call assert_equal(['', '(1 of 4): <<test_mf_hash>> item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE);'], split(a, '\n', 1)) + call assert_equal(' item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE);', getline('.')) + cnext + call assert_equal(' item = mf_hash_find(&ht, key);', getline('.')) + cnext + call assert_equal(' item = mf_hash_find(&ht, key);', getline('.')) + cnext + call assert_equal(' item = mf_hash_find(&ht, key);', getline('.')) + endfor + endif + + " Test 12: leading whitespace is not removed for cscope find text + let a=execute('cscope find t test_mf_hash') + call assert_equal(['', '(1 of 1): <<<unknown>>> test_mf_hash();'], split(a, '\n', 1)) + call assert_equal(' test_mf_hash();', getline('.')) + + " Test 13: test with scscope + let a=execute('scs find t Bram') + call assert_match('(1 of 1): <<<unknown>>> \* VIM - Vi IMproved^Iby Bram Moolenaar', a) + call assert_equal(' * VIM - Vi IMproved by Bram Moolenaar', getline('.')) + + " Test 14: cscope help + for cmd in ['cs', 'cs help', 'cs xxx'] + let a=execute(cmd) + call assert_match('^cscope commands:\n', a) + call assert_match('\nadd :', a) + call assert_match('\nfind :', a) + call assert_match('\nhelp : Show this message', a) + call assert_match('\nkill : Kill a connection', a) + call assert_match('\nreset: Reinit all connections', a) + call assert_match('\nshow : Show connections', a) + endfor + let a=execute('scscope help') + call assert_match('This cscope command does not support splitting the window\.', a) + + " Test 15: reset connections + let a=execute('cscope reset') + call assert_match('\nAdded cscope database.*Xcscope.out (#0)', a) + call assert_match('\nAll cscope databases reset', a) + + " Test 16: cscope show + let a=execute('cscope show') + call assert_match('\n 0 \d\+.*Xcscope.out\s*<none>', a) + + " Test 17: cstag and 'csto' option + set csto=0 + let a=execute('cstag TEST_COUNT') + call assert_match('(1 of 1): <<TEST_COUNT>> #define TEST_COUNT 50000', a) + call assert_equal('#define TEST_COUNT 50000', getline('.')) + set csto=1 + let a=execute('cstag index_to_key') + call assert_match('(1 of 1): <<index_to_key>> #define index_to_key(i) ((i) ^ 15167)', a) + call assert_equal('#define index_to_key(i) ((i) ^ 15167)', getline('.')) + call assert_fails('cstag xxx', 'E257:') + call assert_fails('cstag', 'E562:') + + " Test 18: 'cst' option + set nocst + call assert_fails('tag TEST_COUNT', 'E426:') + set cst + let a=execute('tag TEST_COUNT') + call assert_match('(1 of 1): <<TEST_COUNT>> #define TEST_COUNT 50000', a) + call assert_equal('#define TEST_COUNT 50000', getline('.')) + let a=execute('tags') + call assert_match('1 1 TEST_COUNT\s\+\d\+\s\+#define index_to_key', a) + + " Test 19: this should trigger call to cs_print_tags() + " Unclear how to check result though, we just exercise the code. + set cst cscopequickfix=s0 + call feedkeys(":cs find s main\<CR>", 't') + + " Test 20: cscope kill + call assert_fails('cscope kill 2', 'E261:') + call assert_fails('cscope kill xxx', 'E261:') + + let a=execute('cscope kill 0') + call assert_match('cscope connection 0 closed', a) + + cscope add Xcscope.out + let a=execute('cscope kill Xcscope.out') + call assert_match('cscope connection Xcscope.out closed', a) + + cscope add Xcscope.out . + let a=execute('cscope kill -1') + call assert_match('cscope connection .*Xcscope.out closed', a) + let a=execute('cscope kill -1') + call assert_equal('', a) + + " Test 21: 'csprg' option + call assert_equal('cscope', &csprg) + set csprg=doesnotexist + call assert_fails('cscope add Xcscope2.out', 'E609:') + set csprg=cscope + + " Test 22: multiple cscope connections + cscope add Xcscope.out + cscope add Xcscope2.out . -C + let a=execute('cscope show') + call assert_match('\n 0 \d\+.*Xcscope.out\s*<none>', a) + call assert_match('\n 1 \d\+.*Xcscope2.out\s*\.', a) + + " Test 23: test Ex command line completion + call feedkeys(":cs \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"cs add find help kill reset show', @:) + + call feedkeys(":scs \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"scs find', @:) + + call feedkeys(":cs find \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"cs find a c d e f g i s t', @:) + + call feedkeys(":cs kill \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"cs kill -1 0 1', @:) + + call feedkeys(":cs add Xcscope\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"cs add Xcscope.out Xcscope2.out', @:) + + " Test 24: cscope_connection() + call assert_equal(cscope_connection(), 1) + call assert_equal(cscope_connection(0, 'out'), 1) + call assert_equal(cscope_connection(0, 'xxx'), 1) + call assert_equal(cscope_connection(1, 'out'), 1) + call assert_equal(cscope_connection(1, 'xxx'), 0) + call assert_equal(cscope_connection(2, 'out'), 0) + call assert_equal(cscope_connection(3, 'xxx', '..'), 0) + call assert_equal(cscope_connection(3, 'out', 'xxx'), 0) + call assert_equal(cscope_connection(3, 'out', '.'), 1) + call assert_equal(cscope_connection(4, 'out', '.'), 0) + + " CleanUp + call CscopeSetupOrClean(0) + +endfunc + func Test_cscopequickfix() set cscopequickfix=s-,g-,d+,c-,t+,e-,f0,i-,a- call assert_equal('s-,g-,d+,c-,t+,e-,f0,i-,a-', &cscopequickfix) @@ -13,3 +266,14 @@ func Test_cscopequickfix() call assert_fails('set cscopequickfix=s7', 'E474:') call assert_fails('set cscopequickfix=s-a', 'E474:') endfunc + +func Test_withoutCscopeConnection() + call assert_equal(cscope_connection(), 0) + + call assert_fails('cscope find s main', 'E567:') + let a=execute('cscope show') + call assert_match('no cscope connections', a) +endfunc + + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_cursor_func.vim b/src/nvim/testdir/test_cursor_func.vim index d819b7b092..e1b9651c84 100644 --- a/src/nvim/testdir/test_cursor_func.vim +++ b/src/nvim/testdir/test_cursor_func.vim @@ -1,13 +1,7 @@ " Tests for cursor(). func Test_wrong_arguments() - try - call cursor(1. 3) - " not reached - call assert_false(1) - catch - call assert_exception('E474:') - endtry + call assert_fails('call cursor(1. 3)', 'E474:') endfunc func Test_move_cursor() diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim index 7666594862..f40e06ff33 100644 --- a/src/nvim/testdir/test_diffmode.vim +++ b/src/nvim/testdir/test_diffmode.vim @@ -202,3 +202,36 @@ func Test_diffget_diffput() bwipe! enew! endfunc + +func Test_diffoff() + enew! + call setline(1, ['Two', 'Three']) + let normattr = screenattr(1, 1) + diffthis + botright vert new + call setline(1, ['One', '', 'Two', 'Three']) + diffthis + redraw + diffoff! + redraw + call assert_equal(normattr, screenattr(1, 1)) + bwipe! + bwipe! +endfunc + +func Test_setting_cursor() + new Xtest1 + put =range(1,90) + wq + new Xtest2 + put =range(1,100) + wq + + tabe Xtest2 + $ + diffsp Xtest1 + tabclose + + call delete('Xtest1') + call delete('Xtest2') +endfunc diff --git a/src/nvim/testdir/test_digraph.vim b/src/nvim/testdir/test_digraph.vim new file mode 100644 index 0000000000..6290680305 --- /dev/null +++ b/src/nvim/testdir/test_digraph.vim @@ -0,0 +1,461 @@ +" Tests for digraphs + +if !has("digraphs") || !has("multi_byte") + finish +endif + +func! Put_Dig(chars) + exe "norm! o\<c-k>".a:chars +endfu + +func! Put_Dig_BS(char1, char2) + exe "norm! o".a:char1."\<bs>".a:char2 +endfu + +func! Test_digraphs() + new + call Put_Dig("00") + call assert_equal("∞", getline('.')) + " not a digraph + call Put_Dig("el") + call assert_equal("l", getline('.')) + call Put_Dig("ht") + call assert_equal("þ", getline('.')) + " digraph "ab" is the same as "ba" + call Put_Dig("ab") + call Put_Dig("ba") + call assert_equal(["ã°","ã°"], getline(line('.')-1,line('.'))) + " Euro sign + call Put_Dig("e=") + call Put_Dig("=e") + call Put_Dig("Eu") + call Put_Dig("uE") + call assert_equal(['е']+repeat(["€"],3), getline(line('.')-3,line('.'))) + " Rouble sign + call Put_Dig("R=") + call Put_Dig("=R") + call Put_Dig("=P") + call Put_Dig("P=") + call assert_equal(['Ð ']+repeat(["₽"],2)+['П'], getline(line('.')-3,line('.'))) + " Not a digraph + call Put_Dig("a\<bs>") + call Put_Dig("\<bs>a") + call assert_equal(["<BS>", "<BS>a"], getline(line('.')-1,line('.'))) + " Grave + call Put_Dig("a!") + call Put_Dig("!e") + call Put_Dig("b!") " not defined + call assert_equal(["à ", "è", "!"], getline(line('.')-2,line('.'))) + " Acute accent + call Put_Dig("a'") + call Put_Dig("'e") + call Put_Dig("b'") " not defined + call assert_equal(["á", "é", "'"], getline(line('.')-2,line('.'))) + " Cicumflex + call Put_Dig("a>") + call Put_Dig(">e") + call Put_Dig("b>") " not defined + call assert_equal(['â', 'ê', '>'], getline(line('.')-2,line('.'))) + " Tilde + call Put_Dig("o~") + call Put_Dig("~u") " not defined + call Put_Dig("z~") " not defined + call assert_equal(['õ', 'u', '~'], getline(line('.')-2,line('.'))) + " Tilde + call Put_Dig("o?") + call Put_Dig("?u") + call Put_Dig("z?") " not defined + call assert_equal(['õ', 'Å©', '?'], getline(line('.')-2,line('.'))) + " Macron + call Put_Dig("o-") + call Put_Dig("-u") + call Put_Dig("z-") " not defined + call assert_equal(['Å', 'Å«', '-'], getline(line('.')-2,line('.'))) + " Breve + call Put_Dig("o(") + call Put_Dig("(u") + call Put_Dig("z(") " not defined + call assert_equal(['Å', 'Å', '('], getline(line('.')-2,line('.'))) + " Dot above + call Put_Dig("b.") + call Put_Dig(".e") + call Put_Dig("a.") " not defined + call assert_equal(['ḃ', 'Ä—', '.'], getline(line('.')-2,line('.'))) + " Diaresis + call Put_Dig("a:") + call Put_Dig(":u") + call Put_Dig("b:") " not defined + call assert_equal(['ä', 'ü', ':'], getline(line('.')-2,line('.'))) + " Cedilla + call Put_Dig("',") + call Put_Dig(",C") + call Put_Dig("b,") " not defined + call assert_equal(['¸', 'Ç', ','], getline(line('.')-2,line('.'))) + " Underline + call Put_Dig("B_") + call Put_Dig("_t") + call Put_Dig("a_") " not defined + call assert_equal(['Ḇ', 'ṯ', '_'], getline(line('.')-2,line('.'))) + " Stroke + call Put_Dig("j/") + call Put_Dig("/l") + call Put_Dig("b/") " not defined + call assert_equal(['/', 'Å‚', '/'], getline(line('.')-2,line('.'))) + " Double acute + call Put_Dig('O"') + call Put_Dig('"y') + call Put_Dig('b"') " not defined + call assert_equal(['Å', 'ÿ', '"'], getline(line('.')-2,line('.'))) + " Ogonek + call Put_Dig('u;') + call Put_Dig(';E') + call Put_Dig('b;') " not defined + call assert_equal(['ų', 'Ę', ';'], getline(line('.')-2,line('.'))) + " Caron + call Put_Dig('u<') + call Put_Dig('<E') + call Put_Dig('b<') " not defined + call assert_equal(['Ç”', 'Äš', '<'], getline(line('.')-2,line('.'))) + " Ring above + call Put_Dig('u0') + call Put_Dig('0E') " not defined + call Put_Dig('b0') " not defined + call assert_equal(['ů', 'E', '0'], getline(line('.')-2,line('.'))) + " Hook + call Put_Dig('u2') + call Put_Dig('2E') + call Put_Dig('b2') " not defined + call assert_equal(['á»§', 'Ẻ', '2'], getline(line('.')-2,line('.'))) + " Horn + call Put_Dig('u9') + call Put_Dig('9E') " not defined + call Put_Dig('b9') " not defined + call assert_equal(['ư', 'E', '9'], getline(line('.')-2,line('.'))) + " Cyrillic + call Put_Dig('u=') + call Put_Dig('=b') + call Put_Dig('=_') + call assert_equal(['у', 'б', '〓'], getline(line('.')-2,line('.'))) + " Greek + call Put_Dig('u*') + call Put_Dig('*b') + call Put_Dig('*_') + call assert_equal(['Ï…', 'β', '々'], getline(line('.')-2,line('.'))) + " Greek/Cyrillic special + call Put_Dig('u%') + call Put_Dig('%b') " not defined + call Put_Dig('%_') " not defined + call assert_equal(['Ï', 'b', '_'], getline(line('.')-2,line('.'))) + " Arabic + call Put_Dig('u+') + call Put_Dig('+b') + call Put_Dig('+_') " japanese industrial symbol + call assert_equal(['+', 'ب', '〄'], getline(line('.')-2,line('.'))) + " Hebrew + call Put_Dig('Q+') + call Put_Dig('+B') + call Put_Dig('+X') + call assert_equal(['×§', 'ב', '×—'], getline(line('.')-2,line('.'))) + " Latin + call Put_Dig('a3') + call Put_Dig('A3') + call Put_Dig('3X') + call assert_equal(['Ç£', 'Ç¢', 'X'], getline(line('.')-2,line('.'))) + " Bopomofo + call Put_Dig('a4') + call Put_Dig('A4') + call Put_Dig('4X') + call assert_equal(['ㄚ', '4', 'X'], getline(line('.')-2,line('.'))) + " Hiragana + call Put_Dig('a5') + call Put_Dig('A5') + call Put_Dig('5X') + call assert_equal(['ã‚', 'ã', 'X'], getline(line('.')-2,line('.'))) + " Katakana + call Put_Dig('a6') + call Put_Dig('A6') + call Put_Dig('6X') + call assert_equal(['ã‚¡', 'ã‚¢', 'X'], getline(line('.')-2,line('.'))) + " Superscripts + call Put_Dig('1S') + call Put_Dig('2S') + call Put_Dig('3S') + call assert_equal(['¹', '²', '³'], getline(line('.')-2,line('.'))) + " Subscripts + call Put_Dig('1s') + call Put_Dig('2s') + call Put_Dig('3s') + call assert_equal(['â‚', 'â‚‚', '₃'], getline(line('.')-2,line('.'))) + " Eszet (only lowercase) + call Put_Dig("ss") + call Put_Dig("SS") " start of string + call assert_equal(["ß", "˜"], getline(line('.')-1,line('.'))) + " High bit set + call Put_Dig("a ") + call Put_Dig(" A") + call assert_equal(['á', 'Ã'], getline(line('.')-1,line('.'))) + " Escape is not part of a digraph + call Put_Dig("a\<esc>") + call Put_Dig("\<esc>A") + call assert_equal(['', 'A'], getline(line('.')-1,line('.'))) + " define some custom digraphs + " old: 00 ∞ + " old: el l + digraph 00 9216 + digraph el 0252 + call Put_Dig("00") + call Put_Dig("el") + " Reset digraphs + digraph 00 8734 + digraph el 108 + call Put_Dig("00") + call Put_Dig("el") + call assert_equal(['â€', 'ü', '∞', 'l'], getline(line('.')-3,line('.'))) + bw! +endfunc + +func! Test_digraphs_option() + " reset whichwrap option, so that testing <esc><bs>A works, + " without moving up a line + set digraph ww= + new + call Put_Dig_BS("0","0") + call assert_equal("∞", getline('.')) + " not a digraph + call Put_Dig_BS("e","l") + call assert_equal("l", getline('.')) + call Put_Dig_BS("h","t") + call assert_equal("þ", getline('.')) + " digraph "ab" is the same as "ba" + call Put_Dig_BS("a","b") + call Put_Dig_BS("b","a") + call assert_equal(["ã°","ã°"], getline(line('.')-1,line('.'))) + " Euro sign + call Put_Dig_BS("e","=") + call Put_Dig_BS("=","e") + call Put_Dig_BS("E","u") + call Put_Dig_BS("u","E") + call assert_equal(['е']+repeat(["€"],3), getline(line('.')-3,line('.'))) + " Rouble sign + call Put_Dig_BS("R","=") + call Put_Dig_BS("=","R") + call Put_Dig_BS("=","P") + call Put_Dig_BS("P","=") + call assert_equal(['Ð ']+repeat(["₽"],2)+['П'], getline(line('.')-3,line('.'))) + " Not a digraph: this is different from <c-k>! + call Put_Dig_BS("a","\<bs>") + call Put_Dig_BS("\<bs>","a") + call assert_equal(['','a'], getline(line('.')-1,line('.'))) + " Grave + call Put_Dig_BS("a","!") + call Put_Dig_BS("!","e") + call Put_Dig_BS("b","!") " not defined + call assert_equal(["à ", "è", "!"], getline(line('.')-2,line('.'))) + " Acute accent + call Put_Dig_BS("a","'") + call Put_Dig_BS("'","e") + call Put_Dig_BS("b","'") " not defined + call assert_equal(["á", "é", "'"], getline(line('.')-2,line('.'))) + " Cicumflex + call Put_Dig_BS("a",">") + call Put_Dig_BS(">","e") + call Put_Dig_BS("b",">") " not defined + call assert_equal(['â', 'ê', '>'], getline(line('.')-2,line('.'))) + " Tilde + call Put_Dig_BS("o","~") + call Put_Dig_BS("~","u") " not defined + call Put_Dig_BS("z","~") " not defined + call assert_equal(['õ', 'u', '~'], getline(line('.')-2,line('.'))) + " Tilde + call Put_Dig_BS("o","?") + call Put_Dig_BS("?","u") + call Put_Dig_BS("z","?") " not defined + call assert_equal(['õ', 'Å©', '?'], getline(line('.')-2,line('.'))) + " Macron + call Put_Dig_BS("o","-") + call Put_Dig_BS("-","u") + call Put_Dig_BS("z","-") " not defined + call assert_equal(['Å', 'Å«', '-'], getline(line('.')-2,line('.'))) + " Breve + call Put_Dig_BS("o","(") + call Put_Dig_BS("(","u") + call Put_Dig_BS("z","(") " not defined + call assert_equal(['Å', 'Å', '('], getline(line('.')-2,line('.'))) + " Dot above + call Put_Dig_BS("b",".") + call Put_Dig_BS(".","e") + call Put_Dig_BS("a",".") " not defined + call assert_equal(['ḃ', 'Ä—', '.'], getline(line('.')-2,line('.'))) + " Diaresis + call Put_Dig_BS("a",":") + call Put_Dig_BS(":","u") + call Put_Dig_BS("b",":") " not defined + call assert_equal(['ä', 'ü', ':'], getline(line('.')-2,line('.'))) + " Cedilla + call Put_Dig_BS("'",",") + call Put_Dig_BS(",","C") + call Put_Dig_BS("b",",") " not defined + call assert_equal(['¸', 'Ç', ','], getline(line('.')-2,line('.'))) + " Underline + call Put_Dig_BS("B","_") + call Put_Dig_BS("_","t") + call Put_Dig_BS("a","_") " not defined + call assert_equal(['Ḇ', 'ṯ', '_'], getline(line('.')-2,line('.'))) + " Stroke + call Put_Dig_BS("j","/") + call Put_Dig_BS("/","l") + call Put_Dig_BS("b","/") " not defined + call assert_equal(['/', 'Å‚', '/'], getline(line('.')-2,line('.'))) + " Double acute + call Put_Dig_BS('O','"') + call Put_Dig_BS('"','y') + call Put_Dig_BS('b','"') " not defined + call assert_equal(['Å', 'ÿ', '"'], getline(line('.')-2,line('.'))) + " Ogonek + call Put_Dig_BS('u',';') + call Put_Dig_BS(';','E') + call Put_Dig_BS('b',';') " not defined + call assert_equal(['ų', 'Ę', ';'], getline(line('.')-2,line('.'))) + " Caron + call Put_Dig_BS('u','<') + call Put_Dig_BS('<','E') + call Put_Dig_BS('b','<') " not defined + call assert_equal(['Ç”', 'Äš', '<'], getline(line('.')-2,line('.'))) + " Ring above + call Put_Dig_BS('u','0') + call Put_Dig_BS('0','E') " not defined + call Put_Dig_BS('b','0') " not defined + call assert_equal(['ů', 'E', '0'], getline(line('.')-2,line('.'))) + " Hook + call Put_Dig_BS('u','2') + call Put_Dig_BS('2','E') + call Put_Dig_BS('b','2') " not defined + call assert_equal(['á»§', 'Ẻ', '2'], getline(line('.')-2,line('.'))) + " Horn + call Put_Dig_BS('u','9') + call Put_Dig_BS('9','E') " not defined + call Put_Dig_BS('b','9') " not defined + call assert_equal(['ư', 'E', '9'], getline(line('.')-2,line('.'))) + " Cyrillic + call Put_Dig_BS('u','=') + call Put_Dig_BS('=','b') + call Put_Dig_BS('=','_') + call assert_equal(['у', 'б', '〓'], getline(line('.')-2,line('.'))) + " Greek + call Put_Dig_BS('u','*') + call Put_Dig_BS('*','b') + call Put_Dig_BS('*','_') + call assert_equal(['Ï…', 'β', '々'], getline(line('.')-2,line('.'))) + " Greek/Cyrillic special + call Put_Dig_BS('u','%') + call Put_Dig_BS('%','b') " not defined + call Put_Dig_BS('%','_') " not defined + call assert_equal(['Ï', 'b', '_'], getline(line('.')-2,line('.'))) + " Arabic + call Put_Dig_BS('u','+') + call Put_Dig_BS('+','b') + call Put_Dig_BS('+','_') " japanese industrial symbol + call assert_equal(['+', 'ب', '〄'], getline(line('.')-2,line('.'))) + " Hebrew + call Put_Dig_BS('Q','+') + call Put_Dig_BS('+','B') + call Put_Dig_BS('+','X') + call assert_equal(['×§', 'ב', '×—'], getline(line('.')-2,line('.'))) + " Latin + call Put_Dig_BS('a','3') + call Put_Dig_BS('A','3') + call Put_Dig_BS('3','X') + call assert_equal(['Ç£', 'Ç¢', 'X'], getline(line('.')-2,line('.'))) + " Bopomofo + call Put_Dig_BS('a','4') + call Put_Dig_BS('A','4') + call Put_Dig_BS('4','X') + call assert_equal(['ㄚ', '4', 'X'], getline(line('.')-2,line('.'))) + " Hiragana + call Put_Dig_BS('a','5') + call Put_Dig_BS('A','5') + call Put_Dig_BS('5','X') + call assert_equal(['ã‚', 'ã', 'X'], getline(line('.')-2,line('.'))) + " Katakana + call Put_Dig_BS('a','6') + call Put_Dig_BS('A','6') + call Put_Dig_BS('6','X') + call assert_equal(['ã‚¡', 'ã‚¢', 'X'], getline(line('.')-2,line('.'))) + " Superscripts + call Put_Dig_BS('1','S') + call Put_Dig_BS('2','S') + call Put_Dig_BS('3','S') + call assert_equal(['¹', '²', '³'], getline(line('.')-2,line('.'))) + " Subscripts + call Put_Dig_BS('1','s') + call Put_Dig_BS('2','s') + call Put_Dig_BS('3','s') + call assert_equal(['â‚', 'â‚‚', '₃'], getline(line('.')-2,line('.'))) + " Eszet (only lowercase) + call Put_Dig_BS("s","s") + call Put_Dig_BS("S","S") " start of string + call assert_equal(["ß", "˜"], getline(line('.')-1,line('.'))) + " High bit set (different from <c-k>) + call Put_Dig_BS("a"," ") + call Put_Dig_BS(" ","A") + call assert_equal([' ', 'A'], getline(line('.')-1,line('.'))) + " Escape is not part of a digraph (different from <c-k>) + call Put_Dig_BS("a","\<esc>") + call Put_Dig_BS("\<esc>","A") + call assert_equal(['', ''], getline(line('.')-1,line('.'))) + " define some custom digraphs + " old: 00 ∞ + " old: el l + digraph 00 9216 + digraph el 0252 + call Put_Dig_BS("0","0") + call Put_Dig_BS("e","l") + " Reset digraphs + digraph 00 8734 + digraph el 108 + call Put_Dig_BS("0","0") + call Put_Dig_BS("e","l") + call assert_equal(['â€', 'ü', '∞', 'l'], getline(line('.')-3,line('.'))) + set nodigraph ww&vim + bw! +endfunc + +func! Test_digraphs_output() + new + let out = execute(':digraph') + call assert_equal('Eu € 8364', matchstr(out, '\C\<Eu\D*8364\>')) + call assert_equal('=e € 8364', matchstr(out, '\C=e\D*8364\>')) + call assert_equal('=R ₽ 8381', matchstr(out, '\C=R\D*8381\>')) + call assert_equal('=P ₽ 8381', matchstr(out, '\C=P\D*8381\>')) + call assert_equal('o: ö 246', matchstr(out, '\C\<o:\D*246\>')) + call assert_equal('v4 ㄪ 12586', matchstr(out, '\C\<v4\D*12586\>')) + call assert_equal("'0 Ëš 730", matchstr(out, '\C''0\D*730\>')) + call assert_equal('Z% Ж 1046', matchstr(out, '\C\<Z%\D*1046\>')) + call assert_equal('u- Å« 363', matchstr(out, '\C\<u-\D*363\>')) + call assert_equal('SH ^A 1', matchstr(out, '\C\<SH\D*1\>')) + bw! +endfunc + +func! Test_loadkeymap() + if !has('keymap') + return + endif + new + set keymap=czech + set iminsert=0 + call feedkeys("o|\<c-^>|01234567890|\<esc>", 'tx') + call assert_equal("|'é+ěšÄřžýáÃé'", getline('.')) + " reset keymap and encoding option + set keymap= + bw! +endfunc + +func! Test_digraph_cmndline() + " Create digraph on commandline + " This is a hack, to let Vim create the digraph in commandline mode + let s = '' + exe "sil! norm! :let s.='\<c-k>Eu'\<cr>" + call assert_equal("€", s) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_display.vim b/src/nvim/testdir/test_display.vim new file mode 100644 index 0000000000..0ed672d577 --- /dev/null +++ b/src/nvim/testdir/test_display.vim @@ -0,0 +1,71 @@ +" Test for displaying stuff + +" Nvim: `:set term` is not supported. +" if !has('gui_running') && has('unix') +" set term=ansi +" endif + +source view_util.vim + +func! Test_display_foldcolumn() + if !has("folding") + return + endif + new + vnew + vert resize 25 + call assert_equal(25, winwidth(winnr())) + set isprint=@ + + 1put='e more noise blah blah‚ more stuff here' + + let expect = [ + \ "e more noise blah blah<82", + \ "> more stuff here " + \ ] + + call cursor(2, 1) + norm! zt + let lines=ScreenLines([1,2], winwidth(0)) + call assert_equal(expect, lines) + set fdc=2 + let lines=ScreenLines([1,2], winwidth(0)) + let expect = [ + \ " e more noise blah blah<", + \ " 82> more stuff here " + \ ] + call assert_equal(expect, lines) + + quit! + quit! +endfunc + +func! Test_display_foldtext_mbyte() + if !has("folding") || !has("multi_byte") + return + endif + call NewWindow(10, 40) + call append(0, range(1,20)) + exe "set foldmethod=manual foldtext=foldtext() fillchars=fold:\u2500,vert:\u2502 fdc=2" + call cursor(2, 1) + norm! zf13G + let lines=ScreenLines([1,3], winwidth(0)+1) + let expect=[ + \ " 1 \u2502", + \ "+ +-- 12 lines: 2". repeat("\u2500", 23). "\u2502", + \ " 14 \u2502", + \ ] + call assert_equal(expect, lines) + + set fillchars=fold:-,vert:\| + let lines=ScreenLines([1,3], winwidth(0)+1) + let expect=[ + \ " 1 |", + \ "+ +-- 12 lines: 2". repeat("-", 23). "|", + \ " 14 |", + \ ] + call assert_equal(expect, lines) + + set foldtext& fillchars& foldmethod& fdc& + bw! +endfunc diff --git a/src/nvim/testdir/test_expr.vim b/src/nvim/testdir/test_expr.vim index 7483973fca..d32facaa98 100644 --- a/src/nvim/testdir/test_expr.vim +++ b/src/nvim/testdir/test_expr.vim @@ -1,20 +1,5 @@ " Tests for expressions. -func Test_version() - call assert_true(has('patch-7.4.001')) - call assert_true(has('patch-7.4.01')) - call assert_true(has('patch-7.4.1')) - call assert_true(has('patch-6.9.999')) - call assert_true(has('patch-7.1.999')) - call assert_true(has('patch-7.4.123')) - - call assert_false(has('patch-7')) - call assert_false(has('patch-7.4')) - call assert_false(has('patch-7.4.')) - call assert_false(has('patch-9.1.0')) - call assert_false(has('patch-9.9.1')) -endfunc - func Test_equal() let base = {} func base.method() @@ -37,6 +22,35 @@ func Test_equal() call assert_fails('echo base.method > instance.method') endfunc +func Test_version() + call assert_true(has('patch-7.4.001')) + call assert_true(has('patch-7.4.01')) + call assert_true(has('patch-7.4.1')) + call assert_true(has('patch-6.9.999')) + call assert_true(has('patch-7.1.999')) + call assert_true(has('patch-7.4.123')) + + call assert_false(has('patch-7')) + call assert_false(has('patch-7.4')) + call assert_false(has('patch-7.4.')) + call assert_false(has('patch-9.1.0')) + call assert_false(has('patch-9.9.1')) +endfunc + +func Test_dict() + let d = {'': 'empty', 'a': 'a', 0: 'zero'} + call assert_equal('empty', d['']) + call assert_equal('a', d['a']) + call assert_equal('zero', d[0]) + call assert_true(has_key(d, '')) + call assert_true(has_key(d, 'a')) + + let d[''] = 'none' + let d['a'] = 'aaa' + call assert_equal('none', d['']) + call assert_equal('aaa', d['a']) +endfunc + func Test_strgetchar() call assert_equal(char2nr('a'), strgetchar('axb', 0)) call assert_equal(char2nr('x'), strgetchar('axb', 1)) @@ -61,24 +75,10 @@ func Test_strcharpart() call assert_equal('a', strcharpart('axb', -1, 2)) endfunc -func Test_dict() - let d = {'': 'empty', 'a': 'a', 0: 'zero'} - call assert_equal('empty', d['']) - call assert_equal('a', d['a']) - call assert_equal('zero', d[0]) - call assert_true(has_key(d, '')) - call assert_true(has_key(d, 'a')) - - let d[''] = 'none' - let d['a'] = 'aaa' - call assert_equal('none', d['']) - call assert_equal('aaa', d['a']) -endfunc - func Test_loop_over_null_list() let null_list = submatch(1, 1) for i in null_list - call assert_true(0, 'should not get here') + call assert_report('should not get here') endfor endfunc @@ -92,3 +92,350 @@ endfunc func Test_set_reg_null_list() call setreg('x', v:_null_list) endfunc + +func Test_special_char() + " The failure is only visible using valgrind. + call assert_fails('echo "\<C-">') +endfunc + +func Test_option_value() + " boolean + set bri + call assert_equal(1, &bri) + set nobri + call assert_equal(0, &bri) + + " number + set ts=1 + call assert_equal(1, &ts) + set ts=8 + call assert_equal(8, &ts) + + " string + exe "set cedit=\<Esc>" + call assert_equal("\<Esc>", &cedit) + set cpo= + call assert_equal("", &cpo) + set cpo=abcdefi + call assert_equal("abcdefi", &cpo) + set cpo&vim +endfunc + +function Test_printf_64bit() + if has('num64') + call assert_equal("123456789012345", printf('%d', 123456789012345)) + endif +endfunc + +func Test_setmatches() + hi def link 1 Comment + hi def link 2 PreProc + let set = [{"group": 1, "pattern": 2, "id": 3, "priority": 4}] + let exp = [{"group": '1', "pattern": '2', "id": 3, "priority": 4}] + if has('conceal') + let set[0]['conceal'] = 5 + let exp[0]['conceal'] = '5' + endif + call setmatches(set) + call assert_equal(exp, getmatches()) +endfunc + +function Test_printf_spec_s() + " number + call assert_equal("1234567890", printf('%s', 1234567890)) + + " string + call assert_equal("abcdefgi", printf('%s', "abcdefgi")) + + " float + call assert_equal("1.23", printf('%s', 1.23)) + + " list + let value = [1, 'two', ['three', 4]] + call assert_equal(string(value), printf('%s', value)) + + " dict + let value = {'key1' : 'value1', 'key2' : ['list', 'value'], 'key3' : {'dict' : 'value'}} + call assert_equal(string(value), printf('%s', value)) + + " funcref + call assert_equal('printf', printf('%s', function('printf'))) + + " partial + call assert_equal(string(function('printf', ['%s'])), printf('%s', function('printf', ['%s']))) +endfunc + +function Test_printf_misc() + call assert_equal('123', printf('%d', 123)) + call assert_equal('123', printf('%i', 123)) + call assert_equal('123', printf('%D', 123)) + call assert_equal('123', printf('%U', 123)) + call assert_equal('173', printf('%o', 123)) + call assert_equal('173', printf('%O', 123)) + call assert_equal('7b', printf('%x', 123)) + call assert_equal('7B', printf('%X', 123)) + call assert_equal('{', printf('%c', 123)) + call assert_equal('abc', printf('%s', 'abc')) + call assert_equal('abc', printf('%S', 'abc')) + + call assert_equal('+123', printf('%+d', 123)) + call assert_equal('-123', printf('%+d', -123)) + call assert_equal('+123', printf('%+ d', 123)) + call assert_equal(' 123', printf('% d', 123)) + call assert_equal(' 123', printf('% d', 123)) + call assert_equal('-123', printf('% d', -123)) + + call assert_equal('123', printf('%2d', 123)) + call assert_equal(' 123', printf('%6d', 123)) + call assert_equal('000123', printf('%06d', 123)) + call assert_equal('+00123', printf('%+06d', 123)) + call assert_equal(' 00123', printf('% 06d', 123)) + call assert_equal(' +123', printf('%+6d', 123)) + call assert_equal(' 123', printf('% 6d', 123)) + call assert_equal(' -123', printf('% 6d', -123)) + + " Test left adjusted. + call assert_equal('123 ', printf('%-6d', 123)) + call assert_equal('+123 ', printf('%-+6d', 123)) + call assert_equal(' 123 ', printf('%- 6d', 123)) + call assert_equal('-123 ', printf('%- 6d', -123)) + + call assert_equal(' 00123', printf('%7.5d', 123)) + call assert_equal(' -00123', printf('%7.5d', -123)) + call assert_equal(' +00123', printf('%+7.5d', 123)) + " Precision field should not be used when combined with %0 + call assert_equal(' 00123', printf('%07.5d', 123)) + call assert_equal(' -00123', printf('%07.5d', -123)) + + call assert_equal(' 123', printf('%*d', 5, 123)) + call assert_equal('123 ', printf('%*d', -5, 123)) + call assert_equal('00123', printf('%.*d', 5, 123)) + call assert_equal(' 123', printf('% *d', 5, 123)) + call assert_equal(' +123', printf('%+ *d', 5, 123)) + + " Simple quote (thousand grouping char) is ignored. + call assert_equal('+00123456', printf("%+'09d", 123456)) + + " Unrecognized format specifier kept as-is. + call assert_equal('_123', printf("%_%d", 123)) + + " Test alternate forms. + call assert_equal('0x7b', printf('%#x', 123)) + call assert_equal('0X7B', printf('%#X', 123)) + call assert_equal('0173', printf('%#o', 123)) + call assert_equal('0173', printf('%#O', 123)) + call assert_equal('abc', printf('%#s', 'abc')) + call assert_equal('abc', printf('%#S', 'abc')) + call assert_equal(' 0173', printf('%#6o', 123)) + call assert_equal(' 00173', printf('%#6.5o', 123)) + call assert_equal(' 0173', printf('%#6.2o', 123)) + call assert_equal(' 0173', printf('%#6.2o', 123)) + call assert_equal('0173', printf('%#2.2o', 123)) + + call assert_equal(' 00123', printf('%6.5d', 123)) + call assert_equal(' 0007b', printf('%6.5x', 123)) + + call assert_equal('abc', printf('%2s', 'abc')) + call assert_equal('abc', printf('%2S', 'abc')) + call assert_equal('abc', printf('%.4s', 'abc')) + call assert_equal('abc', printf('%.4S', 'abc')) + call assert_equal('ab', printf('%.2s', 'abc')) + call assert_equal('ab', printf('%.2S', 'abc')) + call assert_equal('', printf('%.0s', 'abc')) + call assert_equal('', printf('%.s', 'abc')) + call assert_equal(' abc', printf('%4s', 'abc')) + call assert_equal(' abc', printf('%4S', 'abc')) + call assert_equal('0abc', printf('%04s', 'abc')) + call assert_equal('0abc', printf('%04S', 'abc')) + call assert_equal('abc ', printf('%-4s', 'abc')) + call assert_equal('abc ', printf('%-4S', 'abc')) + + call assert_equal('1%', printf('%d%%', 1)) +endfunc + +function Test_printf_float() + call assert_equal('1.000000', printf('%f', 1)) + call assert_equal('1.230000', printf('%f', 1.23)) + call assert_equal('1.230000', printf('%F', 1.23)) + call assert_equal('9999999.9', printf('%g', 9999999.9)) + call assert_equal('9999999.9', printf('%G', 9999999.9)) + call assert_equal('1.00000001e7', printf('%.8g', 10000000.1)) + call assert_equal('1.00000001E7', printf('%.8G', 10000000.1)) + call assert_equal('1.230000e+00', printf('%e', 1.23)) + call assert_equal('1.230000E+00', printf('%E', 1.23)) + call assert_equal('1.200000e-02', printf('%e', 0.012)) + call assert_equal('-1.200000e-02', printf('%e', -0.012)) + call assert_equal('0.33', printf('%.2f', 1.0/3.0)) + call assert_equal(' 0.33', printf('%6.2f', 1.0/3.0)) + call assert_equal(' -0.33', printf('%6.2f', -1.0/3.0)) + call assert_equal('000.33', printf('%06.2f', 1.0/3.0)) + call assert_equal('-00.33', printf('%06.2f', -1.0/3.0)) + call assert_equal('-00.33', printf('%+06.2f', -1.0/3.0)) + call assert_equal('+00.33', printf('%+06.2f', 1.0/3.0)) + call assert_equal(' 00.33', printf('% 06.2f', 1.0/3.0)) + call assert_equal('000.33', printf('%06.2g', 1.0/3.0)) + call assert_equal('-00.33', printf('%06.2g', -1.0/3.0)) + call assert_equal('0.33', printf('%3.2f', 1.0/3.0)) + call assert_equal('003.33e-01', printf('%010.2e', 1.0/3.0)) + call assert_equal(' 03.33e-01', printf('% 010.2e', 1.0/3.0)) + call assert_equal('+03.33e-01', printf('%+010.2e', 1.0/3.0)) + call assert_equal('-03.33e-01', printf('%010.2e', -1.0/3.0)) + + " When precision is 0, the dot should be omitted. + call assert_equal(' 2', printf('%3.f', 7.0/3.0)) + call assert_equal(' 2', printf('%3.g', 7.0/3.0)) + call assert_equal(' 2e+00', printf('%7.e', 7.0/3.0)) + + " Float zero can be signed. + call assert_equal('+0.000000', printf('%+f', 0.0)) + call assert_equal('0.000000', printf('%f', 1.0/(1.0/0.0))) + call assert_equal('-0.000000', printf('%f', 1.0/(-1.0/0.0))) + call assert_equal('0.0', printf('%s', 1.0/(1.0/0.0))) + call assert_equal('-0.0', printf('%s', 1.0/(-1.0/0.0))) + call assert_equal('0.0', printf('%S', 1.0/(1.0/0.0))) + call assert_equal('-0.0', printf('%S', 1.0/(-1.0/0.0))) + + " Float infinity can be signed. + call assert_equal('inf', printf('%f', 1.0/0.0)) + call assert_equal('-inf', printf('%f', -1.0/0.0)) + call assert_equal('inf', printf('%g', 1.0/0.0)) + call assert_equal('-inf', printf('%g', -1.0/0.0)) + call assert_equal('inf', printf('%e', 1.0/0.0)) + call assert_equal('-inf', printf('%e', -1.0/0.0)) + call assert_equal('INF', printf('%F', 1.0/0.0)) + call assert_equal('-INF', printf('%F', -1.0/0.0)) + call assert_equal('INF', printf('%E', 1.0/0.0)) + call assert_equal('-INF', printf('%E', -1.0/0.0)) + call assert_equal('INF', printf('%E', 1.0/0.0)) + call assert_equal('-INF', printf('%G', -1.0/0.0)) + call assert_equal('+inf', printf('%+f', 1.0/0.0)) + call assert_equal('-inf', printf('%+f', -1.0/0.0)) + call assert_equal(' inf', printf('% f', 1.0/0.0)) + call assert_equal(' inf', printf('%6f', 1.0/0.0)) + call assert_equal(' -inf', printf('%6f', -1.0/0.0)) + call assert_equal(' inf', printf('%6g', 1.0/0.0)) + call assert_equal(' -inf', printf('%6g', -1.0/0.0)) + call assert_equal(' +inf', printf('%+6f', 1.0/0.0)) + call assert_equal(' inf', printf('% 6f', 1.0/0.0)) + call assert_equal(' +inf', printf('%+06f', 1.0/0.0)) + call assert_equal('inf ', printf('%-6f', 1.0/0.0)) + call assert_equal('-inf ', printf('%-6f', -1.0/0.0)) + call assert_equal('+inf ', printf('%-+6f', 1.0/0.0)) + call assert_equal(' inf ', printf('%- 6f', 1.0/0.0)) + call assert_equal('-INF ', printf('%-6F', -1.0/0.0)) + call assert_equal('+INF ', printf('%-+6F', 1.0/0.0)) + call assert_equal(' INF ', printf('%- 6F', 1.0/0.0)) + call assert_equal('INF ', printf('%-6G', 1.0/0.0)) + call assert_equal('-INF ', printf('%-6G', -1.0/0.0)) + call assert_equal('INF ', printf('%-6E', 1.0/0.0)) + call assert_equal('-INF ', printf('%-6E', -1.0/0.0)) + call assert_equal("str2float('inf')", printf('%s', 1.0/0.0)) + call assert_equal("-str2float('inf')", printf('%s', -1.0/0.0)) + + " Float nan (not a number) has no sign. + call assert_equal('nan', printf('%f', sqrt(-1.0))) + call assert_equal('nan', printf('%f', 0.0/0.0)) + call assert_equal('nan', printf('%f', -0.0/0.0)) + call assert_equal('nan', printf('%g', 0.0/0.0)) + call assert_equal('nan', printf('%e', 0.0/0.0)) + call assert_equal('NAN', printf('%F', 0.0/0.0)) + call assert_equal('NAN', printf('%G', 0.0/0.0)) + call assert_equal('NAN', printf('%E', 0.0/0.0)) + call assert_equal('NAN', printf('%F', -0.0/0.0)) + call assert_equal('NAN', printf('%G', -0.0/0.0)) + call assert_equal('NAN', printf('%E', -0.0/0.0)) + call assert_equal(' nan', printf('%6f', 0.0/0.0)) + call assert_equal(' nan', printf('%06f', 0.0/0.0)) + call assert_equal('nan ', printf('%-6f', 0.0/0.0)) + call assert_equal('nan ', printf('%- 6f', 0.0/0.0)) + call assert_equal("str2float('nan')", printf('%s', 0.0/0.0)) + call assert_equal("str2float('nan')", printf('%s', -0.0/0.0)) + call assert_equal("str2float('nan')", printf('%S', 0.0/0.0)) + call assert_equal("str2float('nan')", printf('%S', -0.0/0.0)) + + call assert_fails('echo printf("%f", "a")', 'E807:') +endfunc + +function Test_printf_errors() + call assert_fails('echo printf("%d", {})', 'E728:') + call assert_fails('echo printf("%d", [])', 'E745:') + call assert_fails('echo printf("%d", 1, 2)', 'E767:') + call assert_fails('echo printf("%*d", 1)', 'E766:') + call assert_fails('echo printf("%d", 1.2)', 'E805:') +endfunc + +function Test_max_min_errors() + call assert_fails('call max(v:true)', 'E712:') + call assert_fails('call max(v:true)', 'max()') + call assert_fails('call min(v:true)', 'E712:') + call assert_fails('call min(v:true)', 'min()') +endfunc + +func Test_substitute_expr() + let g:val = 'XXX' + call assert_equal('XXX', substitute('yyy', 'y*', '\=g:val', '')) + call assert_equal('XXX', substitute('yyy', 'y*', {-> g:val}, '')) + call assert_equal("-\u1b \uf2-", substitute("-%1b %f2-", '%\(\x\x\)', + \ '\=nr2char("0x" . submatch(1))', 'g')) + call assert_equal("-\u1b \uf2-", substitute("-%1b %f2-", '%\(\x\x\)', + \ {-> nr2char("0x" . submatch(1))}, 'g')) + + call assert_equal('231', substitute('123', '\(.\)\(.\)\(.\)', + \ {-> submatch(2) . submatch(3) . submatch(1)}, '')) + + func Recurse() + return substitute('yyy', 'y\(.\)y', {-> submatch(1)}, '') + endfunc + " recursive call works + call assert_equal('-y-x-', substitute('xxx', 'x\(.\)x', {-> '-' . Recurse() . '-' . submatch(1) . '-'}, '')) +endfunc + +func Test_invalid_submatch() + " This was causing invalid memory access in Vim-7.4.2232 and older + call assert_fails("call substitute('x', '.', {-> submatch(10)}, '')", 'E935:') +endfunc + +func Test_substitute_expr_arg() + call assert_equal('123456789-123456789=', substitute('123456789', + \ '\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)', + \ {m -> m[0] . '-' . m[1] . m[2] . m[3] . m[4] . m[5] . m[6] . m[7] . m[8] . m[9] . '='}, '')) + + call assert_equal('123456-123456=789', substitute('123456789', + \ '\(.\)\(.\)\(.\)\(a*\)\(n*\)\(.\)\(.\)\(.\)\(x*\)', + \ {m -> m[0] . '-' . m[1] . m[2] . m[3] . m[4] . m[5] . m[6] . m[7] . m[8] . m[9] . '='}, '')) + + call assert_equal('123456789-123456789x=', substitute('123456789', + \ '\(.\)\(.\)\(.*\)', + \ {m -> m[0] . '-' . m[1] . m[2] . m[3] . 'x' . m[4] . m[5] . m[6] . m[7] . m[8] . m[9] . '='}, '')) + + call assert_fails("call substitute('xxx', '.', {m -> string(add(m, 'x'))}, '')", 'E742:') + call assert_fails("call substitute('xxx', '.', {m -> string(insert(m, 'x'))}, '')", 'E742:') + call assert_fails("call substitute('xxx', '.', {m -> string(extend(m, ['x']))}, '')", 'E742:') + call assert_fails("call substitute('xxx', '.', {m -> string(remove(m, 1))}, '')", 'E742:') +endfunc + +func Test_function_with_funcref() + let s:f = function('type') + let s:fref = function(s:f) + call assert_equal(v:t_string, s:fref('x')) + call assert_fails("call function('s:f')", 'E700:') + + call assert_fails("call function('foo()')", 'E475:') + call assert_fails("call function('foo()')", 'foo()') +endfunc + +func Test_funcref() + func! One() + return 1 + endfunc + let OneByName = function('One') + let OneByRef = funcref('One') + func! One() + return 2 + endfunc + call assert_equal(2, OneByName()) + call assert_equal(1, OneByRef()) + let OneByRef = funcref('One') + call assert_equal(2, OneByRef()) + call assert_fails('echo funcref("{")', 'E475:') +endfunc diff --git a/src/nvim/testdir/test_expr_utf8.vim b/src/nvim/testdir/test_expr_utf8.vim index 097d708329..9ea6d8872b 100644 --- a/src/nvim/testdir/test_expr_utf8.vim +++ b/src/nvim/testdir/test_expr_utf8.vim @@ -35,60 +35,3 @@ func Test_strcharpart_utf8() call assert_equal('Ì€', strcharpart('aÌ€xb', 1, 1)) call assert_equal('x', strcharpart('aÌ€xb', 2, 1)) endfunc - -func s:classes_test() - set isprint=@,161-255 - call assert_equal('Motörhead', matchstr('Motörhead', '[[:print:]]\+')) - - let alphachars = '' - let lowerchars = '' - let upperchars = '' - let alnumchars = '' - let printchars = '' - let punctchars = '' - let xdigitchars = '' - let i = 1 - while i <= 255 - let c = nr2char(i) - if c =~ '[[:alpha:]]' - let alphachars .= c - endif - if c =~ '[[:lower:]]' - let lowerchars .= c - endif - if c =~ '[[:upper:]]' - let upperchars .= c - endif - if c =~ '[[:alnum:]]' - let alnumchars .= c - endif - if c =~ '[[:print:]]' - let printchars .= c - endif - if c =~ '[[:punct:]]' - let punctchars .= c - endif - if c =~ '[[:xdigit:]]' - let xdigitchars .= c - endif - let i += 1 - endwhile - - call assert_equal('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', alphachars) - call assert_equal('abcdefghijklmnopqrstuvwxyzµßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿ', lowerchars) - call assert_equal('ABCDEFGHIJKLMNOPQRSTUVWXYZÀÃÂÃÄÅÆÇÈÉÊËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞ', upperchars) - call assert_equal('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', alnumchars) - call assert_equal(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ¡¢£¤¥¦§¨©ª«¬Â®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÃÂÃÄÅÆÇÈÉÊËÌÃÃŽÃÃÑÒÓÔÕÖרÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõö÷øùúûüýþÿ', printchars) - call assert_equal('!"#$%&''()*+,-./:;<=>?@[\]^_`{|}~', punctchars) - call assert_equal('0123456789ABCDEFabcdef', xdigitchars) -endfunc - -func Test_classes_re1() - set re=1 - call s:classes_test() -endfunc - -func Test_classes_re2() - set re=2 - call s:classes_test() -endfunc diff --git a/src/nvim/testdir/test_farsi.vim b/src/nvim/testdir/test_farsi.vim new file mode 100644 index 0000000000..e094191599 --- /dev/null +++ b/src/nvim/testdir/test_farsi.vim @@ -0,0 +1,84 @@ +" Simplistic testing of Farsi mode. + +if !has('farsi') || has('nvim') " Not supported in Nvim. #6192 + finish +endif +" Farsi uses a single byte encoding. +set enc=latin1 + +func Test_farsi_toggle() + new + + set altkeymap + call assert_equal(0, &fkmap) + call assert_equal(0, &rl) + call feedkeys("\<F8>", 'x') + call assert_equal(1, &fkmap) + call assert_equal(1, &rl) + call feedkeys("\<F8>", 'x') + call assert_equal(0, &fkmap) + call assert_equal(0, &rl) + + set rl + " conversion from Farsi 3342 to Farsi VIM. + call setline(1, join(map(range(0x80, 0xff), 'nr2char(v:val)'), '')) + call feedkeys("\<F9>", 'x') + let exp = [0xfc, 0xf8, 0xc1, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + \ 0xc8, 0xc9, 0xca, 0xd0, 0xd1, 0xd2, 0xd3, 0xd6, + \ 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd8, 0xd9, 0xda, + \ 0xdb, 0xdc, 0xdc, 0xc1, 0xdd, 0xde, 0xe0, 0xe0, + \ 0xe1, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, + \ 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, + \ 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + \ 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, + \ 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, + \ 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, + \ 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, + \ 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, + \ 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, + \ 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xfb, 0xfb, 0xfe, + \ 0xfe, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, + \ 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xe1, + \ ] + call assert_equal(join(map(exp, 'nr2char(v:val)'), ''), getline(1)) + + " conversion from Farsi VIM to Farsi 3342. + call setline(1, join(map(range(0x80, 0xff), 'nr2char(v:val)'), '')) + call feedkeys("\<F9>", 'x') + let exp = [0xfc, 0xf8, 0xc1, 0x83, 0x84, 0x85, 0x86, 0x87, + \ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x90, + \ 0x90, 0x90, 0x92, 0x93, 0x93, 0x95, 0x96, 0x97, + \ 0x98, 0xdc, 0x9a, 0x9b, 0x9c, 0x9e, 0x9e, 0xff, + \ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + \ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + \ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + \ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + \ 0xc0, 0xc1, 0xc2, 0x83, 0x84, 0x85, 0x86, 0x87, + \ 0x88, 0x89, 0x8a, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + \ 0x8b, 0x8c, 0x8d, 0x8e, 0xd4, 0xd5, 0x90, 0x93, + \ 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0xdf, + \ 0x9d, 0xff, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + \ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xec, 0xee, 0xef, + \ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + \ 0xf8, 0xf9, 0xfa, 0xec, 0x80, 0xfd, 0xee, 0xff, + \ ] + call assert_equal(join(map(exp, 'nr2char(v:val)'), ''), getline(1)) + + bwipe! +endfunc + +func Test_farsi_map() + new + + set altkeymap + set rl + " RHS of mapping is reversed. + imap xyz abc + call feedkeys("axyz\<Esc>", 'tx') + call assert_equal('cba', getline(1)) + + set norl + iunmap xyz + set noaltkeymap + bwipe! +endfunc diff --git a/src/nvim/testdir/test_fileformat.vim b/src/nvim/testdir/test_fileformat.vim new file mode 100644 index 0000000000..584f20cdfc --- /dev/null +++ b/src/nvim/testdir/test_fileformat.vim @@ -0,0 +1,17 @@ +" Test behavior of fileformat after bwipeout of last buffer + +func Test_fileformat_after_bw() + bwipeout + set fileformat& + if &fileformat == 'dos' + let test_fileformats = 'unix' + elseif &fileformat == 'unix' + let test_fileformats = 'mac' + else " must be mac + let test_fileformats = 'dos' + endif + exec 'set fileformats='.test_fileformats + bwipeout! + call assert_equal(test_fileformats, &fileformat) + set fileformats& +endfunc diff --git a/src/nvim/testdir/test_filter_cmd.vim b/src/nvim/testdir/test_filter_cmd.vim new file mode 100644 index 0000000000..5aa5fa64df --- /dev/null +++ b/src/nvim/testdir/test_filter_cmd.vim @@ -0,0 +1,76 @@ +" Test the :filter command modifier + +func Test_filter() + edit Xdoesnotmatch + edit Xwillmatch + call assert_equal('"Xwillmatch"', substitute(execute('filter willma ls'), '[^"]*\(".*"\)[^"]*', '\1', '')) + bwipe Xdoesnotmatch + bwipe Xwillmatch + + new + call setline(1, ['foo1', 'foo2', 'foo3', 'foo4', 'foo5']) + call assert_equal("\nfoo2\nfoo4", execute('filter /foo[24]/ 1,$print')) + call assert_equal("\n 2 foo2\n 4 foo4", execute('filter /foo[24]/ 1,$number')) + call assert_equal("\nfoo2$\nfoo4$", execute('filter /foo[24]/ 1,$list')) + + call assert_equal("\nfoo1$\nfoo3$\nfoo5$", execute('filter! /foo[24]/ 1,$list')) + bwipe! + + command XTryThis echo 'this' + command XTryThat echo 'that' + command XDoThat echo 'that' + let lines = split(execute('filter XTry command'), "\n") + call assert_equal(3, len(lines)) + call assert_match("XTryThat", lines[1]) + call assert_match("XTryThis", lines[2]) + delcommand XTryThis + delcommand XTryThat + delcommand XDoThat + + map f1 the first key + map f2 the second key + map f3 not a key + let lines = split(execute('filter the map f'), "\n") + call assert_equal(2, len(lines)) + call assert_match("f2", lines[0]) + call assert_match("f1", lines[1]) + unmap f1 + unmap f2 + unmap f3 +endfunc + +func Test_filter_fails() + call assert_fails('filter', 'E471:') + call assert_fails('filter pat', 'E476:') + call assert_fails('filter /pat', 'E476:') + call assert_fails('filter /pat/', 'E476:') + call assert_fails('filter /pat/ asdf', 'E492:') + + call assert_fails('filter!', 'E471:') + call assert_fails('filter! pat', 'E476:') + call assert_fails('filter! /pat', 'E476:') + call assert_fails('filter! /pat/', 'E476:') + call assert_fails('filter! /pat/ asdf', 'E492:') +endfunc + +function s:complete_filter_cmd(filtcmd) + let keystroke = "\<TAB>\<C-R>=execute('let cmdline = getcmdline()')\<CR>\<C-C>" + let cmdline = '' + call feedkeys(':' . a:filtcmd . keystroke, 'ntx') + return cmdline +endfunction + +func Test_filter_cmd_completion() + " Do not complete pattern + call assert_equal("filter \t", s:complete_filter_cmd('filter ')) + call assert_equal("filter pat\t", s:complete_filter_cmd('filter pat')) + call assert_equal("filter /pat\t", s:complete_filter_cmd('filter /pat')) + call assert_equal("filter /pat/\t", s:complete_filter_cmd('filter /pat/')) + + " Complete after string pattern + call assert_equal('filter pat print', s:complete_filter_cmd('filter pat pri')) + + " Complete after regexp pattern + call assert_equal('filter /pat/ print', s:complete_filter_cmd('filter /pat/ pri')) + call assert_equal('filter #pat# print', s:complete_filter_cmd('filter #pat# pri')) +endfunc diff --git a/src/nvim/testdir/test_filter_map.vim b/src/nvim/testdir/test_filter_map.vim new file mode 100644 index 0000000000..c8d64ce0a4 --- /dev/null +++ b/src/nvim/testdir/test_filter_map.vim @@ -0,0 +1,81 @@ +" Test filter() and map() + +" list with expression string +func Test_filter_map_list_expr_string() + " filter() + call assert_equal([2, 3, 4], filter([1, 2, 3, 4], 'v:val > 1')) + call assert_equal([3, 4], filter([1, 2, 3, 4], 'v:key > 1')) + call assert_equal([], filter([1, 2, 3, 4], 0)) + + " map() + call assert_equal([2, 4, 6, 8], map([1, 2, 3, 4], 'v:val * 2')) + call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], 'v:key * 2')) + call assert_equal([9, 9, 9, 9], map([1, 2, 3, 4], 9)) +endfunc + +" dict with expression string +func Test_filter_map_dict_expr_string() + let dict = {"foo": 1, "bar": 2, "baz": 3} + + " filter() + call assert_equal({"bar": 2, "baz": 3}, filter(copy(dict), 'v:val > 1')) + call assert_equal({"foo": 1, "baz": 3}, filter(copy(dict), 'v:key > "bar"')) + call assert_equal({}, filter(copy(dict), 0)) + + " map() + call assert_equal({"foo": 2, "bar": 4, "baz": 6}, map(copy(dict), 'v:val * 2')) + call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, map(copy(dict), 'v:key[0]')) + call assert_equal({"foo": 9, "bar": 9, "baz": 9}, map(copy(dict), 9)) +endfunc + +" list with funcref +func Test_filter_map_list_expr_funcref() + " filter() + func! s:filter1(index, val) abort + return a:val > 1 + endfunc + call assert_equal([2, 3, 4], filter([1, 2, 3, 4], function('s:filter1'))) + + func! s:filter2(index, val) abort + return a:index > 1 + endfunc + call assert_equal([3, 4], filter([1, 2, 3, 4], function('s:filter2'))) + + " map() + func! s:filter3(index, val) abort + return a:val * 2 + endfunc + call assert_equal([2, 4, 6, 8], map([1, 2, 3, 4], function('s:filter3'))) + + func! s:filter4(index, val) abort + return a:index * 2 + endfunc + call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], function('s:filter4'))) +endfunc + +" dict with funcref +func Test_filter_map_dict_expr_funcref() + let dict = {"foo": 1, "bar": 2, "baz": 3} + + " filter() + func! s:filter1(key, val) abort + return a:val > 1 + endfunc + call assert_equal({"bar": 2, "baz": 3}, filter(copy(dict), function('s:filter1'))) + + func! s:filter2(key, val) abort + return a:key > "bar" + endfunc + call assert_equal({"foo": 1, "baz": 3}, filter(copy(dict), function('s:filter2'))) + + " map() + func! s:filter3(key, val) abort + return a:val * 2 + endfunc + call assert_equal({"foo": 2, "bar": 4, "baz": 6}, map(copy(dict), function('s:filter3'))) + + func! s:filter4(key, val) abort + return a:key[0] + endfunc + call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, map(copy(dict), function('s:filter4'))) +endfunc diff --git a/src/nvim/testdir/test_float_func.vim b/src/nvim/testdir/test_float_func.vim new file mode 100644 index 0000000000..5ea5192994 --- /dev/null +++ b/src/nvim/testdir/test_float_func.vim @@ -0,0 +1,332 @@ +" test float functions + +if !has('float') + finish +end + +func Test_abs() + call assert_equal('1.23', string(abs(1.23))) + call assert_equal('1.23', string(abs(-1.23))) + call assert_equal('0.0', string(abs(0.0))) + call assert_equal('0.0', string(abs(1.0/(1.0/0.0)))) + call assert_equal('0.0', string(abs(-1.0/(1.0/0.0)))) + call assert_equal("str2float('inf')", string(abs(1.0/0.0))) + call assert_equal("str2float('inf')", string(abs(-1.0/0.0))) + call assert_equal("str2float('nan')", string(abs(0.0/0.0))) + call assert_equal('12', string(abs('-12abc'))) + call assert_fails("call abs([])", 'E745:') + call assert_fails("call abs({})", 'E728:') + call assert_fails("call abs(function('string'))", 'E703:') +endfunc + +func Test_sqrt() + call assert_equal('0.0', string(sqrt(0.0))) + call assert_equal('1.414214', string(sqrt(2.0))) + call assert_equal("str2float('inf')", string(sqrt(1.0/0.0))) + call assert_equal("str2float('nan')", string(sqrt(-1.0))) + call assert_equal("str2float('nan')", string(sqrt(0.0/0.0))) + call assert_fails('call sqrt("")', 'E808:') +endfunc + +func Test_log() + call assert_equal('0.0', string(log(1.0))) + call assert_equal('-0.693147', string(log(0.5))) + call assert_equal("-str2float('inf')", string(log(0.0))) + call assert_equal("str2float('nan')", string(log(-1.0))) + call assert_equal("str2float('inf')", string(log(1.0/0.0))) + call assert_equal("str2float('nan')", string(log(0.0/0.0))) + call assert_fails('call log("")', 'E808:') +endfunc + +func Test_log10() + call assert_equal('0.0', string(log10(1.0))) + call assert_equal('2.0', string(log10(100.0))) + call assert_equal('2.079181', string(log10(120.0))) + call assert_equal("-str2float('inf')", string(log10(0.0))) + call assert_equal("str2float('nan')", string(log10(-1.0))) + call assert_equal("str2float('inf')", string(log10(1.0/0.0))) + call assert_equal("str2float('nan')", string(log10(0.0/0.0))) + call assert_fails('call log10("")', 'E808:') +endfunc + +func Test_exp() + call assert_equal('1.0', string(exp(0.0))) + call assert_equal('7.389056', string(exp(2.0))) + call assert_equal('0.367879', string(exp(-1.0))) + call assert_equal("str2float('inf')", string(exp(1.0/0.0))) + call assert_equal('0.0', string(exp(-1.0/0.0))) + call assert_equal("str2float('nan')", string(exp(0.0/0.0))) + call assert_fails('call exp("")', 'E808:') +endfunc + +func Test_sin() + call assert_equal('0.0', string(sin(0.0))) + call assert_equal('0.841471', string(sin(1.0))) + call assert_equal('-0.479426', string(sin(-0.5))) + call assert_equal("str2float('nan')", string(sin(0.0/0.0))) + call assert_equal("str2float('nan')", string(sin(1.0/0.0))) + call assert_equal('0.0', string(sin(1.0/(1.0/0.0)))) + call assert_equal('-0.0', string(sin(-1.0/(1.0/0.0)))) + call assert_fails('call sin("")', 'E808:') +endfunc + +func Test_asin() + call assert_equal('0.0', string(asin(0.0))) + call assert_equal('1.570796', string(asin(1.0))) + call assert_equal('-0.523599', string(asin(-0.5))) + call assert_equal("str2float('nan')", string(asin(1.1))) + call assert_equal("str2float('nan')", string(asin(1.0/0.0))) + call assert_equal("str2float('nan')", string(asin(0.0/0.0))) + call assert_fails('call asin("")', 'E808:') +endfunc + +func Test_sinh() + call assert_equal('0.0', string(sinh(0.0))) + call assert_equal('0.521095', string(sinh(0.5))) + call assert_equal('-1.026517', string(sinh(-0.9))) + call assert_equal("str2float('inf')", string(sinh(1.0/0.0))) + call assert_equal("-str2float('inf')", string(sinh(-1.0/0.0))) + call assert_equal("str2float('nan')", string(sinh(0.0/0.0))) + call assert_fails('call sinh("")', 'E808:') +endfunc + +func Test_cos() + call assert_equal('1.0', string(cos(0.0))) + call assert_equal('0.540302', string(cos(1.0))) + call assert_equal('0.877583', string(cos(-0.5))) + call assert_equal("str2float('nan')", string(cos(0.0/0.0))) + call assert_equal("str2float('nan')", string(cos(1.0/0.0))) + call assert_fails('call cos("")', 'E808:') +endfunc + +func Test_acos() + call assert_equal('1.570796', string(acos(0.0))) + call assert_equal('0.0', string(acos(1.0))) + call assert_equal('3.141593', string(acos(-1.0))) + call assert_equal('2.094395', string(acos(-0.5))) + call assert_equal("str2float('nan')", string(acos(1.1))) + call assert_equal("str2float('nan')", string(acos(1.0/0.0))) + call assert_equal("str2float('nan')", string(acos(0.0/0.0))) + call assert_fails('call acos("")', 'E808:') +endfunc + +func Test_cosh() + call assert_equal('1.0', string(cosh(0.0))) + call assert_equal('1.127626', string(cosh(0.5))) + call assert_equal("str2float('inf')", string(cosh(1.0/0.0))) + call assert_equal("str2float('inf')", string(cosh(-1.0/0.0))) + call assert_equal("str2float('nan')", string(cosh(0.0/0.0))) + call assert_fails('call cosh("")', 'E808:') +endfunc + +func Test_tan() + call assert_equal('0.0', string(tan(0.0))) + call assert_equal('0.546302', string(tan(0.5))) + call assert_equal('-0.546302', string(tan(-0.5))) + call assert_equal("str2float('nan')", string(tan(1.0/0.0))) + call assert_equal("str2float('nan')", string(cos(0.0/0.0))) + call assert_equal('0.0', string(tan(1.0/(1.0/0.0)))) + call assert_equal('-0.0', string(tan(-1.0/(1.0/0.0)))) + call assert_fails('call tan("")', 'E808:') +endfunc + +func Test_atan() + call assert_equal('0.0', string(atan(0.0))) + call assert_equal('0.463648', string(atan(0.5))) + call assert_equal('-0.785398', string(atan(-1.0))) + call assert_equal('1.570796', string(atan(1.0/0.0))) + call assert_equal('-1.570796', string(atan(-1.0/0.0))) + call assert_equal("str2float('nan')", string(atan(0.0/0.0))) + call assert_fails('call atan("")', 'E808:') +endfunc + +func Test_atan2() + call assert_equal('-2.356194', string(atan2(-1, -1))) + call assert_equal('2.356194', string(atan2(1, -1))) + call assert_equal('0.0', string(atan2(1.0, 1.0/0.0))) + call assert_equal('1.570796', string(atan2(1.0/0.0, 1.0))) + call assert_equal("str2float('nan')", string(atan2(0.0/0.0, 1.0))) + call assert_fails('call atan2("", -1)', 'E808:') + call assert_fails('call atan2(-1, "")', 'E808:') +endfunc + +func Test_tanh() + call assert_equal('0.0', string(tanh(0.0))) + call assert_equal('0.462117', string(tanh(0.5))) + call assert_equal('-0.761594', string(tanh(-1.0))) + call assert_equal('1.0', string(tanh(1.0/0.0))) + call assert_equal('-1.0', string(tanh(-1.0/0.0))) + call assert_equal("str2float('nan')", string(tanh(0.0/0.0))) + call assert_fails('call tanh("")', 'E808:') +endfunc + +func Test_fmod() + call assert_equal('0.13', string(fmod(12.33, 1.22))) + call assert_equal('-0.13', string(fmod(-12.33, 1.22))) + call assert_equal("str2float('nan')", string(fmod(1.0/0.0, 1.0))) + " On Windows we get "nan" instead of 1.0, accept both. + let res = string(fmod(1.0, 1.0/0.0)) + if res != "str2float('nan')" + call assert_equal('1.0', res) + endif + call assert_equal("str2float('nan')", string(fmod(1.0, 0.0))) + call assert_fails("call fmod('', 1.22)", 'E808:') + call assert_fails("call fmod(12.33, '')", 'E808:') +endfunc + +func Test_pow() + call assert_equal('1.0', string(pow(0.0, 0.0))) + call assert_equal('8.0', string(pow(2.0, 3.0))) + call assert_equal("str2float('nan')", string(pow(2.0, 0.0/0.0))) + call assert_equal("str2float('nan')", string(pow(0.0/0.0, 3.0))) + call assert_equal("str2float('nan')", string(pow(0.0/0.0, 3.0))) + call assert_equal("str2float('inf')", string(pow(2.0, 1.0/0.0))) + call assert_equal("str2float('inf')", string(pow(1.0/0.0, 3.0))) + call assert_fails("call pow('', 2.0)", 'E808:') + call assert_fails("call pow(2.0, '')", 'E808:') +endfunc + +func Test_str2float() + call assert_equal('1.0', string(str2float('1'))) + call assert_equal('1.0', string(str2float(' 1 '))) + call assert_equal('1.0', string(str2float(' 1.0 '))) + call assert_equal('1.23', string(str2float('1.23'))) + call assert_equal('1.23', string(str2float('1.23abc'))) + call assert_equal('1.0e40', string(str2float('1e40'))) + call assert_equal('-1.23', string(str2float('-1.23'))) + call assert_equal('1.23', string(str2float(' + 1.23 '))) + + call assert_equal('1.0', string(str2float('+1'))) + call assert_equal('1.0', string(str2float('+1'))) + call assert_equal('1.0', string(str2float(' +1 '))) + call assert_equal('1.0', string(str2float(' + 1 '))) + + call assert_equal('-1.0', string(str2float('-1'))) + call assert_equal('-1.0', string(str2float('-1'))) + call assert_equal('-1.0', string(str2float(' -1 '))) + call assert_equal('-1.0', string(str2float(' - 1 '))) + + call assert_equal('0.0', string(str2float('+0.0'))) + call assert_equal('-0.0', string(str2float('-0.0'))) + call assert_equal("str2float('inf')", string(str2float('1e1000'))) + call assert_equal("str2float('inf')", string(str2float('inf'))) + call assert_equal("-str2float('inf')", string(str2float('-inf'))) + call assert_equal("str2float('inf')", string(str2float('+inf'))) + call assert_equal("str2float('inf')", string(str2float('Inf'))) + call assert_equal("str2float('inf')", string(str2float(' +inf '))) + call assert_equal("str2float('nan')", string(str2float('nan'))) + call assert_equal("str2float('nan')", string(str2float('NaN'))) + call assert_equal("str2float('nan')", string(str2float(' nan '))) + + call assert_fails("call str2float(1.2)", 'E806:') + call assert_fails("call str2float([])", 'E730:') + call assert_fails("call str2float({})", 'E731:') + call assert_fails("call str2float(function('string'))", 'E729:') +endfunc + +func Test_float2nr() + call assert_equal(1, float2nr(1.234)) + call assert_equal(123, float2nr(1.234e2)) + call assert_equal(12, float2nr(123.4e-1)) + let max_number = 1/0 + let min_number = -max_number + call assert_equal(max_number/2+1, float2nr(pow(2, 62))) + call assert_equal(max_number, float2nr(pow(2, 63))) + call assert_equal(max_number, float2nr(pow(2, 64))) + call assert_equal(min_number/2-1, float2nr(-pow(2, 62))) + call assert_equal(min_number, float2nr(-pow(2, 63))) + call assert_equal(min_number, float2nr(-pow(2, 64))) +endfunc + +func Test_floor() + call assert_equal('2.0', string(floor(2.0))) + call assert_equal('2.0', string(floor(2.11))) + call assert_equal('2.0', string(floor(2.99))) + call assert_equal('-3.0', string(floor(-2.11))) + call assert_equal('-3.0', string(floor(-2.99))) + call assert_equal("str2float('nan')", string(floor(0.0/0.0))) + call assert_equal("str2float('inf')", string(floor(1.0/0.0))) + call assert_equal("-str2float('inf')", string(floor(-1.0/0.0))) + call assert_fails("call floor('')", 'E808:') +endfunc + +func Test_ceil() + call assert_equal('2.0', string(ceil(2.0))) + call assert_equal('3.0', string(ceil(2.11))) + call assert_equal('3.0', string(ceil(2.99))) + call assert_equal('-2.0', string(ceil(-2.11))) + call assert_equal('-2.0', string(ceil(-2.99))) + call assert_equal("str2float('nan')", string(ceil(0.0/0.0))) + call assert_equal("str2float('inf')", string(ceil(1.0/0.0))) + call assert_equal("-str2float('inf')", string(ceil(-1.0/0.0))) + call assert_fails("call ceil('')", 'E808:') +endfunc + +func Test_round() + call assert_equal('2.0', string(round(2.1))) + call assert_equal('3.0', string(round(2.5))) + call assert_equal('3.0', string(round(2.9))) + call assert_equal('-2.0', string(round(-2.1))) + call assert_equal('-3.0', string(round(-2.5))) + call assert_equal('-3.0', string(round(-2.9))) + call assert_equal("str2float('nan')", string(round(0.0/0.0))) + call assert_equal("str2float('inf')", string(round(1.0/0.0))) + call assert_equal("-str2float('inf')", string(round(-1.0/0.0))) + call assert_fails("call round('')", 'E808:') +endfunc + +func Test_trunc() + call assert_equal('2.0', string(trunc(2.1))) + call assert_equal('2.0', string(trunc(2.5))) + call assert_equal('2.0', string(trunc(2.9))) + call assert_equal('-2.0', string(trunc(-2.1))) + call assert_equal('-2.0', string(trunc(-2.5))) + call assert_equal('-2.0', string(trunc(-2.9))) + call assert_equal("str2float('nan')", string(trunc(0.0/0.0))) + call assert_equal("str2float('inf')", string(trunc(1.0/0.0))) + call assert_equal("-str2float('inf')", string(trunc(-1.0/0.0))) + call assert_fails("call trunc('')", 'E808:') +endfunc + +func Test_isnan() + throw 'skipped: Nvim does not support isnan()' + call assert_equal(0, isnan(1.0)) + call assert_equal(1, isnan(0.0/0.0)) + call assert_equal(0, isnan(1.0/0.0)) + call assert_equal(0, isnan('a')) + call assert_equal(0, isnan([])) + call assert_equal(0, isnan({})) +endfunc + +" This was converted from test65 +func Test_float_misc() + call assert_equal('123.456000', printf('%f', 123.456)) + call assert_equal('1.234560e+02', printf('%e', 123.456)) + call assert_equal('123.456', printf('%g', 123.456)) + " += + let v = 1.234 + let v += 6.543 + call assert_equal('7.777', printf('%g', v)) + let v = 1.234 + let v += 5 + call assert_equal('6.234', printf('%g', v)) + let v = 5 + let v += 3.333 + call assert_equal('8.333', string(v)) + " == + let v = 1.234 + call assert_true(v == 1.234) + call assert_false(v == 1.2341) + " add-subtract + call assert_equal('5.234', printf('%g', 4 + 1.234)) + call assert_equal('-6.766', printf('%g', 1.234 - 8)) + " mult-div + call assert_equal('4.936', printf('%g', 4 * 1.234)) + call assert_equal('0.003241', printf('%g', 4.0 / 1234)) + " dict + call assert_equal("{'x': 1.234, 'y': -2.0e20}", string({'x': 1.234, 'y': -2.0e20})) + " list + call assert_equal('[-123.4, 2.0e-20]', string([-123.4, 2.0e-20])) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_fnameescape.vim b/src/nvim/testdir/test_fnameescape.vim new file mode 100644 index 0000000000..cdff0dfbd9 --- /dev/null +++ b/src/nvim/testdir/test_fnameescape.vim @@ -0,0 +1,21 @@ + +" Test if fnameescape is correct for special chars like ! +function! Test_fnameescape() + let fname = 'Xspa ce' + let status = v:false + try + exe "w! " . fnameescape(fname) + let status = v:true + endtry + call assert_true(status, "Space") + call delete(fname) + + let fname = 'Xemark!' + let status = v:false + try + exe "w! " . fnameescape(fname) + let status = v:true + endtry + call assert_true(status, "ExclamationMark") + call delete(fname) +endfunction diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim new file mode 100644 index 0000000000..46c54e8614 --- /dev/null +++ b/src/nvim/testdir/test_fold.vim @@ -0,0 +1,362 @@ +" Test for folding + +func! PrepIndent(arg) + return [a:arg] + repeat(["\t".a:arg], 5) +endfu + +func! Test_address_fold() + new + call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/', + \ 'after fold 1', 'after fold 2', 'after fold 3']) + setl fen fdm=marker + " The next ccommands should all copy the same part of the buffer, + " regardless of the adressing type, since the part to be copied + " is folded away + :1y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1)) + :.y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1)) + :.+y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1)) + :.,.y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1)) + :sil .1,.y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1)) + " use silent to make E493 go away + :sil .+,.y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1)) + :,y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1)) + :,+y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/','after fold 1'], getreg(0,1,1)) + " using .+3 as second address should copy the whole folded line + the next 3 + " lines + :.,+3y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/', + \ 'after fold 1', 'after fold 2', 'after fold 3'], getreg(0,1,1)) + :sil .,-2y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1)) + + " now test again with folding disabled + set nofoldenable + :1y + call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1)) + :.y + call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1)) + :.+y + call assert_equal(['1'], getreg(0,1,1)) + :.,.y + call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1)) + " use silent to make E493 go away + :sil .1,.y + call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1)) + " use silent to make E493 go away + :sil .+,.y + call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1)) + :,y + call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1)) + :,+y + call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1)) + " using .+3 as second address should copy the whole folded line + the next 3 + " lines + :.,+3y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3'], getreg(0,1,1)) + :7 + :sil .,-2y + call assert_equal(['4', '5', '}/*}}}*/'], getreg(0,1,1)) + + quit! +endfunc + +func! Test_indent_fold() + new + call setline(1, ['', 'a', ' b', ' c']) + setl fen fdm=indent + 2 + norm! >> + let a=map(range(1,4), 'foldclosed(v:val)') + call assert_equal([-1,-1,-1,-1], a) +endfunc + +func! Test_indent_fold() + new + call setline(1, ['', 'a', ' b', ' c']) + setl fen fdm=indent + 2 + norm! >> + let a=map(range(1,4), 'foldclosed(v:val)') + call assert_equal([-1,-1,-1,-1], a) + bw! +endfunc + +func! Test_indent_fold2() + new + call setline(1, ['', '{{{', '}}}', '{{{', '}}}']) + setl fen fdm=marker + 2 + norm! >> + let a=map(range(1,5), 'foldclosed(v:val)') + call assert_equal([-1,-1,-1,4,4], a) + bw! +endfunc + +func Test_manual_fold_with_filter() + if !executable('cat') + return + endif + for type in ['manual', 'marker'] + exe 'set foldmethod=' . type + new + call setline(1, range(1, 20)) + 4,$fold + %foldopen + 10,$fold + %foldopen + " This filter command should not have an effect + 1,8! cat + call feedkeys('5ggzdzMGdd', 'xt') + call assert_equal(['1', '2', '3', '4', '5', '6', '7', '8', '9'], getline(1, '$')) + + bwipe! + set foldmethod& + endfor +endfunc + +func! Test_indent_fold_with_read() + new + set foldmethod=indent + call setline(1, repeat(["\<Tab>a"], 4)) + for n in range(1, 4) + call assert_equal(1, foldlevel(n)) + endfor + + call writefile(["a", "", "\<Tab>a"], 'Xfile') + foldopen + 2read Xfile + %foldclose + call assert_equal(1, foldlevel(1)) + call assert_equal(2, foldclosedend(1)) + call assert_equal(0, foldlevel(3)) + call assert_equal(0, foldlevel(4)) + call assert_equal(1, foldlevel(5)) + call assert_equal(7, foldclosedend(5)) + + bwipe! + set foldmethod& + call delete('Xfile') +endfunc + +func Test_combining_folds_indent() + new + let one = "\<Tab>a" + let zero = 'a' + call setline(1, [one, one, zero, zero, zero, one, one, one]) + set foldmethod=indent + 3,5d + %foldclose + call assert_equal(5, foldclosedend(1)) + + set foldmethod& + bwipe! +endfunc + +func Test_combining_folds_marker() + new + call setline(1, ['{{{', '}}}', '', '', '', '{{{', '', '}}}']) + set foldmethod=marker + 3,5d + %foldclose + call assert_equal(2, foldclosedend(1)) + + set foldmethod& + bwipe! +endfunc + +func Test_folds_marker_in_comment() + new + call setline(1, ['" foo', 'bar', 'baz']) + setl fen fdm=marker + setl com=sO:\"\ -,mO:\"\ \ ,eO:\"\",:\" cms=\"%s + norm! zf2j + setl nofen + :1y + call assert_equal(['" foo{{{'], getreg(0,1,1)) + :+2y + call assert_equal(['baz"}}}'], getreg(0,1,1)) + + set foldmethod& + bwipe! +endfunc + +func s:TestFoldExpr(lnum) + let thisline = getline(a:lnum) + if thisline == 'a' + return 1 + elseif thisline == 'b' + return 0 + elseif thisline == 'c' + return '<1' + elseif thisline == 'd' + return '>1' + endif + return 0 +endfunction + +func Test_update_folds_expr_read() + new + call setline(1, ['a', 'a', 'a', 'a', 'a', 'a']) + set foldmethod=expr + set foldexpr=s:TestFoldExpr(v:lnum) + 2 + foldopen + call writefile(['b', 'b', 'a', 'a', 'd', 'a', 'a', 'c'], 'Xfile') + read Xfile + %foldclose + call assert_equal(2, foldclosedend(1)) + call assert_equal(0, foldlevel(3)) + call assert_equal(0, foldlevel(4)) + call assert_equal(6, foldclosedend(5)) + call assert_equal(10, foldclosedend(7)) + call assert_equal(14, foldclosedend(11)) + + call delete('Xfile') + bwipe! + set foldmethod& foldexpr& +endfunc + +func! Test_move_folds_around_manual() + new + let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c") + call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c")) + let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14] + " all folds closed + set foldenable foldlevel=0 fdm=indent + " needs a forced redraw + redraw! + set fdm=manual + call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) + call assert_equal(input, getline(1, '$')) + 7,12m0 + call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$')) + call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) + 10,12m0 + call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$')) + call assert_equal([1, 1, 1, 1, 1, -1, 7, 7, 7, 7, 7, -1, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)')) + " moving should not close the folds + %d + call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c")) + set fdm=indent + redraw! + set fdm=manual + call cursor(2, 1) + %foldopen + 7,12m0 + let folds=repeat([-1], 18) + call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$')) + call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) + norm! zM + " folds are not corrupted and all have been closed + call assert_equal([-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)')) + %d + call setline(1, ["a", "\tb", "\tc", "\td", "\te"]) + set fdm=indent + redraw! + set fdm=manual + %foldopen + 3m4 + %foldclose + call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$')) + call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)')) + %d + call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"]) + set fdm=indent foldlevel=0 + set fdm=manual + %foldopen + 3m1 + %foldclose + call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$')) + call assert_equal(0, foldlevel(2)) + call assert_equal(5, foldclosedend(3)) + call assert_equal([-1, -1, 3, 3, 3, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)')) + 2,6m$ + %foldclose + call assert_equal(5, foldclosedend(2)) + call assert_equal(0, foldlevel(6)) + call assert_equal(9, foldclosedend(7)) + call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, -1], map(range(1, line('$')), 'foldclosed(v:val)')) + %d + " Ensure moving around the edges still works. + call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"]) + set fdm=indent foldlevel=0 + set fdm=manual + %foldopen + 6m$ + " The first fold has been truncated to the 5'th line. + " Second fold has been moved up because the moved line is now below it. + call assert_equal([0, 1, 1, 1, 1, 0, 0, 0, 1, 0], map(range(1, line('$')), 'foldlevel(v:val)')) + bw! +endfunc + +func! Test_move_folds_around_indent() + new + let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c") + call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c")) + let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14] + " all folds closed + set fdm=indent + call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) + call assert_equal(input, getline(1, '$')) + 7,12m0 + call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$')) + call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) + 10,12m0 + call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$')) + call assert_equal([1, 1, 1, 1, 1, -1, 7, 7, 7, 7, 7, -1, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)')) + " moving should not close the folds + %d + call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c")) + set fdm=indent + call cursor(2, 1) + %foldopen + 7,12m0 + let folds=repeat([-1], 18) + call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$')) + call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) + norm! zM + " folds are not corrupted and all have been closed + call assert_equal([-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)')) + %d + call setline(1, ["a", "\tb", "\tc", "\td", "\te"]) + set fdm=indent + %foldopen + 3m4 + %foldclose + call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$')) + call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)')) + %d + call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"]) + set fdm=indent foldlevel=0 + %foldopen + 3m1 + %foldclose + call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$')) + call assert_equal(1, foldlevel(2)) + call assert_equal(5, foldclosedend(3)) + call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)')) + 2,6m$ + %foldclose + call assert_equal(9, foldclosedend(2)) + call assert_equal(1, foldlevel(6)) + call assert_equal(9, foldclosedend(7)) + call assert_equal([-1, 2, 2, 2, 2, 2, 2, 2, 2, -1], map(range(1, line('$')), 'foldclosed(v:val)')) + " Ensure moving around the edges still works. + %d + call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"]) + set fdm=indent foldlevel=0 + %foldopen + 6m$ + " The first fold has been truncated to the 5'th line. + " Second fold has been moved up because the moved line is now below it. + call assert_equal([0, 1, 1, 1, 1, 0, 0, 0, 1, 1], map(range(1, line('$')), 'foldlevel(v:val)')) + bw! +endfunc diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim new file mode 100644 index 0000000000..237a2dc820 --- /dev/null +++ b/src/nvim/testdir/test_functions.vim @@ -0,0 +1,194 @@ +" Tests for various functions. + +func Test_str2nr() + call assert_equal(0, str2nr('')) + call assert_equal(1, str2nr('1')) + call assert_equal(1, str2nr(' 1 ')) + + call assert_equal(1, str2nr('+1')) + call assert_equal(1, str2nr('+ 1')) + call assert_equal(1, str2nr(' + 1 ')) + + call assert_equal(-1, str2nr('-1')) + call assert_equal(-1, str2nr('- 1')) + call assert_equal(-1, str2nr(' - 1 ')) + + call assert_equal(123456789, str2nr('123456789')) + call assert_equal(-123456789, str2nr('-123456789')) +endfunc + +func Test_setbufvar_options() + " This tests that aucmd_prepbuf() and aucmd_restbuf() properly restore the + " window layout. + call assert_equal(1, winnr('$')) + split dummy_preview + resize 2 + set winfixheight winfixwidth + let prev_id = win_getid() + + wincmd j + let wh = winheight('.') + let dummy_buf = bufnr('dummy_buf1', v:true) + call setbufvar(dummy_buf, '&buftype', 'nofile') + execute 'belowright vertical split #' . dummy_buf + call assert_equal(wh, winheight('.')) + let dum1_id = win_getid() + + wincmd h + let wh = winheight('.') + let dummy_buf = bufnr('dummy_buf2', v:true) + call setbufvar(dummy_buf, '&buftype', 'nofile') + execute 'belowright vertical split #' . dummy_buf + call assert_equal(wh, winheight('.')) + + bwipe! + call win_gotoid(prev_id) + bwipe! + call win_gotoid(dum1_id) + bwipe! +endfunc + +func Test_tolower() + call assert_equal("", tolower("")) + + " Test with all printable ASCII characters. + call assert_equal(' !"#$%&''()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~', + \ tolower(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~')) + + if !has('multi_byte') + return + endif + + " Test with a few uppercase diacritics. + call assert_equal("aà áâãäåÄăąǎǟǡả", tolower("AÀÃÂÃÄÅĀĂĄÇÇžÇ áº¢")) + call assert_equal("bḃḇ", tolower("BḂḆ")) + call assert_equal("cçćĉċÄ", tolower("CÇĆĈĊČ")) + call assert_equal("dÄđḋá¸á¸‘", tolower("DÄŽÄḊḎá¸")) + call assert_equal("eèéêëēĕėęěẻẽ", tolower("EÈÉÊËĒĔĖĘĚẺẼ")) + call assert_equal("fḟ ", tolower("FḞ ")) + call assert_equal("gÄğġģǥǧǵḡ", tolower("GÄœÄžÄ Ä¢Ç¤Ç¦Ç´á¸ ")) + call assert_equal("hĥħḣḧḩ", tolower("HĤĦḢḦḨ")) + call assert_equal("iìÃîïĩīÄįiÇỉ", tolower("IÃŒÃÃŽÃĨĪĬĮİÇỈ")) + call assert_equal("jĵ", tolower("JÄ´")) + call assert_equal("kķǩḱḵ", tolower("KĶǨḰḴ")) + call assert_equal("lĺļľŀłḻ", tolower("LĹĻĽĿÅḺ")) + call assert_equal("mḿá¹", tolower("MḾṀ")) + call assert_equal("nñńņňṅṉ", tolower("NÑŃŅŇṄṈ")) + call assert_equal("oòóôõöøÅÅőơǒǫÇá»", tolower("OÃ’Ã“Ã”Ã•Ã–Ã˜ÅŒÅŽÅÆ ǑǪǬỎ")) + call assert_equal("pṕṗ", tolower("PṔṖ")) + call assert_equal("q", tolower("Q")) + call assert_equal("rŕŗřṙṟ", tolower("RŔŖŘṘṞ")) + call assert_equal("sÅ›Åşšṡ", tolower("SŚŜŞŠṠ")) + call assert_equal("tţťŧṫṯ", tolower("TŢŤŦṪṮ")) + call assert_equal("uùúûüũūÅůűųưǔủ", tolower("UÙÚÛÜŨŪŬŮŰŲƯǓỦ")) + call assert_equal("vá¹½", tolower("Vá¹¼")) + call assert_equal("wŵáºáºƒáº…ẇ", tolower("WŴẀẂẄẆ")) + call assert_equal("xẋáº", tolower("XẊẌ")) + call assert_equal("yýŷÿáºá»³á»·á»¹", tolower("YÃŶŸẎỲỶỸ")) + call assert_equal("zźżžƶẑẕ", tolower("ZŹŻŽƵáºáº”")) + + " Test with a few lowercase diacritics, which should remain unchanged. + call assert_equal("aà áâãäåÄăąǎǟǡả", tolower("aà áâãäåÄăąǎǟǡả")) + call assert_equal("bḃḇ", tolower("bḃḇ")) + call assert_equal("cçćĉċÄ", tolower("cçćĉċÄ")) + call assert_equal("dÄđḋá¸á¸‘", tolower("dÄđḋá¸á¸‘")) + call assert_equal("eèéêëēĕėęěẻẽ", tolower("eèéêëēĕėęěẻẽ")) + call assert_equal("fḟ", tolower("fḟ")) + call assert_equal("gÄğġģǥǧǵḡ", tolower("gÄğġģǥǧǵḡ")) + call assert_equal("hĥħḣḧḩẖ", tolower("hĥħḣḧḩẖ")) + call assert_equal("iìÃîïĩīÄįÇỉ", tolower("iìÃîïĩīÄįÇỉ")) + call assert_equal("jĵǰ", tolower("jĵǰ")) + call assert_equal("kķǩḱḵ", tolower("kķǩḱḵ")) + call assert_equal("lĺļľŀłḻ", tolower("lĺļľŀłḻ")) + call assert_equal("mḿṠ", tolower("mḿṠ")) + call assert_equal("nñńņňʼnṅṉ", tolower("nñńņňʼnṅṉ")) + call assert_equal("oòóôõöøÅÅőơǒǫÇá»", tolower("oòóôõöøÅÅőơǒǫÇá»")) + call assert_equal("pṕṗ", tolower("pṕṗ")) + call assert_equal("q", tolower("q")) + call assert_equal("rŕŗřṙṟ", tolower("rŕŗřṙṟ")) + call assert_equal("sÅ›Åşšṡ", tolower("sÅ›Åşšṡ")) + call assert_equal("tţťŧṫṯẗ", tolower("tţťŧṫṯẗ")) + call assert_equal("uùúûüũūÅůűųưǔủ", tolower("uùúûüũūÅůűųưǔủ")) + call assert_equal("vá¹½", tolower("vá¹½")) + call assert_equal("wŵáºáºƒáº…ẇẘ", tolower("wŵáºáºƒáº…ẇẘ")) + call assert_equal("ẋáº", tolower("ẋáº")) + call assert_equal("yýÿŷáºáº™á»³á»·á»¹", tolower("yýÿŷáºáº™á»³á»·á»¹")) + call assert_equal("zźżžƶẑẕ", tolower("zźżžƶẑẕ")) + + " According to https://twitter.com/jifa/status/625776454479970304 + " Ⱥ (U+023A) and Ⱦ (U+023E) are the *only* code points to increase + " in length (2 to 3 bytes) when lowercased. So let's test them. + call assert_equal("â±¥ ⱦ", tolower("Ⱥ Ⱦ")) +endfunc + +func Test_toupper() + call assert_equal("", toupper("")) + + " Test with all printable ASCII characters. + call assert_equal(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~', + \ toupper(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~')) + + if !has('multi_byte') + return + endif + + " Test with a few lowercase diacritics. + call assert_equal("AÀÃÂÃÄÅĀĂĄÇÇžÇ áº¢", toupper("aà áâãäåÄăąǎǟǡả")) + call assert_equal("BḂḆ", toupper("bḃḇ")) + call assert_equal("CÇĆĈĊČ", toupper("cçćĉċÄ")) + call assert_equal("DÄŽÄḊḎá¸", toupper("dÄđḋá¸á¸‘")) + call assert_equal("EÈÉÊËĒĔĖĘĚẺẼ", toupper("eèéêëēĕėęěẻẽ")) + call assert_equal("FḞ", toupper("fḟ")) + call assert_equal("GÄœÄžÄ Ä¢Ç¤Ç¦Ç´á¸ ", toupper("gÄğġģǥǧǵḡ")) + call assert_equal("HĤĦḢḦḨẖ", toupper("hĥħḣḧḩẖ")) + call assert_equal("IÃŒÃÃŽÃĨĪĬĮÇỈ", toupper("iìÃîïĩīÄįÇỉ")) + call assert_equal("JĴǰ", toupper("jĵǰ")) + call assert_equal("KĶǨḰḴ", toupper("kķǩḱḵ")) + call assert_equal("LĹĻĽĿÅḺ", toupper("lĺļľŀłḻ")) + call assert_equal("MḾṀ ", toupper("mḿṠ")) + call assert_equal("NÑŃŅŇʼnṄṈ", toupper("nñńņňʼnṅṉ")) + call assert_equal("OÃ’Ã“Ã”Ã•Ã–Ã˜ÅŒÅŽÅÆ ǑǪǬỎ", toupper("oòóôõöøÅÅőơǒǫÇá»")) + call assert_equal("PṔṖ", toupper("pṕṗ")) + call assert_equal("Q", toupper("q")) + call assert_equal("RŔŖŘṘṞ", toupper("rŕŗřṙṟ")) + call assert_equal("SŚŜŞŠṠ", toupper("sÅ›Åşšṡ")) + call assert_equal("TŢŤŦṪṮẗ", toupper("tţťŧṫṯẗ")) + call assert_equal("UÙÚÛÜŨŪŬŮŰŲƯǓỦ", toupper("uùúûüũūÅůűųưǔủ")) + call assert_equal("Vá¹¼", toupper("vá¹½")) + call assert_equal("WŴẀẂẄẆẘ", toupper("wŵáºáºƒáº…ẇẘ")) + call assert_equal("ẊẌ", toupper("ẋáº")) + call assert_equal("YßŶẎẙỲỶỸ", toupper("yýÿŷáºáº™á»³á»·á»¹")) + call assert_equal("ZŹŻŽƵáºáº”", toupper("zźżžƶẑẕ")) + + " Test that uppercase diacritics, which should remain unchanged. + call assert_equal("AÀÃÂÃÄÅĀĂĄÇÇžÇ áº¢", toupper("AÀÃÂÃÄÅĀĂĄÇÇžÇ áº¢")) + call assert_equal("BḂḆ", toupper("BḂḆ")) + call assert_equal("CÇĆĈĊČ", toupper("CÇĆĈĊČ")) + call assert_equal("DÄŽÄḊḎá¸", toupper("DÄŽÄḊḎá¸")) + call assert_equal("EÈÉÊËĒĔĖĘĚẺẼ", toupper("EÈÉÊËĒĔĖĘĚẺẼ")) + call assert_equal("FḞ ", toupper("FḞ ")) + call assert_equal("GÄœÄžÄ Ä¢Ç¤Ç¦Ç´á¸ ", toupper("GÄœÄžÄ Ä¢Ç¤Ç¦Ç´á¸ ")) + call assert_equal("HĤĦḢḦḨ", toupper("HĤĦḢḦḨ")) + call assert_equal("IÃŒÃÃŽÃĨĪĬĮİÇỈ", toupper("IÃŒÃÃŽÃĨĪĬĮİÇỈ")) + call assert_equal("JÄ´", toupper("JÄ´")) + call assert_equal("KĶǨḰḴ", toupper("KĶǨḰḴ")) + call assert_equal("LĹĻĽĿÅḺ", toupper("LĹĻĽĿÅḺ")) + call assert_equal("MḾṀ", toupper("MḾṀ")) + call assert_equal("NÑŃŅŇṄṈ", toupper("NÑŃŅŇṄṈ")) + call assert_equal("OÃ’Ã“Ã”Ã•Ã–Ã˜ÅŒÅŽÅÆ ǑǪǬỎ", toupper("OÃ’Ã“Ã”Ã•Ã–Ã˜ÅŒÅŽÅÆ ǑǪǬỎ")) + call assert_equal("PṔṖ", toupper("PṔṖ")) + call assert_equal("Q", toupper("Q")) + call assert_equal("RŔŖŘṘṞ", toupper("RŔŖŘṘṞ")) + call assert_equal("SŚŜŞŠṠ", toupper("SŚŜŞŠṠ")) + call assert_equal("TŢŤŦṪṮ", toupper("TŢŤŦṪṮ")) + call assert_equal("UÙÚÛÜŨŪŬŮŰŲƯǓỦ", toupper("UÙÚÛÜŨŪŬŮŰŲƯǓỦ")) + call assert_equal("Vá¹¼", toupper("Vá¹¼")) + call assert_equal("WŴẀẂẄẆ", toupper("WŴẀẂẄẆ")) + call assert_equal("XẊẌ", toupper("XẊẌ")) + call assert_equal("YÃŶŸẎỲỶỸ", toupper("YÃŶŸẎỲỶỸ")) + call assert_equal("ZŹŻŽƵáºáº”", toupper("ZŹŻŽƵáºáº”")) + + call assert_equal("â±¥ ⱦ", tolower("Ⱥ Ⱦ")) +endfunc + + diff --git a/src/nvim/testdir/test_gf.vim b/src/nvim/testdir/test_gf.vim new file mode 100644 index 0000000000..c4aa6f9218 --- /dev/null +++ b/src/nvim/testdir/test_gf.vim @@ -0,0 +1,33 @@ + +" This is a test if a URL is recognized by "gf", with the cursor before and +" after the "://". Also test ":\\". +function! Test_gf_url() + enew! + call append(0, [ + \ "first test for URL://machine.name/tmp/vimtest2a and other text", + \ "second test for URL://machine.name/tmp/vimtest2b. And other text", + \ "third test for URL:\\\\machine.name\\vimtest2c and other text", + \ "fourth test for URL:\\\\machine.name\\tmp\\vimtest2d, and other text" + \ ]) + call cursor(1,1) + call search("^first") + call search("tmp") + call assert_equal("URL://machine.name/tmp/vimtest2a", expand("<cfile>")) + call search("^second") + call search("URL") + call assert_equal("URL://machine.name/tmp/vimtest2b", expand("<cfile>")) + if has("ebcdic") + set isf=@,240-249,/,.,-,_,+,,,$,:,~,\ + else + set isf=@,48-57,/,.,-,_,+,,,$,:,~,\ + endif + call search("^third") + call search("name") + call assert_equal("URL:\\\\machine.name\\vimtest2c", expand("<cfile>")) + call search("^fourth") + call search("URL") + call assert_equal("URL:\\\\machine.name\\tmp\\vimtest2d", expand("<cfile>")) + + set isf&vim + enew! +endfunction diff --git a/src/nvim/testdir/test_glob2regpat.vim b/src/nvim/testdir/test_glob2regpat.vim new file mode 100644 index 0000000000..fdf17946b6 --- /dev/null +++ b/src/nvim/testdir/test_glob2regpat.vim @@ -0,0 +1,30 @@ +" Test glob2regpat() + +func Test_invalid() + call assert_fails('call glob2regpat(1.33)', 'E806:') + call assert_fails('call glob2regpat("}")', 'E219:') + call assert_fails('call glob2regpat("{")', 'E220:') +endfunc + +func Test_valid() + call assert_equal('^foo\.', glob2regpat('foo.*')) + call assert_equal('^foo.$', glob2regpat('foo?')) + call assert_equal('\.vim$', glob2regpat('*.vim')) + call assert_equal('^[abc]$', glob2regpat('[abc]')) + call assert_equal('^foo bar$', glob2regpat('foo\ bar')) + call assert_equal('^foo,bar$', glob2regpat('foo,bar')) + call assert_equal('^\(foo\|bar\)$', glob2regpat('{foo,bar}')) + call assert_equal('.*', glob2regpat('**')) + + if exists('+shellslash') + call assert_equal('^foo[\/].$', glob2regpat('foo\?')) + call assert_equal('^\(foo[\/]\|bar\|foobar\)$', glob2regpat('{foo\,bar,foobar}')) + call assert_equal('^[\/]\(foo\|bar[\/]\)$', glob2regpat('\{foo,bar\}')) + call assert_equal('^[\/][\/]\(foo\|bar[\/][\/]\)$', glob2regpat('\\{foo,bar\\}')) + else + call assert_equal('^foo?$', glob2regpat('foo\?')) + call assert_equal('^\(foo,bar\|foobar\)$', glob2regpat('{foo\,bar,foobar}')) + call assert_equal('^{foo,bar}$', glob2regpat('\{foo,bar\}')) + call assert_equal('^\\\(foo\|bar\\\)$', glob2regpat('\\{foo,bar\\}')) + endif +endfunc diff --git a/src/nvim/testdir/test_gn.vim b/src/nvim/testdir/test_gn.vim index 3eca99bd99..7a5cdabaa3 100644 --- a/src/nvim/testdir/test_gn.vim +++ b/src/nvim/testdir/test_gn.vim @@ -90,4 +90,4 @@ func Test_gn_command() sil! %d _ endfu -" vim: tabstop=2 shiftwidth=0 expandtab +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_goto.vim b/src/nvim/testdir/test_goto.vim index 2afd96b296..2573401707 100644 --- a/src/nvim/testdir/test_goto.vim +++ b/src/nvim/testdir/test_goto.vim @@ -1,20 +1,290 @@ " Test commands that jump somewhere. -func Test_geeDEE() +" Create a new buffer using "lines" and place the cursor on the word after the +" first occurrence of return and invoke "cmd". The cursor should now be +" positioned at the given line and col. +func XTest_goto_decl(cmd, lines, line, col) new - call setline(1, ["Filename x;", "", "int Filename", "int func() {", "Filename y;"]) - /y;/ - normal gD - call assert_equal(1, line('.')) + call setline(1, a:lines) + /return/ + normal! W + execute 'norm! ' . a:cmd + call assert_equal(a:line, line('.')) + call assert_equal(a:col, col('.')) quit! endfunc -func Test_gee_dee() +func Test_gD() + let lines = [ + \ 'int x;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 1, 5) +endfunc + +func Test_gD_too() + let lines = [ + \ 'Filename x;', + \ '', + \ 'int Filename', + \ 'int func() {', + \ ' Filename x;', + \ ' return x;', + \ ] + call XTest_goto_decl('gD', lines, 1, 10) +endfunc + +func Test_gD_comment() + let lines = [ + \ '/* int x; */', + \ 'int x;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 2, 5) +endfunc + +func Test_gD_inline_comment() + let lines = [ + \ 'int y /* , x */;', + \ 'int x;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 2, 5) +endfunc + +func Test_gD_string() + let lines = [ + \ 'char *s[] = "x";', + \ 'int x = 1;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 2, 5) +endfunc + +func Test_gD_string_same_line() + let lines = [ + \ 'char *s[] = "x", int x = 1;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 1, 22) +endfunc + +func Test_gD_char() + let lines = [ + \ "char c = 'x';", + \ 'int x = 1;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 2, 5) +endfunc + +func Test_gd() + let lines = [ + \ 'int x;', + \ '', + \ 'int func(int x)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 3, 14) +endfunc + +func Test_gd_not_local() + let lines = [ + \ 'int func1(void)', + \ '{', + \ ' return x;', + \ '}', + \ '', + \ 'int func2(int x)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 3, 10) +endfunc + +func Test_gd_kr_style() + let lines = [ + \ 'int func(x)', + \ ' int x;', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 2, 7) +endfunc + +func Test_gd_missing_braces() + let lines = [ + \ 'def func1(a)', + \ ' a + 1', + \ 'end', + \ '', + \ 'a = 1', + \ '', + \ 'def func2()', + \ ' return a', + \ 'end', + \ ] + call XTest_goto_decl('gd', lines, 1, 11) +endfunc + +func Test_gd_comment() + let lines = [ + \ 'int func(void)', + \ '{', + \ ' /* int x; */', + \ ' int x;', + \ ' return x;', + \ '}', + \] + call XTest_goto_decl('gd', lines, 4, 7) +endfunc + +func Test_gd_comment_in_string() + let lines = [ + \ 'int func(void)', + \ '{', + \ ' char *s ="//"; int x;', + \ ' int x;', + \ ' return x;', + \ '}', + \] + call XTest_goto_decl('gd', lines, 3, 22) +endfunc + +func Test_gd_string_in_comment() + set comments= + let lines = [ + \ 'int func(void)', + \ '{', + \ ' /* " */ int x;', + \ ' int x;', + \ ' return x;', + \ '}', + \] + call XTest_goto_decl('gd', lines, 3, 15) + set comments& +endfunc + +func Test_gd_inline_comment() + let lines = [ + \ 'int func(/* x is an int */ int x)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 1, 32) +endfunc + +func Test_gd_inline_comment_only() + let lines = [ + \ 'int func(void) /* one lonely x */', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 3, 10) +endfunc + +func Test_gd_inline_comment_body() + let lines = [ + \ 'int func(void)', + \ '{', + \ ' int y /* , x */;', + \ '', + \ ' for (/* int x = 0 */; y < 2; y++);', + \ '', + \ ' int x = 0;', + \ '', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 7, 7) +endfunc + +func Test_gd_trailing_multiline_comment() + let lines = [ + \ 'int func(int x) /* x is an int */', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 1, 14) +endfunc + +func Test_gd_trailing_comment() + let lines = [ + \ 'int func(int x) // x is an int', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 1, 14) +endfunc + +func Test_gd_string() + let lines = [ + \ 'int func(void)', + \ '{', + \ ' char *s = "x";', + \ ' int x = 1;', + \ '', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 4, 7) +endfunc + +func Test_gd_string_only() + let lines = [ + \ 'int func(void)', + \ '{', + \ ' char *s = "x";', + \ '', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 5, 10) +endfunc + +" Check that setting 'cursorline' does not change curswant +func Test_cursorline_keep_col() new - call setline(1, ["int x;", "", "int func(int x)", "{", " return x;", "}"]) - /return/ - normal $hgd - call assert_equal(3, line('.')) - call assert_equal(14, col('.')) - quit! + call setline(1, ['long long long line', 'short line']) + normal ggfi + let pos = getcurpos() + normal j + set cursorline + normal k + call assert_equal(pos, getcurpos()) + bwipe! + set nocursorline endfunc + diff --git a/src/nvim/testdir/test_help.vim b/src/nvim/testdir/test_help.vim new file mode 100644 index 0000000000..26edc16107 --- /dev/null +++ b/src/nvim/testdir/test_help.vim @@ -0,0 +1,16 @@ + +" Tests for :help + +func Test_help_restore_snapshot() + help + set buftype= + help + edit x + help + helpclose +endfunc + +func Test_help_errors() + call assert_fails('help doesnotexist', 'E149:') + call assert_fails('help!', 'E478:') +endfunc diff --git a/src/nvim/testdir/test_help_tagjump.vim b/src/nvim/testdir/test_help_tagjump.vim index cc1c81c7f6..1ca0f722cf 100644 --- a/src/nvim/testdir/test_help_tagjump.vim +++ b/src/nvim/testdir/test_help_tagjump.vim @@ -162,4 +162,36 @@ func Test_help_complete() endtry endfunc -" vim: et sw=2: +func Test_help_respect_current_file_lang() + try + let list = [] + call s:doc_config_setup() + + if has('multi_lang') + function s:check_help_file_ext(help_keyword, ext) + exec 'help ' . a:help_keyword + call assert_equal(a:ext, expand('%:e')) + call feedkeys("\<C-]>", 'tx') + call assert_equal(a:ext, expand('%:e')) + pop + helpclose + endfunc + + set rtp+=Xdir1/doc-ab + set rtp+=Xdir1/doc-ja + + set helplang=ab + call s:check_help_file_ext('test-char', 'abx') + call s:check_help_file_ext('test-char@ja', 'jax') + set helplang=ab,ja + call s:check_help_file_ext('test-char@ja', 'jax') + call s:check_help_file_ext('test-char@en', 'txt') + endif + catch + call assert_exception('X') + finally + call s:doc_config_teardown() + endtry +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_hide.vim b/src/nvim/testdir/test_hide.vim new file mode 100644 index 0000000000..128b8ff945 --- /dev/null +++ b/src/nvim/testdir/test_hide.vim @@ -0,0 +1,97 @@ +" Tests for :hide command/modifier and 'hidden' option + +function SetUp() + let s:save_hidden = &hidden + let s:save_bufhidden = &bufhidden + let s:save_autowrite = &autowrite + set nohidden + set bufhidden= + set noautowrite +endfunc + +function TearDown() + let &hidden = s:save_hidden + let &bufhidden = s:save_bufhidden + let &autowrite = s:save_autowrite +endfunc + +function Test_hide() + let orig_bname = bufname('') + let orig_winnr = winnr('$') + + new Xf1 + set modified + call assert_fails('edit Xf2') + bwipeout! Xf1 + + new Xf1 + set modified + edit! Xf2 + call assert_equal(['Xf2', 2], [bufname(''), winnr('$')]) + call assert_equal([1, 0], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + bwipeout! Xf2 + + new Xf1 + set modified + " :hide as a command + hide + call assert_equal([orig_bname, orig_winnr], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + + new Xf1 + set modified + " :hide as a command with trailing comment + hide " comment + call assert_equal([orig_bname, orig_winnr], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + + new Xf1 + set modified + " :hide as a command with bar + hide | new Xf2 " comment + call assert_equal(['Xf2', 2], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + bwipeout! Xf2 + + new Xf1 + set modified + " :hide as a modifier with trailing comment + hide edit Xf2 " comment + call assert_equal(['Xf2', 2], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + bwipeout! Xf2 + + new Xf1 + set modified + " To check that the bar is not recognized to separate commands + hide echo "one|two" + call assert_equal(['Xf1', 2], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + + " set hidden + new Xf1 + set hidden + set modified + edit Xf2 " comment + call assert_equal(['Xf2', 2], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + bwipeout! Xf2 + + " set hidden bufhidden=wipe + new Xf1 + set bufhidden=wipe + set modified + hide edit! Xf2 " comment + call assert_equal(['Xf2', 2], [bufname(''), winnr('$')]) + call assert_equal([0, 0], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf2 +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_history.vim b/src/nvim/testdir/test_history.vim index ee6acfffc3..ca31e3f06c 100644 --- a/src/nvim/testdir/test_history.vim +++ b/src/nvim/testdir/test_history.vim @@ -31,6 +31,30 @@ function History_Tests(hist) call assert_equal('ls', histget(a:hist, -1)) call assert_equal(4, histnr(a:hist)) + let a=execute('history ' . a:hist) + call assert_match("^\n # \\S* history\n 3 buffers\n> 4 ls$", a) + let a=execute('history all') + call assert_match("^\n # .* history\n 3 buffers\n> 4 ls", a) + + if len(a:hist) > 0 + let a=execute('history ' . a:hist . ' 2') + call assert_match("^\n # \\S* history$", a) + let a=execute('history ' . a:hist . ' 3') + call assert_match("^\n # \\S* history\n 3 buffers$", a) + let a=execute('history ' . a:hist . ' 4') + call assert_match("^\n # \\S* history\n> 4 ls$", a) + let a=execute('history ' . a:hist . ' 3,4') + call assert_match("^\n # \\S* history\n 3 buffers\n> 4 ls$", a) + let a=execute('history ' . a:hist . ' -1') + call assert_match("^\n # \\S* history\n> 4 ls$", a) + let a=execute('history ' . a:hist . ' -2') + call assert_match("^\n # \\S* history\n 3 buffers$", a) + let a=execute('history ' . a:hist . ' -2,') + call assert_match("^\n # \\S* history\n 3 buffers\n> 4 ls$", a) + let a=execute('history ' . a:hist . ' -3') + call assert_match("^\n # \\S* history$", a) + endif + " Test for removing entries matching a pattern for i in range(1, 3) call histadd(a:hist, 'text_' . i) @@ -63,3 +87,20 @@ function Test_History() call assert_equal(-1, histnr('abc')) call assert_fails('call histnr([])', 'E730:') endfunction + +function Test_Search_history_window() + new + call setline(1, ['a', 'b', 'a', 'b']) + 1 + call feedkeys("/a\<CR>", 'xt') + call assert_equal('a', getline('.')) + 1 + call feedkeys("/b\<CR>", 'xt') + call assert_equal('b', getline('.')) + 1 + " select the previous /a command + call feedkeys("q/kk\<CR>", 'x!') + call assert_equal('a', getline('.')) + call assert_equal('a', @/) + bwipe! +endfunc diff --git a/src/nvim/testdir/test_hlsearch.vim b/src/nvim/testdir/test_hlsearch.vim new file mode 100644 index 0000000000..066fdd0250 --- /dev/null +++ b/src/nvim/testdir/test_hlsearch.vim @@ -0,0 +1,34 @@ +" Test for v:hlsearch + +function! Test_hlsearch() + new + call setline(1, repeat(['aaa'], 10)) + set hlsearch nolazyredraw + let r=[] + " redraw is needed to make hlsearch highlight the matches + exe "normal! /aaa\<CR>" | redraw + let r1 = screenattr(1, 1) + nohlsearch | redraw + call assert_notequal(r1, screenattr(1,1)) + let v:hlsearch=1 | redraw + call assert_equal(r1, screenattr(1,1)) + let v:hlsearch=0 | redraw + call assert_notequal(r1, screenattr(1,1)) + set hlsearch | redraw + call assert_equal(r1, screenattr(1,1)) + let v:hlsearch=0 | redraw + call assert_notequal(r1, screenattr(1,1)) + exe "normal! n" | redraw + call assert_equal(r1, screenattr(1,1)) + let v:hlsearch=0 | redraw + call assert_notequal(r1, screenattr(1,1)) + exe "normal! /\<CR>" | redraw + call assert_equal(r1, screenattr(1,1)) + set nohls + exe "normal! /\<CR>" | redraw + call assert_notequal(r1, screenattr(1,1)) + call assert_fails('let v:hlsearch=[]', 'E745') + call garbagecollect(1) + call getchar(1) + enew! +endfunction diff --git a/src/nvim/testdir/test_increment.vim b/src/nvim/testdir/test_increment.vim new file mode 100644 index 0000000000..8bfd95d810 --- /dev/null +++ b/src/nvim/testdir/test_increment.vim @@ -0,0 +1,760 @@ +" Tests for using Ctrl-A/Ctrl-X on visual selections + +func SetUp() + new dummy + set nrformats&vim +endfunc + +func TearDown() + bwipe! +endfunc + +" 1) Ctrl-A on visually selected number +" Text: +" foobar-10 +" Expected: +" 1) Ctrl-A on start of line: +" foobar-9 +" 2) Ctrl-A on visually selected "-10": +" foobar-9 +" 3) Ctrl-A on visually selected "10": +" foobar-11 +" 4) Ctrl-X on visually selected "-10" +" foobar-11 +" 5) Ctrl-X on visually selected "10" +" foobar-9 +func Test_visual_increment_01() + call setline(1, repeat(["foobaar-10"], 5)) + + call cursor(1, 1) + exec "norm! \<C-A>" + call assert_equal("foobaar-9", getline('.')) + call assert_equal([0, 1, 9, 0], getpos('.')) + + call cursor(2, 1) + exec "norm! f-v$\<C-A>" + call assert_equal("foobaar-9", getline('.')) + call assert_equal([0, 2, 8, 0], getpos('.')) + + call cursor(3, 1) + exec "norm! f1v$\<C-A>" + call assert_equal("foobaar-11", getline('.')) + call assert_equal([0, 3, 9, 0], getpos('.')) + + call cursor(4, 1) + exec "norm! f-v$\<C-X>" + call assert_equal("foobaar-11", getline('.')) + call assert_equal([0, 4, 8, 0], getpos('.')) + + call cursor(5, 1) + exec "norm! f1v$\<C-X>" + call assert_equal("foobaar-9", getline('.')) + call assert_equal([0, 5, 9, 0], getpos('.')) +endfunc + +" 2) Ctrl-A on visually selected lines +" Text: +" 10 +" 20 +" 30 +" 40 +" +" Expected: +" 1) Ctrl-A on visually selected lines: +" 11 +" 21 +" 31 +" 41 +" +" 2) Ctrl-X on visually selected lines: +" 9 +" 19 +" 29 +" 39 +func Test_visual_increment_02() + call setline(1, ["10", "20", "30", "40"]) + exec "norm! GV3k$\<C-A>" + call assert_equal(["11", "21", "31", "41"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, ["10", "20", "30", "40"]) + exec "norm! GV3k$\<C-X>" + call assert_equal(["9", "19", "29", "39"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 3) g Ctrl-A on visually selected lines, with non-numbers in between +" Text: +" 10 +" +" 20 +" +" 30 +" +" 40 +" +" Expected: +" 1) 2 g Ctrl-A on visually selected lines: +" 12 +" +" 24 +" +" 36 +" +" 48 +" 2) 2 g Ctrl-X on visually selected lines +" 8 +" +" 16 +" +" 24 +" +" 32 +func Test_visual_increment_03() + call setline(1, ["10", "", "20", "", "30", "", "40"]) + exec "norm! GV6k2g\<C-A>" + call assert_equal(["12", "", "24", "", "36", "", "48"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, ["10", "", "20", "", "30", "", "40"]) + exec "norm! GV6k2g\<C-X>" + call assert_equal(["8", "", "16", "", "24", "", "32"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 4) Ctrl-A on non-number +" Text: +" foobar-10 +" Expected: +" 1) visually select foobar: +" foobar-10 +func Test_visual_increment_04() + call setline(1, ["foobar-10"]) + exec "norm! vf-\<C-A>" + call assert_equal(["foobar-10"], getline(1, '$')) + " NOTE: I think this is correct behavior... + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 5) g<Ctrl-A> on letter +" Test: +" a +" a +" a +" a +" Expected: +" 1) g Ctrl-A on visually selected lines +" b +" c +" d +" e +func Test_visual_increment_05() + set nrformats+=alpha + call setline(1, repeat(["a"], 4)) + exec "norm! GV3kg\<C-A>" + call assert_equal(["b", "c", "d", "e"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 6) g<Ctrl-A> on letter +" Test: +" z +" z +" z +" z +" Expected: +" 1) g Ctrl-X on visually selected lines +" y +" x +" w +" v +func Test_visual_increment_06() + set nrformats+=alpha + call setline(1, repeat(["z"], 4)) + exec "norm! GV3kg\<C-X>" + call assert_equal(["y", "x", "w", "v"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 7) <Ctrl-A> on letter +" Test: +" 2 +" 1 +" 0 +" -1 +" -2 +" +" Expected: +" 1) Ctrl-A on visually selected lines +" 3 +" 2 +" 1 +" 0 +" -1 +" +" 2) Ctrl-X on visually selected lines +" 1 +" 0 +" -1 +" -2 +" -3 +func Test_visual_increment_07() + call setline(1, ["2", "1", "0", "-1", "-2"]) + exec "norm! GV4k\<C-A>" + call assert_equal(["3", "2", "1", "0", "-1"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, ["2", "1", "0", "-1", "-2"]) + exec "norm! GV4k\<C-X>" + call assert_equal(["1", "0", "-1", "-2", "-3"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 8) Block increment on 0x9 +" Text: +" 0x9 +" 0x9 +" Expected: +" 1) Ctrl-A on visually block selected region (cursor at beginning): +" 0xa +" 0xa +" 2) Ctrl-A on visually block selected region (cursor at end) +" 0xa +" 0xa +func Test_visual_increment_08() + call setline(1, repeat(["0x9"], 2)) + exec "norm! \<C-V>j$\<C-A>" + call assert_equal(["0xa", "0xa"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, repeat(["0x9"], 2)) + exec "norm! gg$\<C-V>+\<C-A>" + call assert_equal(["0xa", "0xa"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 9) Increment and redo +" Text: +" 2 +" 2 +" +" 3 +" 3 +" +" Expected: +" 1) 2 Ctrl-A on first 2 visually selected lines +" 4 +" 4 +" 2) redo (.) on 3 +" 5 +" 5 +func Test_visual_increment_09() + call setline(1, ["2", "2", "", "3", "3", ""]) + exec "norm! ggVj2\<C-A>" + call assert_equal(["4", "4", "", "3", "3", ""], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + exec "norm! 3j." + call assert_equal(["4", "4", "", "5", "5", ""], getline(1, '$')) + call assert_equal([0, 4, 1, 0], getpos('.')) +endfunc + +" 10) sequentially decrement 1 +" Text: +" 1 +" 1 +" 1 +" 1 +" Expected: +" 1) g Ctrl-X on visually selected lines +" 0 +" -1 +" -2 +" -3 +func Test_visual_increment_10() + call setline(1, repeat(["1"], 4)) + exec "norm! GV3kg\<C-X>" + call assert_equal(["0", "-1", "-2", "-3"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 11) visually block selected indented lines +" Text: +" 1 +" 1 +" 1 +" 1 +" Expexted: +" 1) g Ctrl-A on block selected indented lines +" 2 +" 1 +" 3 +" 4 +func Test_visual_increment_11() + call setline(1, [" 1", "1", " 1", " 1"]) + exec "norm! f1\<C-V>3jg\<C-A>" + call assert_equal([" 2", "1", " 3", " 4"], getline(1, '$')) + call assert_equal([0, 1, 5, 0], getpos('.')) +endfunc + +" 12) visually selected several columns +" Text: +" 0 0 +" 0 0 +" 0 0 +" Expected: +" 1) 'v' select last zero and first zeroes +" 0 1 +" 1 0 +" 1 0 +func Test_visual_increment_12() + call setline(1, repeat(["0 0"], 3)) + exec "norm! $v++\<C-A>" + call assert_equal(["0 1", "1 0", "1 0"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) +endfunc + +" 13) visually selected part of columns +" Text: +" max: 100px +" max: 200px +" max: 300px +" max: 400px +" Expected: +" 1) 'v' on first two numbers Ctrl-A +" max: 110px +" max: 220px +" max: 330px +" max: 400px +" 2) 'v' on first two numbers Ctrl-X +" max: 90px +" max: 190px +" max: 290px +" max: 400px +func Test_visual_increment_13() + call setline(1, ["max: 100px", "max: 200px", "max: 300px", "max: 400px"]) + exec "norm! f1\<C-V>l2j\<C-A>" + call assert_equal(["max: 110px", "max: 210px", "max: 310px", "max: 400px"], getline(1, '$')) + call assert_equal([0, 1, 6, 0], getpos('.')) + + call setline(1, ["max: 100px", "max: 200px", "max: 300px", "max: 400px"]) + exec "norm! ggf1\<C-V>l2j\<C-X>" + call assert_equal(["max: 90px", "max: 190px", "max: 290px", "max: 400px"], getline(1, '$')) + call assert_equal([0, 1, 6, 0], getpos('.')) +endfunc + +" 14) redo in block mode +" Text: +" 1 1 +" 1 1 +" Expected: +" 1) Ctrl-a on first column, redo on second column +" 2 2 +" 2 2 +func Test_visual_increment_14() + call setline(1, repeat(["1 1"], 2)) + exec "norm! G\<C-V>k\<C-A>w." + call assert_equal(["2 2", "2 2"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) +endfunc + +" 15) block select single numbers +" Text: +" 101 +" Expected: +" 1) Ctrl-a on visually selected zero +" 111 +func Test_visual_increment_15() + call setline(1, ["101"]) + exec "norm! lv\<C-A>" + call assert_equal(["111"], getline(1, '$')) + call assert_equal([0, 1, 2, 0], getpos('.')) +endfunc + +" 16) increment right aligned numbers +" Text: +" 1 +" 19 +" 119 +" Expected: +" 1) Ctrl-a on line selected region +" 2 +" 20 +" 120 +func Test_visual_increment_16() + call setline(1, [" 1", " 19", " 119"]) + exec "norm! VG\<C-A>" + call assert_equal([" 2", " 20", " 120"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 17) block-wise increment and redo +" Text: +" 100 +" 1 +" +" 100 +" 1 +" +" Expected: +" 1) Ctrl-V j $ on first block, afterwards '.' on second +" 101 +" 2 +" +" 101 +" 2 +func Test_visual_increment_17() + call setline(1, [" 100", " 1", "", " 100", " 1"]) + exec "norm! \<C-V>j$\<C-A>2j." + call assert_equal([" 101", " 2", "", " 101", " 1"], getline(1, '$')) + call assert_equal([0, 3, 1, 0], getpos('.')) +endfunc + +" 18) repeat of g<Ctrl-a> +" Text: +" 0 +" 0 +" 0 +" 0 +" +" Expected: +" 1) V 4j g<ctrl-a>, repeat twice afterwards with . +" 3 +" 6 +" 9 +" 12 +func Test_visual_increment_18() + call setline(1, repeat(["0"], 4)) + exec "norm! GV3kg\<C-A>" + exec "norm! .." + call assert_equal(["3", "6", "9", "12"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 19) increment on number with nrformat including alpha +" Text: +" 1 +" 1a +" +" Expected: +" 1) <Ctrl-V>j$ <ctrl-a> +" 2 +" 2a +func Test_visual_increment_19() + set nrformats+=alpha + call setline(1, ["1", "1a"]) + exec "norm! \<C-V>G$\<C-A>" + call assert_equal(["2", "2a"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 20) increment a single letter +" Text: +" a +" +" Expected: +" 1) <Ctrl-a> and cursor is on a +" b +func Test_visual_increment_20() + set nrformats+=alpha + call setline(1, ["a"]) + exec "norm! \<C-A>" + call assert_equal(["b"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 21) block-wise increment on part of hexadecimal +" Text: +" 0x123456 +" +" Expected: +" 1) Ctrl-V f3 <ctrl-a> +" 0x124456 +func Test_visual_increment_21() + call setline(1, ["0x123456"]) + exec "norm! \<C-V>f3\<C-A>" + call assert_equal(["0x124456"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 22) Block increment on 0b0 +" Text: +" 0b1 +" 0b1 +" Expected: +" 1) Ctrl-A on visually block selected region (cursor at beginning): +" 0b10 +" 0b10 +" 2) Ctrl-A on visually block selected region (cursor at end) +" 0b10 +" 0b10 +func Test_visual_increment_22() + call setline(1, repeat(["0b1"], 2)) + exec "norm! \<C-V>j$\<C-A>" + call assert_equal(repeat(["0b10"], 2), getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, repeat(["0b1"], 2)) + exec "norm! $\<C-V>+\<C-A>" + call assert_equal(repeat(["0b10"], 2), getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 23) block-wise increment on part of binary +" Text: +" 0b1001 +" +" Expected: +" 1) Ctrl-V 5l <ctrl-a> +" 0b1011 +func Test_visual_increment_23() + call setline(1, ["0b1001"]) + exec "norm! \<C-V>4l\<C-A>" + call assert_equal(["0b1011"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 24) increment hexadecimal +" Text: +" 0x0b1001 +" +" Expected: +" 1) <ctrl-a> +" 0x0b1002 +func Test_visual_increment_24() + call setline(1, ["0x0b1001"]) + exec "norm! \<C-V>$\<C-A>" + call assert_equal(["0x0b1002"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 25) increment binary with nrformats including alpha +" Text: +" 0b1001a +" +" Expected: +" 1) <ctrl-a> +" 0b1010a +func Test_visual_increment_25() + set nrformats+=alpha + call setline(1, ["0b1001a"]) + exec "norm! \<C-V>$\<C-A>" + call assert_equal(["0b1010a"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 26) increment binary with 32 bits +" Text: +" 0b11111111111111111111111111111110 +" +" Expected: +" 1) <ctrl-a> +" 0b11111111111111111111111111111111 +func Test_visual_increment_26() + set nrformats+=alpha + call setline(1, ["0b11111111111111111111111111111110"]) + exec "norm! \<C-V>$\<C-A>" + call assert_equal(["0b11111111111111111111111111111111"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + set nrformats-=alpha +endfunc + +" 27) increment with 'rightreft', if supported +func Test_visual_increment_27() + if exists('+rightleft') + set rightleft + call setline(1, ["1234 56"]) + + exec "norm! $\<C-A>" + call assert_equal(["1234 57"], getline(1, '$')) + call assert_equal([0, 1, 7, 0], getpos('.')) + + exec "norm! \<C-A>" + call assert_equal(["1234 58"], getline(1, '$')) + call assert_equal([0, 1, 7, 0], getpos('.')) + set norightleft + endif +endfunc + +" Tab code and linewise-visual inc/dec +func Test_visual_increment_28() + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! Vj\<C-A>" + call assert_equal(["x\<TAB>11", "\<TAB>0"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! ggVj\<C-X>" + call assert_equal(["x\<TAB>9", "\<TAB>-2"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" Tab code and linewise-visual inc/dec with 'nrformats'+=alpha +func Test_visual_increment_29() + set nrformats+=alpha + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! Vj\<C-A>" + call assert_equal(["y\<TAB>10", "\<TAB>0"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! ggVj\<C-X>" + call assert_equal(["w\<TAB>10", "\<TAB>-2"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" Tab code and character-visual inc/dec +func Test_visual_increment_30() + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! f1vjf1\<C-A>" + call assert_equal(["x\<TAB>11", "\<TAB>0"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) + + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! ggf1vjf1\<C-X>" + call assert_equal(["x\<TAB>9", "\<TAB>-2"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) +endfunc + +" Tab code and blockwise-visual inc/dec +func Test_visual_increment_31() + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! f1\<C-V>jl\<C-A>" + call assert_equal(["x\<TAB>11", "\<TAB>0"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) + + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! ggf1\<C-V>jl\<C-X>" + call assert_equal(["x\<TAB>9", "\<TAB>-2"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) +endfunc + +" Tab code and blockwise-visual decrement with 'linebreak' and 'showbreak' +func Test_visual_increment_32() + 28vnew dummy_31 + set linebreak showbreak=+ + call setline(1, ["x\<TAB>\<TAB>\<TAB>10", "\<TAB>\<TAB>\<TAB>\<TAB>-1"]) + exec "norm! ggf0\<C-V>jg_\<C-X>" + call assert_equal(["x\<TAB>\<TAB>\<TAB>1-1", "\<TAB>\<TAB>\<TAB>\<TAB>-2"], getline(1, '$')) + call assert_equal([0, 1, 6, 0], getpos('.')) + bwipe! +endfunc + +" Tab code and blockwise-visual increment with $ +func Test_visual_increment_33() + call setline(1, ["\<TAB>123", "456"]) + exec "norm! gg0\<C-V>j$\<C-A>" + call assert_equal(["\<TAB>124", "457"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" Tab code and blockwise-visual increment and redo +func Test_visual_increment_34() + call setline(1, ["\<TAB>123", " 456789"]) + exec "norm! gg0\<C-V>j\<C-A>" + call assert_equal(["\<TAB>123", " 457789"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + exec "norm! .." + call assert_equal(["\<TAB>123", " 459789"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" Tab code, spaces and character-visual increment and redo +func Test_visual_increment_35() + call setline(1, ["\<TAB>123", " 123", "\<TAB>123", "\<TAB>123"]) + exec "norm! ggvjf3\<C-A>..." + call assert_equal(["\<TAB>127", " 127", "\<TAB>123", "\<TAB>123"], getline(1, '$')) + call assert_equal([0, 1, 2, 0], getpos('.')) +endfunc + +" Tab code, spaces and blockwise-visual increment and redo +func Test_visual_increment_36() + call setline(1, [" 123", "\<TAB>456789"]) + exec "norm! G0\<C-V>kl\<C-A>" + call assert_equal([" 123", "\<TAB>556789"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + exec "norm! ..." + call assert_equal([" 123", "\<TAB>856789"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" block-wise increment and dot-repeat +" Text: +" 1 23 +" 4 56 +" +" Expected: +" 1) f2 Ctrl-V jl <ctrl-a>, repeat twice afterwards with . +" 1 26 +" 4 59 +" +" Try with and without indent. +func Test_visual_increment_37() + call setline(1, [" 1 23", " 4 56"]) + exec "norm! ggf2\<C-V>jl\<C-A>.." + call assert_equal([" 1 26", " 4 59"], getline(1, 2)) + + call setline(1, ["1 23", "4 56"]) + exec "norm! ggf2\<C-V>jl\<C-A>.." + call assert_equal(["1 26", "4 59"], getline(1, 2)) +endfunc + +" Check redo after the normal mode increment +func Test_visual_increment_38() + exec "norm! i10\<ESC>5\<C-A>." + call assert_equal(["20"], getline(1, '$')) + call assert_equal([0, 1, 2, 0], getpos('.')) +endfunc + +" Test what patch 7.3.414 fixed. Ctrl-A on "000" drops the leading zeros. +func Test_normal_increment_01() + call setline(1, "000") + exec "norm! gg0\<C-A>" + call assert_equal("001", getline(1)) + + call setline(1, "000") + exec "norm! gg$\<C-A>" + call assert_equal("001", getline(1)) + + call setline(1, "001") + exec "norm! gg0\<C-A>" + call assert_equal("002", getline(1)) + + call setline(1, "001") + exec "norm! gg$\<C-A>" + call assert_equal("002", getline(1)) +endfunc + +" Test a regression of patch 7.4.1087 fixed. +func Test_normal_increment_02() + call setline(1, ["hello 10", "world"]) + exec "norm! ggl\<C-A>jx" + call assert_equal(["hello 11", "worl"], getline(1, '$')) + call assert_equal([0, 2, 4, 0], getpos('.')) +endfunc + +" The test35 unified to this file. +func Test_normal_increment_03() + call setline(1, ["100 0x100 077 0", + \ "100 0x100 077 ", + \ "100 0x100 077 0xfF 0xFf", + \ "100 0x100 077 "]) + set nrformats=octal,hex + exec "norm! gg\<C-A>102\<C-X>\<C-A>l\<C-X>l\<C-A>64\<C-A>128\<C-X>$\<C-X>" + set nrformats=octal + exec "norm! j0\<C-A>102\<C-X>\<C-A>l\<C-X>2\<C-A>w65\<C-A>129\<C-X>blx6lD" + set nrformats=hex + exec "norm! j0101\<C-X>l257\<C-X>\<C-A>Txldt \<C-A> \<C-X> \<C-X>" + set nrformats= + exec "norm! j0200\<C-X>l100\<C-X>w78\<C-X>\<C-A>k" + call assert_equal(["0 0x0ff 0000 -1", + \ "0 1x100 0777777", + \ "-1 0x0 078 0xFE 0xfe", + \ "-100 -100x100 000 "], getline(1, '$')) + call assert_equal([0, 3, 25, 0], getpos('.')) +endfunc + + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_increment_dbcs.vim b/src/nvim/testdir/test_increment_dbcs.vim new file mode 100644 index 0000000000..474a16feeb --- /dev/null +++ b/src/nvim/testdir/test_increment_dbcs.vim @@ -0,0 +1,29 @@ +" Tests for using Ctrl-A/Ctrl-X using DBCS. +if !has('multi_byte') + finish +endif +scriptencoding cp932 + +func SetUp() + new + set nrformats& +endfunc + +func TearDown() + bwipe! +endfunc + +func Test_increment_dbcs_1() + set nrformats+=alpha + call setline(1, ["ŽR1"]) + exec "norm! 0\<C-A>" + call assert_equal(["ŽR2"], getline(1, '$')) + call assert_equal([0, 1, 4, 0], getpos('.')) + + call setline(1, ["‚`‚a‚b0xDE‚e"]) + exec "norm! 0\<C-X>" + call assert_equal(["‚`‚a‚b0xDD‚e"], getline(1, '$')) + call assert_equal([0, 1, 13, 0], getpos('.')) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_lambda.vim b/src/nvim/testdir/test_lambda.vim new file mode 100644 index 0000000000..311cc6e2cb --- /dev/null +++ b/src/nvim/testdir/test_lambda.vim @@ -0,0 +1,287 @@ +" Test for lambda and closure + +function! Test_lambda_feature() + call assert_equal(1, has('lambda')) +endfunction + +function! Test_lambda_with_filter() + let s:x = 2 + call assert_equal([2, 3], filter([1, 2, 3], {i, v -> v >= s:x})) +endfunction + +function! Test_lambda_with_map() + let s:x = 1 + call assert_equal([2, 3, 4], map([1, 2, 3], {i, v -> v + s:x})) +endfunction + +function! Test_lambda_with_sort() + call assert_equal([1, 2, 3, 4, 7], sort([3,7,2,1,4], {a, b -> a - b})) +endfunction + +function! Test_lambda_with_timer() + if !has('timers') + return + endif + + let s:n = 0 + let s:timer_id = 0 + function! s:Foo() + "let n = 0 + let s:timer_id = timer_start(50, {-> execute("let s:n += 1 | echo s:n", "")}, {"repeat": -1}) + endfunction + + call s:Foo() + sleep 200ms + " do not collect lambda + call garbagecollect() + let m = s:n + sleep 200ms + call timer_stop(s:timer_id) + call assert_true(m > 1) + call assert_true(s:n > m + 1) + call assert_true(s:n < 9) +endfunction + +function! Test_lambda_with_partial() + let l:Cb = function({... -> ['zero', a:1, a:2, a:3]}, ['one', 'two']) + call assert_equal(['zero', 'one', 'two', 'three'], l:Cb('three')) +endfunction + +function Test_lambda_fails() + call assert_equal(3, {a, b -> a + b}(1, 2)) + call assert_fails('echo {a, a -> a + a}(1, 2)', 'E15:') + call assert_fails('echo {a, b -> a + b)}(1, 2)', 'E15:') +endfunc + +func Test_not_lambda() + let x = {'>' : 'foo'} + call assert_equal('foo', x['>']) +endfunc + +function! Test_lambda_capture_by_reference() + let v = 1 + let l:F = {x -> x + v} + let v = 2 + call assert_equal(12, l:F(10)) +endfunction + +function! Test_lambda_side_effect() + function! s:update_and_return(arr) + let a:arr[1] = 5 + return a:arr + endfunction + + function! s:foo(arr) + return {-> s:update_and_return(a:arr)} + endfunction + + let arr = [3,2,1] + call assert_equal([3, 5, 1], s:foo(arr)()) +endfunction + +function! Test_lambda_refer_local_variable_from_other_scope() + function! s:foo(X) + return a:X() " refer l:x in s:bar() + endfunction + + function! s:bar() + let x = 123 + return s:foo({-> x}) + endfunction + + call assert_equal(123, s:bar()) +endfunction + +function! Test_lambda_do_not_share_local_variable() + function! s:define_funcs() + let l:One = {-> split(execute("let a = 'abc' | echo a"))[0]} + let l:Two = {-> exists("a") ? a : "no"} + return [l:One, l:Two] + endfunction + + let l:F = s:define_funcs() + + call assert_equal('no', l:F[1]()) + call assert_equal('abc', l:F[0]()) + call assert_equal('no', l:F[1]()) +endfunction + +function! Test_lambda_closure_counter() + function! s:foo() + let x = 0 + return {-> [execute("let x += 1"), x][-1]} + endfunction + + let l:F = s:foo() + call garbagecollect() + call assert_equal(1, l:F()) + call assert_equal(2, l:F()) + call assert_equal(3, l:F()) + call assert_equal(4, l:F()) +endfunction + +function! Test_lambda_with_a_var() + function! s:foo() + let x = 2 + return {... -> a:000 + [x]} + endfunction + function! s:bar() + return s:foo()(1) + endfunction + + call assert_equal([1, 2], s:bar()) +endfunction + +function! Test_lambda_call_lambda_from_lambda() + function! s:foo(x) + let l:F1 = {-> {-> a:x}} + return {-> l:F1()} + endfunction + + let l:F = s:foo(1) + call assert_equal(1, l:F()()) +endfunction + +function! Test_lambda_delfunc() + function! s:gen() + let pl = l: + let l:Foo = {-> get(pl, "Foo", get(pl, "Bar", {-> 0}))} + let l:Bar = l:Foo + delfunction l:Foo + return l:Bar + endfunction + + let l:F = s:gen() + call assert_fails(':call l:F()', 'E933:') +endfunction + +function! Test_lambda_scope() + function! s:NewCounter() + let c = 0 + return {-> [execute('let c += 1'), c][-1]} + endfunction + + function! s:NewCounter2() + return {-> [execute('let c += 100'), c][-1]} + endfunction + + let l:C = s:NewCounter() + let l:D = s:NewCounter2() + + call assert_equal(1, l:C()) + call assert_fails(':call l:D()', 'E15:') " E121: then E15: + call assert_equal(2, l:C()) +endfunction + +function! Test_lambda_share_scope() + function! s:New() + let c = 0 + let l:Inc0 = {-> [execute('let c += 1'), c][-1]} + let l:Dec0 = {-> [execute('let c -= 1'), c][-1]} + return [l:Inc0, l:Dec0] + endfunction + + let [l:Inc, l:Dec] = s:New() + + call assert_equal(1, l:Inc()) + call assert_equal(2, l:Inc()) + call assert_equal(1, l:Dec()) +endfunction + +function! Test_lambda_circular_reference() + function! s:Foo() + let d = {} + let d.f = {-> d} + return d.f + endfunction + + call s:Foo() + call garbagecollect() + let i = 0 | while i < 10000 | call s:Foo() | let i+= 1 | endwhile + call garbagecollect() +endfunction + +function! Test_lambda_combination() + call assert_equal(2, {x -> {x -> x}}(1)(2)) + call assert_equal(10, {y -> {x -> x(y)(10)}({y -> y})}({z -> z})) + call assert_equal(5.0, {x -> {y -> x / y}}(10)(2.0)) + call assert_equal(6, {x -> {y -> {z -> x + y + z}}}(1)(2)(3)) + + call assert_equal(6, {x -> {f -> f(x)}}(3)({x -> x * 2})) + call assert_equal(6, {f -> {x -> f(x)}}({x -> x * 2})(3)) + + " Z combinator + let Z = {f -> {x -> f({y -> x(x)(y)})}({x -> f({y -> x(x)(y)})})} + let Fact = {f -> {x -> x == 0 ? 1 : x * f(x - 1)}} + call assert_equal(120, Z(Fact)(5)) +endfunction + +function! Test_closure_counter() + function! s:foo() + let x = 0 + function! s:bar() closure + let x += 1 + return x + endfunction + return function('s:bar') + endfunction + + let l:F = s:foo() + call garbagecollect() + call assert_equal(1, l:F()) + call assert_equal(2, l:F()) + call assert_equal(3, l:F()) + call assert_equal(4, l:F()) +endfunction + +function! Test_closure_unlet() + function! s:foo() + let x = 1 + function! s:bar() closure + unlet x + endfunction + call s:bar() + return l: + endfunction + + call assert_false(has_key(s:foo(), 'x')) + call garbagecollect() +endfunction + +function! LambdaFoo() + let x = 0 + function! LambdaBar() closure + let x += 1 + return x + endfunction + return function('LambdaBar') +endfunction + +func Test_closure_refcount() + let g:Count = LambdaFoo() + call test_garbagecollect_now() + call assert_equal(1, g:Count()) + let g:Count2 = LambdaFoo() + call test_garbagecollect_now() + call assert_equal(1, g:Count2()) + call assert_equal(2, g:Count()) + call assert_equal(3, g:Count2()) + + delfunc LambdaFoo + delfunc LambdaBar +endfunc + +" This test is causing a use-after-free on shutdown. +func Test_named_function_closure() + func! Afoo() + let x = 14 + func! s:Abar() closure + return x + endfunc + call assert_equal(14, s:Abar()) + endfunc + call Afoo() + call assert_equal(14, s:Abar()) + call garbagecollect() + call assert_equal(14, s:Abar()) +endfunc diff --git a/src/nvim/testdir/test_largefile.vim b/src/nvim/testdir/test_largefile.vim new file mode 100644 index 0000000000..1b3e02a0c8 --- /dev/null +++ b/src/nvim/testdir/test_largefile.vim @@ -0,0 +1,34 @@ +" Tests for large files +" This is only executed manually: "make test_largefile". +" This is not run as part of "make test". + +func Test_largefile() + let fname = 'Xlarge.txt' + + call delete(fname) + exe "e" fname + " Make sure that a line break is 1 byte (LF). + set ff=unix + set undolevels=-1 + " Input 99 'A's. The line becomes 100 bytes including a line break. + exe "normal 99iA\<Esc>" + yank + " Put 39,999,999 times. The file becomes 4,000,000,000 bytes. + normal 39999999p + " Moving around in the file randomly. + normal G + normal 10% + normal 90% + normal 50% + normal gg + w + " Check if the file size is 4,000,000,000 bytes. + let fsize=getfsize(fname) + if has('num64') + call assert_true(fsize == 4000000000) + else + " getfsize() returns -2 if a Number is 32 bits. + call assert_true(fsize == -2) + endif + call delete(fname) +endfunc diff --git a/src/nvim/testdir/test_listlbr.vim b/src/nvim/testdir/test_listlbr.vim new file mode 100644 index 0000000000..7856ee82ab --- /dev/null +++ b/src/nvim/testdir/test_listlbr.vim @@ -0,0 +1,235 @@ +" Test for linebreak and list option (non-utf8) + +set encoding=latin1 +scriptencoding latin1 + +if !exists("+linebreak") || !has("conceal") + finish +endif + +source view_util.vim + +function s:screen_lines(lnum, width) abort + return ScreenLines(a:lnum, a:width) +endfunction + +function! s:compare_lines(expect, actual) + call assert_equal(join(a:expect, "\n"), join(a:actual, "\n")) +endfunction + +function s:test_windows(...) + call NewWindow(10, 20) + setl ts=8 sw=4 sts=4 linebreak sbr= wrap + exe get(a:000, 0, '') +endfunction + +function s:close_windows(...) + call CloseWindow() + exe get(a:000, 0, '') +endfunction + +func Test_set_linebreak() + call s:test_windows('setl ts=4 sbr=+') + call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP ") + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ " abcdef ", +\ "+hijklmn ", +\ "+pqrstuvwxyz_1060ABC", +\ "+DEFGHIJKLMNOP ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_linebreak_with_list() + call s:test_windows('setl ts=4 sbr=+ list listchars=') + call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP ") + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "^Iabcdef hijklmn^I ", +\ "+pqrstuvwxyz_1060ABC", +\ "+DEFGHIJKLMNOP ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_linebreak_with_nolist() + call s:test_windows('setl ts=4 sbr=+ nolist') + call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP ") + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ " abcdef ", +\ "+hijklmn ", +\ "+pqrstuvwxyz_1060ABC", +\ "+DEFGHIJKLMNOP ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_should_break() + call s:test_windows('setl sbr=+ nolist') + call setline(1, "1\t" . repeat('a', winwidth(0)-2)) + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "1 ", +\ "+aaaaaaaaaaaaaaaaaa ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_linebreak_with_conceal() + call s:test_windows('setl cpo&vim sbr=+ list conceallevel=2 concealcursor=nv listchars=tab:ab') + call setline(1, "_S_\t bla") + syn match ConcealVar contained /_/ conceal + syn match All /.*/ contains=ConcealVar + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "Sabbbbbb bla ", +\ "~ ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_virtual_block() + call s:test_windows('setl sbr=+') + call setline(1, [ +\ "REMOVE: this not", +\ "REMOVE: aaaaaaaaaaaaa", +\ ]) + exe "norm! 1/^REMOVE:" + exe "norm! 0\<C-V>jf x" + $put + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "this not ", +\ "aaaaaaaaaaaaa ", +\ "REMOVE: ", +\ "REMOVE: ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_virtual_block_and_vbA() + call s:test_windows() + call setline(1, "long line: " . repeat("foobar ", 40) . "TARGET at end") + exe "norm! $3B\<C-v>eAx\<Esc>" + let lines = s:screen_lines([1, 10], winwidth(0)) + let expect = [ +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar TARGETx at ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_virtual_char_and_block() + call s:test_windows() + call setline(1, "1111-1111-1111-11-1111-1111-1111") + exe "norm! 0f-lv3lc2222\<Esc>bgj." + let lines = s:screen_lines([1, 2], winwidth(0)) + let expect = [ +\ "1111-2222-1111-11- ", +\ "1111-2222-1111 ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_undo_after_block_visual() + call s:test_windows() + call setline(1, ["aaa", "aaa", "a"]) + exe "norm! gg\<C-V>2j~e." + let lines = s:screen_lines([1, 3], winwidth(0)) + let expect = [ +\ "AaA ", +\ "AaA ", +\ "A ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_norm_after_block_visual() + call s:test_windows() + call setline(1, ["abcd{ef", "ghijklm", "no}pgrs"]) + exe "norm! ggf{\<C-V>\<C-V>c%" + let lines = s:screen_lines([1, 3], winwidth(0)) + let expect = [ +\ "abcdpgrs ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_block_replace_after_wrapping() + call s:test_windows() + call setline(1, repeat("a", 150)) + exe "norm! 0yypk147|\<C-V>jr0" + call assert_equal(repeat("a", 146) . "0aaa", getline(1)) + call assert_equal(repeat("a", 146) . "0aaa", getline(2)) + let lines = s:screen_lines([1, 10], winwidth(0)) + let expect = [ +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaa0aaa ", +\ "@ ", +\ "@ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_list_with_listchars() + call s:test_windows('setl list listchars=space:_,trail:-,tab:>-,eol:$') + call setline(1, "a aaaaaaaaaaaaaaaaaaaaaa\ta ") + let lines = s:screen_lines([1, 3], winwidth(0)) + let expect = [ +\ "a_ ", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aa>-----a-$ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_list_with_tab_and_skipping_first_chars() + call s:test_windows('setl list listchars=tab:>- ts=70 nowrap') + call setline(1, ["iiiiiiiiiiiiiiii\taaaaaaaaaaaaaaaaaa", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\taaaaaaaaaaaaaaaaaa", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\taaaaaaaaaaaaaaaaaa", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\taaaaaaaaaaaaaaaaaa"]) + call cursor(4,64) + norm! 2zl + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "---------------aaaaa", +\ "---------------aaaaa", +\ "---------------aaaaa", +\ "iiiiiiiii>-----aaaaa", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfu diff --git a/src/nvim/testdir/test_listlbr_utf8.vim b/src/nvim/testdir/test_listlbr_utf8.vim new file mode 100644 index 0000000000..980d67d49d --- /dev/null +++ b/src/nvim/testdir/test_listlbr_utf8.vim @@ -0,0 +1,229 @@ +" Test for linebreak and list option in utf-8 mode + +set encoding=utf-8 +scriptencoding utf-8 + +if !exists("+linebreak") || !has("conceal") || !has("signs") + finish +endif + +source view_util.vim + +function s:screen_lines(lnum, width) abort + return ScreenLines(a:lnum, a:width) +endfunction + +function! s:compare_lines(expect, actual) + call assert_equal(a:expect, a:actual) +endfunction + +function s:screen_attr(lnum, chars, ...) abort + let line = getline(a:lnum) + let attr = [] + let prefix = get(a:000, 0, 0) + for i in range(a:chars[0], a:chars[1]) + let scol = strdisplaywidth(strcharpart(line, 0, i-1)) + 1 + let attr += [screenattr(a:lnum, scol + prefix)] + endfor + return attr +endfunction + +function s:test_windows(...) + call NewWindow(10, 20) + setl ts=4 sw=4 sts=4 linebreak sbr=+ wrap + exe get(a:000, 0, '') +endfunction + +function s:close_windows(...) + call CloseWindow() + exe get(a:000, 0, '') +endfunction + +func Test_linebreak_with_fancy_listchars() + call s:test_windows("setl list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6") + call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz\u00a01060ABCDEFGHIJKLMNOP ") + redraw! + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "▕———abcdef ", +\ "+hijklmn▕——— ", +\ "+pqrstuvwxyzâ£1060ABC", +\ "+DEFGHIJKLMNOPˑ¶ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_nolinebreak_with_list() + call s:test_windows("setl nolinebreak list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6") + call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz\u00a01060ABCDEFGHIJKLMNOP ") + redraw! + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "▕———abcdef hijklmn▕—", +\ "+pqrstuvwxyzâ£1060ABC", +\ "+DEFGHIJKLMNOPˑ¶ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_linebreak_with_nolist() + call s:test_windows('setl nolist') + call setline(1, "\t*mask = nil;") + redraw! + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ " *mask = nil; ", +\ "~ ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_list_and_concealing1() + call s:test_windows('setl list listchars=tab:>- cole=1') + call setline(1, [ +\ "#define ABCDE\t\t1", +\ "#define ABCDEF\t\t1", +\ "#define ABCDEFG\t\t1", +\ "#define ABCDEFGH\t1", +\ "#define MSG_MODE_FILE\t\t\t1", +\ "#define MSG_MODE_CONSOLE\t\t2", +\ "#define MSG_MODE_FILE_AND_CONSOLE\t3", +\ "#define MSG_MODE_FILE_THEN_CONSOLE\t4", +\ ]) + vert resize 40 + syn match Conceal conceal cchar=>'AB\|MSG_MODE' + redraw! + let lines = s:screen_lines([1, 7], winwidth(0)) + let expect = [ +\ "#define ABCDE>-->---1 ", +\ "#define >CDEF>-->---1 ", +\ "#define >CDEFG>->---1 ", +\ "#define >CDEFGH>----1 ", +\ "#define >_FILE>--------->--->---1 ", +\ "#define >_CONSOLE>---------->---2 ", +\ "#define >_FILE_AND_CONSOLE>---------3 ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_list_and_concealing2() + call s:test_windows('setl nowrap ts=2 list listchars=tab:>- cole=2 concealcursor=n') + call setline(1, "bbeeeeee\t\t;\tsome text") + vert resize 40 + syn clear + syn match meaning /;\s*\zs.*/ + syn match hasword /^\x\{8}/ contains=word + syn match word /\<\x\{8}\>/ contains=beginword,endword contained + syn match beginword /\<\x\x/ contained conceal + syn match endword /\x\{6}\>/ contained + hi meaning guibg=blue + hi beginword guibg=green + hi endword guibg=red + redraw! + let lines = s:screen_lines([1, 1], winwidth(0)) + let expect = [ +\ "eeeeee>--->-;>some text ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_screenattr_for_comment() + call s:test_windows("setl ft=c ts=7 list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6") + call setline(1, " /*\t\t and some more */") + norm! gg0 + syntax on + hi SpecialKey term=underline ctermfg=red guifg=red + redraw! + let line = getline(1) + let attr = s:screen_attr(1, [1, 6]) + call assert_notequal(attr[0], attr[1]) + call assert_notequal(attr[1], attr[3]) + call assert_notequal(attr[3], attr[5]) + call s:close_windows() +endfunc + +func Test_visual_block_and_selection_exclusive() + call s:test_windows('setl selection=exclusive') + call setline(1, "long line: " . repeat("foobar ", 40) . "TARGETÃ' at end") + exe "norm! $3B\<C-v>eAx\<Esc>" + let lines = s:screen_lines([1, 10], winwidth(0)) + let expect = [ +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar TARGETÃx' ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_multibyte_sign_and_colorcolumn() + call s:test_windows("setl nolinebreak cc=3 list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6") + call setline(1, ["", "a b c", "a b c"]) + exe "sign define foo text=\uff0b" + exe "sign place 1 name=foo line=2 buffer=" . bufnr('%') + redraw! + norm! ggj0 + let signwidth = strdisplaywidth("\uff0b") + let attr1 = s:screen_attr(2, [1, 3], signwidth) + let attr2 = s:screen_attr(3, [1, 3], signwidth) + call assert_equal(attr1[0], attr2[0]) + call assert_equal(attr1[1], attr2[1]) + call assert_equal(attr1[2], attr2[2]) + let lines = s:screen_lines([1, 3], winwidth(0)) + let expect = [ +\ " ¶ ", +\ "+a b c¶ ", +\ " a b c¶ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_chinese_char_on_wrap_column() + call s:test_windows("setl nolbr wrap sbr=") + syntax off + call setline(1, [ +\ 'aaaaaaaaaaaaaaaaaaaä¸'. +\ 'aaaaaaaaaaaaaaaaaä¸'. +\ 'aaaaaaaaaaaaaaaaaä¸'. +\ 'aaaaaaaaaaaaaaaaaä¸'. +\ 'aaaaaaaaaaaaaaaaaä¸'. +\ 'aaaaaaaaaaaaaaaaaä¸'. +\ 'aaaaaaaaaaaaaaaaaä¸'. +\ 'aaaaaaaaaaaaaaaaaä¸'. +\ 'aaaaaaaaaaaaaaaaaä¸'. +\ 'aaaaaaaaaaaaaaaaaä¸'. +\ 'hello']) + call cursor(1,1) + norm! $ + redraw! + let expect=[ +\ 'ä¸aaaaaaaaaaaaaaaaa>', +\ 'ä¸aaaaaaaaaaaaaaaaa>', +\ 'ä¸aaaaaaaaaaaaaaaaa>', +\ 'ä¸aaaaaaaaaaaaaaaaa>', +\ 'ä¸aaaaaaaaaaaaaaaaa>', +\ 'ä¸aaaaaaaaaaaaaaaaa>', +\ 'ä¸aaaaaaaaaaaaaaaaa>', +\ 'ä¸aaaaaaaaaaaaaaaaa>', +\ 'ä¸aaaaaaaaaaaaaaaaa>', +\ 'ä¸hello '] + let lines = s:screen_lines([1, 10], winwidth(0)) + call s:compare_lines(expect, lines) + call s:close_windows() +endfu diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim new file mode 100644 index 0000000000..7f93ddd56e --- /dev/null +++ b/src/nvim/testdir/test_mapping.vim @@ -0,0 +1,160 @@ +" Tests for mappings and abbreviations + +if !has('multi_byte') + finish +endif + +func Test_abbreviation() + " abbreviation with 0x80 should work + inoreab чкпр vim + call feedkeys("Goчкпр \<Esc>", "xt") + call assert_equal('vim ', getline('$')) + iunab чкпр + set nomodified +endfunc + +func Test_map_ctrl_c_insert() + " mapping of ctrl-c in Insert mode + set cpo-=< cpo-=k + inoremap <c-c> <ctrl-c> + cnoremap <c-c> dummy + cunmap <c-c> + call feedkeys("GoTEST2: CTRL-C |\<C-C>A|\<Esc>", "xt") + call assert_equal('TEST2: CTRL-C |<ctrl-c>A|', getline('$')) + unmap! <c-c> + set nomodified +endfunc + +func Test_map_ctrl_c_visual() + " mapping of ctrl-c in Visual mode + vnoremap <c-c> :<C-u>$put ='vmap works' + call feedkeys("GV\<C-C>\<CR>", "xt") + call assert_equal('vmap works', getline('$')) + vunmap <c-c> + set nomodified +endfunc + +func Test_map_langmap() + if !has('langmap') + return + endif + + " check langmap applies in normal mode + set langmap=+- nolangremap + new + call setline(1, ['a', 'b', 'c']) + 2 + call assert_equal('b', getline('.')) + call feedkeys("+", "xt") + call assert_equal('a', getline('.')) + + " check no remapping + map x + + 2 + call feedkeys("x", "xt") + call assert_equal('c', getline('.')) + + " check with remapping + set langremap + 2 + call feedkeys("x", "xt") + call assert_equal('a', getline('.')) + + unmap x + bwipe! + + " 'langnoremap' follows 'langremap' and vise versa + set langremap + set langnoremap + call assert_equal(0, &langremap) + set langremap + call assert_equal(0, &langnoremap) + set nolangremap + call assert_equal(1, &langnoremap) + + " check default values + set langnoremap& + call assert_equal(1, &langnoremap) + call assert_equal(0, &langremap) + set langremap& + call assert_equal(1, &langnoremap) + call assert_equal(0, &langremap) + + " langmap should not apply in insert mode, 'langremap' doesn't matter + set langmap=+{ nolangremap + call feedkeys("Go+\<Esc>", "xt") + call assert_equal('+', getline('$')) + set langmap=+{ langremap + call feedkeys("Go+\<Esc>", "xt") + call assert_equal('+', getline('$')) + + " langmap used for register name in insert mode. + call setreg('a', 'aaaa') + call setreg('b', 'bbbb') + call setreg('c', 'cccc') + set langmap=ab langremap + call feedkeys("Go\<C-R>a\<Esc>", "xt") + call assert_equal('bbbb', getline('$')) + call feedkeys("Go\<C-R>\<C-R>a\<Esc>", "xt") + call assert_equal('bbbb', getline('$')) + " mapping does not apply + imap c a + call feedkeys("Go\<C-R>c\<Esc>", "xt") + call assert_equal('cccc', getline('$')) + imap a c + call feedkeys("Go\<C-R>a\<Esc>", "xt") + call assert_equal('bbbb', getline('$')) + + " langmap should not apply in Command-line mode + set langmap=+{ nolangremap + call feedkeys(":call append(line('$'), '+')\<CR>", "xt") + call assert_equal('+', getline('$')) + + set nomodified +endfunc + +func Test_map_feedkeys() + " issue #212 (feedkeys insert mapping at current position) + nnoremap . :call feedkeys(".", "in")<cr> + call setline('$', ['a b c d', 'a b c d']) + $-1 + call feedkeys("0qqdw.ifoo\<Esc>qj0@q\<Esc>", "xt") + call assert_equal(['fooc d', 'fooc d'], getline(line('$') - 1, line('$'))) + unmap . + set nomodified +endfunc + +func Test_map_cursor() + " <c-g>U<cursor> works only within a single line + imapclear + imap ( ()<c-g>U<left> + call feedkeys("G2o\<Esc>ki\<CR>Test1: text with a (here some more text\<Esc>k.", "xt") + call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 2)) + call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 1)) + + " test undo + call feedkeys("G2o\<Esc>ki\<CR>Test2: text wit a (here some more text [und undo]\<C-G>u\<Esc>k.u", "xt") + call assert_equal('', getline(line('$') - 2)) + call assert_equal('Test2: text wit a (here some more text [und undo])', getline(line('$') - 1)) + set nomodified + imapclear +endfunc + +" This isn't actually testing a mapping, but similar use of CTRL-G U as above. +func Test_break_undo() + :set whichwrap=<,>,[,] + call feedkeys("G4o2k", "xt") + exe ":norm! iTest3: text with a (parenthesis here\<C-G>U\<Right>new line here\<esc>\<up>\<up>." + call assert_equal('new line here', getline(line('$') - 3)) + call assert_equal('Test3: text with a (parenthesis here', getline(line('$') - 2)) + call assert_equal('new line here', getline(line('$') - 1)) + set nomodified +endfunc + +func Test_map_meta_quotes() + imap <M-"> foo + call feedkeys("Go-\<M-\">-\<Esc>", "xt") + call assert_equal("-foo-", getline('$')) + set nomodified + iunmap <M-"> +endfunc diff --git a/src/nvim/testdir/test_marks.vim b/src/nvim/testdir/test_marks.vim new file mode 100644 index 0000000000..d00b1ddc88 --- /dev/null +++ b/src/nvim/testdir/test_marks.vim @@ -0,0 +1,26 @@ + +" Test that a deleted mark is restored after delete-undo-redo-undo. +function! Test_Restore_DelMark() + enew! + call append(0, [" textline A", " textline B", " textline C"]) + normal! 2gg + set nocp viminfo+=nviminfo + exe "normal! i\<C-G>u\<Esc>" + exe "normal! maddu\<C-R>u" + let pos = getpos("'a") + call assert_equal(2, pos[1]) + call assert_equal(1, pos[2]) + enew! +endfunction + +" Test that CTRL-A and CTRL-X updates last changed mark '[, ']. +function! Test_Incr_Marks() + enew! + call append(0, ["123 123 123", "123 123 123", "123 123 123"]) + normal! gg + execute "normal! \<C-A>`[v`]rAjwvjw\<C-X>`[v`]rX" + call assert_equal("AAA 123 123", getline(1)) + call assert_equal("123 XXXXXXX", getline(2)) + call assert_equal("XXX 123 123", getline(3)) + enew! +endfunction diff --git a/src/nvim/testdir/test_match.vim b/src/nvim/testdir/test_match.vim index 7748dee87f..066bb2f6a1 100644 --- a/src/nvim/testdir/test_match.vim +++ b/src/nvim/testdir/test_match.vim @@ -198,6 +198,16 @@ func Test_matchaddpos() call assert_equal(screenattr(2,2), screenattr(1,10)) call assert_notequal(screenattr(2,2), screenattr(1,11)) + " Check overlapping pos + call clearmatches() + call setline(1, ['1234567890', 'NH']) + call matchaddpos('Error', [[1,1,5], [1,3,5], [2,2]]) + redraw! + call assert_notequal(screenattr(2,2), 0) + call assert_equal(screenattr(2,2), screenattr(1,5)) + call assert_equal(screenattr(2,2), screenattr(1,7)) + call assert_notequal(screenattr(2,2), screenattr(1,8)) + nohl call clearmatches() syntax off @@ -231,4 +241,4 @@ func Test_matchaddpos_using_negative_priority() set hlsearch& endfunc -" vim: et ts=2 sw=2 +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_matchadd_conceal.vim b/src/nvim/testdir/test_matchadd_conceal.vim index bc1c28d6e9..c11f1a84a9 100644 --- a/src/nvim/testdir/test_matchadd_conceal.vim +++ b/src/nvim/testdir/test_matchadd_conceal.vim @@ -260,3 +260,26 @@ function! Test_matchadd_repeat_conceal_with_syntax_off() quit! endfunction + +function! Test_matchadd_and_syn_conceal() + new + let cnt='Inductive bool : Type := | true : bool | false : bool.' + let expect = 'Inductive - : Type := | true : - | false : -.' + 0put =cnt + " set filetype and :syntax on to change screenattr() + set cole=1 cocu=nv + hi link CheckedByCoq WarningMsg + syntax on + syntax keyword coqKwd bool conceal cchar=- + redraw! + call assert_equal(expect, s:screenline(1)) + call assert_notequal(screenattr(1, 10) , screenattr(1, 11)) + call assert_notequal(screenattr(1, 11) , screenattr(1, 12)) + call assert_equal(screenattr(1, 11) , screenattr(1, 32)) + call matchadd('CheckedByCoq', '\%<2l\%>9c\%<16c') + redraw! + call assert_equal(expect, s:screenline(1)) + call assert_notequal(screenattr(1, 10) , screenattr(1, 11)) + call assert_notequal(screenattr(1, 11) , screenattr(1, 12)) + call assert_equal(screenattr(1, 11) , screenattr(1, 32)) +endfunction diff --git a/src/nvim/testdir/test_menu.vim b/src/nvim/testdir/test_menu.vim index be559467c8..af18760065 100644 --- a/src/nvim/testdir/test_menu.vim +++ b/src/nvim/testdir/test_menu.vim @@ -4,6 +4,6 @@ func Test_load_menu() try source $VIMRUNTIME/menu.vim catch - call assert_false(1, 'error while loading menus: ' . v:exception) + call assert_report('error while loading menus: ' . v:exception) endtry endfunc diff --git a/src/nvim/testdir/test_nested_function.vim b/src/nvim/testdir/test_nested_function.vim new file mode 100644 index 0000000000..afaaea6ceb --- /dev/null +++ b/src/nvim/testdir/test_nested_function.vim @@ -0,0 +1,63 @@ +"Tests for nested functions +" +func NestedFunc() + func! Func1() + let g:text .= 'Func1 ' + endfunc + call Func1() + func! s:func2() + let g:text .= 's:func2 ' + endfunc + call s:func2() + func! s:_func3() + let g:text .= 's:_func3 ' + endfunc + call s:_func3() + let fn = 'Func4' + func! {fn}() + let g:text .= 'Func4 ' + endfunc + call {fn}() + let fn = 'func5' + func! s:{fn}() + let g:text .= 's:func5' + endfunc + call s:{fn}() +endfunc + +func Test_nested_functions() + let g:text = '' + call NestedFunc() + call assert_equal('Func1 s:func2 s:_func3 Func4 s:func5', g:text) +endfunction + +func Test_nested_argument() + func g:X() + let g:Y = function('sort') + endfunc + let g:Y = function('sort') + echo g:Y([], g:X()) + delfunc g:X + unlet g:Y +endfunc + +func Recurse(count) + if a:count > 0 + call Recurse(a:count - 1) + endif +endfunc + +func Test_max_nesting() + let call_depth_here = 2 + let ex_depth_here = 5 + set mfd& + + call Recurse(99 - call_depth_here) + call assert_fails('call Recurse(' . (100 - call_depth_here) . ')', 'E132:') + + set mfd=210 + call Recurse(209 - ex_depth_here) + call assert_fails('call Recurse(' . (210 - ex_depth_here) . ')', 'E169:') + + set mfd& +endfunc diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim new file mode 100644 index 0000000000..4747d5704d --- /dev/null +++ b/src/nvim/testdir/test_normal.vim @@ -0,0 +1,2337 @@ +" Test for various Normal mode commands + +func! Setup_NewWindow() + 10new + call setline(1, range(1,100)) +endfunc + +func! MyFormatExpr() + " Adds '->$' at lines having numbers followed by trailing whitespace + for ln in range(v:lnum, v:lnum+v:count-1) + let line = getline(ln) + if getline(ln) =~# '\d\s\+$' + call setline(ln, substitute(line, '\s\+$', '', '') . '->$') + endif + endfor +endfunc + +func! CountSpaces(type, ...) + " for testing operatorfunc + " will count the number of spaces + " and return the result in g:a + let sel_save = &selection + let &selection = "inclusive" + let reg_save = @@ + + if a:0 " Invoked from Visual mode, use gv command. + silent exe "normal! gvy" + elseif a:type == 'line' + silent exe "normal! '[V']y" + else + silent exe "normal! `[v`]y" + endif + let g:a=strlen(substitute(@@, '[^ ]', '', 'g')) + let &selection = sel_save + let @@ = reg_save +endfunc + +func! OpfuncDummy(type, ...) + " for testing operatorfunc + let g:opt=&linebreak + + if a:0 " Invoked from Visual mode, use gv command. + silent exe "normal! gvy" + elseif a:type == 'line' + silent exe "normal! '[V']y" + else + silent exe "normal! `[v`]y" + endif + " Create a new dummy window + new + let g:bufnr=bufnr('%') +endfunc + +fun! Test_normal00_optrans() + new + call append(0, ['1 This is a simple test: abcd', '2 This is the second line', '3 this is the third line']) + 1 + exe "norm! Sfoobar\<esc>" + call assert_equal(['foobar', '2 This is the second line', '3 this is the third line', ''], getline(1,'$')) + 2 + exe "norm! $vbsone" + call assert_equal(['foobar', '2 This is the second one', '3 this is the third line', ''], getline(1,'$')) + norm! VS Second line here + call assert_equal(['foobar', ' Second line here', '3 this is the third line', ''], getline(1, '$')) + %d + call append(0, ['4 This is a simple test: abcd', '5 This is the second line', '6 this is the third line']) + call append(0, ['1 This is a simple test: abcd', '2 This is the second line', '3 this is the third line']) + + 1 + norm! 2D + call assert_equal(['3 this is the third line', '4 This is a simple test: abcd', '5 This is the second line', '6 this is the third line', ''], getline(1,'$')) + " Nvim: no "#" flag in 'cpoptions'. + " set cpo+=# + " norm! 4D + " call assert_equal(['', '4 This is a simple test: abcd', '5 This is the second line', '6 this is the third line', ''], getline(1,'$')) + + " clean up + set cpo-=# + bw! +endfunc + +func! Test_normal01_keymodel() + throw "skipped: Nvim regression: 'keymodel'" + call Setup_NewWindow() + " Test 1: depending on 'keymodel' <s-down> does something different + 50 + call feedkeys("V\<S-Up>y", 'tx') + call assert_equal(['47', '48', '49', '50'], getline("'<", "'>")) + set keymodel=startsel + 50 + call feedkeys("V\<S-Up>y", 'tx') + call assert_equal(['49', '50'], getline("'<", "'>")) + " Start visual mode when keymodel = startsel + 50 + call feedkeys("\<S-Up>y", 'tx') + call assert_equal(['49', '5'], getreg(0, 0, 1)) + " Do not start visual mode when keymodel= + set keymodel= + 50 + call feedkeys("\<S-Up>y$", 'tx') + call assert_equal(['42'], getreg(0, 0, 1)) + " Stop visual mode when keymodel=stopsel + set keymodel=stopsel + 50 + call feedkeys("Vkk\<Up>yy", 'tx') + call assert_equal(['47'], getreg(0, 0, 1)) + + set keymodel= + 50 + call feedkeys("Vkk\<Up>yy", 'tx') + call assert_equal(['47', '48', '49', '50'], getreg(0, 0, 1)) + + " clean up + bw! +endfunc + +func! Test_normal02_selectmode() + " some basic select mode tests + call Setup_NewWindow() + 50 + norm! gHy + call assert_equal('y51', getline('.')) + call setline(1, range(1,100)) + 50 + exe ":norm! V9jo\<c-g>y" + call assert_equal('y60', getline('.')) + " clean up + bw! +endfunc + +func! Test_normal02_selectmode2() + " some basic select mode tests + call Setup_NewWindow() + 50 + call feedkeys(":set im\n\<c-o>gHc\<c-o>:set noim\n", 'tx') + call assert_equal('c51', getline('.')) + " clean up + bw! +endfunc + +func! Test_normal03_join() + " basic join test + call Setup_NewWindow() + 50 + norm! VJ + call assert_equal('50 51', getline('.')) + $ + norm! J + call assert_equal('100', getline('.')) + $ + norm! V9-gJ + call assert_equal('919293949596979899100', getline('.')) + call setline(1, range(1,100)) + $ + :j 10 + call assert_equal('100', getline('.')) + " clean up + bw! +endfunc + +func! Test_normal04_filter() + " basic filter test + " only test on non windows platform + if has('win32') + return + endif + call Setup_NewWindow() + 1 + call feedkeys("!!sed -e 's/^/| /'\n", 'tx') + call assert_equal('| 1', getline('.')) + 90 + :sil :!echo one + call feedkeys('.', 'tx') + call assert_equal('| 90', getline('.')) + 95 + set cpo+=! + " 2 <CR>, 1: for executing the command, + " 2: clear hit-enter-prompt + call feedkeys("!!\n", 'tx') + call feedkeys(":!echo one\n\n", 'tx') + call feedkeys(".", 'tx') + call assert_equal('one', getline('.')) + set cpo-=! + bw! +endfunc + +func! Test_normal05_formatexpr() + " basic formatexpr test + call Setup_NewWindow() + %d_ + call setline(1, ['here: 1 ', '2', 'here: 3 ', '4', 'not here: ']) + 1 + set formatexpr=MyFormatExpr() + norm! gqG + call assert_equal(['here: 1->$', '2', 'here: 3->$', '4', 'not here: '], getline(1,'$')) + set formatexpr= + bw! +endfunc + +func Test_normal05_formatexpr_newbuf() + " Edit another buffer in the 'formatexpr' function + new + func! Format() + edit another + endfunc + set formatexpr=Format() + norm gqG + bw! + set formatexpr= +endfunc + +func Test_normal05_formatexpr_setopt() + " Change the 'formatexpr' value in the function + new + func! Format() + set formatexpr= + endfunc + set formatexpr=Format() + norm gqG + bw! + set formatexpr= +endfunc + +func! Test_normal06_formatprg() + " basic test for formatprg + " only test on non windows platform + if has('win32') + return + endif + + " uses sed to number non-empty lines + call writefile(['#!/bin/sh', 'sed ''/./=''|sed ''/./{', 'N', 's/\n/ /', '}'''], 'Xsed_format.sh') + call system('chmod +x ./Xsed_format.sh') + let text = ['a', '', 'c', '', ' ', 'd', 'e'] + let expected = ['1 a', '', '3 c', '', '5 ', '6 d', '7 e'] + + 10new + call setline(1, text) + set formatprg=./Xsed_format.sh + norm! gggqG + call assert_equal(expected, getline(1, '$')) + bw! + + 10new + call setline(1, text) + set formatprg=donothing + setlocal formatprg=./Xsed_format.sh + norm! gggqG + call assert_equal(expected, getline(1, '$')) + bw! + + " clean up + set formatprg= + setlocal formatprg= + call delete('Xsed_format.sh') +endfunc + +func! Test_normal07_internalfmt() + " basic test for internal formmatter to textwidth of 12 + let list=range(1,11) + call map(list, 'v:val." "') + 10new + call setline(1, list) + set tw=12 + norm! gggqG + call assert_equal(['1 2 3', '4 5 6', '7 8 9', '10 11 '], getline(1, '$')) + " clean up + set tw=0 + bw! +endfunc + +func! Test_normal08_fold() + " basic tests for foldopen/folddelete + if !has("folding") + return + endif + call Setup_NewWindow() + 50 + setl foldenable fdm=marker + " First fold + norm! V4jzf + " check that folds have been created + call assert_equal(['50/*{{{*/', '51', '52', '53', '54/*}}}*/'], getline(50,54)) + " Second fold + 46 + norm! V10jzf + " check that folds have been created + call assert_equal('46/*{{{*/', getline(46)) + call assert_equal('60/*}}}*/', getline(60)) + norm! k + call assert_equal('45', getline('.')) + norm! j + call assert_equal('46/*{{{*/', getline('.')) + norm! j + call assert_equal('61', getline('.')) + norm! k + " open a fold + norm! Vzo + norm! k + call assert_equal('45', getline('.')) + norm! j + call assert_equal('46/*{{{*/', getline('.')) + norm! j + call assert_equal('47', getline('.')) + norm! k + norm! zcVzO + call assert_equal('46/*{{{*/', getline('.')) + norm! j + call assert_equal('47', getline('.')) + norm! j + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('51', getline('.')) + " delete folds + :46 + " collapse fold + norm! V14jzC + " delete all folds recursively + norm! VzD + call assert_equal(['46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60'], getline(46,60)) + + " clean up + setl nofoldenable fdm=marker + bw! +endfunc + +func! Test_normal09_operatorfunc() + " Test operatorfunc + call Setup_NewWindow() + " Add some spaces for counting + 50,60s/$/ / + unlet! g:a + let g:a=0 + nmap <buffer><silent> ,, :set opfunc=CountSpaces<CR>g@ + vmap <buffer><silent> ,, :<C-U>call CountSpaces(visualmode(), 1)<CR> + 50 + norm V2j,, + call assert_equal(6, g:a) + norm V,, + call assert_equal(2, g:a) + norm ,,l + call assert_equal(0, g:a) + 50 + exe "norm 0\<c-v>10j2l,," + call assert_equal(11, g:a) + 50 + norm V10j,, + call assert_equal(22, g:a) + + " clean up + unmap <buffer> ,, + set opfunc= + unlet! g:a + bw! +endfunc + +func! Test_normal09a_operatorfunc() + " Test operatorfunc + call Setup_NewWindow() + " Add some spaces for counting + 50,60s/$/ / + unlet! g:opt + set linebreak + nmap <buffer><silent> ,, :set opfunc=OpfuncDummy<CR>g@ + 50 + norm ,,j + exe "bd!" g:bufnr + call assert_true(&linebreak) + call assert_equal(g:opt, &linebreak) + set nolinebreak + norm ,,j + exe "bd!" g:bufnr + call assert_false(&linebreak) + call assert_equal(g:opt, &linebreak) + + " clean up + unmap <buffer> ,, + set opfunc= + bw! + unlet! g:opt +endfunc + +func! Test_normal10_expand() + " Test for expand() + 10new + call setline(1, ['1', 'ifooar,,cbar']) + 2 + norm! $ + let a=expand('<cword>') + let b=expand('<cWORD>') + call assert_equal('cbar', a) + call assert_equal('ifooar,,cbar', b) + " clean up + bw! +endfunc + +func! Test_normal11_showcmd() + " test for 'showcmd' + 10new + exe "norm! ofoobar\<esc>" + call assert_equal(2, line('$')) + set showcmd + exe "norm! ofoobar2\<esc>" + call assert_equal(3, line('$')) + exe "norm! VAfoobar3\<esc>" + call assert_equal(3, line('$')) + exe "norm! 0d3\<del>2l" + call assert_equal('obar2foobar3', getline('.')) + bw! +endfunc + +func! Test_normal12_nv_error() + " Test for nv_error + 10new + call setline(1, range(1,5)) + " should not do anything, just beep + exe "norm! <c-k>" + call assert_equal(map(range(1,5), 'string(v:val)'), getline(1,'$')) + bw! +endfunc + +func! Test_normal13_help() + " Test for F1 + call assert_equal(1, winnr()) + call feedkeys("\<f1>", 'txi') + call assert_match('help\.txt', bufname('%')) + call assert_equal(2, winnr('$')) + bw! +endfunc + +func! Test_normal14_page() + " basic test for Ctrl-F and Ctrl-B + call Setup_NewWindow() + exe "norm! \<c-f>" + call assert_equal('9', getline('.')) + exe "norm! 2\<c-f>" + call assert_equal('25', getline('.')) + exe "norm! 2\<c-b>" + call assert_equal('18', getline('.')) + 1 + set scrolloff=5 + exe "norm! 2\<c-f>" + call assert_equal('21', getline('.')) + exe "norm! \<c-b>" + call assert_equal('13', getline('.')) + 1 + set scrolloff=99 + exe "norm! \<c-f>" + call assert_equal('13', getline('.')) + set scrolloff=0 + 100 + exe "norm! $\<c-b>" + call assert_equal('92', getline('.')) + call assert_equal([0, 92, 1, 0, 1], getcurpos()) + 100 + set nostartofline + exe "norm! $\<c-b>" + call assert_equal('92', getline('.')) + call assert_equal([0, 92, 2, 0, 2147483647], getcurpos()) + " cleanup + set startofline + bw! +endfunc + +func! Test_normal14_page_eol() + 10new + norm oxxxxxxx + exe "norm 2\<c-f>" + " check with valgrind that cursor is put back in column 1 + exe "norm 2\<c-b>" + bw! +endfunc + +func! Test_normal15_z_scroll_vert() + " basic test for z commands that scroll the window + call Setup_NewWindow() + 100 + norm! >> + " Test for z<cr> + exe "norm! z\<cr>" + call assert_equal(' 100', getline('.')) + call assert_equal(100, winsaveview()['topline']) + call assert_equal([0, 100, 2, 0, 9], getcurpos()) + + " Test for zt + 21 + norm! >>0zt + call assert_equal(' 21', getline('.')) + call assert_equal(21, winsaveview()['topline']) + call assert_equal([0, 21, 1, 0, 8], getcurpos()) + + " Test for zb + 30 + norm! >>$ztzb + call assert_equal(' 30', getline('.')) + call assert_equal(30, winsaveview()['topline']+winheight(0)-1) + call assert_equal([0, 30, 3, 0, 2147483647], getcurpos()) + + " Test for z- + 1 + 30 + norm! 0z- + call assert_equal(' 30', getline('.')) + call assert_equal(30, winsaveview()['topline']+winheight(0)-1) + call assert_equal([0, 30, 2, 0, 9], getcurpos()) + + " Test for z{height}<cr> + call assert_equal(10, winheight(0)) + exe "norm! z12\<cr>" + call assert_equal(12, winheight(0)) + exe "norm! z10\<cr>" + call assert_equal(10, winheight(0)) + + " Test for z. + 1 + 21 + norm! 0z. + call assert_equal(' 21', getline('.')) + call assert_equal(17, winsaveview()['topline']) + call assert_equal([0, 21, 2, 0, 9], getcurpos()) + + " Test for zz + 1 + 21 + norm! 0zz + call assert_equal(' 21', getline('.')) + call assert_equal(17, winsaveview()['topline']) + call assert_equal([0, 21, 1, 0, 8], getcurpos()) + + " Test for z+ + 11 + norm! zt + norm! z+ + call assert_equal(' 21', getline('.')) + call assert_equal(21, winsaveview()['topline']) + call assert_equal([0, 21, 2, 0, 9], getcurpos()) + + " Test for [count]z+ + 1 + norm! 21z+ + call assert_equal(' 21', getline('.')) + call assert_equal(21, winsaveview()['topline']) + call assert_equal([0, 21, 2, 0, 9], getcurpos()) + + " Test for z^ + norm! 22z+0 + norm! z^ + call assert_equal(' 21', getline('.')) + call assert_equal(12, winsaveview()['topline']) + call assert_equal([0, 21, 2, 0, 9], getcurpos()) + + " Test for [count]z^ + 1 + norm! 30z^ + call assert_equal(' 21', getline('.')) + call assert_equal(12, winsaveview()['topline']) + call assert_equal([0, 21, 2, 0, 9], getcurpos()) + + " cleanup + bw! +endfunc + +func! Test_normal16_z_scroll_hor() + " basic test for z commands that scroll the window + 10new + 15vsp + set nowrap listchars= + let lineA='abcdefghijklmnopqrstuvwxyz' + let lineB='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + $put =lineA + $put =lineB + 1d + + " Test for zl + 1 + norm! 5zl + call assert_equal(lineA, getline('.')) + call assert_equal(6, col('.')) + call assert_equal(5, winsaveview()['leftcol']) + norm! yl + call assert_equal('f', @0) + + " Test for zh + norm! 2zh + call assert_equal(lineA, getline('.')) + call assert_equal(6, col('.')) + norm! yl + call assert_equal('f', @0) + call assert_equal(3, winsaveview()['leftcol']) + + " Test for zL + norm! zL + call assert_equal(11, col('.')) + norm! yl + call assert_equal('k', @0) + call assert_equal(10, winsaveview()['leftcol']) + norm! 2zL + call assert_equal(25, col('.')) + norm! yl + call assert_equal('y', @0) + call assert_equal(24, winsaveview()['leftcol']) + + " Test for zH + norm! 2zH + call assert_equal(25, col('.')) + call assert_equal(10, winsaveview()['leftcol']) + norm! yl + call assert_equal('y', @0) + + " Test for zs + norm! $zs + call assert_equal(26, col('.')) + call assert_equal(25, winsaveview()['leftcol']) + norm! yl + call assert_equal('z', @0) + + " Test for ze + norm! ze + call assert_equal(26, col('.')) + call assert_equal(11, winsaveview()['leftcol']) + norm! yl + call assert_equal('z', @0) + + " cleanup + set wrap listchars=eol:$ + bw! +endfunc + +func! Test_normal17_z_scroll_hor2() + " basic test for z commands that scroll the window + " using 'sidescrolloff' setting + 10new + 20vsp + set nowrap listchars= sidescrolloff=5 + let lineA='abcdefghijklmnopqrstuvwxyz' + let lineB='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + $put =lineA + $put =lineB + 1d + + " Test for zl + 1 + norm! 5zl + call assert_equal(lineA, getline('.')) + call assert_equal(11, col('.')) + call assert_equal(5, winsaveview()['leftcol']) + norm! yl + call assert_equal('k', @0) + + " Test for zh + norm! 2zh + call assert_equal(lineA, getline('.')) + call assert_equal(11, col('.')) + norm! yl + call assert_equal('k', @0) + call assert_equal(3, winsaveview()['leftcol']) + + " Test for zL + norm! 0zL + call assert_equal(16, col('.')) + norm! yl + call assert_equal('p', @0) + call assert_equal(10, winsaveview()['leftcol']) + norm! 2zL + call assert_equal(26, col('.')) + norm! yl + call assert_equal('z', @0) + call assert_equal(15, winsaveview()['leftcol']) + + " Test for zH + norm! 2zH + call assert_equal(15, col('.')) + call assert_equal(0, winsaveview()['leftcol']) + norm! yl + call assert_equal('o', @0) + + " Test for zs + norm! $zs + call assert_equal(26, col('.')) + call assert_equal(20, winsaveview()['leftcol']) + norm! yl + call assert_equal('z', @0) + + " Test for ze + norm! ze + call assert_equal(26, col('.')) + call assert_equal(11, winsaveview()['leftcol']) + norm! yl + call assert_equal('z', @0) + + " cleanup + set wrap listchars=eol:$ sidescrolloff=0 + bw! +endfunc + +func! Test_normal18_z_fold() + " basic tests for foldopen/folddelete + if !has("folding") + return + endif + call Setup_NewWindow() + 50 + setl foldenable fdm=marker foldlevel=5 + + " Test for zF + " First fold + norm! 4zF + " check that folds have been created + call assert_equal(['50/*{{{*/', '51', '52', '53/*}}}*/'], getline(50,53)) + + " Test for zd + 51 + norm! 2zF + call assert_equal(2, foldlevel('.')) + norm! kzd + call assert_equal(['50', '51/*{{{*/', '52/*}}}*/', '53'], getline(50,53)) + norm! j + call assert_equal(1, foldlevel('.')) + + " Test for zD + " also deletes partially selected folds recursively + 51 + norm! zF + call assert_equal(2, foldlevel('.')) + norm! kV2jzD + call assert_equal(['50', '51', '52', '53'], getline(50,53)) + + " Test for zE + 85 + norm! 4zF + 86 + norm! 2zF + 90 + norm! 4zF + call assert_equal(['85/*{{{*/', '86/*{{{*/', '87/*}}}*/', '88/*}}}*/', '89', '90/*{{{*/', '91', '92', '93/*}}}*/'], getline(85,93)) + norm! zE + call assert_equal(['85', '86', '87', '88', '89', '90', '91', '92', '93'], getline(85,93)) + + " Test for zn + 50 + set foldlevel=0 + norm! 2zF + norm! zn + norm! k + call assert_equal('49', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + call assert_equal(0, &foldenable) + + " Test for zN + 49 + norm! zN + call assert_equal('49', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + call assert_equal(1, &foldenable) + + " Test for zi + norm! zi + call assert_equal(0, &foldenable) + norm! zi + call assert_equal(1, &foldenable) + norm! zi + call assert_equal(0, &foldenable) + norm! zi + call assert_equal(1, &foldenable) + + " Test for za + 50 + norm! za + norm! k + call assert_equal('49', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + 50 + norm! za + norm! k + call assert_equal('49', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + + 49 + norm! 5zF + norm! k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + 49 + norm! za + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + set nofoldenable + " close fold and set foldenable + norm! za + call assert_equal(1, &foldenable) + + 50 + " have to use {count}za to open all folds and make the cursor visible + norm! 2za + norm! 2k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + + " Test for zA + 49 + set foldlevel=0 + 50 + norm! zA + norm! 2k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + + " zA on a opened fold when foldenale is not set + 50 + set nofoldenable + norm! zA + call assert_equal(1, &foldenable) + norm! k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " Test for zc + norm! zE + 50 + norm! 2zF + 49 + norm! 5zF + set nofoldenable + 50 + " There most likely is a bug somewhere: + " https://groups.google.com/d/msg/vim_dev/v2EkfJ_KQjI/u-Cvv94uCAAJ + " TODO: Should this only close the inner most fold or both folds? + norm! zc + call assert_equal(1, &foldenable) + norm! k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + set nofoldenable + 50 + norm! Vjzc + norm! k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " Test for zC + set nofoldenable + 50 + norm! zCk + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " Test for zx + " 1) close folds at line 49-54 + set nofoldenable + 48 + norm! zx + call assert_equal(1, &foldenable) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " 2) do not close fold under curser + 51 + set nofoldenable + norm! zx + call assert_equal(1, &foldenable) + norm! 3k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + norm! j + call assert_equal('53', getline('.')) + norm! j + call assert_equal('54/*}}}*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " 3) close one level of folds + 48 + set nofoldenable + set foldlevel=1 + norm! zx + call assert_equal(1, &foldenable) + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + norm! j + call assert_equal('53', getline('.')) + norm! j + call assert_equal('54/*}}}*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " Test for zX + " Close all folds + set foldlevel=0 nofoldenable + 50 + norm! zX + call assert_equal(1, &foldenable) + norm! k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " Test for zm + 50 + set nofoldenable foldlevel=2 + norm! zm + call assert_equal(1, &foldenable) + call assert_equal(1, &foldlevel) + norm! zm + call assert_equal(0, &foldlevel) + norm! zm + call assert_equal(0, &foldlevel) + norm! k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " Test for zM + 48 + set nofoldenable foldlevel=99 + norm! zM + call assert_equal(1, &foldenable) + call assert_equal(0, &foldlevel) + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " Test for zr + 48 + set nofoldenable foldlevel=0 + norm! zr + call assert_equal(0, &foldenable) + call assert_equal(1, &foldlevel) + set foldlevel=0 foldenable + norm! zr + call assert_equal(1, &foldenable) + call assert_equal(1, &foldlevel) + norm! zr + call assert_equal(2, &foldlevel) + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + + " Test for zR + 48 + set nofoldenable foldlevel=0 + norm! zR + call assert_equal(0, &foldenable) + call assert_equal(2, &foldlevel) + set foldenable foldlevel=0 + norm! zR + call assert_equal(1, &foldenable) + call assert_equal(2, &foldlevel) + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + call append(50, ['a /*{{{*/', 'b /*}}}*/']) + 48 + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('a /*{{{*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + 48 + norm! zR + call assert_equal(1, &foldenable) + call assert_equal(3, &foldlevel) + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('a /*{{{*/', getline('.')) + norm! j + call assert_equal('b /*}}}*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + + " clean up + setl nofoldenable fdm=marker foldlevel=0 + bw! +endfunc + +func! Test_normal19_z_spell() + throw "skipped: Nvim 'spell' requires download" + if !has("spell") || !has('syntax') + return + endif + new + call append(0, ['1 good', '2 goood', '3 goood']) + set spell spellfile=./Xspellfile.add spelllang=en + let oldlang=v:lang + lang C + + " Test for zg + 1 + norm! ]s + call assert_equal('2 goood', getline('.')) + norm! zg + 1 + let a=execute('unsilent :norm! ]s') + call assert_equal('1 good', getline('.')) + call assert_equal('search hit BOTTOM, continuing at TOP', a[1:]) + let cnt=readfile('./Xspellfile.add') + call assert_equal('goood', cnt[0]) + + " Test for zw + 2 + norm! $zw + 1 + norm! ]s + call assert_equal('2 goood', getline('.')) + let cnt=readfile('./Xspellfile.add') + call assert_equal('#oood', cnt[0]) + call assert_equal('goood/!', cnt[1]) + + " Test for zg in visual mode + let a=execute('unsilent :norm! V$zg') + call assert_equal("Word '2 goood' added to ./Xspellfile.add", a[1:]) + 1 + norm! ]s + call assert_equal('3 goood', getline('.')) + let cnt=readfile('./Xspellfile.add') + call assert_equal('2 goood', cnt[2]) + " Remove "2 good" from spellfile + 2 + let a=execute('unsilent norm! V$zw') + call assert_equal("Word '2 goood' added to ./Xspellfile.add", a[1:]) + let cnt=readfile('./Xspellfile.add') + call assert_equal('2 goood/!', cnt[3]) + + " Test for zG + let a=execute('unsilent norm! V$zG') + call assert_match("Word '2 goood' added to .*", a) + let fname=matchstr(a, 'to\s\+\zs\f\+$') + let cnt=readfile(fname) + call assert_equal('2 goood', cnt[0]) + + " Test for zW + let a=execute('unsilent norm! V$zW') + call assert_match("Word '2 goood' added to .*", a) + let cnt=readfile(fname) + call assert_equal('# goood', cnt[0]) + call assert_equal('2 goood/!', cnt[1]) + + " Test for zuW + let a=execute('unsilent norm! V$zuW') + call assert_match("Word '2 goood' removed from .*", a) + let cnt=readfile(fname) + call assert_equal('# goood', cnt[0]) + call assert_equal('# goood/!', cnt[1]) + + " Test for zuG + let a=execute('unsilent norm! $zG') + call assert_match("Word 'goood' added to .*", a) + let cnt=readfile(fname) + call assert_equal('# goood', cnt[0]) + call assert_equal('# goood/!', cnt[1]) + call assert_equal('goood', cnt[2]) + let a=execute('unsilent norm! $zuG') + let cnt=readfile(fname) + call assert_match("Word 'goood' removed from .*", a) + call assert_equal('# goood', cnt[0]) + call assert_equal('# goood/!', cnt[1]) + call assert_equal('#oood', cnt[2]) + " word not found in wordlist + let a=execute('unsilent norm! V$zuG') + let cnt=readfile(fname) + call assert_match("", a) + call assert_equal('# goood', cnt[0]) + call assert_equal('# goood/!', cnt[1]) + call assert_equal('#oood', cnt[2]) + + " Test for zug + call delete('./Xspellfile.add') + 2 + let a=execute('unsilent norm! $zg') + let cnt=readfile('./Xspellfile.add') + call assert_equal('goood', cnt[0]) + let a=execute('unsilent norm! $zug') + call assert_match("Word 'goood' removed from \./Xspellfile.add", a) + let cnt=readfile('./Xspellfile.add') + call assert_equal('#oood', cnt[0]) + " word not in wordlist + let a=execute('unsilent norm! V$zug') + call assert_match('', a) + let cnt=readfile('./Xspellfile.add') + call assert_equal('#oood', cnt[0]) + + " Test for zuw + call delete('./Xspellfile.add') + 2 + let a=execute('unsilent norm! Vzw') + let cnt=readfile('./Xspellfile.add') + call assert_equal('2 goood/!', cnt[0]) + let a=execute('unsilent norm! Vzuw') + call assert_match("Word '2 goood' removed from \./Xspellfile.add", a) + let cnt=readfile('./Xspellfile.add') + call assert_equal('# goood/!', cnt[0]) + " word not in wordlist + let a=execute('unsilent norm! $zug') + call assert_match('', a) + let cnt=readfile('./Xspellfile.add') + call assert_equal('# goood/!', cnt[0]) + + " add second entry to spellfile setting + set spellfile=./Xspellfile.add,./Xspellfile2.add + call delete('./Xspellfile.add') + 2 + let a=execute('unsilent norm! $2zg') + let cnt=readfile('./Xspellfile2.add') + call assert_match("Word 'goood' added to ./Xspellfile2.add", a) + call assert_equal('goood', cnt[0]) + + " clean up + exe "lang" oldlang + call delete("./Xspellfile.add") + call delete("./Xspellfile2.add") + call delete("./Xspellfile.add.spl") + call delete("./Xspellfile2.add.spl") + + " zux -> no-op + 2 + norm! $zux + call assert_equal([], glob('Xspellfile.add',0,1)) + call assert_equal([], glob('Xspellfile2.add',0,1)) + + set spellfile= + bw! +endfunc + +func! Test_normal20_exmode() + if !has("unix") + " Reading from redirected file doesn't work on MS-Windows + return + endif + call writefile(['1a', 'foo', 'bar', '.', 'w! Xfile2', 'q!'], 'Xscript') + call writefile(['1', '2'], 'Xfile') + call system(v:progpath .' -e -s < Xscript Xfile') + let a=readfile('Xfile2') + call assert_equal(['1', 'foo', 'bar', '2'], a) + + " clean up + for file in ['Xfile', 'Xfile2', 'Xscript'] + call delete(file) + endfor + bw! +endfunc + +func! Test_normal21_nv_hat() + set hidden + new + " to many buffers opened already, will not work + "call assert_fails(":b#", 'E23') + "call assert_equal('', @#) + e Xfoobar + e Xfile2 + call feedkeys("\<c-^>", 't') + call assert_equal("Xfile2", fnamemodify(bufname('%'), ':t')) + call feedkeys("f\<c-^>", 't') + call assert_equal("Xfile2", fnamemodify(bufname('%'), ':t')) + " clean up + set nohidden + bw! +endfunc + +func! Test_normal22_zet() + " Test for ZZ + " let shell = &shell + " let &shell = 'sh' + + " Remove any stale test files from previous run. + for file in ['Xfile_Test_normal22_zet'] + call delete(file) + endfor + + call writefile(['1', '2'], 'Xfile_Test_normal22_zet') + let args = ' --headless -u NONE -N -U NONE -i NONE --noplugins' + call system(v:progpath . args . ' -c "%d" -c ":norm! ZZ" Xfile_Test_normal22_zet') + let a = readfile('Xfile_Test_normal22_zet') + call assert_equal([], a) + " Test for ZQ + call writefile(['1', '2'], 'Xfile_Test_normal22_zet') + call system(v:progpath . args . ' -c "%d" -c ":norm! ZQ" Xfile_Test_normal22_zet') + let a = readfile('Xfile_Test_normal22_zet') + call assert_equal(['1', '2'], a) + + " Nvim: This sometimes hangs the TSAN build. + " for file in ['Xfile_Test_normal22_zet'] + " call delete(file) + " endfor + " let &shell = shell +endfunc + +func! Test_normal23_K() + " Test for K command + new + call append(0, ['helphelp.txt', 'man', 'aa%bb', 'cc|dd']) + let k = &keywordprg + set keywordprg=:help + 1 + norm! VK + call assert_equal('helphelp.txt', fnamemodify(bufname('%'), ':t')) + call assert_equal('help', &ft) + call assert_match('\*helphelp.txt\*', getline('.')) + helpclose + norm! 0K + call assert_equal('helphelp.txt', fnamemodify(bufname('%'), ':t')) + call assert_equal('help', &ft) + call assert_match('Help on help files', getline('.')) + helpclose + + set keywordprg=:new + set iskeyword+=% + set iskeyword+=\| + 2 + norm! K + call assert_equal('man', fnamemodify(bufname('%'), ':t')) + bwipe! + 3 + norm! K + call assert_equal('aa%bb', fnamemodify(bufname('%'), ':t')) + bwipe! + if !has('win32') + 4 + norm! K + call assert_equal('cc|dd', fnamemodify(bufname('%'), ':t')) + bwipe! + endif + set iskeyword-=% + set iskeyword-=\| + + " Only expect "man" to work on Unix + if !has("unix") + let &keywordprg = k + bw! + return + endif + set keywordprg=man\ --pager=cat + " Test for using man + 2 + let a = execute('unsilent norm! K') + call assert_match("man --pager=cat 'man'", a) + + " clean up + let &keywordprg = k + bw! +endfunc + +func! Test_normal24_rot13() + " This test uses multi byte characters + if !has("multi_byte") + return + endif + " Testing for g?? g?g? + new + call append(0, 'abcdefghijklmnopqrstuvwxyzäüö') + 1 + norm! g?? + call assert_equal('nopqrstuvwxyzabcdefghijklmäüö', getline('.')) + norm! g?g? + call assert_equal('abcdefghijklmnopqrstuvwxyzäüö', getline('.')) + + " clean up + bw! +endfunc + +func! Test_normal25_tag() + " Testing for CTRL-] g CTRL-] g] + " CTRL-W g] CTRL-W CTRL-] CTRL-W g CTRL-] + h + " Test for CTRL-] + call search('\<x\>$') + exe "norm! \<c-]>" + call assert_equal("change.txt", fnamemodify(bufname('%'), ':t')) + norm! yiW + call assert_equal("*x*", @0) + exe ":norm \<c-o>" + + " Test for g_CTRL-] + call search('\<v_u\>$') + exe "norm! g\<c-]>" + call assert_equal("change.txt", fnamemodify(bufname('%'), ':t')) + norm! yiW + call assert_equal("*v_u*", @0) + exe ":norm \<c-o>" + + " Test for g] + call search('\<i_<Esc>$') + let a = execute(":norm! g]") + call assert_match('i_<Esc>.*insert.txt', a) + + if !empty(exepath('cscope')) && has('cscope') + " setting cscopetag changes how g] works + set cst + exe "norm! g]" + call assert_equal("insert.txt", fnamemodify(bufname('%'), ':t')) + norm! yiW + call assert_equal("*i_<Esc>*", @0) + exe ":norm \<c-o>" + " Test for CTRL-W g] + exe "norm! \<C-W>g]" + call assert_equal("insert.txt", fnamemodify(bufname('%'), ':t')) + norm! yiW + call assert_equal("*i_<Esc>*", @0) + call assert_equal(3, winnr('$')) + helpclose + set nocst + endif + + " Test for CTRL-W g] + let a = execute("norm! \<C-W>g]") + call assert_match('i_<Esc>.*insert.txt', a) + + " Test for CTRL-W CTRL-] + exe "norm! \<C-W>\<C-]>" + call assert_equal("insert.txt", fnamemodify(bufname('%'), ':t')) + norm! yiW + call assert_equal("*i_<Esc>*", @0) + call assert_equal(3, winnr('$')) + helpclose + + " Test for CTRL-W g CTRL-] + exe "norm! \<C-W>g\<C-]>" + call assert_equal("insert.txt", fnamemodify(bufname('%'), ':t')) + norm! yiW + call assert_equal("*i_<Esc>*", @0) + call assert_equal(3, winnr('$')) + helpclose + + " clean up + helpclose +endfunc + +func! Test_normal26_put() + " Test for ]p ]P [p and [P + new + call append(0, ['while read LINE', 'do', ' ((count++))', ' if [ $? -ne 0 ]; then', " echo 'Error writing file'", ' fi', 'done']) + 1 + /Error/y a + 2 + norm! "a]pj"a[p + call assert_equal(['do', "echo 'Error writing file'", " echo 'Error writing file'", ' ((count++))'], getline(2,5)) + 1 + /^\s\{4}/ + exe "norm! \"a]P3Eldt'" + exe "norm! j\"a[P2Eldt'" + call assert_equal([' if [ $? -ne 0 ]; then', " echo 'Error writing'", " echo 'Error'", " echo 'Error writing file'", ' fi'], getline(6,10)) + + " clean up + bw! +endfunc + +func! Test_normal27_bracket() + " Test for [' [` ]' ]` + call Setup_NewWindow() + 1,21s/.\+/ & b/ + 1 + norm! $ma + 5 + norm! $mb + 10 + norm! $mc + 15 + norm! $md + 20 + norm! $me + + " Test for [' + 9 + norm! 2[' + call assert_equal(' 1 b', getline('.')) + call assert_equal(1, line('.')) + call assert_equal(3, col('.')) + + " Test for ]' + norm! ]' + call assert_equal(' 5 b', getline('.')) + call assert_equal(5, line('.')) + call assert_equal(3, col('.')) + + " No mark after line 21, cursor moves to first non blank on current line + 21 + norm! $]' + call assert_equal(' 21 b', getline('.')) + call assert_equal(21, line('.')) + call assert_equal(3, col('.')) + + " Test for [` + norm! 2[` + call assert_equal(' 15 b', getline('.')) + call assert_equal(15, line('.')) + call assert_equal(8, col('.')) + + " Test for ]` + norm! ]` + call assert_equal(' 20 b', getline('.')) + call assert_equal(20, line('.')) + call assert_equal(8, col('.')) + + " clean up + bw! +endfunc + +func! Test_normal28_parenthesis() + " basic testing for ( and ) + new + call append(0, ['This is a test. With some sentences!', '', 'Even with a question? And one more. And no sentence here']) + + $ + norm! d( + call assert_equal(['This is a test. With some sentences!', '', 'Even with a question? And one more. ', ''], getline(1, '$')) + norm! 2d( + call assert_equal(['This is a test. With some sentences!', '', ' ', ''], getline(1, '$')) + 1 + norm! 0d) + call assert_equal(['With some sentences!', '', ' ', ''], getline(1, '$')) + + call append('$', ['This is a long sentence', '', 'spanning', 'over several lines. ']) + $ + norm! $d( + call assert_equal(['With some sentences!', '', ' ', '', 'This is a long sentence', ''], getline(1, '$')) + + " clean up + bw! +endfunc + +fun! Test_normal29_brace() + " basic test for { and } movements + let text= ['A paragraph begins after each empty line, and also at each of a set of', + \ 'paragraph macros, specified by the pairs of characters in the ''paragraphs''', + \ 'option. The default is "IPLPPPQPP TPHPLIPpLpItpplpipbp", which corresponds to', + \ 'the macros ".IP", ".LP", etc. (These are nroff macros, so the dot must be in', + \ 'the first column). A section boundary is also a paragraph boundary.', + \ 'Note that a blank line (only containing white space) is NOT a paragraph', + \ 'boundary.', + \ '', + \ '', + \ 'Also note that this does not include a ''{'' or ''}'' in the first column. When', + \ 'the ''{'' flag is in ''cpoptions'' then ''{'' in the first column is used as a', + \ 'paragraph boundary |posix|.', + \ '{', + \ 'This is no paragaraph', + \ 'unless the ''{'' is set', + \ 'in ''cpoptions''', + \ '}', + \ '.IP', + \ 'The nroff macros IP seperates a paragraph', + \ 'That means, it must be a ''.''', + \ 'followed by IP', + \ '.LPIt does not matter, if afterwards some', + \ 'more characters follow.', + \ '.SHAlso section boundaries from the nroff', + \ 'macros terminate a paragraph. That means', + \ 'a character like this:', + \ '.NH', + \ 'End of text here'] + new + call append(0, text) + 1 + norm! 0d2} + call assert_equal(['.IP', + \ 'The nroff macros IP seperates a paragraph', 'That means, it must be a ''.''', 'followed by IP', + \ '.LPIt does not matter, if afterwards some', 'more characters follow.', '.SHAlso section boundaries from the nroff', + \ 'macros terminate a paragraph. That means', 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$')) + norm! 0d} + call assert_equal(['.LPIt does not matter, if afterwards some', 'more characters follow.', + \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means', + \ 'a character like this:', '.NH', 'End of text here', ''], getline(1, '$')) + $ + norm! d{ + call assert_equal(['.LPIt does not matter, if afterwards some', 'more characters follow.', + \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means', 'a character like this:', ''], getline(1, '$')) + norm! d{ + call assert_equal(['.LPIt does not matter, if afterwards some', 'more characters follow.', ''], getline(1,'$')) + " Test with { in cpooptions + %d + call append(0, text) + " Nvim: no "{" flag in 'cpoptions'. + " set cpo+={ + " 1 + " norm! 0d2} + " call assert_equal(['{', 'This is no paragaraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', + " \ '.IP', 'The nroff macros IP seperates a paragraph', 'That means, it must be a ''.''', + " \ 'followed by IP', '.LPIt does not matter, if afterwards some', 'more characters follow.', + " \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means', + " \ 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$')) + " $ + " norm! d} + " call assert_equal(['{', 'This is no paragaraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', + " \ '.IP', 'The nroff macros IP seperates a paragraph', 'That means, it must be a ''.''', + " \ 'followed by IP', '.LPIt does not matter, if afterwards some', 'more characters follow.', + " \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means', + " \ 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$')) + " norm! gg} + " norm! d5} + " call assert_equal(['{', 'This is no paragaraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', ''], getline(1,'$')) + + " clean up + set cpo-={ + bw! +endfunc + +fun! Test_normal30_changecase() + " This test uses multi byte characters + if !has("multi_byte") + return + endif + new + call append(0, 'This is a simple test: äüöß') + norm! 1ggVu + call assert_equal('this is a simple test: äüöß', getline('.')) + norm! VU + call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.')) + norm! guu + call assert_equal('this is a simple test: äüöss', getline('.')) + norm! gUgU + call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.')) + norm! gugu + call assert_equal('this is a simple test: äüöss', getline('.')) + norm! gUU + call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.')) + norm! 010~ + call assert_equal('this is a SIMPLE TEST: ÄÜÖSS', getline('.')) + norm! V~ + call assert_equal('THIS IS A simple test: äüöss', getline('.')) + + " Turkish ASCII turns to multi-byte. On some systems Turkish locale + " is available but toupper()/tolower() don't do the right thing. + try + lang tr_TR.UTF-8 + set casemap= + let iupper = toupper('i') + if iupper == "\u0130" + call setline(1, 'iI') + 1normal gUU + call assert_equal("\u0130I", getline(1)) + call assert_equal("\u0130I", toupper("iI")) + + call setline(1, 'iI') + 1normal guu + call assert_equal("i\u0131", getline(1)) + call assert_equal("i\u0131", tolower("iI")) + elseif iupper == "I" + call setline(1, 'iI') + 1normal gUU + call assert_equal("II", getline(1)) + call assert_equal("II", toupper("iI")) + + call setline(1, 'iI') + 1normal guu + call assert_equal("ii", getline(1)) + call assert_equal("ii", tolower("iI")) + else + call assert_true(false, "expected toupper('i') to be either 'I' or '\u0131'") + endif + set casemap& + call setline(1, 'iI') + 1normal gUU + call assert_equal("II", getline(1)) + call assert_equal("II", toupper("iI")) + + call setline(1, 'iI') + 1normal guu + call assert_equal("ii", getline(1)) + call assert_equal("ii", tolower("iI")) + + lang en_US.UTF-8 + catch /E197:/ + " can't use Turkish locale + throw 'Skipped: Turkish locale not available' + endtry + + " clean up + bw! +endfunc + +fun! Test_normal31_r_cmd() + " Test for r command + new + call append(0, 'This is a simple test: abcd') + exe "norm! 1gg$r\<cr>" + call assert_equal(['This is a simple test: abc', '', ''], getline(1,'$')) + exe "norm! 1gg2wlr\<cr>" + call assert_equal(['This is a', 'simple test: abc', '', ''], getline(1,'$')) + exe "norm! 2gg0W5r\<cr>" + call assert_equal(['This is a', 'simple ', ' abc', '', ''], getline('1', '$')) + set autoindent + call setline(2, ['simple test: abc', '']) + exe "norm! 2gg0W5r\<cr>" + call assert_equal(['This is a', 'simple ', 'abc', '', '', ''], getline('1', '$')) + exe "norm! 1ggVr\<cr>" + call assert_equal('^M^M^M^M^M^M^M^M^M', strtrans(getline(1))) + call setline(1, 'This is a') + exe "norm! 1gg05rf" + call assert_equal('fffffis a', getline(1)) + + " clean up + set noautoindent + bw! +endfunc + +func! Test_normal32_g_cmd1() + " Test for g*, g# + new + call append(0, ['abc.x_foo', 'x_foobar.abc']) + 1 + norm! $g* + call assert_equal('x_foo', @/) + call assert_equal('x_foobar.abc', getline('.')) + norm! $g# + call assert_equal('abc', @/) + call assert_equal('abc.x_foo', getline('.')) + + " clean up + bw! +endfunc + +fun! Test_normal33_g_cmd2() + if !has("jumplist") + return + endif + " Tests for g cmds + call Setup_NewWindow() + " Test for g` + clearjumps + norm! ma10j + let a=execute(':jumps') + " empty jumplist + call assert_equal('>', a[-1:]) + norm! g`a + call assert_equal('>', a[-1:]) + call assert_equal(1, line('.')) + call assert_equal('1', getline('.')) + + " Test for g; and g, + norm! g; + " there is only one change in the changelist + " currently, when we setup the window + call assert_equal(2, line('.')) + call assert_fails(':norm! g;', 'E662') + call assert_fails(':norm! g,', 'E663') + let &ul=&ul + call append('$', ['a', 'b', 'c', 'd']) + let &ul=&ul + call append('$', ['Z', 'Y', 'X', 'W']) + let a = execute(':changes') + call assert_match('2\s\+0\s\+2', a) + call assert_match('101\s\+0\s\+a', a) + call assert_match('105\s\+0\s\+Z', a) + norm! 3g; + call assert_equal(2, line('.')) + norm! 2g, + call assert_equal(105, line('.')) + + " Test for g& - global substitute + %d + call setline(1, range(1,10)) + call append('$', ['a', 'b', 'c', 'd']) + $s/\w/&&/g + exe "norm! /[1-8]\<cr>" + norm! g& + call assert_equal(['11', '22', '33', '44', '55', '66', '77', '88', '9', '110', 'a', 'b', 'c', 'dd'], getline(1, '$')) + + " Test for gv + %d + call append('$', repeat(['abcdefgh'], 8)) + exe "norm! 2gg02l\<c-v>2j2ly" + call assert_equal(['cde', 'cde', 'cde'], getreg(0, 1, 1)) + " in visual mode, gv swaps current and last selected region + exe "norm! G0\<c-v>4k4lgvd" + call assert_equal(['', 'abfgh', 'abfgh', 'abfgh', 'abcdefgh', 'abcdefgh', 'abcdefgh', 'abcdefgh', 'abcdefgh'], getline(1,'$')) + exe "norm! G0\<c-v>4k4ly" + exe "norm! gvood" + call assert_equal(['', 'abfgh', 'abfgh', 'abfgh', 'fgh', 'fgh', 'fgh', 'fgh', 'fgh'], getline(1,'$')) + + " Test for gk/gj + %d + 15vsp + set wrap listchars= sbr= + let lineA='abcdefghijklmnopqrstuvwxyz' + let lineB='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + $put =lineA + $put =lineB + + norm! 3gg0dgk + call assert_equal(['', 'abcdefghijklmno', '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'], getline(1, '$')) + set nu + norm! 3gg0gjdgj + call assert_equal(['', 'abcdefghijklmno', '0123456789AMNOPQRSTUVWXYZ'], getline(1,'$')) + + " Test for gJ + norm! 2gggJ + call assert_equal(['', 'abcdefghijklmno0123456789AMNOPQRSTUVWXYZ'], getline(1,'$')) + call assert_equal(16, col('.')) + " shouldn't do anything + norm! 10gJ + call assert_equal(1, col('.')) + + " Test for g0 g^ gm g$ + exe "norm! 2gg0gji " + call assert_equal(['', 'abcdefghijk lmno0123456789AMNOPQRSTUVWXYZ'], getline(1,'$')) + norm! g0yl + call assert_equal(12, col('.')) + call assert_equal(' ', getreg(0)) + norm! g$yl + call assert_equal(22, col('.')) + call assert_equal('3', getreg(0)) + norm! gmyl + call assert_equal(17, col('.')) + call assert_equal('n', getreg(0)) + norm! g^yl + call assert_equal(15, col('.')) + call assert_equal('l', getreg(0)) + + " Test for g Ctrl-G + set ff=unix + let a=execute(":norm! g\<c-g>") + call assert_match('Col 15 of 43; Line 2 of 2; Word 2 of 2; Byte 16 of 45', a) + + " Test for gI + norm! gIfoo + call assert_equal(['', 'fooabcdefghijk lmno0123456789AMNOPQRSTUVWXYZ'], getline(1,'$')) + + " Test for gi + wincmd c + %d + set tw=0 + call setline(1, ['foobar', 'new line']) + norm! A next word + $put ='third line' + norm! gi another word + call assert_equal(['foobar next word another word', 'new line', 'third line'], getline(1,'$')) + + " clean up + bw! +endfunc + +fun! Test_normal34_g_cmd3() + if !has("multi_byte") + return + endif + " Test for g8 + new + call append(0, 'abcdefghijklmnopqrstuvwxyzäüö') + let a=execute(':norm! 1gg$g8') + call assert_equal('c3 b6 ', a[1:]) + + " Test for gp gP + call append(1, range(1,10)) + " clean up + bw! +endfunc + +fun! Test_normal35_g_cmd4() + " Test for g< + " Cannot capture its output, + " probably a bug, therefore, test disabled: + throw "Skipped: output of g< can't be tested currently" + echo "a\nb\nc\nd" + let b=execute(':norm! g<') + call assert_true(!empty(b), 'failed `execute(g<)`') +endfunc + +fun! Test_normal36_g_cmd5() + new + call append(0, 'abcdefghijklmnopqrstuvwxyz') + set ff=unix + " Test for gp gP + call append(1, range(1,10)) + 1 + norm! 1yy + 3 + norm! gp + call assert_equal([0, 5, 1, 0, 1], getcurpos()) + $ + norm! gP + call assert_equal([0, 14, 1, 0, 1], getcurpos()) + + " Test for go + norm! 26go + call assert_equal([0, 1, 26, 0, 26], getcurpos()) + norm! 27go + call assert_equal([0, 1, 26, 0, 26], getcurpos()) + norm! 28go + call assert_equal([0, 2, 1, 0, 1], getcurpos()) + set ff=dos + norm! 29go + call assert_equal([0, 2, 1, 0, 1], getcurpos()) + set ff=unix + norm! gg0 + norm! 101go + call assert_equal([0, 13, 26, 0, 26], getcurpos()) + norm! 103go + call assert_equal([0, 14, 1, 0, 1], getcurpos()) + " count > buffer content + norm! 120go + call assert_equal([0, 14, 1, 0, 2147483647], getcurpos()) + " clean up + bw! +endfunc + +fun! Test_normal37_g_cmd6() + " basic test for gt and gT + tabnew 1.txt + tabnew 2.txt + tabnew 3.txt + norm! 1gt + call assert_equal(1, tabpagenr()) + norm! 3gt + call assert_equal(3, tabpagenr()) + norm! 1gT + " count gT goes not to the absolute tabpagenumber + " but, but goes to the count previous tabpagenumber + call assert_equal(2, tabpagenr()) + " wrap around + norm! 3gT + call assert_equal(3, tabpagenr()) + " gt does not wrap around + norm! 5gt + call assert_equal(3, tabpagenr()) + + for i in range(3) + tabclose + endfor + " clean up + call assert_fails(':tabclose', 'E784') +endfunc + +fun! Test_normal38_nvhome() + " Test for <Home> and <C-Home> key + new + call setline(1, range(10)) + $ + setl et sw=2 + norm! V10>$ + " count is ignored + exe "norm! 10\<home>" + call assert_equal(1, col('.')) + exe "norm! \<home>" + call assert_equal([0, 10, 1, 0, 1], getcurpos()) + exe "norm! 5\<c-home>" + call assert_equal([0, 5, 1, 0, 1], getcurpos()) + exe "norm! \<c-home>" + call assert_equal([0, 1, 1, 0, 1], getcurpos()) + + " clean up + bw! +endfunc + +fun! Test_normal39_cw() + " Test for cw and cW on whitespace + " and cpo+=w setting + new + set tw=0 + call append(0, 'here are some words') + norm! 1gg0elcwZZZ + call assert_equal('hereZZZare some words', getline('.')) + norm! 1gg0elcWYYY + call assert_equal('hereZZZareYYYsome words', getline('.')) + " Nvim: no "w" flag in 'cpoptions'. + " set cpo+=w + " call setline(1, 'here are some words') + " norm! 1gg0elcwZZZ + " call assert_equal('hereZZZ are some words', getline('.')) + " norm! 1gg2elcWYYY + " call assert_equal('hereZZZ areYYY some words', getline('.')) + set cpo-=w + norm! 2gg0cwfoo + call assert_equal('foo', getline('.')) + + " clean up + bw! +endfunc + +fun! Test_normal40_ctrl_bsl() + " Basic test for CTRL-\ commands + new + call append(0, 'here are some words') + exe "norm! 1gg0a\<C-\>\<C-N>" + call assert_equal('n', mode()) + call assert_equal(1, col('.')) + call assert_equal('', visualmode()) + exe "norm! 1gg0viw\<C-\>\<C-N>" + call assert_equal('n', mode()) + call assert_equal(4, col('.')) + exe "norm! 1gg0a\<C-\>\<C-G>" + call assert_equal('n', mode()) + call assert_equal(1, col('.')) + "imap <buffer> , <c-\><c-n> + set im + exe ":norm! \<c-\>\<c-n>dw" + set noim + call assert_equal('are some words', getline(1)) + call assert_false(&insertmode) + + " clean up + bw! +endfunc + +fun! Test_normal41_insert_reg() + " Test for <c-r>=, <c-r><c-r>= and <c-r><c-o>= + " in insert mode + new + set sts=2 sw=2 ts=8 tw=0 + call append(0, ["aaa\tbbb\tccc", '', '', '']) + let a=getline(1) + norm! 2gg0 + exe "norm! a\<c-r>=a\<cr>" + norm! 3gg0 + exe "norm! a\<c-r>\<c-r>=a\<cr>" + norm! 4gg0 + exe "norm! a\<c-r>\<c-o>=a\<cr>" + call assert_equal(['aaa bbb ccc', 'aaa bbb ccc', 'aaa bbb ccc', 'aaa bbb ccc', ''], getline(1, '$')) + + " clean up + set sts=0 sw=8 ts=8 + bw! +endfunc + +func! Test_normal42_halfpage() + " basic test for Ctrl-D and Ctrl-U + call Setup_NewWindow() + call assert_equal(5, &scroll) + exe "norm! \<c-d>" + call assert_equal('6', getline('.')) + exe "norm! 2\<c-d>" + call assert_equal('8', getline('.')) + call assert_equal(2, &scroll) + set scroll=5 + exe "norm! \<c-u>" + call assert_equal('3', getline('.')) + 1 + set scrolloff=5 + exe "norm! \<c-d>" + call assert_equal('10', getline('.')) + exe "norm! \<c-u>" + call assert_equal('5', getline('.')) + 1 + set scrolloff=99 + exe "norm! \<c-d>" + call assert_equal('10', getline('.')) + set scrolloff=0 + 100 + exe "norm! $\<c-u>" + call assert_equal('95', getline('.')) + call assert_equal([0, 95, 1, 0, 1], getcurpos()) + 100 + set nostartofline + exe "norm! $\<c-u>" + call assert_equal('95', getline('.')) + call assert_equal([0, 95, 2, 0, 2147483647], getcurpos()) + " cleanup + set startofline + bw! +endfunc + +fun! Test_normal43_textobject1() + " basic tests for text object aw + new + call append(0, ['foobar,eins,foobar', 'foo,zwei,foo ']) + " diw + norm! 1gg0diw + call assert_equal([',eins,foobar', 'foo,zwei,foo ', ''], getline(1,'$')) + " daw + norm! 2ggEdaw + call assert_equal([',eins,foobar', 'foo,zwei,', ''], getline(1, '$')) + %d + call append(0, ["foo\teins\tfoobar", "foo\tzwei\tfoo "]) + " diW + norm! 2ggwd2iW + call assert_equal(['foo eins foobar', 'foo foo ', ''], getline(1,'$')) + " daW + norm! 1ggd2aW + call assert_equal(['foobar', 'foo foo ', ''], getline(1,'$')) + + %d + call append(0, ["foo\teins\tfoobar", "foo\tzwei\tfoo "]) + " aw in visual line mode switches to characterwise mode + norm! 2gg$Vawd + call assert_equal(['foo eins foobar', 'foo zwei foo'], getline(1,'$')) + norm! 1gg$Viwd + call assert_equal(['foo eins ', 'foo zwei foo'], getline(1,'$')) + + " clean up + bw! +endfunc + +func! Test_normal44_textobjects2() + " basic testing for is and as text objects + new + call append(0, ['This is a test. With some sentences!', '', 'Even with a question? And one more. And no sentence here']) + " Test for dis - does not remove trailing whitespace + norm! 1gg0dis + call assert_equal([' With some sentences!', '', 'Even with a question? And one more. And no sentence here', ''], getline(1,'$')) + " Test for das - removes leading whitespace + norm! 3ggf?ldas + call assert_equal([' With some sentences!', '', 'Even with a question? And no sentence here', ''], getline(1,'$')) + " when used in visual mode, is made characterwise + norm! 3gg$Visy + call assert_equal('v', visualmode()) + " reset visualmode() + norm! 3ggVy + norm! 3gg$Vasy + call assert_equal('v', visualmode()) + " basic testing for textobjects a< and at + %d + call setline(1, ['<div> ','<a href="foobar" class="foo">xyz</a>',' </div>', ' ']) + " a< + norm! 1gg0da< + call assert_equal([' ', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$')) + norm! 1pj + call assert_equal([' <div>', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$')) + " at + norm! d2at + call assert_equal([' '], getline(1,'$')) + %d + call setline(1, ['<div> ','<a href="foobar" class="foo">xyz</a>',' </div>', ' ']) + " i< + norm! 1gg0di< + call assert_equal(['<> ', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$')) + norm! 1Pj + call assert_equal(['<div> ', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$')) + norm! d2it + call assert_equal(['<div></div>',' '], getline(1,'$')) + " basic testing for a[ and i[ text object + %d + call setline(1, [' ', '[', 'one [two]', 'thre', ']']) + norm! 3gg0di[ + call assert_equal([' ', '[', ']'], getline(1,'$')) + call setline(1, [' ', '[', 'one [two]', 'thre', ']']) + norm! 3gg0ftd2a[ + call assert_equal([' '], getline(1,'$')) + %d + " Test for i" when cursor is in front of a quoted object + call append(0, 'foo "bar"') + norm! 1gg0di" + call assert_equal(['foo ""', ''], getline(1,'$')) + + " clean up + bw! +endfunc + +func! Test_normal45_drop() + if !has("dnd") + return + endif + " basic test for :drop command + " unfortunately, without a gui, we can't really test much here, + " so simply test that ~p fails (which uses the drop register) + new + call assert_fails(':norm! "~p', 'E353') + call assert_equal([], getreg('~', 1, 1)) + " the ~ register is read only + call assert_fails(':let @~="1"', 'E354') + bw! +endfunc + +func! Test_normal46_ignore() + " This test uses multi byte characters + if !has("multi_byte") + return + endif + + new + " How to test this? + " let's just for now test, that the buffer + " does not change + call feedkeys("\<c-s>", 't') + call assert_equal([''], getline(1,'$')) + + " no valid commands + exe "norm! \<char-0x100>" + call assert_equal([''], getline(1,'$')) + + exe "norm! ä" + call assert_equal([''], getline(1,'$')) + + " clean up + bw! +endfunc + +func! Test_normal47_visual_buf_wipe() + " This was causing a crash or ml_get error. + enew! + call setline(1,'xxx') + normal $ + new + call setline(1, range(1,2)) + 2 + exe "norm \<C-V>$" + bw! + norm yp + set nomodified +endfunc + +func! Test_normal47_autocmd() + " disabled, does not seem to be possible currently + throw "Skipped: not possible to test cursorhold autocmd while waiting for input in normal_cmd" + new + call append(0, repeat('-',20)) + au CursorHold * call feedkeys('2l', '') + 1 + set updatetime=20 + " should delete 12 chars (d12l) + call feedkeys('d1', '!') + call assert_equal('--------', getline(1)) + + " clean up + au! CursorHold + set updatetime=4000 + bw! +endfunc + +func! Test_normal48_wincmd() + new + exe "norm! \<c-w>c" + call assert_equal(1, winnr('$')) + call assert_fails(":norm! \<c-w>c", "E444") +endfunc + +func! Test_normal49_counts() + new + call setline(1, 'one two three four five six seven eight nine ten') + 1 + norm! 3d2w + call assert_equal('seven eight nine ten', getline(1)) + bw! +endfunc + +func! Test_normal50_commandline() + if !has("timers") || !has("cmdline_hist") || !has("vertsplit") + return + endif + func! DoTimerWork(id) + call assert_equal('[Command Line]', bufname('')) + " should fail, with E11, but does fail with E23? + "call feedkeys("\<c-^>", 'tm') + + " should also fail with E11 + call assert_fails(":wincmd p", 'E11') + " return from commandline window + call feedkeys("\<cr>") + endfunc + + let oldlang=v:lang + lang C + set updatetime=20 + call timer_start(100, 'DoTimerWork') + try + " throws E23, for whatever reason... + call feedkeys('q:', 'x!') + catch /E23/ + " no-op + endtry + " clean up + set updatetime=4000 + exe "lang" oldlang + bw! +endfunc + +func! Test_normal51_FileChangedRO() + if !has("autocmd") + return + endif + call writefile(['foo'], 'Xreadonly.log') + new Xreadonly.log + setl ro + au FileChangedRO <buffer> :call feedkeys("\<c-^>", 'tix') + call assert_fails(":norm! Af", 'E788') + call assert_equal(['foo'], getline(1,'$')) + call assert_equal('Xreadonly.log', bufname('')) + + " cleanup + bw! + call delete("Xreadonly.log") +endfunc + +func! Test_normal52_rl() + if !has("rightleft") + return + endif + new + call setline(1, 'abcde fghij klmnopq') + norm! 1gg$ + set rl + call assert_equal(19, col('.')) + call feedkeys('l', 'tx') + call assert_equal(18, col('.')) + call feedkeys('h', 'tx') + call assert_equal(19, col('.')) + call feedkeys("\<right>", 'tx') + call assert_equal(18, col('.')) + call feedkeys("\<s-right>", 'tx') + call assert_equal(13, col('.')) + call feedkeys("\<c-right>", 'tx') + call assert_equal(7, col('.')) + call feedkeys("\<c-left>", 'tx') + call assert_equal(13, col('.')) + call feedkeys("\<s-left>", 'tx') + call assert_equal(19, col('.')) + call feedkeys("<<", 'tx') + call assert_equal(' abcde fghij klmnopq',getline(1)) + call feedkeys(">>", 'tx') + call assert_equal('abcde fghij klmnopq',getline(1)) + + " cleanup + set norl + bw! +endfunc + +func! Test_normal53_digraph() + if !has('digraphs') + return + endif + new + call setline(1, 'abcdefgh|') + exe "norm! 1gg0f\<c-k>!!" + call assert_equal(9, col('.')) + set cpo+=D + exe "norm! 1gg0f\<c-k>!!" + call assert_equal(1, col('.')) + + set cpo-=D + bw! +endfunc + +func! Test_normal54_Ctrl_bsl() + new + call setline(1, 'abcdefghijklmn') + exe "norm! df\<c-\>\<c-n>" + call assert_equal(['abcdefghijklmn'], getline(1,'$')) + exe "norm! df\<c-\>\<c-g>" + call assert_equal(['abcdefghijklmn'], getline(1,'$')) + exe "norm! df\<c-\>m" + call assert_equal(['abcdefghijklmn'], getline(1,'$')) + if !has("multi_byte") + return + endif + call setline(2, 'abcdefghijklmnÄf') + norm! 2gg0 + exe "norm! df\<Char-0x101>" + call assert_equal(['abcdefghijklmn', 'f'], getline(1,'$')) + norm! 1gg0 + exe "norm! df\<esc>" + call assert_equal(['abcdefghijklmn', 'f'], getline(1,'$')) + + " clean up + bw! +endfunc diff --git a/src/nvim/testdir/test_partial.vim b/src/nvim/testdir/test_partial.vim index 3a6e162453..de5c26c2dd 100644 --- a/src/nvim/testdir/test_partial.vim +++ b/src/nvim/testdir/test_partial.vim @@ -14,6 +14,14 @@ func MySort(up, one, two) return a:one < a:two ? 1 : -1 endfunc +func MyMap(sub, index, val) + return a:val - a:sub +endfunc + +func MyFilter(threshold, index, val) + return a:val > a:threshold +endfunc + func Test_partial_args() let Cb = function('MyFunc', ["foo", "bar"]) @@ -36,6 +44,16 @@ func Test_partial_args() call assert_equal([1, 2, 3], sort([3, 1, 2], Sort)) let Sort = function('MySort', [0]) call assert_equal([3, 2, 1], sort([3, 1, 2], Sort)) + + let Map = function('MyMap', [2]) + call assert_equal([-1, 0, 1], map([1, 2, 3], Map)) + let Map = function('MyMap', [3]) + call assert_equal([-2, -1, 0], map([1, 2, 3], Map)) + + let Filter = function('MyFilter', [1]) + call assert_equal([2, 3], filter([1, 2, 3], Filter)) + let Filter = function('MyFilter', [2]) + call assert_equal([3], filter([1, 2, 3], Filter)) endfunc func MyDictFunc(arg1, arg2) dict @@ -59,6 +77,9 @@ func Test_partial_dict() call assert_equal("hello/xxx/yyy", Cb("xxx", "yyy")) call assert_fails('Cb("fff")', 'E492:') + let Cb = function('MyDictFunc', dict) + call assert_equal({"foo": "hello/foo/1", "bar": "hello/bar/2"}, map({"foo": 1, "bar": 2}, Cb)) + let dict = {"tr": function('tr', ['hello', 'h', 'H'])} call assert_equal("Hello", dict.tr()) endfunc diff --git a/src/nvim/testdir/test_popup.vim b/src/nvim/testdir/test_popup.vim index 50110dd622..e1ba142d1c 100644 --- a/src/nvim/testdir/test_popup.vim +++ b/src/nvim/testdir/test_popup.vim @@ -7,10 +7,10 @@ func! ListMonths() if g:setting != '' exe ":set" g:setting endif - let mth=copy(g:months) + let mth = copy(g:months) let entered = strcharpart(getline('.'),0,col('.')) if !empty(entered) - let mth=filter(mth, 'v:val=~"^".entered') + let mth = filter(mth, 'v:val=~"^".entered') endif call complete(1, mth) return '' @@ -468,7 +468,7 @@ endfunc " auto-wrap text. func Test_completion_ctrl_e_without_autowrap() new - let tw_save=&tw + let tw_save = &tw set tw=78 let li = [ \ '" zzz', @@ -478,8 +478,96 @@ func Test_completion_ctrl_e_without_autowrap() call feedkeys("A\<C-X>\<C-N>\<C-E>\<Esc>", "tx") call assert_equal(li, getline(1, '$')) - let &tw=tw_save + let &tw = tw_save q! endfunc +func Test_completion_respect_bs_option() + new + let li = ["aaa", "aaa12345", "aaaabcdef", "aaaABC"] + + set bs=indent,eol + call setline(1, li) + 1 + call feedkeys("A\<C-X>\<C-N>\<C-P>\<BS>\<BS>\<BS>\<Esc>", "tx") + call assert_equal('aaa', getline(1)) + + %d + set bs=indent,eol,start + call setline(1, li) + 1 + call feedkeys("A\<C-X>\<C-N>\<C-P>\<BS>\<BS>\<BS>\<Esc>", "tx") + call assert_equal('', getline(1)) + + bw! +endfunc + +func CompleteUndo() abort + call complete(1, g:months) + return '' +endfunc + +func Test_completion_can_undo() + inoremap <Right> <c-r>=CompleteUndo()<cr> + set completeopt+=noinsert,noselect + + new + call feedkeys("a\<Right>a\<Esc>", 'xt') + call assert_equal('a', getline(1)) + undo + call assert_equal('', getline(1)) + + bwipe! + set completeopt& + iunmap <Right> +endfunc + +func Test_completion_comment_formatting() + new + setl formatoptions=tcqro + call feedkeys("o/*\<cr>\<cr>/\<esc>", 'tx') + call assert_equal(['', '/*', ' *', ' */'], getline(1,4)) + %d + call feedkeys("o/*\<cr>foobar\<cr>/\<esc>", 'tx') + call assert_equal(['', '/*', ' * foobar', ' */'], getline(1,4)) + %d + try + call feedkeys("o/*\<cr>\<cr>\<c-x>\<c-u>/\<esc>", 'tx') + call assert_report('completefunc not set, should have failed') + catch + call assert_exception('E764:') + endtry + call assert_equal(['', '/*', ' *', ' */'], getline(1,4)) + bwipe! +endfunc + +function! DummyCompleteSix() + call complete(1, ['Hello', 'World']) + return '' +endfunction + +" complete() correctly clears the list of autocomplete candidates +func Test_completion_clear_candidate_list() + new + %d + " select first entry from the completion popup + call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>", "tx") + call assert_equal('Hello', getline(1)) + %d + " select second entry from the completion popup + call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>", "tx") + call assert_equal('World', getline(1)) + %d + " select original text + call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>\<C-N>", "tx") + call assert_equal(' xxx', getline(1)) + %d + " back at first entry from completion list + call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>\<C-N>\<C-N>", "tx") + call assert_equal('Hello', getline(1)) + + bw! +endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index f30902b915..aff5fc2eed 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -6,7 +6,7 @@ endif set encoding=utf-8 -function! s:setup_commands(cchar) +func s:setup_commands(cchar) if a:cchar == 'c' command! -nargs=* -bang Xlist <mods>clist<bang> <args> command! -nargs=* Xgetexpr <mods>cgetexpr <args> @@ -68,10 +68,10 @@ function! s:setup_commands(cchar) let g:Xgetlist = function('getloclist', [0]) let g:Xsetlist = function('setloclist', [0]) endif -endfunction +endfunc " Tests for the :clist and :llist commands -function XlistTests(cchar) +func XlistTests(cchar) call s:setup_commands(a:cchar) " With an empty list, command should return error @@ -128,17 +128,17 @@ function XlistTests(cchar) let l = split(result, "\n") call assert_equal([' 2 Xtestfile1:1 col 3: Line1', \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l) -endfunction +endfunc -function Test_clist() +func Test_clist() call XlistTests('c') call XlistTests('l') -endfunction +endfunc " Tests for the :colder, :cnewer, :lolder and :lnewer commands " Note that this test assumes that a quickfix/location list is " already set by the caller. -function XageTests(cchar) +func XageTests(cchar) call s:setup_commands(a:cchar) " Jumping to a non existent list should return error @@ -171,20 +171,20 @@ function XageTests(cchar) Xnewer 2 let l = g:Xgetlist() call assert_equal('Line3', l[0].text) -endfunction +endfunc -function Test_cage() +func Test_cage() let list = [{'bufnr': 1, 'lnum': 1}] call setqflist(list) call XageTests('c') call setloclist(0, list) call XageTests('l') -endfunction +endfunc " Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen " commands -function XwindowTests(cchar) +func XwindowTests(cchar) call s:setup_commands(a:cchar) " Create a list with no valid entries @@ -227,16 +227,16 @@ function XwindowTests(cchar) " Calling cwindow should close the quickfix window with no valid errors Xwindow call assert_true(winnr('$') == 1) -endfunction +endfunc -function Test_cwindow() +func Test_cwindow() call XwindowTests('c') call XwindowTests('l') -endfunction +endfunc " Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile " commands. -function XfileTests(cchar) +func XfileTests(cchar) call s:setup_commands(a:cchar) call writefile(['Xtestfile1:700:10:Line 700', @@ -275,16 +275,16 @@ function XfileTests(cchar) \ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333') call delete('Xqftestfile1') -endfunction +endfunc -function Test_cfile() +func Test_cfile() call XfileTests('c') call XfileTests('l') -endfunction +endfunc " Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and " :lgetbuffer commands. -function XbufferTests(cchar) +func XbufferTests(cchar) call s:setup_commands(a:cchar) enew! @@ -316,26 +316,26 @@ function XbufferTests(cchar) \ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750') enew! -endfunction +endfunc -function Test_cbuffer() +func Test_cbuffer() call XbufferTests('c') call XbufferTests('l') -endfunction +endfunc -function XexprTests(cchar) +func XexprTests(cchar) call s:setup_commands(a:cchar) call assert_fails('Xexpr 10', 'E777:') -endfunction +endfunc -function Test_cexpr() +func Test_cexpr() call XexprTests('c') call XexprTests('l') -endfunction +endfunc " Tests for :cnext, :cprev, :cfirst, :clast commands -function Xtest_browse(cchar) +func Xtest_browse(cchar) call s:setup_commands(a:cchar) call s:create_test_file('Xqftestfile1') @@ -366,14 +366,14 @@ function Xtest_browse(cchar) call delete('Xqftestfile1') call delete('Xqftestfile2') -endfunction +endfunc -function Test_browse() +func Test_browse() call Xtest_browse('c') call Xtest_browse('l') -endfunction +endfunc -function! s:test_xhelpgrep(cchar) +func s:test_xhelpgrep(cchar) call s:setup_commands(a:cchar) Xhelpgrep quickfix Xopen @@ -385,10 +385,11 @@ function! s:test_xhelpgrep(cchar) call assert_true(w:quickfix_title =~ title_text, w:quickfix_title) " This wipes out the buffer, make sure that doesn't cause trouble. Xclose -endfunction +endfunc -function Test_helpgrep() +func Test_helpgrep() call s:test_xhelpgrep('c') + helpclose call s:test_xhelpgrep('l') endfunc @@ -424,7 +425,7 @@ func Test_vimgreptitle() augroup! QfBufWinEnter endfunc -function XqfTitleTests(cchar) +func XqfTitleTests(cchar) call s:setup_commands(a:cchar) Xgetexpr ['file:1:1:message'] @@ -443,16 +444,16 @@ function XqfTitleTests(cchar) endif call assert_equal(title, w:quickfix_title) Xclose -endfunction +endfunc " Tests for quickfix window's title -function Test_qf_title() +func Test_qf_title() call XqfTitleTests('c') call XqfTitleTests('l') -endfunction +endfunc " Tests for 'errorformat' -function Test_efm() +func Test_efm() let save_efm = &efm set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%# cgetexpr ['WWWW', 'EEEE', 'CCCC'] @@ -465,7 +466,7 @@ function Test_efm() let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]'))) call assert_equal("[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]", l) let &efm = save_efm -endfunction +endfunc " This will test for problems in quickfix: " A. incorrectly copying location lists which caused the location list to show @@ -476,7 +477,7 @@ endfunction " window it belongs to. " " Set up the test environment: -function! ReadTestProtocol(name) +func ReadTestProtocol(name) let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '') let word = substitute(base, '\v(.*)\..*', '\1', '') @@ -495,9 +496,9 @@ function! ReadTestProtocol(name) setl nomodifiable setl readonly exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '') -endfunction +endfunc -function Test_locationlist() +func Test_locationlist() enew augroup testgroup @@ -577,15 +578,15 @@ function Test_locationlist() wincmd n | only augroup! testgroup -endfunction + endfunc -function Test_locationlist_curwin_was_closed() +func Test_locationlist_curwin_was_closed() augroup testgroup au! autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>")) augroup END - function! R(n) + func! R(n) quit endfunc @@ -596,10 +597,26 @@ function Test_locationlist_curwin_was_closed() call assert_fails('lrewind', 'E924:') augroup! testgroup -endfunction + endfunc + +func Test_locationlist_cross_tab_jump() + call writefile(['loclistfoo'], 'loclistfoo') + call writefile(['loclistbar'], 'loclistbar') + set switchbuf=usetab + + edit loclistfoo + tabedit loclistbar + silent lgrep loclistfoo loclist* + call assert_equal(1, tabpagenr()) + + enew | only | tabonly + set switchbuf&vim + call delete('loclistfoo') + call delete('loclistbar') +endfunc " More tests for 'errorformat' -function! Test_efm1() +func Test_efm1() if !has('unix') " The 'errorformat' setting is different on non-Unix systems. " This test works only on Unix-like systems. @@ -717,10 +734,10 @@ function! Test_efm1() call delete('Xerrorfile1') call delete('Xerrorfile2') call delete('Xtestfile') -endfunction + endfunc " Test for quickfix directory stack support -function! s:dir_stack_tests(cchar) +func s:dir_stack_tests(cchar) call s:setup_commands(a:cchar) let save_efm=&efm @@ -762,10 +779,10 @@ function! s:dir_stack_tests(cchar) call assert_equal(5, qf[11].lnum) let &efm=save_efm -endfunction +endfunc " Tests for %D and %X errorformat options -function! Test_efm_dirstack() +func Test_efm_dirstack() " Create the directory stack and files call mkdir('dir1') call mkdir('dir1/a') @@ -797,10 +814,33 @@ function! Test_efm_dirstack() call delete('dir1', 'rf') call delete('dir2', 'rf') call delete('habits1.txt') -endfunction +endfunc + +" Test for resync after continuing an ignored message +func Xefm_ignore_continuations(cchar) + call s:setup_commands(a:cchar) + + let save_efm = &efm + + let &efm = + \ '%Eerror %m %l,' . + \ '%-Wignored %m %l,' . + \ '%+Cmore ignored %m %l,' . + \ '%Zignored end' + Xgetexpr ['ignored warning 1', 'more ignored continuation 2', 'ignored end', 'error resync 4'] + let l = map(g:Xgetlist(), '[v:val.text, v:val.valid, v:val.lnum, v:val.type]') + call assert_equal([['resync', 1, 4, 'E']], l) + + let &efm = save_efm +endfunc + +func Test_efm_ignore_continuations() + call Xefm_ignore_continuations('c') + call Xefm_ignore_continuations('l') +endfunc " Tests for invalid error format specifies -function Xinvalid_efm_Tests(cchar) +func Xinvalid_efm_Tests(cchar) call s:setup_commands(a:cchar) let save_efm = &efm @@ -833,17 +873,17 @@ function Xinvalid_efm_Tests(cchar) call assert_fails('Xexpr ["Entering dir abc", "abc.txt:1:Hello world"]', 'E379:') let &efm = save_efm -endfunction +endfunc -function Test_invalid_efm() +func Test_invalid_efm() call Xinvalid_efm_Tests('c') call Xinvalid_efm_Tests('l') -endfunction +endfunc " TODO: " Add tests for the following formats in 'errorformat' " %r %O -function! Test_efm2() +func Test_efm2() let save_efm = &efm " Test for %s format in efm @@ -904,20 +944,44 @@ function! Test_efm2() call assert_equal('E', l[0].type) call assert_equal("\nunknown variable 'i'", l[0].text) + " Test for %A, %C and other formats + let lines = [ + \"==============================================================", + \"FAIL: testGetTypeIdCachesResult (dbfacadeTest.DjsDBFacadeTest)", + \"--------------------------------------------------------------", + \"Traceback (most recent call last):", + \' File "unittests/dbfacadeTest.py", line 89, in testFoo', + \" self.assertEquals(34, dtid)", + \' File "/usr/lib/python2.2/unittest.py", line 286, in', + \" failUnlessEqual", + \" raise self.failureException, \\", + \"AssertionError: 34 != 33", + \"", + \"--------------------------------------------------------------", + \"Ran 27 tests in 0.063s" + \] + set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m + cgetexpr lines + let l = getqflist() + call assert_equal(8, len(l)) + call assert_equal(89, l[4].lnum) + call assert_equal(1, l[4].valid) + call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr)) + let &efm = save_efm -endfunction +endfunc -function XquickfixChangedByAutocmd(cchar) +func XquickfixChangedByAutocmd(cchar) call s:setup_commands(a:cchar) if a:cchar == 'c' let ErrorNr = 'E925' - function! ReadFunc() + func! ReadFunc() colder cgetexpr [] endfunc else let ErrorNr = 'E926' - function! ReadFunc() + func! ReadFunc() lolder lgetexpr [] endfunc @@ -940,10 +1004,10 @@ function XquickfixChangedByAutocmd(cchar) augroup! testgroup endfunc -function Test_quickfix_was_changed_by_autocmd() +func Test_quickfix_was_changed_by_autocmd() call XquickfixChangedByAutocmd('c') call XquickfixChangedByAutocmd('l') -endfunction +endfunc func Test_caddbuffer_to_empty() helpgr quickfix @@ -965,7 +1029,7 @@ func Test_cgetexpr_works() endfunc " Tests for the setqflist() and setloclist() functions -function SetXlistTests(cchar, bnum) +func SetXlistTests(cchar, bnum) call s:setup_commands(a:cchar) call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1}, @@ -1000,9 +1064,9 @@ function SetXlistTests(cchar, bnum) call g:Xsetlist([]) let l = g:Xgetlist() call assert_equal(0, len(l)) -endfunction +endfunc -function Test_setqflist() +func Test_setqflist() new Xtestfile | only let bnum = bufnr('%') call setline(1, range(1,5)) @@ -1012,9 +1076,9 @@ function Test_setqflist() enew! call delete('Xtestfile') -endfunction +endfunc -function Xlist_empty_middle(cchar) +func Xlist_empty_middle(cchar) call s:setup_commands(a:cchar) " create three quickfix lists @@ -1037,12 +1101,12 @@ function Xlist_empty_middle(cchar) call assert_equal(matchlen, len(g:Xgetlist())) endfunc -function Test_setqflist_empty_middle() +func Test_setqflist_empty_middle() call Xlist_empty_middle('c') call Xlist_empty_middle('l') -endfunction +endfunc -function Xlist_empty_older(cchar) +func Xlist_empty_older(cchar) call s:setup_commands(a:cchar) " create three quickfix lists @@ -1063,14 +1127,14 @@ function Xlist_empty_older(cchar) call assert_equal(twolen, len(g:Xgetlist())) Xnewer call assert_equal(threelen, len(g:Xgetlist())) -endfunction +endfunc -function Test_setqflist_empty_older() +func Test_setqflist_empty_older() call Xlist_empty_older('c') call Xlist_empty_older('l') -endfunction +endfunc -function! XquickfixSetListWithAct(cchar) +func XquickfixSetListWithAct(cchar) call s:setup_commands(a:cchar) let list1 = [{'filename': 'fnameA', 'text': 'A'}, @@ -1144,12 +1208,12 @@ function! XquickfixSetListWithAct(cchar) call assert_fails("call g:Xsetlist(list1, 0)", 'E928:') endfunc -function Test_quickfix_set_list_with_act() +func Test_quickfix_set_list_with_act() call XquickfixSetListWithAct('c') call XquickfixSetListWithAct('l') -endfunction +endfunc -function XLongLinesTests(cchar) +func XLongLinesTests(cchar) let l = g:Xgetlist() call assert_equal(4, len(l)) @@ -1167,9 +1231,9 @@ function XLongLinesTests(cchar) call assert_equal(10, len(l[3].text)) call g:Xsetlist([], 'r') -endfunction +endfunc -function s:long_lines_tests(cchar) +func s:long_lines_tests(cchar) call s:setup_commands(a:cchar) let testfile = 'samples/quickfix.txt' @@ -1190,22 +1254,22 @@ function s:long_lines_tests(cchar) exe 'edit' testfile exe 'Xbuffer' bufnr('%') call XLongLinesTests(a:cchar) -endfunction +endfunc -function Test_long_lines() +func Test_long_lines() call s:long_lines_tests('c') call s:long_lines_tests('l') -endfunction +endfunc -function! s:create_test_file(filename) +func s:create_test_file(filename) let l = [] for i in range(1, 20) call add(l, 'Line' . i) endfor call writefile(l, a:filename) -endfunction +endfunc -function! Test_switchbuf() +func Test_switchbuf() call s:create_test_file('Xqftestfile1') call s:create_test_file('Xqftestfile2') call s:create_test_file('Xqftestfile3') @@ -1292,20 +1356,21 @@ function! Test_switchbuf() call delete('Xqftestfile1') call delete('Xqftestfile2') call delete('Xqftestfile3') -endfunction +endfunc -function! Xadjust_qflnum(cchar) +func Xadjust_qflnum(cchar) call s:setup_commands(a:cchar) enew | only - call s:create_test_file('Xqftestfile') - edit Xqftestfile + let fname = 'Xqftestfile' . a:cchar + call s:create_test_file(fname) + exe 'edit ' . fname - Xgetexpr ['Xqftestfile:5:Line5', - \ 'Xqftestfile:10:Line10', - \ 'Xqftestfile:15:Line15', - \ 'Xqftestfile:20:Line20'] + Xgetexpr [fname . ':5:Line5', + \ fname . ':10:Line10', + \ fname . ':15:Line15', + \ fname . ':20:Line20'] 6,14delete call append(6, ['Buffer', 'Window']) @@ -1317,16 +1382,18 @@ function! Xadjust_qflnum(cchar) call assert_equal(13, l[3].lnum) enew! - call delete('Xqftestfile') -endfunction + call delete(fname) +endfunc -function! Test_adjust_lnum() +func Test_adjust_lnum() + call setloclist(0, []) call Xadjust_qflnum('c') + call setqflist([]) call Xadjust_qflnum('l') -endfunction +endfunc " Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands -function! s:test_xgrep(cchar) +func s:test_xgrep(cchar) call s:setup_commands(a:cchar) " The following lines are used for the grep test. Don't remove. @@ -1345,9 +1412,9 @@ function! s:test_xgrep(cchar) set makeef=Temp_File_## silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim call assert_true(len(g:Xgetlist()) == 6) -endfunction +endfunc -function! Test_grep() +func Test_grep() if !has('unix') " The grepprg may not be set on non-Unix systems return @@ -1355,9 +1422,9 @@ function! Test_grep() call s:test_xgrep('c') call s:test_xgrep('l') -endfunction +endfunc -function! Test_two_windows() +func Test_two_windows() " Use one 'errorformat' for two windows. Add an expression to each of them, " make sure they each keep their own state. set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f' @@ -1383,12 +1450,10 @@ function! Test_two_windows() laddexpr 'one.txt:3:one one one' let loc_one = getloclist(one_id) -echo string(loc_one) call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr)) call assert_equal(3, loc_one[1].lnum) let loc_two = getloclist(two_id) -echo string(loc_two) call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr)) call assert_equal(5, loc_two[1].lnum) @@ -1400,7 +1465,7 @@ echo string(loc_two) call delete('Xtwo', 'rf') endfunc -function XbottomTests(cchar) +func XbottomTests(cchar) call s:setup_commands(a:cchar) call g:Xsetlist([{'filename': 'foo', 'lnum': 42}]) @@ -1416,7 +1481,195 @@ function XbottomTests(cchar) endfunc " Tests for the :cbottom and :lbottom commands -function Test_cbottom() +func Test_cbottom() call XbottomTests('c') call XbottomTests('l') -endfunction +endfunc + +func HistoryTest(cchar) + call s:setup_commands(a:cchar) + + call assert_fails(a:cchar . 'older 99', 'E380:') + " clear all lists after the first one, then replace the first one. + call g:Xsetlist([]) + Xolder + let entry = {'filename': 'foo', 'lnum': 42} + call g:Xsetlist([entry], 'r') + call g:Xsetlist([entry, entry]) + call g:Xsetlist([entry, entry, entry]) + let res = split(execute(a:cchar . 'hist'), "\n") + call assert_equal(3, len(res)) + let common = 'errors :set' . (a:cchar == 'c' ? 'qf' : 'loc') . 'list()' + call assert_equal(' error list 1 of 3; 1 ' . common, res[0]) + call assert_equal(' error list 2 of 3; 2 ' . common, res[1]) + call assert_equal('> error list 3 of 3; 3 ' . common, res[2]) +endfunc + +func Test_history() + call HistoryTest('c') + call HistoryTest('l') +endfunc + +func Test_duplicate_buf() + " make sure we can get the highest buffer number + edit DoesNotExist + edit DoesNotExist2 + let last_buffer = bufnr("$") + + " make sure only one buffer is created + call writefile(['this one', 'that one'], 'Xgrepthis') + vimgrep one Xgrepthis + vimgrep one Xgrepthis + call assert_equal(last_buffer + 1, bufnr("$")) + + call delete('Xgrepthis') +endfunc + +" Quickfix/Location list set/get properties tests +func Xproperty_tests(cchar) + call s:setup_commands(a:cchar) + + " Error cases + call assert_fails('call g:Xgetlist(99)', 'E715:') + call assert_fails('call g:Xsetlist(99)', 'E714:') + call assert_fails('call g:Xsetlist([], "a", [])', 'E715:') + + " Set and get the title + Xopen + wincmd p + call g:Xsetlist([{'filename':'foo', 'lnum':27}]) + call g:Xsetlist([], 'a', {'title' : 'Sample'}) + let d = g:Xgetlist({"title":1}) + call assert_equal('Sample', d.title) + + Xopen + call assert_equal('Sample', w:quickfix_title) + Xclose + + " Tests for action argument + silent! Xolder 999 + let qfnr = g:Xgetlist({'all':1}).nr + call g:Xsetlist([], 'r', {'title' : 'N1'}) + call assert_equal('N1', g:Xgetlist({'all':1}).title) + call g:Xsetlist([], ' ', {'title' : 'N2'}) + call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr) + + let res = g:Xgetlist({'nr': 0}) + call assert_equal(qfnr + 1, res.nr) + call assert_equal(['nr'], keys(res)) + + call g:Xsetlist([], ' ', {'title' : 'N3'}) + call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title) + + " Invalid arguments + call assert_fails('call g:Xgetlist([])', 'E715') + call assert_fails('call g:Xsetlist([], "a", [])', 'E715') + let s = g:Xsetlist([], 'a', {'abc':1}) + call assert_equal(-1, s) + + call assert_equal({}, g:Xgetlist({'abc':1})) + + if a:cchar == 'l' + call assert_equal({}, getloclist(99, {'title': 1})) + endif + endfunc + +func Test_qf_property() + call Xproperty_tests('c') + call Xproperty_tests('l') + endfunc + +" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands +func QfAutoCmdHandler(loc, cmd) + call add(g:acmds, a:loc . a:cmd) +endfunc + +func Test_Autocmd() + autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>')) + autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>')) + + let g:acmds = [] + cexpr "F1:10:Line 10" + caddexpr "F1:20:Line 20" + cgetexpr "F1:30:Line 30" + enew! | call append(0, "F2:10:Line 10") + cbuffer! + enew! | call append(0, "F2:20:Line 20") + cgetbuffer + enew! | call append(0, "F2:30:Line 30") + caddbuffer + + let l = ['precexpr', + \ 'postcexpr', + \ 'precaddexpr', + \ 'postcaddexpr', + \ 'precgetexpr', + \ 'postcgetexpr', + \ 'precbuffer', + \ 'postcbuffer', + \ 'precgetbuffer', + \ 'postcgetbuffer', + \ 'precaddbuffer', + \ 'postcaddbuffer'] + call assert_equal(l, g:acmds) +endfunc + +func Test_Autocmd_Exception() + set efm=%m + lgetexpr '?' + + try + call DoesNotExit() + catch + lgetexpr '1' + finally + lgetexpr '1' + endtry + + call assert_equal('1', getloclist(0)[0].text) + + set efm&vim +endfunc + +func Test_caddbuffer_wrong() + " This used to cause a memory access in freed memory. + let save_efm = &efm + set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.# + cgetexpr ['WWWW', 'EEEE', 'CCCC'] + let &efm = save_efm + caddbuffer + bwipe! +endfunc + +func Test_caddexpr_wrong() + " This used to cause a memory access in freed memory. + cbuffer + cbuffer + copen + let save_efm = &efm + set efm=% + call assert_fails('caddexpr ""', 'E376:') + let &efm = save_efm +endfunc + +func Test_dirstack_cleanup() + " This used to cause a memory access in freed memory. + let save_efm = &efm + lexpr '0' + lopen + fun X(c) + let save_efm=&efm + set efm=%D%f + if a:c == 'c' + caddexpr '::' + else + laddexpr ':0:0' + endif + let &efm=save_efm + endfun + call X('c') + call X('l') + call setqflist([], 'r') + caddbuffer + let &efm = save_efm +endfunc diff --git a/src/nvim/testdir/test_regexp_utf8.vim b/src/nvim/testdir/test_regexp_utf8.vim index ecb03a0f8c..a2f4286d4f 100644 --- a/src/nvim/testdir/test_regexp_utf8.vim +++ b/src/nvim/testdir/test_regexp_utf8.vim @@ -31,6 +31,65 @@ func Test_equivalence_re2() set re=0 endfunc +func s:classes_test() + set isprint=@,161-255 + call assert_equal('Motörhead', matchstr('Motörhead', '[[:print:]]\+')) + + let alphachars = '' + let lowerchars = '' + let upperchars = '' + let alnumchars = '' + let printchars = '' + let punctchars = '' + let xdigitchars = '' + let i = 1 + while i <= 255 + let c = nr2char(i) + if c =~ '[[:alpha:]]' + let alphachars .= c + endif + if c =~ '[[:lower:]]' + let lowerchars .= c + endif + if c =~ '[[:upper:]]' + let upperchars .= c + endif + if c =~ '[[:alnum:]]' + let alnumchars .= c + endif + if c =~ '[[:print:]]' + let printchars .= c + endif + if c =~ '[[:punct:]]' + let punctchars .= c + endif + if c =~ '[[:xdigit:]]' + let xdigitchars .= c + endif + let i += 1 + endwhile + + call assert_equal('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', alphachars) + call assert_equal('abcdefghijklmnopqrstuvwxyzµßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿ', lowerchars) + call assert_equal('ABCDEFGHIJKLMNOPQRSTUVWXYZÀÃÂÃÄÅÆÇÈÉÊËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞ', upperchars) + call assert_equal('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', alnumchars) + call assert_equal(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ¡¢£¤¥¦§¨©ª«¬Â®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÃÂÃÄÅÆÇÈÉÊËÌÃÃŽÃÃÑÒÓÔÕÖרÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõö÷øùúûüýþÿ', printchars) + call assert_equal('!"#$%&''()*+,-./:;<=>?@[\]^_`{|}~', punctchars) + call assert_equal('0123456789ABCDEFabcdef', xdigitchars) +endfunc + +func Test_classes_re1() + set re=1 + call s:classes_test() + set re=0 +endfunc + +func Test_classes_re2() + set re=2 + call s:classes_test() + set re=0 +endfunc + func Test_recursive_substitute() new s/^/\=execute("s#^##gn") @@ -38,3 +97,27 @@ func Test_recursive_substitute() call setwinvar(1, 'myvar', 1) bwipe! endfunc + +func Test_nested_backrefs() + " Check example in change.txt. + new + for re in range(0, 2) + exe 'set re=' . re + call setline(1, 'aa ab x') + 1s/\(\(a[a-d] \)*\)\(x\)/-\1- -\2- -\3-/ + call assert_equal('-aa ab - -ab - -x-', getline(1)) + + call assert_equal('-aa ab - -ab - -x-', substitute('aa ab x', '\(\(a[a-d] \)*\)\(x\)', '-\1- -\2- -\3-', '')) + endfor + bwipe! + set re=0 +endfunc + +func Test_eow_with_optional() + let expected = ['abc def', 'abc', 'def', '', '', '', '', '', '', ''] + for re in range(0, 2) + exe 'set re=' . re + let actual = matchlist('abc def', '\(abc\>\)\?\s*\(def\)') + call assert_equal(expected, actual) + endfor +endfunc diff --git a/src/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim new file mode 100644 index 0000000000..a333e7f206 --- /dev/null +++ b/src/nvim/testdir/test_search.vim @@ -0,0 +1,300 @@ +" Test for the search command + +func Test_search_cmdline() + " See test/functional/legacy/search_spec.lua + throw 'skipped: Nvim does not support test_disable_char_avail()' + if !exists('+incsearch') + return + endif + " need to disable char_avail, + " so that expansion of commandline works + call test_disable_char_avail(1) + new + call setline(1, [' 1', ' 2 these', ' 3 the', ' 4 their', ' 5 there', ' 6 their', ' 7 the', ' 8 them', ' 9 these', ' 10 foobar']) + " Test 1 + " CTRL-N / CTRL-P skips through the previous search history + set noincsearch + :1 + call feedkeys("/foobar\<cr>", 'tx') + call feedkeys("/the\<cr>",'tx') + call assert_equal('the', @/) + call feedkeys("/thes\<C-P>\<C-P>\<cr>",'tx') + call assert_equal('foobar', @/) + + " Test 2 + " Ctrl-G goes from one match to the next + " until the end of the buffer + set incsearch nowrapscan + :1 + " first match + call feedkeys("/the\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + :1 + " second match + call feedkeys("/the\<C-G>\<cr>", 'tx') + call assert_equal(' 3 the', getline('.')) + call assert_equal([0, 0, 0, 0], getpos('"')) + :1 + " third match + call feedkeys("/the".repeat("\<C-G>", 2)."\<cr>", 'tx') + call assert_equal(' 4 their', getline('.')) + :1 + " fourth match + call feedkeys("/the".repeat("\<C-G>", 3)."\<cr>", 'tx') + call assert_equal(' 5 there', getline('.')) + :1 + " fifth match + call feedkeys("/the".repeat("\<C-G>", 4)."\<cr>", 'tx') + call assert_equal(' 6 their', getline('.')) + :1 + " sixth match + call feedkeys("/the".repeat("\<C-G>", 5)."\<cr>", 'tx') + call assert_equal(' 7 the', getline('.')) + :1 + " seventh match + call feedkeys("/the".repeat("\<C-G>", 6)."\<cr>", 'tx') + call assert_equal(' 8 them', getline('.')) + :1 + " eigth match + call feedkeys("/the".repeat("\<C-G>", 7)."\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + :1 + " no further match + call feedkeys("/the".repeat("\<C-G>", 8)."\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + call assert_equal([0, 0, 0, 0], getpos('"')) + + " Test 3 + " Ctrl-G goes from one match to the next + " and continues back at the top + set incsearch wrapscan + :1 + " first match + call feedkeys("/the\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + :1 + " second match + call feedkeys("/the\<C-G>\<cr>", 'tx') + call assert_equal(' 3 the', getline('.')) + :1 + " third match + call feedkeys("/the".repeat("\<C-G>", 2)."\<cr>", 'tx') + call assert_equal(' 4 their', getline('.')) + :1 + " fourth match + call feedkeys("/the".repeat("\<C-G>", 3)."\<cr>", 'tx') + call assert_equal(' 5 there', getline('.')) + :1 + " fifth match + call feedkeys("/the".repeat("\<C-G>", 4)."\<cr>", 'tx') + call assert_equal(' 6 their', getline('.')) + :1 + " sixth match + call feedkeys("/the".repeat("\<C-G>", 5)."\<cr>", 'tx') + call assert_equal(' 7 the', getline('.')) + :1 + " seventh match + call feedkeys("/the".repeat("\<C-G>", 6)."\<cr>", 'tx') + call assert_equal(' 8 them', getline('.')) + :1 + " eigth match + call feedkeys("/the".repeat("\<C-G>", 7)."\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + :1 + " back at first match + call feedkeys("/the".repeat("\<C-G>", 8)."\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + + " Test 4 + " CTRL-T goes to the previous match + set incsearch nowrapscan + $ + " first match + call feedkeys("?the\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + $ + " first match + call feedkeys("?the\<C-G>\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + $ + " second match + call feedkeys("?the".repeat("\<C-T>", 1)."\<cr>", 'tx') + call assert_equal(' 8 them', getline('.')) + $ + " last match + call feedkeys("?the".repeat("\<C-T>", 7)."\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + $ + " last match + call feedkeys("?the".repeat("\<C-T>", 8)."\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + + " Test 5 + " CTRL-T goes to the previous match + set incsearch wrapscan + $ + " first match + call feedkeys("?the\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + $ + " first match at the top + call feedkeys("?the\<C-G>\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + $ + " second match + call feedkeys("?the".repeat("\<C-T>", 1)."\<cr>", 'tx') + call assert_equal(' 8 them', getline('.')) + $ + " last match + call feedkeys("?the".repeat("\<C-T>", 7)."\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + $ + " back at the bottom of the buffer + call feedkeys("?the".repeat("\<C-T>", 8)."\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + + " Test 6 + " CTRL-L adds to the search pattern + set incsearch wrapscan + 1 + " first match + call feedkeys("/the\<c-l>\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + 1 + " go to next match of 'thes' + call feedkeys("/the\<c-l>\<C-G>\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + 1 + " wrap around + call feedkeys("/the\<c-l>\<C-G>\<C-G>\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + 1 + " wrap around + set nowrapscan + call feedkeys("/the\<c-l>\<C-G>\<C-G>\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + + " Test 7 + " <bs> remove from match, but stay at current match + set incsearch wrapscan + 1 + " first match + call feedkeys("/thei\<cr>", 'tx') + call assert_equal(' 4 their', getline('.')) + 1 + " delete one char, add another + call feedkeys("/thei\<bs>s\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + 1 + " delete one char, add another, go to previous match, add one char + call feedkeys("/thei\<bs>s\<bs>\<C-T>\<c-l>\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + 1 + " delete all chars, start from the beginning again + call feedkeys("/them". repeat("\<bs>",4).'the\>'."\<cr>", 'tx') + call assert_equal(' 3 the', getline('.')) + + " clean up + call test_disable_char_avail(0) + bw! +endfunc + +func Test_search_cmdline2() + " See test/functional/legacy/search_spec.lua + throw 'skipped: Nvim does not support test_disable_char_avail()' + if !exists('+incsearch') + return + endif + " need to disable char_avail, + " so that expansion of commandline works + call test_disable_char_avail(1) + new + call setline(1, [' 1', ' 2 these', ' 3 the theother']) + " Test 1 + " Ctrl-T goes correctly back and forth + set incsearch + 1 + " first match + call feedkeys("/the\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + 1 + " go to next match (on next line) + call feedkeys("/the\<C-G>\<cr>", 'tx') + call assert_equal(' 3 the theother', getline('.')) + 1 + " go to next match (still on line 3) + call feedkeys("/the\<C-G>\<C-G>\<cr>", 'tx') + call assert_equal(' 3 the theother', getline('.')) + 1 + " go to next match (still on line 3) + call feedkeys("/the\<C-G>\<C-G>\<C-G>\<cr>", 'tx') + call assert_equal(' 3 the theother', getline('.')) + 1 + " go to previous match (on line 3) + call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<cr>", 'tx') + call assert_equal(' 3 the theother', getline('.')) + 1 + " go to previous match (on line 3) + call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<C-T>\<cr>", 'tx') + call assert_equal(' 3 the theother', getline('.')) + 1 + " go to previous match (on line 2) + call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<C-T>\<C-T>\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + + " Test 2: keep the view, + " after deleting a character from the search cmd + call setline(1, [' 1', ' 2 these', ' 3 the', ' 4 their', ' 5 there', ' 6 their', ' 7 the', ' 8 them', ' 9 these', ' 10 foobar']) + resize 5 + 1 + call feedkeys("/foo\<bs>\<cr>", 'tx') + redraw + call assert_equal({'lnum': 10, 'leftcol': 0, 'col': 4, 'topfill': 0, 'topline': 6, 'coladd': 0, 'skipcol': 0, 'curswant': 4}, winsaveview()) + + " remove all history entries + for i in range(10) + call histdel('/') + endfor + + " Test 3: reset the view, + " after deleting all characters from the search cmd + norm! 1gg0 + " unfortunately, neither "/foo\<c-w>\<cr>", nor "/foo\<bs>\<bs>\<bs>\<cr>", + " nor "/foo\<c-u>\<cr>" works to delete the commandline. + " In that case Vim should return "E35 no previous regular expression", + " but it looks like Vim still sees /foo and therefore the test fails. + " Therefore, disableing this test + "call assert_fails(feedkeys("/foo\<c-w>\<cr>", 'tx'), 'E35') + "call assert_equal({'lnum': 1, 'leftcol': 0, 'col': 0, 'topfill': 0, 'topline': 1, 'coladd': 0, 'skipcol': 0, 'curswant': 0}, winsaveview()) + + " clean up + set noincsearch + call test_disable_char_avail(0) + bw! +endfunc + +func Test_use_sub_pat() + split + let @/ = '' + func X() + s/^/a/ + / + endfunc + call X() + bwipe! +endfunc + +func Test_searchpair() + new + call setline(1, ['other code here', '', '[', '" cursor here', ']']) + 4 + let a=searchpair('\[','',']','bW') + call assert_equal(3, a) + set nomagic + 4 + let a=searchpair('\[','',']','bW') + call assert_equal(3, a) + set magic + q! +endfunc + diff --git a/src/nvim/testdir/test_smartindent.vim b/src/nvim/testdir/test_smartindent.vim new file mode 100644 index 0000000000..d00eac9798 --- /dev/null +++ b/src/nvim/testdir/test_smartindent.vim @@ -0,0 +1,14 @@ + +" Tests for not doing smart indenting when it isn't set. +function! Test_nosmartindent() + new + call append(0, [" some test text", + \ " test text", + \ "test text", + \ " test text"]) + set nocindent nosmartindent autoindent + exe "normal! gg/some\<CR>" + exe "normal! 2cc#test\<Esc>" + call assert_equal(" #test", getline(1)) + enew! | close +endfunction diff --git a/src/nvim/testdir/test_source_utf8.vim b/src/nvim/testdir/test_source_utf8.vim new file mode 100644 index 0000000000..edb76fc43d --- /dev/null +++ b/src/nvim/testdir/test_source_utf8.vim @@ -0,0 +1,33 @@ +" Test the :source! command +if !has('multi_byte') + finish +endif + +func Test_source_utf8() + " check that sourcing a script with 0x80 as second byte works + new + call setline(1, [':%s/à x/--à 1234--/g', ':%s/Àx/--À1234--/g']) + write! Xscript + bwipe! + new + call setline(1, [' à x ', ' Àx ']) + source! Xscript | echo + call assert_equal(' --à 1234-- ', getline(1)) + call assert_equal(' --À1234-- ', getline(2)) + bwipe! + call delete('Xscript') +endfunc + +func Test_source_latin() + " check that sourcing a latin1 script with a 0xc0 byte works + new + call setline(1, ["call feedkeys('r')", "call feedkeys('\xc0', 'xt')"]) + write! Xscript + bwipe! + new + call setline(1, ['xxx']) + source Xscript + call assert_equal("\u00c0xx", getline(1)) + bwipe! + call delete('Xscript') +endfunc diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim new file mode 100644 index 0000000000..11e26d03aa --- /dev/null +++ b/src/nvim/testdir/test_startup.vim @@ -0,0 +1,242 @@ +" Tests for startup. + +source shared.vim + +" Check that loading startup.vim works. +func Test_startup_script() + throw 'skipped: Nvim does not need defaults.vim' + set compatible + source $VIMRUNTIME/defaults.vim + + call assert_equal(0, &compatible) +endfunc + +" Verify the order in which plugins are loaded: +" 1. plugins in non-after directories +" 2. packages +" 3. plugins in after directories +func Test_after_comes_later() + if !has('packages') + return + endif + let before = [ + \ 'set nocp viminfo+=nviminfo', + \ 'set guioptions+=M', + \ 'let $HOME = "/does/not/exist"', + \ 'set loadplugins', + \ 'set rtp=Xhere,Xafter,Xanother', + \ 'set packpath=Xhere,Xafter', + \ 'set nomore', + \ 'let g:sequence = ""', + \ ] + let after = [ + \ 'redir! > Xtestout', + \ 'scriptnames', + \ 'redir END', + \ 'redir! > Xsequence', + \ 'echo g:sequence', + \ 'redir END', + \ 'quit', + \ ] + call mkdir('Xhere/plugin', 'p') + call writefile(['let g:sequence .= "here "'], 'Xhere/plugin/here.vim') + call mkdir('Xanother/plugin', 'p') + call writefile(['let g:sequence .= "another "'], 'Xanother/plugin/another.vim') + call mkdir('Xhere/pack/foo/start/foobar/plugin', 'p') + call writefile(['let g:sequence .= "pack "'], 'Xhere/pack/foo/start/foobar/plugin/foo.vim') + + call mkdir('Xafter/plugin', 'p') + call writefile(['let g:sequence .= "after "'], 'Xafter/plugin/later.vim') + + if RunVim(before, after, '') + + let lines = readfile('Xtestout') + let expected = ['Xbefore.vim', 'here.vim', 'another.vim', 'foo.vim', 'later.vim', 'Xafter.vim'] + let found = [] + for line in lines + for one in expected + if line =~ one + call add(found, one) + endif + endfor + endfor + call assert_equal(expected, found) + endif + + call assert_equal('here another pack after', substitute(join(readfile('Xsequence', 1), ''), '\s\+$', '', '')) + + call delete('Xtestout') + call delete('Xsequence') + call delete('Xhere', 'rf') + call delete('Xanother', 'rf') + call delete('Xafter', 'rf') +endfunc + +func Test_pack_in_rtp_when_plugins_run() + if !has('packages') + return + endif + let before = [ + \ 'set nocp viminfo+=nviminfo', + \ 'set guioptions+=M', + \ 'let $HOME = "/does/not/exist"', + \ 'set loadplugins', + \ 'set rtp=Xhere', + \ 'set packpath=Xhere', + \ 'set nomore', + \ ] + let after = [ + \ 'quit', + \ ] + call mkdir('Xhere/plugin', 'p') + call writefile(['redir! > Xtestout', 'silent set runtimepath?', 'silent! call foo#Trigger()', 'redir END'], 'Xhere/plugin/here.vim') + call mkdir('Xhere/pack/foo/start/foobar/autoload', 'p') + call writefile(['function! foo#Trigger()', 'echo "autoloaded foo"', 'endfunction'], 'Xhere/pack/foo/start/foobar/autoload/foo.vim') + + if RunVim(before, after, '') + + let lines = filter(readfile('Xtestout'), '!empty(v:val)') + call assert_match('Xhere[/\\]pack[/\\]foo[/\\]start[/\\]foobar', get(lines, 0)) + call assert_match('autoloaded foo', get(lines, 1)) + endif + + call delete('Xtestout') + call delete('Xhere', 'rf') +endfunc + +func Test_help_arg() + if !has('unix') && has('gui') + " this doesn't work with gvim on MS-Windows + return + endif + if RunVim([], [], '--help >Xtestout') + let lines = readfile('Xtestout') + call assert_true(len(lines) > 20) + call assert_match('Usage:', lines[0]) + + " check if couple of lines are there + let found = [] + for line in lines + if line =~ '-R.*Read-only mode' + call add(found, 'Readonly mode') + endif + " Watch out for a second --version line in the Gnome version. + if line =~ '--version.*Print version information' + call add(found, "--version") + endif + endfor + call assert_equal(['Readonly mode', '--version'], found) + endif + call delete('Xtestout') +endfunc + +func Test_compatible_args() + throw "skipped: Nvim is always 'nocompatible'" + let after = [ + \ 'call writefile([string(&compatible)], "Xtestout")', + \ 'set viminfo+=nviminfo', + \ 'quit', + \ ] + if RunVim([], after, '-C') + let lines = readfile('Xtestout') + call assert_equal('1', lines[0]) + endif + + if RunVim([], after, '-N') + let lines = readfile('Xtestout') + call assert_equal('0', lines[0]) + endif + + call delete('Xtestout') +endfunc + +func Test_file_args() + let after = [ + \ 'call writefile(argv(), "Xtestout")', + \ 'qall', + \ ] + if RunVim([], after, '') + let lines = readfile('Xtestout') + call assert_equal(0, len(lines)) + endif + + if RunVim([], after, 'one') + let lines = readfile('Xtestout') + call assert_equal(1, len(lines)) + call assert_equal('one', lines[0]) + endif + + if RunVim([], after, 'one two three') + let lines = readfile('Xtestout') + call assert_equal(3, len(lines)) + call assert_equal('one', lines[0]) + call assert_equal('two', lines[1]) + call assert_equal('three', lines[2]) + endif + + if RunVim([], after, 'one -c echo two') + let lines = readfile('Xtestout') + call assert_equal(2, len(lines)) + call assert_equal('one', lines[0]) + call assert_equal('two', lines[1]) + endif + + if RunVim([], after, 'one -- -c echo two') + let lines = readfile('Xtestout') + call assert_equal(4, len(lines)) + call assert_equal('one', lines[0]) + call assert_equal('-c', lines[1]) + call assert_equal('echo', lines[2]) + call assert_equal('two', lines[3]) + endif + + call delete('Xtestout') +endfunc + +func Test_startuptime() + if !has('startuptime') + return + endif + let after = ['qall'] + if RunVim([], after, '--startuptime Xtestout one') + let lines = readfile('Xtestout') + let expected = ['parsing arguments', 'inits 3', 'opening buffers'] + let found = [] + for line in lines + for exp in expected + if line =~ exp + call add(found, exp) + endif + endfor + endfor + call assert_equal(expected, found) + endif + call delete('Xtestout') +endfunc + +func Test_read_stdin() + let after = [ + \ 'write Xtestout', + \ 'quit!', + \ ] + if RunVimPiped([], after, '-', 'echo something | ') + let lines = readfile('Xtestout') + " MS-Windows adds a space after the word + call assert_equal(['something'], split(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. + if has('unix') + call assert_equal('/', v:progpath[0]) + elseif has('win32') + call assert_equal(':', v:progpath[1]) + call assert_match('[/\\]', v:progpath[2]) + endif + + " Only expect "vim" to appear in v:progname. + call assert_match('vim\c', v:progname) +endfunc diff --git a/src/nvim/testdir/test_startup_utf8.vim b/src/nvim/testdir/test_startup_utf8.vim new file mode 100644 index 0000000000..d179a4cc79 --- /dev/null +++ b/src/nvim/testdir/test_startup_utf8.vim @@ -0,0 +1,64 @@ +" Tests for startup using utf-8. +if !has('multi_byte') + finish +endif + +source shared.vim + +func Test_read_stdin_utf8() + let linesin = ['テスト', '€ÀÈÌÒÙ'] + call writefile(linesin, 'Xtestin') + let before = [ + \ 'set enc=utf-8', + \ 'set fencs=cp932,utf-8', + \ ] + let after = [ + \ 'write ++enc=utf-8 Xtestout', + \ 'quit!', + \ ] + if has('win32') + let pipecmd = 'type Xtestin | ' + else + let pipecmd = 'cat Xtestin | ' + endif + if RunVimPiped(before, after, '-', pipecmd) + let lines = readfile('Xtestout') + call assert_equal(linesin, lines) + else + call assert_equal('', 'RunVimPiped failed.') + endif + call delete('Xtestout') + call delete('Xtestin') +endfunc + +func Test_read_fifo_utf8() + if !has('unix') + return + endif + " Using bash/zsh's process substitution. + if executable('bash') + set shell=bash + elseif executable('zsh') + set shell=zsh + else + return + endif + let linesin = ['テスト', '€ÀÈÌÒÙ'] + call writefile(linesin, 'Xtestin') + let before = [ + \ 'set enc=utf-8', + \ 'set fencs=cp932,utf-8', + \ ] + let after = [ + \ 'write ++enc=utf-8 Xtestout', + \ 'quit!', + \ ] + if RunVim(before, after, '<(cat Xtestin)') + let lines = readfile('Xtestout') + call assert_equal(linesin, lines) + else + call assert_equal('', 'RunVim failed.') + endif + call delete('Xtestout') + call delete('Xtestin') +endfunc diff --git a/src/nvim/testdir/test_stat.vim b/src/nvim/testdir/test_stat.vim new file mode 100644 index 0000000000..89ca9ef379 --- /dev/null +++ b/src/nvim/testdir/test_stat.vim @@ -0,0 +1,64 @@ +" Tests for stat functions and checktime + +func Test_existent_file() + let fname='Xtest.tmp' + + let ts=localtime() + sleep 1 + let fl=['Hello World!'] + call writefile(fl, fname) + let tf=getftime(fname) + sleep 1 + let te=localtime() + + call assert_true(ts <= tf && tf <= te) + call assert_equal(strlen(fl[0] . "\n"), getfsize(fname)) + call assert_equal('file', getftype(fname)) + call assert_equal('rw-', getfperm(fname)[0:2]) +endfunc + +func Test_existent_directory() + let dname='.' + + call assert_equal(0, getfsize(dname)) + call assert_equal('dir', getftype(dname)) + call assert_equal('rwx', getfperm(dname)[0:2]) +endfunc + +func Test_checktime() + let fname='Xtest.tmp' + + let fl=['Hello World!'] + call writefile(fl, fname) + set autoread + exec 'e' fname + sleep 2 + let fl=readfile(fname) + let fl[0] .= ' - checktime' + call writefile(fl, fname) + checktime + call assert_equal(fl[0], getline(1)) +endfunc + +func Test_nonexistent_file() + let fname='Xtest.tmp' + + call delete(fname) + call assert_equal(-1, getftime(fname)) + call assert_equal(-1, getfsize(fname)) + call assert_equal('', getftype(fname)) + call assert_equal('', getfperm(fname)) +endfunc + +func Test_win32_symlink_dir() + " On Windows, non-admin users cannot create symlinks. + " So we use an existing symlink for this test. + if has('win32') + " Check if 'C:\Users\All Users' is a symlink to a directory. + let res=system('dir C:\Users /a') + if match(res, '\C<SYMLINKD> *All Users') >= 0 + " Get the filetype of the symlink. + call assert_equal('dir', getftype('C:\Users\All Users')) + endif + endif +endfunc diff --git a/src/nvim/testdir/test_substitute.vim b/src/nvim/testdir/test_substitute.vim new file mode 100644 index 0000000000..e2b6de03c3 --- /dev/null +++ b/src/nvim/testdir/test_substitute.vim @@ -0,0 +1,41 @@ +" Tests for multi-line regexps with ":s". + +function! Test_multiline_subst() + enew! + call append(0, ["1 aa", + \ "bb", + \ "cc", + \ "2 dd", + \ "ee", + \ "3 ef", + \ "gh", + \ "4 ij", + \ "5 a8", + \ "8b c9", + \ "9d", + \ "6 e7", + \ "77f", + \ "xxxxx"]) + + 1 + " test if replacing a line break works with a back reference + /^1/,/^2/s/\n\(.\)/ \1/ + " test if inserting a line break works with a back reference + /^3/,/^4/s/\(.\)$/\r\1/ + " test if replacing a line break with another line break works + /^5/,/^6/s/\(\_d\{3}\)/x\1x/ + call assert_equal('1 aa bb cc 2 dd ee', getline(1)) + call assert_equal('3 e', getline(2)) + call assert_equal('f', getline(3)) + call assert_equal('g', getline(4)) + call assert_equal('h', getline(5)) + call assert_equal('4 i', getline(6)) + call assert_equal('j', getline(7)) + call assert_equal('5 ax8', getline(8)) + call assert_equal('8xb cx9', getline(9)) + call assert_equal('9xd', getline(10)) + call assert_equal('6 ex7', getline(11)) + call assert_equal('7x7f', getline(12)) + call assert_equal('xxxxx', getline(13)) + enew! +endfunction diff --git a/src/nvim/testdir/test_syn_attr.vim b/src/nvim/testdir/test_syn_attr.vim index 94d6b8735f..64aab3411d 100644 --- a/src/nvim/testdir/test_syn_attr.vim +++ b/src/nvim/testdir/test_syn_attr.vim @@ -20,7 +20,7 @@ func Test_missing_attr() if fontname == '' let fontname = 'something' endif - exe 'hi Mine guifg=blue guibg=red font=' . escape(fontname, ' \') + exe "hi Mine guifg=blue guibg=red font='" . fontname . "'" call assert_equal('blue', synIDattr(hlID("Mine"), "fg", 'gui')) call assert_equal('red', synIDattr(hlID("Mine"), "bg", 'gui')) call assert_equal(fontname, synIDattr(hlID("Mine"), "font", 'gui')) diff --git a/src/nvim/testdir/test_tabpage.vim b/src/nvim/testdir/test_tabpage.vim index 7c3039ba24..33139fcda0 100644 --- a/src/nvim/testdir/test_tabpage.vim +++ b/src/nvim/testdir/test_tabpage.vim @@ -11,6 +11,7 @@ function Test_tabpage() 0tabnew 1tabnew $tabnew + %del tabdo call append(line('$'), tabpagenr()) tabclose! 2 tabrewind @@ -93,10 +94,6 @@ function Test_tabpage() call assert_equal(7, tabpagenr()) tabmove call assert_equal(10, tabpagenr()) - tabmove -20 - call assert_equal(1, tabpagenr()) - tabmove +20 - call assert_equal(10, tabpagenr()) 0tabmove call assert_equal(1, tabpagenr()) $tabmove @@ -109,7 +106,16 @@ function Test_tabpage() call assert_equal(4, tabpagenr()) 7tabmove 5 call assert_equal(5, tabpagenr()) + call assert_fails("99tabmove", 'E16:') + call assert_fails("+99tabmove", 'E16:') + call assert_fails("-99tabmove", 'E16:') call assert_fails("tabmove foo", 'E474:') + call assert_fails("tabmove 99", 'E474:') + call assert_fails("tabmove +99", 'E474:') + call assert_fails("tabmove -99", 'E474:') + call assert_fails("tabmove -3+", 'E474:') + call assert_fails("tabmove $3", 'E474:') + 1tabonly! endfunc " Test autocommands @@ -117,7 +123,6 @@ function Test_tabpage_with_autocmd() if !has('autocmd') return endif - tabonly! command -nargs=1 -bar C :call add(s:li, '=== ' . <q-args> . ' ===')|<args> augroup TestTabpageGroup au! @@ -182,8 +187,10 @@ function Test_tabpage_with_autocmd() autocmd TabDestructive TabEnter * nested :C tabnext 2 | C tabclose 3 let s:li = [] - C tabnext 3 - call assert_equal(['=== tabnext 3 ===', 'BufLeave', 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', '=== tabnext 2 ===', 'BufLeave', 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', '=== tabnext 2 ===', '=== tabclose 3 ===', 'BufEnter', '=== tabclose 3 ==='], s:li) + call assert_equal(3, tabpagenr('$')) + C tabnext 2 + call assert_equal(2, tabpagenr('$')) + call assert_equal(['=== tabnext 2 ===', 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', '=== tabnext 2 ===', '=== tabclose 3 ==='], s:li) call assert_equal(['2/2'], [tabpagenr().'/'.tabpagenr('$')]) delcommand C @@ -191,8 +198,7 @@ function Test_tabpage_with_autocmd() augroup! TabDestructive autocmd! TestTabpageGroup augroup! TestTabpageGroup - tabonly! - bw! + 1tabonly! endfunction function Test_tabpage_with_tab_modifier() @@ -204,7 +210,7 @@ function Test_tabpage_with_tab_modifier() exec 'tabnext ' . a:pre_nr exec a:cmd call assert_equal(a:post_nr, tabpagenr()) - call assert_equal('help', &filetype) + call assert_equal('help', &buftype) helpclose endfunc @@ -223,8 +229,223 @@ function Test_tabpage_with_tab_modifier() call assert_fails('-99tab help', 'E16:') delfunction s:check_tab - tabonly! - bw! + 1tabonly! +endfunction + +function Check_tab_count(pre_nr, cmd, post_nr) + exec 'tabnext' a:pre_nr + normal! G + exec a:cmd + call assert_equal(a:post_nr, tabpagenr(), a:cmd) +endfunc + +" Test for [count] of tabnext +function Test_tabpage_with_tabnext() + for n in range(4) + tabedit + call setline(1, ['', '', '3']) + endfor + + call Check_tab_count(1, 'tabnext', 2) + call Check_tab_count(1, '3tabnext', 3) + call Check_tab_count(1, '.tabnext', 1) + call Check_tab_count(1, '.+1tabnext', 2) + call Check_tab_count(2, '+tabnext', 3) + call Check_tab_count(2, '+2tabnext', 4) + call Check_tab_count(4, '-tabnext', 3) + call Check_tab_count(4, '-2tabnext', 2) + call Check_tab_count(3, '$tabnext', 5) + call assert_fails('0tabnext', 'E16:') + call assert_fails('99tabnext', 'E16:') + call assert_fails('+99tabnext', 'E16:') + call assert_fails('-99tabnext', 'E16:') + call Check_tab_count(1, 'tabnext 3', 3) + call Check_tab_count(2, 'tabnext +', 3) + call Check_tab_count(2, 'tabnext +2', 4) + call Check_tab_count(4, 'tabnext -', 3) + call Check_tab_count(4, 'tabnext -2', 2) + call Check_tab_count(3, 'tabnext $', 5) + call assert_fails('tabnext 0', 'E474:') + call assert_fails('tabnext .', 'E474:') + call assert_fails('tabnext -+', 'E474:') + call assert_fails('tabnext +2-', 'E474:') + call assert_fails('tabnext $3', 'E474:') + call assert_fails('tabnext 99', 'E474:') + call assert_fails('tabnext +99', 'E474:') + call assert_fails('tabnext -99', 'E474:') + + 1tabonly! +endfunction + +" Test for [count] of tabprevious +function Test_tabpage_with_tabprevious() + for n in range(5) + tabedit + call setline(1, ['', '', '3']) + endfor + + for cmd in ['tabNext', 'tabprevious'] + call Check_tab_count(6, cmd, 5) + call Check_tab_count(6, '3' . cmd, 3) + call Check_tab_count(6, '8' . cmd, 4) + call Check_tab_count(6, cmd . ' 3', 3) + call Check_tab_count(6, cmd . ' 8', 4) + for n in range(2) + for c in ['0', '.+3', '+', '+2' , '-', '-2' , '$', '+99', '-99'] + if n == 0 " pre count + let entire_cmd = c . cmd + let err_code = 'E16:' + else + let entire_cmd = cmd . ' ' . c + let err_code = 'E474:' + endif + call assert_fails(entire_cmd, err_code) + endfor + endfor + endfor + + 1tabonly! +endfunction + +function s:reconstruct_tabpage_for_test(nr) + let n = (a:nr > 2) ? a:nr - 2 : 1 + 1tabonly! + 0tabedit n0 + for n in range(1, n) + exec '$tabedit n' . n + if n == 1 + call setline(1, ['', '', '3']) + endif + endfor +endfunc + +" Test for [count] of tabclose +function Test_tabpage_with_tabclose() + + " pre count + call s:reconstruct_tabpage_for_test(6) + call Check_tab_count(3, 'tabclose!', 3) + call Check_tab_count(1, '3tabclose', 1) + call Check_tab_count(4, '4tabclose', 3) + call Check_tab_count(3, '1tabclose', 2) + call Check_tab_count(2, 'tabclose', 1) + call assert_equal(1, tabpagenr('$')) + call assert_equal('', bufname('')) + + call s:reconstruct_tabpage_for_test(6) + call Check_tab_count(2, '$tabclose', 2) + call Check_tab_count(4, '.tabclose', 4) + call Check_tab_count(3, '.+tabclose', 3) + call Check_tab_count(3, '.-2tabclose', 2) + call Check_tab_count(1, '.+1tabclose!', 1) + call assert_equal(1, tabpagenr('$')) + call assert_equal('', bufname('')) + + " post count + call s:reconstruct_tabpage_for_test(6) + call Check_tab_count(3, 'tabclose!', 3) + call Check_tab_count(1, 'tabclose 3', 1) + call Check_tab_count(4, 'tabclose 4', 3) + call Check_tab_count(3, 'tabclose 1', 2) + call Check_tab_count(2, 'tabclose', 1) + call assert_equal(1, tabpagenr('$')) + call assert_equal('', bufname('')) + + call s:reconstruct_tabpage_for_test(6) + call Check_tab_count(2, 'tabclose $', 2) + call Check_tab_count(4, 'tabclose', 4) + call Check_tab_count(3, 'tabclose +', 3) + call Check_tab_count(3, 'tabclose -2', 2) + call Check_tab_count(1, 'tabclose! +1', 1) + call assert_equal(1, tabpagenr('$')) + call assert_equal('', bufname('')) + + call s:reconstruct_tabpage_for_test(6) + for n in range(2) + for c in ['0', '$3', '99', '+99', '-99'] + if n == 0 " pre count + let entire_cmd = c . 'tabclose' + let err_code = 'E16:' + else + let entire_cmd = 'tabclose ' . c + let err_code = 'E474:' + endif + call assert_fails(entire_cmd, err_code) + call assert_equal(6, tabpagenr('$')) + endfor + endfor + + call assert_fails('3tabclose', 'E37:') + call assert_fails('tabclose 3', 'E37:') + call assert_fails('tabclose -+', 'E474:') + call assert_fails('tabclose +2-', 'E474:') + call assert_equal(6, tabpagenr('$')) + + 1tabonly! +endfunction + +" Test for [count] of tabonly +function Test_tabpage_with_tabonly() + + " Test for the normal behavior (pre count only) + let tc = [ [4, '.', '!'], [2, '.+', ''], [3, '.-2', '!'], [1, '.+1', '!'] ] + for c in tc + call s:reconstruct_tabpage_for_test(6) + let entire_cmd = c[1] . 'tabonly' . c[2] + call Check_tab_count(c[0], entire_cmd, 1) + call assert_equal(1, tabpagenr('$')) + endfor + + " Test for the normal behavior + let tc2 = [ [3, '', ''], [1, '3', ''], [4, '4', '!'], [3, '1', '!'], + \ [2, '', '!'], + \ [2, '$', '!'], [3, '+', '!'], [3, '-2', '!'], [3, '+1', '!'] + \ ] + for n in range(2) + for c in tc2 + call s:reconstruct_tabpage_for_test(6) + if n == 0 " pre count + let entire_cmd = c[1] . 'tabonly' . c[2] + else + let entire_cmd = 'tabonly' . c[2] . ' ' . c[1] + endif + call Check_tab_count(c[0], entire_cmd, 1) + call assert_equal(1, tabpagenr('$')) + endfor + endfor + + " Test for the error behavior + for n in range(2) + for c in ['0', '$3', '99', '+99', '-99'] + call s:reconstruct_tabpage_for_test(6) + if n == 0 " pre count + let entire_cmd = c . 'tabonly' + let err_code = 'E16:' + else + let entire_cmd = 'tabonly ' . c + let err_code = 'E474:' + endif + call assert_fails(entire_cmd, err_code) + call assert_equal(6, tabpagenr('$')) + endfor + endfor + + " Test for the error behavior (post count only) + for c in tc + call s:reconstruct_tabpage_for_test(6) + let entire_cmd = 'tabonly' . c[2] . ' ' . c[1] + let err_code = 'E474:' + call assert_fails(entire_cmd, err_code) + call assert_equal(6, tabpagenr('$')) + endfor + + call assert_fails('tabonly -+', 'E474:') + call assert_fails('tabonly +2-', 'E474:') + call assert_equal(6, tabpagenr('$')) + + 1tabonly! + new + only! endfunction func Test_tabnext_on_buf_unload1() diff --git a/src/nvim/testdir/test_tagcase.vim b/src/nvim/testdir/test_tagcase.vim new file mode 100644 index 0000000000..833cb9f990 --- /dev/null +++ b/src/nvim/testdir/test_tagcase.vim @@ -0,0 +1,73 @@ +" test 'tagcase' option + +func Test_tagcase() + call writefile(["Bar\tXtext\t3", "Foo\tXtext\t2", "foo\tXtext\t4"], 'Xtags') + set tags=Xtags + e Xtext + + for &ic in [0, 1] + for &scs in [0, 1] + for &g:tc in ["followic", "ignore", "match", "followscs", "smart"] + for &l:tc in ["", "followic", "ignore", "match", "followscs", "smart"] + let smart = 0 + if &l:tc != '' + let tc = &l:tc + else + let tc = &g:tc + endif + if tc == 'followic' + let ic = &ic + elseif tc == 'ignore' + let ic = 1 + elseif tc == 'followscs' + let ic = &ic + let smart = &scs + elseif tc == 'smart' + let ic = 1 + let smart = 1 + else + let ic = 0 + endif + if ic && smart + call assert_equal(['foo', 'Foo'], map(taglist("^foo$"), {i, v -> v.name})) + call assert_equal(['Foo'], map(taglist("^Foo$"), {i, v -> v.name})) + elseif ic + call assert_equal(['foo', 'Foo'], map(taglist("^foo$"), {i, v -> v.name})) + call assert_equal(['Foo', 'foo'], map(taglist("^Foo$"), {i, v -> v.name})) + else + call assert_equal(['foo'], map(taglist("^foo$"), {i, v -> v.name})) + call assert_equal(['Foo'], map(taglist("^Foo$"), {i, v -> v.name})) + endif + endfor + endfor + endfor + endfor + + call delete('Xtags') + set ic& + setg tc& + setl tc& + set scs& +endfunc + +func Test_set_tagcase() + " Verify default values. + set ic& + setg tc& + setl tc& + call assert_equal(0, &ic) + call assert_equal('followic', &g:tc) + call assert_equal('followic', &l:tc) + call assert_equal('followic', &tc) + + " Verify that the local setting accepts <empty> but that the global setting + " does not. The first of these (setting the local value to <empty>) should + " succeed; the other two should fail. + setl tc= + call assert_fails('setg tc=', 'E474:') + call assert_fails('set tc=', 'E474:') + + set ic& + setg tc& + setl tc& +endfunc diff --git a/src/nvim/testdir/test_tagjump.vim b/src/nvim/testdir/test_tagjump.vim index d8a333f44c..0d697b3f3e 100644 --- a/src/nvim/testdir/test_tagjump.vim +++ b/src/nvim/testdir/test_tagjump.vim @@ -6,4 +6,93 @@ func Test_ptag_with_notagstack() call assert_fails('ptag does_not_exist_tag_name', 'E426') set tagstack&vim endfunc -" vim: sw=2 et + +func Test_cancel_ptjump() + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "word\tfile1\tcmd1", + \ "word\tfile2\tcmd2"], + \ 'Xtags') + + only! + call feedkeys(":ptjump word\<CR>\<CR>", "xt") + help + call assert_equal(2, winnr('$')) + + call delete('Xtags') + quit +endfunc + +func Test_static_tagjump() + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile1\t/^one/;\"\tf\tfile:\tsignature:(void)", + \ "word\tXfile2\tcmd2"], + \ 'Xtags') + new Xfile1 + call setline(1, ['empty', 'one()', 'empty']) + write + tag one + call assert_equal(2, line('.')) + + bwipe! + set tags& + call delete('Xtags') + call delete('Xfile1') +endfunc + +func Test_duplicate_tagjump() + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "thesame\tXfile1\t1;\"\td\tfile:", + \ "thesame\tXfile1\t2;\"\td\tfile:", + \ "thesame\tXfile1\t3;\"\td\tfile:", + \ ], + \ 'Xtags') + new Xfile1 + call setline(1, ['thesame one', 'thesame two', 'thesame three']) + write + tag thesame + call assert_equal(1, line('.')) + tnext + call assert_equal(2, line('.')) + tnext + call assert_equal(3, line('.')) + + bwipe! + set tags& + call delete('Xtags') + call delete('Xfile1') +endfunc + +" Tests for [ CTRL-I and CTRL-W CTRL-I commands +function Test_keyword_jump() + call writefile(["#include Xinclude", "", + \ "", + \ "/* test text test tex start here", + \ " some text", + \ " test text", + \ " start OK if found this line", + \ " start found wrong line", + \ "test text"], 'Xtestfile') + call writefile(["/* test text test tex start here", + \ " some text", + \ " test text", + \ " start OK if found this line", + \ " start found wrong line", + \ "test text"], 'Xinclude') + new Xtestfile + call cursor(1,1) + call search("start") + exe "normal! 5[\<C-I>" + call assert_equal(" start OK if found this line", getline('.')) + call cursor(1,1) + call search("start") + exe "normal! 5\<C-W>\<C-I>" + call assert_equal(" start OK if found this line", getline('.')) + enew! | only + call delete('Xtestfile') + call delete('Xinclude') +endfunction + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_taglist.vim b/src/nvim/testdir/test_taglist.vim new file mode 100644 index 0000000000..2d1557ebd9 --- /dev/null +++ b/src/nvim/testdir/test_taglist.vim @@ -0,0 +1,58 @@ +" test 'taglist' function + +func Test_taglist() + call writefile([ + \ "FFoo\tXfoo\t1", + \ "FBar\tXfoo\t2", + \ "BFoo\tXbar\t1", + \ "BBar\tXbar\t2" + \ ], 'Xtags') + set tags=Xtags + split Xtext + + call assert_equal(['FFoo', 'BFoo'], map(taglist("Foo"), {i, v -> v.name})) + call assert_equal(['FFoo', 'BFoo'], map(taglist("Foo", "Xtext"), {i, v -> v.name})) + call assert_equal(['FFoo', 'BFoo'], map(taglist("Foo", "Xfoo"), {i, v -> v.name})) + call assert_equal(['BFoo', 'FFoo'], map(taglist("Foo", "Xbar"), {i, v -> v.name})) + + call delete('Xtags') + bwipe +endfunc + +func Test_taglist_native_etags() + if !has('emacs_tags') + return + endif + call writefile([ + \ "\x0c", + \ "src/os_unix.c,13491", + \ "set_signals(\x7f1335,32699", + \ "reset_signals(\x7f1407,34136", + \ ], 'Xtags') + + set tags=Xtags + + call assert_equal([['set_signals', '1335,32699'], ['reset_signals', '1407,34136']], + \ map(taglist('set_signals'), {i, v -> [v.name, v.cmd]})) + + call delete('Xtags') +endfunc + +func Test_taglist_ctags_etags() + if !has('emacs_tags') + return + endif + call writefile([ + \ "\x0c", + \ "src/os_unix.c,13491", + \ "set_signals(void)\x7fset_signals\x011335,32699", + \ "reset_signals(void)\x7freset_signals\x011407,34136", + \ ], 'Xtags') + + set tags=Xtags + + call assert_equal([['set_signals', '1335,32699'], ['reset_signals', '1407,34136']], + \ map(taglist('set_signals'), {i, v -> [v.name, v.cmd]})) + + call delete('Xtags') +endfunc diff --git a/src/nvim/testdir/test_textobjects.vim b/src/nvim/testdir/test_textobjects.vim new file mode 100644 index 0000000000..630ae5d3a4 --- /dev/null +++ b/src/nvim/testdir/test_textobjects.vim @@ -0,0 +1,43 @@ +" Test for textobjects + +if !has('textobjects') + finish +endif + +function! CpoM(line, useM, expected) + new + + if a:useM + set cpoptions+=M + else + set cpoptions-=M + endif + + call setline(1, a:line) + + call setreg('"', '') + normal! ggfrmavi)y + call assert_equal(getreg('"'), a:expected[0]) + + call setreg('"', '') + normal! `afbmavi)y + call assert_equal(getreg('"'), a:expected[1]) + + call setreg('"', '') + normal! `afgmavi)y + call assert_equal(getreg('"'), a:expected[2]) + + q! +endfunction + +function! Test_inner_block_without_cpo_M() + call CpoM('(red \(blue) green)', 0, ['red \(blue', 'red \(blue', '']) +endfunction + +function! Test_inner_block_with_cpo_M_left_backslash() + call CpoM('(red \(blue) green)', 1, ['red \(blue) green', 'blue', 'red \(blue) green']) +endfunction + +function! Test_inner_block_with_cpo_M_right_backslash() + call CpoM('(red (blue\) green)', 1, ['red (blue\) green', 'blue\', 'red (blue\) green']) +endfunction diff --git a/src/nvim/testdir/test_timers.vim b/src/nvim/testdir/test_timers.vim index d92cbe6897..d377062780 100644 --- a/src/nvim/testdir/test_timers.vim +++ b/src/nvim/testdir/test_timers.vim @@ -4,8 +4,10 @@ if !has('timers') finish endif +source shared.vim + func MyHandler(timer) - let s:val += 1 + let g:val += 1 endfunc func MyHandlerWithLists(lists, timer) @@ -13,43 +15,159 @@ func MyHandlerWithLists(lists, timer) endfunc func Test_oneshot() - let s:val = 0 + let g:val = 0 let timer = timer_start(50, 'MyHandler') - sleep 200m - call assert_equal(1, s:val) + let slept = WaitFor('g:val == 1') + call assert_equal(1, g:val) + if has('reltime') + call assert_inrange(40, 100, slept) + else + call assert_inrange(20, 100, slept) + endif endfunc func Test_repeat_three() - let s:val = 0 + let g:val = 0 let timer = timer_start(50, 'MyHandler', {'repeat': 3}) - sleep 500m - call assert_equal(3, s:val) + let slept = WaitFor('g:val == 3') + call assert_equal(3, g:val) + if has('reltime') + call assert_inrange(120, 250, slept) + else + call assert_inrange(80, 200, slept) + endif endfunc func Test_repeat_many() - let s:val = 0 + let g:val = 0 let timer = timer_start(50, 'MyHandler', {'repeat': -1}) sleep 200m call timer_stop(timer) - call assert_true(s:val > 1) - call assert_true(s:val < 5) + call assert_inrange(2, 4, g:val) endfunc func Test_with_partial_callback() - let s:val = 0 - let s:meow = {} - function s:meow.bite(...) - let s:val += 1 + let g:val = 0 + let meow = {'one': 1} + function meow.bite(...) + let g:val += self.one endfunction - call timer_start(50, s:meow.bite) - sleep 200m - call assert_equal(1, s:val) + call timer_start(50, meow.bite) + let slept = WaitFor('g:val == 1') + call assert_equal(1, g:val) + if has('reltime') + call assert_inrange(40, 130, slept) + else + call assert_inrange(20, 100, slept) + endif endfunc func Test_retain_partial() - call timer_start(100, function('MyHandlerWithLists', [['a']])) + call timer_start(50, function('MyHandlerWithLists', [['a']])) call garbagecollect() + sleep 100m +endfunc + +func Test_info() + let id = timer_start(1000, 'MyHandler') + let info = timer_info(id) + call assert_equal(id, info[0]['id']) + call assert_equal(1000, info[0]['time']) + call assert_equal("function('MyHandler')", string(info[0]['callback'])) + + let found = 0 + for info in timer_info() + if info['id'] == id + let found += 1 + endif + endfor + call assert_equal(1, found) + + call timer_stop(id) + call assert_equal([], timer_info(id)) +endfunc + +func Test_stopall() + let id1 = timer_start(1000, 'MyHandler') + let id2 = timer_start(2000, 'MyHandler') + let info = timer_info() + call assert_equal(2, len(info)) + + call timer_stopall() + let info = timer_info() + call assert_equal(0, len(info)) +endfunc + +func Test_paused() + let g:val = 0 + + let id = timer_start(50, 'MyHandler') + let info = timer_info(id) + call assert_equal(0, info[0]['paused']) + + call timer_pause(id, 1) + let info = timer_info(id) + call assert_equal(1, info[0]['paused']) sleep 200m + call assert_equal(0, g:val) + + call timer_pause(id, 0) + let info = timer_info(id) + call assert_equal(0, info[0]['paused']) + + let slept = WaitFor('g:val == 1') + call assert_equal(1, g:val) + if has('reltime') + call assert_inrange(0, 60, slept) + else + call assert_inrange(0, 10, slept) + endif endfunc -" vim: ts=2 sw=0 et + +func StopMyself(timer) + let g:called += 1 + if g:called == 2 + call timer_stop(a:timer) + endif +endfunc + +func Test_delete_myself() + let g:called = 0 + let t = timer_start(10, 'StopMyself', {'repeat': -1}) + call WaitFor('g:called == 2') + call assert_equal(2, g:called) + call assert_equal([], timer_info(t)) +endfunc + +func StopTimer1(timer) + let g:timer2 = timer_start(10, 'StopTimer2') + " avoid maxfuncdepth error + call timer_pause(g:timer1, 1) + sleep 40m +endfunc + +func StopTimer2(timer) + call timer_stop(g:timer1) +endfunc + +func Test_stop_in_callback() + let g:timer1 = timer_start(10, 'StopTimer1') + sleep 40m +endfunc + +func StopTimerAll(timer) + call timer_stopall() +endfunc + +func Test_stop_all_in_callback() + let g:timer1 = timer_start(10, 'StopTimerAll') + let info = timer_info() + call assert_equal(1, len(info)) + sleep 40m + let info = timer_info() + call assert_equal(0, len(info)) +endfunc + + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_true_false.vim b/src/nvim/testdir/test_true_false.vim new file mode 100644 index 0000000000..84aca737ac --- /dev/null +++ b/src/nvim/testdir/test_true_false.vim @@ -0,0 +1,150 @@ +" Test behavior of boolean-like values. + +" Test what is explained at ":help TRUE" and ":help FALSE". +func Test_if() + if v:false + call assert_true(false, 'v:false is false') + endif + if 0 + call assert_true(false, 'zero is false') + endif + if "0" + call assert_true(false, 'zero string is false') + endif + if "foo" + call assert_true(false, 'foo is false') + endif + if " " + call assert_true(false, 'space is false') + endif + if empty("foo") + call assert_true(false, 'foo is not empty') + endif + + if v:true + else + call assert_true(false, 'v:true is true') + endif + if 1 + else + call assert_true(false, 'one is true') + endif + if "1" + else + call assert_true(false, 'one string is true') + endif + if "1foo" + else + call assert_true(false, 'one in string is true') + endif + + call assert_fails('if [1]', 'E745') + call assert_fails('if {1: 1}', 'E728') + call assert_fails('if function("string")', 'E703') + call assert_fails('if 1.3")', 'E805') +endfunc + +function Try_arg_true_false(expr, false_val, true_val) + for v in ['v:false', '0', '"0"', '"foo"', '" "'] + let r = eval(substitute(a:expr, '%v%', v, '')) + call assert_equal(a:false_val, r, 'result for ' . v . ' is not ' . string(a:false_val) . ' but ' . string(r)) + endfor + for v in ['v:true', '1', '"1"', '"1foo"'] + let r = eval(substitute(a:expr, '%v%', v, '')) + call assert_equal(a:true_val, r, 'result for ' . v . ' is not ' . string(a:true_val) . ' but ' . string(r)) + endfor +endfunc + +" Test using TRUE or FALSE values for an argument. +func Test_true_false_arg() + call Try_arg_true_false('count(["a", "A"], "a", %v%)', 1, 2) + + set wildignore=*.swp + call Try_arg_true_false('expand("foo.swp", %v%)', "", "foo.swp") + call Try_arg_true_false('expand("foo.vim", 0, %v%)', "foo.vim", ["foo.vim"]) + + call setreg('a', ['x', 'y']) + call Try_arg_true_false('getreg("a", 1, %v%)', "x\ny\n", ['x', 'y']) + + set wildignore=*.vim + call Try_arg_true_false('glob("runtest.vim", %v%)', "", "runtest.vim") + set wildignore=*.swp + call Try_arg_true_false('glob("runtest.vim", 0, %v%)', "runtest.vim", ["runtest.vim"]) + if has('unix') + silent !ln -s doesntexit Xlink + call Try_arg_true_false('glob("Xlink", 0, 0, %v%)', "", "Xlink") + silent !rm Xlink + endif + + set wildignore=*.vim + call Try_arg_true_false('globpath(".", "runtest.vim", %v%)', "", "./runtest.vim") + set wildignore=*.swp + call Try_arg_true_false('globpath(".", "runtest.vim", 0, %v%)', "./runtest.vim", ["./runtest.vim"]) + if has('unix') + silent !ln -s doesntexit Xlink + call Try_arg_true_false('globpath(".", "Xlink", 0, 0, %v%)', "", "./Xlink") + silent !rm Xlink + endif + + abbr asdf asdff + call Try_arg_true_false('hasmapto("asdff", "i", %v%)', 0, 1) + + call Try_arg_true_false('index(["a", "A"], "A", 0, %v%)', 1, 0) + + function FilterMapArg(d) + if type(a:d) == type({}) + return filter(a:d, 'v:key == "rhs"') + endif + return a:d + endfunction + call Try_arg_true_false('maparg("asdf", "i", %v%)', "", "asdff") + call Try_arg_true_false('FilterMapArg(maparg("asdf", "i", 1, %v%))', "asdff", {'rhs': 'asdff'}) + + call Try_arg_true_false('hasmapto("asdf", "i", %v%)', 0, 1) + + new colored + call setline(1, '<here>') + syn match brackets "<.*>" + syn match here "here" transparent + let brackets_id = synID(1, 1, 0) + let here_id = synID(1, 3, 0) + call Try_arg_true_false('synID(1, 3, %v%)', here_id, brackets_id) + bwipe! +endfunc + +function Try_arg_non_zero(expr, false_val, true_val) + for v in ['v:false', '0', '[1]', '{2:3}', '3.4'] + let r = eval(substitute(a:expr, '%v%', v, '')) + call assert_equal(a:false_val, r, 'result for ' . v . ' is not ' . a:false_val . ' but ' . r) + endfor + for v in ['v:true', '1', '" "', '"0"'] + let r = eval(substitute(a:expr, '%v%', v, '')) + call assert_equal(a:true_val, r, 'result for ' . v . ' is not ' . a:true_val . ' but ' . r) + endfor +endfunc + + +" Test using non-zero-arg for an argument. +func Test_non_zero_arg() + " call test_settime(93784) + " call Try_arg_non_zero("mode(%v%)", 'x', 'x!') + " call test_settime(0) + + call Try_arg_non_zero("shellescape('foo%', %v%)", "'foo%'", "'foo\\%'") + + " visualmode() needs to be called twice to check + for v in [v:false, 0, [1], {2:3}, 3.4] + normal vv + let r = visualmode(v) + call assert_equal('v', r, 'result for ' . string(v) . ' is not "v" but ' . r) + let r = visualmode(v) + call assert_equal('v', r, 'result for ' . string(v) . ' is not "v" but ' . r) + endfor + for v in [v:true, 1, " ", "0"] + normal vv + let r = visualmode(v) + call assert_equal('v', r, 'result for ' . v . ' is not "v" but ' . r) + let r = visualmode(v) + call assert_equal('', r, 'result for ' . v . ' is not "" but ' . r) + endfor +endfunc diff --git a/src/nvim/testdir/test_undo.vim b/src/nvim/testdir/test_undo.vim new file mode 100644 index 0000000000..171618f6f7 --- /dev/null +++ b/src/nvim/testdir/test_undo.vim @@ -0,0 +1,267 @@ +" Tests for the undo tree. +" Since this script is sourced we need to explicitly break changes up in +" undo-able pieces. Do that by setting 'undolevels'. +" Also tests :earlier and :later. + +func Test_undotree() + exe "normal Aabc\<Esc>" + set ul=100 + exe "normal Adef\<Esc>" + set ul=100 + undo + let d = undotree() + call assert_true(d.seq_last > 0) + call assert_true(d.seq_cur > 0) + call assert_true(d.seq_cur < d.seq_last) + call assert_true(len(d.entries) > 0) + " TODO: check more members of d + + w! Xtest + call assert_equal(d.save_last + 1, undotree().save_last) + call delete('Xtest') + bwipe Xtest +endfunc + +func FillBuffer() + for i in range(1,13) + put=i + " Set 'undolevels' to split undo. + exe "setg ul=" . &g:ul + endfor +endfunc + +func Test_global_local_undolevels() + new one + set undolevels=5 + call FillBuffer() + " will only undo the last 5 changes, end up with 13 - (5 + 1) = 7 lines + earlier 10 + call assert_equal(5, &g:undolevels) + call assert_equal(-123456, &l:undolevels) + call assert_equal('7', getline('$')) + + new two + setlocal undolevels=2 + call FillBuffer() + " will only undo the last 2 changes, end up with 13 - (2 + 1) = 10 lines + earlier 10 + call assert_equal(5, &g:undolevels) + call assert_equal(2, &l:undolevels) + call assert_equal('10', getline('$')) + + setlocal ul=10 + call assert_equal(5, &g:undolevels) + call assert_equal(10, &l:undolevels) + + " Setting local value in "two" must not change local value in "one" + wincmd p + call assert_equal(5, &g:undolevels) + call assert_equal(-123456, &l:undolevels) + + new three + setglobal ul=50 + call assert_equal(50, &g:undolevels) + call assert_equal(-123456, &l:undolevels) + + " Drop created windows + set ul& + new + only! +endfunc + +func BackOne(expected) + call feedkeys('g-', 'xt') + call assert_equal(a:expected, getline(1)) +endfunc + +func Test_undo_del_chars() + throw 'skipped: Nvim does not support test_settime()' + + " Setup a buffer without creating undo entries + new + set ul=-1 + call setline(1, ['123-456']) + set ul=100 + 1 + call test_settime(100) + + " Delete three characters and undo with g- + call feedkeys('x', 'xt') + call feedkeys('x', 'xt') + call feedkeys('x', 'xt') + call assert_equal('-456', getline(1)) + call BackOne('3-456') + call BackOne('23-456') + call BackOne('123-456') + call assert_fails("BackOne('123-456')") + + :" Delete three other characters and go back in time with g- + call feedkeys('$x', 'xt') + call feedkeys('x', 'xt') + call feedkeys('x', 'xt') + call assert_equal('123-', getline(1)) + call test_settime(101) + + call BackOne('123-4') + call BackOne('123-45') + " skips '123-456' because it's older + call BackOne('-456') + call BackOne('3-456') + call BackOne('23-456') + call BackOne('123-456') + call assert_fails("BackOne('123-456')") + normal 10g+ + call assert_equal('123-', getline(1)) + + :" Jump two seconds and go some seconds forward and backward + call test_settime(103) + call feedkeys("Aa\<Esc>", 'xt') + call feedkeys("Ab\<Esc>", 'xt') + call feedkeys("Ac\<Esc>", 'xt') + call assert_equal('123-abc', getline(1)) + earlier 1s + call assert_equal('123-', getline(1)) + earlier 3s + call assert_equal('123-456', getline(1)) + later 1s + call assert_equal('123-', getline(1)) + later 1h + call assert_equal('123-abc', getline(1)) + + close! +endfunc + +func Test_undolist() + new + set ul=100 + + let a=execute('undolist') + call assert_equal("\nNothing to undo", a) + + " 1 leaf (2 changes). + call feedkeys('achange1', 'xt') + call feedkeys('achange2', 'xt') + let a=execute('undolist') + call assert_match("^\nnumber changes when *saved\n *2 *2 .*$", a) + + " 2 leaves. + call feedkeys('u', 'xt') + call feedkeys('achange3\<Esc>', 'xt') + let a=execute('undolist') + call assert_match("^\nnumber changes when *saved\n *2 *2 *.*\n *3 *2 .*$", a) + close! +endfunc + +func Test_U_command() + new + set ul=100 + call feedkeys("achange1\<Esc>", 'xt') + call feedkeys("achange2\<Esc>", 'xt') + norm! U + call assert_equal('', getline(1)) + norm! U + call assert_equal('change1change2', getline(1)) + close! +endfunc + +func Test_undojoin() + new + call feedkeys("Goaaaa\<Esc>", 'xt') + call feedkeys("obbbb\<Esc>", 'xt') + call assert_equal(['aaaa', 'bbbb'], getline(2, '$')) + call feedkeys("u", 'xt') + call assert_equal(['aaaa'], getline(2, '$')) + call feedkeys("obbbb\<Esc>", 'xt') + undojoin + " Note: next change must not be as if typed + call feedkeys("occcc\<Esc>", 'x') + call assert_equal(['aaaa', 'bbbb', 'cccc'], getline(2, '$')) + call feedkeys("u", 'xt') + call assert_equal(['aaaa'], getline(2, '$')) + close! +endfunc + +func Test_undo_write() + split Xtest + call feedkeys("ione one one\<Esc>", 'xt') + w! + call feedkeys("otwo\<Esc>", 'xt') + call feedkeys("otwo\<Esc>", 'xt') + w + call feedkeys("othree\<Esc>", 'xt') + call assert_equal(['one one one', 'two', 'two', 'three'], getline(1, '$')) + earlier 1f + call assert_equal(['one one one', 'two', 'two'], getline(1, '$')) + earlier 1f + call assert_equal(['one one one'], getline(1, '$')) + earlier 1f + call assert_equal([''], getline(1, '$')) + later 1f + call assert_equal(['one one one'], getline(1, '$')) + later 1f + call assert_equal(['one one one', 'two', 'two'], getline(1, '$')) + later 1f + call assert_equal(['one one one', 'two', 'two', 'three'], getline(1, '$')) + + close! + call delete('Xtest') + bwipe! Xtest +endfunc + +func Test_insert_expr() + new + " calling setline() triggers undo sync + call feedkeys("oa\<Esc>", 'xt') + call feedkeys("ob\<Esc>", 'xt') + set ul=100 + call feedkeys("o1\<Esc>a2\<C-R>=setline('.','1234')\<CR>\<CR>\<Esc>", 'x') + call assert_equal(['a', 'b', '120', '34'], getline(2, '$')) + call feedkeys("u", 'x') + call assert_equal(['a', 'b', '12'], getline(2, '$')) + call feedkeys("u", 'x') + call assert_equal(['a', 'b'], getline(2, '$')) + + call feedkeys("oc\<Esc>", 'xt') + set ul=100 + call feedkeys("o1\<Esc>a2\<C-R>=setline('.','1234')\<CR>\<CR>\<Esc>", 'x') + call assert_equal(['a', 'b', 'c', '120', '34'], getline(2, '$')) + call feedkeys("u", 'x') + call assert_equal(['a', 'b', 'c', '12'], getline(2, '$')) + + call feedkeys("od\<Esc>", 'xt') + set ul=100 + call feedkeys("o1\<Esc>a2\<C-R>=string(123)\<CR>\<Esc>", 'x') + call assert_equal(['a', 'b', 'c', '12', 'd', '12123'], getline(2, '$')) + call feedkeys("u", 'x') + call assert_equal(['a', 'b', 'c', '12', 'd'], getline(2, '$')) + + close! +endfunc + +func Test_undofile_earlier() + throw 'skipped: Nvim does not support test_settime()' + + let t0 = localtime() - 43200 + call test_settime(t0) + new Xfile + call feedkeys("ione\<Esc>", 'xt') + set ul=100 + call test_settime(t0 + 1) + call feedkeys("otwo\<Esc>", 'xt') + set ul=100 + call test_settime(t0 + 2) + call feedkeys("othree\<Esc>", 'xt') + set ul=100 + w + wundo Xundofile + bwipe! + " restore normal timestamps. + call test_settime(0) + new Xfile + rundo Xundofile + earlier 1d + call assert_equal('', getline(1)) + bwipe! + call delete('Xfile') + call delete('Xundofile') +endfunc diff --git a/src/nvim/testdir/test_utf8.vim b/src/nvim/testdir/test_utf8.vim new file mode 100644 index 0000000000..24e3db86fb --- /dev/null +++ b/src/nvim/testdir/test_utf8.vim @@ -0,0 +1,65 @@ +" Tests for Unicode manipulations +if !has('multi_byte') + finish +endif + + +" Visual block Insert adjusts for multi-byte char +func Test_visual_block_insert() + new + call setline(1, ["aaa", "ã‚ã‚ã‚", "bbb"]) + exe ":norm! gg0l\<C-V>jjIx\<Esc>" + call assert_equal(['axaa', 'xã‚ã‚ã‚', 'bxbb'], getline(1, '$')) + bwipeout! +endfunc + +" Test for built-in function strchars() +func Test_strchars() + let inp = ["a", "ã‚ã„a", "A\u20dd", "A\u20dd\u20dd", "\u20dd"] + let exp = [[1, 1, 1], [3, 3, 3], [2, 2, 1], [3, 3, 1], [1, 1, 1]] + for i in range(len(inp)) + call assert_equal(exp[i][0], strchars(inp[i])) + call assert_equal(exp[i][1], strchars(inp[i], 0)) + call assert_equal(exp[i][2], strchars(inp[i], 1)) + endfor +endfunc + +" Test for customlist completion +function! CustomComplete1(lead, line, pos) + return ['ã‚', 'ã„'] +endfunction + +function! CustomComplete2(lead, line, pos) + return ['ã‚ãŸã—', 'ã‚ãŸã¾', 'ã‚ãŸã‚Šã‚'] +endfunction + +function! CustomComplete3(lead, line, pos) + return ['Nã“', 'Nã‚“', 'Nã¶'] +endfunction + +func Test_customlist_completion() + command -nargs=1 -complete=customlist,CustomComplete1 Test1 echo + call feedkeys(":Test1 \<C-L>\<C-B>\"\<CR>", 'itx') + call assert_equal('"Test1 ', getreg(':')) + + command -nargs=1 -complete=customlist,CustomComplete2 Test2 echo + call feedkeys(":Test2 \<C-L>\<C-B>\"\<CR>", 'itx') + call assert_equal('"Test2 ã‚ãŸ', getreg(':')) + + command -nargs=1 -complete=customlist,CustomComplete3 Test3 echo + call feedkeys(":Test3 \<C-L>\<C-B>\"\<CR>", 'itx') + call assert_equal('"Test3 N', getreg(':')) + + call garbagecollect(1) +endfunc + +" Yank one 3 byte character and check the mark columns. +func Test_getvcol() + new + call setline(1, "x\u2500x") + normal 0lvy + call assert_equal(2, col("'[")) + call assert_equal(4, col("']")) + call assert_equal(2, virtcol("'[")) + call assert_equal(2, virtcol("']")) +endfunc diff --git a/src/nvim/testdir/test_viml.vim b/src/nvim/testdir/test_vimscript.vim index a2997b6d4d..4e0f1bbd2f 100644 --- a/src/nvim/testdir/test_viml.vim +++ b/src/nvim/testdir/test_vimscript.vim @@ -1062,6 +1062,157 @@ func Test_echo_and_string() call assert_equal(["{'a': [], 'b': []}", \ "{'a': [], 'b': []}"], l) +"------------------------------------------------------------------------------- +" Test 94: 64-bit Numbers {{{1 +"------------------------------------------------------------------------------- + +func Test_num64() + if !has('num64') + return + endif + + call assert_notequal( 4294967296, 0) + call assert_notequal(-4294967296, 0) + call assert_equal( 4294967296, 0xFFFFffff + 1) + call assert_equal(-4294967296, -0xFFFFffff - 1) + + call assert_equal( 9223372036854775807, 1 / 0) + call assert_equal(-9223372036854775807, -1 / 0) + call assert_equal(-9223372036854775807 - 1, 0 / 0) + + call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150)) + call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150)) + + let rng = range(0xFFFFffff, 0x100000001) + call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng) + call assert_equal(0x100000001, max(rng)) + call assert_equal(0xFFFFffff, min(rng)) + call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N')) +endfunc + +"------------------------------------------------------------------------------- +" Test 95: lines of :append, :change, :insert {{{1 +"------------------------------------------------------------------------------- + +function! DefineFunction(name, body) + let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n") + exec func +endfunction + +func Test_script_lines() + " :append + try + call DefineFunction('T_Append', [ + \ 'append', + \ 'py <<EOS', + \ '.', + \ ]) + catch + call assert_report("Can't define function") + endtry + try + call DefineFunction('T_Append', [ + \ 'append', + \ 'abc', + \ ]) + call assert_report("Shouldn't be able to define function") + catch + call assert_exception('Vim(function):E126: Missing :endfunction') + endtry + + " :change + try + call DefineFunction('T_Change', [ + \ 'change', + \ 'py <<EOS', + \ '.', + \ ]) + catch + call assert_report("Can't define function") + endtry + try + call DefineFunction('T_Change', [ + \ 'change', + \ 'abc', + \ ]) + call assert_report("Shouldn't be able to define function") + catch + call assert_exception('Vim(function):E126: Missing :endfunction') + endtry + + " :insert + try + call DefineFunction('T_Insert', [ + \ 'insert', + \ 'py <<EOS', + \ '.', + \ ]) + catch + call assert_report("Can't define function") + endtry + try + call DefineFunction('T_Insert', [ + \ 'insert', + \ 'abc', + \ ]) + call assert_report("Shouldn't be able to define function") + catch + call assert_exception('Vim(function):E126: Missing :endfunction') + endtry +endfunc + +"------------------------------------------------------------------------------- +" Test 96: line continuation {{{1 +" +" Undefined behavior was detected by ubsan with line continuation +" after an empty line. +"------------------------------------------------------------------------------- +func Test_script_emty_line_continuation() + + \ +endfunc + +"------------------------------------------------------------------------------- +" Test 97: bitwise functions {{{1 +"------------------------------------------------------------------------------- +func Test_bitwise_functions() + " and + call assert_equal(127, and(127, 127)) + call assert_equal(16, and(127, 16)) + call assert_equal(0, and(127, 128)) + call assert_fails("call and(1.0, 1)", 'E805:') + call assert_fails("call and([], 1)", 'E745:') + call assert_fails("call and({}, 1)", 'E728:') + call assert_fails("call and(1, 1.0)", 'E805:') + call assert_fails("call and(1, [])", 'E745:') + call assert_fails("call and(1, {})", 'E728:') + " or + call assert_equal(23, or(16, 7)) + call assert_equal(15, or(8, 7)) + call assert_equal(123, or(0, 123)) + call assert_fails("call or(1.0, 1)", 'E805:') + call assert_fails("call or([], 1)", 'E745:') + call assert_fails("call or({}, 1)", 'E728:') + call assert_fails("call or(1, 1.0)", 'E805:') + call assert_fails("call or(1, [])", 'E745:') + call assert_fails("call or(1, {})", 'E728:') + " xor + call assert_equal(0, xor(127, 127)) + call assert_equal(111, xor(127, 16)) + call assert_equal(255, xor(127, 128)) + call assert_fails("call xor(1.0, 1)", 'E805:') + call assert_fails("call xor([], 1)", 'E745:') + call assert_fails("call xor({}, 1)", 'E728:') + call assert_fails("call xor(1, 1.0)", 'E805:') + call assert_fails("call xor(1, [])", 'E745:') + call assert_fails("call xor(1, {})", 'E728:') + " invert + call assert_equal(65408, and(invert(127), 65535)) + call assert_equal(65519, and(invert(16), 65535)) + call assert_equal(65407, and(invert(128), 65535)) + call assert_fails("call invert(1.0)", 'E805:') + call assert_fails("call invert([])", 'E745:') + call assert_fails("call invert({})", 'E728:') endfunc "------------------------------------------------------------------------------- diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim index b7f41a711b..9d61921988 100644 --- a/src/nvim/testdir/test_window_cmd.vim +++ b/src/nvim/testdir/test_window_cmd.vim @@ -67,4 +67,360 @@ function Test_window_cmd_wincmd_gf() augroup! test_window_cmd_wincmd_gf endfunc -" vim: sw=2 et +func Test_next_split_all() + " This was causing an illegal memory access. + n x + norm axxx + split + split + s/x + s/x + all + bwipe! +endfunc + +func Test_window_quit() + e Xa + split Xb + call assert_equal(2, winnr('$')) + call assert_equal('Xb', bufname(winbufnr(1))) + call assert_equal('Xa', bufname(winbufnr(2))) + + wincmd q + call assert_equal(1, winnr('$')) + call assert_equal('Xa', bufname(winbufnr(1))) + + bw Xa Xb +endfunc + +func Test_window_horizontal_split() + call assert_equal(1, winnr('$')) + 3wincmd s + call assert_equal(2, winnr('$')) + call assert_equal(3, winheight(0)) + call assert_equal(winwidth(1), winwidth(2)) + + call assert_fails('botright topleft wincmd s', 'E442:') + bw +endfunc + +func Test_window_vertical_split() + call assert_equal(1, winnr('$')) + 3wincmd v + call assert_equal(2, winnr('$')) + call assert_equal(3, winwidth(0)) + call assert_equal(winheight(1), winheight(2)) + + call assert_fails('botright topleft wincmd v', 'E442:') + bw +endfunc + +func Test_window_split_edit_alternate() + e Xa + e Xb + + wincmd ^ + call assert_equal('Xa', bufname(winbufnr(1))) + call assert_equal('Xb', bufname(winbufnr(2))) + + bw Xa Xb +endfunc + +func Test_window_preview() + " Open a preview window + pedit Xa + call assert_equal(2, winnr('$')) + call assert_equal(0, &previewwindow) + + " Go to the preview window + wincmd P + call assert_equal(1, &previewwindow) + + " Close preview window + wincmd z + call assert_equal(1, winnr('$')) + call assert_equal(0, &previewwindow) + + call assert_fails('wincmd P', 'E441:') +endfunc + +func Test_window_exchange() + e Xa + + " Nothing happens with window exchange when there is 1 window + wincmd x + call assert_equal(1, winnr('$')) + + split Xb + split Xc + + call assert_equal('Xc', bufname(winbufnr(1))) + call assert_equal('Xb', bufname(winbufnr(2))) + call assert_equal('Xa', bufname(winbufnr(3))) + + " Exchange current window 1 with window 3 + 3wincmd x + call assert_equal('Xa', bufname(winbufnr(1))) + call assert_equal('Xb', bufname(winbufnr(2))) + call assert_equal('Xc', bufname(winbufnr(3))) + + " Exchange window with next when at the top window + wincmd x + call assert_equal('Xb', bufname(winbufnr(1))) + call assert_equal('Xa', bufname(winbufnr(2))) + call assert_equal('Xc', bufname(winbufnr(3))) + + " Exchange window with next when at the middle window + wincmd j + wincmd x + call assert_equal('Xb', bufname(winbufnr(1))) + call assert_equal('Xc', bufname(winbufnr(2))) + call assert_equal('Xa', bufname(winbufnr(3))) + + " Exchange window with next when at the bottom window. + " When there is no next window, it exchanges with the previous window. + wincmd j + wincmd x + call assert_equal('Xb', bufname(winbufnr(1))) + call assert_equal('Xa', bufname(winbufnr(2))) + call assert_equal('Xc', bufname(winbufnr(3))) + + bw Xa Xb Xc +endfunc + +func Test_window_rotate() + e Xa + split Xb + split Xc + call assert_equal('Xc', bufname(winbufnr(1))) + call assert_equal('Xb', bufname(winbufnr(2))) + call assert_equal('Xa', bufname(winbufnr(3))) + + " Rotate downwards + wincmd r + call assert_equal('Xa', bufname(winbufnr(1))) + call assert_equal('Xc', bufname(winbufnr(2))) + call assert_equal('Xb', bufname(winbufnr(3))) + + 2wincmd r + call assert_equal('Xc', bufname(winbufnr(1))) + call assert_equal('Xb', bufname(winbufnr(2))) + call assert_equal('Xa', bufname(winbufnr(3))) + + " Rotate upwards + wincmd R + call assert_equal('Xb', bufname(winbufnr(1))) + call assert_equal('Xa', bufname(winbufnr(2))) + call assert_equal('Xc', bufname(winbufnr(3))) + + 2wincmd R + call assert_equal('Xc', bufname(winbufnr(1))) + call assert_equal('Xb', bufname(winbufnr(2))) + call assert_equal('Xa', bufname(winbufnr(3))) + + bot vsplit + call assert_fails('wincmd R', 'E443:') + + bw Xa Xb Xc +endfunc + +func Test_window_height() + e Xa + split Xb + + let [wh1, wh2] = [winheight(1), winheight(2)] + " Active window (1) should have the same height or 1 more + " than the other window. + call assert_inrange(wh2, wh2 + 1, wh1) + + wincmd - + call assert_equal(wh1 - 1, winheight(1)) + call assert_equal(wh2 + 1, winheight(2)) + + wincmd + + call assert_equal(wh1, winheight(1)) + call assert_equal(wh2, winheight(2)) + + 2wincmd _ + call assert_equal(2, winheight(1)) + call assert_equal(wh1 + wh2 - 2, winheight(2)) + + wincmd = + call assert_equal(wh1, winheight(1)) + call assert_equal(wh2, winheight(2)) + + 2wincmd _ + set winfixheight + split Xc + let [wh1, wh2, wh3] = [winheight(1), winheight(2), winheight(3)] + call assert_equal(2, winheight(2)) + call assert_inrange(wh3, wh3 + 1, wh1) + 3wincmd + + call assert_equal(2, winheight(2)) + call assert_equal(wh1 + 3, winheight(1)) + call assert_equal(wh3 - 3, winheight(3)) + wincmd = + call assert_equal(2, winheight(2)) + call assert_equal(wh1, winheight(1)) + call assert_equal(wh3, winheight(3)) + + wincmd j + set winfixheight& + + wincmd = + let [wh1, wh2, wh3] = [winheight(1), winheight(2), winheight(3)] + " Current window (2) should have the same height or 1 more + " than the other windows. + call assert_inrange(wh1, wh1 + 1, wh2) + call assert_inrange(wh3, wh3 + 1, wh2) + + bw Xa Xb Xc +endfunc + +func Test_window_width() + e Xa + vsplit Xb + + let [ww1, ww2] = [winwidth(1), winwidth(2)] + " Active window (1) should have the same width or 1 more + " than the other window. + call assert_inrange(ww2, ww2 + 1, ww1) + + wincmd < + call assert_equal(ww1 - 1, winwidth(1)) + call assert_equal(ww2 + 1, winwidth(2)) + + wincmd > + call assert_equal(ww1, winwidth(1)) + call assert_equal(ww2, winwidth(2)) + + 2wincmd | + call assert_equal(2, winwidth(1)) + call assert_equal(ww1 + ww2 - 2, winwidth(2)) + + wincmd = + call assert_equal(ww1, winwidth(1)) + call assert_equal(ww2, winwidth(2)) + + 2wincmd | + set winfixwidth + vsplit Xc + let [ww1, ww2, ww3] = [winwidth(1), winwidth(2), winwidth(3)] + " FIXME: commented out: I would expect the width of 2nd window to + " remain 2 but it's actually 1?! + "call assert_equal(2, winwidth(2)) + call assert_inrange(ww3, ww3 + 1, ww1) + 3wincmd > + " FIXME: commented out: I would expect the width of 2nd window to + " remain 2 but it's actually 1?! + "call assert_equal(2, winwidth(2)) + call assert_equal(ww1 + 3, winwidth(1)) + call assert_equal(ww3 - 3, winwidth(3)) + wincmd = + " FIXME: commented out: I would expect the width of 2nd window to + " remain 2 but it's actually 1?! + "call assert_equal(2, winwidth(2)) + call assert_equal(ww1, winwidth(1)) + call assert_equal(ww3, winwidth(3)) + + wincmd l + set winfixwidth& + + wincmd = + let [ww1, ww2, ww3] = [winwidth(1), winwidth(2), winwidth(3)] + " Current window (2) should have the same width or 1 more + " than the other windows. + call assert_inrange(ww1, ww1 + 1, ww2) + call assert_inrange(ww3, ww3 + 1, ww2) + + bw Xa Xb Xc +endfunc + +func Test_equalalways_on_close() + set equalalways + vsplit + windo split + split + wincmd J + " now we have a frame top-left with two windows, a frame top-right with two + " windows and a frame at the bottom, full-width. + let height_1 = winheight(1) + let height_2 = winheight(2) + let height_3 = winheight(3) + let height_4 = winheight(4) + " closing the bottom window causes all windows to be resized. + close + call assert_notequal(height_1, winheight(1)) + call assert_notequal(height_2, winheight(2)) + call assert_notequal(height_3, winheight(3)) + call assert_notequal(height_4, winheight(4)) + call assert_equal(winheight(1), winheight(3)) + call assert_equal(winheight(2), winheight(4)) + + 1wincmd w + split + 4wincmd w + resize + 5 + " left column has three windows, equalized heights. + " right column has two windows, top one a bit higher + let height_1 = winheight(1) + let height_2 = winheight(2) + let height_4 = winheight(4) + let height_5 = winheight(5) + 3wincmd w + " closing window in left column equalizes heights in left column but not in + " the right column + close + call assert_notequal(height_1, winheight(1)) + call assert_notequal(height_2, winheight(2)) + call assert_equal(height_4, winheight(3)) + call assert_equal(height_5, winheight(4)) + + only + set equalalways& +endfunc + +func Test_window_jump_tag() + help + /iccf + call assert_match('^|iccf|', getline('.')) + call assert_equal(2, winnr('$')) + 2wincmd } + call assert_equal(3, winnr('$')) + call assert_match('^|iccf|', getline('.')) + wincmd k + call assert_match('\*iccf\*', getline('.')) + call assert_equal(2, winheight(0)) + + wincmd z + set previewheight=4 + help + /bugs + wincmd } + wincmd k + call assert_match('\*bugs\*', getline('.')) + call assert_equal(4, winheight(0)) + set previewheight& + + %bw! +endfunc + +func Test_window_newtab() + e Xa + + call assert_equal(1, tabpagenr('$')) + call assert_equal("\nAlready only one window", execute('wincmd T')) + + split Xb + split Xc + + wincmd T + call assert_equal(2, tabpagenr('$')) + call assert_equal(['Xb', 'Xa'], map(tabpagebuflist(1), 'bufname(v:val)')) + call assert_equal(['Xc' ], map(tabpagebuflist(2), 'bufname(v:val)')) + + %bw! +endfunc + + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_window_id.vim b/src/nvim/testdir/test_window_id.vim index 66656e1d0a..b3b506d04d 100644 --- a/src/nvim/testdir/test_window_id.vim +++ b/src/nvim/testdir/test_window_id.vim @@ -92,3 +92,12 @@ func Test_win_getid() only! endfunc + +func Test_win_getid_curtab() + tabedit X + tabfirst + copen + only + call assert_equal(win_getid(1), win_getid(1, 1)) + tabclose! +endfunc diff --git a/src/nvim/testdir/test_writefile.vim b/src/nvim/testdir/test_writefile.vim new file mode 100644 index 0000000000..d820c580ac --- /dev/null +++ b/src/nvim/testdir/test_writefile.vim @@ -0,0 +1,16 @@ + +function! Test_WriteFile() + let f = tempname() + call writefile(["over","written"], f, "b") + call writefile(["hello","world"], f, "b") + call writefile(["!", "good"], f, "a") + call writefile(["morning"], f, "ab") + call writefile(["", "vimmers"], f, "ab") + let l = readfile(f) + call assert_equal("hello", l[0]) + call assert_equal("world!", l[1]) + call assert_equal("good", l[2]) + call assert_equal("morning", l[3]) + call assert_equal("vimmers", l[4]) + call delete(f) +endfunction diff --git a/src/nvim/testdir/view_util.vim b/src/nvim/testdir/view_util.vim new file mode 100644 index 0000000000..eb92630761 --- /dev/null +++ b/src/nvim/testdir/view_util.vim @@ -0,0 +1,30 @@ +" Functions about view shared by several tests + +" ScreenLines(lnum, width) or +" ScreenLines([start, end], width) +function! ScreenLines(lnum, width) abort + redraw! + if type(a:lnum) == v:t_list + let start = a:lnum[0] + let end = a:lnum[1] + else + let start = a:lnum + let end = a:lnum + endif + let lines = [] + for l in range(start, end) + let lines += [join(map(range(1, a:width), 'nr2char(screenchar(l, v:val))'), '')] + endfor + return lines +endfunction + +function! NewWindow(height, width) abort + exe a:height . 'new' + exe a:width . 'vsp' + redraw! +endfunction + +function! CloseWindow() abort + bw! + redraw! +endfunction diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 8e5adb14f9..03587d68f0 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -1,3 +1,6 @@ +// 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 "nvim/tui/input.h" #include "nvim/vim.h" @@ -44,7 +47,13 @@ void term_input_init(TermInput *input, Loop *loop) int curflags = termkey_get_canonflags(input->tk); termkey_set_canonflags(input->tk, curflags | TERMKEY_CANON_DELBS); // setup input handle +#ifdef WIN32 + uv_tty_init(loop, &input->tty_in, 0, 1); + uv_tty_set_mode(&input->tty_in, UV_TTY_MODE_RAW); + rstream_init_stream(&input->read_stream, &input->tty_in, 0xfff); +#else rstream_init_fd(loop, &input->read_stream, input->in_fd, 0xfff); +#endif // initialize a timer handle for handling ESC with libtermkey time_watcher_init(loop, &input->timer_handle, input); } @@ -99,7 +108,7 @@ static void flush_input(TermInput *input, bool wait_until_empty) size_t drain_boundary = wait_until_empty ? 0 : 0xff; do { uv_mutex_lock(&input->key_buffer_mutex); - loop_schedule(&main_loop, event_create(1, wait_input_enqueue, 1, input)); + loop_schedule(&main_loop, event_create(wait_input_enqueue, 1, input)); input->waiting = true; while (input->waiting) { uv_cond_wait(&input->key_buffer_cond, &input->key_buffer_mutex); @@ -220,12 +229,14 @@ static int get_key_code_timeout(void) { Integer ms = -1; // Check 'ttimeout' to determine if we should send ESC after 'ttimeoutlen'. - // See :help 'ttimeout' for more information Error err = ERROR_INIT; if (nvim_get_option(cstr_as_string("ttimeout"), &err).data.boolean) { - ms = nvim_get_option(cstr_as_string("ttimeoutlen"), &err).data.integer; + Object rv = nvim_get_option(cstr_as_string("ttimeoutlen"), &err); + if (!ERROR_SET(&err)) { + ms = rv.data.integer; + } } - + api_clear_error(&err); return (int)ms; } @@ -347,7 +358,7 @@ static void read_cb(Stream *stream, RBuffer *buf, size_t c, void *data, stream_close(&input->read_stream, NULL, NULL); multiqueue_put(input->loop->fast_events, restart_reading, 1, input); } else { - loop_schedule(&main_loop, event_create(1, input_done_event, 0)); + loop_schedule(&main_loop, event_create(input_done_event, 0)); } return; } diff --git a/src/nvim/tui/input.h b/src/nvim/tui/input.h index 7d59cf5c6a..573cc9d683 100644 --- a/src/nvim/tui/input.h +++ b/src/nvim/tui/input.h @@ -17,6 +17,9 @@ typedef struct term_input { #endif TimeWatcher timer_handle; Loop *loop; +#ifdef WIN32 + uv_tty_t tty_in; +#endif Stream read_stream; RBuffer *key_buffer; uv_mutex_t key_buffer_mutex; diff --git a/src/nvim/tui/terminfo.c b/src/nvim/tui/terminfo.c new file mode 100644 index 0000000000..586fafba97 --- /dev/null +++ b/src/nvim/tui/terminfo.c @@ -0,0 +1,123 @@ +// 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 + +// Built-in fallback terminfo entries. + +#include <unibilium.h> + +#include "nvim/tui/terminfo.h" +#include "nvim/tui/tui.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "tui/terminfo.c.generated.h" +#endif + +// One creates the dumps from terminfo.src by using +// od -t d1 -w | cut -c9- | sed -e 's/\>/,/g' +// on the compiled files. + +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +// This is a 256-colour terminfo description that lacks true-colour and +// DECSTBM/DECSLRM/DECLRMM capabilities that xterm actually has. +static const signed char xterm_256colour_terminfo[] = { + 26, 1, 37, 0, 29, 0, 15, 0, 105, 1, -42, 5, 120, 116, 101, 114, 109, 45, 50, 53, 54, 99, 111, 108, 111, 114, 124, 120, 116, 101, 114, 109, 32, 119, 105, 116, 104, 32, 50, 53, 54, 32, 99, 111, 108, 111, 114, 115, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 80, 0, 8, 0, 24, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 127, 0, 0, 4, 0, 6, 0, 8, 0, 25, 0, 30, 0, 38, 0, 42, 0, 46, 0, -1, -1, 57, 0, 74, 0, 76, 0, 80, 0, 87, 0, -1, -1, 89, 0, 102, 0, -1, -1, 106, 0, 110, 0, 120, 0, 124, 0, -1, -1, -1, -1,-128, 0,-124, 0,-119, 0,-114, 0, -1, -1,-105, 0,-100, 0, -95, 0, -1, -1, -90, 0, -85, 0, -80, 0, -75, 0, -66, 0, -62, 0, -55, 0, -1, -1, -46, 0, -41, 0, -35, 0, -29, 0, -1, -1, -1, -1, -1, -1, -11, 0, -1, -1, -1, -1, -1, -1, 7, 1, -1, -1, 11, 1, -1, -1, -1, -1, -1, -1, 13, 1, -1, -1, 18, 1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 1, 26, 1, 32, 1, 36, 1, 40, 1, 44, 1, 50, 1, 56, 1, 62, 1, 68, 1, 74, 1, 78, 1, -1, -1, 83, 1, -1, -1, 87, 1, 92, 1, 97, 1, 101, 1, 108, 1, -1, -1, 115, 1, 119, 1, 127, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-121, 1,-112, 1, -1, -1, -1, -1,-103, 1, -94, 1, -85, 1, -76, 1, -67, 1, -58, 1, -49, 1, -40, 1, -31, 1, -22, 1, -1, -1, -1, -1, -1, -1, -13, 1, -9, 1, -4, 1, -1, -1, 1, 2, 10, 2, -1, -1, -1, -1, 28, 2, 31, 2, 42, 2, 45, 2, 47, 2, 50, 2,-113, 2, -1, -1,-110, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-108, 2, -1, -1, -1, -1, -1, -1, -1, -1,-104, 2, -1, -1, -51, 2, -1, -1, -1, -1, -47, 2, -41, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -35, 2, -31, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -27, 2, -1, -1, -1, -1, -20, 2, -1, -1, -1, -1, -1, -1, -1, -1, -13, 2, -6, 2, 1, 3, -1, -1, -1, -1, 8, 3, -1, -1, 15, 3, -1, -1, -1, -1, -1, -1, 22, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, 3, 35, 3, 41, 3, 48, 3, 55, 3, 62, 3, 69, 3, 77, 3, 85, 3, 93, 3, 101, 3, 109, 3, 117, 3, 125, 3,-123, 3,-116, 3,-109, 3,-102, 3, -95, 3, -87, 3, -79, 3, -71, 3, -63, 3, -55, 3, -47, 3, -39, 3, -31, 3, -24, 3, -17, 3, -10, 3, -3, 3, 5, 4, 13, 4, 21, 4, 29, 4, 37, 4, 45, 4, 53, 4, 61, 4, 68, 4, 75, 4, 82, 4, 89, 4, 97, 4, 105, 4, 113, 4, 121, 4,-127, 4,-119, 4,-111, 4,-103, 4, -96, 4, -89, 4, -82, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -77, 4, -66, 4, -61, 4, -42, 4, -38, 4, -29, 4, -22, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 72, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 77, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 83, 5, -1, -1, -1, -1, -1, -1, 87, 5,-106, 5, 27, 91, 90, 0, 7, 0, 13, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 114, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 50, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 71, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 0, 8, 0, 27, 91, 63, 49, 50, 108, 27, 91, 63, 50, 53, 104, 0, 27, 91, 67, 0, 27, 91, 65, 0, 27, 91, 63, 49, 50, 59, 50, 53, 104, 0, 27, 91, 80, 0, 27, 91, 77, 0, 27, 40, 48, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 27, 91, 63, 49, 48, 52, 57, 104, 0, 27, 91, 50, 109, 0, 27, 91, 52, 104, 0, 27, 91, 56, 109, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 27, 91, 37, 112, 49, 37, 100, 88, 0, 27, 40, 66, 0, 27, 40, 66, 27, 91, 109, 0, 27, 91, 63, 49, 48, 52, 57, 108, 0, 27, 91, 52, 108, 0, 27, 91, 50, 55, 109, 0, 27, 91, 50, 52, 109, 0, 27, 91, 63, 53, 104, 36, 60, 49, 48, 48, 47, 62, 27, 91, 63, 53, 108, 0, 27, 91, 33, 112, 27, 91, 63, 51, 59, 52, 108, 27, 91, 52, 108, 27, 62, 0, 27, 91, 76, 0, 8, 0, 27, 91, 51, 126, 0, 27, 79, 66, 0, 27, 79, 80, 0, 27, 91, 50, 49, 126, 0, 27, 79, 81, 0, 27, 79, 82, 0, 27, 79, 83, 0, 27, 91, 49, 53, 126, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 79, 72, 0, 27, 91, 50, 126, 0, 27, 79, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 79, 67, 0, 27, 91, 49, 59, 50, 66, 0, 27, 91, 49, 59, 50, 65, 0, 27, 79, 65, 0, 27, 91, 63, 49, 108, 27, 62, 0, 27, 91, 63, 49, 104, 27, 61, 0, 27, 91, 63, 49, 48, 51, 52, 108, 0, 27, 91, 63, 49, 48, 51, 52, 104, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 83, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 84, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 91, 105, 0, 27, 91, 52, 105, 0, 27, 91, 53, 105, 0, 27, 99, 27, 93, 49, 48, 52, 7, 0, 27, 91, 33, 112, 27, 91, 63, 51, 59, 52, 108, 27, 91, 52, 108, 27, 62, 0, 27, 56, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 100, 0, 27, 55, 0, 10, 0, 27, 77, 0, 37, 63, 37, 112, 57, 37, 116, 27, 40, 48, 37, 101, 27, 40, 66, 37, 59, 27, 91, 48, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 53, 37, 116, 59, 50, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 49, 37, 112, 51, 37, 124, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 37, 63, 37, 112, 55, 37, 116, 59, 56, 37, 59, 109, 0, 27, 72, 0, 9, 0, 27, 79, 69, 0, 96, 96, 97, 97, 102, 102, 103, 103, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 0, 27, 91, 90, 0, 27, 91, 63, 55, 104, 0, 27, 91, 63, 55, 108, 0, 27, 79, 70, 0, 27, 79, 77, 0, 27, 91, 51, 59, 50, 126, 0, 27, 91, 49, 59, 50, 70, 0, 27, 91, 49, 59, 50, 72, 0, 27, 91, 50, 59, 50, 126, 0, 27, 91, 49, 59, 50, 68, 0, 27, 91, 54, 59, 50, 126, 0, 27, 91, 53, 59, 50, 126, 0, 27, 91, 49, 59, 50, 67, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 49, 59, 50, 80, 0, 27, 91, 49, 59, 50, 81, 0, 27, 91, 49, 59, 50, 82, 0, 27, 91, 49, 59, 50, 83, 0, 27, 91, 49, 53, 59, 50, 126, 0, 27, 91, 49, 55, 59, 50, 126, 0, 27, 91, 49, 56, 59, 50, 126, 0, 27, 91, 49, 57, 59, 50, 126, 0, 27, 91, 50, 48, 59, 50, 126, 0, 27, 91, 50, 49, 59, 50, 126, 0, 27, 91, 50, 51, 59, 50, 126, 0, 27, 91, 50, 52, 59, 50, 126, 0, 27, 91, 49, 59, 53, 80, 0, 27, 91, 49, 59, 53, 81, 0, 27, 91, 49, 59, 53, 82, 0, 27, 91, 49, 59, 53, 83, 0, 27, 91, 49, 53, 59, 53, 126, 0, 27, 91, 49, 55, 59, 53, 126, 0, 27, 91, 49, 56, 59, 53, 126, 0, 27, 91, 49, 57, 59, 53, 126, 0, 27, 91, 50, 48, 59, 53, 126, 0, 27, 91, 50, 49, 59, 53, 126, 0, 27, 91, 50, 51, 59, 53, 126, 0, 27, 91, 50, 52, 59, 53, 126, 0, 27, 91, 49, 59, 54, 80, 0, 27, 91, 49, 59, 54, 81, 0, 27, 91, 49, 59, 54, 82, 0, 27, 91, 49, 59, 54, 83, 0, 27, 91, 49, 53, 59, 54, 126, 0, 27, 91, 49, 55, 59, 54, 126, 0, 27, 91, 49, 56, 59, 54, 126, 0, 27, 91, 49, 57, 59, 54, 126, 0, 27, 91, 50, 48, 59, 54, 126, 0, 27, 91, 50, 49, 59, 54, 126, 0, 27, 91, 50, 51, 59, 54, 126, 0, 27, 91, 50, 52, 59, 54, 126, 0, 27, 91, 49, 59, 51, 80, 0, 27, 91, 49, 59, 51, 81, 0, 27, 91, 49, 59, 51, 82, 0, 27, 91, 49, 59, 51, 83, 0, 27, 91, 49, 53, 59, 51, 126, 0, 27, 91, 49, 55, 59, 51, 126, 0, 27, 91, 49, 56, 59, 51, 126, 0, 27, 91, 49, 57, 59, 51, 126, 0, 27, 91, 50, 48, 59, 51, 126, 0, 27, 91, 50, 49, 59, 51, 126, 0, 27, 91, 50, 51, 59, 51, 126, 0, 27, 91, 50, 52, 59, 51, 126, 0, 27, 91, 49, 59, 52, 80, 0, 27, 91, 49, 59, 52, 81, 0, 27, 91, 49, 59, 52, 82, 0, 27, 91, 49, 75, 0, 27, 91, 37, 105, 37, 100, 59, 37, 100, 82, 0, 27, 91, 54, 110, 0, 27, 91, 63, 37, 91, 59, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 93, 99, 0, 27, 91, 99, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 93, 49, 48, 52, 7, 0, 27, 93, 52, 59, 37, 112, 49, 37, 100, 59, 114, 103, 98, 58, 37, 112, 50, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 47, 37, 112, 51, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 47, 37, 112, 52, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 27, 92, 0, 27, 91, 51, 109, 0, 27, 91, 50, 51, 109, 0, 27, 91, 77, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 51, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 57, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 51, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 52, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 49, 48, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 52, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0 +}; +// Taken from unibilium/t/static_tmux.c as of 2015-08-14. +// This is an 256-colour terminfo description that lacks +// status line capabilities that tmux actually has. +static const signed char tmux_256colour_terminfo[] = { + 26, 1, 56, 0, 15, 0, 15, 0, 105, 1, -48, 2, 116, 109, 117, 120, 124, 86, 84, 32, 49, 48, 48, 47, 65, 78, 83, 73, 32, 88, 51, 46, 54, 52, 32, 118, 105, 114, 116, 117, 97, 108, 32, 116, 101, 114, 109, 105, 110, 97, 108, 32, 119, 105, 116, 104, 32, 50, 53, 54, 32, 99, 111, 108, 111, 114, 115, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 80, 0, 8, 0, 24, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 127, 0, 0, 4, 0, 6, 0, 8, 0, 25, 0, 30, 0, 37, 0, 41, 0, -1, -1, -1, -1, 45, 0, 62, 0, 64, 0, 68, 0, 75, 0, -1, -1, 77, 0, 89, 0, -1, -1, 93, 0, 96, 0, 102, 0, 106, 0, -1, -1, -1, -1, 110, 0, 112, 0, 117, 0, 122, 0, -1, -1, -1, -1, 123, 0, -1, -1, -1, -1, -128, 0, -123, 0, -118, 0, -1, -1, -113, 0, -111, 0, -106, 0, -1, -1, -105, 0, -100, 0, -94, 0, -88, 0, -1, -1, -1, -1, -1, -1, -85, 0, -1, -1, -1, -1, -1, -1, -81, 0, -1, -1, -77, 0, -1, -1, -1, -1, -1, -1, -75, 0, -1, -1, -70, 0, -1, -1, -1, -1, -1, -1, -1, -1, -66, 0, -62, 0, -56, 0, -52, 0, -48, 0, -44, 0, -38, 0, -32, 0, -26, 0, -20, 0, -14, 0, -9, 0, -1, -1, -4, 0, -1, -1, 0, 1, 5, 1, 10, 1, -1, -1, -1, -1, -1, -1, 14, 1, 18, 1, 26, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, 1, -1, -1, 37, 1, 46, 1, 55, 1, 64, 1, -1, -1, 73, 1, 82, 1, 91, 1, -1, -1, 100, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 109, 1, -1, -1, -1, -1, 126, 1, -1, -1, -127, 1, -124, 1, -122, 1, -119, 1, -46, 1, -1, -1, -43, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -41, 1, -1, -1, 24, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 28, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, 2, 46, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 52, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 57, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 66, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 71, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 77, 2, -1, -1, -1, -1, -1, -1, 81, 2, -112, 2, 27, 91, 90, 0, 7, 0, 13, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 114, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 0, 8, 0, 27, 91, 51, 52, 104, 27, 91, 63, 50, 53, 104, 0, 27, 91, 67, 0, 27, 77, 0, 27, 91, 51, 52, 108, 0, 27, 91, 80, 0, 27, 91, 77, 0, 14, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 0, 27, 91, 52, 104, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 15, 0, 27, 91, 109, 15, 0, 0, 27, 91, 52, 108, 0, 27, 91, 50, 55, 109, 0, 27, 91, 50, 52, 109, 0, 27, 103, 0, 27, 41, 48, 0, 27, 91, 76, 0, 8, 0, 27, 91, 51, 126, 0, 27, 79, 66, 0, 27, 79, 80, 0, 27, 91, 50, 49, 126, 0, 27, 79, 81, 0, 27, 79, 82, 0, 27, 79, 83, 0, 27, 91, 49, 53, 126, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 91, 49, 126, 0, 27, 91, 50, 126, 0, 27, 79, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 79, 67, 0, 27, 79, 65, 0, 27, 91, 63, 49, 108, 27, 62, 0, 27, 91, 63, 49, 104, 27, 61, 0, 27, 69, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 99, 27, 91, 63, 49, 48, 48, 48, 108, 27, 91, 63, 50, 53, 104, 0, 27, 56, 0, 27, 55, 0, 10, 0, 27, 77, 0, 27, 91, 48, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 49, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 51, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 109, 37, 63, 37, 112, 57, 37, 116, 14, 37, 101, 15, 37, 59, 0, 27, 72, 0, 9, 0, 43, 43, 44, 44, 45, 45, 46, 46, 48, 48, 96, 96, 97, 97, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 0, 27, 91, 90, 0, 27, 40, 66, 27, 41, 48, 0, 27, 91, 52, 126, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 49, 75, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 91, 51, 109, 0, 27, 91, 50, 51, 109, 0, 27, 91, 77, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 51, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 57, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 51, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 52, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 49, 48, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 52, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0 +}; +// Taken from unibilium/t/static_screen-256color.c as of 2015-08-14. +// This is an 256-colour terminfo description that lacks +// status line capabilities that screen actually has. +static const signed char screen_256colour_terminfo[] = { + 26, 1, 43, 0, 43, 0, 15, 0, 105, 1, -43, 2, 115, 99, 114, 101, 101, 110, 45, 50, 53, 54, 99, 111, 108, 111, 114, 124, 71, 78, 85, 32, 83, 99, 114, 101, 101, 110, 32, 119, 105, 116, 104, 32, 50, 53, 54, 32, 99, 111, 108, 111, 114, 115, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 80, 0, 8, 0, 24, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 127, 0, 0, 4, 0, 6, 0, 8, 0, 25, 0, 30, 0, 37, 0, 41, 0, -1, -1, -1, -1, 45, 0, 62, 0, 64, 0, 68, 0, 75, 0, -1, -1, 77, 0, 89, 0, -1, -1, 93, 0, 96, 0, 102, 0, 106, 0, -1, -1, -1, -1, 110, 0, 112, 0, 117, 0, 122, 0, -1, -1, -1, -1, -125, 0, -1, -1, -1, -1, -120, 0, -115, 0, -110, 0, -1, -1, -105, 0, -103, 0, -98, 0, -1, -1, -89, 0, -84, 0, -78, 0, -72, 0, -1, -1, -1, -1, -1, -1, -69, 0, -1, -1, -1, -1, -1, -1, -65, 0, -1, -1, -61, 0, -1, -1, -1, -1, -1, -1, -59, 0, -1, -1, -54, 0, -1, -1, -1, -1, -1, -1, -1, -1, -50, 0, -46, 0, -40, 0, -36, 0, -32, 0, -28, 0, -22, 0, -16, 0, -10, 0, -4, 0, 2, 1, 7, 1, -1, -1, 12, 1, -1, -1, 16, 1, 21, 1, 26, 1, -1, -1, -1, -1, -1, -1, 30, 1, 34, 1, 42, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 1, -1, -1, 53, 1, 62, 1, 71, 1, 80, 1, -1, -1, 89, 1, 98, 1, 107, 1, -1, -1, 116, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 125, 1, -1, -1, -1, -1, -114, 1, -1, -1, -111, 1, -108, 1, -106, 1, -103, 1, -30, 1, -1, -1, -27, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -25, 1, -1, -1, 40, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 51, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, 2, 62, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 68, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 73, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 82, 2, -1, -1, -1, -1, -1, -1, 86, 2, -107, 2, 27, 91, 90, 0, 7, 0, 13, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 114, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 0, 8, 0, 27, 91, 51, 52, 104, 27, 91, 63, 50, 53, 104, 0, 27, 91, 67, 0, 27, 77, 0, 27, 91, 51, 52, 108, 0, 27, 91, 80, 0, 27, 91, 77, 0, 14, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 27, 91, 63, 49, 48, 52, 57, 104, 0, 27, 91, 52, 104, 0, 27, 91, 55, 109, 0, 27, 91, 51, 109, 0, 27, 91, 52, 109, 0, 15, 0, 27, 91, 109, 15, 0, 27, 91, 63, 49, 48, 52, 57, 108, 0, 27, 91, 52, 108, 0, 27, 91, 50, 51, 109, 0, 27, 91, 50, 52, 109, 0, 27, 103, 0, 27, 41, 48, 0, 27, 91, 76, 0, 8, 0, 27, 91, 51, 126, 0, 27, 79, 66, 0, 27, 79, 80, 0, 27, 91, 50, 49, 126, 0, 27, 79, 81, 0, 27, 79, 82, 0, 27, 79, 83, 0, 27, 91, 49, 53, 126, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 91, 49, 126, 0, 27, 91, 50, 126, 0, 27, 79, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 79, 67, 0, 27, 79, 65, 0, 27, 91, 63, 49, 108, 27, 62, 0, 27, 91, 63, 49, 104, 27, 61, 0, 27, 69, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 99, 27, 91, 63, 49, 48, 48, 48, 108, 27, 91, 63, 50, 53, 104, 0, 27, 56, 0, 27, 55, 0, 10, 0, 27, 77, 0, 27, 91, 48, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 49, 37, 116, 59, 51, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 51, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 109, 37, 63, 37, 112, 57, 37, 116, 14, 37, 101, 15, 37, 59, 0, 27, 72, 0, 9, 0, 43, 43, 44, 44, 45, 45, 46, 46, 48, 48, 96, 96, 97, 97, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 0, 27, 91, 90, 0, 27, 40, 66, 27, 41, 48, 0, 27, 91, 52, 126, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 49, 75, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 91, 77, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 51, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 57, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 51, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 52, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 49, 48, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 52, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 0, 3, 0, 1, 0, 24, 0, 52, 0, -112, 0, 1, 1, 0, 0, 1, 0, 0, 0, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 3, 0, 6, 0, 9, 0, 12, 0, 15, 0, 18, 0, 23, 0, 28, 0, 32, 0, 37, 0, 43, 0, 49, 0, 55, 0, 61, 0, 66, 0, 71, 0, 77, 0, 83, 0, 89, 0, 95, 0, 101, 0, 107, 0, 111, 0, 116, 0, 120, 0, 124, 0, -128, 0, 27, 40, 66, 0, 27, 40, 37, 112, 49, 37, 99, 0, 65, 88, 0, 71, 48, 0, 88, 84, 0, 85, 56, 0, 69, 48, 0, 83, 48, 0, 107, 68, 67, 53, 0, 107, 68, 67, 54, 0, 107, 68, 78, 0, 107, 68, 78, 53, 0, 107, 69, 78, 68, 53, 0, 107, 69, 78, 68, 54, 0, 107, 72, 79, 77, 53, 0, 107, 72, 79, 77, 54, 0, 107, 73, 67, 53, 0, 107, 73, 67, 54, 0, 107, 76, 70, 84, 53, 0, 107, 78, 88, 84, 53, 0, 107, 78, 88, 84, 54, 0, 107, 80, 82, 86, 53, 0, 107, 80, 82, 86, 54, 0, 107, 82, 73, 84, 53, 0, 107, 85, 80, 0, 107, 85, 80, 53, 0, 107, 97, 50, 0, 107, 98, 49, 0, 107, 98, 51, 0, 107, 99, 50, 0 +}; +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +static const signed char iterm_256colour_terminfo[] = { + 26, 1, 57, 0, 29, 0, 15, 0, 105, 1, 73, 3, 105, 84, 101, 114, 109, 46, 97, 112, 112, 124, 105, 116, 101, 114, 109, 124, 105, 84, 101, 114, 109, 46, 97, 112, 112, 32, 116, 101, 114, 109, 105, 110, 97, 108, 32, 101, 109, 117, 108, 97, 116, 111, 114, 32, 102, 111, 114, 32, 77, 97, 99, 32, 79, 83, 32, 88, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 80, 0, 8, 0, 24, 0, -1, -1, -1, -1, -1, -1, -1, -1, 50, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 127, -1, -1, 0, 0, 2, 0, -2, -1, 4, 0, 9, 0, 16, 0, 20, 0, 24, 0, -1, -1, 35, 0, 52, 0, 54, 0, 58, 0, 65, 0, -1, -1, 67, 0, 74, 0, -1, -1, 78, 0, -1, -1, 82, 0, 86, 0, 90, 0, -1, -1, 96, 0, 98, 0, 103, 0, 108, 0, -1, -1, -2, -1, 117, 0, 122, 0, -1, -1, 127, 0,-124, 0,-119, 0, -1, -1,-114, 0,-112, 0,-107, 0, -1, -1, -94, 0, -89, 0, -85, 0, -81, 0, -1, -1, -63, 0, -1, -1, -1, -1, -1, -1, -1, -1, -61, 0, -57, 0, -1, -1, -53, 0, -1, -1, -1, -1, -1, -1, -51, 0, -1, -1, -46, 0, -1, -1, -1, -1, -1, -1, -1, -1, -42, 0, -38, 0, -32, 0, -28, 0, -24, 0, -20, 0, -14, 0, -8, 0, -2, 0, 4, 1, 10, 1, -1, -1, -1, -1, 14, 1, -1, -1, 18, 1, 23, 1, 28, 1, -1, -1, -1, -1, -1, -1, 32, 1, 36, 1, 44, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 52, 1, 61, 1, 70, 1, 79, 1, -1, -1, 88, 1, 97, 1, 106, 1, -1, -1, 115, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 124, 1, -1, -1, -1, -1,-104, 1,-101, 1, -90, 1, -87, 1, -85, 1, -82, 1, -4, 1, -1, -1, -1, 1, 1, 2, -1, -1, -1, -1, -1, -1, 6, 2, 10, 2, 14, 2, 18, 2, 22, 2, -1, -1, -1, -1, 26, 2, -1, -1, -1, -1, -1, -1, -1, -1, 77, 2, 83, 2, -1, -1, -1, -1, 89, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 96, 2, 100, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 104, 2, 110, 2, 116, 2, 122, 2,-128, 2,-122, 2,-116, 2,-110, 2, 104, 2, -98, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -92, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -87, 2, -76, 2, -71, 2, -63, 2, -59, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -54, 2, 9, 3, 7, 0, 13, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 71, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 0, 8, 0, 27, 91, 63, 50, 53, 104, 0, 27, 91, 67, 0, 27, 91, 65, 0, 27, 91, 80, 0, 27, 91, 77, 0, 27, 93, 50, 59, 7, 0, 14, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 27, 55, 27, 91, 63, 52, 55, 104, 0, 27, 91, 52, 104, 0, 27, 91, 56, 109, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 15, 0, 27, 91, 109, 15, 0, 27, 91, 50, 74, 27, 91, 63, 52, 55, 108, 27, 56, 0, 27, 91, 52, 108, 0, 27, 91, 109, 0, 27, 91, 109, 0, 27, 91, 63, 53, 104, 36, 60, 50, 48, 48, 47, 62, 27, 91, 63, 53, 108, 0, 7, 0, 27, 91, 64, 0, 27, 91, 76, 0, 127, 0, 27, 91, 51, 126, 0, 27, 79, 66, 0, 27, 79, 80, 0, 27, 91, 50, 49, 126, 0, 27, 79, 81, 0, 27, 79, 82, 0, 27, 79, 83, 0, 27, 91, 49, 53, 126, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 79, 72, 0, 27, 79, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 79, 67, 0, 27, 79, 65, 0, 27, 91, 63, 49, 108, 27, 62, 0, 27, 91, 63, 49, 104, 27, 61, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 62, 27, 91, 63, 51, 108, 27, 91, 63, 52, 108, 27, 91, 63, 53, 108, 27, 91, 63, 55, 104, 27, 91, 63, 56, 104, 0, 27, 56, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 100, 0, 27, 55, 0, 10, 0, 27, 77, 0, 27, 91, 48, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 49, 37, 112, 51, 37, 124, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 37, 63, 37, 112, 55, 37, 116, 59, 56, 37, 59, 109, 37, 63, 37, 112, 57, 37, 116, 14, 37, 101, 15, 37, 59, 0, 27, 72, 0, 9, 0, 27, 93, 50, 59, 0, 27, 79, 113, 0, 27, 79, 115, 0, 27, 79, 114, 0, 27, 79, 112, 0, 27, 79, 110, 0, 96, 96, 97, 97, 102, 102, 103, 103, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 0, 27, 91, 63, 55, 104, 0, 27, 91, 63, 55, 108, 0, 27, 40, 66, 27, 41, 48, 0, 27, 79, 70, 0, 27, 79, 77, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 50, 53, 126, 0, 27, 91, 50, 54, 126, 0, 27, 91, 50, 56, 126, 0, 27, 91, 50, 57, 126, 0, 27, 91, 51, 49, 126, 0, 27, 91, 50, 50, 126, 0, 27, 91, 51, 51, 126, 0, 27, 91, 51, 52, 126, 0, 27, 91, 49, 75, 0, 27, 91, 37, 105, 37, 100, 59, 37, 100, 82, 0, 27, 91, 54, 110, 0, 27, 91, 63, 49, 59, 50, 99, 0, 27, 91, 99, 0, 27, 91, 48, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 51, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 57, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 51, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 52, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 49, 48, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 52, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0 +}; +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +// This is a 256-colour terminfo description that lacks true-colour +// capabilities that rxvt actually has. +static const signed char rxvt_256colour_terminfo[] = { + 26, 1, 47, 0, 29, 0, 15, 0, 110, 1, -31, 4, 114, 120, 118, 116, 45, 50, 53, 54, 99, 111, 108, 111, 114, 124, 114, 120, 118, 116, 32, 50, 46, 55, 46, 57, 32, 119, 105, 116, 104, 32, 120, 116, 101, 114, 109, 32, 50, 53, 54, 45, 99, 111, 108, 111, 114, 115, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 80, 0, 8, 0, 24, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 127, -1, -1, 0, 0, 2, 0, 4, 0, 21, 0, 26, 0, 34, 0, 38, 0, 42, 0, -1, -1, 53, 0, 70, 0, 72, 0, 76, 0, 83, 0, -1, -1, 85, 0, 92, 0, -1, -1, 96, 0, -1, -1, -1, -1, 100, 0, -1, -1, -1, -1, 104, 0, 106, 0, 111, 0, 116, 0, -1, -1, -1, -1, 125, 0, -1, -1, -1, -1,-126, 0,-121, 0,-116, 0, -1, -1,-111, 0,-109, 0,-104, 0, -1, -1, -91, 0, -86, 0, -80, 0, -74, 0, -1, -1, -1, -1, -56, 0, -42, 0, -1, -1, -1, -1, -8, 0, -4, 0, -1, -1, 0, 1, -1, -1, -1, -1, -1, -1, 2, 1, -1, -1, 7, 1, -1, -1, 11, 1, -1, -1, 16, 1, 22, 1, 28, 1, 34, 1, 40, 1, 46, 1, 52, 1, 58, 1, 64, 1, 70, 1, 76, 1, 82, 1, 87, 1, -1, -1, 92, 1, -1, -1, 96, 1, 101, 1, 106, 1, 110, 1, 114, 1, -1, -1, 118, 1, 122, 1, 125, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-128, 1,-119, 1,-110, 1, -1, -1,-101, 1, -92, 1, -83, 1, -1, -1, -74, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -65, 1, -32, 1, -1, -1, -1, -1, 18, 2, 21, 2, 32, 2, 35, 2, 37, 2, 40, 2, 107, 2, -1, -1, 110, 2, -1, -1, -1, -1, -1, -1, -1, -1, 112, 2, 116, 2, 120, 2, 124, 2,-128, 2, -1, -1, -1, -1,-124, 2, -1, -1, -73, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -69, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -62, 2, -57, 2, -1, -1, -53, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -48, 2, -1, -1, -43, 2, -38, 2, -1, -1, -1, -1, -1, -1, -1, -1, -33, 2, -28, 2, -23, 2, -1, -1, -1, -1, -19, 2, -1, -1, -14, 2, -1, -1, -1, -1, -1, -1, -9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -5, 2, 1, 3, 7, 3, 13, 3, 19, 3, 25, 3, 31, 3, 37, 3, 43, 3, 49, 3, 55, 3, 61, 3, 67, 3, 73, 3, 79, 3, 85, 3, 91, 3, 97, 3, 103, 3, 109, 3, 115, 3, 121, 3, 127, 3,-123, 3,-117, 3,-111, 3,-105, 3, -99, 3, -93, 3, -87, 3, -81, 3, -75, 3, -69, 3, -63, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -57, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -52, 3, -41, 3, -36, 3, -28, 3, -24, 3, -15, 3, -8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 86, 4, -1, -1, -1, -1, -1, -1, 90, 4,-103, 4, -1, -1, -1, -1, -1, -1, -39, 4, -35, 4, 7, 0, 13, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 114, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 50, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 71, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 0, 8, 0, 27, 91, 63, 50, 53, 104, 0, 27, 91, 67, 0, 27, 91, 65, 0, 27, 91, 77, 0, 14, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 27, 55, 27, 91, 63, 52, 55, 104, 0, 27, 91, 52, 104, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 15, 0, 27, 91, 109, 15, 0, 27, 91, 50, 74, 27, 91, 63, 52, 55, 108, 27, 56, 0, 27, 91, 52, 108, 0, 27, 91, 50, 55, 109, 0, 27, 91, 50, 52, 109, 0, 27, 91, 63, 53, 104, 36, 60, 49, 48, 48, 47, 62, 27, 91, 63, 53, 108, 0, 27, 91, 63, 52, 55, 108, 27, 61, 27, 91, 63, 49, 108, 0, 27, 91, 114, 27, 91, 109, 27, 91, 50, 74, 27, 91, 72, 27, 91, 63, 55, 104, 27, 91, 63, 49, 59, 51, 59, 52, 59, 54, 108, 27, 91, 52, 108, 0, 27, 91, 64, 0, 27, 91, 76, 0, 8, 0, 27, 91, 51, 126, 0, 27, 91, 66, 0, 27, 91, 56, 94, 0, 27, 91, 50, 49, 126, 0, 27, 91, 49, 49, 126, 0, 27, 91, 50, 49, 126, 0, 27, 91, 49, 50, 126, 0, 27, 91, 49, 51, 126, 0, 27, 91, 49, 52, 126, 0, 27, 91, 49, 53, 126, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 91, 55, 126, 0, 27, 91, 50, 126, 0, 27, 91, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 91, 67, 0, 27, 91, 97, 0, 27, 91, 98, 0, 27, 91, 65, 0, 27, 62, 0, 27, 61, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 62, 27, 91, 49, 59, 51, 59, 52, 59, 53, 59, 54, 108, 27, 91, 63, 55, 104, 27, 91, 109, 27, 91, 114, 27, 91, 50, 74, 27, 91, 72, 0, 27, 91, 114, 27, 91, 109, 27, 91, 50, 74, 27, 91, 72, 27, 91, 63, 55, 104, 27, 91, 63, 49, 59, 51, 59, 52, 59, 54, 108, 27, 91, 52, 108, 27, 62, 27, 91, 63, 49, 48, 48, 48, 108, 27, 91, 63, 50, 53, 104, 0, 27, 56, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 100, 0, 27, 55, 0, 10, 0, 27, 77, 0, 27, 91, 48, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 49, 37, 112, 51, 37, 124, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 109, 37, 63, 37, 112, 57, 37, 116, 14, 37, 101, 15, 37, 59, 0, 27, 72, 0, 9, 0, 27, 79, 119, 0, 27, 79, 121, 0, 27, 79, 117, 0, 27, 79, 113, 0, 27, 79, 115, 0, 96, 96, 97, 97, 102, 102, 103, 103, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 0, 27, 91, 90, 0, 27, 40, 66, 27, 41, 48, 0, 27, 91, 56, 126, 0, 27, 79, 77, 0, 27, 91, 49, 126, 0, 27, 91, 51, 36, 0, 27, 91, 52, 126, 0, 27, 91, 56, 36, 0, 27, 91, 55, 36, 0, 27, 91, 50, 36, 0, 27, 91, 100, 0, 27, 91, 54, 36, 0, 27, 91, 53, 36, 0, 27, 91, 99, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 50, 53, 126, 0, 27, 91, 50, 54, 126, 0, 27, 91, 50, 56, 126, 0, 27, 91, 50, 57, 126, 0, 27, 91, 51, 49, 126, 0, 27, 91, 51, 50, 126, 0, 27, 91, 51, 51, 126, 0, 27, 91, 51, 52, 126, 0, 27, 91, 50, 51, 36, 0, 27, 91, 50, 52, 36, 0, 27, 91, 49, 49, 94, 0, 27, 91, 49, 50, 94, 0, 27, 91, 49, 51, 94, 0, 27, 91, 49, 52, 94, 0, 27, 91, 49, 53, 94, 0, 27, 91, 49, 55, 94, 0, 27, 91, 49, 56, 94, 0, 27, 91, 49, 57, 94, 0, 27, 91, 50, 48, 94, 0, 27, 91, 50, 49, 94, 0, 27, 91, 50, 51, 94, 0, 27, 91, 50, 52, 94, 0, 27, 91, 50, 53, 94, 0, 27, 91, 50, 54, 94, 0, 27, 91, 50, 56, 94, 0, 27, 91, 50, 57, 94, 0, 27, 91, 51, 49, 94, 0, 27, 91, 51, 50, 94, 0, 27, 91, 51, 51, 94, 0, 27, 91, 51, 52, 94, 0, 27, 91, 50, 51, 64, 0, 27, 91, 50, 52, 64, 0, 27, 91, 49, 75, 0, 27, 91, 37, 105, 37, 100, 59, 37, 100, 82, 0, 27, 91, 54, 110, 0, 27, 91, 63, 49, 59, 50, 99, 0, 27, 91, 99, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 93, 49, 48, 52, 7, 0, 27, 93, 52, 59, 37, 112, 49, 37, 100, 59, 114, 103, 98, 58, 37, 112, 50, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 47, 37, 112, 51, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 47, 37, 112, 52, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 27, 92, 0, 27, 91, 77, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 51, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 57, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 51, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 52, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 49, 48, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 52, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 40, 66, 0, 27, 40, 48, 0 +}; +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +// This is a 16-colour terminfo description that lacks true-colour +// and 256-colour capabilities that linux (4.8+) actually has. +static const signed char linux_16colour_terminfo[] = { + 26, 1, 43, 0, 29, 0, 16, 0, 125, 1, 125, 3, 108, 105, 110, 117, 120, 45, 49, 54, 99, 111, 108, 111, 114, 124, 108, 105, 110, 117, 120, 32, 99, 111, 110, 115, 111, 108, 101, 32, 119, 105, 116, 104, 32, 49, 54, 32, 99, 111, 108, 111, 114, 115, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, -1, -1, 8, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, 0, 0, 1, 42, 0, -1, -1, 0, 0, 2, 0, 4, 0, 21, 0, 26, 0, 33, 0, 37, 0, 41, 0, -1, -1, 52, 0, 69, 0, 71, 0, 75, 0, 87, 0, -1, -1, 89, 0, 101, 0, -1, -1, 105, 0, 109, 0, 121, 0, 125, 0, -1, -1, -1, -1,-127, 0,-125, 0,-120, 0, -1, -1, -1, -1,-115, 0,-110, 0, -1, -1, -1, -1,-105, 0,-100, 0, -95, 0, -90, 0, -81, 0, -79, 0, -1, -1, -1, -1, -74, 0, -69, 0, -63, 0, -57, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -39, 0, -35, 0, -1, -1, -31, 0, -1, -1, -1, -1, -1, -1, -29, 0, -1, -1, -24, 0, -1, -1, -1, -1, -1, -1, -1, -1, -20, 0, -15, 0, -9, 0, -4, 0, 1, 1, 6, 1, 11, 1, 17, 1, 23, 1, 29, 1, 35, 1, 40, 1, -1, -1, 45, 1, -1, -1, 49, 1, 54, 1, 59, 1, -1, -1, -1, -1, -1, -1, 63, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 67, 1, -1, -1, 70, 1, 79, 1, 88, 1, 97, 1, -1, -1, 106, 1, 115, 1, 124, 1, -1, -1,-123, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-114, 1, -1, -1, -1, -1, -1, -1,-108, 1,-105, 1, -94, 1, -91, 1, -89, 1, -86, 1, 1, 2, -1, -1, 4, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, 10, 2, -1, -1, 77, 2, -1, -1, -1, -1, 81, 2, 87, 2, -1, -1, -1, -1, 93, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 102, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 104, 2, 110, 2, 116, 2, 122, 2,-128, 2,-122, 2,-116, 2,-110, 2,-104, 2, -98, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -92, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -87, 2, -76, 2, -71, 2, -65, 2, -61, 2, -52, 2, -48, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 3, -1, -1, -1, -1, -1, -1, 37, 3, 75, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 113, 3, 119, 3, 7, 0, 13, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 114, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 71, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 27, 91, 63, 49, 99, 0, 8, 0, 27, 91, 63, 50, 53, 104, 27, 91, 63, 48, 99, 0, 27, 91, 67, 0, 27, 91, 65, 0, 27, 91, 63, 50, 53, 104, 27, 91, 63, 56, 99, 0, 27, 91, 80, 0, 27, 91, 77, 0, 14, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 27, 91, 50, 109, 0, 27, 91, 52, 104, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 27, 91, 37, 112, 49, 37, 100, 88, 0, 15, 0, 27, 91, 109, 15, 0, 27, 91, 52, 108, 0, 27, 91, 50, 55, 109, 0, 27, 91, 50, 52, 109, 0, 27, 91, 63, 53, 104, 36, 60, 50, 48, 48, 47, 62, 27, 91, 63, 53, 108, 0, 27, 91, 64, 0, 27, 91, 76, 0, 127, 0, 27, 91, 51, 126, 0, 27, 91, 66, 0, 27, 91, 91, 65, 0, 27, 91, 50, 49, 126, 0, 27, 91, 91, 66, 0, 27, 91, 91, 67, 0, 27, 91, 91, 68, 0, 27, 91, 91, 69, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 91, 49, 126, 0, 27, 91, 50, 126, 0, 27, 91, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 91, 67, 0, 27, 91, 65, 0, 13, 10, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 99, 27, 93, 82, 0, 27, 56, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 100, 0, 27, 55, 0, 10, 0, 27, 77, 0, 27, 91, 48, 59, 49, 48, 37, 63, 37, 112, 49, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 51, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 37, 63, 37, 112, 53, 37, 116, 59, 50, 37, 59, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 109, 37, 63, 37, 112, 57, 37, 116, 14, 37, 101, 15, 37, 59, 0, 27, 72, 0, 9, 0, 27, 91, 71, 0, 43, 43, 44, 44, 45, 45, 46, 46, 48, 48, 95, 95, 96, 96, 97, 97, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 99, 126, 126, 0, 27, 91, 90, 0, 27, 91, 63, 55, 104, 0, 27, 91, 63, 55, 108, 0, 27, 41, 48, 0, 27, 91, 52, 126, 0, 26, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 50, 53, 126, 0, 27, 91, 50, 54, 126, 0, 27, 91, 50, 56, 126, 0, 27, 91, 50, 57, 126, 0, 27, 91, 51, 49, 126, 0, 27, 91, 51, 50, 126, 0, 27, 91, 51, 51, 126, 0, 27, 91, 51, 52, 126, 0, 27, 91, 49, 75, 0, 27, 91, 37, 105, 37, 100, 59, 37, 100, 82, 0, 27, 91, 54, 110, 0, 27, 91, 63, 54, 99, 0, 27, 91, 99, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 93, 82, 0, 27, 93, 80, 37, 112, 49, 37, 120, 37, 112, 50, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 48, 50, 120, 37, 112, 51, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 48, 50, 120, 37, 112, 52, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 48, 50, 120, 0, 27, 91, 77, 0, 27, 91, 51, 37, 112, 49, 37, 123, 56, 125, 37, 109, 37, 100, 37, 63, 37, 112, 49, 37, 123, 55, 125, 37, 62, 37, 116, 59, 49, 37, 101, 59, 50, 49, 37, 59, 109, 0, 27, 91, 52, 37, 112, 49, 37, 123, 56, 125, 37, 109, 37, 100, 37, 63, 37, 112, 49, 37, 123, 55, 125, 37, 62, 37, 116, 59, 53, 37, 101, 59, 50, 53, 37, 59, 109, 0, 27, 91, 49, 49, 109, 0, 27, 91, 49, 48, 109, 0 +}; +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +static const signed char putty_256colour_terminfo[] = { + 26, 1, 48, 0, 29, 0, 16, 0, 125, 1,-106, 4, 112, 117, 116, 116, 121, 45, 50, 53, 54, 99, 111, 108, 111, 114, 124, 80, 117, 84, 84, 89, 32, 48, 46, 53, 56, 32, 119, 105, 116, 104, 32, 120, 116, 101, 114, 109, 32, 50, 53, 54, 45, 99, 111, 108, 111, 114, 115, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, -1, 8, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 127, 22, 0, 0, 0, 4, 0, 6, 0, 8, 0, 25, 0, 30, 0, 37, 0, 41, 0, 45, 0, -1, -1, 56, 0, 73, 0, 76, 0, 80, 0, 87, 0, -1, -1, 89, 0, 96, 0, -1, -1, 100, 0, -1, -1, 103, 0, 107, 0, 111, 0, -1, -1, 117, 0, 119, 0, 124, 0,-127, 0, -1, -1, -1, -1,-120, 0, -1, -1, -1, -1,-115, 0,-110, 0,-105, 0,-100, 0, -91, 0, -89, 0, -84, 0, -1, -1, -73, 0, -68, 0, -62, 0, -56, 0, -1, -1, -38, 0, -1, -1, -36, 0, -1, -1, -1, -1, -1, -1, -2, 0, -1, -1, 2, 1, -1, -1, -1, -1, -1, -1, 4, 1, -1, -1, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, 13, 1, 19, 1, 25, 1, 31, 1, 37, 1, 43, 1, 49, 1, 55, 1, 61, 1, 67, 1, 73, 1, 78, 1, -1, -1, 83, 1, -1, -1, 87, 1, 92, 1, 97, 1, 101, 1, 105, 1, -1, -1, 109, 1, 113, 1, 121, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-127, 1, -1, -1,-124, 1,-115, 1,-106, 1, -1, -1, -97, 1, -88, 1, -79, 1, -70, 1, -61, 1, -52, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -43, 1, -1, -1, -1, -1, -10, 1, -7, 1, 4, 2, 7, 2, 9, 2, 12, 2, 84, 2, -1, -1, 87, 2, 89, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 94, 2, -1, -1, -1, -1, -1, -1, -1, -1, 98, 2, -1, -1,-107, 2, -1, -1, -1, -1,-103, 2, -97, 2, -1, -1, -1, -1, -91, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -84, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -79, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -77, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -73, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -69, 2, -63, 2, -57, 2, -51, 2, -45, 2, -39, 2, -33, 2, -27, 2, -21, 2, -15, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -4, 2, 7, 3, 12, 3, 18, 3, 22, 3, 31, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, 3, -1, -1, -1, -1, -1, -1, 39, 3, 102, 3, -1, -1, -1, -1, -1, -1, -90, 3, -84, 3, -78, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -72, 3,-118, 4,-112, 4, 27, 91, 90, 0, 7, 0, 13, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 114, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 71, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 27, 68, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 0, 8, 0, 27, 91, 63, 50, 53, 104, 0, 27, 91, 67, 0, 27, 77, 0, 27, 91, 80, 0, 27, 91, 77, 0, 27, 93, 48, 59, 7, 0, 14, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 27, 91, 63, 52, 55, 104, 0, 27, 91, 52, 104, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 27, 91, 37, 112, 49, 37, 100, 88, 0, 15, 0, 27, 91, 109, 15, 0, 27, 91, 50, 74, 27, 91, 63, 52, 55, 108, 0, 27, 91, 52, 108, 0, 27, 91, 50, 55, 109, 0, 27, 91, 50, 52, 109, 0, 27, 91, 63, 53, 104, 36, 60, 49, 48, 48, 47, 62, 27, 91, 63, 53, 108, 0, 7, 0, 27, 55, 27, 91, 114, 27, 91, 109, 27, 91, 63, 55, 104, 27, 91, 63, 49, 59, 52, 59, 54, 108, 27, 91, 52, 108, 27, 56, 27, 62, 27, 93, 82, 0, 27, 91, 76, 0, 127, 0, 27, 91, 51, 126, 0, 27, 79, 66, 0, 27, 91, 49, 49, 126, 0, 27, 91, 50, 49, 126, 0, 27, 91, 49, 50, 126, 0, 27, 91, 49, 51, 126, 0, 27, 91, 49, 52, 126, 0, 27, 91, 49, 53, 126, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 91, 49, 126, 0, 27, 91, 50, 126, 0, 27, 79, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 79, 67, 0, 27, 91, 66, 0, 27, 91, 65, 0, 27, 79, 65, 0, 27, 91, 63, 49, 108, 27, 62, 0, 27, 91, 63, 49, 104, 27, 61, 0, 13, 10, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 83, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 84, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 60, 27, 91, 34, 112, 27, 91, 53, 48, 59, 54, 34, 112, 27, 99, 27, 91, 63, 51, 108, 27, 93, 82, 27, 91, 63, 49, 48, 48, 48, 108, 0, 27, 56, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 100, 0, 27, 55, 0, 10, 0, 27, 77, 0, 27, 91, 48, 37, 63, 37, 112, 49, 37, 112, 54, 37, 124, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 49, 37, 112, 51, 37, 124, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 109, 37, 63, 37, 112, 57, 37, 116, 14, 37, 101, 15, 37, 59, 0, 27, 72, 0, 9, 0, 27, 93, 48, 59, 0, 27, 91, 71, 0, 96, 96, 97, 97, 102, 102, 103, 103, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 0, 27, 91, 90, 0, 27, 91, 63, 55, 104, 0, 27, 91, 63, 55, 108, 0, 27, 40, 66, 27, 41, 48, 0, 27, 91, 52, 126, 0, 26, 0, 27, 91, 68, 0, 27, 91, 67, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 50, 53, 126, 0, 27, 91, 50, 54, 126, 0, 27, 91, 50, 56, 126, 0, 27, 91, 50, 57, 126, 0, 27, 91, 51, 49, 126, 0, 27, 91, 51, 50, 126, 0, 27, 91, 51, 51, 126, 0, 27, 91, 51, 52, 126, 0, 27, 91, 49, 75, 0, 27, 91, 37, 105, 37, 100, 59, 37, 100, 82, 0, 27, 91, 54, 110, 0, 27, 91, 63, 54, 99, 0, 27, 91, 99, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 93, 82, 0, 27, 91, 77, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 51, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 57, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 51, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 52, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 49, 48, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 52, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 49, 48, 109, 0, 27, 91, 49, 49, 109, 0, 27, 91, 49, 50, 109, 0, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 61, 37, 116, 27, 37, 37, 71, -30,-105,-104, 27, 37, 37, 64, 37, 101, 37, 112, 49, 37, 123, 49, 48, 125, 37, 61, 37, 116, 27, 37, 37, 71, -30,-105,-103, 27, 37, 37, 64, 37, 101, 37, 112, 49, 37, 123, 49, 50, 125, 37, 61, 37, 116, 27, 37, 37, 71, -30,-103,-128, 27, 37, 37, 64, 37, 101, 37, 112, 49, 37, 123, 49, 51, 125, 37, 61, 37, 116, 27, 37, 37, 71, -30,-103, -86, 27, 37, 37, 64, 37, 101, 37, 112, 49, 37, 123, 49, 52, 125, 37, 61, 37, 116, 27, 37, 37, 71, -30,-103, -85, 27, 37, 37, 64, 37, 101, 37, 112, 49, 37, 123, 49, 53, 125, 37, 61, 37, 116, 27, 37, 37, 71, -30,-104, -68, 27, 37, 37, 64, 37, 101, 37, 112, 49, 37, 123, 50, 55, 125, 37, 61, 37, 116, 27, 37, 37, 71, -30,-122,-112, 27, 37, 37, 64, 37, 101, 37, 112, 49, 37, 123, 49, 53, 53, 125, 37, 61, 37, 116, 27, 37, 37, 71, -32,-126, -94, 27, 37, 37, 64, 37, 101, 37, 112, 49, 37, 99, 37, 59, 0, 27, 91, 49, 49, 109, 0, 27, 91, 49, 48, 109, 0 +}; +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +static const signed char interix_8colour_terminfo[] = { + 26, 1, 82, 0, 15, 0, 16, 0, 105, 1, 123, 2, 105, 110, 116, 101, 114, 105, 120, 124, 111, 112, 101, 110, 110, 116, 124, 111, 112, 101, 110, 110, 116, 45, 50, 53, 124, 110, 116, 99, 111, 110, 115, 111, 108, 101, 124, 110, 116, 99, 111, 110, 115, 111, 108, 101, 45, 50, 53, 124, 79, 112, 101, 110, 78, 84, 45, 116, 101, 114, 109, 32, 99, 111, 109, 112, 97, 116, 105, 98, 108, 101, 32, 119, 105, 116, 104, 32, 99, 111, 108, 111, 114, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 80, 0, -1, -1, 25, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, 0, 64, 0, 3, 0, 0, 0, 4, 0, -1, -1, -1, -1, -1, -1, 6, 0, 11, 0, 15, 0, -1, -1, -1, -1, 19, 0, 36, 0, 38, 0, -1, -1, 42, 0, -1, -1, -1, -1, 46, 0, 50, 0, 54, 0, -1, -1, -1, -1, 58, 0, -1, -1, -1, -1, -1, -1, -1, -1, 62, 0, 67, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 0, 80, 0, 85, 0, -1, -1, -1, -1, 90, 0, 95, 0, -1, -1, -1, -1, 107, 0, 111, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 115, 0, -1, -1, 119, 0, -1, -1, -1, -1, -1, -1, 121, 0, -1, -1, 125, 0, -1, -1, -1, -1, -1, -1,-127, 0,-123, 0,-119, 0,-115, 0,-111, 0,-107, 0,-103, 0, -99, 0, -95, 0, -91, 0, -87, 0, -1, -1, -83, 0, -1, -1, -79, 0, -75, 0, -71, 0, -67, 0, -63, 0, -1, -1, -1, -1, -1, -1, -59, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -55, 0, -1, -1, -1, -1, -52, 0, -43, 0, -1, -1, -34, 0, -25, 0, -16, 0, -7, 0, 2, 1, 11, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, 1, -1, -1, -1, -1, -1, -1, 23, 1, -1, -1, 27, 1, 31, 1, 35, 1, -1, -1, -1, -1, -1, -1, 39, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, 1, -1, -1, 104, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 108, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 112, 1, 116, 1, 120, 1, 124, 1,-128, 1,-124, 1,-120, 1,-116, 1,-112, 1,-108, 1,-104, 1,-100, 1, -96, 1, -92, 1, -88, 1, -84, 1, -80, 1, -76, 1, -72, 1, -68, 1, -64, 1, -60, 1, -56, 1, -52, 1, -48, 1, -44, 1, -40, 1, -36, 1, -32, 1, -28, 1, -24, 1, -20, 1, -16, 1, -12, 1, -8, 1, -4, 1, 0, 2, 4, 2, 8, 2, 12, 2, 16, 2, 20, 2, 24, 2, 28, 2, 32, 2, 36, 2, 40, 2, 44, 2, 48, 2, 52, 2, 56, 2, 60, 2, 64, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 68, 2, -1, -1, -1, -1, -1, -1, -1, -1, 72, 2, 88, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 103, 2, 113, 2, 27, 91, 90, 0, 7, 0, 27, 91, 50, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 68, 0, 27, 91, 67, 0, 27, 91, 85, 0, 27, 91, 65, 0, 27, 91, 77, 0, 27, 91, 49, 109, 0, 27, 91, 115, 27, 91, 49, 98, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 27, 91, 48, 109, 0, 27, 91, 50, 98, 27, 91, 117, 13, 27, 91, 75, 0, 27, 91, 109, 0, 27, 91, 109, 0, 27, 91, 76, 0, 8, 0, 27, 91, 77, 0, 27, 91, 66, 0, 27, 70, 65, 0, 27, 70, 49, 0, 27, 70, 65, 0, 27, 70, 50, 0, 27, 70, 51, 0, 27, 70, 52, 0, 27, 70, 53, 0, 27, 70, 54, 0, 27, 70, 55, 0, 27, 70, 56, 0, 27, 70, 57, 0, 27, 91, 76, 0, 27, 91, 68, 0, 27, 91, 85, 0, 27, 91, 84, 0, 27, 91, 83, 0, 27, 91, 67, 0, 27, 91, 65, 0, 13, 10, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 83, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 84, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 99, 0, 27, 91, 117, 0, 27, 91, 115, 0, 27, 91, 83, 0, 27, 91, 84, 0, 9, 0, 43, 16, 44, 17, 45, 24, 46, 25, 48, -37, 96, 4, 97, -79, 102, -8, 103, -15, 104, -80, 106, -39, 107, -65, 108, -38, 109, -64, 110, -59, 111, 126, 112, -60, 113, -60, 114, -60, 115, 95, 116, -61, 117, -76, 118, -63, 119, -62, 120, -77, 121, -13, 122, -14, 123, -29, 124, -40, 125,-100, 126, -2, 0, 27, 91, 90, 0, 27, 91, 85, 0, 27, 70, 66, 0, 27, 70, 67, 0, 27, 70, 68, 0, 27, 70, 69, 0, 27, 70, 70, 0, 27, 70, 71, 0, 27, 70, 72, 0, 27, 70, 73, 0, 27, 70, 74, 0, 27, 70, 75, 0, 27, 70, 76, 0, 27, 70, 77, 0, 27, 70, 78, 0, 27, 70, 79, 0, 27, 70, 80, 0, 27, 70, 81, 0, 27, 70, 82, 0, 27, 70, 83, 0, 27, 70, 84, 0, 27, 70, 85, 0, 27, 70, 86, 0, 27, 70, 87, 0, 27, 70, 88, 0, 27, 70, 89, 0, 27, 70, 90, 0, 27, 70, 97, 0, 27, 70, 98, 0, 27, 70, 99, 0, 27, 70, 100, 0, 27, 70, 101, 0, 27, 70, 102, 0, 27, 70, 103, 0, 27, 70, 104, 0, 27, 70, 105, 0, 27, 70, 106, 0, 27, 70, 107, 0, 27, 70, 109, 0, 27, 70, 110, 0, 27, 70, 111, 0, 27, 70, 112, 0, 27, 70, 113, 0, 27, 70, 114, 0, 27, 70, 115, 0, 27, 70, 116, 0, 27, 70, 117, 0, 27, 70, 118, 0, 27, 70, 119, 0, 27, 70, 120, 0, 27, 70, 121, 0, 27, 70, 122, 0, 27, 70, 43, 0, 27, 70, 45, 0, 27, 70, 12, 0, 27, 91, 109, 0, 27, 91, 37, 112, 49, 37, 123, 51, 48, 125, 37, 43, 37, 100, 109, 0, 27, 91, 37, 112, 49, 37, 39, 40, 39, 37, 43, 37, 100, 109, 0, 27, 91, 51, 37, 112, 49, 37, 100, 109, 0, 27, 91, 52, 37, 112, 49, 37, 100, 109, 0 +}; +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +// This is a 256-colour terminfo description that lacks true-colour +// capabilities that stterm actually has. +static const signed char st_256colour_terminfo[] = { + 26, 1, 55, 0, 29, 0, 15, 0, 105, 1, 117, 5, 115, 116, 45, 50, 53, 54, 99, 111, 108, 111, 114, 124, 115, 116, 116, 101, 114, 109, 45, 50, 53, 54, 99, 111, 108, 111, 114, 124, 115, 105, 109, 112, 108, 101, 116, 101, 114, 109, 32, 119, 105, 116, 104, 32, 50, 53, 54, 32, 99, 111, 108, 111, 114, 115, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 80, 0, 8, 0, 24, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 127, 0, 0, 4, 0, 6, 0, 8, 0, 25, 0, 30, 0, 38, 0, 42, 0, 46, 0, -1, -1, 57, 0, 74, 0, 76, 0, 80, 0, 87, 0, -1, -1, 89, 0, 102, 0, -1, -1, 106, 0, 110, 0, 117, 0, 121, 0, -1, -1, -1, -1, 125, 0,-127, 0,-122, 0,-117, 0, -1, -1, -1, -1,-108, 0,-103, 0, -1, -1, -98, 0, -93, 0, -88, 0, -83, 0, -74, 0, -70, 0, -65, 0, -1, -1, -56, 0, -51, 0, -45, 0, -39, 0, -1, -1, -21, 0, -1, -1, -19, 0, -1, -1, -1, -1, -1, -1, -4, 0, -1, -1, 0, 1, -1, -1, 2, 1, -1, -1, 9, 1, 14, 1, 21, 1, 25, 1, 32, 1, 39, 1, -1, -1, 46, 1, 50, 1, 56, 1, 60, 1, 64, 1, 68, 1, 74, 1, 80, 1, 86, 1, 92, 1, 98, 1, 103, 1, 108, 1, 115, 1, -1, -1, 119, 1, 124, 1,-127, 1,-123, 1,-116, 1, -1, -1,-109, 1,-105, 1, -97, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -89, 1, -80, 1, -71, 1, -62, 1, -53, 1, -44, 1, -35, 1, -26, 1, -1, -1, -17, 1, -1, -1, -1, -1, -1, -1, -8, 1, -4, 1, 1, 2, -1, -1, 6, 2, 9, 2, -1, -1, -1, -1, 24, 2, 27, 2, 38, 2, 41, 2, 43, 2, 46, 2,-128, 2, -1, -1,-125, 2,-123, 2, -1, -1, -1, -1, -1, -1,-118, 2,-113, 2,-108, 2,-104, 2, -99, 2, -1, -1, -1, -1, -94, 2, -1, -1, -29, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -25, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -21, 2, -16, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -12, 2, -1, -1, -1, -1, -5, 2, -1, -1, -1, -1, -1, -1, -1, -1, 2, 3, 9, 3, 16, 3, -1, -1, -1, -1, 23, 3, -1, -1, 30, 3, -1, -1, -1, -1, -1, -1, 37, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, 3, 50, 3, 56, 3, 63, 3, 70, 3, 77, 3, 84, 3, 92, 3, 100, 3, 108, 3, 116, 3, 124, 3,-124, 3,-116, 3,-108, 3,-101, 3, -94, 3, -87, 3, -80, 3, -72, 3, -64, 3, -56, 3, -48, 3, -40, 3, -32, 3, -24, 3, -16, 3, -9, 3, -2, 3, 5, 4, 12, 4, 20, 4, 28, 4, 36, 4, 44, 4, 52, 4, 60, 4, 68, 4, 76, 4, 83, 4, 90, 4, 97, 4, 104, 4, 112, 4, 120, 4,-128, 4,-120, 4,-112, 4,-104, 4, -96, 4, -88, 4, -81, 4, -74, 4, -67, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -62, 4, -51, 4, -46, 4, -38, 4, -34, 4, -2, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -25, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -20, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -14, 4, -1, -1, -1, -1, -1, -1, -10, 4, 53, 5, 27, 91, 90, 0, 7, 0, 13, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 114, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 50, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 71, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 0, 8, 0, 27, 91, 63, 49, 50, 108, 27, 91, 63, 50, 53, 104, 0, 27, 91, 67, 0, 27, 91, 65, 0, 27, 91, 63, 50, 53, 104, 0, 27, 91, 80, 0, 27, 91, 77, 0, 27, 40, 48, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 27, 91, 63, 49, 48, 52, 57, 104, 0, 27, 91, 52, 104, 0, 27, 91, 56, 109, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 27, 91, 37, 112, 49, 37, 100, 88, 0, 27, 40, 66, 0, 27, 91, 48, 109, 0, 27, 91, 63, 49, 48, 52, 57, 108, 0, 27, 91, 52, 108, 0, 27, 91, 50, 55, 109, 0, 27, 91, 50, 52, 109, 0, 27, 91, 63, 53, 104, 36, 60, 49, 48, 48, 47, 62, 27, 91, 63, 53, 108, 0, 7, 0, 27, 91, 52, 108, 27, 62, 27, 91, 63, 49, 48, 51, 52, 108, 0, 27, 91, 76, 0, 127, 0, 27, 91, 51, 59, 53, 126, 0, 27, 91, 51, 126, 0, 27, 91, 51, 59, 50, 126, 0, 27, 79, 66, 0, 27, 91, 50, 59, 50, 126, 0, 27, 91, 49, 59, 50, 70, 0, 27, 91, 49, 59, 53, 70, 0, 27, 79, 80, 0, 27, 91, 50, 49, 126, 0, 27, 79, 81, 0, 27, 79, 82, 0, 27, 79, 83, 0, 27, 91, 49, 53, 126, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 91, 49, 126, 0, 27, 91, 50, 126, 0, 27, 91, 50, 59, 53, 126, 0, 27, 79, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 79, 67, 0, 27, 91, 49, 59, 50, 66, 0, 27, 91, 49, 59, 50, 65, 0, 27, 79, 65, 0, 27, 91, 63, 49, 108, 27, 62, 0, 27, 91, 63, 49, 104, 27, 61, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 83, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 91, 105, 0, 27, 91, 52, 105, 0, 27, 91, 53, 105, 0, 27, 99, 0, 27, 91, 52, 108, 27, 62, 27, 91, 63, 49, 48, 51, 52, 108, 0, 27, 56, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 100, 0, 27, 55, 0, 10, 0, 27, 77, 0, 37, 63, 37, 112, 57, 37, 116, 27, 40, 48, 37, 101, 27, 40, 66, 37, 59, 27, 91, 48, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 49, 37, 112, 51, 37, 124, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 37, 63, 37, 112, 55, 37, 116, 59, 56, 37, 59, 109, 0, 27, 72, 0, 9, 0, 27, 93, 48, 59, 0, 27, 91, 49, 126, 0, 27, 91, 53, 126, 0, 27, 79, 117, 0, 27, 91, 52, 126, 0, 27, 91, 54, 126, 0, 43, 67, 44, 68, 45, 65, 46, 66, 48, 69, 96, 96, 97, 97, 102, 102, 103, 103, 104, 70, 105, 71, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 0, 27, 91, 90, 0, 27, 41, 48, 0, 27, 91, 52, 126, 0, 27, 79, 77, 0, 27, 91, 51, 59, 50, 126, 0, 27, 91, 49, 59, 50, 70, 0, 27, 91, 49, 59, 50, 72, 0, 27, 91, 50, 59, 50, 126, 0, 27, 91, 49, 59, 50, 68, 0, 27, 91, 54, 59, 50, 126, 0, 27, 91, 53, 59, 50, 126, 0, 27, 91, 49, 59, 50, 67, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 49, 59, 50, 80, 0, 27, 91, 49, 59, 50, 81, 0, 27, 91, 49, 59, 50, 82, 0, 27, 91, 49, 59, 50, 83, 0, 27, 91, 49, 53, 59, 50, 126, 0, 27, 91, 49, 55, 59, 50, 126, 0, 27, 91, 49, 56, 59, 50, 126, 0, 27, 91, 49, 57, 59, 50, 126, 0, 27, 91, 50, 48, 59, 50, 126, 0, 27, 91, 50, 49, 59, 50, 126, 0, 27, 91, 50, 51, 59, 50, 126, 0, 27, 91, 50, 52, 59, 50, 126, 0, 27, 91, 49, 59, 53, 80, 0, 27, 91, 49, 59, 53, 81, 0, 27, 91, 49, 59, 53, 82, 0, 27, 91, 49, 59, 53, 83, 0, 27, 91, 49, 53, 59, 53, 126, 0, 27, 91, 49, 55, 59, 53, 126, 0, 27, 91, 49, 56, 59, 53, 126, 0, 27, 91, 49, 57, 59, 53, 126, 0, 27, 91, 50, 48, 59, 53, 126, 0, 27, 91, 50, 49, 59, 53, 126, 0, 27, 91, 50, 51, 59, 53, 126, 0, 27, 91, 50, 52, 59, 53, 126, 0, 27, 91, 49, 59, 54, 80, 0, 27, 91, 49, 59, 54, 81, 0, 27, 91, 49, 59, 54, 82, 0, 27, 91, 49, 59, 54, 83, 0, 27, 91, 49, 53, 59, 54, 126, 0, 27, 91, 49, 55, 59, 54, 126, 0, 27, 91, 49, 56, 59, 54, 126, 0, 27, 91, 49, 57, 59, 54, 126, 0, 27, 91, 50, 48, 59, 54, 126, 0, 27, 91, 50, 49, 59, 54, 126, 0, 27, 91, 50, 51, 59, 54, 126, 0, 27, 91, 50, 52, 59, 54, 126, 0, 27, 91, 49, 59, 51, 80, 0, 27, 91, 49, 59, 51, 81, 0, 27, 91, 49, 59, 51, 82, 0, 27, 91, 49, 59, 51, 83, 0, 27, 91, 49, 53, 59, 51, 126, 0, 27, 91, 49, 55, 59, 51, 126, 0, 27, 91, 49, 56, 59, 51, 126, 0, 27, 91, 49, 57, 59, 51, 126, 0, 27, 91, 50, 48, 59, 51, 126, 0, 27, 91, 50, 49, 59, 51, 126, 0, 27, 91, 50, 51, 59, 51, 126, 0, 27, 91, 50, 52, 59, 51, 126, 0, 27, 91, 49, 59, 52, 80, 0, 27, 91, 49, 59, 52, 81, 0, 27, 91, 49, 59, 52, 82, 0, 27, 91, 49, 75, 0, 27, 91, 37, 105, 37, 100, 59, 37, 100, 82, 0, 27, 91, 54, 110, 0, 27, 91, 63, 49, 59, 50, 99, 0, 27, 91, 99, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 91, 51, 109, 0, 27, 91, 50, 51, 109, 0, 27, 91, 77, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 51, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 57, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 51, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 52, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 49, 48, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 52, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0 +}; +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +// This is a 256-colour terminfo description that lacks true-colour +// capabilities that gnome actually has. +static const signed char vte_256colour_terminfo[] = { + 26, 1, 52, 0, 29, 0, 15, 0, 105, 1, -55, 5, 103, 110, 111, 109, 101, 45, 50, 53, 54, 99, 111, 108, 111, 114, 124, 71, 78, 79, 77, 69, 32, 84, 101, 114, 109, 105, 110, 97, 108, 32, 119, 105, 116, 104, 32, 120, 116, 101, 114, 109, 32, 50, 53, 54, 45, 99, 111, 108, 111, 114, 115, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 80, 0, 8, 0, 24, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 127, 0, 0, 4, 0, 6, 0, 8, 0, 25, 0, 30, 0, 38, 0, 42, 0, 46, 0, -1, -1, 57, 0, 74, 0, 76, 0, 80, 0, 87, 0, -1, -1, 89, 0, 96, 0, -1, -1, 100, 0, -1, -1, 104, 0, 108, 0, -1, -1, -1, -1, 112, 0, -1, -1, 114, 0, 119, 0, -1, -1, -128, 0, -123, 0, -118, 0, -1, -1,-113, 0, -108, 0, -103, 0, -98, 0, -89, 0, -87, 0, -81, 0, -1, -1, -68, 0, -63, 0, -57, 0, -51, 0, -1, -1, -1, -1, -1, -1, -33, 0, -1, -1, -1, -1, -1, -1, 0, 1, -1, -1, 4, 1, -1, -1, -1, -1, -1, -1, 6, 1, -1, -1, 11, 1, -1, -1, -1, -1, -1, -1, -1, -1, 15, 1, 19, 1, 25, 1, 29, 1, 33, 1, 37, 1, 43, 1, 49, 1, 55, 1, 61, 1, 67, 1, 71, 1, -1, -1, 76, 1, -1, -1, 80, 1, 85, 1, 90, 1, 94, 1, 101, 1, -1, -1, 108, 1, 112, 1, 120, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -128, 1,-119, 1, -110, 1, -101, 1, -92, 1, -83, 1, -74, 1, -65, 1, -56, 1, -47, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -38, 1, -35, 1, -1, -1, -1, -1, 16, 2, 19, 2, 30, 2, 33, 2, 35, 2, 38, 2, 116, 2, -1, -1, 119, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 121, 2, -1, -1, -1, -1, -1, -1, -1, -1, 125, 2, -1, -1, -78, 2, -1, -1, -1, -1, -74, 2, -68, 2, -1, -1, -1, -1, -62, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -58, 2, -54, 2, -1, -1, -50, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -45, 2, -1, -1, -38, 2, -33, 2, -1, -1, -1, -1, -1, -1, -1, -1, -26, 2, -19, 2, -12, 2, -1, -1, -1, -1, -5, 2, -1, -1, 2, 3, -1, -1, -1, -1, -1, -1, 9, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, 3, 22, 3, 28, 3, 35, 3, 42, 3, 49, 3, 56, 3, 64, 3, 72, 3, 80, 3, 88, 3, 96, 3, 104, 3, 112, 3, 120, 3, 127, 3, -122, 3, -115, 3,-108, 3, -100, 3, -92, 3, -84, 3, -76, 3, -68, 3, -60, 3, -52, 3, -44, 3, -37, 3, -30, 3, -23, 3, -16, 3, -8, 3, 0, 4, 8, 4, 16, 4, 24, 4, 32, 4, 40, 4, 48, 4, 55, 4, 62, 4, 69, 4, 76, 4, 84, 4, 92, 4, 100, 4, 108, 4, 116, 4, 124, 4, -124, 4,-116, 4, -109, 4, -102, 4, -95, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -90, 4, -79, 4, -74, 4, -55, 4, -51, 4, -42, 4, -35, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 64, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 70, 5, -1, -1, -1, -1, -1, -1, 74, 5, -119, 5, 27, 91, 90, 0, 7, 0, 13, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 114, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 50, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 71, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 0, 8, 0, 27, 91, 63, 50, 53, 104, 0, 27, 91, 67, 0, 27, 91, 65, 0, 27, 91, 80, 0, 27, 91, 77, 0, 14, 0, 27, 91, 49, 109, 0, 27, 55, 27, 91, 63, 52, 55, 104, 0, 27, 91, 50, 109, 0, 27, 91, 52, 104, 0, 27, 91, 56, 109, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 27, 91, 37, 112, 49, 37, 100, 88, 0, 15, 0, 27, 91, 48, 109, 15, 0, 27, 91, 50, 74, 27, 91, 63, 52, 55, 108, 27, 56, 0, 27, 91, 52, 108, 0, 27, 91, 50, 55, 109, 0, 27, 91, 50, 52, 109, 0, 27, 91, 63, 53, 104, 36, 60, 49, 48, 48, 47, 62, 27, 91, 63, 53, 108, 0, 27, 91, 109, 27, 91, 63, 55, 104, 27, 91, 52, 108, 27, 62, 27, 55, 27, 91, 114, 27, 91, 63, 49, 59, 51, 59, 52, 59, 54, 108, 27, 56, 0, 27, 91, 76, 0, 127, 0, 27, 91, 51, 126, 0, 27, 79, 66, 0, 27, 79, 80, 0, 27, 91, 50, 49, 126, 0, 27, 79, 81, 0, 27, 79, 82, 0, 27, 79, 83, 0, 27, 91, 49, 53, 126, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 79, 72, 0, 27, 91, 50, 126, 0, 27, 79, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 79, 67, 0, 27, 91, 49, 59, 50, 66, 0, 27, 91, 49, 59, 50, 65, 0, 27, 79, 65, 0, 27, 91, 63, 49, 108, 27, 62, 0, 27, 91, 63, 49, 104, 27, 61, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 83, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 84, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 99, 0, 27, 55, 27, 91, 114, 27, 56, 27, 91, 109, 27, 91, 63, 55, 104, 27, 91, 33, 112, 27, 91, 63, 49, 59, 51, 59, 52, 59, 54, 108, 27, 91, 52, 108, 27, 62, 27, 91, 63, 49, 48, 48, 48, 108, 27, 91, 63, 50, 53, 104, 0, 27, 56, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 100, 0, 27, 55, 0, 10, 0, 27, 77, 0, 27, 91, 48, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 53, 37, 116, 59, 50, 37, 59, 37, 63, 37, 112, 55, 37, 116, 59, 56, 37, 59, 37, 63, 37, 112, 49, 37, 112, 51, 37, 124, 37, 116, 59, 55, 37, 59, 109, 37, 63, 37, 112, 57, 37, 116, 14, 37, 101, 15, 37, 59, 0, 27, 72, 0, 9, 0, 27, 91, 69, 0, 96, 96, 97, 97, 102, 102, 103, 103, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 0, 27, 91, 90, 0, 27, 91, 63, 55, 104, 0, 27, 91, 63, 55, 108, 0, 27, 41, 48, 0, 27, 79, 70, 0, 27, 79, 77, 0, 27, 91, 49, 126, 0, 27, 91, 51, 59, 50, 126, 0, 27, 91, 52, 126, 0, 27, 91, 49, 59, 50, 70, 0, 27, 91, 49, 59, 50, 72, 0, 27, 91, 50, 59, 50, 126, 0, 27, 91, 49, 59, 50, 68, 0, 27, 91, 54, 59, 50, 126, 0, 27, 91, 53, 59, 50, 126, 0, 27, 91, 49, 59, 50, 67, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 49, 59, 50, 80, 0, 27, 91, 49, 59, 50, 81, 0, 27, 91, 49, 59, 50, 82, 0, 27, 91, 49, 59, 50, 83, 0, 27, 91, 49, 53, 59, 50, 126, 0, 27, 91, 49, 55, 59, 50, 126, 0, 27, 91, 49, 56, 59, 50, 126, 0, 27, 91, 49, 57, 59, 50, 126, 0, 27, 91, 50, 48, 59, 50, 126, 0, 27, 91, 50, 49, 59, 50, 126, 0, 27, 91, 50, 51, 59, 50, 126, 0, 27, 91, 50, 52, 59, 50, 126, 0, 27, 91, 49, 59, 53, 80, 0, 27, 91, 49, 59, 53, 81, 0, 27, 91, 49, 59, 53, 82, 0, 27, 91, 49, 59, 53, 83, 0, 27, 91, 49, 53, 59, 53, 126, 0, 27, 91, 49, 55, 59, 53, 126, 0, 27, 91, 49, 56, 59, 53, 126, 0, 27, 91, 49, 57, 59, 53, 126, 0, 27, 91, 50, 48, 59, 53, 126, 0, 27, 91, 50, 49, 59, 53, 126, 0, 27, 91, 50, 51, 59, 53, 126, 0, 27, 91, 50, 52, 59, 53, 126, 0, 27, 91, 49, 59, 54, 80, 0, 27, 91, 49, 59, 54, 81, 0, 27, 91, 49, 59, 54, 82, 0, 27, 91, 49, 59, 54, 83, 0, 27, 91, 49, 53, 59, 54, 126, 0, 27, 91, 49, 55, 59, 54, 126, 0, 27, 91, 49, 56, 59, 54, 126, 0, 27, 91, 49, 57, 59, 54, 126, 0, 27, 91, 50, 48, 59, 54, 126, 0, 27, 91, 50, 49, 59, 54, 126, 0, 27, 91, 50, 51, 59, 54, 126, 0, 27, 91, 50, 52, 59, 54, 126, 0, 27, 91, 49, 59, 51, 80, 0, 27, 91, 49, 59, 51, 81, 0, 27, 91, 49, 59, 51, 82, 0, 27, 91, 49, 59, 51, 83, 0, 27, 91, 49, 53, 59, 51, 126, 0, 27, 91, 49, 55, 59, 51, 126, 0, 27, 91, 49, 56, 59, 51, 126, 0, 27, 91, 49, 57, 59, 51, 126, 0, 27, 91, 50, 48, 59, 51, 126, 0, 27, 91, 50, 49, 59, 51, 126, 0, 27, 91, 50, 51, 59, 51, 126, 0, 27, 91, 50, 52, 59, 51, 126, 0, 27, 91, 49, 59, 52, 80, 0, 27, 91, 49, 59, 52, 81, 0, 27, 91, 49, 59, 52, 82, 0, 27, 91, 49, 75, 0, 27, 91, 37, 105, 37, 100, 59, 37, 100, 82, 0, 27, 91, 54, 110, 0, 27, 91, 63, 37, 91, 59, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 93, 99, 0, 27, 91, 99, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 93, 49, 48, 52, 7, 0, 27, 93, 52, 59, 37, 112, 49, 37, 100, 59, 114, 103, 98, 58, 37, 112, 50, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 47, 37, 112, 51, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 47, 37, 112, 52, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 27, 92, 0, 27, 91, 51, 109, 0, 27, 91, 50, 51, 109, 0, 27, 91, 77, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 51, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 57, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 51, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 52, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 49, 48, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 52, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0 +}; +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +static const signed char ansi_terminfo[] = { + 26, 1, 40, 0, 23, 0, 16, 0, 125, 1, 68, 2, 97, 110, 115, 105, 124, 97, 110, 115, 105, 47, 112, 99, 45, 116, 101, 114, 109, 32, 99, 111, 109, 112, 97, 116, 105, 98, 108, 101, 32, 119, 105, 116, 104, 32, 99, 111, 108, 111, 114, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 80, 0, 8, 0, 24, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, 0, 64, 0, 3, 0, 0, 0, 4, 0, 6, 0, -1, -1, 8, 0, 13, 0, 20, 0, 24, 0, 28, 0, -1, -1, 39, 0, 56, 0, 60, 0, -1, -1, 64, 0, -1, -1, -1, -1, 68, 0, -1, -1, 72, 0, -1, -1, 76, 0, 80, 0, -1, -1, -1, -1, 84, 0, 90, 0, 95, 0, -1, -1, -1, -1, -1, -1, -1, -1, 100, 0, -1, -1, 105, 0, 110, 0, 115, 0, 120, 0,-127, 0,-121, 0, -1, -1, -1, -1, -1, -1,-113, 0,-109, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-105, 0, -1, -1,-101, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -99, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -95, 0, -91, 0, -1, -1, -87, 0, -1, -1, -1, -1, -1, -1, -83, 0, -1, -1, -1, -1, -1, -1, -79, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -75, 0, -1, -1, -70, 0, -61, 0, -52, 0, -43, 0, -34, 0, -25, 0, -16, 0, -7, 0, 2, 1, 11, 1, -1, -1, -1, -1, -1, -1, -1, -1, 20, 1, 25, 1, 30, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 1, -1, -1, 61, 1, -1, -1, 63, 1,-107, 1, -1, -1,-104, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-100, 1, -1, -1, -37, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -33, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -28, 1, -17, 1, -12, 1, 7, 2, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, 2, 30, 2, -1, -1, -1, -1, -1, -1, 40, 2, 44, 2, 48, 2, 52, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, 2, 62, 2, 27, 91, 90, 0, 7, 0, 13, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 71, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 27, 91, 66, 0, 27, 91, 72, 0, 27, 91, 68, 0, 27, 91, 67, 0, 27, 91, 65, 0, 27, 91, 80, 0, 27, 91, 77, 0, 27, 91, 49, 49, 109, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 27, 91, 56, 109, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 27, 91, 37, 112, 49, 37, 100, 88, 0, 27, 91, 49, 48, 109, 0, 27, 91, 48, 59, 49, 48, 109, 0, 27, 91, 109, 0, 27, 91, 109, 0, 27, 91, 76, 0, 8, 0, 27, 91, 66, 0, 27, 91, 72, 0, 27, 91, 76, 0, 27, 91, 68, 0, 27, 91, 67, 0, 27, 91, 65, 0, 13, 27, 91, 83, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 83, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 84, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 91, 52, 105, 0, 27, 91, 53, 105, 0, 37, 112, 49, 37, 99, 27, 91, 37, 112, 50, 37, 123, 49, 125, 37, 45, 37, 100, 98, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 100, 0, 10, 0, 27, 91, 48, 59, 49, 48, 37, 63, 37, 112, 49, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 51, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 55, 37, 116, 59, 56, 37, 59, 37, 63, 37, 112, 57, 37, 116, 59, 49, 49, 37, 59, 109, 0, 27, 72, 0, 27, 91, 73, 0, 43, 16, 44, 17, 45, 24, 46, 25, 48, -37, 96, 4, 97, -79, 102, -8, 103, -15, 104, -80, 106, -39, 107, -65, 108, -38, 109, -64, 110, -59, 111, 126, 112, -60, 113, -60, 114, -60, 115, 95, 116, -61, 117, -76, 118, -63, 119, -62, 120, -77, 121, -13, 122, -14, 123, -29, 124, -40, 125,-100, 126, -2, 0, 27, 91, 90, 0, 27, 91, 49, 75, 0, 27, 91, 37, 105, 37, 100, 59, 37, 100, 82, 0, 27, 91, 54, 110, 0, 27, 91, 63, 37, 91, 59, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 93, 99, 0, 27, 91, 99, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 91, 51, 37, 112, 49, 37, 100, 109, 0, 27, 91, 52, 37, 112, 49, 37, 100, 109, 0, 27, 40, 66, 0, 27, 41, 66, 0, 27, 42, 66, 0, 27, 43, 66, 0, 27, 91, 49, 49, 109, 0, 27, 91, 49, 48, 109, 0 +}; + +/// Load one of the built-in terminfo entries when unibilium has failed to +/// load a terminfo record from an external database, as it does on termcap- +/// -only systems. We do not do any fancy recognition of xterm pretenders +/// here. An external terminfo database would not do that, and we want to +/// behave as much like an external terminfo database as possible. +unibi_term *load_builtin_terminfo(const char * term) +{ + if (terminfo_is_term_family(term, "xterm")) { + return unibi_from_mem((const char *)xterm_256colour_terminfo, + sizeof xterm_256colour_terminfo); + } else if (terminfo_is_term_family(term, "screen")) { + return unibi_from_mem((const char *)screen_256colour_terminfo, + sizeof screen_256colour_terminfo); + } else if (terminfo_is_term_family(term, "tmux")) { + return unibi_from_mem((const char *)tmux_256colour_terminfo, + sizeof tmux_256colour_terminfo); + } else if (terminfo_is_term_family(term, "rxvt")) { + return unibi_from_mem((const char *)rxvt_256colour_terminfo, + sizeof rxvt_256colour_terminfo); + } else if (terminfo_is_term_family(term, "putty")) { + return unibi_from_mem((const char *)putty_256colour_terminfo, + sizeof putty_256colour_terminfo); + } else if (terminfo_is_term_family(term, "linux")) { + return unibi_from_mem((const char *)linux_16colour_terminfo, + sizeof linux_16colour_terminfo); + } else if (terminfo_is_term_family(term, "interix")) { + return unibi_from_mem((const char *)interix_8colour_terminfo, + sizeof interix_8colour_terminfo); + } else if (terminfo_is_term_family(term, "iterm") + || terminfo_is_term_family(term, "iterm2") + || terminfo_is_term_family(term, "iTerm.app") + || terminfo_is_term_family(term, "iTerm2.app")) { + return unibi_from_mem((const char *)iterm_256colour_terminfo, + sizeof iterm_256colour_terminfo); + } else if (terminfo_is_term_family(term, "st")) { + return unibi_from_mem((const char *)st_256colour_terminfo, + sizeof st_256colour_terminfo); + } else if (terminfo_is_term_family(term, "gnome") + || terminfo_is_term_family(term, "vte")) { + return unibi_from_mem((const char *)vte_256colour_terminfo, + sizeof vte_256colour_terminfo); + } else { + return unibi_from_mem((const char *)ansi_terminfo, + sizeof ansi_terminfo); + } +} diff --git a/src/nvim/tui/terminfo.h b/src/nvim/tui/terminfo.h new file mode 100644 index 0000000000..099df8967f --- /dev/null +++ b/src/nvim/tui/terminfo.h @@ -0,0 +1,10 @@ +#ifndef NVIM_TUI_TERMINFO_H +#define NVIM_TUI_TERMINFO_H + +#include <unibilium.h> + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "tui/terminfo.h.generated.h" +#endif + +#endif // NVIM_TUI_TERMINFO_H diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 74187e07c0..1cbd02dfd9 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -1,3 +1,6 @@ +// 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 + // Terminal UI functions. Invoked (by ui_bridge.c) on the TUI thread. #include <assert.h> @@ -31,13 +34,37 @@ #include "nvim/ugrid.h" #include "nvim/tui/input.h" #include "nvim/tui/tui.h" +#include "nvim/tui/terminfo.h" +#include "nvim/cursor_shape.h" +#include "nvim/syntax.h" +#include "nvim/macros.h" -// Space reserved in the output buffer to restore the cursor to normal when -// flushing. No existing terminal will require 32 bytes to do that. +// 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. #define CNORM_COMMAND_MAX_SIZE 32 #define OUTBUF_SIZE 0xffff #define TOO_MANY_EVENTS 1000000 +#define STARTS_WITH(str, prefix) (strlen(str) >= (sizeof(prefix) - 1) \ + && 0 == memcmp((str), (prefix), sizeof(prefix) - 1)) +#define TMUX_WRAP(is_tmux, seq) ((is_tmux) \ + ? "\x1bPtmux;\x1b" seq "\x1b\\" : seq) +#define LINUXSET0C "\x1b[?0c" +#define LINUXSET1C "\x1b[?1c" + +// Per the commentary in terminfo, only a minus sign is a true suffix +// separator. +bool terminfo_is_term_family(const char *term, const char *family) +{ + if (!term) { + return false; + } + size_t tlen = strlen(term); + size_t flen = strlen(family); + return tlen >= flen + && 0 == memcmp(term, family, flen) \ + && ('\0' == term[flen] || '-' == term[flen]); +} typedef struct { int top, bot, left, right; @@ -49,7 +76,10 @@ typedef struct { bool stop; unibi_var_t params[9]; char buf[OUTBUF_SIZE]; - size_t bufpos, bufsize; + size_t bufpos; + char norm[CNORM_COMMAND_MAX_SIZE]; + char invis[CNORM_COMMAND_MAX_SIZE]; + size_t normlen, invislen; TermInput input; uv_loop_t write_loop; unibi_term *ut; @@ -60,27 +90,35 @@ typedef struct { bool out_isatty; SignalWatcher winch_handle, cont_handle; bool cont_received; - // Event scheduled by the ui bridge. Since the main thread suspends until - // the event is handled, it is fine to use a single field instead of a queue - Event scheduled_event; UGrid grid; kvec_t(Rect) invalid_regions; int out_fd; - bool can_use_terminal_scroll; + bool scroll_region_is_full_screen; + bool can_change_scroll_region; + bool can_set_lr_margin; + bool can_set_left_right_margin; + bool immediate_wrap_after_last_column; bool mouse_enabled; - bool busy; + bool busy, is_invisible; + cursorentry_T cursor_shapes[SHAPE_IDX_COUNT]; HlAttrs print_attrs; - int showing_mode; + bool default_attr; + ModeShape showing_mode; struct { int enable_mouse, disable_mouse; int enable_bracketed_paste, disable_bracketed_paste; - int set_cursor_shape_bar, set_cursor_shape_ul, set_cursor_shape_block; + int enable_lr_margin, disable_lr_margin; int set_rgb_foreground, set_rgb_background; + int set_cursor_color; int enable_focus_reporting, disable_focus_reporting; + int resize_screen; + int reset_scroll_region; + int set_cursor_style, reset_cursor_style; } unibi_ext; } TUIData; static bool volatile got_winch = false; +static bool cursor_style_enabled = false; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "tui/tui.c.generated.h" @@ -92,11 +130,11 @@ UI *tui_start(void) UI *ui = xcalloc(1, sizeof(UI)); ui->stop = tui_stop; ui->rgb = p_tgc; - ui->pum_external = false; ui->resize = tui_resize; ui->clear = tui_clear; ui->eol_clear = tui_eol_clear; ui->cursor_goto = tui_cursor_goto; + ui->mode_info_set = tui_mode_info_set; ui->update_menu = tui_update_menu; ui->busy_start = tui_busy_start; ui->busy_stop = tui_busy_stop; @@ -117,50 +155,96 @@ UI *tui_start(void) ui->set_title = tui_set_title; ui->set_icon = tui_set_icon; ui->event = tui_event; + + memset(ui->ui_ext, 0, sizeof(ui->ui_ext)); + return ui_bridge_attach(ui, tui_main, tui_scheduler); } +static size_t unibi_pre_fmt_str(TUIData *data, unsigned int unibi_index, + char * buf, size_t len) +{ + const char *str = unibi_get_str(data->ut, unibi_index); + if (!str) { + return 0U; + } + return unibi_run(str, data->params, buf, len); +} + static void terminfo_start(UI *ui) { TUIData *data = ui->data; - data->can_use_terminal_scroll = true; + data->scroll_region_is_full_screen = true; data->bufpos = 0; - data->bufsize = sizeof(data->buf) - CNORM_COMMAND_MAX_SIZE; - data->showing_mode = 0; + data->default_attr = false; + data->is_invisible = true; + data->busy = false; + data->showing_mode = SHAPE_IDX_N; data->unibi_ext.enable_mouse = -1; data->unibi_ext.disable_mouse = -1; + data->unibi_ext.set_cursor_color = -1; data->unibi_ext.enable_bracketed_paste = -1; data->unibi_ext.disable_bracketed_paste = -1; - data->unibi_ext.set_cursor_shape_bar = -1; - data->unibi_ext.set_cursor_shape_ul = -1; - data->unibi_ext.set_cursor_shape_block = -1; + data->unibi_ext.enable_lr_margin = -1; + data->unibi_ext.disable_lr_margin = -1; data->unibi_ext.enable_focus_reporting = -1; data->unibi_ext.disable_focus_reporting = -1; + data->unibi_ext.resize_screen = -1; + data->unibi_ext.reset_scroll_region = -1; + data->unibi_ext.set_cursor_style = -1; + data->unibi_ext.reset_cursor_style = -1; data->out_fd = 1; data->out_isatty = os_isatty(data->out_fd); // setup unibilium + const char *term = os_getenv("TERM"); data->ut = unibi_from_env(); if (!data->ut) { - // For some reason could not read terminfo file, use a dummy entry that - // will be populated with common values by fix_terminfo below - data->ut = unibi_dummy(); + data->ut = load_builtin_terminfo(term); } - fix_terminfo(data); - // Initialize the cursor shape. - unibi_out(ui, data->unibi_ext.set_cursor_shape_block); + // None of the following work over SSH; see :help TERM . + const char *colorterm = os_getenv("COLORTERM"); + const char *termprg = os_getenv("TERM_PROGRAM"); + const char *vte_version_env = os_getenv("VTE_VERSION"); + long vte_version = vte_version_env ? strtol(vte_version_env, NULL, 10) : 0; + bool iterm_env = termprg && strstr(termprg, "iTerm.app"); + bool konsole = os_getenv("KONSOLE_PROFILE_NAME") + || os_getenv("KONSOLE_DBUS_SESSION"); + + patch_terminfo_bugs(data, term, colorterm, vte_version, konsole, iterm_env); + augment_terminfo(data, term, colorterm, vte_version, konsole, iterm_env); + data->can_change_scroll_region = + !!unibi_get_str(data->ut, unibi_change_scroll_region); + data->can_set_lr_margin = + !!unibi_get_str(data->ut, unibi_set_lr_margin); + data->can_set_left_right_margin = + !!unibi_get_str(data->ut, unibi_set_left_margin_parm) + && !!unibi_get_str(data->ut, unibi_set_right_margin_parm); + data->immediate_wrap_after_last_column = + terminfo_is_term_family(term, "cygwin") + || terminfo_is_term_family(term, "interix"); + data->normlen = unibi_pre_fmt_str(data, unibi_cursor_normal, + data->norm, sizeof data->norm); + data->invislen = unibi_pre_fmt_str(data, unibi_cursor_invisible, + data->invis, sizeof data->invis); // Set 't_Co' from the result of unibilium & fix_terminfo. t_colors = unibi_get_num(data->ut, unibi_max_colors); // Enter alternate screen and clear + // NOTE: Do this *before* changing terminal settings. #6433 unibi_out(ui, unibi_enter_ca_mode); + unibi_out(ui, unibi_keypad_xmit); unibi_out(ui, unibi_clear_screen); // Enable bracketed paste - unibi_out(ui, data->unibi_ext.enable_bracketed_paste); + unibi_out_ext(ui, data->unibi_ext.enable_bracketed_paste); // Enable focus reporting - unibi_out(ui, data->unibi_ext.enable_focus_reporting); + unibi_out_ext(ui, data->unibi_ext.enable_focus_reporting); uv_loop_init(&data->write_loop); if (data->out_isatty) { uv_tty_init(&data->write_loop, &data->output_handle.tty, data->out_fd, 0); +#ifdef WIN32 uv_tty_set_mode(&data->output_handle.tty, UV_TTY_MODE_RAW); +#else + uv_tty_set_mode(&data->output_handle.tty, UV_TTY_MODE_IO); +#endif } else { uv_pipe_init(&data->write_loop, &data->output_handle.pipe, 0); uv_pipe_open(&data->output_handle.pipe, data->out_fd); @@ -171,16 +255,17 @@ static void terminfo_stop(UI *ui) { TUIData *data = ui->data; // Destroy output stuff - tui_mode_change(ui, NORMAL); + tui_mode_change(ui, (String)STRING_INIT, SHAPE_IDX_N); tui_mouse_off(ui); unibi_out(ui, unibi_exit_attribute_mode); // cursor should be set to normal before exiting alternate screen unibi_out(ui, unibi_cursor_normal); + unibi_out(ui, unibi_keypad_local); unibi_out(ui, unibi_exit_ca_mode); // Disable bracketed paste - unibi_out(ui, data->unibi_ext.disable_bracketed_paste); + unibi_out_ext(ui, data->unibi_ext.disable_bracketed_paste); // Disable focus reporting - unibi_out(ui, data->unibi_ext.disable_focus_reporting); + unibi_out_ext(ui, data->unibi_ext.disable_focus_reporting); flush_buf(ui, true); uv_tty_reset_mode(); uv_close((uv_handle_t *)&data->output_handle, NULL); @@ -199,11 +284,6 @@ static void tui_terminal_start(UI *ui) terminfo_start(ui); update_size(ui); signal_watcher_start(&data->winch_handle, sigwinch_cb, SIGWINCH); - -#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18 - data->input.tk_ti_hook_fn = tui_tk_ti_getstr; -#endif - term_input_init(&data->input, data->loop); term_input_start(&data->input); } @@ -235,9 +315,17 @@ static void tui_main(UIBridgeData *bridge, UI *ui) kv_init(data->invalid_regions); signal_watcher_init(data->loop, &data->winch_handle, ui); signal_watcher_init(data->loop, &data->cont_handle, data); +#ifdef UNIX signal_watcher_start(&data->cont_handle, sigcont_cb, SIGCONT); +#endif + +#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18 + data->input.tk_ti_hook_fn = tui_tk_ti_getstr; +#endif + term_input_init(&data->input, &tui_loop); tui_terminal_start(ui); data->stop = false; + // allow the main thread to continue, we are ready to start handling UI // callbacks CONTINUE(bridge); @@ -264,10 +352,12 @@ static void tui_scheduler(Event event, void *d) loop_schedule(data->loop, event); } +#ifdef UNIX static void sigcont_cb(SignalWatcher *watcher, int signum, void *data) { ((TUIData *)data)->cont_received = true; } +#endif static void sigwinch_cb(SignalWatcher *watcher, int signum, void *data) { @@ -294,25 +384,56 @@ static void update_attrs(UI *ui, HlAttrs attrs) } data->print_attrs = attrs; - unibi_out(ui, unibi_exit_attribute_mode); UGrid *grid = &data->grid; int fg = attrs.foreground != -1 ? attrs.foreground : grid->fg; int bg = attrs.background != -1 ? attrs.background : grid->bg; + if (unibi_get_str(data->ut, unibi_set_attributes)) { + if (attrs.bold || attrs.reverse || attrs.underline || attrs.undercurl) { + data->params[0].i = 0; // standout + data->params[1].i = attrs.underline || attrs.undercurl; + data->params[2].i = attrs.reverse; + data->params[3].i = 0; // blink + data->params[4].i = 0; // dim + data->params[5].i = attrs.bold; + data->params[6].i = 0; // blank + data->params[7].i = 0; // protect + data->params[8].i = 0; // alternate character set + unibi_out(ui, unibi_set_attributes); + } else if (!data->default_attr) { + unibi_out(ui, unibi_exit_attribute_mode); + } + } else { + if (!data->default_attr) { + unibi_out(ui, unibi_exit_attribute_mode); + } + if (attrs.bold) { + unibi_out(ui, unibi_enter_bold_mode); + } + if (attrs.underline || attrs.undercurl) { + unibi_out(ui, unibi_enter_underline_mode); + } + if (attrs.reverse) { + unibi_out(ui, unibi_enter_reverse_mode); + } + } + if (attrs.italic) { + unibi_out(ui, unibi_enter_italics_mode); + } if (ui->rgb) { if (fg != -1) { data->params[0].i = (fg >> 16) & 0xff; // red data->params[1].i = (fg >> 8) & 0xff; // green data->params[2].i = fg & 0xff; // blue - unibi_out(ui, data->unibi_ext.set_rgb_foreground); + unibi_out_ext(ui, data->unibi_ext.set_rgb_foreground); } if (bg != -1) { data->params[0].i = (bg >> 16) & 0xff; // red data->params[1].i = (bg >> 8) & 0xff; // green data->params[2].i = bg & 0xff; // blue - unibi_out(ui, data->unibi_ext.set_rgb_background); + unibi_out_ext(ui, data->unibi_ext.set_rgb_background); } } else { if (fg != -1) { @@ -326,30 +447,173 @@ static void update_attrs(UI *ui, HlAttrs attrs) } } - if (attrs.bold) { - unibi_out(ui, unibi_enter_bold_mode); - } - if (attrs.italic) { - unibi_out(ui, unibi_enter_italics_mode); - } - if (attrs.underline || attrs.undercurl) { - unibi_out(ui, unibi_enter_underline_mode); - } - if (attrs.reverse) { - unibi_out(ui, unibi_enter_reverse_mode); + data->default_attr = fg == -1 && bg == -1 + && !attrs.bold && !attrs.italic && !attrs.underline && !attrs.undercurl + && !attrs.reverse; +} + +static void final_column_wrap(UI *ui) +{ + TUIData *data = ui->data; + UGrid *grid = &data->grid; + if (grid->col == ui->width) { + grid->col = 0; + if (grid->row < ui->height) { + grid->row++; + } } } +/// It is undocumented, but in the majority of terminals and terminal emulators +/// printing at the right margin does not cause an automatic wrap until the +/// next character is printed, holding the cursor in place until then. static void print_cell(UI *ui, UCell *ptr) { + TUIData *data = ui->data; + UGrid *grid = &data->grid; + if (!data->immediate_wrap_after_last_column) { + // Printing the next character finally advances the cursor. + final_column_wrap(ui); + } update_attrs(ui, ptr->attrs); out(ui, ptr->data, strlen(ptr->data)); + grid->col++; + if (data->immediate_wrap_after_last_column) { + // Printing at the right margin immediately advances the cursor. + final_column_wrap(ui); + } +} + +static bool cheap_to_print(UI *ui, int row, int col, int next) +{ + TUIData *data = ui->data; + UGrid *grid = &data->grid; + UCell *cell = grid->cells[row] + col; + while (next) { + next--; + if (attrs_differ(cell->attrs, data->print_attrs)) { + if (data->default_attr) { + return false; + } + } + if (strlen(cell->data) > 1) { + return false; + } + cell++; + } + return true; +} + +/// This optimizes several cases where it is cheaper to do something other +/// than send a full cursor positioning control sequence. However, there are +/// some further optimizations that may seem obvious but that will not work. +/// +/// We cannot use VT (ASCII 0/11) for moving the cursor up, because VT means +/// move the cursor down on a DEC terminal. Similarly, on a DEC terminal FF +/// (ASCII 0/12) means the same thing and does not mean home. VT, CVT, and +/// TAB also stop at software-defined tabulation stops, not at a fixed set +/// of row/column positions. +static void cursor_goto(UI *ui, int row, int col) +{ + TUIData *data = ui->data; + UGrid *grid = &data->grid; + if (row == grid->row && col == grid->col) { + return; + } + if (0 == row && 0 == col) { + unibi_out(ui, unibi_cursor_home); + ugrid_goto(grid, row, col); + return; + } + if (0 == col ? col != grid->col : + row != grid->row ? false : + 1 == col ? 2 < grid->col && cheap_to_print(ui, grid->row, 0, col) : + 2 == col ? 5 < grid->col && cheap_to_print(ui, grid->row, 0, col) : + false) { + // Motion to left margin from anywhere else, or CR + printing chars is + // even less expensive than using BSes or CUB. + unibi_out(ui, unibi_carriage_return); + ugrid_goto(grid, grid->row, 0); + } else if (col > grid->col) { + int n = col - grid->col; + if (n <= (row == grid->row ? 4 : 2) + && cheap_to_print(ui, grid->row, grid->col, n)) { + UGRID_FOREACH_CELL(grid, grid->row, grid->row, + grid->col, col - 1, { + print_cell(ui, cell); + }); + } + } + if (row == grid->row) { + if (col < grid->col + // Deferred right margin wrap terminals have inconsistent ideas about + // where the cursor actually is during a deferred wrap. Relative + // motion calculations have OBOEs that cannot be compensated for, + // because two terminals that claim to be the same will implement + // different cursor positioning rules. + && (data->immediate_wrap_after_last_column || grid->col < ui->width)) { + int n = grid->col - col; + if (n <= 4) { // This might be just BS, so it is considered really cheap. + while (n--) { + unibi_out(ui, unibi_cursor_left); + } + } else { + data->params[0].i = n; + unibi_out(ui, unibi_parm_left_cursor); + } + ugrid_goto(grid, row, col); + return; + } else if (col > grid->col) { + int n = col - grid->col; + if (n <= 2) { + while (n--) { + unibi_out(ui, unibi_cursor_right); + } + } else { + data->params[0].i = n; + unibi_out(ui, unibi_parm_right_cursor); + } + ugrid_goto(grid, row, col); + return; + } + } + if (col == grid->col) { + if (row > grid->row) { + int n = row - grid->row; + if (n <= 4) { // This might be just LF, so it is considered really cheap. + while (n--) { + unibi_out(ui, unibi_cursor_down); + } + } else { + data->params[0].i = n; + unibi_out(ui, unibi_parm_down_cursor); + } + ugrid_goto(grid, row, col); + return; + } else if (row < grid->row) { + int n = grid->row - row; + if (n <= 2) { + while (n--) { + unibi_out(ui, unibi_cursor_up); + } + } else { + data->params[0].i = n; + unibi_out(ui, unibi_parm_up_cursor); + } + ugrid_goto(grid, row, col); + return; + } + } + unibi_goto(ui, row, col); + ugrid_goto(grid, row, col); } static void clear_region(UI *ui, int top, int bot, int left, int right) { TUIData *data = ui->data; UGrid *grid = &data->grid; + int saved_row = grid->row; + int saved_col = grid->col; bool cleared = false; if (grid->bg == -1 && right == ui->width -1) { @@ -363,8 +627,9 @@ static void clear_region(UI *ui, int top, int bot, int left, int right) if (bot == ui->height - 1) { if (top == 0) { unibi_out(ui, unibi_clear_screen); + ugrid_goto(&data->grid, top, left); } else { - unibi_goto(ui, top, 0); + cursor_goto(ui, top, 0); unibi_out(ui, unibi_clr_eos); } cleared = true; @@ -373,8 +638,8 @@ static void clear_region(UI *ui, int top, int bot, int left, int right) if (!cleared) { // iterate through each line and clear with clr_eol - for (int row = top; row <= bot; ++row) { - unibi_goto(ui, row, left); + for (int row = top; row <= bot; row++) { + cursor_goto(ui, row, left); unibi_out(ui, unibi_clr_eol); } cleared = true; @@ -383,29 +648,93 @@ static void clear_region(UI *ui, int top, int bot, int left, int right) if (!cleared) { // could not clear using faster terminal codes, refresh the whole region - int currow = -1; UGRID_FOREACH_CELL(grid, top, bot, left, right, { - if (currow != row) { - unibi_goto(ui, row, col); - currow = row; - } + cursor_goto(ui, row, col); print_cell(ui, cell); }); } // restore cursor + cursor_goto(ui, saved_row, saved_col); +} + +static bool can_use_scroll(UI * ui) +{ + TUIData *data = ui->data; + UGrid *grid = &data->grid; + + return data->scroll_region_is_full_screen + || (data->can_change_scroll_region + && ((grid->left == 0 && grid->right == ui->width - 1) + || data->can_set_lr_margin + || data->can_set_left_right_margin)); +} + +static void set_scroll_region(UI *ui) +{ + TUIData *data = ui->data; + UGrid *grid = &data->grid; + + data->params[0].i = grid->top; + data->params[1].i = grid->bot; + unibi_out(ui, unibi_change_scroll_region); + if (grid->left != 0 || grid->right != ui->width - 1) { + unibi_out_ext(ui, data->unibi_ext.enable_lr_margin); + if (data->can_set_lr_margin) { + data->params[0].i = grid->left; + data->params[1].i = grid->right; + unibi_out(ui, unibi_set_lr_margin); + } else { + data->params[0].i = grid->left; + unibi_out(ui, unibi_set_left_margin_parm); + data->params[0].i = grid->right; + unibi_out(ui, unibi_set_right_margin_parm); + } + } unibi_goto(ui, grid->row, grid->col); } -static void tui_resize(UI *ui, int width, int height) +static void reset_scroll_region(UI *ui) { TUIData *data = ui->data; - ugrid_resize(&data->grid, width, height); + UGrid *grid = &data->grid; + + if (0 <= data->unibi_ext.reset_scroll_region) { + unibi_out_ext(ui, data->unibi_ext.reset_scroll_region); + } else { + data->params[0].i = 0; + data->params[1].i = ui->height - 1; + unibi_out(ui, unibi_change_scroll_region); + } + if (grid->left != 0 || grid->right != ui->width - 1) { + if (data->can_set_lr_margin) { + data->params[0].i = 0; + data->params[1].i = ui->width - 1; + unibi_out(ui, unibi_set_lr_margin); + } else { + data->params[0].i = 0; + unibi_out(ui, unibi_set_left_margin_parm); + data->params[0].i = ui->width - 1; + unibi_out(ui, unibi_set_right_margin_parm); + } + unibi_out_ext(ui, data->unibi_ext.disable_lr_margin); + } + unibi_goto(ui, grid->row, grid->col); +} + +static void tui_resize(UI *ui, Integer width, Integer height) +{ + TUIData *data = ui->data; + ugrid_resize(&data->grid, (int)width, (int)height); if (!got_winch) { // Try to resize the terminal window. - char r[16]; // enough for 9999x9999 - snprintf(r, sizeof(r), "\x1b[8;%d;%dt", height, width); - out(ui, r, strlen(r)); + data->params[0].i = (int)height; + data->params[1].i = (int)width; + unibi_out_ext(ui, data->unibi_ext.resize_screen); + // DECSLPP does not reset the scroll region. + if (data->scroll_region_is_full_screen) { + reset_scroll_region(ui); + } } else { // Already handled the SIGWINCH signal; avoid double-resize. got_winch = false; } @@ -427,11 +756,65 @@ static void tui_eol_clear(UI *ui) clear_region(ui, grid->row, grid->row, grid->col, grid->right); } -static void tui_cursor_goto(UI *ui, int row, int col) +static void tui_cursor_goto(UI *ui, Integer row, Integer col) +{ + cursor_goto(ui, (int)row, (int)col); +} + +CursorShape tui_cursor_decode_shape(const char *shape_str) { + CursorShape shape = 0; + if (strequal(shape_str, "block")) { + shape = SHAPE_BLOCK; + } else if (strequal(shape_str, "vertical")) { + shape = SHAPE_VER; + } else if (strequal(shape_str, "horizontal")) { + shape = SHAPE_HOR; + } else { + EMSG2(_(e_invarg2), shape_str); + } + return shape; +} + +static cursorentry_T decode_cursor_entry(Dictionary args) +{ + cursorentry_T r; + + for (size_t i = 0; i < args.size; i++) { + char *key = args.items[i].key.data; + Object value = args.items[i].value; + + if (strequal(key, "cursor_shape")) { + r.shape = tui_cursor_decode_shape(args.items[i].value.data.string.data); + } else if (strequal(key, "blinkon")) { + r.blinkon = (int)value.data.integer; + } else if (strequal(key, "blinkoff")) { + r.blinkoff = (int)value.data.integer; + } else if (strequal(key, "hl_id")) { + r.id = (int)value.data.integer; + } + } + return r; +} + +static void tui_mode_info_set(UI *ui, bool guicursor_enabled, Array args) +{ + cursor_style_enabled = guicursor_enabled; + if (!guicursor_enabled) { + return; // Do not send cursor style control codes. + } TUIData *data = ui->data; - ugrid_goto(&data->grid, row, col); - unibi_goto(ui, row, col); + + assert(args.size); + + // cursor style entries as defined by `shape_table`. + for (size_t i = 0; i < args.size; i++) { + assert(args.items[i].type == kObjectTypeDictionary); + cursorentry_T r = decode_cursor_entry(args.items[i].data.dictionary); + data->cursor_shapes[i] = r; + } + + tui_set_mode(ui, data->showing_mode); } static void tui_update_menu(UI *ui) @@ -452,106 +835,119 @@ static void tui_busy_stop(UI *ui) static void tui_mouse_on(UI *ui) { TUIData *data = ui->data; - unibi_out(ui, data->unibi_ext.enable_mouse); - data->mouse_enabled = true; + if (!data->mouse_enabled) { + unibi_out_ext(ui, data->unibi_ext.enable_mouse); + data->mouse_enabled = true; + } } static void tui_mouse_off(UI *ui) { TUIData *data = ui->data; - unibi_out(ui, data->unibi_ext.disable_mouse); - data->mouse_enabled = false; + if (data->mouse_enabled) { + unibi_out_ext(ui, data->unibi_ext.disable_mouse); + data->mouse_enabled = false; + } } -static void tui_mode_change(UI *ui, int mode) +static void tui_set_mode(UI *ui, ModeShape mode) { + if (!cursor_style_enabled) { + return; + } TUIData *data = ui->data; - - if (mode == INSERT) { - if (data->showing_mode != INSERT) { - unibi_out(ui, data->unibi_ext.set_cursor_shape_bar); - } - } else if (mode == CMDLINE) { - if (data->showing_mode != CMDLINE) { - unibi_out(ui, data->unibi_ext.set_cursor_shape_bar); - } - } else if (mode == REPLACE) { - if (data->showing_mode != REPLACE) { - unibi_out(ui, data->unibi_ext.set_cursor_shape_ul); - } - } else { - assert(mode == NORMAL); - if (data->showing_mode != NORMAL) { - unibi_out(ui, data->unibi_ext.set_cursor_shape_block); + cursorentry_T c = data->cursor_shapes[mode]; + int shape = c.shape; + + if (c.id != 0 && ui->rgb) { + int attr = syn_id2attr(c.id); + if (attr > 0) { + attrentry_T *aep = syn_cterm_attr2entry(attr); + data->params[0].i = aep->rgb_bg_color; + unibi_out_ext(ui, data->unibi_ext.set_cursor_color); } } - data->showing_mode = mode; + + switch (shape) { + case SHAPE_BLOCK: shape = 1; break; + case SHAPE_HOR: shape = 3; break; + case SHAPE_VER: shape = 5; break; + default: WLOG("Unknown shape value %d", shape); break; + } + data->params[0].i = shape + (int)(c.blinkon == 0); + unibi_out_ext(ui, data->unibi_ext.set_cursor_style); +} + +/// @param mode editor mode +static void tui_mode_change(UI *ui, String mode, Integer mode_idx) +{ + TUIData *data = ui->data; + tui_set_mode(ui, (ModeShape)mode_idx); + data->showing_mode = (ModeShape)mode_idx; } -static void tui_set_scroll_region(UI *ui, int top, int bot, int left, - int right) +static void tui_set_scroll_region(UI *ui, Integer top, Integer bot, + Integer left, Integer right) { TUIData *data = ui->data; - ugrid_set_scroll_region(&data->grid, top, bot, left, right); - data->can_use_terminal_scroll = + ugrid_set_scroll_region(&data->grid, (int)top, (int)bot, + (int)left, (int)right); + data->scroll_region_is_full_screen = left == 0 && right == ui->width - 1 - && ((top == 0 && bot == ui->height - 1) - || unibi_get_str(data->ut, unibi_change_scroll_region)); + && top == 0 && bot == ui->height - 1; } -static void tui_scroll(UI *ui, int count) +static void tui_scroll(UI *ui, Integer count) { TUIData *data = ui->data; UGrid *grid = &data->grid; int clear_top, clear_bot; - ugrid_scroll(grid, count, &clear_top, &clear_bot); + ugrid_scroll(grid, (int)count, &clear_top, &clear_bot); + + if (can_use_scroll(ui)) { + int saved_row = grid->row; + int saved_col = grid->col; + bool scroll_clears_to_current_colour = + unibi_get_bool(data->ut, unibi_back_color_erase); - if (data->can_use_terminal_scroll) { // Change terminal scroll region and move cursor to the top - data->params[0].i = grid->top; - data->params[1].i = grid->bot; - unibi_out(ui, unibi_change_scroll_region); - unibi_goto(ui, grid->top, grid->left); + if (!data->scroll_region_is_full_screen) { + set_scroll_region(ui); + } + cursor_goto(ui, grid->top, grid->left); // also set default color attributes or some terminals can become funny - HlAttrs clear_attrs = EMPTY_ATTRS; - clear_attrs.foreground = grid->fg; - clear_attrs.background = grid->bg; - update_attrs(ui, clear_attrs); - } + if (scroll_clears_to_current_colour) { + HlAttrs clear_attrs = EMPTY_ATTRS; + clear_attrs.foreground = grid->fg; + clear_attrs.background = grid->bg; + update_attrs(ui, clear_attrs); + } - if (count > 0) { - if (data->can_use_terminal_scroll) { + if (count > 0) { if (count == 1) { unibi_out(ui, unibi_delete_line); } else { - data->params[0].i = count; + data->params[0].i = (int)count; unibi_out(ui, unibi_parm_delete_line); } - } - - } else { - if (data->can_use_terminal_scroll) { + } else { if (count == -1) { unibi_out(ui, unibi_insert_line); } else { - data->params[0].i = -count; + data->params[0].i = -(int)count; unibi_out(ui, unibi_parm_insert_line); } } - } - if (data->can_use_terminal_scroll) { // Restore terminal scroll region and cursor - data->params[0].i = 0; - data->params[1].i = ui->height - 1; - unibi_out(ui, unibi_change_scroll_region); - unibi_goto(ui, grid->row, grid->col); + if (!data->scroll_region_is_full_screen) { + reset_scroll_region(ui); + } + cursor_goto(ui, saved_row, saved_col); - if (grid->bg != -1) { - // Update the cleared area of the terminal if its builtin scrolling - // facility was used and the background color is not the default. This is - // required because scrolling may leave wrong background in the cleared - // area. + if (!scroll_clears_to_current_colour) { + // This is required because scrolling will leave wrong background in the + // cleared area on non-bge terminals. clear_region(ui, clear_top, clear_bot, grid->left, grid->right); } } else { @@ -565,10 +961,18 @@ static void tui_highlight_set(UI *ui, HlAttrs attrs) ((TUIData *)ui->data)->grid.attrs = attrs; } -static void tui_put(UI *ui, uint8_t *text, size_t size) +static void tui_put(UI *ui, String text) { TUIData *data = ui->data; - print_cell(ui, ugrid_put(&data->grid, text, size)); + UGrid *grid = &data->grid; + UCell *cell; + + cell = ugrid_put(&data->grid, (uint8_t *)text.data, text.size); + // ugrid_put does not advance the cursor correctly, as the actual terminal + // will when we print. Its cursor motion model is simplistic and wrong. So + // we have to undo what it has just done before doing it right. + grid->col--; + print_cell(ui, cell); } static void tui_bell(UI *ui) @@ -581,17 +985,17 @@ static void tui_visual_bell(UI *ui) unibi_out(ui, unibi_flash_screen); } -static void tui_update_fg(UI *ui, int fg) +static void tui_update_fg(UI *ui, Integer fg) { - ((TUIData *)ui->data)->grid.fg = fg; + ((TUIData *)ui->data)->grid.fg = (int)fg; } -static void tui_update_bg(UI *ui, int bg) +static void tui_update_bg(UI *ui, Integer bg) { - ((TUIData *)ui->data)->grid.bg = bg; + ((TUIData *)ui->data)->grid.bg = (int)bg; } -static void tui_update_sp(UI *ui, int sp) +static void tui_update_sp(UI *ui, Integer sp) { // Do nothing; 'special' color is for GUI only } @@ -603,7 +1007,7 @@ static void tui_flush(UI *ui) size_t nrevents = loop_size(data->loop); if (nrevents > TOO_MANY_EVENTS) { - ILOG("TUI event-queue flooded (thread_events=%zu); purging", nrevents); + WLOG("TUI event-queue flooded (thread_events=%zu); purging", nrevents); // Back-pressure: UI events may accumulate much faster than the terminal // device can serve them. Even if SIGINT/CTRL-C is received, user must still // wait for the TUI event-queue to drain, and if there are ~millions of @@ -613,23 +1017,23 @@ static void tui_flush(UI *ui) tui_busy_stop(ui); // avoid hidden cursor } + int saved_row = grid->row; + int saved_col = grid->col; + while (kv_size(data->invalid_regions)) { Rect r = kv_pop(data->invalid_regions); - int currow = -1; UGRID_FOREACH_CELL(grid, r.top, r.bot, r.left, r.right, { - if (currow != row) { - unibi_goto(ui, row, col); - currow = row; - } + cursor_goto(ui, row, col); print_cell(ui, cell); }); } - unibi_goto(ui, grid->row, grid->col); + cursor_goto(ui, saved_row, saved_col); flush_buf(ui, true); } +#ifdef UNIX static void suspend_event(void **argv) { UI *ui = argv[0]; @@ -651,30 +1055,33 @@ static void suspend_event(void **argv) // resume the main thread CONTINUE(data->bridge); } +#endif static void tui_suspend(UI *ui) { +#ifdef UNIX TUIData *data = ui->data; // kill(0, SIGTSTP) won't stop the UI thread, so we must poll for SIGCONT // before continuing. This is done in another callback to avoid // loop_poll_events recursion multiqueue_put_event(data->loop->fast_events, - event_create(1, suspend_event, 1, ui)); + event_create(suspend_event, 1, ui)); +#endif } -static void tui_set_title(UI *ui, char *title) +static void tui_set_title(UI *ui, String title) { TUIData *data = ui->data; - if (!(title && unibi_get_str(data->ut, unibi_to_status_line) + if (!(title.data && unibi_get_str(data->ut, unibi_to_status_line) && unibi_get_str(data->ut, unibi_from_status_line))) { return; } unibi_out(ui, unibi_to_status_line); - out(ui, title, strlen(title)); + out(ui, title.data, title.size); unibi_out(ui, unibi_from_status_line); } -static void tui_set_icon(UI *ui, char *icon) +static void tui_set_icon(UI *ui, String icon) { } @@ -775,31 +1182,33 @@ static void unibi_goto(UI *ui, int row, int col) unibi_out(ui, unibi_cursor_address); } +#define UNIBI_OUT(fn) \ + do { \ + TUIData *data = ui->data; \ + const char *str = NULL; \ + if (unibi_index >= 0) { \ + str = fn(data->ut, (unsigned)unibi_index); \ + } \ + if (str) { \ + unibi_var_t vars[26 + 26] = { { 0 } }; \ + unibi_format(vars, vars + 26, str, data->params, out, ui, NULL, NULL); \ + } \ + } while (0) static void unibi_out(UI *ui, int unibi_index) { - TUIData *data = ui->data; - - const char *str = NULL; - - if (unibi_index >= 0) { - if (unibi_index < unibi_string_begin_) { - str = unibi_get_ext_str(data->ut, (unsigned)unibi_index); - } else { - str = unibi_get_str(data->ut, (unsigned)unibi_index); - } - } - - if (str) { - unibi_var_t vars[26 + 26] = {{0}}; - unibi_format(vars, vars + 26, str, data->params, out, ui, NULL, NULL); - } + UNIBI_OUT(unibi_get_str); +} +static void unibi_out_ext(UI *ui, int unibi_index) +{ + UNIBI_OUT(unibi_get_ext_str); } +#undef UNIBI_OUT static void out(void *ctx, const char *str, size_t len) { UI *ui = ctx; TUIData *data = ui->data; - size_t available = data->bufsize - data->bufpos; + size_t available = sizeof(data->buf) - data->bufpos; if (len > available) { flush_buf(ui, false); @@ -817,152 +1226,453 @@ static void unibi_set_if_empty(unibi_term *ut, enum unibi_string str, } } -static void fix_terminfo(TUIData *data) +static int unibi_find_ext_str(unibi_term *ut, const char *name) { - unibi_term *ut = data->ut; + size_t max = unibi_count_ext_str(ut); + for (size_t i = 0; i < max; i++) { + const char * n = unibi_get_ext_str_name(ut, i); + if (n && 0 == strcmp(n, name)) { + return (int)i; + } + } + return -1; +} - const char *term = os_getenv("TERM"); - const char *colorterm = os_getenv("COLORTERM"); - if (!term) { - goto end; +/// Several entries in terminfo are known to be deficient or outright wrong, +/// unfortunately; and several terminal emulators falsely announce incorrect +/// terminal types. So patch the terminfo records after loading from an +/// external or a built-in database. In an ideal world, the real terminfo data +/// would be correct and complete, and this function would be almost empty. +static void patch_terminfo_bugs(TUIData *data, const char *term, + const char *colorterm, long vte_version, + bool konsole, bool iterm_env) +{ + unibi_term *ut = data->ut; + const char * xterm_version = os_getenv("XTERM_VERSION"); +#if 0 // We don't need to identify this specifically, for now. + bool roxterm = !!os_getenv("ROXTERM_ID"); +#endif + bool xterm = terminfo_is_term_family(term, "xterm"); + bool linuxvt = terminfo_is_term_family(term, "linux"); + bool rxvt = terminfo_is_term_family(term, "rxvt"); + bool teraterm = terminfo_is_term_family(term, "teraterm"); + bool putty = terminfo_is_term_family(term, "putty"); + bool screen = terminfo_is_term_family(term, "screen"); + bool tmux = terminfo_is_term_family(term, "tmux") || !!os_getenv("TMUX"); + bool st = terminfo_is_term_family(term, "st"); + bool gnome = terminfo_is_term_family(term, "gnome") + || terminfo_is_term_family(term, "vte"); + bool iterm = terminfo_is_term_family(term, "iterm") + || terminfo_is_term_family(term, "iterm2") + || terminfo_is_term_family(term, "iTerm.app") + || terminfo_is_term_family(term, "iTerm2.app"); + // None of the following work over SSH; see :help TERM . + bool iterm_pretending_xterm = xterm && iterm_env; + bool konsole_pretending_xterm = xterm && konsole; + bool gnome_pretending_xterm = xterm && colorterm + && strstr(colorterm, "gnome-terminal"); + bool mate_pretending_xterm = xterm && colorterm + && strstr(colorterm, "mate-terminal"); + bool true_xterm = xterm && !!xterm_version; + + char *fix_normal = (char *)unibi_get_str(ut, unibi_cursor_normal); + if (fix_normal) { + if (STARTS_WITH(fix_normal, "\x1b[?12l")) { + // terminfo typically includes DECRST 12 as part of setting up the + // normal cursor, which interferes with the user's control via + // set_cursor_style. When DECRST 12 is present, skip over it, but honor + // the rest of the cnorm setting. + fix_normal += sizeof "\x1b[?12l" - 1; + unibi_set_str(ut, unibi_cursor_normal, fix_normal); + } + if (linuxvt + && strlen(fix_normal) >= (sizeof LINUXSET0C - 1) + && !memcmp(strchr(fix_normal, 0) - (sizeof LINUXSET0C - 1), + LINUXSET0C, sizeof LINUXSET0C - 1)) { + // The Linux terminfo entry similarly includes a Linux-idiosyncractic + // cursor shape reset in cnorm, which similarly interferes with + // set_cursor_style. + fix_normal[strlen(fix_normal) - (sizeof LINUXSET0C - 1)] = 0; + } + } + char *fix_invisible = (char *)unibi_get_str(ut, unibi_cursor_invisible); + if (fix_invisible) { + if (linuxvt + && strlen(fix_invisible) >= (sizeof LINUXSET1C - 1) + && !memcmp(strchr(fix_invisible, 0) - (sizeof LINUXSET1C - 1), + LINUXSET1C, sizeof LINUXSET1C - 1)) { + // The Linux terminfo entry similarly includes a Linux-idiosyncractic + // cursor shape reset in cinvis, which similarly interferes with + // set_cursor_style. + fix_invisible[strlen(fix_invisible) - (sizeof LINUXSET1C - 1)] = 0; + } } - bool inside_tmux = os_getenv("TMUX") != NULL; + if (xterm) { + // Termit, LXTerminal, GTKTerm2, GNOME Terminal, MATE Terminal, roxterm, + // and EvilVTE falsely claim to be xterm and do not support important xterm + // control sequences that we use. In an ideal world, these would have + // their own terminal types and terminfo entries, like PuTTY does, and not + // claim to be xterm. Or they would mimic xterm properly enough to be + // treatable as xterm. -#define STARTS_WITH(str, prefix) (!memcmp(str, prefix, sizeof(prefix) - 1)) + // 2017-04 terminfo.src lacks these. genuine Xterm has them, as have + // the false claimants. + unibi_set_if_empty(ut, unibi_to_status_line, "\x1b]0;"); + unibi_set_if_empty(ut, unibi_from_status_line, "\x07"); + unibi_set_if_empty(ut, unibi_set_tb_margin, "\x1b[%i%p1%d;%p2%dr"); - if (STARTS_WITH(term, "rxvt")) { - unibi_set_if_empty(ut, unibi_exit_attribute_mode, "\x1b[m\x1b(B"); - unibi_set_if_empty(ut, unibi_flash_screen, "\x1b[?5h$<20/>\x1b[?5l"); + if (true_xterm) { + // 2017-04 terminfo.src lacks these. genuine Xterm has them. + unibi_set_if_empty(ut, unibi_set_lr_margin, "\x1b[%i%p1%d;%p2%ds"); + unibi_set_if_empty(ut, unibi_set_left_margin_parm, "\x1b[%i%p1%ds"); + unibi_set_if_empty(ut, unibi_set_right_margin_parm, "\x1b[%i;%p2%ds"); + } + if (true_xterm + || iterm_pretending_xterm + || gnome_pretending_xterm + || konsole_pretending_xterm) { + // Apple's outdated copy of terminfo.src for MacOS lacks these. + // genuine Xterm and three false claimants have them. + unibi_set_if_empty(ut, unibi_enter_italics_mode, "\x1b[3m"); + unibi_set_if_empty(ut, unibi_exit_italics_mode, "\x1b[23m"); + } + } else if (rxvt) { + // 2017-04 terminfo.src lacks these. Unicode rxvt has them. unibi_set_if_empty(ut, unibi_enter_italics_mode, "\x1b[3m"); + unibi_set_if_empty(ut, unibi_exit_italics_mode, "\x1b[23m"); unibi_set_if_empty(ut, unibi_to_status_line, "\x1b]2"); - } else if (STARTS_WITH(term, "xterm")) { - unibi_set_if_empty(ut, unibi_to_status_line, "\x1b]0;"); - } else if (STARTS_WITH(term, "screen") || STARTS_WITH(term, "tmux")) { + unibi_set_if_empty(ut, unibi_from_status_line, "\x07"); + // 2017-04 terminfo.src has older control sequences. + unibi_set_str(ut, unibi_enter_ca_mode, "\x1b[?1049h"); + unibi_set_str(ut, unibi_exit_ca_mode, "\x1b[?1049l"); + } else if (screen) { + // per the screen manual; 2017-04 terminfo.src lacks these. unibi_set_if_empty(ut, unibi_to_status_line, "\x1b_"); unibi_set_if_empty(ut, unibi_from_status_line, "\x1b\\"); + } else if (tmux) { + unibi_set_if_empty(ut, unibi_to_status_line, "\x1b_"); + unibi_set_if_empty(ut, unibi_from_status_line, "\x1b\\"); + } else if (terminfo_is_term_family(term, "interix")) { + // 2017-04 terminfo.src lacks this. + unibi_set_if_empty(ut, unibi_carriage_return, "\x0d"); + } else if (linuxvt) { + // Apple's outdated copy of terminfo.src for MacOS lacks these. + unibi_set_if_empty(ut, unibi_parm_up_cursor, "\x1b[%p1%dA"); + unibi_set_if_empty(ut, unibi_parm_down_cursor, "\x1b[%p1%dB"); + unibi_set_if_empty(ut, unibi_parm_right_cursor, "\x1b[%p1%dC"); + unibi_set_if_empty(ut, unibi_parm_left_cursor, "\x1b[%p1%dD"); + } else if (putty) { + // No bugs in the vanilla terminfo for our purposes. + } else if (iterm) { + // 2017-04 terminfo.src has older control sequences. + unibi_set_str(ut, unibi_enter_ca_mode, "\x1b[?1049h"); + unibi_set_str(ut, unibi_exit_ca_mode, "\x1b[?1049l"); + // 2017-04 terminfo.src lacks these. + unibi_set_if_empty(ut, unibi_set_tb_margin, "\x1b[%i%p1%d;%p2%dr"); + unibi_set_if_empty(ut, unibi_orig_pair, "\x1b[39;49m"); + unibi_set_if_empty(ut, unibi_enter_dim_mode, "\x1b[2m"); + unibi_set_if_empty(ut, unibi_enter_italics_mode, "\x1b[3m"); + unibi_set_if_empty(ut, unibi_exit_italics_mode, "\x1b[23m"); + unibi_set_if_empty(ut, unibi_exit_underline_mode, "\x1b[24m"); + unibi_set_if_empty(ut, unibi_exit_standout_mode, "\x1b[27m"); + } else if (st) { + // No bugs in the vanilla terminfo for our purposes. } - if (STARTS_WITH(term, "xterm") || STARTS_WITH(term, "rxvt")) { - unibi_set_if_empty(ut, unibi_cursor_normal, "\x1b[?12l\x1b[?25h"); - unibi_set_if_empty(ut, unibi_cursor_invisible, "\x1b[?25l"); - unibi_set_if_empty(ut, unibi_flash_screen, "\x1b[?5h$<100/>\x1b[?5l"); - unibi_set_if_empty(ut, unibi_exit_attribute_mode, "\x1b(B\x1b[m"); - unibi_set_if_empty(ut, unibi_change_scroll_region, "\x1b[%i%p1%d;%p2%dr"); - unibi_set_if_empty(ut, unibi_clear_screen, "\x1b[H\x1b[2J"); - unibi_set_if_empty(ut, unibi_from_status_line, "\x07"); - } - - data->unibi_ext.enable_bracketed_paste = (int)unibi_add_ext_str(ut, NULL, - "\x1b[?2004h"); - data->unibi_ext.disable_bracketed_paste = (int)unibi_add_ext_str(ut, NULL, - "\x1b[?2004l"); +// At this time (2017-07-12) it seems like all terminals that support 256 +// color codes can use semicolons in the terminal code and be fine. +// However, this is not correct according to the spec. So to reward those +// terminals that also support colons, we output the code that way on these +// specific ones. - data->unibi_ext.enable_focus_reporting = (int)unibi_add_ext_str(ut, NULL, - "\x1b[?1004h"); - data->unibi_ext.disable_focus_reporting = (int)unibi_add_ext_str(ut, NULL, - "\x1b[?1004l"); +// using colons like ISO 8613-6:1994/ITU T.416:1993 says. +#define XTERM_SETAF_256_COLON \ + "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38:5:%p1%d%;m" +#define XTERM_SETAB_256_COLON \ + "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48:5:%p1%d%;m" -#define XTERM_SETAF \ +#define XTERM_SETAF_256 \ "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m" -#define XTERM_SETAB \ +#define XTERM_SETAB_256 \ "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m" +#define XTERM_SETAF_16 \ + "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e39%;m" +#define XTERM_SETAB_16 \ + "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e39%;m" + + // Terminals where there is actually 256-colour SGR support despite what + // the terminfo record may say. + if (unibi_get_num(ut, unibi_max_colors) < 256) { + // See http://fedoraproject.org/wiki/Features/256_Color_Terminals for + // more on this. + if (true_xterm || iterm || iterm_pretending_xterm) { + unibi_set_num(ut, unibi_max_colors, 256); + unibi_set_str(ut, unibi_set_a_foreground, XTERM_SETAF_256_COLON); + unibi_set_str(ut, unibi_set_a_background, XTERM_SETAB_256_COLON); + } else if (konsole || xterm || gnome || rxvt || st || putty + || linuxvt // Linux 4.8+ supports 256-colour SGR. + || mate_pretending_xterm || gnome_pretending_xterm + || tmux + || (colorterm && strstr(colorterm, "256")) + || (term && strstr(term, "256"))) { + unibi_set_num(ut, unibi_max_colors, 256); + unibi_set_str(ut, unibi_set_a_foreground, XTERM_SETAF_256); + unibi_set_str(ut, unibi_set_a_background, XTERM_SETAB_256); + } + } + // Terminals where there is actually 16-colour SGR support despite what + // the terminfo record may say. + if (unibi_get_num(ut, unibi_max_colors) < 16) { + if (colorterm) { + unibi_set_num(ut, unibi_max_colors, 16); + unibi_set_if_empty(ut, unibi_set_a_foreground, XTERM_SETAF_16); + unibi_set_if_empty(ut, unibi_set_a_background, XTERM_SETAB_16); + } + } - if ((colorterm && strstr(colorterm, "256")) - || strstr(term, "256") - || strstr(term, "xterm")) { - // Assume TERM~=xterm or COLORTERM~=256 supports 256 colors. - unibi_set_num(ut, unibi_max_colors, 256); - unibi_set_str(ut, unibi_set_a_foreground, XTERM_SETAF); - unibi_set_str(ut, unibi_set_a_background, XTERM_SETAB); + // Some terminals can not currently be trusted to report if they support + // DECSCUSR or not. So we need to have a blacklist for when we should not + // trust the reported features. + if (!((vte_version != 0 && vte_version < 3900) || konsole)) { + // Dickey ncurses terminfo has included the Ss and Se capabilities, + // pioneered by tmux, since 2011-07-14. So adding them to terminal types, + // that do actually have such control sequences but lack the correct + // definitions in terminfo, is a fixup, not an augmentation. + data->unibi_ext.reset_cursor_style = unibi_find_ext_str(ut, "Se"); + data->unibi_ext.set_cursor_style = unibi_find_ext_str(ut, "Ss"); } + if (-1 == data->unibi_ext.set_cursor_style) { + // The DECSCUSR sequence to change the cursor shape is widely + // supported by several terminal types and should be in many + // teminfo entries. See + // https://github.com/gnachman/iTerm2/pull/92 for more. + // xterm even has an extended version that has a vertical bar. + if (!konsole && (true_xterm // per xterm ctlseqs doco (since version 282) + // per MinTTY 0.4.3-1 release notes from 2009 + || putty + // per https://bugzilla.gnome.org/show_bug.cgi?id=720821 + || (vte_version >= 3900) + || tmux // per tmux manual page + // https://lists.gnu.org/archive/html/screen-devel/2013-03/msg00000.html + || screen + || rxvt // per command.C + // per analysis of VT100Terminal.m + || iterm || iterm_pretending_xterm + || teraterm // per TeraTerm "Supported Control Functions" doco + // Allows forcing the use of DECSCUSR on linux type terminals, such as + // console-terminal-emulator from the nosh toolset, which does indeed + // implement the xterm extension: + || (linuxvt && (xterm_version || (vte_version > 0) || colorterm)))) { + data->unibi_ext.set_cursor_style = + (int)unibi_add_ext_str(ut, "Ss", "\x1b[%p1%d q"); + if (-1 == data->unibi_ext.reset_cursor_style) { + data->unibi_ext.reset_cursor_style = (int)unibi_add_ext_str(ut, "Se", + ""); + } + unibi_set_ext_str(ut, (size_t)data->unibi_ext.reset_cursor_style, + "\x1b[ q"); + } else if (linuxvt) { + // Linux uses an idiosyncratic escape code to set the cursor shape and + // does not support DECSCUSR. + // See http://linuxgazette.net/137/anonymous.html for more info + data->unibi_ext.set_cursor_style = (int)unibi_add_ext_str(ut, "Ss", + "\x1b[?" + "%?" + // The parameter passed to Ss is the DECSCUSR parameter, so the + // terminal capability has to translate into the Linux idiosyncratic + // parameter. + // + // linuxvt only supports block and underline. It is also only + // possible to have a steady block (no steady underline) + "%p1%{2}%<" "%t%{8}" // blink block + "%e%p1%{2}%=" "%t%{112}" // steady block + "%e%p1%{3}%=" "%t%{4}" // blink underline (set to half block) + "%e%p1%{4}%=" "%t%{4}" // steady underline + "%e%p1%{5}%=" "%t%{2}" // blink bar (set to underline) + "%e%p1%{6}%=" "%t%{2}" // steady bar + "%e%{0}" // anything else + "%;" "%dc"); + if (-1 == data->unibi_ext.reset_cursor_style) { + data->unibi_ext.reset_cursor_style = (int)unibi_add_ext_str(ut, "Se", + ""); + } + unibi_set_ext_str(ut, (size_t)data->unibi_ext.reset_cursor_style, + "\x1b[?c"); + } else if (konsole) { + // Konsole uses an idiosyncratic escape code to set the cursor shape and + // does not support DECSCUSR. This makes Konsole set up and apply a + // nonce profile, which has side-effects on temporary font resizing. + // In an ideal world, Konsole would just support DECSCUSR. + data->unibi_ext.set_cursor_style = (int)unibi_add_ext_str(ut, "Ss", + TMUX_WRAP(tmux, "\x1b]50;CursorShape=%?" + "%p1%{3}%<" "%t%{0}" // block + "%e%p1%{5}%<" "%t%{2}" // underline + "%e%{1}" // everything else is bar + "%;%d;BlinkingCursorEnabled=%?" + "%p1%{1}%<" "%t%{1}" // Fortunately if we exclude zero as special, + "%e%p1%{1}%&" // in all other cases we can treat bit #0 as a flag. + "%;%d\x07")); + if (-1 == data->unibi_ext.reset_cursor_style) { + data->unibi_ext.reset_cursor_style = (int)unibi_add_ext_str(ut, "Se", + ""); + } + unibi_set_ext_str(ut, (size_t)data->unibi_ext.reset_cursor_style, + "\x1b]50;\x07"); + } + } +} - if (os_getenv("NVIM_TUI_ENABLE_CURSOR_SHAPE") == NULL) { - goto end; +/// This adds stuff that is not in standard terminfo as extended unibilium +/// capabilities. +static void augment_terminfo(TUIData *data, const char *term, + const char *colorterm, long vte_version, bool konsole, bool iterm_env) +{ + unibi_term *ut = data->ut; + bool xterm = terminfo_is_term_family(term, "xterm"); + bool dtterm = terminfo_is_term_family(term, "dtterm"); + bool rxvt = terminfo_is_term_family(term, "rxvt"); + bool teraterm = terminfo_is_term_family(term, "teraterm"); + bool putty = terminfo_is_term_family(term, "putty"); + bool screen = terminfo_is_term_family(term, "screen"); + bool tmux = terminfo_is_term_family(term, "tmux") || !!os_getenv("TMUX"); + bool iterm = terminfo_is_term_family(term, "iterm") + || terminfo_is_term_family(term, "iterm2") + || terminfo_is_term_family(term, "iTerm.app") + || terminfo_is_term_family(term, "iTerm2.app"); + // None of the following work over SSH; see :help TERM . + bool iterm_pretending_xterm = xterm && iterm_env; + + const char * xterm_version = os_getenv("XTERM_VERSION"); + bool true_xterm = xterm && !!xterm_version; + + // Only define this capability for terminal types that we know understand it. + if (dtterm // originated this extension + || xterm // per xterm ctlseqs doco + || konsole // per commentary in VT102Emulation.cpp + || teraterm // per TeraTerm "Supported Control Functions" doco + || rxvt) { // per command.C + data->unibi_ext.resize_screen = (int)unibi_add_ext_str(ut, NULL, + "\x1b[8;%p1%d;%p2%dt"); + } + if (putty || xterm || rxvt) { + data->unibi_ext.reset_scroll_region = (int)unibi_add_ext_str(ut, NULL, + "\x1b[r"); + } + + // Dickey ncurses terminfo does not include the setrgbf and setrgbb + // capabilities, proposed by Rüdiger Sonderfeld on 2013-10-15. So adding + // them to terminal types, that do actually have such control sequences but + // lack the correct definitions in terminfo, is an augmentation, not a + // fixup. See https://gist.github.com/XVilka/8346728 for more about this. + + // At this time (2017-07-12) it seems like all terminals that support rgb + // color codes can use semicolons in the terminal code and be fine. + // However, this is not correct according to the spec. So to reward those + // terminals that also support colons, we output the code that way on these + // specific ones. + + // can use colons like ISO 8613-6:1994/ITU T.416:1993 says. + bool has_colon_rgb = !tmux && !screen + && ((vte_version >= 3600) // per GNOME bug #685759, #704449 + || iterm || iterm_pretending_xterm // per analysis of VT100Terminal.m + // per http://invisible-island.net/xterm/xterm.log.html#xterm_282 + || true_xterm); + + data->unibi_ext.set_rgb_foreground = unibi_find_ext_str(ut, "setrgbf"); + if (-1 == data->unibi_ext.set_rgb_foreground) { + if (has_colon_rgb) { + data->unibi_ext.set_rgb_foreground = (int)unibi_add_ext_str(ut, "setrgbf", + "\x1b[38:2:%p1%d:%p2%d:%p3%dm"); + } else { + data->unibi_ext.set_rgb_foreground = (int)unibi_add_ext_str(ut, "setrgbf", + "\x1b[38;2;%p1%d;%p2%d;%p3%dm"); + } + } + data->unibi_ext.set_rgb_background = unibi_find_ext_str(ut, "setrgbb"); + if (-1 == data->unibi_ext.set_rgb_background) { + if (has_colon_rgb) { + data->unibi_ext.set_rgb_background = (int)unibi_add_ext_str(ut, "setrgbb", + "\x1b[48:2:%p1%d:%p2%d:%p3%dm"); + } else { + data->unibi_ext.set_rgb_background = (int)unibi_add_ext_str(ut, "setrgbb", + "\x1b[48;2;%p1%d;%p2%d;%p3%dm"); + } } -#define TMUX_WRAP(seq) (inside_tmux ? "\x1bPtmux;\x1b" seq "\x1b\\" : seq) - // Support changing cursor shape on some popular terminals. - const char *term_prog = os_getenv("TERM_PROGRAM"); - const char *vte_version = os_getenv("VTE_VERSION"); - - if ((term_prog && !strcmp(term_prog, "Konsole")) - || os_getenv("KONSOLE_DBUS_SESSION") != NULL) { - // Konsole uses a proprietary escape code to set the cursor shape - // and does not support DECSCUSR. - data->unibi_ext.set_cursor_shape_bar = (int)unibi_add_ext_str(ut, NULL, - TMUX_WRAP("\x1b]50;CursorShape=1;BlinkingCursorEnabled=1\x07")); - data->unibi_ext.set_cursor_shape_ul = (int)unibi_add_ext_str(ut, NULL, - TMUX_WRAP("\x1b]50;CursorShape=2;BlinkingCursorEnabled=1\x07")); - data->unibi_ext.set_cursor_shape_block = (int)unibi_add_ext_str(ut, NULL, - TMUX_WRAP("\x1b]50;CursorShape=0;BlinkingCursorEnabled=0\x07")); - } else if (!vte_version || atoi(vte_version) >= 3900) { - // Assume that the terminal supports DECSCUSR unless it is an - // old VTE based terminal. This should not get wrapped for tmux, - // which will handle it via its Ss/Se terminfo extension - usually - // according to its terminal-overrides. - data->unibi_ext.set_cursor_shape_bar = - (int)unibi_add_ext_str(ut, NULL, "\x1b[5 q"); - data->unibi_ext.set_cursor_shape_ul = - (int)unibi_add_ext_str(ut, NULL, "\x1b[3 q"); - data->unibi_ext.set_cursor_shape_block = - (int)unibi_add_ext_str(ut, NULL, "\x1b[2 q"); + if (iterm || iterm_pretending_xterm) { + // FIXME: Bypassing tmux like this affects the cursor colour globally, in + // all panes, which is not particularly desirable. A better approach + // would use a tmux control sequence and an extra if(screen) test. + data->unibi_ext.set_cursor_color = (int)unibi_add_ext_str( + ut, NULL, TMUX_WRAP(tmux, "\033]Pl%p1%06x\033\\")); + } else if (xterm || (vte_version != 0) || rxvt) { + // This seems to be supported for a long time in VTE + // urxvt also supports this + data->unibi_ext.set_cursor_color = (int)unibi_add_ext_str( + ut, NULL, "\033]12;#%p1%06x\007"); } -end: - // Fill some empty slots with common terminal strings + /// Terminals generally ignore private modes that they do not recognize, + /// and there is no known ambiguity with these modes from terminal type to + /// terminal type, so we can afford to just set these unconditionally. + data->unibi_ext.enable_lr_margin = (int)unibi_add_ext_str(ut, NULL, + "\x1b[?69h"); + data->unibi_ext.disable_lr_margin = (int)unibi_add_ext_str(ut, NULL, + "\x1b[?69l"); + data->unibi_ext.enable_bracketed_paste = (int)unibi_add_ext_str(ut, NULL, + "\x1b[?2004h"); + data->unibi_ext.disable_bracketed_paste = (int)unibi_add_ext_str(ut, NULL, + "\x1b[?2004l"); + data->unibi_ext.enable_focus_reporting = (int)unibi_add_ext_str(ut, NULL, + "\x1b[?1004h"); + data->unibi_ext.disable_focus_reporting = (int)unibi_add_ext_str(ut, NULL, + "\x1b[?1004l"); data->unibi_ext.enable_mouse = (int)unibi_add_ext_str(ut, NULL, "\x1b[?1002h\x1b[?1006h"); data->unibi_ext.disable_mouse = (int)unibi_add_ext_str(ut, NULL, "\x1b[?1002l\x1b[?1006l"); - data->unibi_ext.set_rgb_foreground = (int)unibi_add_ext_str(ut, NULL, - "\x1b[38;2;%p1%d;%p2%d;%p3%dm"); - data->unibi_ext.set_rgb_background = (int)unibi_add_ext_str(ut, NULL, - "\x1b[48;2;%p1%d;%p2%d;%p3%dm"); - unibi_set_if_empty(ut, unibi_cursor_address, "\x1b[%i%p1%d;%p2%dH"); - unibi_set_if_empty(ut, unibi_exit_attribute_mode, "\x1b[0;10m"); - unibi_set_if_empty(ut, unibi_set_a_foreground, XTERM_SETAF); - unibi_set_if_empty(ut, unibi_set_a_background, XTERM_SETAB); - unibi_set_if_empty(ut, unibi_enter_bold_mode, "\x1b[1m"); - unibi_set_if_empty(ut, unibi_enter_underline_mode, "\x1b[4m"); - unibi_set_if_empty(ut, unibi_enter_reverse_mode, "\x1b[7m"); - unibi_set_if_empty(ut, unibi_bell, "\x07"); - unibi_set_if_empty(data->ut, unibi_enter_ca_mode, "\x1b[?1049h"); - unibi_set_if_empty(data->ut, unibi_exit_ca_mode, "\x1b[?1049l"); - unibi_set_if_empty(ut, unibi_delete_line, "\x1b[M"); - unibi_set_if_empty(ut, unibi_parm_delete_line, "\x1b[%p1%dM"); - unibi_set_if_empty(ut, unibi_insert_line, "\x1b[L"); - unibi_set_if_empty(ut, unibi_parm_insert_line, "\x1b[%p1%dL"); - unibi_set_if_empty(ut, unibi_clear_screen, "\x1b[H\x1b[J"); - unibi_set_if_empty(ut, unibi_clr_eol, "\x1b[K"); - unibi_set_if_empty(ut, unibi_clr_eos, "\x1b[J"); } static void flush_buf(UI *ui, bool toggle_cursor) { uv_write_t req; - uv_buf_t buf; + uv_buf_t bufs[3]; + uv_buf_t *bufp = bufs; TUIData *data = ui->data; - if (toggle_cursor && !data->busy) { - // not busy and the cursor is invisible(see below). Append a "cursor - // normal" command to the end of the buffer. - data->bufsize += CNORM_COMMAND_MAX_SIZE; - unibi_out(ui, unibi_cursor_normal); - data->bufsize -= CNORM_COMMAND_MAX_SIZE; + if (data->bufpos <= 0 && data->busy == data->is_invisible) { + return; + } + + if (toggle_cursor && !data->is_invisible) { + // cursor is visible. Write a "cursor invisible" command before writing the + // buffer. + bufp->base = data->invis; + bufp->len = data->invislen; + bufp++; + data->is_invisible = true; } - buf.base = data->buf; - buf.len = data->bufpos; - uv_write(&req, (uv_stream_t *)&data->output_handle, &buf, 1, NULL); - uv_run(&data->write_loop, UV_RUN_DEFAULT); - data->bufpos = 0; + if (data->bufpos > 0) { + bufp->base = data->buf; + bufp->len = data->bufpos; + bufp++; + } - if (toggle_cursor && !data->busy) { - // not busy and cursor is visible(see above), append a "cursor invisible" - // command to the beginning of the buffer for the next flush - unibi_out(ui, unibi_cursor_invisible); + if (toggle_cursor && !data->busy && data->is_invisible) { + // not busy and the cursor is invisible. Write a "cursor normal" command + // after writing the buffer. + bufp->base = data->norm; + bufp->len = data->normlen; + bufp++; + data->is_invisible = data->busy; } + + uv_write(&req, STRUCT_CAST(uv_stream_t, &data->output_handle), + bufs, (unsigned)(bufp - bufs), NULL); + uv_run(&data->write_loop, UV_RUN_DEFAULT); + data->bufpos = 0; } #if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18 @@ -979,7 +1689,7 @@ static const char *tui_get_stty_erase(void) if (tcgetattr(input_global_fd(), &t) != -1) { stty_erase[0] = (char)t.c_cc[VERASE]; stty_erase[1] = '\0'; - ILOG("stty/termios:erase=%s", stty_erase); + DLOG("stty/termios:erase=%s", stty_erase); } #endif return stty_erase; @@ -995,16 +1705,16 @@ static const char *tui_tk_ti_getstr(const char *name, const char *value, stty_erase = tui_get_stty_erase(); } - if (strcmp(name, "key_backspace") == 0) { - ILOG("libtermkey:kbs=%s", value); - if (stty_erase != NULL && stty_erase[0] != 0) { + if (strequal(name, "key_backspace")) { + DLOG("libtermkey:kbs=%s", value); + if (stty_erase[0] != 0) { return stty_erase; } - } else if (strcmp(name, "key_dc") == 0) { - ILOG("libtermkey:kdch1=%s", value); + } else if (strequal(name, "key_dc")) { + DLOG("libtermkey:kdch1=%s", value); // Vim: "If <BS> and <DEL> are now the same, redefine <DEL>." - if (stty_erase != NULL && strcmp(stty_erase, value) == 0) { - return stty_erase[0] == DEL ? (char *)CTRL_H_STR : (char *)DEL_STR; + if (value != NULL && strequal(stty_erase, value)) { + return stty_erase[0] == DEL ? CTRL_H_STR : DEL_STR; } } diff --git a/src/nvim/tui/tui.h b/src/nvim/tui/tui.h index 07523bc124..996496ee60 100644 --- a/src/nvim/tui/tui.h +++ b/src/nvim/tui/tui.h @@ -1,6 +1,9 @@ #ifndef NVIM_TUI_TUI_H #define NVIM_TUI_TUI_H +#include "nvim/cursor_shape.h" +#include "nvim/ui.h" + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "tui/tui.h.generated.h" #endif diff --git a/src/nvim/types.h b/src/nvim/types.h index 35a5d1e2bd..317bead3bb 100644 --- a/src/nvim/types.h +++ b/src/nvim/types.h @@ -14,4 +14,5 @@ typedef unsigned char char_u; typedef uint32_t u8char_T; typedef struct expand expand_T; + #endif // NVIM_TYPES_H diff --git a/src/nvim/ugrid.c b/src/nvim/ugrid.c index 127b18feb6..7a0a16687e 100644 --- a/src/nvim/ugrid.c +++ b/src/nvim/ugrid.c @@ -1,3 +1,6 @@ +// 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 <stdbool.h> #include <stdio.h> diff --git a/src/nvim/ui.c b/src/nvim/ui.c index d3784b6cd3..b85a01814d 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -1,3 +1,6 @@ +// 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 <inttypes.h> #include <stdbool.h> @@ -5,6 +8,7 @@ #include <limits.h> #include "nvim/vim.h" +#include "nvim/log.h" #include "nvim/ui.h" #include "nvim/charset.h" #include "nvim/cursor.h" @@ -29,6 +33,7 @@ #include "nvim/screen.h" #include "nvim/syntax.h" #include "nvim/window.h" +#include "nvim/cursor_shape.h" #ifdef FEAT_TUI # include "nvim/tui/tui.h" #else @@ -43,6 +48,7 @@ #define MAX_UI_COUNT 16 static UI *uis[MAX_UI_COUNT]; +static bool ui_ext[UI_WIDGETS] = { 0 }; static size_t ui_count = 0; static int row = 0, col = 0; static struct { @@ -52,6 +58,28 @@ static int current_attr_code = 0; static bool pending_cursor_update = false; static int busy = 0; static int height, width; +static int old_mode_idx = -1; + +#if MIN_LOG_LEVEL > DEBUG_LOG_LEVEL +# define UI_LOG(funname, ...) +#else +static size_t uilog_seen = 0; +static char uilog_last_event[1024] = { 0 }; +# define UI_LOG(funname, ...) \ + do { \ + if (strequal(uilog_last_event, STR(funname))) { \ + uilog_seen++; \ + } else { \ + if (uilog_seen > 0) { \ + do_log(DEBUG_LOG_LEVEL, "ui", 0, true, \ + "%s (+%zu times...)", uilog_last_event, uilog_seen); \ + } \ + DLOG("ui: " STR(funname)); \ + uilog_seen = 0; \ + xstrlcpy(uilog_last_event, STR(funname), sizeof(uilog_last_event)); \ + } \ + } while (0) +#endif // UI_CALL invokes a function on all registered UI instances. The functions can // have 0-5 arguments (configurable by SELECT_NTH). @@ -61,6 +89,7 @@ static int height, width; # define UI_CALL(funname, ...) \ do { \ flush_cursor_update(); \ + UI_LOG(funname, 0); \ for (size_t i = 0; i < ui_count; i++) { \ UI *ui = uis[i]; \ UI_CALL_MORE(funname, __VA_ARGS__); \ @@ -70,6 +99,7 @@ static int height, width; # define UI_CALL(...) \ do { \ flush_cursor_update(); \ + UI_LOG(__VA_ARGS__, 0); \ for (size_t i = 0; i < ui_count; i++) { \ UI *ui = uis[i]; \ UI_CALL_HELPER(CNT(__VA_ARGS__), __VA_ARGS__); \ @@ -79,10 +109,15 @@ static int height, width; #define CNT(...) SELECT_NTH(__VA_ARGS__, MORE, MORE, MORE, MORE, ZERO, ignore) #define SELECT_NTH(a1, a2, a3, a4, a5, a6, ...) a6 #define UI_CALL_HELPER(c, ...) UI_CALL_HELPER2(c, __VA_ARGS__) +// Resolves to UI_CALL_MORE or UI_CALL_ZERO. #define UI_CALL_HELPER2(c, ...) UI_CALL_##c(__VA_ARGS__) #define UI_CALL_MORE(method, ...) if (ui->method) ui->method(ui, __VA_ARGS__) #define UI_CALL_ZERO(method) if (ui->method) ui->method(ui) +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "ui_events_call.generated.h" +#endif + void ui_builtin_start(void) { #ifdef FEAT_TUI @@ -122,24 +157,6 @@ bool ui_active(void) return ui_count != 0; } -void ui_suspend(void) -{ - UI_CALL(suspend); - UI_CALL(flush); -} - -void ui_set_title(char *title) -{ - UI_CALL(set_title, title); - UI_CALL(flush); -} - -void ui_set_icon(char *icon) -{ - UI_CALL(set_icon, icon); - UI_CALL(flush); -} - void ui_event(char *name, Array args) { bool args_consumed = false; @@ -149,31 +166,45 @@ void ui_event(char *name, Array args) } } -// May update the shape of the cursor. -void ui_cursor_shape(void) -{ - ui_mode_change(); -} - void ui_refresh(void) { if (!ui_active()) { return; } + if (updating_screen) { + ui_schedule_refresh(); + return; + } + int width = INT_MAX, height = INT_MAX; - bool pum_external = true; + bool ext_widgets[UI_WIDGETS]; + for (UIWidget i = 0; (int)i < UI_WIDGETS; i++) { + ext_widgets[i] = true; + } for (size_t i = 0; i < ui_count; i++) { UI *ui = uis[i]; width = MIN(ui->width, width); height = MIN(ui->height, height); - pum_external &= ui->pum_external; + for (UIWidget i = 0; (int)i < UI_WIDGETS; i++) { + ext_widgets[i] &= ui->ui_ext[i]; + } } row = col = 0; + + int save_p_lz = p_lz; + p_lz = false; // convince redrawing() to return true ... screen_resize(width, height); - pum_set_external(pum_external); + p_lz = save_p_lz; + + for (UIWidget i = 0; (int)i < UI_WIDGETS; i++) { + ui_set_external(i, ext_widgets[i]); + } + ui_mode_info_set(); + old_mode_idx = -1; + ui_cursor_shape(); } static void ui_refresh_event(void **argv) @@ -183,7 +214,7 @@ static void ui_refresh_event(void **argv) void ui_schedule_refresh(void) { - loop_schedule(&main_loop, event_create(1, ui_refresh_event, 0)); + loop_schedule(&main_loop, event_create(ui_refresh_event, 0)); } void ui_resize(int new_width, int new_height) @@ -199,33 +230,23 @@ void ui_resize(int new_width, int new_height) sr.bot = height - 1; sr.left = 0; sr.right = width - 1; - UI_CALL(resize, width, height); + ui_call_resize(width, height); } void ui_busy_start(void) { if (!(busy++)) { - UI_CALL(busy_start); + ui_call_busy_start(); } } void ui_busy_stop(void) { if (!(--busy)) { - UI_CALL(busy_stop); + ui_call_busy_stop(); } } -void ui_mouse_on(void) -{ - UI_CALL(mouse_on); -} - -void ui_mouse_off(void) -{ - UI_CALL(mouse_off); -} - void ui_attach_impl(UI *ui) { if (ui_count == MAX_UI_COUNT) { @@ -258,16 +279,14 @@ void ui_detach_impl(UI *ui) shift_index++; } - if (--ui_count) { + if (--ui_count + // During teardown/exit the loop was already destroyed, cannot schedule. + // https://github.com/neovim/neovim/pull/5119#issuecomment-258667046 + && !exiting) { ui_schedule_refresh(); } } -void ui_clear(void) -{ - UI_CALL(clear); -} - // Set scrolling region for window 'wp'. // The region starts 'off' lines from the start of the window. // Also set the vertical scroll region for a vertically split window. Always @@ -282,7 +301,7 @@ void ui_set_scroll_region(win_T *wp, int off) sr.right = wp->w_wincol + wp->w_width - 1; } - UI_CALL(set_scroll_region, sr.top, sr.bot, sr.left, sr.right); + ui_call_set_scroll_region(sr.top, sr.bot, sr.left, sr.right); } // Reset scrolling region to the whole screen. @@ -292,22 +311,7 @@ void ui_reset_scroll_region(void) sr.bot = (int)Rows - 1; sr.left = 0; sr.right = (int)Columns - 1; - UI_CALL(set_scroll_region, sr.top, sr.bot, sr.left, sr.right); -} - -void ui_append_lines(int count) -{ - UI_CALL(scroll, -count); -} - -void ui_delete_lines(int count) -{ - UI_CALL(scroll, count); -} - -void ui_eol_clear(void) -{ - UI_CALL(eol_clear); + ui_call_set_scroll_region(sr.top, sr.bot, sr.left, sr.right); } void ui_start_highlight(int attr_code) @@ -332,23 +336,31 @@ void ui_stop_highlight(void) set_highlight_args(current_attr_code); } -void ui_visual_bell(void) -{ - UI_CALL(visual_bell); -} - void ui_puts(uint8_t *str) { - uint8_t *ptr = str; + uint8_t *p = str; uint8_t c; - while ((c = *ptr)) { + while ((c = *p)) { if (c < 0x20) { - parse_control_character(c); - ptr++; - } else { - send_output(&ptr); + abort(); + } + + size_t clen = (size_t)mb_ptr2len(p); + ui_call_put((String){ .data = (char *)p, .size = clen }); + col++; + if (mb_ptr2cells(p) > 1) { + // double cell character, blank the next cell + ui_call_put((String)STRING_INIT); + col++; + } + if (utf_ambiguous_width(utf_ptr2char(p))) { + pending_cursor_update = true; + } + if (col >= width) { + ui_linefeed(); } + p += clen; } } @@ -368,9 +380,12 @@ void ui_cursor_goto(int new_row, int new_col) pending_cursor_update = true; } -void ui_update_menu(void) +void ui_mode_info_set(void) { - UI_CALL(update_menu); + Array style = mode_style_array(); + bool enabled = (*p_guicursor != NUL); + ui_call_mode_info_set(enabled, style); + api_free_array(style); } int ui_current_row(void) @@ -385,47 +400,7 @@ int ui_current_col(void) void ui_flush(void) { - UI_CALL(flush); -} - -static void send_output(uint8_t **ptr) -{ - uint8_t *p = *ptr; - - while (*p >= 0x20) { - size_t clen = (size_t)mb_ptr2len(p); - UI_CALL(put, p, (size_t)clen); - col++; - if (mb_ptr2cells(p) > 1) { - // double cell character, blank the next cell - UI_CALL(put, NULL, 0); - col++; - } - if (utf_ambiguous_width(utf_ptr2char(p))) { - pending_cursor_update = true; - } - if (col >= width) { - ui_linefeed(); - } - p += clen; - } - - *ptr = p; -} - -static void parse_control_character(uint8_t c) -{ - if (c == '\n') { - ui_linefeed(); - } else if (c == '\r') { - ui_carriage_return(); - } else if (c == '\b') { - ui_cursor_left(); - } else if (c == Ctrl_L) { - ui_cursor_right(); - } else if (c == Ctrl_G) { - UI_CALL(bell); - } + ui_call_flush(); } static void set_highlight_args(int attr_code) @@ -483,65 +458,53 @@ end: UI_CALL(highlight_set, (ui->rgb ? rgb_attrs : cterm_attrs)); } -static void ui_linefeed(void) +void ui_linefeed(void) { int new_col = 0; int new_row = row; if (new_row < sr.bot) { new_row++; } else { - UI_CALL(scroll, 1); + ui_call_scroll(1); } ui_cursor_goto(new_row, new_col); } -static void ui_carriage_return(void) -{ - int new_col = 0; - ui_cursor_goto(row, new_col); -} - -static void ui_cursor_left(void) -{ - int new_col = col - 1; - assert(new_col >= 0); - ui_cursor_goto(row, new_col); -} - -static void ui_cursor_right(void) -{ - int new_col = col + 1; - assert(new_col < width); - ui_cursor_goto(row, new_col); -} - static void flush_cursor_update(void) { if (pending_cursor_update) { pending_cursor_update = false; - UI_CALL(cursor_goto, row, col); + ui_call_cursor_goto(row, col); } } -// Notify that the current mode has changed. Can be used to change cursor -// shape, for example. -static void ui_mode_change(void) +/// Check if current mode has changed. +/// May update the shape of the cursor. +void ui_cursor_shape(void) { - int mode; if (!full_screen) { return; } - // Get a simple UI mode out of State. - if ((State & REPLACE) == REPLACE) { - mode = REPLACE; - } else if (State & INSERT) { - mode = INSERT; - } else if (State & CMDLINE) { - mode = CMDLINE; - } else { - mode = NORMAL; + int mode_idx = cursor_get_mode_idx(); + + if (old_mode_idx != mode_idx) { + old_mode_idx = mode_idx; + char *full_name = shape_table[mode_idx].full_name; + ui_call_mode_change(cstr_as_string(full_name), mode_idx); } - UI_CALL(mode_change, mode); conceal_check_cursur_line(); } +/// Returns true if `widget` is externalized. +bool ui_is_external(UIWidget widget) +{ + return ui_ext[widget]; +} + +/// Sets `widget` as "external". +/// Such widgets are not drawn by Nvim; external UIs are expected to handle +/// higher-level UI events and present the data. +void ui_set_external(UIWidget widget, bool external) +{ + ui_ext[widget] = external; +} diff --git a/src/nvim/ui.h b/src/nvim/ui.h index d14bc5812c..064f77fee1 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -6,6 +6,15 @@ #include <stdint.h> #include "api/private/defs.h" +#include "nvim/buffer_defs.h" + +typedef enum { + kUICmdline = 0, + kUIPopupmenu, + kUITabline, + kUIWildmenu, +} UIWidget; +#define UI_WIDGETS (kUIWildmenu + 1) typedef struct { bool bold, underline, undercurl, italic, reverse; @@ -15,37 +24,21 @@ typedef struct { typedef struct ui_t UI; struct ui_t { - bool rgb, pum_external; + bool rgb; + bool ui_ext[UI_WIDGETS]; ///< Externalized widgets int width, height; void *data; - void (*resize)(UI *ui, int rows, int columns); - void (*clear)(UI *ui); - void (*eol_clear)(UI *ui); - void (*cursor_goto)(UI *ui, int row, int col); - void (*update_menu)(UI *ui); - void (*busy_start)(UI *ui); - void (*busy_stop)(UI *ui); - void (*mouse_on)(UI *ui); - void (*mouse_off)(UI *ui); - void (*mode_change)(UI *ui, int mode); - void (*set_scroll_region)(UI *ui, int top, int bot, int left, int right); - void (*scroll)(UI *ui, int count); - void (*highlight_set)(UI *ui, HlAttrs attrs); - void (*put)(UI *ui, uint8_t *str, size_t len); - void (*bell)(UI *ui); - void (*visual_bell)(UI *ui); - void (*flush)(UI *ui); - void (*update_fg)(UI *ui, int fg); - void (*update_bg)(UI *ui, int bg); - void (*update_sp)(UI *ui, int sp); - void (*suspend)(UI *ui); - void (*set_title)(UI *ui, char *title); - void (*set_icon)(UI *ui, char *icon); + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "ui_events.generated.h" +#endif + void (*event)(UI *ui, char *name, Array args, bool *args_consumed); void (*stop)(UI *ui); }; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ui.h.generated.h" +# include "ui_events_call.h.generated.h" #endif #endif // NVIM_UI_H diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c index 25861abc1b..5585886612 100644 --- a/src/nvim/ui_bridge.c +++ b/src/nvim/ui_bridge.c @@ -1,3 +1,6 @@ +// 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 + // UI wrapper that sends requests to the UI thread. // Used by the built-in TUI and libnvim-based UIs. @@ -13,6 +16,7 @@ #include "nvim/memory.h" #include "nvim/ui_bridge.h" #include "nvim/ugrid.h" +#include "nvim/api/private/helpers.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ui_bridge.c.generated.h" @@ -20,45 +24,29 @@ #define UI(b) (((UIBridgeData *)b)->ui) -#if MIN_LOG_LEVEL <= DEBUG_LOG_LEVEL -static size_t uilog_seen = 0; -static argv_callback uilog_event = NULL; -#define UI_CALL(ui, name, argc, ...) \ - do { \ - if (uilog_event == ui_bridge_##name##_event) { \ - uilog_seen++; \ - } else { \ - if (uilog_seen > 0) { \ - DLOG("UI bridge: ...%zu times", uilog_seen); \ - } \ - DLOG("UI bridge: " STR(name)); \ - uilog_seen = 0; \ - uilog_event = ui_bridge_##name##_event; \ - } \ - ((UIBridgeData *)ui)->scheduler( \ - event_create(1, ui_bridge_##name##_event, argc, __VA_ARGS__), UI(ui)); \ - } while (0) -#else // Schedule a function call on the UI bridge thread. -#define UI_CALL(ui, name, argc, ...) \ +#define UI_BRIDGE_CALL(ui, name, argc, ...) \ ((UIBridgeData *)ui)->scheduler( \ - event_create(1, ui_bridge_##name##_event, argc, __VA_ARGS__), UI(ui)) -#endif + event_create(ui_bridge_##name##_event, argc, __VA_ARGS__), UI(ui)) + +#define INT2PTR(i) ((void *)(intptr_t)i) +#define PTR2INT(p) ((Integer)(intptr_t)p) -#define INT2PTR(i) ((void *)(uintptr_t)i) -#define PTR2INT(p) ((int)(uintptr_t)p) +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "ui_events_bridge.generated.h" +#endif UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler) { UIBridgeData *rv = xcalloc(1, sizeof(UIBridgeData)); rv->ui = ui; rv->bridge.rgb = ui->rgb; - rv->bridge.pum_external = ui->pum_external; rv->bridge.stop = ui_bridge_stop; rv->bridge.resize = ui_bridge_resize; rv->bridge.clear = ui_bridge_clear; rv->bridge.eol_clear = ui_bridge_eol_clear; rv->bridge.cursor_goto = ui_bridge_cursor_goto; + rv->bridge.mode_info_set = ui_bridge_mode_info_set; rv->bridge.update_menu = ui_bridge_update_menu; rv->bridge.busy_start = ui_bridge_busy_start; rv->bridge.busy_stop = ui_bridge_busy_stop; @@ -80,6 +68,10 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler) rv->bridge.set_icon = ui_bridge_set_icon; rv->scheduler = scheduler; + for (UIWidget i = 0; (int)i < UI_WIDGETS; i++) { + rv->bridge.ui_ext[i] = ui->ui_ext[i]; + } + rv->ui_main = ui_main; uv_mutex_init(&rv->mutex); uv_cond_init(&rv->cond); @@ -116,7 +108,7 @@ static void ui_bridge_stop(UI *b) { UIBridgeData *bridge = (UIBridgeData *)b; bool stopped = bridge->stopped = false; - UI_CALL(b, stop, 1, b); + UI_BRIDGE_CALL(b, stop, 1, b); for (;;) { uv_mutex_lock(&bridge->mutex); stopped = bridge->stopped; @@ -138,134 +130,11 @@ static void ui_bridge_stop_event(void **argv) ui->stop(ui); } -static void ui_bridge_resize(UI *b, int width, int height) -{ - UI_CALL(b, resize, 3, b, INT2PTR(width), INT2PTR(height)); -} -static void ui_bridge_resize_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->resize(ui, PTR2INT(argv[1]), PTR2INT(argv[2])); -} - -static void ui_bridge_clear(UI *b) -{ - UI_CALL(b, clear, 1, b); -} -static void ui_bridge_clear_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->clear(ui); -} - -static void ui_bridge_eol_clear(UI *b) -{ - UI_CALL(b, eol_clear, 1, b); -} -static void ui_bridge_eol_clear_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->eol_clear(ui); -} - -static void ui_bridge_cursor_goto(UI *b, int row, int col) -{ - UI_CALL(b, cursor_goto, 3, b, INT2PTR(row), INT2PTR(col)); -} -static void ui_bridge_cursor_goto_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->cursor_goto(ui, PTR2INT(argv[1]), PTR2INT(argv[2])); -} - -static void ui_bridge_update_menu(UI *b) -{ - UI_CALL(b, update_menu, 1, b); -} -static void ui_bridge_update_menu_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->update_menu(ui); -} - -static void ui_bridge_busy_start(UI *b) -{ - UI_CALL(b, busy_start, 1, b); -} -static void ui_bridge_busy_start_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->busy_start(ui); -} - -static void ui_bridge_busy_stop(UI *b) -{ - UI_CALL(b, busy_stop, 1, b); -} -static void ui_bridge_busy_stop_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->busy_stop(ui); -} - -static void ui_bridge_mouse_on(UI *b) -{ - UI_CALL(b, mouse_on, 1, b); -} -static void ui_bridge_mouse_on_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->mouse_on(ui); -} - -static void ui_bridge_mouse_off(UI *b) -{ - UI_CALL(b, mouse_off, 1, b); -} -static void ui_bridge_mouse_off_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->mouse_off(ui); -} - -static void ui_bridge_mode_change(UI *b, int mode) -{ - UI_CALL(b, mode_change, 2, b, INT2PTR(mode)); -} -static void ui_bridge_mode_change_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->mode_change(ui, PTR2INT(argv[1])); -} - -static void ui_bridge_set_scroll_region(UI *b, int top, int bot, int left, - int right) -{ - UI_CALL(b, set_scroll_region, 5, b, INT2PTR(top), INT2PTR(bot), - INT2PTR(left), INT2PTR(right)); -} -static void ui_bridge_set_scroll_region_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->set_scroll_region(ui, PTR2INT(argv[1]), PTR2INT(argv[2]), - PTR2INT(argv[3]), PTR2INT(argv[4])); -} - -static void ui_bridge_scroll(UI *b, int count) -{ - UI_CALL(b, scroll, 2, b, INT2PTR(count)); -} -static void ui_bridge_scroll_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->scroll(ui, PTR2INT(argv[1])); -} - static void ui_bridge_highlight_set(UI *b, HlAttrs attrs) { HlAttrs *a = xmalloc(sizeof(HlAttrs)); *a = attrs; - UI_CALL(b, highlight_set, 2, b, a); + UI_BRIDGE_CALL(b, highlight_set, 2, b, a); } static void ui_bridge_highlight_set_event(void **argv) { @@ -274,87 +143,11 @@ static void ui_bridge_highlight_set_event(void **argv) xfree(argv[1]); } -static void ui_bridge_put(UI *b, uint8_t *text, size_t size) -{ - uint8_t *t = NULL; - if (text) { - t = xmalloc(sizeof(((UCell *)0)->data)); - memcpy(t, text, size); - } - UI_CALL(b, put, 3, b, t, INT2PTR(size)); -} -static void ui_bridge_put_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->put(ui, (uint8_t *)argv[1], (size_t)(uintptr_t)argv[2]); - xfree(argv[1]); -} - -static void ui_bridge_bell(UI *b) -{ - UI_CALL(b, bell, 1, b); -} -static void ui_bridge_bell_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->bell(ui); -} - -static void ui_bridge_visual_bell(UI *b) -{ - UI_CALL(b, visual_bell, 1, b); -} -static void ui_bridge_visual_bell_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->visual_bell(ui); -} - -static void ui_bridge_update_fg(UI *b, int fg) -{ - UI_CALL(b, update_fg, 2, b, INT2PTR(fg)); -} -static void ui_bridge_update_fg_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->update_fg(ui, PTR2INT(argv[1])); -} - -static void ui_bridge_update_bg(UI *b, int bg) -{ - UI_CALL(b, update_bg, 2, b, INT2PTR(bg)); -} -static void ui_bridge_update_bg_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->update_bg(ui, PTR2INT(argv[1])); -} - -static void ui_bridge_update_sp(UI *b, int sp) -{ - UI_CALL(b, update_sp, 2, b, INT2PTR(sp)); -} -static void ui_bridge_update_sp_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->update_sp(ui, PTR2INT(argv[1])); -} - -static void ui_bridge_flush(UI *b) -{ - UI_CALL(b, flush, 1, b); -} -static void ui_bridge_flush_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->flush(ui); -} - static void ui_bridge_suspend(UI *b) { UIBridgeData *data = (UIBridgeData *)b; uv_mutex_lock(&data->mutex); - UI_CALL(b, suspend, 1, b); + UI_BRIDGE_CALL(b, suspend, 1, b); data->ready = false; // suspend the main thread until CONTINUE is called by the UI thread while (!data->ready) { @@ -367,25 +160,3 @@ static void ui_bridge_suspend_event(void **argv) UI *ui = UI(argv[0]); ui->suspend(ui); } - -static void ui_bridge_set_title(UI *b, char *title) -{ - UI_CALL(b, set_title, 2, b, title ? xstrdup(title) : NULL); -} -static void ui_bridge_set_title_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->set_title(ui, argv[1]); - xfree(argv[1]); -} - -static void ui_bridge_set_icon(UI *b, char *icon) -{ - UI_CALL(b, set_icon, 2, b, icon ? xstrdup(icon) : NULL); -} -static void ui_bridge_set_icon_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->set_icon(ui, argv[1]); - xfree(argv[1]); -} diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 4d56046bc1..3d7ebc8837 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -1,3 +1,6 @@ +// 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 + /* * undo.c: multi level undo facility * @@ -76,12 +79,14 @@ #include <inttypes.h> #include <limits.h> #include <stdbool.h> +#include <stdint.h> #include <string.h> #include <fcntl.h> #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/undo.h" +#include "nvim/macros.h" #include "nvim/cursor.h" #include "nvim/edit.h" #include "nvim/eval.h" @@ -305,23 +310,19 @@ bool undo_allowed(void) return true; } -/* - * Get the undolevle value for the current buffer. - */ +/// Get the 'undolevels' value for the current buffer. static long get_undolevel(void) { - if (curbuf->terminal) { - return -1; - } - if (curbuf->b_p_ul == NO_LOCAL_UNDOLEVEL) + if (curbuf->b_p_ul == NO_LOCAL_UNDOLEVEL) { return p_ul; + } return curbuf->b_p_ul; } static inline void zero_fmark_additional_data(fmark_T *fmarks) { for (size_t i = 0; i < NMARKS; i++) { - dict_unref(fmarks[i].additional_data); + tv_dict_unref(fmarks[i].additional_data); fmarks[i].additional_data = NULL; } } @@ -969,12 +970,12 @@ static u_entry_T *unserialize_uep(bufinfo_T * bi, bool *error, uep->ue_lcount = undo_read_4c(bi); uep->ue_size = undo_read_4c(bi); - char_u **array; + char_u **array = NULL; if (uep->ue_size > 0) { - array = xmalloc(sizeof(char_u *) * (size_t)uep->ue_size); - memset(array, 0, sizeof(char_u *) * (size_t)uep->ue_size); - } else { - array = NULL; + if ((size_t)uep->ue_size < SIZE_MAX / sizeof(char_u *)) { + array = xmalloc(sizeof(char_u *) * (size_t)uep->ue_size); + memset(array, 0, sizeof(char_u *) * (size_t)uep->ue_size); + } } uep->ue_array = array; @@ -1084,7 +1085,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, */ perm = 0600; if (buf->b_ffname != NULL) { - perm = os_getperm(buf->b_ffname); + perm = os_getperm((const char *)buf->b_ffname); if (perm < 0) { perm = 0600; } @@ -1143,7 +1144,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, EMSG2(_(e_not_open), file_name); goto theend; } - (void)os_setperm((char_u *)file_name, perm); + (void)os_setperm(file_name, perm); if (p_verbose > 0) { verbose_enter(); smsg(_("Writing undo file: %s"), file_name); @@ -1168,7 +1169,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, && os_fileinfo(file_name, &file_info_new) && file_info_old.stat.st_gid != file_info_new.stat.st_gid && os_fchown(fd, (uv_uid_t)-1, (uv_gid_t)file_info_old.stat.st_gid)) { - os_setperm((char_u *)file_name, (perm & 0707) | ((perm & 07) << 3)); + os_setperm(file_name, (perm & 0707) | ((perm & 07) << 3)); } # ifdef HAVE_SELINUX if (buf->b_ffname != NULL) @@ -1403,7 +1404,9 @@ void u_read_undo(char *name, char_u *hash, char_u *orig_name) // sequence numbers of the headers. // When there are no headers uhp_table is NULL. if (num_head > 0) { - uhp_table = xmalloc((size_t)num_head * sizeof(u_header_T *)); + if ((size_t)num_head < SIZE_MAX / sizeof(*uhp_table)) { + uhp_table = xmalloc((size_t)num_head * sizeof(*uhp_table)); + } } long num_read_uhps = 0; @@ -1710,7 +1713,8 @@ bool u_undo_and_forget(int count) if (curbuf->b_u_curhead) { to_forget->uh_alt_next.ptr = NULL; curbuf->b_u_curhead->uh_alt_prev.ptr = to_forget->uh_alt_prev.ptr; - curbuf->b_u_seq_cur = curbuf->b_u_curhead->uh_seq-1; + curbuf->b_u_seq_cur = curbuf->b_u_curhead->uh_next.ptr ? + curbuf->b_u_curhead->uh_next.ptr->uh_seq : 0; } else if (curbuf->b_u_newhead) { curbuf->b_u_seq_cur = curbuf->b_u_newhead->uh_seq; } @@ -1834,11 +1838,9 @@ void undo_time(long step, int sec, int file, int absolute) } closest = -1; } else { - /* When doing computations with time_t subtract starttime, because - * time_t converted to a long may result in a wrong number. */ - if (dosec) - target = (long)(curbuf->b_u_time_cur - starttime) + step; - else if (dofile) { + if (dosec) { + target = (long)(curbuf->b_u_time_cur) + step; + } else if (dofile) { if (step < 0) { /* Going back to a previous write. If there were changes after * the last write, count that as moving one file-write, so @@ -1876,14 +1878,16 @@ void undo_time(long step, int sec, int file, int absolute) target = 0; closest = -1; } else { - if (dosec) - closest = (long)(time(NULL) - starttime + 1); - else if (dofile) + if (dosec) { + closest = (long)(os_time() + 1); + } else if (dofile) { closest = curbuf->b_u_save_nr_last + 2; - else + } else { closest = curbuf->b_u_seq_last + 2; - if (target >= closest) + } + if (target >= closest) { target = closest - 1; + } } } closest_start = closest; @@ -1912,12 +1916,13 @@ void undo_time(long step, int sec, int file, int absolute) while (uhp != NULL) { uhp->uh_walk = mark; - if (dosec) - val = (long)(uhp->uh_time - starttime); - else if (dofile) + if (dosec) { + val = (long)(uhp->uh_time); + } else if (dofile) { val = uhp->uh_save_nr; - else + } else { val = uhp->uh_seq; + } if (round == 1 && !(dofile && val == 0)) { /* Remember the header that is closest to the target. @@ -2228,11 +2233,13 @@ static void u_undoredo(int undo) /* adjust marks */ if (oldsize != newsize) { mark_adjust(top + 1, top + oldsize, (long)MAXLNUM, - (long)newsize - (long)oldsize); - if (curbuf->b_op_start.lnum > top + oldsize) + (long)newsize - (long)oldsize, false); + if (curbuf->b_op_start.lnum > top + oldsize) { curbuf->b_op_start.lnum += newsize - oldsize; - if (curbuf->b_op_end.lnum > top + oldsize) + } + if (curbuf->b_op_end.lnum > top + oldsize) { curbuf->b_op_end.lnum += newsize - oldsize; + } } changed_lines(top + 1, 0, bot, newsize - oldsize); @@ -2321,7 +2328,8 @@ static void u_undoredo(int undo) if (undo) /* We are below the previous undo. However, to make ":earlier 1s" * work we compute this as being just above the just undone change. */ - --curbuf->b_u_seq_cur; + curbuf->b_u_seq_cur = curhead->uh_next.ptr ? + curhead->uh_next.ptr->uh_seq : 0; /* Remember where we are for ":earlier 1f" and ":later 1f". */ if (curhead->uh_save_nr != 0) { @@ -2510,13 +2518,14 @@ void ex_undolist(exarg_T *eap) sort_strings((char_u **)ga.ga_data, ga.ga_len); msg_start(); - msg_puts_attr((char_u *)_("number changes when saved"), - hl_attr(HLF_T)); - for (int i = 0; i < ga.ga_len && !got_int; ++i) { + msg_puts_attr(_("number changes when saved"), + hl_attr(HLF_T)); + for (int i = 0; i < ga.ga_len && !got_int; i++) { msg_putchar('\n'); - if (got_int) + if (got_int) { break; - msg_puts(((char_u **)ga.ga_data)[i]); + } + msg_puts(((const char **)ga.ga_data)[i]); } msg_end(); @@ -2549,20 +2558,20 @@ static void u_add_time(char_u *buf, size_t buflen, time_t tt) */ void ex_undojoin(exarg_T *eap) { - if (curbuf->b_u_newhead == NULL) - return; /* nothing changed before */ + if (curbuf->b_u_newhead == NULL) { + return; // nothing changed before + } if (curbuf->b_u_curhead != NULL) { EMSG(_("E790: undojoin is not allowed after undo")); return; } - if (!curbuf->b_u_synced) - return; /* already unsynced */ - if (get_undolevel() < 0) - return; /* no entries, nothing to do */ - else { - /* Go back to the last entry */ - curbuf->b_u_curhead = curbuf->b_u_newhead; - curbuf->b_u_synced = false; /* no entries, nothing to do */ + if (!curbuf->b_u_synced) { + return; // already unsynced + } + if (get_undolevel() < 0) { + return; // no entries, nothing to do + } else { + curbuf->b_u_synced = false; // Append next change to last entry } } @@ -2942,25 +2951,28 @@ void u_eval_tree(u_header_T *first_uhp, list_T *list) dict_T *dict; while (uhp != NULL) { - dict = dict_alloc(); - dict_add_nr_str(dict, "seq", uhp->uh_seq, NULL); - dict_add_nr_str(dict, "time", (long)uhp->uh_time, NULL); - if (uhp == curbuf->b_u_newhead) - dict_add_nr_str(dict, "newhead", 1, NULL); - if (uhp == curbuf->b_u_curhead) - dict_add_nr_str(dict, "curhead", 1, NULL); - if (uhp->uh_save_nr > 0) - dict_add_nr_str(dict, "save", uhp->uh_save_nr, NULL); + dict = tv_dict_alloc(); + tv_dict_add_nr(dict, S_LEN("seq"), (varnumber_T)uhp->uh_seq); + tv_dict_add_nr(dict, S_LEN("time"), (varnumber_T)uhp->uh_time); + if (uhp == curbuf->b_u_newhead) { + tv_dict_add_nr(dict, S_LEN("newhead"), 1); + } + if (uhp == curbuf->b_u_curhead) { + tv_dict_add_nr(dict, S_LEN("curhead"), 1); + } + if (uhp->uh_save_nr > 0) { + tv_dict_add_nr(dict, S_LEN("save"), (varnumber_T)uhp->uh_save_nr); + } if (uhp->uh_alt_next.ptr != NULL) { - list_T *alt_list = list_alloc(); + list_T *alt_list = tv_list_alloc(); - /* Recursive call to add alternate undo tree. */ + // Recursive call to add alternate undo tree. u_eval_tree(uhp->uh_alt_next.ptr, alt_list); - dict_add_list(dict, "alt", alt_list); + tv_dict_add_list(dict, S_LEN("alt"), alt_list); } - list_append_dict(list, dict); + tv_list_append_dict(list, dict); uhp = uhp->uh_prev.ptr; } } diff --git a/src/nvim/version.c b/src/nvim/version.c index 3e9cccda20..6e24e30a09 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -1,3 +1,6 @@ +// 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 + /// @file version.c /// /// Nvim was forked from Vim 7.4.160. @@ -25,8 +28,9 @@ // for ":version", ":intro", and "nvim --version" #ifndef NVIM_VERSION_MEDIUM -#define NVIM_VERSION_MEDIUM STR(NVIM_VERSION_MAJOR) "." STR(NVIM_VERSION_MINOR)\ - "." STR(NVIM_VERSION_PATCH) NVIM_VERSION_PRERELEASE +#define NVIM_VERSION_MEDIUM "v" STR(NVIM_VERSION_MAJOR)\ + "." STR(NVIM_VERSION_MINOR) "." STR(NVIM_VERSION_PATCH)\ + NVIM_VERSION_PRERELEASE #endif #define NVIM_VERSION_LONG "NVIM " NVIM_VERSION_MEDIUM @@ -72,2371 +76,878 @@ static char *features[] = { }; // clang-format off -static int included_patches[] = { - // 2367, - // 2366 NA - // 2365 NA - // 2364, - // 2363 NA - // 2362, - // 2361 NA - // 2360, - // 2359 NA - // 2358 NA - // 2357, - // 2356, - // 2355, - // 2354, - // 2353, - // 2352 NA - // 2351 NA - // 2350, - // 2349, - // 2348, - // 2347, - // 2346, - // 2345 NA - // 2344 NA - // 2343, - // 2342 NA - // 2341, - // 2340 NA - // 2339, - // 2338 NA - 2337, - // 2336, - 2335, - // 2334, - // 2333, - // 2332 NA - 2331, - // 2330, - // 2329, - // 2328, - // 2327 NA - // 2326, - // 2325 NA - // 2324, - // 2323, - // 2322, - 2321, - // 2320, - // 2319 NA - // 2318, - // 2317, - // 2316 NA - // 2315, - // 2314, - // 2313, - 2312, - // 2311 NA - // 2310 NA - 2309, - // 2308 NA - // 2307, - // 2306, - // 2305, - // 2304 NA - // 2303, - // 2302 NA - // 2301 NA - // 2300, - // 2299, - // 2298 NA - // 2297 NA - // 2296, - // 2295, - 2294, - // 2293, - // 2292, - // 2291, - // 2290 NA - // 2289 NA - // 2288 NA - // 2287 NA - // 2286 NA - // 2285 NA - 2284, - // 2283, - // 2282 NA - // 2281 NA - // 2280, - // 2279, - // 2278 NA - 2277, - // 2276, - // 2275, - 2274, - 2273, - 2272, - // 2271 NA - // 2270 NA - // 2269, - // 2268, - // 2267 NA - // 2266, - // 2265, - // 2264, - // 2263, - // 2262 NA - // 2261 NA - // 2260 NA - // 2259, - // 2258 NA - // 2257 NA - // 2256, - // 2255, - // 2254 NA - // 2253 NA - // 2252 NA - 2251, - // 2250, - // 2249, - // 2248, - // 2247 NA - // 2246, - // 2245, - // 2244, - // 2243 NA - // 2242, - // 2241, - // 2240, - // 2239, - // 2238 NA - 2237, - // 2236, - // 2235, - // 2234 NA - // 2233, - // 2232 NA - // 2231, - // 2230, - // 2229, - // 2228, - 2227, - 2226, - 2225, - // 2224, - // 2223, - // 2222, - // 2221, - // 2220, - 2219, - // 2218 NA - 2217, - // 2216 NA - 2215, - // 2214 NA - 2213, - 2212, - // 2211 NA - // 2210 NA - // 2209, - // 2208, - // 2207 NA - // 2206 NA - 2205, - 2204, - // 2203 NA - // 2202 NA - 2201, - // 2200, - // 2199 NA - // 2198 NA - // 2197, - // 2196, - // 2195 NA - 2194, - // 2193 NA - // 2192 NA - // 2191 NA - // 2190, - // 2189, - 2188, - // 2187, - // 2186 NA - // 2185, - // 2184, - 2183, - // 2182 NA - // 2181, - // 2180, - // 2179, - // 2178, - // 2177, - // 2176 NA - // 2175, - 2174, - // 2173, - // 2172, - // 2171, - // 2170, - // 2169, - // 2168 NA - // 2167 NA - // 2166 NA - // 2165, - // 2164, - 2163, - 2162, - // 2161, - // 2160, - // 2159, - 2158, - // 2157 NA - // 2156 NA - // 2155 NA - // 2154 NA - // 2153 NA - // 2152, - // 2151, - // 2150 NA - 2149, - // 2148, - 2147, - 2146, - // 2145 NA - // 2144, - // 2143, - // 2142, - // 2141, - // 2140 NA - // 2139, - // 2138 NA - // 2137, - // 2136, - // 2135, - // 2134, - // 2133 NA - // 2132 NA - // 2131 NA - // 2130 NA - // 2129 NA - 2128, - 2127, - 2126, - // 2125 NA - 2124, - 2123, - // 2122 NA - // 2121, - // 2120, - // 2119, - // 2118 NA - // 2117, - // 2116 NA - // 2115 NA - // 2114 NA - // 2113, - 2112, - // 2111, - 2110, - 2109, - // 2108 NA - // 2107, - // 2106, - // 2105 NA - // 2104, - 2103, - // 2102 NA - // 2101, - 2100, - // 2099, - // 2098, - // 2097, - // 2096, - // 2095, - // 2094 NA - // 2093 NA - // 2092 NA - // 2091 NA - // 2090, - // 2089 NA - // 2088, - // 2087, - 2086, - // 2085, - // 2084, - // 2083, - // 2082, - // 2081, - // 2080, - // 2079 NA - // 2078 NA - // 2077, - // 2076, - // 2075, - // 2074, - // 2073 NA - // 2072, - 2071, - // 2070 NA - // 2069, - // 2068, - // 2067, - 2066, - // 2065, - // 2064, - // 2063 NA - // 2062, - // 2061, - // 2060 NA - // 2059 NA - // 2058, - // 2057 NA - // 2056 NA - // 2055 NA - // 2054 NA - // 2053 NA - // 2052 NA - // 2051, - // 2050, - // 2049, - // 2048 NA - // 2047, - // 2046, - // 2045 NA - // 2044, - 2043, - // 2042 NA - // 2041 NA - // 2040 NA - // 2039 NA - // 2038 NA - // 2037 NA - // 2036, - // 2035 NA - // 2034 NA - 2033, - // 2032 NA - // 2031, - // 2030 NA - // 2029, - 2028, - // 2027 NA - // 2026 NA - // 2025 NA - // 2024, - // 2023, - // 2022, - // 2021, - // 2020 NA - 2019, - // 2018, - // 2017, - // 2016 NA - 2015, - 2014, - 2013, - 2012, - 2011, - 2010, - 2009, - 2008, - 2007, - // 2006, - 2005, - // 2004 NA - // 2003 NA - // 2002, - // 2001 NA - 2000, - 1999, - // 1998 NA - 1997, - 1996, - // 1995 NA - // 1994, - // 1993, - // 1992, - // 1991, - 1990, - // 1989, - // 1988 NA - // 1987 NA - // 1986, - // 1985 NA - 1984, - // 1983 NA - // 1982 NA - // 1981, - 1980, - // 1979, - // 1978, - // 1977, - // 1976, - // 1975, - // 1974 NA - 1973, - // 1972 NA - 1971, - 1970, - // 1969 NA - // 1968, - 1967, - 1966, - // 1965 NA - 1964, - // 1963 NA - // 1962, - 1961, - 1960, - // 1959 NA - // 1958 NA - // 1957 NA - 1956, - // 1955 NA - // 1954, - 1953, - 1952, - // 1951 NA - 1950, - 1949, - // 1948, - // 1947 NA - // 1946 NA - // 1945 NA - // 1944 NA - // 1943 NA - // 1942 NA - 1941, - 1940, - // 1939 NA - // 1938 NA - 1937, - // 1936 NA - // 1935 NA - // 1934 NA - // 1933 NA - // 1932 NA - // 1931 NA - // 1930 NA - // 1929 NA - 1928, - // 1927 NA - // 1926 NA - 1925, - // 1924 NA - 1923, - // 1922 NA - // 1921 NA - // 1920 NA - // 1919 NA - // 1918 NA - // 1917 NA - // 1916 NA - // 1915 NA - // 1914, - 1913, - 1912, - // 1911 NA - // 1910, - 1909, - // 1908 NA - // 1907 NA - // 1906 NA - // 1905 NA - // 1904 NA - // 1903 NA - // 1902 NA - // 1901 NA - 1900, - // 1899 NA - 1898, - 1897, - 1896, - 1895, - 1894, - 1893, - 1892, - // 1891 NA - // 1890 NA - 1889, - // 1888 NA - // 1887 NA - // 1886 NA - // 1885 NA - 1884, - // 1883 NA - 1882, - 1881, - // 1880 NA - // 1879 NA - // 1878 NA - // 1877 NA - 1876, - 1875, - // 1874 NA - // 1873 NA - // 1872 NA - 1871, - // 1870 NA - // 1869 NA - 1868, - 1867, - 1866, - // 1865 NA - // 1864 NA - // 1863 NA - // 1862 NA - 1861, - 1860, - // 1859 NA - // 1858 NA - // 1857 NA - // 1856 NA - // 1855 NA - // 1854 NA - // 1853 NA - // 1852 NA - // 1851, - // 1850 NA - // 1849 NA - // 1848 NA - 1847, - // 1846 NA - // 1845 NA - // 1844 NA - // 1843 NA - 1842, - 1841, - 1840, - 1839, - 1838, - 1837, - 1836, - 1835, - 1834, - 1833, - 1832, - 1831, - // 1830 NA - // 1829 NA - // 1828 NA - // 1827 NA - // 1826 NA - // 1825 NA - // 1824 NA - 1823, - // 1822 NA - 1821, - 1820, - // 1819 NA - 1818, - // 1817 NA - 1816, - 1815, - // 1814 NA - 1813, - // 1812 NA - // 1811 NA - // 1810 NA - 1809, - 1808, - // 1807 NA - 1806, - // 1805 NA - // 1804 NA - // 1803 NA - 1802, - // 1801 NA - // 1800 NA - 1799, - // 1798 NA - // 1797 NA - // 1796 NA - // 1795 NA - // 1794 NA - 1793, - // 1792 NA - // 1791 NA - // 1790 NA - // 1789 NA - // 1789 NA - // 1788 NA - // 1787 NA - // 1786 NA - 1785, - // 1784 NA - 1783, - 1782, - 1781, - 1780, - 1779, - // 1778 NA - // 1777 NA - // 1776 NA - // 1775 NA - // 1774 NA - // 1773 NA - // 1772 NA - // 1771 NA - // 1770 NA - // 1769 NA - 1768, - // 1767 NA - // 1766 NA - 1765, - // 1764 NA - 1763, - // 1762 NA - // 1761 NA - // 1760 NA - 1759, - 1758, - 1757, - // 1756 NA - 1755, - 1754, - 1753, - 1752, - 1751, - // 1750 NA - // 1749 NA - 1748, - // 1747 NA - // 1746 NA - // 1745 NA - // 1744 NA - // 1743 NA - 1742, - 1741, - 1740, - 1739, - 1738, - // 1737 NA - // 1736 NA - 1735, - 1734, - // 1733 NA - 1732, - // 1731 NA - 1730, - // 1729 NA - 1728, - // 1727 NA - // 1726 NA - // 1725 NA - // 1724 NA - 1723, - // 1722 NA - // 1721 NA - // 1720 NA - 1719, - 1718, - // 1717 NA - 1716, - 1715, - 1714, - // 1713 NA - 1712, - 1711, - // 1710 NA - // 1709 NA - 1708, - 1707, - // 1706 NA - // 1705 NA - 1704, - 1703, - 1702, - 1701, - 1700, - 1699, - // 1698 NA - 1697, - 1696, - 1695, - // 1694 NA - // 1693 NA - 1692, - 1691, - // 1690 NA - // 1689 NA - // 1688 NA - // 1687 NA - 1686, - 1685, - // 1684 NA - // 1683 NA - 1682, - 1681, - // 1680 NA - 1679, - // 1678 NA - // 1677 NA - 1676, - 1675, - // 1674 NA - 1673, - // 1672 NA - 1671, - 1670, - // 1669 NA - // 1668 NA - // 1667 NA - // 1666 NA - // 1665 NA - 1664, - 1663, - // 1662 NA - // 1661 NA - 1660, - // 1659 NA - 1658, - // 1657 NA - 1656, - // 1655 NA - 1654, - // 1653 NA - 1652, - // 1651 NA - 1650, - 1649, - 1648, - 1647, - // 1646 NA - 1645, - // 1644 NA - 1643, - 1642, - 1641, - 1640, - 1639, - 1638, - // 1637 NA - // 1636 NA - // 1635 NA - 1634, - // 1633 NA - // 1632 NA - // 1631 NA - 1630, - 1629, - // 1628 NA - // 1627 NA - // 1626 NA - // 1625 NA - // 1624 NA - // 1623 NA - // 1622 NA - // 1621 NA - 1620, - 1619, - // 1618 NA - // 1617 NA - // 1616 NA - // 1615 NA - 1614, - // 1613 NA - // 1612 NA - // 1611 NA - // 1610 NA - // 1609 NA - 1608, - 1607, - 1606, - 1605, - 1604, - 1603, - // 1602 NA - // 1601 NA - // 1600 NA - // 1599 NA - // 1598 NA - // 1597 NA - 1596, - // 1595 NA - // 1594 NA - // 1593 NA - 1592, - 1591, - 1590, - 1589, - 1588, - // 1587 NA - 1586, - 1585, - // 1584 NA - // 1583 NA - 1582, - 1581, - 1580, - // 1579 NA - 1578, - 1577, - 1576, - // 1575 NA - 1574, - // 1573 NA - // 1572 NA - 1571, - 1570, - 1569, - 1568, - 1567, - // 1566 NA - 1565, - 1564, - 1563, - // 1562 NA - // 1561 NA - // 1560 NA - 1559, - 1558, - 1557, - // 1556 NA - // 1555 NA - 1554, - 1553, - 1552, - 1551, - 1550, - 1549, - 1548, - 1547, - 1546, - // 1545 NA - // 1544 NA - // 1543 NA - // 1542 NA - // 1541 NA - // 1540 NA - // 1539 NA - // 1538 NA - // 1537 NA - // 1536 NA - 1535, - // 1534 NA - 1533, - // 1532 NA - // 1531 NA - // 1530 NA - // 1529 NA - 1528, - // 1527 NA - // 1526 NA - // 1525 NA - // 1524 NA - // 1523 NA - // 1522 NA - 1521, - // 1520 NA - // 1519 NA - // 1518 NA - // 1517 NA - 1516, - // 1515 NA - // 1514 NA - 1513, - // 1512 NA - 1511, - // 1510 NA - // 1509 NA - // 1508 NA - // 1507 NA - // 1506 NA - // 1505 NA - // 1504 NA - // 1503 NA - // 1502 NA - // 1501 NA - 1500, - 1499, - // 1498 NA - // 1497 NA - // 1496 NA - // 1495 NA - 1494, - // 1493 NA - 1492, - 1491, - // 1490 NA - // 1489 NA - // 1488 NA - // 1487 NA - 1486, - // 1485 NA - // 1484 NA - // 1483 NA - // 1482 NA - // 1481 NA - 1480, - 1479, - 1478, - 1477, - // 1476 NA - // 1475 NA - // 1474 NA - // 1473 NA - // 1472 NA - // 1471 NA - // 1470 NA - // 1469 NA - 1468, - // 1467 NA - // 1466 NA - // 1465 NA - 1464, - // 1463 NA - // 1462 NA - // 1461 NA - // 1460 NA - // 1459 NA - // 1458 NA - // 1457 NA - // 1456 NA - // 1455 NA - // 1454 NA - // 1453 NA - // 1452 NA - // 1451 NA - // 1450 NA - // 1449 NA - // 1448 NA - // 1447 NA - // 1446 NA - // 1445 NA - // 1444 NA - // 1443 NA - // 1442 NA - // 1441 NA - // 1440 NA - // 1439 NA - // 1438 NA - // 1437 NA - // 1436 NA - // 1435 NA - // 1434 NA - // 1433 NA - // 1432 NA - // 1431 NA - // 1430 NA - // 1429 NA - // 1428 NA - // 1427 NA - // 1426 NA - 1425, - // 1424 NA - // 1423 NA - // 1422 NA - // 1421 NA - // 1420 NA - // 1419 NA - // 1418 NA - // 1417 NA - // 1416 NA - // 1415 NA - // 1414 NA - // 1413 NA - // 1412 NA - // 1411 NA - 1410, - // 1409 NA - // 1408 NA - // 1407 NA - 1406, - 1405, - // 1404 NA - // 1403 NA - // 1402 NA - 1401, - // 1400 NA - // 1399 NA - // 1398 NA - 1397, - 1396, - // 1395 NA - 1394, - // 1393 NA - // 1392 NA - // 1391 NA - // 1390 NA - // 1389 NA - 1388, - // 1387 NA - // 1386 NA - // 1385 NA - 1384, - // 1383 NA - // 1382 NA - // 1381 NA - // 1380 NA - // 1379 NA - // 1378 NA - // 1377 NA - // 1376 NA - // 1375 NA - // 1374 NA - // 1373 NA - // 1372 NA - // 1371 NA - // 1370 NA - // 1369 NA - // 1368 NA - // 1367 NA - 1366, - 1365, - // 1364 NA - // 1363 NA - // 1362 NA - // 1361 NA - // 1360 NA - // 1359 NA - // 1358 NA - // 1357 NA - // 1356 NA - // 1355 NA - // 1354 NA - // 1353 NA - 1352, - // 1351 NA - // 1350 NA - // 1349 NA - // 1348 NA - 1347, - 1346, - // 1345 NA - // 1344 NA - // 1343 NA - // 1342 NA - // 1341 NA - // 1340 NA - // 1339 NA - // 1338 NA - // 1337 NA - // 1336 NA - // 1335 NA - // 1334 NA - // 1333 NA - // 1332 NA - // 1331 NA - // 1330 NA - // 1329 NA - // 1328 NA - // 1327 NA - // 1326 NA - // 1325 NA - // 1324 NA - // 1323 NA - // 1322 NA - // 1321 NA - // 1320 NA - // 1319 NA - // 1318 NA - // 1317 NA - // 1316 NA - // 1315 NA - // 1314 NA - // 1313 NA - // 1312 NA - // 1311 NA - // 1310 NA - 1309, - // 1308 NA - // 1307 NA - // 1306 NA - 1305, - 1304, - // 1303 NA - // 1302 NA - // 1301 NA - // 1300 NA - // 1299 NA - // 1298 NA - // 1297 NA - 1296, - // 1295 NA - // 1294 NA - // 1293 NA - 1292, - // 1291 NA - // 1290 NA - // 1289 NA - // 1288 NA - // 1287 NA - // 1286 NA - 1285, - 1284, - // 1283 NA - 1282, - 1281, - // 1280 NA - // 1279 NA - // 1278 NA - // 1277 NA - 1276, - // 1275 NA - // 1274 NA - // 1273 NA - // 1272 NA - 1271, - // 1270 NA - 1269, - // 1268 NA - 1267, - 1266, - // 1265 NA - // 1264 NA - // 1263 NA - // 1262 NA - // 1261 NA - // 1260 NA - 1259, - // 1258 NA - // 1257 NA - // 1256 NA - // 1255 NA - // 1254 NA - // 1253 NA - // 1252 NA - // 1251 NA - // 1250 NA - // 1249 NA - // 1248 NA - // 1247 NA - // 1246 NA - // 1245 NA - // 1244 NA - // 1243 NA - // 1242 NA - // 1241 NA - // 1240 NA - // 1239 NA - // 1238 NA - 1237, - 1236, - // 1235 NA - // 1234 NA - // 1233 NA - // 1232 NA - // 1231 NA - // 1230 NA - // 1229 NA - 1228, - // 1227 NA - // 1226 NA - // 1225 NA - // 1224 NA - 1223, - // 1222 NA - // 1221 NA - // 1220 NA - // 1219 NA - // 1218 NA - // 1217 NA - // 1216 NA - // 1215 NA - // 1214 NA - // 1213 NA - // 1212 NA - // 1211 NA - // 1210 NA - // 1209 NA - // 1208 NA - // 1207 NA - // 1206 NA - // 1205 NA - // 1204 NA - // 1203 NA - // 1202 NA - // 1201 NA - // 1200 NA - // 1199 NA - // 1198 NA - // 1197 NA - // 1196 NA - // 1195 NA - // 1194 NA - // 1193 NA - // 1192 NA - // 1191 NA - // 1190 NA - // 1189 NA - // 1188 NA - // 1187 NA - // 1186 NA - // 1185 NA - // 1184 NA - // 1183 NA - // 1182 NA - 1181, - 1180, - 1179, - 1178, - // 1177 NA - // 1176 NA - // 1175 NA - // 1174 NA - 1173, - // 1172 NA - // 1171 NA - // 1170 NA - // 1169 NA - 1168, - 1167, - 1166, - // 1165 NA - 1164, - 1163, - // 1162 NA - 1161, - 1160, - // 1159 NA - // 1158 NA - 1157, - // 1156 NA - // 1155 NA - // 1154 NA - 1153, - // 1152 NA - 1151, - 1150, - 1149, - // 1148 NA - 1147, - // 1146 NA - // 1145 NA - 1144, - 1143, - 1142, - 1141, - 1140, - // 1139 NA - // 1138 NA - 1137, - 1136, - // 1135 NA - // 1134 NA - // 1133 NA - 1132, - // 1131 NA - // 1130 NA - // 1129 NA - // 1128 NA - // 1127 NA - 1126, - // 1125 NA - // 1124 NA - 1123, - // 1122 NA - 1121, - 1120, - 1119, - 1118, - 1117, - 1116, - // 1115 NA - 1114, - 1113, - 1112, - 1111, - 1110, - // 1109 NA - 1108, - 1107, - // 1106 NA - 1105, - // 1104 NA - // 1103 NA - 1102, - 1101, - // 1100 NA - // 1099 NA - // 1098 NA - // 1097 NA - 1096, - // 1095 NA - 1094, - 1093, - 1092, - 1091, - 1090, - 1089, - 1088, - 1087, - 1086, - 1085, - 1084, - // 1083 NA - // 1082 NA - 1081, - // 1080 NA - // 1079 NA - // 1078 NA - // 1077 NA - 1076, - 1075, - // 1074 NA - // 1073 NA - 1072, - 1071, - // 1070 NA - // 1069 NA - 1068, - // 1067 NA - // 1066 NA - 1065, - 1064, - // 1063 NA - // 1062 NA - 1061, - // 1060 NA - 1059, - // 1058 NA - 1057, - 1056, - 1055, - 1054, - 1053, - 1052, - 1051, - 1050, - 1049, - 1048, - 1047, - 1046, - // 1045 NA - // 1044 NA - // 1043 NA - 1042, - 1041, - // 1040 NA - // 1039 NA - // 1038 NA - 1037, - 1036, - 1035, - 1034, - // 1033 NA - 1032, - // 1031 NA - 1030, - 1029, - // 1028 NA - 1027, - // 1026 NA - // 1025 NA - // 1024 NA - // 1023 NA - // 1022 NA - // 1021 NA - // 1020 NA - // 1019 NA - 1018, - 1017, - // 1016 NA - 1015, - // 1014 NA - 1013, - // 1012 NA - // 1011 NA - // 1010 NA - // 1009 NA - // 1008 NA - 1007, - 1006, - // 1005 NA - // 1004 NA - // 1003 NA - // 1002 NA - 1001, - 1000, - // 999 NA - 998, - // 997 NA - // 996 NA - // 995 NA - // 994 NA - // 993 NA - // 992 NA - 991, - // 990 NA - 989, - // 988 NA - // 987 NA - // 986 NA - // 985 NA - 984, - // 983 NA - // 982 NA - 981, - 980, - // 979 NA - 978, - 977, - // 976 NA - 975, - 974, - 973, - 972, - // 971 NA - // 970 NA - // 969 NA - // 968 NA - // 967 NA - // 966 NA - // 965 NA - // 964 NA - 963, - // 962 NA - 961, - // 960 NA - // 959 NA - 958, - 957, - // 956 NA - 955, - // 954 NA - 953, - 952, - 951, - 950, - 949, - // 948 NA - // 947 NA - 946, - 945, - 944, - // 943 NA - 942, - 941, - // 940 NA - 939, - // 938 NA - 937, - 936, - // 935 NA - // 934 NA - 933, - 932, - // 931 NA - // 930 NA - 929, - // 928 NA - // 927 NA - 926, - 925, - // 924 NA - // 923 NA - 922, - // 921 NA - // 920 NA - // 919 NA - // 918 NA - // 917 NA - 916, - 915, - // 914 NA - // 913 NA - 912, - // 911 NA - // 910 NA - // 909 NA - // 908 NA - // 907 NA - // 906 NA - // 905 NA - // 904 NA - 903, - // 902 NA - 901, - // 900 NA - // 899 NA - 898, - // 897 NA - 896, - 895, - // 894 NA - 893, - // 892 NA - 891, - // 890 NA - 889, - 888, - 887, - // 886 NA - 885, - // 884 NA - 883, - 882, - 881, - // 880 NA - 879, - 878, - 877, - // 876 NA - // 875 NA - // 874 NA - // 873 NA - // 872 NA - 871, - 870, - // 869 NA - 868, - // 867 NA - // 866 NA - // 865 NA - // 864 NA - // 863 NA - // 862 NA - // 861 NA - // 860 NA - 859, - 858, - 857, - 856, - // 855 NA - // 854 NA - 853, - // 852 NA - // 851 NA - // 850 NA - 849, - 848, - 847, - // 846 NA - 845, - 844, - 843, - // 842 NA - // 841 NA - // 840 NA - // 839 NA - // 838 NA - // 837 NA - 836, - 835, - 834, - 833, - 832, - 831, - 830, - // 829 NA - 828, - // 827 NA - 826, - 825, - // 824 NA - 823, - 822, - // 821 NA - 820, - 819, - 818, - 817, - 816, - 815, - 814, - 813, - // 812 NA - 811, - 810, - 809, - // 808 NA - 807, - 806, - 805, - // 804 NA - 803, - 802, - 801, - 800, - 799, - 798, - // 797 NA - // 796 NA - 795, - // 794 NA - 793, - 792, - 791, - 790, - 789, - // 788 NA - 787, - 786, - 785, - 784, - // 783 NA - 782, - 781, - 780, - 779, - 778, - // 777 NA - 776, - 775, - 774, - 773, - // 772 NA - 771, - // 770 NA - 769, - 768, - // 767 NA - // 766 NA - 765, - 764, - // 763 NA - // 762 NA - // 761 NA - 760, - // 759 NA - 758, - // 757 NA - // 756 NA - 755, - 754, - 753, - // 752 NA - // 751 NA - // 750 NA - 749, - 748, - 747, - 746, - 745, - // 744 NA - 743, - 742, - 741, - 740, - 739, - // 738 NA - 737, - 736, - // 735 NA - 734, - // 733 NA - 732, - // 731 NA - // 730 NA - 729, - // 728 NA - // 727 NA - // 726 NA - // 725 NA - // 724 NA - 723, - 722, - 721, - // 720 NA - 719, - 718, - 717, - 716, - 715, - 714, - 713, - 712, - 711, +static const int included_patches[] = { + // 875, + // 874, + // 873, + // 872, + // 871, + // 870, + // 869, + // 868, + // 867, + // 866, + // 865, + // 864, + // 863, + // 862, + // 861, + // 860, + // 859, + // 858, + // 857, + // 856, + // 855, + // 854, + // 853, + // 852, + // 851, + // 850, + // 849, + // 848, + // 847, + // 846, + // 845, + // 844, + // 843, + // 842, + // 841, + // 840, + // 839, + // 838, + // 837, + // 836, + // 835, + // 834, + // 833, + // 832, + // 831, + // 830, + // 829, + // 828, + // 827, + // 826, + // 825, + // 824, + // 823, + // 822, + // 821, + // 820, + // 819, + // 818, + // 817, + // 816, + // 815, + // 814, + // 813, + // 812, + // 811, + // 810, + // 809, + // 808, + // 807, + // 806, + // 805, + // 804, + // 803, + // 802, + // 801, + // 800, + // 799, + // 798, + // 797, + // 796, + // 795, + // 794, + // 793, + // 792, + // 791, + // 790, + // 789, + // 788, + // 787, + // 786, + // 785, + // 784, + // 783, + // 782, + // 781, + // 780, + // 779, + // 778, + // 777, + // 776, + // 775, + // 774, + // 773, + // 772, + // 771, + // 770, + // 769, + // 768, + // 767, + // 766, + // 765, + // 764, + // 763, + // 762, + // 761, + // 760, + // 759, + // 758, + // 757, + // 756, + // 755, + // 754, + // 753, + // 752, + // 751, + // 750, + // 749, + // 748, + // 747, + // 746, + // 745, + // 744, + // 743, + // 742, + // 741, + // 740, + // 739, + // 738, + // 737, + // 736, + // 735, + // 734, + // 733, + // 732, + // 731, + // 730, + // 729, + // 728, + // 727, + // 726, + // 725, + // 724, + // 723, + // 722, + // 721, + // 720, + // 719, + // 718, + // 717, + // 716, + // 715, + // 714, + // 713, + // 712, + // 711, 710, - 709, - 708, - 707, - 706, - // 705 NA - 704, - // 703 NA - 702, - // 701 NA - 700, - 699, - 698, - 697, - 696, - 695, - 694, - 693, - // 692 NA - // 691 NA - 690, - 689, - 688, - // 687 NA - 686, - 685, - // 684 NA - // 683 NA - 682, - // 681 NA + // 709, + // 708, + // 707, + // 706, + // 705, + // 704, + // 703, + // 702, + // 701, + // 700, + // 699, + // 698, + // 697, + // 696, + // 695, + // 694, + // 693, + // 692, + // 691, + // 690, + // 689, + // 688, + // 687, + // 686, + // 685, + // 684, + // 683, + // 682, + // 681, 680, - // 679 NA - // 678 NA - // 677 NA - // 676 NA - 675, - // 674 NA - 673, - 672, - 671, - 670, - // 669 NA - 668, - 667, - // 666 NA - 665, - // 664 NA - // 663 NA - 662, - // 661 NA - 660, - 659, - 658, - // 657 NA - 656, - 655, - 654, - 653, - // 652 NA - 651, - // 650 NA - 649, - // 648 NA - // 647 NA - 646, - 645, - // 644 NA - 643, - 642, - // 641 NA - 640, - 639, - // 638 NA - 637, - 636, - 635, - 634, - 633, - // 632 NA - 631, - 630, - 629, - // 628 NA - // 627 NA - // 626 NA - // 625 NA - // 624 NA - 623, - // 622 NA - // 621 NA - // 620 NA - // 619 NA - // 618 NA - 617, - 616, - 615, + 679, + 678, + // 677, + // 676, + // 675, + // 674, + // 673, + // 672, + // 671, + // 670, + // 669, + // 668, + // 667, + // 666, + // 665, + // 664, + // 663, + // 662, + // 661, + // 660, + // 659, + // 658, + // 657, + // 656, + // 655, + // 654, + // 653, + 652, + // 651, + // 650, + // 649, + // 648, + // 647, + // 646, + // 645, + // 644, + // 643, + // 642, + // 641, + // 640, + // 639, + // 638, + // 637, + // 636, + // 635, + // 634, + // 633, + // 632, + // 631, + // 630, + // 629, + // 628, + // 627, + // 626, + // 625, + // 624, + // 623, + // 622, + // 621, + // 620, + // 619, + 618, + // 617, + // 616, + // 615, 614, - 613, + // 613, 612, - // 611 NA - // 610 NA - 609, - 608, - // 607 NA - 606, + // 611, + // 610, + // 609, + // 608, + 607, + // 606, 605, - 604, - 603, - 602, - 601, - 600, - 599, - 598, - 597, - // 596 NA - 595, - 594, - 593, - // 592 NA - // 591 NA - 590, - // 589 NA - 588, - 587, - // 586 NA - 585, - // 584 NA - // 583 NA - 582, - // 581 NA - 580, - 579, - 578, - 577, - 576, - 575, - 574, - 573, - 572, - // 571 NA - // 570 NA - 569, - 568, - 567, - 566, - 565, - // 564 NA - 563, - 562, + // 604, + // 603, + // 602, + // 601, + // 600, + // 599, + // 598, + // 597, + // 596, + // 595, + // 594, + // 593, + // 592, + // 591, + // 590, + // 589, + // 588, + // 587, + // 586, + // 585, + // 584, + // 583, + // 582, + // 581, + // 580, + // 579, + // 578, + // 577, + // 576, + // 575, + // 574, + // 573, + // 572, + 571, + // 570, + // 569, + // 568, + // 567, + // 566, + // 565, + // 564, + // 563, + // 562, 561, - // 560 NA - 559, - // 558 NA - // 557 NA - // 556 NA - // 555 NA + // 560, + // 559, + // 558, + // 557, + // 556, + 555, 554, 553, 552, - 551, + // 551, 550, - 549, - // 548 NA - 547, - 546, - 545, - // 544 NA - 543, - 542, - 541, - // 540 NA - 539, - 538, - 537, - 536, - 535, - // 534 NA - 533, - 532, - 531, - 530, - 529, - 528, - 527, - 526, - 525, + // 549, + // 548, + // 547, + // 546, + // 545, + // 544, + // 543, + // 542, + // 541, + // 540, + // 539, + // 538, + // 537, + // 536, + // 535, + // 534, + // 533, + // 532, + // 531, + // 530, + // 529, + // 528, + // 527, + // 526, + // 525, 524, - // 523 NA - // 522 NA - 521, - 520, - 519, + // 523, + // 522, + // 521, + // 520, + // 519, 518, - 517, - 516, - 515, - 514, - 513, - // 512 NA - // 511 NA - // 510 NA - // 509 NA - 508, - // 507 NA - // 506 NA - // 505 NA - // 504 NA - 503, + // 517, + // 516, + // 515, + // 514, + // 513, + // 512, + // 511, + // 510, + // 509, + // 508, + // 507, + // 506, + // 505, + // 504, + // 503, 502, - // 501 NA - 500, + // 501, + // 500, 499, - // 498 NA - 497, - // 496 NA - // 495 NA - 494, - 493, - 492, - 491, - 490, - 489, - 488, + 498, + // 497, + // 496, + // 495, + // 494, + // 493, + // 492, + // 491, + // 490, + // 489, + // 488, 487, 486, 485, - // 484 NA + // 484, 483, - // 482 NA - // 481 NA - // 480 NA - // 479 NA + 482, + // 481, + // 480, + // 479, 478, 477, - // 476 NA - // 475 NA - 474, - 473, - 472, - // 471 NA - 470, - // 469 NA - 468, - 467, - 466, - // 465 NA - // 464 NA - 463, - 462, - // 461 NA - // 460 NA - // 459 NA - 458, + // 476, + // 475, + // 474, + // 473, + // 472, + // 471, + // 470, + // 469, + // 468, + // 467, + // 466, + 465, + // 464, + // 463, + // 462, + 461, + // 460, + 459, + // 458, 457, - 456, - 455, - 454, - // 453 NA - 452, - // 451 NA - 450, - 449, - // 448 NA - 447, - 446, - 445, - 444, - // 443 NA - 442, - 441, - 440, - 439, - 438, + // 456, + // 455, + // 454, + 453, + // 452, + // 451, + // 450, + // 449, + // 448, + // 447, + // 446, + // 445, + // 444, + // 443, + // 442, + // 441, + // 440, + // 439, + // 438, 437, - 436, - 435, - 434, - 433, - // 432 NA - // 431 NA - // 430 NA - // 429 NA - // 428 NA - 427, - // 426 NA - 425, - // 424 NA - 423, - 422, - 421, - // 420 NA - 419, - 418, - 417, - 416, - 415, - 414, - // 413 NA - // 412 NA - 411, - 410, - // 409 NA + // 436, + // 435, + // 434, + // 433, + // 432, + // 431, + // 430, + // 429, + // 428, + // 427, + // 426, + // 425, + // 424, + // 423, + // 422, + // 421, + // 420, + // 419, + // 418, + // 417, + // 416, + // 415, + // 414, + // 413, + // 412, + // 411, + // 410, + // 409, 408, 407, - 406, - 405, - // 404 NA - // 403 NA - // 402 NA - // 401 NA + // 406, + // 405 NA + // 404, + // 403, + // 402, + // 401, // 400 NA - // 399 NA - // 398 NA - 397, - 396, - 395, - // 394 NA - // 393 NA - 392, - 391, + // 399, + // 398, + // 397, + // 396, + // 395, + 394, + 393, + // 392, + // 391, 390, - 389, + // 389, 388, - 387, - 386, - // 385 NA - // 384 NA - 383, - 382, - 381, - // 380 NA - 379, + // 387, + // 386, + // 385, + // 384, + // 383, + // 382, + // 381, + // 380, + // 379, 378, 377, 376, - 375, - 374, - 373, - 372, - 371, - 370, - 369, - 368, - 367, - // 366 NA - 365, - 364, - // 363 NA - 362, - 361, + // 375, + // 374, + // 373, + // 372, + // 371, + // 370, + // 369, + // 368, + // 367, + // 366, + // 365, + // 364, + // 363, + // 362, + // 361, 360, - 359, - 358, - 357, - // 356 NA - 355, - // 354 NA + // 359, + // 358, + // 357, + // 356, + // 355, + // 354, 353, - 352, - 351, - 350, - 349, - 348, + // 352, + // 351, + // 350, + // 349, + // 348, 347, - 346, + // 346, 345, - 344, + // 344, 343, - // 342 NA + // 342, 341, - // 340 NA - 339, - 338, - 337, - 336, - 335, - 334, - // 333 NA - // 332 NA + // 340, + // 339, + // 338, + // 337, + // 336, + // 335, + // 334, + // 333, + // 332, 331, - 330, - 329, - 328, - 327, - // 326 NA + // 330, + // 329, + // 328, + // 327, + 326, 325, - 324, - 323, - // 322 NA - // 321 NA - 320, - // 319 NA - 318, - 317, - // 316 NA - 315, - 314, - 313, - 312, + // 324, + // 323, + 322, + // 321, + // 320, + 319, + // 318, + // 317, + // 316, + // 315, + // 314, + // 313, + // 312, 311, - 310, - 309, + // 310, + // 309, 308, - // 307 NA - 306, - 305, - // 304 NA - 303, - 302, - 301, - // 300 NA - // 299 NA - 298, + 307, + // 306, + // 305, + // 304, + // 303, + // 302, + // 301, + // 300, + // 299, + // 298, 297, - 296, - 295, - 294, - 293, - 292, - 291, + // 296, + // 295, + // 294, + // 293, + // 292, + // 291, 290, - 289, - 288, - // 287 NA - 286, - 285, - 284, - // 283 NA - 282, - 281, + // 289, + // 288 NA + // 287, + // 286, + // 285 NA + // 284 NA + // 283, + // 282, + // 281 NA 280, - 279, - 278, - 277, - 276, + // 279 NA + // 278 NA + // 277 NA + // 276 NA 275, 274, // 273 NA - 272, + // 272 NA // 271 NA // 270 NA - 269, - 268, - 267, + // 269 NA + // 268 NA + // 267 NA 266, - 265, - 264, - // 263 NA - 262, - 261, - 260, - // 259 NA - // 258 NA + // 265, + // 264, + // 263, + // 262, + // 261, + // 260 NA + 259, + // 258, // 257 NA - 256, - // 255 NA - // 254 NA - 253, - // 252 NA - 251, - // 250 NA - 249, - 248, + // 256, + // 255, + // 254, + // 253, + // 252, + // 251, + 250, + // 249 NA + // 248, 247, // 246 NA - 245, - // 244 NA + // 245, + // 244, 243, - 242, - 241, - 240, - 239, - // 238 NA - 237, - 236, + // 242, + // 241 NA + // 240 NA + // 239 NA + // 238, + // 237, + // 236, 235, - 234, - 233, - 232, - 231, - 230, + // 234, + // 233, + // 232 NA + // 231, + // 230, 229, - // 228 NA - // 227 NA - 226, - // 225 NA - // 224 NA - // 223 NA - // 222 NA - 221, - 220, + // 228, + // 227, + // 226, + // 225, + // 224, + 223, + // 222, + // 221 NA + // 220, 219, - 218, + // 218, // 217 NA - // 216 NA - 215, - // 214 NA - 213, - // 212 NA - 211, - 210, + // 216, + // 215, + // 214, + // 213 NA + // 212, + // 211 NA + // 210, 209, - // 208 NA - 207, - // 206 NA + 208, + // 207, + // 206, 205, - 204, - 203, - // 202 NA - 201, - // 200 NA - 199, - // 198 NA - // 197 NA - // 196 NA - // 195 NA - // 194 NA - 193, - 192, - 191, - // 190 NA - // 189 NA - // 188 NA - 187, - 186, - // 185 NA - 184, - // 183 NA - // 182 NA - 181, - // 180 NA - // 179 NA + // 204, + // 203 NA + // 202, + // 201, + // 200, + // 199 NA + // 198, + // 197, + // 196, + 195, + // 194, + // 193 NA + // 192 NA + // 191 NA + 190, + // 189, + // 188, + // 187 NA + // 186, + // 185, + // 184, + // 183, + // 182, + // 181, + // 180, + 179, 178, - // 177 NA - // 176 NA - // 175 NA - // 174 NA - 173, + 177, + 176, + // 175, + 174, + // 173 NA 172, - 171, - 170, - 169, - // 168 NA + // 171, + // 170, + // 169, + 168, 167, - 166, + // 166, 165, - // 164 NA + // 164, // 163 NA // 162 NA // 161 NA - 160, + // 160, 159, 158, - 157, + // 157, 156, - 155, - 154, - 153, - 152, - 151, + // 155, + // 154, + // 153, + // 152 NA + // 151, 150, 149, - 148, + // 148, 147, 146, - 145, - 144, + // 145 NA + // 144 NA 143, - 142, - 141, - 140, - 139, - 138, + // 142, + // 141, + // 140, + // 139 NA + // 138 NA 137, 136, 135, 134, 133, - 132, - 131, - 130, - 129, + // 132, + // 131, + // 130 NA + // 129 NA 128, 127, 126, 125, 124, - 123, - 122, + // 123 NA + // 122 NA 121, - 120, + // 120 NA 119, - 118, - 117, + // 118, + // 117 NA 116, - 115, - 114, - 113, - 112, + // 115 NA + // 114 NA + // 113 NA + // 112, 111, 110, - 109, - 108, - 107, - 106, - 105, - 104, - 103, - 102, - 101, + // 109 NA + // 108 NA + // 107 NA + // 106, + // 105 NA + // 104, + // 103 NA + // 102, + // 101, 100, 99, - 98, - 97, - 96, - 95, - 94, - 93, + // 98 NA + // 97 NA + // 96, + // 95 NA + // 94 NA + // 93 NA 92, - 91, + // 91, 90, - 89, + // 89 NA 88, - 87, + // 87 NA 86, 85, 84, 83, - 82, + // 82 NA 81, - 80, + // 80 NA 79, 78, - 77, - 76, + // 77 NA + // 76 NA 75, - 74, + // 74, 73, - 72, - 71, - 70, + // 72 NA + // 71 NA + // 70 NA 69, 68, - 67, + // 67 NA 66, - 65, + // 65 NA 64, - 63, + // 63 NA 62, - 61, + // 61 NA 60, - 59, + // 59 NA 58, 57, 56, - 55, - 54, + // 55 NA + // 54 NA 53, 52, - 51, - 50, + // 51 NA + // 50 NA 49, - 48, + // 48 NA 47, 46, - 45, + // 45 NA 44, 43, 42, 41, 40, - 39, + // 39 NA 38, 37, - 36, + // 36 NA 35, 34, 33, 32, 31, - 30, - 29, - 28, - 27, + // 30 NA + // 29 NA + // 28 NA + // 27 NA 26, 25, - 24, + // 24 NA 23, - 22, - 21, + // 22 NA + // 21, 20, 19, - 18, + // 18, 17, - 16, - 15, - 14, - 13, + // 16 NA + // 15 NA + // 14 NA + // 13 NA 12, - 11, - 10, - 9, + // 11 NA + // 10 NA + // 9 NA 8, - 7, + // 7 NA 6, - 5, + // 5 NA 4, 3, 2, @@ -2460,10 +971,10 @@ static char *(extra_patches[]) = { /// @param version Version string like "1.3.42" /// /// @return true if Nvim is at or above the version. -bool has_nvim_version(char *version_str) - FUNC_ATTR_NONNULL_ALL +bool has_nvim_version(const char *const version_str) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { - char *p = version_str; + const char *p = version_str; int major = 0; int minor = 0; int patch = 0; @@ -2472,7 +983,7 @@ bool has_nvim_version(char *version_str) return false; } major = atoi(p); - p = strchr(p, '.'); // Find the next dot. + p = strchr(p, '.'); // Find the next dot. if (p) { p++; // Advance past the dot. @@ -2480,7 +991,7 @@ bool has_nvim_version(char *version_str) return false; } minor = atoi(p); - p = strchr(p, '.'); + p = strchr(p, '.'); if (p) { p++; if (!ascii_isdigit(*p)) { @@ -2572,19 +1083,13 @@ static void list_features(void) int idx = (i / ncol) + (i % ncol) * nrow; if (idx < nfeat) { int last_col = (i + 1) % ncol == 0; - msg_puts((char_u *)features[idx]); + msg_puts(features[idx]); if (last_col) { if (msg_col > 0) { msg_putchar('\n'); } } else { - while (msg_col % width) { - int old_msg_col = msg_col; - msg_putchar(' '); - if (old_msg_col == msg_col) { - break; // XXX: Avoid infinite loop. - } - } + msg_putchar(' '); } } else { if (msg_col > 0) { @@ -2592,7 +1097,7 @@ static void list_features(void) } } } - MSG_PUTS("For differences from Vim, see :help vim-differences\n\n"); + MSG_PUTS("See \":help feature-compile\"\n\n"); } void list_version(void) @@ -2633,7 +1138,7 @@ void list_version(void) } #endif // ifdef HAVE_PATHDEF - version_msg(_("\n\nOptional features included (+) or not (-): ")); + version_msg(_("\n\nFeatures: ")); list_features(); @@ -2705,7 +1210,6 @@ void intro_message(int colon) static char *(lines[]) = { N_(NVIM_VERSION_LONG), "", - N_("by Bram Moolenaar et al."), N_("Nvim is open source and freely distributable"), N_("https://neovim.io/community"), "", diff --git a/src/nvim/version.h b/src/nvim/version.h index 1de809e539..c10f6fa534 100644 --- a/src/nvim/version.h +++ b/src/nvim/version.h @@ -1,6 +1,8 @@ #ifndef NVIM_VERSION_H #define NVIM_VERSION_H +#include "nvim/ex_cmds_defs.h" + // defined in version.c extern char* Version; extern char* longVersion; @@ -8,14 +10,14 @@ extern char* longVersion; // // Vim version number, name, etc. Patchlevel is defined in version.c. // -#define VIM_VERSION_MAJOR 7 -#define VIM_VERSION_MINOR 4 +#define VIM_VERSION_MAJOR 8 +#define VIM_VERSION_MINOR 0 #define VIM_VERSION_100 (VIM_VERSION_MAJOR * 100 + VIM_VERSION_MINOR) // used for the runtime directory name -#define VIM_VERSION_NODOT "vim74" +#define VIM_VERSION_NODOT "vim80" // swap file compatibility (max. length is 6 chars) -#define VIM_VERSION_SHORT "7.4" +#define VIM_VERSION_SHORT "8.0" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "version.h.generated.h" diff --git a/src/nvim/vim.h b/src/nvim/vim.h index 8271abda8d..62ffc7433e 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -11,26 +11,22 @@ #define RUNTIME_DIRNAME "runtime" /* end */ -/* ============ the header file puzzle (ca. 50-100 pieces) ========= */ - -#ifdef HAVE_CONFIG_H /* GNU autoconf (or something else) was here */ -# include "auto/config.h" -# define HAVE_PATHDEF +#include "auto/config.h" +#define HAVE_PATHDEF /* * Check if configure correctly managed to find sizeof(int). If this failed, * it becomes zero. This is likely a problem of not being able to run the * test program. Other items from configure may also be wrong then! */ -# if (SIZEOF_INT == 0) -Error: configure did not run properly.Check auto/config.log. -# endif +#if (SIZEOF_INT == 0) +# error Configure did not run properly. #endif #include "nvim/os/os_defs.h" /* bring lots of system header files */ /// length of a buffer to store a number in ASCII (64 bits binary + NUL) -#define NUMBUFLEN 65 +enum { NUMBUFLEN = 65 }; // flags for vim_str2nr() #define STR2NR_BIN 1 @@ -46,27 +42,7 @@ Error: configure did not run properly.Check auto/config.log. #include "nvim/keymap.h" #include "nvim/macros.h" - - - -/* ================ end of the header file puzzle =============== */ - -#ifdef HAVE_WORKING_LIBINTL -# include <libintl.h> -# define _(x) gettext((char *)(x)) -// XXX do we actually need this? -# ifdef gettext_noop -# define N_(x) gettext_noop(x) -# else -# define N_(x) x -# endif -#else -# define _(x) ((char *)(x)) -# define N_(x) x -# define bindtextdomain(x, y) /* empty */ -# define bind_textdomain_codeset(x, y) /* empty */ -# define textdomain(x) /* empty */ -#endif +#include "nvim/gettext.h" /* special attribute addition: Put message in history */ #define MSG_HIST 0x1000 @@ -109,11 +85,14 @@ Error: configure did not run properly.Check auto/config.log. // all mode bits used for mapping #define MAP_ALL_MODES (0x3f | SELECTMODE | TERM_FOCUS) -/* directions */ -#define FORWARD 1 -#define BACKWARD (-1) -#define FORWARD_FILE 3 -#define BACKWARD_FILE (-3) +/// Directions. +typedef enum { + kDirectionNotSet = 0, + FORWARD = 1, + BACKWARD = (-1), + FORWARD_FILE = 3, + BACKWARD_FILE = (-3), +} Direction; /* return values for functions */ #if !(defined(OK) && (OK == 1)) @@ -184,6 +163,7 @@ enum { EXPAND_SYNTIME, EXPAND_USER_ADDR_TYPE, EXPAND_PACKADD, + EXPAND_MESSAGES, }; @@ -225,6 +205,8 @@ enum { #define DIALOG_MSG_SIZE 1000 /* buffer size for dialog_msg() */ +enum { FOLD_TEXT_LEN = 51 }; //!< buffer size for get_foldtext() + /* * Maximum length of key sequence to be mapped. * Must be able to hold an Amiga resize report. @@ -269,6 +251,7 @@ enum { #define STRCAT(d, s) strcat((char *)(d), (char *)(s)) #define STRNCAT(d, s, n) strncat((char *)(d), (char *)(s), (size_t)(n)) +#define STRLCAT(d, s, n) xstrlcat((char *)(d), (char *)(s), (size_t)(n)) # define vim_strpbrk(s, cs) (char_u *)strpbrk((char *)(s), (char *)(cs)) @@ -281,15 +264,22 @@ enum { #define SHOWCMD_COLS 10 /* columns needed by shown command */ #define STL_MAX_ITEM 80 /* max nr of %<flag> in statusline */ -/* - * fnamecmp() is used to compare file names. - * On some systems case in a file name does not matter, on others it does. - * (this does not account for maximum name lengths and things like "../dir", - * thus it is not 100% accurate!) - */ -#define fnamecmp(x, y) vim_fnamecmp((char_u *)(x), (char_u *)(y)) -#define fnamencmp(x, y, n) vim_fnamencmp((char_u *)(x), (char_u *)(y), \ - (size_t)(n)) +/// Compare file names +/// +/// On some systems case in a file name does not matter, on others it does. +/// +/// @note Does not account for maximum name lengths and things like "../dir", +/// thus it is not 100% accurate. OS may also use different algorythm for +/// case-insensitive comparison. +/// +/// @param[in] x First file name to compare. +/// @param[in] y Second file name to compare. +/// +/// @return 0 for equal file names, non-zero otherwise. +#define fnamecmp(x, y) path_fnamecmp((const char *)(x), (const char *)(y)) +#define fnamencmp(x, y, n) path_fnamencmp((const char *)(x), \ + (const char *)(y), \ + (size_t)(n)) /* * Enums need a typecast to be used as array index (for Ultrix). @@ -324,8 +314,14 @@ enum { #define DIP_START 0x08 // also use "start" directory in 'packpath' #define DIP_OPT 0x10 // also use "opt" directory in 'packpath' #define DIP_NORTP 0x20 // do not use 'runtimepath' +#define DIP_NOAFTER 0x40 // skip "after" directories +#define DIP_AFTER 0x80 // only use "after" directories // Lowest number used for window ID. Cannot have this many windows per tab. #define LOWEST_WIN_ID 1000 +#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && defined(S_ISCHR) +# define OPEN_CHR_FILES +#endif + #endif /* NVIM_VIM_H */ diff --git a/src/nvim/window.c b/src/nvim/window.c index 00229ccca9..c2d0a9b3b1 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1,3 +1,6 @@ +// 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 <inttypes.h> #include <stdbool.h> @@ -45,6 +48,7 @@ #include "nvim/syntax.h" #include "nvim/terminal.h" #include "nvim/undo.h" +#include "nvim/ui.h" #include "nvim/os/os.h" @@ -129,9 +133,10 @@ newwindow: vim_snprintf(cbuf, sizeof(cbuf) - 5, "%" PRId64, (int64_t)Prenum); else cbuf[0] = NUL; - if (nchar == 'v' || nchar == Ctrl_V) - strcat(cbuf, "v"); - strcat(cbuf, "new"); + if (nchar == 'v' || nchar == Ctrl_V) { + xstrlcat(cbuf, "v", sizeof(cbuf)); + } + xstrlcat(cbuf, "new", sizeof(cbuf)); do_cmdline_cmd(cbuf); break; @@ -160,13 +165,18 @@ newwindow: /* cursor to preview window */ case 'P': - for (wp = firstwin; wp != NULL; wp = wp->w_next) - if (wp->w_p_pvw) + wp = NULL; + FOR_ALL_WINDOWS_IN_TAB(wp2, curtab) { + if (wp2->w_p_pvw) { + wp = wp2; break; - if (wp == NULL) + } + } + if (wp == NULL) { EMSG(_("E441: There is no preview window")); - else + } else { win_goto(wp); + } break; /* close all but current window */ @@ -183,7 +193,7 @@ newwindow: /* cursor to previous window with wrap around */ case 'W': CHECK_CMDWIN - if (firstwin == lastwin && Prenum != 1) /* just one window */ + if (ONE_WINDOW && Prenum != 1) /* just one window */ beep_flush(); else { if (Prenum) { /* go to specified window */ @@ -441,13 +451,12 @@ wingotofile: case 'g': case Ctrl_G: CHECK_CMDWIN - ++ no_mapping; - ++allow_keys; /* no mapping for xchar, but allow key codes */ - if (xchar == NUL) + no_mapping++; + if (xchar == NUL) { xchar = plain_vgetc(); - LANGMAP_ADJUST(xchar, TRUE); - --no_mapping; - --allow_keys; + } + LANGMAP_ADJUST(xchar, true); + no_mapping--; (void)add_to_showcmd(xchar); switch (xchar) { case '}': @@ -565,7 +574,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) oldwin = curwin; /* add a status line when p_ls == 1 and splitting the first window */ - if (lastwin == firstwin && p_ls == 1 && oldwin->w_status_height == 0) { + if (ONE_WINDOW && p_ls == 1 && oldwin->w_status_height == 0) { if (oldwin->w_height <= p_wmh && new_wp == NULL) { EMSG(_(e_noroom)); return FAIL; @@ -973,11 +982,12 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) /* * make the new window the current window */ - win_enter(wp, false); - if (flags & WSP_VERT) + win_enter_ext(wp, false, false, true, true, true); + if (flags & WSP_VERT) { p_wiw = i; - else + } else { p_wh = i; + } return OK; } @@ -1033,7 +1043,7 @@ static void win_init(win_T *newp, win_T *oldp, int flags) win_init_some(newp, oldp); - check_colorcolumn(newp); + didset_window_options(newp); } /* @@ -1172,7 +1182,7 @@ static void win_exchange(long Prenum) win_T *wp2; int temp; - if (lastwin == firstwin) { /* just one window */ + if (ONE_WINDOW) { /* just one window */ beep_flush(); return; } @@ -1261,7 +1271,7 @@ static void win_rotate(int upwards, int count) frame_T *frp; int n; - if (firstwin == lastwin) { /* nothing to do */ + if (ONE_WINDOW) { /* nothing to do */ beep_flush(); return; } @@ -1333,7 +1343,7 @@ static void win_totop(int size, int flags) int dir; int height = curwin->w_height; - if (lastwin == firstwin) { + if (ONE_WINDOW) { beep_flush(); return; } @@ -1707,25 +1717,24 @@ static void win_equal_rec( } } -/* - * close all windows for buffer 'buf' - */ -void -close_windows ( - buf_T *buf, - int keep_curwin /* don't close "curwin" */ -) +/// Closes all windows for buffer `buf`. +/// +/// @param keep_curwin don't close `curwin` +void close_windows(buf_T *buf, int keep_curwin) { tabpage_T *tp, *nexttp; int h = tabline_height(); + int count = tabpage_index(NULL); ++RedrawingDisabled; - for (win_T *wp = firstwin; wp != NULL && lastwin != firstwin; ) { + for (win_T *wp = firstwin; wp != NULL && !ONE_WINDOW; ) { if (wp->w_buffer == buf && (!keep_curwin || wp != curwin) - && !(wp->w_closing || wp->w_buffer->b_closing) - ) { - win_close(wp, FALSE); + && !(wp->w_closing || wp->w_buffer->b_locked > 0)) { + if (win_close(wp, false) == FAIL) { + // If closing the window fails give up, to avoid looping forever. + break; + } /* Start all over, autocommands may change the window layout. */ wp = firstwin; @@ -1739,9 +1748,8 @@ close_windows ( if (tp != curtab) { FOR_ALL_WINDOWS_IN_TAB(wp, tp) { if (wp->w_buffer == buf - && !(wp->w_closing || wp->w_buffer->b_closing) - ) { - win_close_othertab(wp, FALSE, tp); + && !(wp->w_closing || wp->w_buffer->b_locked > 0)) { + win_close_othertab(wp, false, tp); /* Start all over, the tab page may be closed and * autocommands may change the window layout. */ @@ -1754,9 +1762,14 @@ close_windows ( --RedrawingDisabled; - redraw_tabline = TRUE; - if (h != tabline_height()) + if (count != tabpage_index(NULL)) { + apply_autocmds(EVENT_TABCLOSED, NULL, NULL, false, curbuf); + } + + redraw_tabline = true; + if (h != tabline_height()) { shell_new_rows(); + } } /// Check that current window is the last one. @@ -1797,7 +1810,7 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev_curtab) FUNC_ATTR_NONNULL_ARG(1) { - if (firstwin != lastwin) { + if (!ONE_WINDOW) { return false; } buf_T *old_curbuf = curbuf; @@ -1865,14 +1878,17 @@ int win_close(win_T *win, int free_buf) int dir; int help_window = FALSE; tabpage_T *prev_curtab = curtab; + frame_T *win_frame = win->w_frame->fr_parent; if (last_window()) { EMSG(_("E444: Cannot close last window")); return FAIL; } - if (win->w_closing || (win->w_buffer != NULL && win->w_buffer->b_closing)) - return FAIL; /* window is already being closed */ + if (win->w_closing + || (win->w_buffer != NULL && win->w_buffer->b_locked > 0)) { + return FAIL; // window is already being closed + } if (win == aucmd_win) { EMSG(_("E813: Cannot close autocmd window")); return FAIL; @@ -1937,6 +1953,8 @@ int win_close(win_T *win, int free_buf) * Close the link to the buffer. */ if (win->w_buffer != NULL) { + bufref_T bufref; + set_bufref(&bufref, curbuf); win->w_closing = true; close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, true); if (win_valid_any_tab(win)) { @@ -1945,7 +1963,7 @@ int win_close(win_T *win, int free_buf) // Make sure curbuf is valid. It can become invalid if 'bufhidden' is // "wipe". - if (!buf_valid(curbuf)) { + if (!bufref_valid(&bufref)) { curbuf = firstbuf; } } @@ -2004,20 +2022,25 @@ int win_close(win_T *win, int free_buf) } curbuf = curwin->w_buffer; close_curwin = TRUE; + + // The cursor position may be invalid if the buffer changed after last + // using the window. + check_cursor(); } - if (p_ea - && (*p_ead == 'b' || *p_ead == dir) - ) { - win_equal(curwin, true, dir); + if (p_ea && (*p_ead == 'b' || *p_ead == dir)) { + // If the frame of the closed window contains the new current window, + // only resize that frame. Otherwise resize all windows. + win_equal(curwin, curwin->w_frame->fr_parent == win_frame, dir); } else { win_comp_pos(); } if (close_curwin) { - win_enter_ext(wp, false, TRUE, TRUE, TRUE); - if (other_buffer) - /* careful: after this wp and win may be invalid! */ - apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf); + win_enter_ext(wp, false, true, false, true, true); + if (other_buffer) { + // careful: after this wp and win may be invalid! + apply_autocmds(EVENT_BUFENTER, NULL, NULL, false, curbuf); + } } /* @@ -2050,7 +2073,8 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp) // Get here with win->w_buffer == NULL when win_close() detects the tab page // changed. - if (win->w_closing || (win->w_buffer != NULL && win->w_buffer->b_closing)) { + if (win->w_closing + || (win->w_buffer != NULL && win->w_buffer->b_locked > 0)) { return; // window is already being closed } @@ -2173,7 +2197,7 @@ winframe_remove ( /* * If there is only one window there is nothing to remove. */ - if (tp == NULL ? firstwin == lastwin : tp->tp_firstwin == tp->tp_lastwin) + if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin) return NULL; /* @@ -2310,7 +2334,7 @@ win_altframe ( frame_T *frp; int b; - if (tp == NULL ? firstwin == lastwin : tp->tp_firstwin == tp->tp_lastwin) + if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin) /* Last window in this tab page, will go to next tab page. */ return alt_tabpage()->tp_curwin->w_frame; @@ -2830,7 +2854,7 @@ close_others ( win_close(wp, !P_HID(wp->w_buffer) && !bufIsChanged(wp->w_buffer)); } - if (message && lastwin != firstwin) + if (message && !ONE_WINDOW) EMSG(_("E445: Other window contains changes")); } @@ -2966,8 +2990,8 @@ static tabpage_T *alloc_tabpage(void) tp->handle = ++last_tp_handle; handle_register_tabpage(tp); - /* init t: variables */ - tp->tp_vars = dict_alloc(); + // Init t: variables. + tp->tp_vars = tv_dict_alloc(); init_var_dict(tp->tp_vars, &tp->tp_winvar, VAR_SCOPE); tp->tp_diff_invalid = TRUE; tp->tp_ch_used = p_ch; @@ -2987,8 +3011,7 @@ void free_tabpage(tabpage_T *tp) hash_init(&tp->tp_vars->dv_hashtab); unref_var_dict(tp->tp_vars); - - xfree(tp->localdir); // Free tab-local working directory + xfree(tp->tp_localdir); xfree(tp); } @@ -3014,7 +3037,7 @@ int win_new_tabpage(int after, char_u *filename) return FAIL; } - newtp->localdir = tp->localdir ? vim_strsave(tp->localdir) : NULL; + newtp->tp_localdir = tp->tp_localdir ? vim_strsave(tp->tp_localdir) : NULL; curtab = newtp; @@ -3045,8 +3068,9 @@ int win_new_tabpage(int after, char_u *filename) redraw_all_later(CLEAR); - apply_autocmds(EVENT_TABNEW, filename, filename, false, curbuf); + apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf); apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf); + apply_autocmds(EVENT_TABNEW, filename, filename, false, curbuf); apply_autocmds(EVENT_TABENTER, NULL, NULL, false, curbuf); return OK; @@ -3118,6 +3142,45 @@ bool valid_tabpage(tabpage_T *tpc) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT return false; } +/// Returns true when `tpc` is valid and at least one window is valid. +int valid_tabpage_win(tabpage_T *tpc) +{ + FOR_ALL_TABS(tp) { + if (tp == tpc) { + FOR_ALL_WINDOWS_IN_TAB(wp, tp) { + if (win_valid_any_tab(wp)) { + return true; + } + } + return false; + } + } + // shouldn't happen + return false; +} + +/// Close tabpage `tab`, assuming it has no windows in it. +/// There must be another tabpage or this will crash. +void close_tabpage(tabpage_T *tab) +{ + tabpage_T *ptp; + + if (tab == first_tabpage) { + first_tabpage = tab->tp_next; + ptp = first_tabpage; + } else { + for (ptp = first_tabpage; ptp != NULL && ptp->tp_next != tab; + ptp = ptp->tp_next) { + // do nothing + } + assert(ptp != NULL); + ptp->tp_next = tab->tp_next; + } + + goto_tabpage_tp(ptp, false, false); + free_tabpage(tab); +} + /* * Find tab page "n" (first one is 1). Returns NULL when not found. */ @@ -3204,8 +3267,8 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, int trigger_enter_au /* We would like doing the TabEnter event first, but we don't have a * valid current window yet, which may break some commands. * This triggers autocommands, thus may make "tp" invalid. */ - win_enter_ext(tp->tp_curwin, false, TRUE, - trigger_enter_autocmds, trigger_leave_autocmds); + win_enter_ext(tp->tp_curwin, false, true, false, + trigger_enter_autocmds, trigger_leave_autocmds); prevwin = next_prevwin; last_status(FALSE); /* status line may appear or disappear */ @@ -3350,15 +3413,20 @@ void tabpage_move(int nr) tp_dst = tp; - /* Remove the current tab page from the list of tab pages. */ - if (curtab == first_tabpage) + // Remove the current tab page from the list of tab pages. + if (curtab == first_tabpage) { first_tabpage = curtab->tp_next; - else { - for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) - if (tp->tp_next == curtab) + } else { + tp = NULL; + FOR_ALL_TABS(tp2) { + if (tp2->tp_next == curtab) { + tp = tp2; break; - if (tp == NULL) /* "cannot happen" */ + } + } + if (tp == NULL) { // "cannot happen" return; + } tp->tp_next = curtab->tp_next; } @@ -3546,7 +3614,7 @@ end: */ void win_enter(win_T *wp, bool undo_sync) { - win_enter_ext(wp, undo_sync, FALSE, TRUE, TRUE); + win_enter_ext(wp, undo_sync, false, false, true, true); } /* @@ -3554,7 +3622,9 @@ void win_enter(win_T *wp, bool undo_sync) * Can be called with "curwin_invalid" TRUE, which means that curwin has just * been closed and isn't valid. */ -static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid, int trigger_enter_autocmds, int trigger_leave_autocmds) +static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid, + int trigger_new_autocmds, int trigger_enter_autocmds, + int trigger_leave_autocmds) { int other_buffer = FALSE; @@ -3603,33 +3673,46 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid, int tri curwin->w_cursor.coladd = 0; changed_line_abv_curs(); /* assume cursor position needs updating */ - // The new directory is either the local directory of the window, of the tab - // or NULL. - char_u *new_dir = curwin->w_localdir ? curwin->w_localdir : curtab->localdir; + // New directory is either the local directory of the window, tab or NULL. + char *new_dir = (char *)(curwin->w_localdir + ? curwin->w_localdir : curtab->tp_localdir); + + char cwd[MAXPATHL]; + if (os_dirname((char_u *)cwd, MAXPATHL) != OK) { + cwd[0] = NUL; + } if (new_dir) { // Window/tab has a local directory: Save current directory as global - // directory (unless that was done already) and change to the local - // directory. + // (unless that was done already) and change to the local directory. if (globaldir == NULL) { - char_u cwd[MAXPATHL]; - - if (os_dirname(cwd, MAXPATHL) == OK) { - globaldir = vim_strsave(cwd); + if (cwd[0] != NUL) { + globaldir = (char_u *)xstrdup(cwd); } } - if (os_chdir((char *)new_dir) == 0) { + if (os_chdir(new_dir) == 0) { + if (!p_acd && !strequal(new_dir, cwd)) { + do_autocmd_dirchanged(new_dir, curwin->w_localdir + ? kCdScopeWindow : kCdScopeTab); + } shorten_fnames(true); } } else if (globaldir != NULL) { - /* Window doesn't have a local directory and we are not in the global - * directory: Change to the global directory. */ - ignored = os_chdir((char *)globaldir); + // Window doesn't have a local directory and we are not in the global + // directory: Change to the global directory. + if (os_chdir((char *)globaldir) == 0) { + if (!p_acd && !strequal((char *)globaldir, cwd)) { + do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal); + } + } xfree(globaldir); globaldir = NULL; shorten_fnames(TRUE); } + if (trigger_new_autocmds) { + apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf); + } if (trigger_enter_autocmds) { apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf); if (other_buffer) @@ -3642,6 +3725,12 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid, int tri if (restart_edit) redraw_later(VALID); /* causes status line redraw */ + if (hl_attr(HLF_INACTIVE) + || (prevwin && prevwin->w_hl_ids[HLF_INACTIVE]) + || curwin->w_hl_ids[HLF_INACTIVE]) { + redraw_all_later(NOT_VALID); + } + /* set window height to desired minimal value */ if (curwin->w_height < p_wh && !curwin->w_p_wfh) win_setheight((int)p_wh); @@ -3735,8 +3824,8 @@ static win_T *win_alloc(win_T *after, int hidden) new_wp->handle = ++last_win_id; handle_register_window(new_wp); - /* init w: variables */ - new_wp->w_vars = dict_alloc(); + // Init w: variables. + new_wp->w_vars = tv_dict_alloc(); init_var_dict(new_wp->w_vars, &new_wp->w_winvar, VAR_SCOPE); /* Don't execute autocommands while the window is not properly @@ -4700,8 +4789,6 @@ void set_fraction(win_T *wp) */ void win_new_height(win_T *wp, int height) { - linenr_T lnum; - int sline, line_size; int prev_height = wp->w_height; /* Don't want a negative height. Happens when splitting a tiny window. @@ -4728,6 +4815,19 @@ void win_new_height(win_T *wp, int height) wp->w_height = height; wp->w_skipcol = 0; + // There is no point in adjusting the scroll position when exiting. Some + // values might be invalid. + if (!exiting) { + scroll_to_fraction(wp, prev_height); + } +} + +void scroll_to_fraction(win_T *wp, int prev_height) +{ + linenr_T lnum; + int sline, line_size; + int height = wp->w_height; + /* Don't change w_topline when height is zero. Don't set w_topline when * 'scrollbind' is set and this isn't the current window. */ if (height > 0 @@ -4824,7 +4924,7 @@ void win_new_height(win_T *wp, int height) if (wp->w_buffer->terminal) { terminal_resize(wp->w_buffer->terminal, 0, wp->w_height); - redraw_win_later(wp, CLEAR); + redraw_win_later(wp, NOT_VALID); } } @@ -4848,7 +4948,6 @@ void win_new_width(win_T *wp, int width) if (wp->w_height != 0) { terminal_resize(wp->w_buffer->terminal, wp->w_width, 0); } - redraw_win_later(wp, CLEAR); } } @@ -5077,7 +5176,7 @@ last_status ( { /* Don't make a difference between horizontal or vertical split. */ last_status_rec(topframe, (p_ls == 2 - || (p_ls == 1 && (morewin || lastwin != firstwin)))); + || (p_ls == 1 && (morewin || !ONE_WINDOW)))); } static void last_status_rec(frame_T *fr, int statusline) @@ -5134,6 +5233,9 @@ static void last_status_rec(frame_T *fr, int statusline) */ int tabline_height(void) { + if (ui_is_external(kUITabline)) { + return 0; + } assert(first_tabpage); switch (p_stal) { case 0: return 0; @@ -5283,10 +5385,8 @@ restore_snapshot ( clear_snapshot(curtab, idx); } -/* - * Check if frames "sn" and "fr" have the same layout, same following frames - * and same children. - */ +/// Check if frames "sn" and "fr" have the same layout, same following frames +/// and same children. And the window pointer is valid. static int check_snapshot_rec(frame_T *sn, frame_T *fr) { if (sn->fr_layout != fr->fr_layout @@ -5295,7 +5395,8 @@ static int check_snapshot_rec(frame_T *sn, frame_T *fr) || (sn->fr_next != NULL && check_snapshot_rec(sn->fr_next, fr->fr_next) == FAIL) || (sn->fr_child != NULL - && check_snapshot_rec(sn->fr_child, fr->fr_child) == FAIL)) + && check_snapshot_rec(sn->fr_child, fr->fr_child) == FAIL) + || (sn->fr_win != NULL && !win_valid(sn->fr_win))) return FAIL; return OK; } @@ -5386,44 +5487,45 @@ void restore_win(win_T *save_curwin, tabpage_T *save_curtab, int no_display) unblock_autocmds(); } -/* - * Make "buf" the current buffer. restore_buffer() MUST be called to undo. - * No autocommands will be executed. Use aucmd_prepbuf() if there are any. - */ -void switch_buffer(buf_T **save_curbuf, buf_T *buf) +/// Make "buf" the current buffer. +/// +/// restore_buffer() MUST be called to undo. +/// No autocommands will be executed. Use aucmd_prepbuf() if there are any. +void switch_buffer(bufref_T *save_curbuf, buf_T *buf) { block_autocmds(); - *save_curbuf = curbuf; - --curbuf->b_nwindows; + set_bufref(save_curbuf, curbuf); + curbuf->b_nwindows--; curbuf = buf; curwin->w_buffer = buf; - ++curbuf->b_nwindows; + curbuf->b_nwindows++; } -/* - * Restore the current buffer after using switch_buffer(). - */ -void restore_buffer(buf_T *save_curbuf) +/// Restore the current buffer after using switch_buffer(). +void restore_buffer(bufref_T *save_curbuf) { unblock_autocmds(); - /* Check for valid buffer, just in case. */ - if (buf_valid(save_curbuf)) { - --curbuf->b_nwindows; - curwin->w_buffer = save_curbuf; - curbuf = save_curbuf; - ++curbuf->b_nwindows; + // Check for valid buffer, just in case. + if (bufref_valid(save_curbuf)) { + curbuf->b_nwindows--; + curwin->w_buffer = save_curbuf->br_buf; + curbuf = save_curbuf->br_buf; + curbuf->b_nwindows++; } } -// Add match to the match list of window 'wp'. The pattern 'pat' will be -// highlighted with the group 'grp' with priority 'prio'. -// Optionally, a desired ID 'id' can be specified (greater than or equal to 1). -// If no particular ID is desired, -1 must be specified for 'id'. -// Return ID of added match, -1 on failure. -int match_add(win_T *wp, char_u *grp, char_u *pat, +/// Add match to the match list of window 'wp'. The pattern 'pat' will be +/// highlighted with the group 'grp' with priority 'prio'. +/// Optionally, a desired ID 'id' can be specified (greater than or equal to 1). +/// +/// @param[in] id a desired ID 'id' can be specified +/// (greater than or equal to 1). -1 must be specified if no +/// particular ID is desired +/// @return ID of added match, -1 on failure. +int match_add(win_T *wp, const char *const grp, const char *const pat, int prio, int id, list_T *pos_list, - char_u *conceal_char) + const char *const conceal_char) { matchitem_T *cur; matchitem_T *prev; @@ -5436,8 +5538,8 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, return -1; } if (id < -1 || id == 0) { - EMSGN("E799: Invalid ID: %" PRId64 - " (must be greater than or equal to 1)", + EMSGN(_("E799: Invalid ID: %" PRId64 + " (must be greater than or equal to 1)"), id); return -1; } @@ -5445,17 +5547,17 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, cur = wp->w_match_head; while (cur != NULL) { if (cur->id == id) { - EMSGN("E801: ID already taken: %" PRId64, id); + EMSGN(_("E801: ID already taken: %" PRId64), id); return -1; } cur = cur->next; } } - if ((hlg_id = syn_namen2id(grp, (int)STRLEN(grp))) == 0) { + if ((hlg_id = syn_name2id((const char_u *)grp)) == 0) { EMSG2(_(e_nogroup), grp); return -1; } - if (pat != NULL && (regprog = vim_regcomp(pat, RE_MAGIC)) == NULL) { + if (pat != NULL && (regprog = vim_regcomp((char_u *)pat, RE_MAGIC)) == NULL) { EMSG2(_(e_invarg2), pat); return -1; } @@ -5474,14 +5576,14 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, m = xcalloc(1, sizeof(matchitem_T)); m->id = id; m->priority = prio; - m->pattern = pat == NULL ? NULL: vim_strsave(pat); + m->pattern = pat == NULL ? NULL: (char_u *)xstrdup(pat); m->hlg_id = hlg_id; m->match.regprog = regprog; m->match.rmm_ic = FALSE; m->match.rmm_maxcol = 0; m->conceal_char = 0; if (conceal_char != NULL) { - m->conceal_char = (*mb_ptr2char)(conceal_char); + m->conceal_char = (*mb_ptr2char)((const char_u *)conceal_char); } // Set up position matches @@ -5499,7 +5601,7 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, int len = 1; list_T *subl; listitem_T *subli; - int error = false; + bool error = false; if (li->li_tv.v_type == VAR_LIST) { subl = li->li_tv.vval.v_list; @@ -5510,8 +5612,8 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, if (subli == NULL) { goto fail; } - lnum = get_tv_number_chk(&subli->li_tv, &error); - if (error == true) { + lnum = tv_get_number_chk(&subli->li_tv, &error); + if (error) { goto fail; } if (lnum == 0) { @@ -5521,13 +5623,14 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, m->pos.pos[i].lnum = lnum; subli = subli->li_next; if (subli != NULL) { - col = get_tv_number_chk(&subli->li_tv, &error); - if (error == true) + col = tv_get_number_chk(&subli->li_tv, &error); + if (error) { goto fail; + } subli = subli->li_next; if (subli != NULL) { - len = get_tv_number_chk(&subli->li_tv, &error); - if (error == true) { + len = tv_get_number_chk(&subli->li_tv, &error); + if (error) { goto fail; } } @@ -5597,10 +5700,9 @@ fail: return -1; } -/* - * Delete match with ID 'id' in the match list of window 'wp'. - * Print error messages if 'perr' is TRUE. - */ + +/// Delete match with ID 'id' in the match list of window 'wp'. +/// Print error messages if 'perr' is TRUE. int match_delete(win_T *wp, int id, int perr) { matchitem_T *cur = wp->w_match_head; @@ -5608,10 +5710,11 @@ int match_delete(win_T *wp, int id, int perr) int rtype = SOME_VALID; if (id < 1) { - if (perr == TRUE) - EMSGN("E802: Invalid ID: %" PRId64 - " (must be greater than or equal to 1)", + if (perr) { + EMSGN(_("E802: Invalid ID: %" PRId64 + " (must be greater than or equal to 1)"), id); + } return -1; } while (cur != NULL && cur->id != id) { @@ -5619,8 +5722,9 @@ int match_delete(win_T *wp, int id, int perr) cur = cur->next; } if (cur == NULL) { - if (perr == TRUE) - EMSGN("E803: ID not found: %" PRId64, id); + if (perr) { + EMSGN(_("E803: ID not found: %" PRId64), id); + } return -1; } if (cur == prev) @@ -5726,23 +5830,28 @@ int win_getid(typval_T *argvars) if (argvars[0].v_type == VAR_UNKNOWN) { return curwin->handle; } - int winnr = get_tv_number(&argvars[0]); + int winnr = tv_get_number(&argvars[0]); win_T *wp; if (winnr > 0) { if (argvars[1].v_type == VAR_UNKNOWN) { wp = firstwin; } else { - tabpage_T *tp; - int tabnr = get_tv_number(&argvars[1]); - for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) { + tabpage_T *tp = NULL; + int tabnr = tv_get_number(&argvars[1]); + FOR_ALL_TABS(tp2) { if (--tabnr == 0) { + tp = tp2; break; } } if (tp == NULL) { return -1; } - wp = tp->tp_firstwin; + if (tp == curtab) { + wp = firstwin; + } else { + wp = tp->tp_firstwin; + } } for ( ; wp != NULL; wp = wp->w_next) { if (--winnr == 0) { @@ -5755,7 +5864,7 @@ int win_getid(typval_T *argvars) int win_gotoid(typval_T *argvars) { - int id = get_tv_number(&argvars[0]); + int id = tv_get_number(&argvars[0]); FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->handle == id) { @@ -5790,16 +5899,16 @@ void win_id2tabwin(typval_T *argvars, list_T *list) { int winnr = 1; int tabnr = 1; - int id = get_tv_number(&argvars[0]); + handle_T id = (handle_T)tv_get_number(&argvars[0]); win_get_tabwin(id, &tabnr, &winnr); - list_append_number(list, tabnr); - list_append_number(list, winnr); + tv_list_append_number(list, tabnr); + tv_list_append_number(list, winnr); } win_T * win_id2wp(typval_T *argvars) { - int id = get_tv_number(&argvars[0]); + int id = tv_get_number(&argvars[0]); FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->handle == id) { @@ -5812,11 +5921,10 @@ win_T * win_id2wp(typval_T *argvars) int win_id2win(typval_T *argvars) { - win_T *wp; int nr = 1; - int id = get_tv_number(&argvars[0]); + int id = tv_get_number(&argvars[0]); - for (wp = firstwin; wp != NULL; wp = wp->w_next) { + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { if (wp->handle == id) { return nr; } @@ -5827,14 +5935,11 @@ int win_id2win(typval_T *argvars) void win_findbuf(typval_T *argvars, list_T *list) { - int bufnr = get_tv_number(&argvars[0]); + int bufnr = tv_get_number(&argvars[0]); - for (tabpage_T *tp = first_tabpage; tp != NULL; tp = tp->tp_next) { - for (win_T *wp = tp == curtab ? firstwin : tp->tp_firstwin; - wp != NULL; wp = wp->w_next) { - if (wp->w_buffer->b_fnum == bufnr) { - list_append_number(list, wp->handle); - } + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (wp->w_buffer->b_fnum == bufnr) { + tv_list_append_number(list, wp->handle); } } } diff --git a/src/nvim/window.h b/src/nvim/window.h index 2ac4c00c28..82b3fe5e88 100644 --- a/src/nvim/window.h +++ b/src/nvim/window.h @@ -3,6 +3,8 @@ #include <stdbool.h> +#include "nvim/buffer_defs.h" + /* Values for file_name_in_line() */ #define FNAME_MESS 1 /* give error message */ #define FNAME_EXP 2 /* expand to path */ |