diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval.c | 9 | ||||
-rw-r--r-- | src/nvim/event/libuv_process.c | 6 | ||||
-rw-r--r-- | src/nvim/event/process.c | 6 | ||||
-rw-r--r-- | src/nvim/event/process.h | 1 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 7 | ||||
-rw-r--r-- | src/nvim/fileio.c | 120 | ||||
-rw-r--r-- | src/nvim/globals.h | 10 | ||||
-rw-r--r-- | src/nvim/iconv.h | 46 | ||||
-rw-r--r-- | src/nvim/lua/executor.c | 65 | ||||
-rw-r--r-- | src/nvim/main.c | 3 | ||||
-rw-r--r-- | src/nvim/mbyte.c | 198 | ||||
-rw-r--r-- | src/nvim/mbyte.h | 2 | ||||
-rw-r--r-- | src/nvim/os/pty_process_unix.c | 2 | ||||
-rw-r--r-- | src/nvim/os/pty_process_win.c | 2 | ||||
-rw-r--r-- | src/nvim/search.c | 1 | ||||
-rw-r--r-- | src/nvim/spell.c | 6 | ||||
-rw-r--r-- | src/nvim/terminal.c | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_spell.vim | 54 | ||||
-rw-r--r-- | src/nvim/version.c | 6 |
19 files changed, 251 insertions, 295 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index fabd26ce47..31a49faaf3 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -11260,7 +11260,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) "fork", #endif "gettext", -#if defined(HAVE_ICONV_H) && defined(USE_ICONV) +#if defined(HAVE_ICONV) "iconv", #endif "insert_expand", @@ -11373,10 +11373,6 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) n = stdout_isatty; } else if (STRICMP(name, "multi_byte_encoding") == 0) { n = has_mbyte != 0; -#if defined(USE_ICONV) && defined(DYNAMIC_ICONV) - } else if (STRICMP(name, "iconv") == 0) { - n = iconv_enabled(false); -#endif } else if (STRICMP(name, "syntax_items") == 0) { n = syntax_present(curwin); #ifdef UNIX @@ -12359,7 +12355,6 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - Channel *data = find_job(argvars[0].vval.v_number, true); if (!data) { return; @@ -16764,6 +16759,8 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr) break; } str += len; + capcol -= len; + len = 0; } } } diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c index ffe2db9b76..63efee59a8 100644 --- a/src/nvim/event/libuv_process.c +++ b/src/nvim/event/libuv_process.c @@ -101,6 +101,10 @@ static void close_cb(uv_handle_t *handle) static void exit_cb(uv_process_t *handle, int64_t status, int term_signal) { Process *proc = handle->data; - proc->status = (int)status; +#if defined(WIN32) + // Use stored/expected signal. + term_signal = proc->exit_signal; +#endif + proc->status = term_signal ? 128 + term_signal : (int)status; proc->internal_exit_cb(proc); } diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index 4410deadef..c31ecdaddf 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -159,7 +159,7 @@ void process_close_streams(Process *proc) FUNC_ATTR_NONNULL_ALL /// 0 for no wait. -1 to wait until the process quits. /// @return Exit code of the process. proc->status will have the same value. /// -1 if the timeout expired while the process is still running. -/// -2 if the user interruped the wait. +/// -2 if the user interrupted the wait. int process_wait(Process *proc, int ms, MultiQueue *events) FUNC_ATTR_NONNULL_ARG(1) { @@ -220,6 +220,7 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL return; } proc->stopped_time = os_hrtime(); + proc->exit_signal = SIGTERM; switch (proc->type) { case kProcessTypeUv: @@ -253,8 +254,10 @@ static void children_kill_cb(uv_timer_t *handle) } uint64_t term_sent = UINT64_MAX == proc->stopped_time; if (kProcessTypePty != proc->type || term_sent) { + proc->exit_signal = SIGKILL; os_proc_tree_kill(proc->pid, SIGKILL); } else { + proc->exit_signal = SIGTERM; os_proc_tree_kill(proc->pid, SIGTERM); proc->stopped_time = UINT64_MAX; // Flag: SIGTERM was sent. // Restart timer. @@ -403,4 +406,3 @@ static void on_process_stream_close(Stream *stream, void *data) Process *proc = data; decref(proc); } - diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h index 13dc3839ce..ef9d953ab7 100644 --- a/src/nvim/event/process.h +++ b/src/nvim/event/process.h @@ -19,6 +19,7 @@ struct process { Loop *loop; void *data; int pid, status, refcount; + uint8_t exit_signal; // Signal used when killing (on Windows). uint64_t stopped_time; // process_stop() timestamp const char *cwd; char **argv; diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 85952a6cbf..0f345df22b 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -4061,10 +4061,9 @@ static char_u *replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep) return p; } -/* - * Expand file name in Ex command argument. - * Return FAIL for failure, OK otherwise. - */ +// Expand file name in Ex command argument. +// When an error is detected, "errormsgp" is set to a non-NULL pointer. +// Return FAIL for failure, OK otherwise. int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp) { int has_wildcards; /* need to expand wildcards */ diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 9531c13356..d2620376c6 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -164,22 +164,22 @@ typedef struct AutoPatCmd { * Structure to pass arguments from buf_write() to buf_write_bytes(). */ struct bw_info { - int bw_fd; /* file descriptor */ - char_u *bw_buf; /* buffer with data to be written */ - int bw_len; /* length of data */ + int bw_fd; // file descriptor + char_u *bw_buf; // buffer with data to be written + int bw_len; // length of data #ifdef HAS_BW_FLAGS - int bw_flags; /* FIO_ flags */ + int bw_flags; // FIO_ flags #endif - char_u bw_rest[CONV_RESTLEN]; /* not converted bytes */ - int bw_restlen; /* nr of bytes in bw_rest[] */ - int bw_first; /* first write call */ - char_u *bw_conv_buf; /* buffer for writing converted chars */ - int bw_conv_buflen; /* size of bw_conv_buf */ - int bw_conv_error; /* set for conversion error */ - linenr_T bw_conv_error_lnum; /* first line with error or zero */ - linenr_T bw_start_lnum; /* line number at start of buffer */ -# ifdef USE_ICONV - iconv_t bw_iconv_fd; /* descriptor for iconv() or -1 */ + char_u bw_rest[CONV_RESTLEN]; // not converted bytes + int bw_restlen; // nr of bytes in bw_rest[] + int bw_first; // first write call + char_u *bw_conv_buf; // buffer for writing converted chars + int bw_conv_buflen; // size of bw_conv_buf + int bw_conv_error; // set for conversion error + linenr_T bw_conv_error_lnum; // first line with error or zero + linenr_T bw_start_lnum; // line number at start of buffer +# ifdef HAVE_ICONV + iconv_t bw_iconv_fd; // descriptor for iconv() or -1 # endif }; @@ -328,10 +328,10 @@ readfile( char_u *fenc_next = NULL; // next item in 'fencs' or NULL bool advance_fenc = false; long real_size = 0; -# ifdef USE_ICONV - iconv_t iconv_fd = (iconv_t)-1; /* descriptor for iconv() or -1 */ - int did_iconv = FALSE; /* TRUE when iconv() failed and trying - 'charconvert' next */ +# ifdef HAVE_ICONV + iconv_t iconv_fd = (iconv_t)-1; // descriptor for iconv() or -1 + int did_iconv = false; // TRUE when iconv() failed and trying + // 'charconvert' next # endif int converted = FALSE; /* TRUE if conversion done */ int notconverted = FALSE; /* TRUE if conversion wanted but it @@ -842,7 +842,7 @@ retry: fileformat = EOL_UNKNOWN; /* detect from file */ } -# ifdef USE_ICONV +# ifdef HAVE_ICONV if (iconv_fd != (iconv_t)-1) { /* aborted conversion with iconv(), close the descriptor */ iconv_close(iconv_fd); @@ -909,15 +909,14 @@ retry: -# ifdef USE_ICONV - /* - * Try using iconv() if we can't convert internally. - */ +# ifdef HAVE_ICONV + // Try using iconv() if we can't convert internally. if (fio_flags == 0 && !did_iconv - ) + ) { iconv_fd = (iconv_t)my_iconv_open( enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc); + } # endif /* @@ -926,12 +925,12 @@ retry: */ if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL && !read_fifo -# ifdef USE_ICONV +# ifdef HAVE_ICONV && iconv_fd == (iconv_t)-1 # endif ) { -# ifdef USE_ICONV - did_iconv = FALSE; +# ifdef HAVE_ICONV + did_iconv = false; # endif /* Skip conversion when it's already done (retry for wrong * "fileformat"). */ @@ -951,7 +950,7 @@ retry: } } else { if (fio_flags == 0 -# ifdef USE_ICONV +# ifdef HAVE_ICONV && iconv_fd == (iconv_t)-1 # endif ) { @@ -1024,20 +1023,23 @@ retry: * ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be * multiple of 4 */ real_size = (int)size; -# ifdef USE_ICONV - if (iconv_fd != (iconv_t)-1) +# ifdef HAVE_ICONV + if (iconv_fd != (iconv_t)-1) { size = size / ICONV_MULT; - else + } else { # endif - if (fio_flags & FIO_LATIN1) + if (fio_flags & FIO_LATIN1) { size = size / 2; - else if (fio_flags & (FIO_UCS2 | FIO_UTF16)) + } else if (fio_flags & (FIO_UCS2 | FIO_UTF16)) { size = (size * 2 / 3) & ~1; - else if (fio_flags & FIO_UCS4) + } else if (fio_flags & FIO_UCS4) { size = (size * 2 / 3) & ~3; - else if (fio_flags == FIO_UCSBOM) - size = size / ICONV_MULT; /* worst case */ - + } else if (fio_flags == FIO_UCSBOM) { + size = size / ICONV_MULT; // worst case + } +# ifdef HAVE_ICONV + } +# endif if (conv_restlen > 0) { // Insert unconverted bytes from previous line. memmove(ptr, conv_rest, conv_restlen); // -V614 @@ -1113,7 +1115,7 @@ retry: /* When we did a conversion report an error. */ if (fio_flags != 0 -# ifdef USE_ICONV +# ifdef HAVE_ICONV || iconv_fd != (iconv_t)-1 # endif ) { @@ -1136,7 +1138,7 @@ retry: * leave the UTF8 checking code to do it, as it * works slightly differently. */ if (bad_char_behavior != BAD_KEEP && (fio_flags != 0 -# ifdef USE_ICONV +# ifdef HAVE_ICONV || iconv_fd != (iconv_t)-1 # endif )) { @@ -1145,8 +1147,8 @@ retry: --conv_restlen; } } - fio_flags = 0; /* don't convert this */ -# ifdef USE_ICONV + fio_flags = 0; // don't convert this +# ifdef HAVE_ICONV if (iconv_fd != (iconv_t)-1) { iconv_close(iconv_fd); iconv_fd = (iconv_t)-1; @@ -1217,7 +1219,7 @@ retry: if (size <= 0) break; -# ifdef USE_ICONV +# ifdef HAVE_ICONV if (iconv_fd != (iconv_t)-1) { /* * Attempt conversion of the read bytes to 'encoding' using @@ -1475,10 +1477,11 @@ retry: * file is more likely than a conversion error. */ if (can_retry && !incomplete_tail) break; -# ifdef USE_ICONV - /* When we did a conversion report an error. */ - if (iconv_fd != (iconv_t)-1 && conv_error == 0) +# ifdef HAVE_ICONV + // When we did a conversion report an error. + if (iconv_fd != (iconv_t)-1 && conv_error == 0) { conv_error = readfile_linenr(linecnt, ptr, p); + } # endif /* Remember the first linenr with an illegal byte */ if (conv_error == 0 && illegal_byte == 0) @@ -1498,15 +1501,18 @@ retry: if (p < ptr + size && !incomplete_tail) { /* Detected a UTF-8 error. */ rewind_retry: - /* Retry reading with another conversion. */ -# ifdef USE_ICONV - if (*p_ccv != NUL && iconv_fd != (iconv_t)-1) - /* iconv() failed, try 'charconvert' */ - did_iconv = TRUE; - else + // Retry reading with another conversion. +# ifdef HAVE_ICONV + if (*p_ccv != NUL && iconv_fd != (iconv_t)-1) { + // iconv() failed, try 'charconvert' + did_iconv = true; + } else { # endif // use next item from 'fileencodings' advance_fenc = true; +# ifdef HAVE_ICONV + } +# endif file_rewind = true; goto retry; } @@ -1711,7 +1717,7 @@ failed: } if (fenc_alloced) xfree(fenc); -# ifdef USE_ICONV +# ifdef HAVE_ICONV if (iconv_fd != (iconv_t)-1) { iconv_close(iconv_fd); # ifndef __clang_analyzer__ @@ -2295,7 +2301,7 @@ buf_write( write_info.bw_conv_error = FALSE; write_info.bw_conv_error_lnum = 0; write_info.bw_restlen = 0; -# ifdef USE_ICONV +# ifdef HAVE_ICONV write_info.bw_iconv_fd = (iconv_t)-1; # endif @@ -3016,7 +3022,7 @@ nobackup: if (converted && wb_flags == 0) { -# ifdef USE_ICONV +# ifdef HAVE_ICONV // Use iconv() conversion when conversion is needed and it's not done // internally. write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc, @@ -3046,7 +3052,7 @@ nobackup: } } if (converted && wb_flags == 0 -# ifdef USE_ICONV +# ifdef HAVE_ICONV && write_info.bw_iconv_fd == (iconv_t)-1 # endif && wfname == fname @@ -3574,7 +3580,7 @@ nofail: xfree(buffer); xfree(fenc_tofree); xfree(write_info.bw_conv_buf); -# ifdef USE_ICONV +# ifdef HAVE_ICONV if (write_info.bw_iconv_fd != (iconv_t)-1) { iconv_close(write_info.bw_iconv_fd); write_info.bw_iconv_fd = (iconv_t)-1; @@ -3949,7 +3955,7 @@ static int buf_write_bytes(struct bw_info *ip) } } -# ifdef USE_ICONV +# ifdef HAVE_ICONV if (ip->bw_iconv_fd != (iconv_t)-1) { const char *from; size_t fromlen; diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 4524c4b2c0..b095e759d9 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -655,16 +655,6 @@ EXTERN int inhibit_delete_count INIT(= 0); /// Encoding used when 'fencs' is set to "default" EXTERN char_u *fenc_default INIT(= NULL); -# if defined(USE_ICONV) && defined(DYNAMIC_ICONV) -/* Pointers to functions and variables to be loaded at runtime */ -EXTERN size_t (*iconv)(iconv_t cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft); -EXTERN iconv_t (*iconv_open)(const char *tocode, const char *fromcode); -EXTERN int (*iconv_close)(iconv_t cd); -EXTERN int (*iconvctl)(iconv_t cd, int request, void *argument); -EXTERN int* (*iconv_errno)(void); -# endif - /// "State" is the main state of Vim. /// There are other variables that modify the state: /// Visual_mode: When State is NORMAL or INSERT. diff --git a/src/nvim/iconv.h b/src/nvim/iconv.h index d7234090c4..a7c9ad4040 100644 --- a/src/nvim/iconv.h +++ b/src/nvim/iconv.h @@ -1,52 +1,20 @@ #ifndef NVIM_ICONV_H #define NVIM_ICONV_H -// iconv can be linked at compile-time as well as loaded at runtime. In the -// latter case, some function pointers need to be initialized after loading -// the library (see `iconv_enabled()` in mbyte.c). These function pointers -// are stored in globals.h. Since globals.h includes iconv.h to get the -// definition of USE_ICONV, we can't include it from iconv.h. One way to -// solve this conundrum would be perhaps to let cmake decide the value of -// 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. - #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. -#if (defined(HAVE_ICONV_H) && defined(HAVE_ICONV)) || defined(DYNAMIC_ICONV) -# define USE_ICONV -#endif - -// If we don't have the actual iconv header files present but USE_ICONV was -// defined, we provide a type shim (pull in errno.h and define iconv_t). -// This enables us to still load and use iconv dynamically at runtime. -#ifdef USE_ICONV +#ifdef HAVE_ICONV # include <errno.h> -# ifdef HAVE_ICONV_H -# include <iconv.h> -# else -typedef void *iconv_t; -# endif -#endif +# include <iconv.h> // define some missing constants if necessary -# ifdef USE_ICONV # ifndef EILSEQ # define EILSEQ 123 # endif -# ifdef DYNAMIC_ICONV -// on win32 iconv.dll is dynamically loaded -# define ICONV_ERRNO (*iconv_errno()) -# define ICONV_E2BIG 7 -# define ICONV_EINVAL 22 -# define ICONV_EILSEQ 42 -# else -# define ICONV_ERRNO errno -# define ICONV_E2BIG E2BIG -# define ICONV_EINVAL EINVAL -# define ICONV_EILSEQ EILSEQ -# endif -# endif +# define ICONV_ERRNO errno +# define ICONV_E2BIG E2BIG +# define ICONV_EINVAL EINVAL +# define ICONV_EILSEQ EILSEQ +#endif #endif // NVIM_ICONV_H diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 6f1d7996a5..3de1b531e6 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -113,6 +113,65 @@ static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL return 1; } +/// convert byte index to UTF-32 and UTF-16 indicies +/// +/// Expects a string and an optional index. If no index is supplied, the length +/// of the string is returned. +/// +/// Returns two values: the UTF-32 and UTF-16 indicies. +static int nlua_str_utfindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + size_t s1_len; + const char *s1 = luaL_checklstring(lstate, 1, &s1_len); + intptr_t idx; + if (lua_gettop(lstate) >= 2) { + idx = luaL_checkinteger(lstate, 2); + if (idx < 0 || idx > (intptr_t)s1_len) { + return luaL_error(lstate, "index out of range"); + } + } else { + idx = (intptr_t)s1_len; + } + + size_t codepoints = 0, codeunits = 0; + mb_utflen((const char_u *)s1, (size_t)idx, &codepoints, &codeunits); + + lua_pushinteger(lstate, (long)codepoints); + lua_pushinteger(lstate, (long)codeunits); + + return 2; +} + +/// convert UTF-32 or UTF-16 indicies to byte index. +/// +/// Expects up to three args: string, index and use_utf16. +/// If use_utf16 is not supplied it defaults to false (use UTF-32) +/// +/// Returns the byte index. +static int nlua_str_byteindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + size_t s1_len; + const char *s1 = luaL_checklstring(lstate, 1, &s1_len); + intptr_t idx = luaL_checkinteger(lstate, 2); + if (idx < 0) { + return luaL_error(lstate, "index out of range"); + } + bool use_utf16 = false; + if (lua_gettop(lstate) >= 3) { + use_utf16 = lua_toboolean(lstate, 3); + } + + ssize_t byteidx = mb_utf_index_to_bytes((const char_u *)s1, s1_len, + (size_t)idx, use_utf16); + if (byteidx == -1) { + return luaL_error(lstate, "index out of range"); + } + + lua_pushinteger(lstate, (long)byteidx); + + return 1; +} + static void nlua_luv_error_event(void **argv) { char *error = (char *)argv[0]; @@ -221,6 +280,12 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL // stricmp lua_pushcfunction(lstate, &nlua_stricmp); lua_setfield(lstate, -2, "stricmp"); + // str_utfindex + lua_pushcfunction(lstate, &nlua_str_utfindex); + lua_setfield(lstate, -2, "str_utfindex"); + // str_byteindex + lua_pushcfunction(lstate, &nlua_str_byteindex); + lua_setfield(lstate, -2, "str_byteindex"); // schedule lua_pushcfunction(lstate, &nlua_schedule); lua_setfield(lstate, -2, "schedule"); diff --git a/src/nvim/main.c b/src/nvim/main.c index 9c342e62c0..6bb3c37b92 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -664,9 +664,6 @@ void getout(int exitval) ui_call_set_title(cstr_as_string((char *)p_titleold)); } -#if defined(USE_ICONV) && defined(DYNAMIC_ICONV) - iconv_end(); -#endif cs_end(); if (garbage_collect_at_exit) { garbage_collect(false); diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index bf8ce46113..fae7635d34 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -1470,6 +1470,31 @@ void mb_utflen(const char_u *s, size_t len, size_t *codepoints, *codeunits += count + extra; } +ssize_t mb_utf_index_to_bytes(const char_u *s, size_t len, + size_t index, bool use_utf16_units) + FUNC_ATTR_NONNULL_ALL +{ + size_t count = 0; + size_t clen, i; + if (index == 0) { + return 0; + } + for (i = 0; i < len && s[i] != NUL; i += clen) { + clen = utf_ptr2len_len(s+i, len-i); + // NB: gets the byte value of invalid sequence bytes. + // we only care whether the char fits in the BMP or not + int c = (clen > 1) ? utf_ptr2char(s+i) : s[i]; + count++; + if (use_utf16_units && c > 0xFFFF) { + count++; + } + if (count >= index) { + return i+clen; + } + } + return -1; +} + /* * Version of strnicmp() that handles multi-byte characters. @@ -2037,7 +2062,7 @@ enc_locale_copy_enc: return enc_canonize((char_u *)buf); } -# if defined(USE_ICONV) +# if defined(HAVE_ICONV) /* @@ -2058,13 +2083,6 @@ void * my_iconv_open(char_u *to, char_u *from) if (iconv_working == kBroken) return (void *)-1; /* detected a broken iconv() previously */ -#ifdef DYNAMIC_ICONV - // Check if the iconv.dll can be found. - if (!iconv_enabled(true)) { - return (void *)-1; - } -#endif - fd = iconv_open((char *)enc_skip(to), (char *)enc_skip(from)); if (fd != (iconv_t)-1 && iconv_working == kUnknown) { @@ -2171,152 +2189,7 @@ static char_u *iconv_string(const vimconv_T *const vcp, char_u *str, return result; } -# if defined(DYNAMIC_ICONV) -// Dynamically load the "iconv.dll" on Win32. - -#ifndef DYNAMIC_ICONV // just generating prototypes -# define HINSTANCE int -#endif -static HINSTANCE hIconvDLL = 0; -static HINSTANCE hMsvcrtDLL = 0; - -# ifndef DYNAMIC_ICONV_DLL -# define DYNAMIC_ICONV_DLL "iconv.dll" -# define DYNAMIC_ICONV_DLL_ALT "libiconv-2.dll" -# endif -# ifndef DYNAMIC_MSVCRT_DLL -# define DYNAMIC_MSVCRT_DLL "msvcrt.dll" -# endif - -/* - * Get the address of 'funcname' which is imported by 'hInst' DLL. - */ -static void * get_iconv_import_func(HINSTANCE hInst, - const char *funcname) -{ - PBYTE pImage = (PBYTE)hInst; - PIMAGE_DOS_HEADER pDOS = (PIMAGE_DOS_HEADER)hInst; - PIMAGE_NT_HEADERS pPE; - PIMAGE_IMPORT_DESCRIPTOR pImpDesc; - PIMAGE_THUNK_DATA pIAT; /* Import Address Table */ - PIMAGE_THUNK_DATA pINT; /* Import Name Table */ - PIMAGE_IMPORT_BY_NAME pImpName; - - if (pDOS->e_magic != IMAGE_DOS_SIGNATURE) - return NULL; - pPE = (PIMAGE_NT_HEADERS)(pImage + pDOS->e_lfanew); - if (pPE->Signature != IMAGE_NT_SIGNATURE) - return NULL; - pImpDesc = (PIMAGE_IMPORT_DESCRIPTOR)(pImage - + pPE->OptionalHeader.DataDirectory[ - IMAGE_DIRECTORY_ENTRY_IMPORT] - .VirtualAddress); - for (; pImpDesc->FirstThunk; ++pImpDesc) { - if (!pImpDesc->OriginalFirstThunk) - continue; - pIAT = (PIMAGE_THUNK_DATA)(pImage + pImpDesc->FirstThunk); - pINT = (PIMAGE_THUNK_DATA)(pImage + pImpDesc->OriginalFirstThunk); - for (; pIAT->u1.Function; ++pIAT, ++pINT) { - if (IMAGE_SNAP_BY_ORDINAL(pINT->u1.Ordinal)) - continue; - pImpName = (PIMAGE_IMPORT_BY_NAME)(pImage - + (UINT_PTR)(pINT->u1.AddressOfData)); - if (strcmp(pImpName->Name, funcname) == 0) - return (void *)pIAT->u1.Function; - } - } - return NULL; -} - -// Load library "name". -HINSTANCE vimLoadLib(char *name) -{ - HINSTANCE dll = NULL; - - // NOTE: Do not use mch_dirname() and mch_chdir() here, they may call - // vimLoadLib() recursively, which causes a stack overflow. - wchar_t old_dirw[MAXPATHL]; - - // Path to exe dir. - char *buf = xstrdup((char *)get_vim_var_str(VV_PROGPATH)); - // ptrdiff_t len = ; - // assert(len > 0); - buf[path_tail_with_sep(buf) - buf] = '\0'; - - if (GetCurrentDirectoryW(MAXPATHL, old_dirw) != 0) { - // Change directory to where the executable is, both to make - // sure we find a .dll there and to avoid looking for a .dll - // in the current directory. - SetCurrentDirectory((LPCSTR)buf); - // TODO(justinmk): use uv_dlopen instead. see os_libcall - dll = LoadLibrary(name); - SetCurrentDirectoryW(old_dirw); - } - - return dll; -} - - -/* - * Try opening the iconv.dll and return TRUE if iconv() can be used. - */ -bool iconv_enabled(bool verbose) -{ - if (hIconvDLL != 0 && hMsvcrtDLL != 0) - return true; - hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL); - if (hIconvDLL == 0) /* sometimes it's called libiconv.dll */ - hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL_ALT); - if (hIconvDLL != 0) - hMsvcrtDLL = vimLoadLib(DYNAMIC_MSVCRT_DLL); - if (hIconvDLL == 0 || hMsvcrtDLL == 0) { - /* Only give the message when 'verbose' is set, otherwise it might be - * done whenever a conversion is attempted. */ - if (verbose && p_verbose > 0) { - verbose_enter(); - EMSG2(_(e_loadlib), - hIconvDLL == 0 ? DYNAMIC_ICONV_DLL : DYNAMIC_MSVCRT_DLL); - verbose_leave(); - } - iconv_end(); - return false; - } - - iconv = (void *)GetProcAddress(hIconvDLL, "libiconv"); - iconv_open = (void *)GetProcAddress(hIconvDLL, "libiconv_open"); - iconv_close = (void *)GetProcAddress(hIconvDLL, "libiconv_close"); - iconvctl = (void *)GetProcAddress(hIconvDLL, "libiconvctl"); - iconv_errno = get_iconv_import_func(hIconvDLL, "_errno"); - if (iconv_errno == NULL) - iconv_errno = (void *)GetProcAddress(hMsvcrtDLL, "_errno"); - if (iconv == NULL || iconv_open == NULL || iconv_close == NULL - || iconvctl == NULL || iconv_errno == NULL) { - iconv_end(); - if (verbose && p_verbose > 0) { - verbose_enter(); - EMSG2(_(e_loadfunc), "for libiconv"); - verbose_leave(); - } - return false; - } - return true; -} - -void iconv_end(void) -{ - if (hIconvDLL != 0) { - // TODO(justinmk): use uv_dlclose instead. - FreeLibrary(hIconvDLL); - } - if (hMsvcrtDLL != 0) { - FreeLibrary(hMsvcrtDLL); - } - hIconvDLL = 0; - hMsvcrtDLL = 0; -} - -# endif /* DYNAMIC_ICONV */ -# endif /* USE_ICONV */ +# endif // HAVE_ICONV @@ -2347,10 +2220,11 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8, int from_is_utf8; int to_is_utf8; - /* Reset to no conversion. */ -# ifdef USE_ICONV - if (vcp->vc_type == CONV_ICONV && vcp->vc_fd != (iconv_t)-1) + // Reset to no conversion. +# ifdef HAVE_ICONV + if (vcp->vc_type == CONV_ICONV && vcp->vc_fd != (iconv_t)-1) { iconv_close(vcp->vc_fd); + } # endif *vcp = (vimconv_T)MBYTE_NONE_CONV; @@ -2385,9 +2259,9 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8, /* Internal utf-8 -> latin9 conversion. */ vcp->vc_type = CONV_TO_LATIN9; } -# ifdef USE_ICONV - else { - /* Use iconv() for conversion. */ +# ifdef HAVE_ICONV + else { // NOLINT(readability/braces) + // Use iconv() for conversion. vcp->vc_fd = (iconv_t)my_iconv_open( to_is_utf8 ? (char_u *)"utf-8" : to, from_is_utf8 ? (char_u *)"utf-8" : from); @@ -2539,8 +2413,8 @@ char_u * string_convert_ext(const vimconv_T *const vcp, char_u *ptr, *lenp = (size_t)(d - retval); break; -# ifdef USE_ICONV - case CONV_ICONV: /* conversion with vcp->vc_fd */ +# ifdef HAVE_ICONV + case CONV_ICONV: // conversion with vcp->vc_fd retval = iconv_string(vcp, ptr, len, unconvlenp, lenp); break; # endif diff --git a/src/nvim/mbyte.h b/src/nvim/mbyte.h index ed48705c6d..536d58be1f 100644 --- a/src/nvim/mbyte.h +++ b/src/nvim/mbyte.h @@ -63,7 +63,7 @@ typedef enum { typedef struct { int vc_type; ///< Zero or more ConvFlags. int vc_factor; ///< Maximal expansion factor. -# ifdef USE_ICONV +# ifdef HAVE_ICONV iconv_t vc_fd; ///< Value for CONV_ICONV. # endif bool vc_fail; ///< What to do with invalid characters: if true, fail, diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c index 5fdf0e6181..f0bc13783c 100644 --- a/src/nvim/os/pty_process_unix.c +++ b/src/nvim/os/pty_process_unix.c @@ -288,7 +288,7 @@ static void chld_handler(uv_signal_t *handle, int signum) if (WIFEXITED(stat)) { proc->status = WEXITSTATUS(stat); } else if (WIFSIGNALED(stat)) { - proc->status = WTERMSIG(stat); + proc->status = 128 + WTERMSIG(stat); } proc->internal_exit_cb(proc); } diff --git a/src/nvim/os/pty_process_win.c b/src/nvim/os/pty_process_win.c index c5f8efadff..290668bca3 100644 --- a/src/nvim/os/pty_process_win.c +++ b/src/nvim/os/pty_process_win.c @@ -252,7 +252,7 @@ static void pty_process_finish2(PtyProcess *ptyproc) DWORD exit_code = 0; GetExitCodeProcess(ptyproc->process_handle, &exit_code); - proc->status = (int)exit_code; + proc->status = proc->exit_signal ? 128 + proc->exit_signal : (int)exit_code; CloseHandle(ptyproc->process_handle); ptyproc->process_handle = NULL; diff --git a/src/nvim/search.c b/src/nvim/search.c index 7d46b3b4d5..fe4fdf57ba 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -4242,6 +4242,7 @@ static void search_stat(int dirc, pos_T *pos, // STRNICMP ignores case, but we should not ignore case. // Unfortunately, there is no STRNICMP function. if (!(chgtick == buf_get_changedtick(curbuf) + && lastpat != NULL // supress clang/NULL passed as nonnull parameter && STRNICMP(lastpat, spats[last_idx].pat, STRLEN(lastpat)) == 0 && STRLEN(lastpat) == STRLEN(spats[last_idx].pat) && equalpos(lastpos, curwin->w_cursor) diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 5bf315cdc3..8d800843f8 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -1808,9 +1808,11 @@ void count_common_word(slang_T *lp, char_u *word, int len, int count) char_u buf[MAXWLEN]; char_u *p; - if (len == -1) + if (len == -1) { p = word; - else { + } else if (len >= MAXWLEN) { + return; + } else { STRLCPY(buf, word, len + 1); p = buf; } diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index e503efe46e..5aeea3223b 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -1307,7 +1307,7 @@ static void refresh_screen(Terminal *term, buf_T *buf) static void adjust_topline(Terminal *term, buf_T *buf, long added) { - FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->w_buffer == buf) { linenr_T ml_end = buf->b_ml.ml_line_count; bool following = ml_end == wp->w_cursor.lnum + added; // cursor at end? diff --git a/src/nvim/testdir/test_spell.vim b/src/nvim/testdir/test_spell.vim index b3438cc649..230cb72335 100644 --- a/src/nvim/testdir/test_spell.vim +++ b/src/nvim/testdir/test_spell.vim @@ -1,4 +1,5 @@ " Test spell checking +" Note: this file uses latin1 encoding, but is used with utf-8 encoding. if !has('spell') finish @@ -68,6 +69,47 @@ func Test_z_equal_on_invalid_utf8_word() bwipe! endfunc +" Test spellbadword() with argument +func Test_spellbadword() + set spell + + call assert_equal(['bycycle', 'bad'], spellbadword('My bycycle.')) + call assert_equal(['another', 'caps'], spellbadword('A sentence. another sentence')) + + set spelllang=en + call assert_equal(['', ''], spellbadword('centre')) + call assert_equal(['', ''], spellbadword('center')) + set spelllang=en_us + call assert_equal(['centre', 'local'], spellbadword('centre')) + call assert_equal(['', ''], spellbadword('center')) + set spelllang=en_gb + call assert_equal(['', ''], spellbadword('centre')) + call assert_equal(['center', 'local'], spellbadword('center')) + + " Create a small word list to test that spellbadword('...') + " can return ['...', 'rare']. + e Xwords + insert +foo +foobar/? +. + w! + mkspell! Xwords.spl Xwords + set spelllang=Xwords.spl + call assert_equal(['foobar', 'rare'], spellbadword('foo foobar')) + + " Typo should not be detected without the 'spell' option. + set spelllang=en_gb nospell + call assert_equal(['', ''], spellbadword('centre')) + call assert_equal(['', ''], spellbadword('My bycycle.')) + call assert_equal(['', ''], spellbadword('A sentence. another sentence')) + + call delete('Xwords.spl') + call delete('Xwords') + set spelllang& + set spell& +endfunc + func Test_spellreall() new set spell @@ -351,6 +393,18 @@ func Test_zeq_crash() bwipe! endfunc +" Check handling a word longer than MAXWLEN. +func Test_spell_long_word() + set enc=utf-8 + new + call setline(1, "d\xCC\xB4\xCC\xBD\xCD\x88\xCD\x94a\xCC\xB5\xCD\x84\xCD\x84\xCC\xA8\xCD\x9Cr\xCC\xB5\xCC\x8E\xCD\x85\xCD\x85k\xCC\xB6\xCC\x89\xCC\x9D \xCC\xB6\xCC\x83\xCC\x8F\xCC\xA4\xCD\x8Ef\xCC\xB7\xCC\x81\xCC\x80\xCC\xA9\xCC\xB0\xCC\xAC\xCC\xA2\xCD\x95\xCD\x87\xCD\x8D\xCC\x9E\xCD\x99\xCC\xAD\xCC\xAB\xCC\x97\xCC\xBBo\xCC\xB6\xCC\x84\xCC\x95\xCC\x8C\xCC\x8B\xCD\x9B\xCD\x9C\xCC\xAFr\xCC\xB7\xCC\x94\xCD\x83\xCD\x97\xCC\x8C\xCC\x82\xCD\x82\xCD\x80\xCD\x91\xCC\x80\xCC\xBE\xCC\x82\xCC\x8F\xCC\xA3\xCD\x85\xCC\xAE\xCD\x8D\xCD\x99\xCC\xBC\xCC\xAB\xCC\xA7\xCD\x88c\xCC\xB7\xCD\x83\xCC\x84\xCD\x92\xCC\x86\xCC\x83\xCC\x88\xCC\x92\xCC\x94\xCC\xBE\xCC\x9D\xCC\xAF\xCC\x98\xCC\x9D\xCC\xBB\xCD\x8E\xCC\xBB\xCC\xB3\xCC\xA3\xCD\x8E\xCD\x99\xCC\xA5\xCC\xAD\xCC\x99\xCC\xB9\xCC\xAE\xCC\xA5\xCC\x9E\xCD\x88\xCC\xAE\xCC\x9E\xCC\xA9\xCC\x97\xCC\xBC\xCC\x99\xCC\xA5\xCD\x87\xCC\x97\xCD\x8E\xCD\x94\xCC\x99\xCC\x9D\xCC\x96\xCD\x94\xCC\xAB\xCC\xA7\xCC\xA5\xCC\x98\xCC\xBB\xCC\xAF\xCC\xABe\xCC\xB7\xCC\x8E\xCC\x82\xCD\x86\xCD\x9B\xCC\x94\xCD\x83\xCC\x85\xCD\x8A\xCD\x8C\xCC\x8B\xCD\x92\xCD\x91\xCC\x8F\xCC\x81\xCD\x95\xCC\xA2\xCC\xB9\xCC\xB2\xCD\x9C\xCC\xB1\xCC\xA6\xCC\xB3\xCC\xAF\xCC\xAE\xCC\x9C\xCD\x99s\xCC\xB8\xCC\x8C\xCC\x8E\xCC\x87\xCD\x81\xCD\x82\xCC\x86\xCD\x8C\xCD\x8C\xCC\x8B\xCC\x84\xCC\x8C\xCD\x84\xCD\x9B\xCD\x86\xCC\x93\xCD\x90\xCC\x85\xCC\x94\xCD\x98\xCD\x84\xCD\x92\xCD\x8B\xCC\x90\xCC\x83\xCC\x8F\xCD\x84\xCD\x81\xCD\x9B\xCC\x90\xCD\x81\xCC\x8F\xCC\xBD\xCC\x88\xCC\xBF\xCC\x88\xCC\x84\xCC\x8E\xCD\x99\xCD\x94\xCC\x99\xCD\x99\xCC\xB0\xCC\xA8\xCC\xA3\xCC\xA8\xCC\x96\xCC\x99\xCC\xAE\xCC\xBC\xCC\x99\xCD\x9A\xCC\xB2\xCC\xB1\xCC\x9F\xCC\xBB\xCC\xA6\xCD\x85\xCC\xAA\xCD\x89\xCC\x9D\xCC\x99\xCD\x96\xCC\xB1\xCC\xB1\xCC\x99\xCC\xA6\xCC\xA5\xCD\x95\xCC\xB2\xCC\xA0\xCD\x99 within") + set spell spelllang=en + redraw + redraw! + bwipe! + set nospell +endfunc + func LoadAffAndDic(aff_contents, dic_contents) throw 'skipped: Nvim does not support enc=latin1' set enc=latin1 diff --git a/src/nvim/version.c b/src/nvim/version.c index e07865a410..74a4852def 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -52,12 +52,8 @@ static char *features[] = { "-acl", #endif -#if (defined(HAVE_ICONV_H) && defined(USE_ICONV)) || defined(DYNAMIC_ICONV) -# ifdef DYNAMIC_ICONV -"+iconv/dyn", -# else +#if defined(HAVE_ICONV) "+iconv", -# endif #else "-iconv", #endif |