diff options
36 files changed, 580 insertions, 343 deletions
diff --git a/cmake/FindLibTermkey.cmake b/cmake/FindLibTermkey.cmake new file mode 100644 index 0000000000..533f168fe9 --- /dev/null +++ b/cmake/FindLibTermkey.cmake @@ -0,0 +1,48 @@ +# - Try to find libtermkey +# Once done this will define +# LIBTERMKEY_FOUND - System has libtermkey +# LIBTERMKEY_INCLUDE_DIRS - The libtermkey include directories +# LIBTERMKEY_LIBRARIES - The libraries needed to use libtermkey + +find_package(PkgConfig) +if(NOT LIBTERMKEY_USE_BUNDLED) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(PC_LIBTERMKEY QUIET libtermkey) + endif() +else() + set(PC_LIBTERMKEY_INCLUDEDIR) + set(PC_LIBTERMKEY_INCLUDE_DIRS) + set(PC_LIBTERMKEY_LIBDIR) + set(PC_LIBTERMKEY_LIBRARY_DIRS) + set(LIMIT_SEARCH NO_DEFAULT_PATH) +endif() + +set(LIBTERMKEY_DEFINITIONS ${PC_LIBTERMKEY_CFLAGS_OTHER}) + +find_path(LIBTERMKEY_INCLUDE_DIR termkey.h + PATHS ${PC_LIBTERMKEY_INCLUDEDIR} ${PC_LIBTERMKEY_INCLUDE_DIRS} + ${LIMIT_SEARCH}) + +# If we're asked to use static linkage, add libuv.a as a preferred library name. +if(LIBTERMKEY_USE_STATIC) + list(APPEND LIBTERMKEY_NAMES + "${CMAKE_STATIC_LIBRARY_PREFIX}termkey${CMAKE_STATIC_LIBRARY_SUFFIX}") +endif() + +list(APPEND LIBTERMKEY_NAMES termkey) + +find_library(LIBTERMKEY_LIBRARY NAMES ${LIBTERMKEY_NAMES} + HINTS ${PC_LIBTERMKEY_LIBDIR} ${PC_LIBTERMKEY_LIBRARY_DIRS} + ${LIMIT_SEARCH}) + +set(LIBTERMKEY_LIBRARIES ${LIBTERMKEY_LIBRARY}) +set(LIBTERMKEY_INCLUDE_DIRS ${LIBTERMKEY_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LIBTERMKEY_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(LibTermkey DEFAULT_MSG + LIBTERMKEY_LIBRARY LIBTERMKEY_INCLUDE_DIR) + +mark_as_advanced(LIBTERMKEY_INCLUDE_DIR LIBTERMKEY_LIBRARY) diff --git a/cmake/FindLibTickit.cmake b/cmake/FindLibTickit.cmake new file mode 100644 index 0000000000..c20bf4f74f --- /dev/null +++ b/cmake/FindLibTickit.cmake @@ -0,0 +1,48 @@ +# - Try to find libtickit +# Once done this will define +# LIBTICKIT_FOUND - System has libtickit +# LIBTICKIT_INCLUDE_DIRS - The libtickit include directories +# LIBTICKIT_LIBRARIES - The libraries needed to use libtickit + +find_package(PkgConfig) +if(NOT LIBTICKIT_USE_BUNDLED) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(PC_LIBTICKIT QUIET libtickit) + endif() +else() + set(PC_LIBTICKIT_INCLUDEDIR) + set(PC_LIBTICKIT_INCLUDE_DIRS) + set(PC_LIBTICKIT_LIBDIR) + set(PC_LIBTICKIT_LIBRARY_DIRS) + set(LIMIT_SEARCH NO_DEFAULT_PATH) +endif() + +set(LIBTICKIT_DEFINITIONS ${PC_LIBTICKIT_CFLAGS_OTHER}) + +find_path(LIBTICKIT_INCLUDE_DIR tickit.h + PATHS ${PC_LIBTICKIT_INCLUDEDIR} ${PC_LIBTICKIT_INCLUDE_DIRS} + ${LIMIT_SEARCH}) + +# If we're asked to use static linkage, add libuv.a as a preferred library name. +if(LIBTICKIT_USE_STATIC) + list(APPEND LIBTICKIT_NAMES + "${CMAKE_STATIC_LIBRARY_PREFIX}tickit${CMAKE_STATIC_LIBRARY_SUFFIX}") +endif() + +list(APPEND LIBTICKIT_NAMES tickit) + +find_library(LIBTICKIT_LIBRARY NAMES ${LIBTICKIT_NAMES} + HINTS ${PC_LIBTICKIT_LIBDIR} ${PC_LIBTICKIT_LIBRARY_DIRS} + ${LIMIT_SEARCH}) + +set(LIBTICKIT_LIBRARIES ${LIBTICKIT_LIBRARY}) +set(LIBTICKIT_INCLUDE_DIRS ${LIBTICKIT_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LIBTICKIT_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(LibTickit DEFAULT_MSG + LIBTICKIT_LIBRARY LIBTICKIT_INCLUDE_DIR) + +mark_as_advanced(LIBTICKIT_INCLUDE_DIR LIBTICKIT_LIBRARY) diff --git a/cmake/FindLibUnibilium.cmake b/cmake/FindLibUnibilium.cmake new file mode 100644 index 0000000000..aace9a40d5 --- /dev/null +++ b/cmake/FindLibUnibilium.cmake @@ -0,0 +1,48 @@ +# - Try to find libunibilium +# Once done this will define +# LIBUNIBILIUM_FOUND - System has libunibilium +# LIBUNIBILIUM_INCLUDE_DIRS - The libunibilium include directories +# LIBUNIBILIUM_LIBRARIES - The libraries needed to use libunibilium + +find_package(PkgConfig) +if(NOT LIBUNIBILIUM_USE_BUNDLED) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(PC_LIBUNIBILIUM QUIET libunibilium) + endif() +else() + set(PC_LIBUNIBILIUM_INCLUDEDIR) + set(PC_LIBUNIBILIUM_INCLUDE_DIRS) + set(PC_LIBUNIBILIUM_LIBDIR) + set(PC_LIBUNIBILIUM_LIBRARY_DIRS) + set(LIMIT_SEARCH NO_DEFAULT_PATH) +endif() + +set(LIBUNIBILIUM_DEFINITIONS ${PC_LIBUNIBILIUM_CFLAGS_OTHER}) + +find_path(LIBUNIBILIUM_INCLUDE_DIR unibilium.h + PATHS ${PC_LIBUNIBILIUM_INCLUDEDIR} ${PC_LIBUNIBILIUM_INCLUDE_DIRS} + ${LIMIT_SEARCH}) + +# If we're asked to use static linkage, add libuv.a as a preferred library name. +if(LIBUNIBILIUM_USE_STATIC) + list(APPEND LIBUNIBILIUM_NAMES + "${CMAKE_STATIC_LIBRARY_PREFIX}unibilium${CMAKE_STATIC_LIBRARY_SUFFIX}") +endif() + +list(APPEND LIBUNIBILIUM_NAMES unibilium) + +find_library(LIBUNIBILIUM_LIBRARY NAMES ${LIBUNIBILIUM_NAMES} + HINTS ${PC_LIBUNIBILIUM_LIBDIR} ${PC_LIBUNIBILIUM_LIBRARY_DIRS} + ${LIMIT_SEARCH}) + +set(LIBUNIBILIUM_LIBRARIES ${LIBUNIBILIUM_LIBRARY}) +set(LIBUNIBILIUM_INCLUDE_DIRS ${LIBUNIBILIUM_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LIBUNIBILIUM_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(LibUnibilium DEFAULT_MSG + LIBUNIBILIUM_LIBRARY LIBUNIBILIUM_INCLUDE_DIR) + +mark_as_advanced(LIBUNIBILIUM_INCLUDE_DIR LIBUNIBILIUM_LIBRARY) diff --git a/cmake/FindLuaJit.cmake b/cmake/FindLuaJit.cmake index a72fb175b4..e5fdc764f1 100644 --- a/cmake/FindLuaJit.cmake +++ b/cmake/FindLuaJit.cmake @@ -25,7 +25,8 @@ find_path(LUAJIT_INCLUDE_DIR luajit.h PATH_SUFFIXES luajit-2.0 ${LIMIT_SEARCH}) -# If we're asked to use static linkage, add libuv.a as a preferred library name. +# If we're asked to use static linkage, add libluajit-5.1.a as a preferred +# library name. if(LUAJIT_USE_STATIC) list(APPEND LUAJIT_NAMES "${CMAKE_STATIC_LIBRARY_PREFIX}luajit-5.1${CMAKE_STATIC_LIBRARY_SUFFIX}") diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 91a9f1292f..0778cf6122 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -6188,11 +6188,12 @@ system({expr} [, {input}]) *system()* *E677* Use |:checktime| to force a check. -systemlist({expr} [, {input}]) *systemlist()* +systemlist({expr} [, {input} [, {keepempty}]]) *systemlist()* Same as |system()|, but returns a |List| with lines (parts of output separated by NL) with NULs transformed into NLs. Output is the same as |readfile()| will output with {binary} argument - set to "b". + set to "b", except that a final newline is not preserved, + unless {keepempty} is present and it's non-zero. Returns an empty string on error, so be careful not to run into |E706|. diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 69b7440da2..2867857fb3 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -77,7 +77,6 @@ set(CONV_SOURCES search.c sha256.c spell.c - strings.c syntax.c tag.c term.c diff --git a/src/nvim/charset.c b/src/nvim/charset.c index bbe80a519c..9e5194a5df 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -1855,7 +1855,7 @@ int hexhex2nr(char_u *p) #endif // if defined(FEAT_TERMRESPONSE) || defined(FEAT_GUI_GTK) // || defined(PROTO) -/// Return TRUE if "str" starts with a backslash that should be removed. +/// Return true if "str" starts with a backslash that should be removed. /// For WIN32 this is only done when the character after the /// backslash is not a normal file name character. /// '$' is a valid file name character, we don't remove the backslash before @@ -1869,8 +1869,8 @@ int hexhex2nr(char_u *p) /// /// @param str /// -/// @return TRUE if `str` starts with a backslash that should be removed. -int rem_backslash(char_u *str) +/// @return true if `str` starts with a backslash that should be removed. +bool rem_backslash(const char_u *str) { #ifdef BACKSLASH_IN_FILENAME return str[0] == '\\' diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c index 6587a43452..2b5fdea2fe 100644 --- a/src/nvim/digraph.c +++ b/src/nvim/digraph.c @@ -1813,10 +1813,10 @@ void ex_loadkeymap(exarg_T *eap) if ((*p != '"') && (*p != NUL)) { kmap_T *kp = GA_APPEND_VIA_PTR(kmap_T, &curbuf->b_kmap_ga); s = skiptowhite(p); - kp->from = vim_strnsave(p, (int)(s - p)); + kp->from = vim_strnsave(p, (size_t)(s - p)); p = skipwhite(s); s = skiptowhite(p); - kp->to = vim_strnsave(p, (int)(s - p)); + kp->to = vim_strnsave(p, (size_t)(s - p)); if ((STRLEN(kp->from) + STRLEN(kp->to) >= KMAP_LLEN) || (*kp->from == NUL) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 8be25bc34e..be69bdbe61 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6593,7 +6593,7 @@ static struct fst { {"synconcealed", 2, 2, f_synconcealed}, {"synstack", 2, 2, f_synstack}, {"system", 1, 2, f_system}, - {"systemlist", 1, 2, f_systemlist}, + {"systemlist", 1, 3, f_systemlist}, {"tabpagebuflist", 0, 1, f_tabpagebuflist}, {"tabpagenr", 0, 1, f_tabpagenr}, {"tabpagewinnr", 1, 2, f_tabpagewinnr}, @@ -14523,7 +14523,7 @@ static void f_synstack(typval_T *argvars, typval_T *rettv) } } -static list_T* string_to_list(char_u *str, size_t len) +static list_T* string_to_list(char_u *str, size_t len, bool keepempty) { list_T *list = list_alloc(); @@ -14543,6 +14543,11 @@ static list_T* string_to_list(char_u *str, size_t len) list_append(list, li); } + // Optionally retain final newline, if present + if (keepempty && str[len-1] == NL) { + list_append_string(list, (char_u*)"", 0); + } + return list; } @@ -14585,7 +14590,11 @@ static void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv, } if (retlist) { - rettv->vval.v_list = string_to_list((char_u *) res, nread); + int keepempty = 0; + if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) { + keepempty = get_tv_number(&argvars[2]); + } + rettv->vval.v_list = string_to_list((char_u *) res, nread, keepempty != 0); rettv->vval.v_list->lv_refcount++; rettv->v_type = VAR_LIST; @@ -19723,7 +19732,7 @@ static void apply_job_autocmds(int id, char *name, char *type, str_slot->li_tv.v_type = VAR_LIST; str_slot->li_tv.v_lock = 0; str_slot->li_tv.vval.v_list = - string_to_list((char_u *) received, received_len); + string_to_list((char_u *) received, received_len, false); str_slot->li_tv.vval.v_list->lv_refcount++; list_append(list, str_slot); diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 0829049e4d..44caa67847 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -47,6 +47,7 @@ #include "nvim/garray.h" #include "nvim/memory.h" #include "nvim/move.h" +#include "nvim/mouse.h" #include "nvim/normal.h" #include "nvim/ops.h" #include "nvim/option.h" @@ -3605,12 +3606,13 @@ void do_sub(exarg_T *eap) linenr_T joined_lines_count = eap->line2 < curbuf->b_ml.ml_line_count ? eap->line2 - eap->line1 + 2 : eap->line2 - eap->line1 + 1; - if (joined_lines_count >= 2) { + if (joined_lines_count > 1) { do_join(joined_lines_count, FALSE, TRUE, FALSE, true); + sub_nsubs = joined_lines_count - 1; + sub_nlines = 1; + do_sub_msg(false); + ex_may_print(eap); } - sub_nlines = sub_nsubs = joined_lines_count - 1; - do_sub_msg(false); - ex_may_print(eap); return; } diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 24a1ccf85d..794e9930b9 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -157,7 +157,6 @@ void do_debug(char_u *cmd) /* Make sure we are in raw mode and start termcap mode. Might have side * effects... */ - settmode(TMODE_RAW); starttermcap(); ++RedrawingDisabled; /* don't redisplay the window */ diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 3967c916bb..e180be4421 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -5107,7 +5107,6 @@ static void ex_highlight(exarg_T *eap) void not_exiting(void) { exiting = FALSE; - settmode(TMODE_RAW); } /* @@ -5994,7 +5993,6 @@ do_exedit ( { int n; int need_hide; - int exmode_was = exmode_active; /* * ":vi" command ends Ex mode. @@ -6014,8 +6012,6 @@ do_exedit ( eap->nextcmd = NULL; } - if (exmode_was != EXMODE_VIM) - settmode(TMODE_RAW); RedrawingDisabled = 0; no_wait_return = 0; need_wait_return = FALSE; @@ -6446,7 +6442,7 @@ static void ex_winsize(exarg_T *eap) p = arg; h = getdigits(&arg); if (*p != NUL && *arg == NUL) - set_shellsize(w, h, TRUE); + screen_resize(w, h, TRUE); else EMSG(_("E465: :winsize requires two number arguments")); } @@ -7482,7 +7478,7 @@ static void ex_tag_cmd(exarg_T *eap, char_u *name) * If found return one of the SPEC_ values and set "*usedlen" to the length of * the variable. Otherwise return -1 and "*usedlen" is unchanged. */ -int find_cmdline_var(char_u *src, int *usedlen) +int find_cmdline_var(const char_u *src, int *usedlen) FUNC_ATTR_NONNULL_ALL { int len; int i; diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index ef3facb18b..196f8e6136 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -386,21 +386,19 @@ int do_intthrow(struct condstack *cstack) char_u *get_exception_string(void *value, int type, char_u *cmdname, int *should_free) { char_u *ret, *mesg; - int cmdlen; char_u *p, *val; if (type == ET_ERROR) { *should_free = FALSE; mesg = ((struct msglist *)value)->throw_msg; if (cmdname != NULL && *cmdname != NUL) { - cmdlen = (int)STRLEN(cmdname); - ret = vim_strnsave((char_u *)"Vim(", - 4 + cmdlen + 2 + (int)STRLEN(mesg)); + size_t cmdlen = STRLEN(cmdname); + ret = vim_strnsave((char_u *)"Vim(", 4 + cmdlen + 2 + STRLEN(mesg)); STRCPY(&ret[4], cmdname); STRCPY(&ret[4 + cmdlen], "):"); val = ret + 4 + cmdlen + 2; } else { - ret = vim_strnsave((char_u *)"Vim:", 4 + (int)STRLEN(mesg)); + ret = vim_strnsave((char_u *)"Vim:", 4 + STRLEN(mesg)); val = ret + 4; } @@ -708,7 +706,7 @@ static void report_pending(int action, int pending, void *value) if (pending & CSTP_THROW) { vim_snprintf((char *)IObuff, IOSIZE, (char *)mesg, _("Exception")); - mesg = vim_strnsave(IObuff, (int)STRLEN(IObuff) + 4); + mesg = vim_strnsave(IObuff, STRLEN(IObuff) + 4); STRCAT(mesg, ": %s"); s = (char *)((except_T *)value)->value; } else if ((pending & CSTP_ERROR) && (pending & CSTP_INTERRUPT)) diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 70db2dc479..e56592923d 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -48,6 +48,7 @@ #include "nvim/keymap.h" #include "nvim/garray.h" #include "nvim/move.h" +#include "nvim/mouse.h" #include "nvim/ops.h" #include "nvim/option.h" #include "nvim/os_unix.h" @@ -270,10 +271,6 @@ getcmdline ( setmouse(); ui_cursor_shape(); /* may show different cursor shape */ - /* When inside an autocommand for writing "exiting" may be set and - * terminal mode set to cooked. Need to set raw mode here then. */ - settmode(TMODE_RAW); - init_history(); hiscnt = hislen; /* set hiscnt to impossible history value */ histype = hist_char2type(firstc); diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index a51f088586..9267e7991c 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -308,7 +308,7 @@ vim_findfile_init ( && (vim_ispathsep(path[1]) || path[1] == NUL) && (!tagfile || vim_strchr(p_cpo, CPO_DOTTAG) == NULL) && rel_fname != NULL) { - int len = (int)(path_tail(rel_fname) - rel_fname); + size_t len = (size_t)(path_tail(rel_fname) - rel_fname); if (!vim_isAbsName(rel_fname) && len + 1 < MAXPATHL) { /* Make the start dir an absolute path name. */ @@ -375,8 +375,9 @@ vim_findfile_init ( search_ctx->ffsc_stopdirs_v = ptr; walker = vim_strchr(walker, ';'); if (walker) { + assert(walker - helper >= 0); search_ctx->ffsc_stopdirs_v[dircount-1] = - vim_strnsave(helper, (int)(walker - helper)); + vim_strnsave(helper, (size_t)(walker - helper)); walker++; } else /* this might be "", which means ascent till top @@ -404,7 +405,8 @@ vim_findfile_init ( char *errpt; /* save the fix part of the path */ - search_ctx->ffsc_fix_path = vim_strnsave(path, (int)(wc_part - path)); + assert(wc_part - path >= 0); + search_ctx->ffsc_fix_path = vim_strnsave(path, (size_t)(wc_part - path)); /* * copy wc_path and add restricts to the '**' wildcard. diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 3be9d89d87..021b12208e 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -1812,7 +1812,6 @@ failed: * Switch on raw mode now and clear the screen. */ if (read_stdin) { - settmode(TMODE_RAW); /* set to raw mode */ starttermcap(); screenclear(); } @@ -2387,9 +2386,6 @@ buf_write ( else overwriting = FALSE; - if (exiting) - settmode(TMODE_COOK); /* when exiting allow typeahead now */ - ++no_wait_return; /* don't wait for return yet */ /* diff --git a/src/nvim/macros.h b/src/nvim/macros.h index f8fd6ac6a2..215ad3a1f7 100644 --- a/src/nvim/macros.h +++ b/src/nvim/macros.h @@ -143,8 +143,9 @@ /* get length of multi-byte char, not including composing chars */ # define mb_cptr2len(p) (enc_utf8 ? utf_ptr2len(p) : (*mb_ptr2len)(p)) -# define MB_COPY_CHAR(f, \ - t) if (has_mbyte) mb_copy_char(&f, &t); else *t++ = *f++ +# define MB_COPY_CHAR(f, t) \ + if (has_mbyte) mb_copy_char((const char_u **)(&f), &t); \ + else *t++ = *f++ # define MB_CHARLEN(p) (has_mbyte ? mb_charlen(p) : (int)STRLEN(p)) # define MB_CHAR2LEN(c) (has_mbyte ? mb_char2len(c) : 1) # define PTR2CHAR(p) (has_mbyte ? mb_ptr2char(p) : (int)*(p)) diff --git a/src/nvim/main.c b/src/nvim/main.c index 54077acfe3..8e19cf3686 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -43,6 +43,7 @@ #include "nvim/log.h" #include "nvim/memory.h" #include "nvim/move.h" +#include "nvim/mouse.h" #include "nvim/normal.h" #include "nvim/ops.h" #include "nvim/option.h" @@ -281,7 +282,7 @@ int main(int argc, char **argv) // In embedded mode don't do terminal-related initializations, assume an // initial screen size of 80x20 full_screen = true; - set_shellsize(80, 20, false); + screen_resize(80, 20, false); } else { // set terminal name and get terminal capabilities (will set full_screen) // Do some initialization of the screen diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index d79a46ceaa..9b4513e979 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -3002,7 +3002,7 @@ int utf_head_off(const char_u *base, const char_u *p) /* * Copy a character from "*fp" to "*tp" and advance the pointers. */ -void mb_copy_char(char_u **fp, char_u **tp) +void mb_copy_char(const char_u **fp, char_u **tp) { int l = (*mb_ptr2len)(*fp); diff --git a/src/nvim/memory.c b/src/nvim/memory.c index 4c5a45b8b6..f959ea55e4 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -305,6 +305,7 @@ char *xstpncpy(char *restrict dst, const char *restrict src, size_t maxlen) /// @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) + FUNC_ATTR_NONNULL_ALL { size_t ret = strlen(src); @@ -348,7 +349,7 @@ char *xstrdup(const char *str) /// @param c The byte to search for. /// @param len The length of the memory object. /// @returns a pointer to the found byte in src[len], or NULL. -void *xmemrchr(void *src, uint8_t c, size_t len) +void *xmemrchr(const void *src, uint8_t c, size_t len) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE { while (len--) { diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index 230e198121..fc848466c6 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -42,6 +42,7 @@ #include "nvim/misc2.h" #include "nvim/garray.h" #include "nvim/move.h" +#include "nvim/mouse.h" #include "nvim/option.h" #include "nvim/os_unix.h" #include "nvim/path.h" @@ -2286,8 +2287,6 @@ int ask_yesno(char_u *str, int direct) int r = ' '; int save_State = State; - if (exiting) /* put terminal in raw mode for this question */ - settmode(TMODE_RAW); ++no_wait_return; #ifdef USE_ON_FLY_SCROLL dont_scroll = TRUE; /* disallow scrolling here */ diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 7fc581a7c0..439cdbd5c8 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -2,8 +2,12 @@ #include "nvim/mouse.h" #include "nvim/vim.h" -#include "nvim/screen.h" +#include "nvim/ascii.h" #include "nvim/window.h" +#include "nvim/strings.h" +#include "nvim/screen.h" +#include "nvim/ui.h" +#include "nvim/os_unix.h" #include "nvim/term.h" #include "nvim/fold.h" #include "nvim/diff.h" @@ -165,11 +169,9 @@ retnomove: // (MOUSE_FOCUS was set above if we dragged first). if (dragwin == NULL || (flags & MOUSE_RELEASED)) win_enter(wp, true); // can make wp invalid! -# ifdef CHECK_DOUBLE_CLICK // set topline, to be able to check for double click ourselves if (curwin != old_curwin) set_mouse_topline(curwin); -# endif if (on_status_line) { // In (or below) status line // Don't use start_arrow() if we're in the same window if (curwin == old_curwin) @@ -436,3 +438,62 @@ win_T *mouse_find_win(int *rowp, int *colp) } return fp->fr_win; } + +/* + * setmouse() - switch mouse on/off depending on current mode and 'mouse' + */ +void setmouse(void) +{ + int checkfor; + + + /* be quick when mouse is off */ + if (*p_mouse == NUL) + return; + + /* don't switch mouse on when not in raw mode (Ex mode) */ + if (cur_tmode != TMODE_RAW) { + mch_setmouse(false); + return; + } + + if (VIsual_active) + checkfor = MOUSE_VISUAL; + else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE) + checkfor = MOUSE_RETURN; + else if (State & INSERT) + checkfor = MOUSE_INSERT; + else if (State & CMDLINE) + checkfor = MOUSE_COMMAND; + else if (State == CONFIRM || State == EXTERNCMD) + checkfor = ' '; /* don't use mouse for ":confirm" or ":!cmd" */ + else + checkfor = MOUSE_NORMAL; /* assume normal mode */ + + if (mouse_has(checkfor)) + mch_setmouse(true); + else + mch_setmouse(false); +} + +/* + * Return true if + * - "c" is in 'mouse', or + * - 'a' is in 'mouse' and "c" is in MOUSE_A, or + * - the current buffer is a help file and 'h' is in 'mouse' and we are in a + * normal editing mode (not at hit-return message). + */ +int mouse_has(int c) +{ + for (char_u *p = p_mouse; *p; ++p) + switch (*p) { + case 'a': if (vim_strchr((char_u *)MOUSE_A, c) != NULL) + return true; + break; + case MOUSE_HELP: if (c != MOUSE_RETURN && curbuf->b_help) + return true; + break; + default: if (c == *p) return true; break; + } + return false; +} diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 0a43d59607..1b21100933 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -46,6 +46,7 @@ #include "nvim/misc2.h" #include "nvim/keymap.h" #include "nvim/move.h" +#include "nvim/mouse.h" #include "nvim/ops.h" #include "nvim/option.h" #include "nvim/quickfix.h" @@ -7374,3 +7375,11 @@ static void nv_cursorhold(cmdarg_T *cap) did_cursorhold = true; cap->retval |= CA_COMMAND_BUSY; /* don't call edit() now */ } + +/* + * Return TRUE when 'mousemodel' is set to "popup" or "popup_setpos". + */ +static int mouse_model_popup(void) +{ + return p_mousem[0] == 'p'; +} diff --git a/src/nvim/option.c b/src/nvim/option.c index ee70b5bf8a..2882d7a511 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -66,6 +66,7 @@ #include "nvim/garray.h" #include "nvim/cursor_shape.h" #include "nvim/move.h" +#include "nvim/mouse.h" #include "nvim/normal.h" #include "nvim/os_unix.h" #include "nvim/path.h" @@ -5540,7 +5541,7 @@ set_num_option ( *pp = old_value; else if (full_screen ) - set_shellsize((int)Columns, (int)Rows, TRUE); + screen_resize((int)Columns, (int)Rows, TRUE); else { /* Postpone the resizing; check the size and cmdline position for * messages. */ diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index 3aefbc39d1..b2e62453c5 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -43,7 +43,7 @@ char *os_getenvname_at_index(size_t index) if (str == NULL) { return NULL; } - int namesize = 0; + size_t namesize = 0; while (str[namesize] != '=' && str[namesize] != NUL) { namesize++; } diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 1b279f18f5..cdd85e4e96 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -104,14 +104,10 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_arg) { DynamicBuffer input = DYNAMIC_BUFFER_INIT; char *output = NULL, **output_ptr = NULL; - int current_state = State, old_mode = cur_tmode; + int current_state = State; bool forward_output = true; out_flush(); - if (opts & kShellOptCooked) { - settmode(TMODE_COOK); - } - // While the child is running, ignore terminating signals signal_reject_deadly(); @@ -155,10 +151,6 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_arg) msg_putchar('\n'); } - if (old_mode == TMODE_RAW) { - // restore mode - settmode(TMODE_RAW); - } State = current_state; signal_accept_deadly(); diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c index a4871ef499..3794e813d2 100644 --- a/src/nvim/os/time.c +++ b/src/nvim/os/time.c @@ -6,6 +6,7 @@ #include <uv.h> #include "nvim/os/time.h" +#include "nvim/os/event.h" #include "nvim/vim.h" #include "nvim/term.h" @@ -38,31 +39,22 @@ uint64_t os_hrtime(void) /// @param ignoreinput If true, allow a SIGINT to interrupt us void os_delay(uint64_t milliseconds, bool ignoreinput) { - os_microdelay(milliseconds * 1000, ignoreinput); + if (ignoreinput) { + if (milliseconds > INT_MAX) { + milliseconds = INT_MAX; + } + event_poll_until((int)milliseconds, got_int); + } else { + os_microdelay(milliseconds * 1000); + } } /// Sleeps for a certain amount of microseconds /// /// @param microseconds Number of microseconds to sleep -/// @param ignoreinput If true, allow a SIGINT to interrupt us -void os_microdelay(uint64_t microseconds, bool ignoreinput) +void os_microdelay(uint64_t microseconds) { - int old_tmode; - - if (ignoreinput) { - // Go to cooked mode without echo, to allow SIGINT interrupting us - // here - old_tmode = curr_tmode; - - if (curr_tmode == TMODE_RAW) - settmode(TMODE_SLEEP); - - microdelay(microseconds); - - settmode(old_tmode); - } else { - microdelay(microseconds); - } + microdelay(microseconds); } /// Portable version of POSIX localtime_r() diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c index 8784559b50..677976e3e1 100644 --- a/src/nvim/os_unix.c +++ b/src/nvim/os_unix.c @@ -37,6 +37,7 @@ #include "nvim/message.h" #include "nvim/misc1.h" #include "nvim/misc2.h" +#include "nvim/mouse.h" #include "nvim/garray.h" #include "nvim/path.h" #include "nvim/screen.h" diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 2dbf3f8888..0225eb72c1 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -103,6 +103,7 @@ #include "nvim/ex_cmds.h" #include "nvim/ex_cmds2.h" #include "nvim/ex_getln.h" +#include "nvim/edit.h" #include "nvim/farsi.h" #include "nvim/fileio.h" #include "nvim/fold.h" @@ -120,6 +121,7 @@ #include "nvim/move.h" #include "nvim/normal.h" #include "nvim/option.h" +#include "nvim/os_unix.h" #include "nvim/path.h" #include "nvim/popupmnu.h" #include "nvim/quickfix.h" @@ -129,6 +131,7 @@ #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/version.h" #include "nvim/window.h" @@ -8117,3 +8120,98 @@ int screen_screenrow(void) return screen_cur_row; } +/* + * 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'. + */ +void screen_resize(int width, int height, int mustset) +{ + static int busy = FALSE; + + /* + * Avoid recursiveness, can happen when setting the window size causes + * another window-changed signal. + */ + if (busy) + return; + + if (width < 0 || height < 0) /* just checking... */ + return; + + if (State == HITRETURN || State == SETWSIZE) { + /* postpone the resizing */ + State = SETWSIZE; + return; + } + + /* curwin->w_buffer can be NULL when we are closing a window and the + * buffer has already been closed and removing a scrollbar causes a resize + * event. Don't resize then, it will happen after entering another buffer. + */ + if (curwin->w_buffer == NULL) + return; + + ++busy; + + + if (mustset || (ui_get_shellsize() == FAIL && height != 0)) { + Rows = height; + Columns = width; + check_shellsize(); + mch_set_shellsize(); + } else + check_shellsize(); + + /* The window layout used to be adjusted here, but it now happens in + * screenalloc() (also invoked from screenclear()). That is because the + * "busy" check above may skip this, but not screenalloc(). */ + + if (State != ASKMORE && State != EXTERNCMD && State != CONFIRM) + screenclear(); + else + screen_start(); /* don't know where cursor is now */ + + if (starting != NO_SCREEN) { + maketitle(); + changed_line_abv_curs(); + invalidate_botline(); + + /* + * We only redraw when it's needed: + * - While at the more prompt or executing an external command, don't + * redraw, but position the cursor. + * - While editing the command line, only redraw that. + * - in Ex mode, don't redraw anything. + * - Otherwise, redraw right now, and position the cursor. + * Always need to call update_screen() or screenalloc(), to make + * sure Rows/Columns and the size of ScreenLines[] is correct! + */ + if (State == ASKMORE || State == EXTERNCMD || State == CONFIRM + || exmode_active) { + screenalloc(false); + repeat_message(); + } else { + if (curwin->w_p_scb) + do_check_scrollbind(TRUE); + if (State & CMDLINE) { + update_screen(NOT_VALID); + redrawcmdline(); + } else { + update_topline(); + if (pum_visible()) { + redraw_later(NOT_VALID); + ins_compl_show_pum(); /* This includes the redraw. */ + } else + update_screen(NOT_VALID); + if (redrawing()) + setcursor(); + } + } + cursor_on(); /* redrawing may have switched it off */ + } + out_flush(); + --busy; +} diff --git a/src/nvim/search.c b/src/nvim/search.c index e9184d84cd..3055729bf8 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -39,6 +39,7 @@ #include "nvim/misc1.h" #include "nvim/misc2.h" #include "nvim/move.h" +#include "nvim/mouse.h" #include "nvim/normal.h" #include "nvim/option.h" #include "nvim/path.h" diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 6c69b3b34a..20008bca16 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -49,7 +49,8 @@ /* * Copy "string" into newly allocated memory. */ -char_u *vim_strsave(char_u *string) FUNC_ATTR_NONNULL_RET +char_u *vim_strsave(const char_u *string) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { return (char_u *)xstrdup((char *)string); } @@ -60,7 +61,8 @@ char_u *vim_strsave(char_u *string) FUNC_ATTR_NONNULL_RET * The allocated memory always has size "len + 1", also when "string" is * shorter. */ -char_u *vim_strnsave(char_u *string, int len) FUNC_ATTR_NONNULL_RET +char_u *vim_strnsave(const char_u *string, size_t len) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { return (char_u *)strncpy(xmallocz(len), (char *)string, len); } @@ -69,31 +71,30 @@ char_u *vim_strnsave(char_u *string, int len) FUNC_ATTR_NONNULL_RET * Same as vim_strsave(), but any characters found in esc_chars are preceded * by a backslash. */ -char_u *vim_strsave_escaped(char_u *string, char_u *esc_chars) - FUNC_ATTR_NONNULL_RET +char_u *vim_strsave_escaped(const char_u *string, const char_u *esc_chars) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { - return vim_strsave_escaped_ext(string, esc_chars, '\\', FALSE); + return vim_strsave_escaped_ext(string, esc_chars, '\\', false); } /* - * Same as vim_strsave_escaped(), but when "bsl" is TRUE also escape + * Same as vim_strsave_escaped(), but when "bsl" is true also escape * characters where rem_backslash() would remove the backslash. * Escape the characters with "cc". */ -char_u *vim_strsave_escaped_ext(char_u *string, char_u *esc_chars, int cc, int bsl) - FUNC_ATTR_NONNULL_RET +char_u *vim_strsave_escaped_ext(const char_u *string, const char_u *esc_chars, + char_u cc, bool bsl) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { - unsigned length; - int l; - /* * First count the number of backslashes required. * Then allocate the memory and insert them. */ - length = 1; /* count the trailing NUL */ - for (char_u *p = string; *p; p++) { - if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) { - length += l; /* count a multibyte char */ + size_t length = 1; // count the trailing NUL + for (const char_u *p = string; *p; p++) { + size_t l; + if (has_mbyte && (l = (size_t)(*mb_ptr2len)(p)) > 1) { + length += l; // count a multibyte char p += l - 1; continue; } @@ -104,9 +105,10 @@ char_u *vim_strsave_escaped_ext(char_u *string, char_u *esc_chars, int cc, int b char_u *escaped_string = xmalloc(length); char_u *p2 = escaped_string; - for (char_u *p = string; *p; p++) { - if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) { - memmove(p2, p, (size_t)l); + for (const char_u *p = string; *p; p++) { + size_t l; + if (has_mbyte && (l = (size_t)(*mb_ptr2len)(p)) > 1) { + memcpy(p2, p, l); p2 += l; p += l - 1; /* skip multibyte char */ continue; @@ -130,10 +132,10 @@ char_u *vim_strsave_escaped_ext(char_u *string, char_u *esc_chars, int cc, int b * When "do_newline" is false do not escape newline unless it is csh shell. * Returns the result in allocated memory. */ -char_u *vim_strsave_shellescape(char_u *string, bool do_special, bool do_newline) +char_u *vim_strsave_shellescape(const char_u *string, + bool do_special, bool do_newline) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { - unsigned length; - char_u *p; char_u *d; char_u *escaped_string; int l; @@ -146,8 +148,8 @@ char_u *vim_strsave_shellescape(char_u *string, bool do_special, bool do_newline csh_like = csh_like_shell(); /* First count the number of extra bytes required. */ - length = (unsigned)STRLEN(string) + 3; /* two quotes and a trailing NUL */ - for (p = string; *p != NUL; mb_ptr_adv(p)) { + 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; /* ' => '\'' */ if ((*p == '\n' && (csh_like || do_newline)) @@ -169,7 +171,7 @@ char_u *vim_strsave_shellescape(char_u *string, bool do_special, bool do_newline /* add opening quote */ *d++ = '\''; - for (p = string; *p != NUL; ) { + for (const char_u *p = string; *p != NUL; ) { if (*p == '\'') { *d++ = '\''; *d++ = '\\'; @@ -207,7 +209,8 @@ char_u *vim_strsave_shellescape(char_u *string, bool do_special, bool do_newline * Like vim_strsave(), but make all characters uppercase. * This uses ASCII lower-to-upper case translation, language independent. */ -char_u *vim_strsave_up(char_u *string) +char_u *vim_strsave_up(const char_u *string) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { char_u *p1; @@ -220,7 +223,8 @@ char_u *vim_strsave_up(char_u *string) * Like vim_strnsave(), but make all characters uppercase. * This uses ASCII lower-to-upper case translation, language independent. */ -char_u *vim_strnsave_up(char_u *string, int len) FUNC_ATTR_NONNULL_RET +char_u *vim_strnsave_up(const char_u *string, size_t len) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { char_u *p1 = vim_strnsave(string, len); vim_strup(p1); @@ -231,14 +235,15 @@ char_u *vim_strnsave_up(char_u *string, int len) FUNC_ATTR_NONNULL_RET * ASCII lower-to-upper case translation, language independent. */ void vim_strup(char_u *p) + FUNC_ATTR_NONNULL_ALL { char_u *p2; - int c; + char_u c; if (p != NULL) { p2 = p; while ((c = *p2) != NUL) - *p2++ = (c < 'a' || c > 'z') ? c : (c - 0x20); + *p2++ = (char_u)((c < 'a' || c > 'z') ? c : c - 0x20); } } @@ -246,7 +251,8 @@ 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(char_u *orig) +char_u *strup_save(const char_u *orig) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { char_u *res = vim_strsave(orig); @@ -264,8 +270,8 @@ char_u *strup_save(char_u *orig) int newl = utf_char2len(uc); if (newl != l) { // TODO(philix): use xrealloc() in strup_save() - char_u *s = xmalloc(STRLEN(res) + 1 + newl - l); - memmove(s, res, p - res); + 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); free(res); @@ -277,7 +283,7 @@ char_u *strup_save(char_u *orig) } else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) p += l; /* skip multi-byte character */ else { - *p = TOUPPER_LOC(*p); /* note that toupper() can be a macro */ + *p = (char_u) TOUPPER_LOC(*p); // note that toupper() can be a macro p++; } } @@ -289,6 +295,7 @@ char_u *strup_save(char_u *orig) * copy a space a number of times */ void copy_spaces(char_u *ptr, size_t count) + FUNC_ATTR_NONNULL_ALL { size_t i = count; char_u *p = ptr; @@ -301,7 +308,8 @@ void copy_spaces(char_u *ptr, size_t count) * Copy a character a number of times. * Does not work for multi-byte characters! */ -void copy_chars(char_u *ptr, size_t count, int c) +void copy_chars(char_u *ptr, size_t count, char_u c) + FUNC_ATTR_NONNULL_ALL { size_t i = count; char_u *p = ptr; @@ -314,6 +322,7 @@ void copy_chars(char_u *ptr, size_t count, int c) * delete spaces at the end of a string */ void del_trailing_spaces(char_u *ptr) + FUNC_ATTR_NONNULL_ALL { char_u *q; @@ -326,7 +335,8 @@ void del_trailing_spaces(char_u *ptr) * Like strncpy(), but always terminate the result with one NUL. * "to" must be "len + 1" long! */ -void vim_strncpy(char_u *to, char_u *from, size_t len) +void vim_strncpy(char_u *restrict to, const char_u *restrict from, size_t len) + FUNC_ATTR_NONNULL_ALL { STRNCPY(to, from, len); to[len] = NUL; @@ -336,13 +346,15 @@ void vim_strncpy(char_u *to, char_u *from, size_t len) * Like strcat(), but make sure the result fits in "tosize" bytes and is * always NUL terminated. */ -void vim_strcat(char_u *to, char_u *from, size_t tosize) +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) { - memmove(to + tolen, from, tosize - tolen - 1); + memcpy(to + tolen, from, tosize - tolen - 1); to[tosize - 1] = NUL; } else STRCPY(to + tolen, from); @@ -354,7 +366,8 @@ void vim_strcat(char_u *to, char_u *from, size_t tosize) * Doesn't work for multi-byte characters. * return 0 for match, < 0 for smaller, > 0 for bigger */ -int vim_stricmp(char *s1, char *s2) +int vim_stricmp(const char *s1, const char *s2) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE { int i; @@ -377,7 +390,8 @@ int vim_stricmp(char *s1, char *s2) * Doesn't work for multi-byte characters. * return 0 for match, < 0 for smaller, > 0 for bigger */ -int vim_strnicmp(char *s1, char *s2, size_t len) +int vim_strnicmp(const char *s1, const char *s2, size_t len) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE { int i; @@ -400,16 +414,16 @@ int vim_strnicmp(char *s1, char *s2, size_t len) * 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(char_u *string, int c) +char_u *vim_strchr(const char_u *string, int c) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE { - char_u *p; int b; - p = string; + const char_u *p = string; if (enc_utf8 && c >= 0x80) { while (*p != NUL) { if (utf_ptr2char(p) == c) - return p; + return (char_u *) p; p += (*mb_ptr2len)(p); } return NULL; @@ -420,7 +434,7 @@ char_u *vim_strchr(char_u *string, int c) c = ((unsigned)c >> 8) & 0xff; while ((b = *p) != NUL) { if (b == c && p[1] == n2) - return p; + return (char_u *) p; p += (*mb_ptr2len)(p); } return NULL; @@ -428,14 +442,14 @@ char_u *vim_strchr(char_u *string, int c) if (has_mbyte) { while ((b = *p) != NUL) { if (b == c) - return p; + return (char_u *) p; p += (*mb_ptr2len)(p); } return NULL; } while ((b = *p) != NUL) { if (b == c) - return p; + return (char_u *) p; ++p; } return NULL; @@ -446,13 +460,14 @@ char_u *vim_strchr(char_u *string, int c) * 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(char_u *string, int c) +char_u *vim_strbyte(const char_u *string, int c) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE { - char_u *p = string; + const char_u *p = string; while (*p != NUL) { if (*p == c) - return p; + return (char_u *) p; ++p; } return NULL; @@ -463,24 +478,26 @@ char_u *vim_strbyte(char_u *string, int c) * Return NULL if not found. * Does not handle multi-byte char for "c"! */ -char_u *vim_strrchr(char_u *string, int c) +char_u *vim_strrchr(const char_u *string, int c) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE { - char_u *retval = NULL; - char_u *p = string; + const char_u *retval = NULL; + const char_u *p = string; while (*p) { if (*p == c) retval = p; mb_ptr_adv(p); } - return retval; + return (char_u *) retval; } /* * Vim has its own isspace() function, because on some machines isspace() * can't handle characters above 128. */ -int vim_isspace(int x) +bool vim_isspace(int x) + FUNC_ATTR_CONST { return (x >= 9 && x <= 13) || x == ' '; } @@ -493,6 +510,7 @@ int vim_isspace(int x) # include "strings.c.generated.h" #endif static int sort_compare(const void *s1, const void *s2) + FUNC_ATTR_NONNULL_ALL { return STRCMP(*(char **)s1, *(char **)s2); } @@ -503,24 +521,26 @@ void sort_strings(char_u **files, int count) } /* - * Return TRUE if string "s" contains a non-ASCII character (128 or higher). - * When "s" is NULL FALSE is returned. + * Return true if string "s" contains a non-ASCII character (128 or higher). + * When "s" is NULL false is returned. */ -int has_non_ascii(char_u *s) +bool has_non_ascii(const char_u *s) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE { - char_u *p; + const char_u *p; if (s != NULL) for (p = s; *p != NUL; ++p) if (*p >= 128) - return TRUE; - return FALSE; + return true; + return false; } /* * Concatenate two strings and return the result in allocated memory. */ -char_u *concat_str(char_u *str1, char_u *str2) FUNC_ATTR_NONNULL_RET +char_u *concat_str(const char_u *restrict str1, const char_u *restrict str2) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { size_t l = STRLEN(str1); char_u *dest = xmalloc(l + STRLEN(str2) + 1); diff --git a/src/nvim/term.c b/src/nvim/term.c index 9da7e11b96..54508b1daa 100644 --- a/src/nvim/term.c +++ b/src/nvim/term.c @@ -43,6 +43,7 @@ #include "nvim/keymap.h" #include "nvim/memory.h" #include "nvim/move.h" +#include "nvim/mouse.h" #include "nvim/normal.h" #include "nvim/option.h" #include "nvim/os_unix.h" @@ -1472,7 +1473,7 @@ int set_termname(char_u *term) width = 80; height = 24; /* most terminals are 24 lines */ } - set_shellsize(width, height, FALSE); /* may change Rows */ + screen_resize(width, height, FALSE); /* may change Rows */ if (starting != NO_SCREEN) { if (scroll_region) scroll_region_reset(); /* In case Rows changed */ @@ -1506,7 +1507,6 @@ int set_termname(char_u *term) # define HMT_PTERM 8 # define HMT_URXVT 16 # define HMT_SGR 32 -static int has_mouse_termcode = 0; void set_mouse_termcode ( @@ -1517,16 +1517,6 @@ set_mouse_termcode ( char_u name[2] = { n, KE_FILLER }; add_termcode(name, s, FALSE); - if (n == KS_NETTERM_MOUSE) - has_mouse_termcode |= HMT_NETTERM; - else if (n == KS_DEC_MOUSE) - has_mouse_termcode |= HMT_DEC; - else if (n == KS_URXVT_MOUSE) - has_mouse_termcode |= HMT_URXVT; - else if (n == KS_SGR_MOUSE) - has_mouse_termcode |= HMT_SGR; - else - has_mouse_termcode |= HMT_NORMAL; } # if (defined(UNIX) && defined(FEAT_MOUSE_TTY)) || defined(PROTO) @@ -1538,16 +1528,6 @@ del_mouse_termcode ( char_u name[2] = { n, KE_FILLER }; del_termcode(name); - if (n == KS_NETTERM_MOUSE) - has_mouse_termcode &= ~HMT_NETTERM; - else if (n == KS_DEC_MOUSE) - has_mouse_termcode &= ~HMT_DEC; - else if (n == KS_URXVT_MOUSE) - has_mouse_termcode &= ~HMT_URXVT; - else if (n == KS_SGR_MOUSE) - has_mouse_termcode &= ~HMT_SGR; - else - has_mouse_termcode &= ~HMT_NORMAL; } # endif @@ -1865,7 +1845,7 @@ void term_write(char_u *s, size_t len) #ifdef UNIX if (p_wd) { // Unix is too fast, slow down a bit more - os_microdelay(p_wd, false); + os_microdelay(p_wd); } #endif } @@ -2289,7 +2269,7 @@ void win_new_shellsize(void) */ void shell_resized(void) { - set_shellsize(0, 0, FALSE); + screen_resize(0, 0, FALSE); } /* @@ -2311,102 +2291,6 @@ void shell_resized_check(void) } /* - * 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'. - */ -void set_shellsize(int width, int height, int mustset) -{ - static int busy = FALSE; - - /* - * Avoid recursiveness, can happen when setting the window size causes - * another window-changed signal. - */ - if (busy) - return; - - if (width < 0 || height < 0) /* just checking... */ - return; - - if (State == HITRETURN || State == SETWSIZE) { - /* postpone the resizing */ - State = SETWSIZE; - return; - } - - /* curwin->w_buffer can be NULL when we are closing a window and the - * buffer has already been closed and removing a scrollbar causes a resize - * event. Don't resize then, it will happen after entering another buffer. - */ - if (curwin->w_buffer == NULL) - return; - - ++busy; - - - if (mustset || (ui_get_shellsize() == FAIL && height != 0)) { - Rows = height; - Columns = width; - check_shellsize(); - mch_set_shellsize(); - } else - check_shellsize(); - - /* The window layout used to be adjusted here, but it now happens in - * screenalloc() (also invoked from screenclear()). That is because the - * "busy" check above may skip this, but not screenalloc(). */ - - if (State != ASKMORE && State != EXTERNCMD && State != CONFIRM) - screenclear(); - else - screen_start(); /* don't know where cursor is now */ - - if (starting != NO_SCREEN) { - maketitle(); - changed_line_abv_curs(); - invalidate_botline(); - - /* - * We only redraw when it's needed: - * - While at the more prompt or executing an external command, don't - * redraw, but position the cursor. - * - While editing the command line, only redraw that. - * - in Ex mode, don't redraw anything. - * - Otherwise, redraw right now, and position the cursor. - * Always need to call update_screen() or screenalloc(), to make - * sure Rows/Columns and the size of ScreenLines[] is correct! - */ - if (State == ASKMORE || State == EXTERNCMD || State == CONFIRM - || exmode_active) { - screenalloc(false); - repeat_message(); - } else { - if (curwin->w_p_scb) - do_check_scrollbind(TRUE); - if (State & CMDLINE) { - update_screen(NOT_VALID); - redrawcmdline(); - } else { - update_topline(); - if (pum_visible()) { - redraw_later(NOT_VALID); - ins_compl_show_pum(); /* This includes the redraw. */ - } else - update_screen(NOT_VALID); - if (redrawing()) - setcursor(); - } - } - cursor_on(); /* redrawing may have switched it off */ - } - out_flush(); - --busy; -} - -/* * Set the terminal to TMODE_RAW (for Normal mode) or TMODE_COOK (for external * commands and Ex mode). */ @@ -2641,73 +2525,6 @@ int swapping_screen(void) } /* - * setmouse() - switch mouse on/off depending on current mode and 'mouse' - */ -void setmouse(void) -{ - int checkfor; - - - /* be quick when mouse is off */ - if (*p_mouse == NUL || has_mouse_termcode == 0) - return; - - /* don't switch mouse on when not in raw mode (Ex mode) */ - if (cur_tmode != TMODE_RAW) { - mch_setmouse(FALSE); - return; - } - - if (VIsual_active) - checkfor = MOUSE_VISUAL; - else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE) - checkfor = MOUSE_RETURN; - else if (State & INSERT) - checkfor = MOUSE_INSERT; - else if (State & CMDLINE) - checkfor = MOUSE_COMMAND; - else if (State == CONFIRM || State == EXTERNCMD) - checkfor = ' '; /* don't use mouse for ":confirm" or ":!cmd" */ - else - checkfor = MOUSE_NORMAL; /* assume normal mode */ - - if (mouse_has(checkfor)) - mch_setmouse(TRUE); - else - mch_setmouse(FALSE); -} - -/* - * Return TRUE if - * - "c" is in 'mouse', or - * - 'a' is in 'mouse' and "c" is in MOUSE_A, or - * - the current buffer is a help file and 'h' is in 'mouse' and we are in a - * normal editing mode (not at hit-return message). - */ -int mouse_has(int c) -{ - for (char_u *p = p_mouse; *p; ++p) - switch (*p) { - case 'a': if (vim_strchr((char_u *)MOUSE_A, c) != NULL) - return TRUE; - break; - case MOUSE_HELP: if (c != MOUSE_RETURN && curbuf->b_help) - return TRUE; - break; - default: if (c == *p) return TRUE; break; - } - return FALSE; -} - -/* - * Return TRUE when 'mousemodel' is set to "popup" or "popup_setpos". - */ -int mouse_model_popup(void) -{ - return p_mousem[0] == 'p'; -} - -/* * By outputting the 'cursor very visible' termcap code, for some windowed * terminals this makes the screen scrolled to the correct position. * Used when starting Vim or returning from a shell. @@ -3002,11 +2819,9 @@ static void switch_to_8bit(void) LOG_TR("Switching to 8 bit"); } -#ifdef CHECK_DOUBLE_CLICK static linenr_T orig_topline = 0; static int orig_topfill = 0; -#endif -#if defined(CHECK_DOUBLE_CLICK) || defined(PROTO) + /* * Checking for double clicks ourselves. * "orig_topline" is used to avoid detecting a double-click when the window @@ -3021,7 +2836,6 @@ void set_mouse_topline(win_T *wp) orig_topline = wp->w_topline; orig_topfill = wp->w_topfill; } -#endif /* * Check if typebuf.tb_buf[] contains a terminal key code. @@ -3712,7 +3526,6 @@ int check_termcode(int max_offset, char_u *buf, int bufsize, int *buflen) is_drag = TRUE; current_button = held_button; } else if (wheel_code == 0) { -# ifdef CHECK_DOUBLE_CLICK { static int orig_mouse_col = 0; static int orig_mouse_row = 0; @@ -3746,9 +3559,6 @@ int check_termcode(int max_offset, char_u *buf, int bufsize, int *buflen) orig_topline = curwin->w_topline; orig_topfill = curwin->w_topfill; } -# else - orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code); -# endif is_click = TRUE; orig_mouse_code = mouse_code; } diff --git a/src/nvim/term.h b/src/nvim/term.h index 17154b8c26..3f70f484a7 100644 --- a/src/nvim/term.h +++ b/src/nvim/term.h @@ -52,10 +52,6 @@ * 128 = 16384 columns, now it's reduced to 10000. */ #define MOUSE_COLOFF 10000 -#if defined(UNIX) -# define CHECK_DOUBLE_CLICK 1 /* Checking for double clicks ourselves. */ -#endif - #ifdef INCLUDE_GENERATED_DECLARATIONS # include "term.h.generated.h" #endif diff --git a/src/nvim/window.c b/src/nvim/window.c index 315d5f07de..bd461a873f 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -41,6 +41,7 @@ #include "nvim/file_search.h" #include "nvim/garray.h" #include "nvim/move.h" +#include "nvim/mouse.h" #include "nvim/normal.h" #include "nvim/option.h" #include "nvim/os_unix.h" diff --git a/test/functional/shell/viml_system_spec.lua b/test/functional/shell/viml_system_spec.lua index 8d212c1375..48dc518d7b 100644 --- a/test/functional/shell/viml_system_spec.lua +++ b/test/functional/shell/viml_system_spec.lua @@ -188,6 +188,28 @@ describe('systemlist()', function() end) end) + describe('handles empty lines', function() + it('in the middle', function() + eq({'line one','','line two'}, eval("systemlist('cat',['line one','','line two'])")) + end) + + it('in the beginning', function() + eq({'','line one','line two'}, eval("systemlist('cat',['','line one','line two'])")) + end) + end) + + describe('when keepempty option is', function() + it('0, ignores trailing newline', function() + eq({'aa','bb'}, eval("systemlist('cat',['aa','bb'],0)")) + eq({'aa','bb'}, eval("systemlist('cat',['aa','bb',''],0)")) + end) + + it('1, preserves trailing newline', function() + eq({'aa','bb'}, eval("systemlist('cat',['aa','bb'],1)")) + eq({'aa','bb',''}, eval("systemlist('cat',['aa','bb',''],2)")) + end) + end) + if xclip then describe("with a program that doesn't close stdout", function() it('will exit properly after passing input', function() diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index 83c2cfdc61..7d86382d34 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -15,6 +15,9 @@ set(DEPS_DOWNLOAD_DIR "${DEPS_BUILD_DIR}/downloads") option(USE_BUNDLED "Use bundled dependencies." ON) +option(USE_BUNDLED_LIBUNIBILIUM "Use the bundled libunibilium." ${USE_BUNDLED}) +option(USE_BUNDLED_LIBTERMKEY "Use the bundled libtermkey." ${USE_BUNDLED}) +option(USE_BUNDLED_LIBTICKIT "Use the bundled libtickit." ${USE_BUNDLED}) option(USE_BUNDLED_LIBUV "Use the bundled libuv." ${USE_BUNDLED}) option(USE_BUNDLED_MSGPACK "Use the bundled msgpack." ${USE_BUNDLED}) option(USE_BUNDLED_LUAJIT "Use the bundled version of luajit." ${USE_BUNDLED}) @@ -51,9 +54,9 @@ endif() include(ExternalProject) -set(LIBUV_URL https://github.com/libuv/libuv/archive/v0.11.28.tar.gz) -set(LIBUV_SHA1 3b70b65467ee693228b8b8385665a52690d74092) -set(LIBUV_MD5 1a849ba4fc571d531482ed74bc7aabc4) +set(LIBUV_URL https://github.com/libuv/libuv/archive/v1.0.1.tar.gz) +set(LIBUV_SHA1 be4edcca18a518153b5e249a17621f2674d7654d) +set(LIBUV_MD5 c5e4bbf954b8438c57d9414ee54b4d90) set(MSGPACK_URL https://github.com/msgpack/msgpack-c/archive/ecf4b09acd29746829b6a02939db91dfdec635b4.tar.gz) set(MSGPACK_SHA1 c160ff99f20d9d0a25bea0a57f4452f1c9bde370) @@ -67,6 +70,90 @@ set(LUAROCKS_URL https://github.com/keplerproject/luarocks/archive/0587afbb5fe8c set(LUAROCKS_SHA1 61a894fd5d61987bf7e7f9c3e0c5de16ba4b68c4) set(LUAROCKS_MD5 0f53f42909fbcd2c88be303e8f970516) +set(LIBUNIBILIUM_URL https://github.com/neovim/unibilium/archive/neovim.tar.gz) +set(LIBUNIBILIUM_SHA1 5d3d4913dd267b14f81fc665e0fa20661d3cb817) +set(LIBUNIBILIUM_MD5 0657a906164529f1e0f60aba3b876f23) + +set(LIBTERMKEY_URL https://github.com/neovim/libtermkey/archive/neovim.tar.gz) +set(LIBTERMKEY_SHA1 a309038a2297fe4905f03a8807723a9aa07c272a) +set(LIBTERMKEY_MD5 c99e5546da0063fa26dfa7d7f1d5a26f) + +set(LIBTICKIT_URL https://github.com/neovim/libtickit/archive/neovim.tar.gz) +set(LIBTICKIT_SHA1 49e609de29c3bdc3b40d2ade76e69fde6e0d74bc) +set(LIBTICKIT_MD5 71a5d36d0ef6688d79828aabaf27eb36) + +if(USE_BUNDLED_LIBUNIBILIUM) + ExternalProject_Add(libunibilium + PREFIX ${DEPS_BUILD_DIR} + URL ${LIBUNIBILIUM_URL} + DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libunibilium + DOWNLOAD_COMMAND ${CMAKE_COMMAND} + -DPREFIX=${DEPS_BUILD_DIR} + -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/libunibilium + -DURL=${LIBUNIBILIUM_URL} + -DEXPECTED_SHA1=${LIBUNIBILIUM_SHA1} + -DEXPECTED_MD5=${LIBUNIBILIUM_MD5} + -DTARGET=libunibilium + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake + CONFIGURE_COMMAND "" + BUILD_IN_SOURCE 1 + BUILD_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER} + PREFIX=${DEPS_INSTALL_DIR} + CFLAGS=-fPIC + INSTALL_COMMAND ${MAKE_PRG} PREFIX=${DEPS_INSTALL_DIR} install) + list(APPEND THIRD_PARTY_DEPS libunibilium) +endif() + +if(USE_BUNDLED_LIBTERMKEY) + ExternalProject_Add(libtermkey + PREFIX ${DEPS_BUILD_DIR} + URL ${LIBTERMKEY_URL} + DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libtermkey + DOWNLOAD_COMMAND ${CMAKE_COMMAND} + -DPREFIX=${DEPS_BUILD_DIR} + -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/libtermkey + -DURL=${LIBTERMKEY_URL} + -DEXPECTED_SHA1=${LIBTERMKEY_SHA1} + -DEXPECTED_MD5=${LIBTERMKEY_MD5} + -DTARGET=libtermkey + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake + CONFIGURE_COMMAND "" + BUILD_IN_SOURCE 1 + BUILD_COMMAND "" + INSTALL_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER} + PREFIX=${DEPS_INSTALL_DIR} + PKG_CONFIG_PATH=${DEPS_LIB_DIR}/pkgconfig + CFLAGS=-fPIC + install) + list(APPEND THIRD_PARTY_DEPS libtermkey) + add_dependencies(libtermkey libunibilium) +endif() + +if(USE_BUNDLED_LIBTICKIT) + ExternalProject_Add(libtickit + PREFIX ${DEPS_BUILD_DIR} + URL ${LIBTICKIT_URL} + DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libtickit + DOWNLOAD_COMMAND ${CMAKE_COMMAND} + -DPREFIX=${DEPS_BUILD_DIR} + -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/libtickit + -DURL=${LIBTICKIT_URL} + -DEXPECTED_SHA1=${LIBTICKIT_SHA1} + -DEXPECTED_MD5=${LIBTICKIT_MD5} + -DTARGET=libtickit + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake + CONFIGURE_COMMAND "" + BUILD_IN_SOURCE 1 + BUILD_COMMAND "" + INSTALL_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER} + PREFIX=${DEPS_INSTALL_DIR} + PKG_CONFIG_PATH=${DEPS_LIB_DIR}/pkgconfig + CFLAGS=-fPIC + install) + list(APPEND THIRD_PARTY_DEPS libtickit) + add_dependencies(libtickit libtermkey) +endif() + if(USE_BUNDLED_LIBUV) ExternalProject_Add(libuv PREFIX ${DEPS_BUILD_DIR} |