diff options
48 files changed, 3096 insertions, 2440 deletions
diff --git a/.gitattributes b/.gitattributes index 1deb4dea49..e09a918303 100755 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,6 @@ *.h linguist-language=C src/nvim/testdir/test42.in diff .github/ export-ignore -ci/ export-ignore .travis.yml export-ignore codecov.yml export-ignore .builds/ export-ignore diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 88d2989f13..fe3540f1f6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -161,7 +161,7 @@ see potential bugs found by [PVS Studio](https://www.viva64.com/en/pvs-studio/). - Use this format for commit messages (where `{id}` is the PVS warning-id)): ``` - PVS/V{id}: {description} + fix(PVS/V{id}): {description} ``` - Search the Neovim commit history to find examples: ``` @@ -177,7 +177,7 @@ master build. To view the defects, just request access; you will be approved. - Use this format for commit messages (where `{id}` is the CID (Coverity ID); ([example](https://github.com/neovim/neovim/pull/804))): ``` - coverity/{id}: {description} + fix(coverity/{id}): {description} ``` - Search the Neovim commit history to find examples: ``` @@ -220,10 +220,11 @@ You can lint a single file (but this will _not_ exclude legacy errors): - Style rules are (mostly) defined by `src/uncrustify.cfg` which tries to match the [style-guide]. To use the Nvim `gq` command with `uncrustify`: ``` - if !empty(findfile('src/.uncrustify', ';')) - setlocal formatprg=uncrustify\ -q\ -c\ src/uncrustify.cfg\ --replace\ --no-backup + if !empty(findfile('src/uncrustify.cfg', ';')) + setlocal formatprg=uncrustify\ -q\ -l\ C\ -c\ src/uncrustify.cfg\ --no-backup endif ``` + The required version of `uncrustify` is specified in `uncrustify.cfg`. - There is also `.clang-format` which has drifted from the [style-guide], but is available for reference. To use the Nvim `gq` command with `clang-format`: ``` diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt index 679bb2f7ff..276571d042 100644 --- a/runtime/doc/diagnostic.txt +++ b/runtime/doc/diagnostic.txt @@ -201,7 +201,52 @@ DiagnosticsChanged After diagnostics have changed. Example: > autocmd User DiagnosticsChanged lua vim.diagnostic.setqflist({open = false }) < - +============================================================================== +CUSTOMIZATION *diagnostic-config* + +If you need more customization over the way diagnostics are displayed than the +built-in configuration options provide, you can override the display handler +explicitly. For example, use the following to only show a sign for the highest +severity diagnostic on a given line: > + + -- Disable the default signs handler + vim.diagnostic.config({signs = false}) + + -- Create a namespace. This won't be used to add any diagnostics, + -- only to display them. + local ns = vim.api.nvim_create_namespace("my_namespace") + + -- Create a reference to the original function + local orig_show = vim.diagnostic.show + + local function set_signs(bufnr) + -- Get all diagnostics from the current buffer + local diagnostics = vim.diagnostic.get(bufnr) + + -- Find the "worst" diagnostic per line + local max_severity_per_line = {} + for _, d in pairs(diagnostics) do + local m = max_severity_per_line[d.lnum] + if not m or d.severity < m.severity then + max_severity_per_line[d.lnum] = d + end + end + + -- Show the filtered diagnostics using the custom namespace. Use the + -- reference to the original function to avoid a loop. + local filtered_diagnostics = vim.tbl_values(max_severity_per_line) + orig_show(ns, bufnr, filtered_diagnostics, { + virtual_text=false, + underline=false, + signs=true + }) + end + + function vim.diagnostic.show(namespace, bufnr, ...) + orig_show(namespace, bufnr, ...) + set_signs(bufnr) + end +< ============================================================================== Lua module: vim.diagnostic *diagnostic-api* @@ -253,6 +298,12 @@ config({opts}, {namespace}) *vim.diagnostic.config()* • severity: Only show signs for diagnostics matching the given severity |diagnostic-severity| + • priority: (number, default 10) Base + priority to use for signs. When + {severity_sort} is used, the priority of + a sign is adjusted based on its severity. + Otherwise, all signs use the same + priority. • update_in_insert: (default false) Update diagnostics in Insert mode (if false, diff --git a/runtime/doc/helphelp.txt b/runtime/doc/helphelp.txt index 4a94701b2e..aaa2a35fe1 100644 --- a/runtime/doc/helphelp.txt +++ b/runtime/doc/helphelp.txt @@ -389,17 +389,5 @@ highlighting. So do these: You can find the details in $VIMRUNTIME/syntax/help.vim - *inclusion* -Vim is for everybody, no matter race, gender or anything. Some people make a -big deal about using "he" or "his" when referring to the user, thinking it -means we assume the user is male. That is not the case, it's just a habit of -writing help text, which quite often is many years old. Also, a lot of the -text is written by contributors for whom English is not their first language. -We do not make any assumptions about the gender of the user, no matter how the -text is phrased. Some people have suggested using "they", but that is not -regular English. We do not want to spend much time on this discussion. The -goal is that the reader understands how Vim works, the exact wording is -secondary. - vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/filetype.vim b/runtime/filetype.vim index bc3965d4b6..5e0c6fb32e 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1136,6 +1136,9 @@ au BufNewFile,BufRead Neomuttrc setf neomuttrc " Netrc au BufNewFile,BufRead .netrc setf netrc +" Nginx +au BufNewFile,BufRead *.nginx,nginx*.conf,*nginx.conf,*/etc/nginx/*,*/usr/local/nginx/conf/*,*/nginx/*.conf setf nginx + " Ninja file au BufNewFile,BufRead *.ninja setf ninja diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 00945a7fb3..c7c8c1878e 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -556,6 +556,9 @@ end --- - signs: (default true) Use signs for diagnostics. Options: --- * severity: Only show signs for diagnostics matching the given severity --- |diagnostic-severity| +--- * priority: (number, default 10) Base priority to use for signs. When +--- {severity_sort} is used, the priority of a sign is adjusted based on +--- its severity. Otherwise, all signs use the same priority. --- - update_in_insert: (default false) Update diagnostics in Insert mode (if false, --- diagnostics are updated on InsertLeave) --- - severity_sort: (default false) Sort diagnostics by severity. This affects the order in @@ -617,23 +620,22 @@ function M.set(namespace, bufnr, diagnostics, opts) } if vim.tbl_isempty(diagnostics) then - return M.reset(namespace, bufnr) - end - - if not diagnostic_cleanup[bufnr][namespace] then - diagnostic_cleanup[bufnr][namespace] = true - - -- Clean up our data when the buffer unloads. - vim.api.nvim_buf_attach(bufnr, false, { - on_detach = function(_, b) - clear_diagnostic_cache(b, namespace) - diagnostic_cleanup[b][namespace] = nil - end - }) + clear_diagnostic_cache(namespace, bufnr) + else + if not diagnostic_cleanup[bufnr][namespace] then + diagnostic_cleanup[bufnr][namespace] = true + + -- Clean up our data when the buffer unloads. + vim.api.nvim_buf_attach(bufnr, false, { + on_detach = function(_, b) + clear_diagnostic_cache(b, namespace) + diagnostic_cleanup[b][namespace] = nil + end + }) + end + set_diagnostic_cache(namespace, bufnr, diagnostics) end - set_diagnostic_cache(namespace, bufnr, diagnostics) - if vim.api.nvim_buf_is_loaded(bufnr) then M.show(namespace, bufnr, diagnostics, opts) elseif opts then @@ -643,6 +645,13 @@ function M.set(namespace, bufnr, diagnostics, opts) vim.api.nvim_command("doautocmd <nomodeline> User DiagnosticsChanged") end +--- Get current diagnostic namespaces. +--- +---@return table A list of active diagnostic namespaces |vim.diagnostic|. +function M.get_namespaces() + return vim.deepcopy(all_namespaces) +end + --- Get current diagnostics. --- ---@param bufnr number|nil Buffer number to get diagnostics from. Use 0 for diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index e95f170427..fca956fb57 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -951,6 +951,11 @@ end ---@param width (number) window width (in character cells) ---@param height (number) window height (in character cells) ---@param opts (table, optional) +--- - offset_x (number) offset to add to `col` +--- - offset_y (number) offset to add to `row` +--- - border (string or table) override `border` +--- - focusable (string or table) override `focusable` +--- - zindex (string or table) override `zindex`, defaults to 50 ---@returns (table) Options function M.make_floating_popup_options(width, height, opts) validate { @@ -975,7 +980,7 @@ function M.make_floating_popup_options(width, height, opts) else anchor = anchor..'S' height = math.min(lines_above, height) - row = -get_border_size(opts).height + row = 0 end if vim.fn.wincol() + width + (opts.offset_x or 0) <= api.nvim_get_option('columns') then @@ -1124,8 +1129,6 @@ end --- - wrap_at character to wrap at for computing height --- - max_width maximal width of floating window --- - max_height maximal height of floating window ---- - pad_left number of columns to pad contents at left ---- - pad_right number of columns to pad contents at right --- - pad_top number of lines to pad contents at top --- - pad_bottom number of lines to pad contents at bottom --- - separator insert separator after code block @@ -1376,8 +1379,6 @@ end --- - wrap_at character to wrap at for computing height when wrap is enabled --- - max_width maximal width of floating window --- - max_height maximal height of floating window ---- - pad_left number of columns to pad contents at left ---- - pad_right number of columns to pad contents at right --- - pad_top number of lines to pad contents at top --- - pad_bottom number of lines to pad contents at bottom --- - focus_id if a popup with this id is opened, then focus it diff --git a/scripts/release.sh b/scripts/release.sh index 4ec959d697..380503662d 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -80,8 +80,8 @@ _do_release_commit() { _do_bump_commit() { $__sed -i.bk 's/(NVIM_VERSION_PRERELEASE) ""/\1 "-dev"/' CMakeLists.txt $__sed -i.bk 's/set\((NVIM_VERSION_PATCH) [[:digit:]]/set(\1 ?/' CMakeLists.txt - rm CMakeLists.txt.bk - rm runtime/nvim.appdata.xml.bk + rm -f CMakeLists.txt.bk + rm -f runtime/nvim.appdata.xml.bk nvim +'/NVIM_VERSION' +1new +'exe "norm! iUpdate version numbers!!!"' \ -O CMakeLists.txt diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index f4b817dfff..d92480abb9 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -125,8 +125,12 @@ commit_message() { } find_git_remote() { - git_remote=$(git remote -v \ - | awk '$2 ~ /github.com[:\/]neovim\/neovim/ && $3 == "(fetch)" {print $1; exit}') + local git_remote + if [[ "${1-}" == fork ]]; then + git_remote=$(git remote -v | awk '$2 !~ /github.com[:\/]neovim\/neovim/ && $3 == "(fetch)" {print $1; exit}') + else + git_remote=$(git remote -v | awk '$2 ~ /github.com[:\/]neovim\/neovim/ && $3 == "(fetch)" {print $1; exit}') + fi if [[ -z "$git_remote" ]]; then git_remote="origin" fi @@ -268,8 +272,8 @@ stage_patch() { get_vimpatch "$1" local try_apply="${2:-}" - local git_remote - git_remote="$(find_git_remote)" + local nvim_remote + nvim_remote="$(find_git_remote)" local checked_out_branch checked_out_branch="$(git rev-parse --abbrev-ref HEAD)" @@ -277,16 +281,16 @@ stage_patch() { msg_ok "Current branch '${checked_out_branch}' seems to be a vim-patch" echo " branch; not creating a new branch." else - printf '\nFetching "%s/master".\n' "${git_remote}" - output="$(git fetch "${git_remote}" master 2>&1)" && + printf '\nFetching "%s/master".\n' "${nvim_remote}" + output="$(git fetch "${nvim_remote}" master 2>&1)" && msg_ok "${output}" || (msg_err "${output}"; false) local nvim_branch="${BRANCH_PREFIX}${vim_version}" echo - echo "Creating new branch '${nvim_branch}' based on '${git_remote}/master'." + echo "Creating new branch '${nvim_branch}' based on '${nvim_remote}/master'." cd "${NVIM_SOURCE_DIR}" - output="$(git checkout -b "${nvim_branch}" "${git_remote}/master" 2>&1)" && + output="$(git checkout -b "${nvim_branch}" "${nvim_remote}/master" 2>&1)" && msg_ok "${output}" || (msg_err "${output}"; false) fi @@ -362,13 +366,13 @@ submit_pr() { exit 1 fi - local git_remote - git_remote="$(find_git_remote)" + local nvim_remote + nvim_remote="$(find_git_remote)" local pr_body - pr_body="$(git log --grep=vim-patch --reverse --format='#### %s%n%n%b%n' "${git_remote}"/master..HEAD)" + pr_body="$(git log --grep=vim-patch --reverse --format='#### %s%n%n%b%n' "${nvim_remote}"/master..HEAD)" local patches # Extract just the "vim-patch:X.Y.ZZZZ" or "vim-patch:sha" portion of each log - patches=("$(git log --grep=vim-patch --reverse --format='%s' "${git_remote}"/master..HEAD | sed 's/: .*//')") + patches=("$(git log --grep=vim-patch --reverse --format='%s' "${nvim_remote}"/master..HEAD | sed 's/: .*//')") # shellcheck disable=SC2206 patches=(${patches[@]//vim-patch:}) # Remove 'vim-patch:' prefix for each item in array. local pr_title="${patches[*]}" # Create space-separated string from array. @@ -376,8 +380,19 @@ submit_pr() { pr_title="$(printf 'vim-patch:%s' "${pr_title#,}")" if [[ $push_first -ne 0 ]]; then - echo "Pushing to 'origin/${checked_out_branch}'." - output="$(git push origin "${checked_out_branch}" 2>&1)" && + local push_remote + push_remote="$(git config --get branch."${checked_out_branch}".pushRemote || true)" + if [[ -z "$push_remote" ]]; then + push_remote="$(git config --get remote.pushDefault || true)" + if [[ -z "$push_remote" ]]; then + push_remote="$(git config --get branch."${checked_out_branch}".remote || true)" + if [[ -z "$push_remote" ]] || [[ "$push_remote" == "$nvim_remote" ]]; then + push_remote="$(find_git_remote fork)" + fi + fi + fi + echo "Pushing to '${push_remote}/${checked_out_branch}'." + output="$(git push "${push_remote}" "${checked_out_branch}" 2>&1)" && msg_ok "${output}" || (msg_err "${output}"; false) diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 6a0a4c4e0a..f80d605d9a 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1360,7 +1360,9 @@ void nvim_chan_send(Integer chan, String data, Error *err) /// - `bufpos`: Places float relative to buffer text (only when /// relative="win"). Takes a tuple of zero-indexed [line, column]. /// `row` and `col` if given are applied relative to this -/// position, else they default to `row=1` and `col=0` +/// position, else they default to: +/// - `row=1` and `col=0` if `anchor` is "NW" or "NE" +/// - `row=0` and `col=0` if `anchor` is "SW" or "SE" /// (thus like a tooltip near the buffer text). /// - `row`: Row position in units of "screen cell height", may be fractional. /// - `col`: Column position in units of "screen cell width", may be @@ -1437,13 +1439,14 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dict(float_config) *config, E if (enter) { win_enter(wp, false); } + // autocmds in win_enter or win_set_buf below may close the window + if (win_valid(wp) && buffer > 0) { + win_set_buf(wp->handle, buffer, fconfig.noautocmd, err); + } if (!win_valid(wp)) { api_set_error(err, kErrorTypeException, "Window was closed immediately"); return 0; } - if (buffer > 0) { - win_set_buf(wp->handle, buffer, fconfig.noautocmd, err); - } if (fconfig.style == kWinStyleMinimal) { win_set_minimal_style(wp); diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index e7b2ad9000..d991b88131 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -199,7 +199,7 @@ static void au_cleanup(void) } // Loop over all events. - for (event = (event_T)0; (int)event < (int)NUM_EVENTS; + for (event = (event_T)0; (int)event < NUM_EVENTS; event = (event_T)((int)event + 1)) { // Loop over all autocommand patterns. prev_ap = &(first_autopat[(int)event]); @@ -266,7 +266,7 @@ void aubuflocal_remove(buf_T *buf) } // invalidate buflocals looping through events - for (event = (event_T)0; (int)event < (int)NUM_EVENTS; + for (event = (event_T)0; (int)event < NUM_EVENTS; event = (event_T)((int)event + 1)) { // loop over all autocommand patterns for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next) { @@ -321,7 +321,7 @@ static void au_del_group(char_u *name) AutoPat *ap; int in_use = false; - for (event = (event_T)0; (int)event < (int)NUM_EVENTS; + for (event = (event_T)0; (int)event < 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) { @@ -475,7 +475,7 @@ static char_u *find_end_event(char_u *arg, int have_group) pat = arg + 1; } else { for (pat = arg; *pat && *pat != '|' && !ascii_iswhite(*pat); pat = p) { - if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS) { + if ((int)event_name2nr(pat, &p) >= NUM_EVENTS) { if (have_group) { EMSG2(_("E216: No such event: %s"), pat); } else { @@ -701,7 +701,7 @@ void do_autocmd(char_u *arg_in, int forceit) if (!forceit && *cmd != NUL) { EMSG(_(e_cannot_define_autocommands_for_all_events)); } else { - for (event_T event = (event_T)0; event < (int)NUM_EVENTS; + for (event_T event = (event_T)0; event < NUM_EVENTS; event = (event_T)(event + 1)) { if (do_autocmd_event(event, pat, once, nested, cmd, forceit, group) == FAIL) { diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 3c86f55260..20dd94622f 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -117,7 +117,7 @@ static int read_buffer(int read_stdin, exarg_T *eap, int flags) 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, + line_count, (linenr_T)0, (linenr_T)MAXLNUM, eap, flags | READ_BUFFER); if (retval == OK) { // Delete the binary lines. diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c index 0ddf163176..58b1d9ce7f 100644 --- a/src/nvim/debugger.c +++ b/src/nvim/debugger.c @@ -398,7 +398,7 @@ void dbg_check_breakpoint(exarg_T *eap) // replace K_SNR with "<SNR>" if (debug_breakpoint_name[0] == K_SPECIAL && debug_breakpoint_name[1] == KS_EXTRA - && debug_breakpoint_name[2] == (int)KE_SNR) { + && debug_breakpoint_name[2] == KE_SNR) { p = (char_u *)"<SNR>"; } else { p = (char_u *)""; diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index 561be9968a..4e80528c74 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -421,11 +421,11 @@ int decor_virtual_lines(win_T *wp, linenr_T lnum) return 0; } if (buf->b_virt_line_pos < 0) { - mtpos_t pos = marktree_lookup(buf->b_marktree, buf->b_virt_line_mark, NULL); - if (pos.row < 0) { - buf->b_virt_line_mark = 0; - } - buf->b_virt_line_pos = pos.row + (buf->b_virt_line_above ? 0 : 1); + mtpos_t pos = marktree_lookup(buf->b_marktree, buf->b_virt_line_mark, NULL); + if (pos.row < 0) { + buf->b_virt_line_mark = 0; + } + buf->b_virt_line_pos = pos.row + (buf->b_virt_line_above ? 0 : 1); } return (lnum-1 == buf->b_virt_line_pos) ? (int)kv_size(buf->b_virt_lines) : 0; diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index beb4ff4da6..15acd73aa5 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -1000,6 +1000,18 @@ void ins_char_typebuf(int c) buf[3] = NUL; } else { buf[utf_char2bytes(c, buf)] = NUL; + char_u *p = buf; + while (*p) { + if ((uint8_t)(*p) == CSI || (uint8_t)(*p) == K_SPECIAL) { + bool is_csi = (uint8_t)(*p) == CSI; + memmove(p + 3, p + 1, STRLEN(p + 1) + 1); + *p++ = K_SPECIAL; + *p++ = is_csi ? KS_EXTRA : KS_SPECIAL; + *p++ = is_csi ? KE_CSI : KE_FILLER; + } else { + p++; + } + } } (void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent); } @@ -1558,7 +1570,7 @@ int vgetc(void) // a CSI (0x9B), // of a K_SPECIAL - KS_EXTRA - KE_CSI, which is CSI too. c = vgetorpeek(true); - if (vgetorpeek(true) == (int)KE_CSI && c == KS_EXTRA) { + if (vgetorpeek(true) == KE_CSI && c == KS_EXTRA) { buf[i] = CSI; } } @@ -1573,9 +1585,9 @@ int vgetc(void) if (!no_mapping && KeyTyped && (mod_mask == MOD_MASK_ALT || mod_mask == MOD_MASK_META)) { mod_mask = 0; - stuffcharReadbuff(c); - u_sync(false); - c = ESC; + ins_char_typebuf(c); + ins_char_typebuf(ESC); + continue; } break; @@ -1934,7 +1946,7 @@ static int vgetorpeek(bool advance) && (mp->m_keys[0] != K_SPECIAL || mp->m_keys[1] != KS_EXTRA || mp->m_keys[2] - != (int)KE_SNR)) { + != KE_SNR)) { continue; } /* @@ -2216,7 +2228,7 @@ static int vgetorpeek(bool advance) if (!ascii_iswhite(ptr[col])) { curwin->w_wcol = vcol; } - vcol += lbr_chartabsize(ptr, ptr + col, (colnr_T)vcol); + vcol += lbr_chartabsize(ptr, ptr + col, vcol); col += utfc_ptr2len(ptr + col); } curwin->w_wrow = curwin->w_cline_row diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c index df2c494ace..9d9ffa550a 100644 --- a/src/nvim/hardcopy.c +++ b/src/nvim/hardcopy.c @@ -643,12 +643,8 @@ void ex_hardcopy(exarg_T *eap) * PS.) */ if (mch_print_init(&settings, - curbuf->b_fname == NULL - ? (char_u *)buf_spname(curbuf) - : curbuf->b_sfname == NULL - ? curbuf->b_fname - : curbuf->b_sfname, - eap->forceit) == FAIL) { + curbuf->b_fname == NULL ? buf_spname(curbuf) : curbuf->b_sfname == + NULL ? curbuf->b_fname : curbuf->b_sfname, eap->forceit) == FAIL) { return; } diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c index 31615e744a..76dcb58236 100644 --- a/src/nvim/if_cscope.c +++ b/src/nvim/if_cscope.c @@ -9,31 +9,29 @@ * might be a few lines of code that look similar to what Nvi has. */ -#include <stdbool.h> - #include <assert.h> #include <errno.h> -#include <inttypes.h> #include <fcntl.h> +#include <inttypes.h> +#include <stdbool.h> +#include <sys/stat.h> +#include <sys/types.h> -#include "nvim/buffer.h" #include "nvim/ascii.h" -#include "nvim/if_cscope.h" +#include "nvim/buffer.h" #include "nvim/charset.h" +#include "nvim/event/stream.h" #include "nvim/fileio.h" -#include "nvim/message.h" +#include "nvim/if_cscope.h" #include "nvim/memory.h" +#include "nvim/message.h" +#include "nvim/os/input.h" +#include "nvim/os/os.h" #include "nvim/os/time.h" #include "nvim/path.h" #include "nvim/quickfix.h" #include "nvim/strings.h" #include "nvim/tag.h" -#include "nvim/os/os.h" -#include "nvim/os/input.h" -#include "nvim/event/stream.h" - -#include <sys/types.h> -#include <sys/stat.h> #if defined(UNIX) # include <sys/wait.h> #endif @@ -90,19 +88,20 @@ char_u *get_cscope_name(expand_T *xp, int idx) // Complete with sub-commands of ":cscope": // add, find, help, kill, reset, show return (char_u *)cs_cmds[idx].name; - case EXP_SCSCOPE_SUBCMD: - { + case EXP_SCSCOPE_SUBCMD: { // Complete with sub-commands of ":scscope": same sub-commands as // ":cscope" but skip commands which don't support split windows int i; - for (i = 0, current_idx = 0; cs_cmds[i].name != NULL; i++) - if (cs_cmds[i].cansplit) - if (current_idx++ == idx) + for (i = 0, current_idx = 0; cs_cmds[i].name != NULL; i++) { + if (cs_cmds[i].cansplit) { + if (current_idx++ == idx) { break; + } + } + } return (char_u *)cs_cmds[i].name; } - case EXP_CSCOPE_FIND: - { + case EXP_CSCOPE_FIND: { const char *query_type[] = { "a", "c", "d", "e", "f", "g", "i", "s", "t", NULL @@ -114,8 +113,7 @@ char_u *get_cscope_name(expand_T *xp, int idx) // redundant. return (char_u *)query_type[idx]; } - case EXP_CSCOPE_KILL: - { + case EXP_CSCOPE_KILL: { static char connection[5]; // ":cscope kill" accepts connection numbers or partial names of @@ -124,8 +122,9 @@ char_u *get_cscope_name(expand_T *xp, int idx) // connections. size_t i; for (i = 0, current_idx = 0; i < csinfo_size; i++) { - if (csinfo[i].fname == NULL) + if (csinfo[i].fname == NULL) { continue; + } if (current_idx++ == idx) { vim_snprintf(connection, sizeof(connection), "%zu", i); return (char_u *)connection; @@ -172,11 +171,9 @@ void set_context_in_cscope_cmd(expand_T *xp, const char *arg, cmdidx_T cmdidx) /// 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 -) +/// +/// @param make_split whether to split window +static void do_cscope_general(exarg_T *eap, int make_split) { cscmd_T *cmdp; @@ -187,8 +184,7 @@ do_cscope_general( if (make_split) { if (!cmdp->cansplit) { - (void)MSG_PUTS(_( - "This cscope command does not support splitting the window.\n")); + (void)MSG_PUTS(_("This cscope command does not support splitting the window.\n")); return; } postponed_split = -1; @@ -228,14 +224,16 @@ void ex_cstag(exarg_T *eap) case 0: if (cs_check_for_connections()) { ret = cs_find_common("g", (char *)(eap->arg), eap->forceit, FALSE, - FALSE, *eap->cmdlinep); + FALSE, *eap->cmdlinep); if (ret == FALSE) { cs_free_tags(); - if (msg_col) + if (msg_col) { msg_putchar('\n'); + } - if (cs_check_for_tags()) + if (cs_check_for_tags()) { ret = do_tag(eap->arg, DT_JUMP, 0, eap->forceit, FALSE); + } } } else if (cs_check_for_tags()) { ret = do_tag(eap->arg, DT_JUMP, 0, eap->forceit, FALSE); @@ -245,21 +243,24 @@ void ex_cstag(exarg_T *eap) if (cs_check_for_tags()) { ret = do_tag(eap->arg, DT_JUMP, 0, eap->forceit, FALSE); if (ret == FALSE) { - if (msg_col) + if (msg_col) { msg_putchar('\n'); + } if (cs_check_for_connections()) { ret = cs_find_common("g", (char *)(eap->arg), eap->forceit, - FALSE, FALSE, *eap->cmdlinep); - if (ret == FALSE) + FALSE, FALSE, *eap->cmdlinep); + if (ret == FALSE) { cs_free_tags(); + } } } } else if (cs_check_for_connections()) { ret = cs_find_common("g", (char *)(eap->arg), eap->forceit, FALSE, - FALSE, *eap->cmdlinep); - if (ret == FALSE) + FALSE, *eap->cmdlinep); + if (ret == FALSE) { cs_free_tags(); + } } break; default: @@ -306,29 +307,29 @@ void cs_print_tags(void) /* * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function * - * Checks for the existence of a |cscope| connection. If no - * parameters are specified, then the function returns: + * Checks for the existence of a |cscope| connection. If no + * parameters are specified, then the function returns: * - * 0, if cscope was not available (not compiled in), or if there - * are no cscope connections; or - * 1, if there is at least one cscope connection. + * 0, if cscope was not available (not compiled in), or if there + * are no cscope connections; or + * 1, if there is at least one cscope connection. * - * If parameters are specified, then the value of {num} - * determines how existence of a cscope connection is checked: + * If parameters are specified, then the value of {num} + * determines how existence of a cscope connection is checked: * - * {num} Description of existence check - * ----- ------------------------------ - * 0 Same as no parameters (e.g., "cscope_connection()"). - * 1 Ignore {prepend}, and use partial string matches for - * {dbpath}. - * 2 Ignore {prepend}, and use exact string matches for - * {dbpath}. - * 3 Use {prepend}, use partial string matches for both - * {dbpath} and {prepend}. - * 4 Use {prepend}, use exact string matches for both - * {dbpath} and {prepend}. + * {num} Description of existence check + * ----- ------------------------------ + * 0 Same as no parameters (e.g., "cscope_connection()"). + * 1 Ignore {prepend}, and use partial string matches for + * {dbpath}. + * 2 Ignore {prepend}, and use exact string matches for + * {dbpath}. + * 3 Use {prepend}, use partial string matches for both + * {dbpath} and {prepend}. + * 4 Use {prepend}, use exact string matches for both + * {dbpath} and {prepend}. * - * Note: All string comparisons are case sensitive! + * Note: All string comparisons are case sensitive! */ bool cs_connection(int num, char_u *dbpath, char_u *ppath) { @@ -393,8 +394,9 @@ static int cs_add(exarg_T *eap) cs_usage_msg(Add); return CSCOPE_FAILURE; } - if ((ppath = strtok((char *)NULL, (const char *)" ")) != NULL) + if ((ppath = strtok((char *)NULL, (const char *)" ")) != NULL) { flags = strtok((char *)NULL, (const char *)" "); + } return cs_add_common(fname, ppath, flags); } @@ -413,18 +415,16 @@ static void cs_stat_emsg(char *fname) /// 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 -) +/// +/// @param arg1 filename - may contain environment variables +/// @param arg2 prepend path - may contain environment variables +static int cs_add_common(char *arg1, char *arg2, char *flags) { - char *fname = NULL; - char *fname2 = NULL; - char *ppath = NULL; + char *fname = NULL; + char *fname2 = NULL; + char *ppath = NULL; size_t usedlen = 0; - char_u *fbuf = NULL; + char_u *fbuf = NULL; // get the filename (arg1), expand it, and try to stat it fname = xmalloc(MAXPATHL + 1); @@ -443,8 +443,9 @@ cs_add_common( bool file_info_ok = os_fileinfo(fname, &file_info); if (!file_info_ok) { staterr: - if (p_csverbose) + if (p_csverbose) { cs_stat_emsg(fname); + } goto add_err; } @@ -465,31 +466,32 @@ staterr: while (fname[strlen(fname)-1] == '/' ) { fname[strlen(fname)-1] = '\0'; - if (fname[0] == '\0') + if (fname[0] == '\0') { break; + } } - if (fname[0] == '\0') + if (fname[0] == '\0') { (void)sprintf(fname2, "/%s", CSCOPE_DBFILE); - else + } else { (void)sprintf(fname2, "%s/%s", fname, CSCOPE_DBFILE); + } file_info_ok = os_fileinfo(fname2, &file_info); if (!file_info_ok) { - if (p_csverbose) + if (p_csverbose) { cs_stat_emsg(fname2); + } goto add_err; } i = cs_insert_filelist(fname2, ppath, flags, &file_info); - } - else if (S_ISREG(file_info.stat.st_mode) || S_ISLNK(file_info.stat.st_mode)) - { + } else if (S_ISREG(file_info.stat.st_mode) || S_ISLNK(file_info.stat.st_mode)) { i = cs_insert_filelist(fname, ppath, flags, &file_info); } else { - if (p_csverbose) - (void)EMSG2( - _("E564: %s is not a directory or a valid cscope database"), - fname); + if (p_csverbose) { + (void)EMSG2(_("E564: %s is not a directory or a valid cscope database"), + fname); + } goto add_err; } @@ -538,15 +540,15 @@ static size_t cs_cnt_connections(void) size_t cnt = 0; for (size_t i = 0; i < csinfo_size; i++) { - if (csinfo[i].fname != NULL) + if (csinfo[i].fname != NULL) { cnt++; + } } return cnt; } -static void cs_reading_emsg( - size_t idx // connection index -) +/// @param idx connection index +static void cs_reading_emsg(size_t idx) { EMSGU(_("E262: error reading cscope connection %" PRIu64), idx); } @@ -582,7 +584,7 @@ static int cs_cnt_matches(size_t idx) // Accept "\S*cscope: X lines", also matches "mlcscope". // Bail out for the "Unable to search" error. if (strstr((const char *)buf, "Unable to search database") != NULL) { - break; + break; } if ((stok = strtok(buf, (const char *)" ")) == NULL) { continue; @@ -591,18 +593,21 @@ static int cs_cnt_matches(size_t idx) continue; } - if ((stok = strtok(NULL, (const char *)" ")) == NULL) + if ((stok = strtok(NULL, (const char *)" ")) == NULL) { continue; + } nlines = atoi(stok); if (nlines < 0) { nlines = 0; break; } - if ((stok = strtok(NULL, (const char *)" ")) == NULL) + if ((stok = strtok(NULL, (const char *)" ")) == NULL) { continue; - if (strncmp((const char *)stok, "lines", 5)) + } + if (strncmp((const char *)stok, "lines", 5)) { continue; + } break; } @@ -620,31 +625,40 @@ static char *cs_create_cmd(char *csoption, char *pattern) char *pat; switch (csoption[0]) { - case '0': case 's': + case '0': + case 's': search = 0; break; - case '1': case 'g': + case '1': + case 'g': search = 1; break; - case '2': case 'd': + case '2': + case 'd': search = 2; break; - case '3': case 'c': + case '3': + case 'c': search = 3; break; - case '4': case 't': + case '4': + case 't': search = 4; break; - case '6': case 'e': + case '6': + case 'e': search = 6; break; - case '7': case 'f': + case '7': + case 'f': search = 7; break; - case '8': case 'i': + case '8': + case 'i': search = 8; break; - case '9': case 'a': + case '9': + case 'a': search = 9; break; default: @@ -656,9 +670,11 @@ static char *cs_create_cmd(char *csoption, char *pattern) // Skip white space before the patter, except for text and pattern search, // they may want to use the leading white space. pat = pattern; - if (search != 4 && search != 6) - while (ascii_iswhite(*pat)) + if (search != 4 && search != 6) { + while (ascii_iswhite(*pat)) { ++pat; + } + } cmd = xmalloc(strlen(pat) + 2); @@ -675,7 +691,7 @@ static int cs_create_connection(size_t i) #ifdef UNIX int to_cs[2], from_cs[2]; #endif - char *prog, *cmd, *ppath = NULL; + char *prog, *cmd, *ppath = NULL; #if defined(UNIX) /* @@ -686,14 +702,18 @@ static int cs_create_connection(size_t i) if (pipe(to_cs) < 0 || pipe(from_cs) < 0) { (void)EMSG(_("E566: Could not create cscope pipes")); err_closing: - if (to_cs[0] != -1) + if (to_cs[0] != -1) { (void)close(to_cs[0]); - if (to_cs[1] != -1) + } + if (to_cs[1] != -1) { (void)close(to_cs[1]); - if (from_cs[0] != -1) + } + if (from_cs[0] != -1) { (void)close(from_cs[0]); - if (from_cs[1] != -1) + } + if (from_cs[1] != -1) { (void)close(from_cs[1]); + } return CSCOPE_FAILURE; } @@ -759,8 +779,9 @@ err_closing: len += strlen(ppath); } - if (csinfo[i].flags) + if (csinfo[i].flags) { len += strlen(csinfo[i].flags); + } cmd = xmalloc(len); @@ -779,10 +800,10 @@ err_closing: (void)strcat(cmd, " "); (void)strcat(cmd, csinfo[i].flags); } -# ifdef UNIX +#ifdef UNIX // on Win32 we still need prog xfree(prog); -# endif +#endif xfree(ppath); #if defined(UNIX) @@ -791,12 +812,14 @@ err_closing: # if defined(HAVE_SETSID) (void)setsid(); # else - if (setpgid(0, 0) == -1) + if (setpgid(0, 0) == -1) { PERROR(_("cs_create_connection setpgid failed")); + } # endif # endif - if (execl("/bin/sh", "sh", "-c", cmd, (char *)NULL) == -1) + if (execl("/bin/sh", "sh", "-c", cmd, (char *)NULL) == -1) { PERROR(_("cs_create_connection exec failed")); + } exit(127); // NOTREACHED @@ -827,7 +850,7 @@ err_closing: si.hStdError = stdout_wr; si.hStdInput = stdin_rd; created = CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, - NULL, NULL, &si, &pi); + NULL, NULL, &si, &pi); xfree(prog); xfree(cmd); @@ -888,9 +911,11 @@ static int cs_find(exarg_T *eap) * Let's replace the NULs written by strtok() with spaces - we need the * spaces to correctly display the quickfix/location list window's title. */ - for (int i = 0; i < eap_arg_len; ++i) - if (NUL == eap->arg[i]) + for (int i = 0; i < eap_arg_len; ++i) { + if (NUL == eap->arg[i]) { eap->arg[i] = ' '; + } + } return cs_find_common(opt, pat, eap->forceit, true, eap->cmdidx == CMD_lcscope, *eap->cmdlinep); @@ -898,8 +923,8 @@ static int cs_find(exarg_T *eap) /// 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) +static int cs_find_common(char *opt, char *pat, int forceit, int verbose, int use_ll, + char_u *cmdline) { char *cmd; int *nummatches; @@ -966,8 +991,9 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose, // create the actual command to send to cscope cmd = cs_create_cmd(opt, pat); - if (cmd == NULL) + if (cmd == NULL) { return FALSE; + } nummatches = xmalloc(sizeof(int) * csinfo_size); @@ -978,8 +1004,9 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose, } totmatches = 0; for (size_t i = 0; i < csinfo_size; i++) { - if (csinfo[i].fname == NULL || csinfo[i].to_fp == NULL) + if (csinfo[i].fname == NULL || csinfo[i].to_fp == NULL) { continue; + } // send cmd to cscope (void)fprintf(csinfo[i].to_fp, "%s\n", cmd); @@ -987,11 +1014,13 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose, nummatches[i] = cs_cnt_matches(i); - if (nummatches[i] > -1) + if (nummatches[i] > -1) { totmatches += (size_t)nummatches[i]; + } - if (nummatches[i] == 0) + if (nummatches[i] == 0) { (void)cs_read_prompt(i); + } } xfree(cmd); @@ -1014,10 +1043,10 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose, if (qfpos != NULL && *qfpos != '0') { // Fill error list. - FILE *f; - char_u *tmp = vim_tempname(); - qf_info_T *qi = NULL; - win_T *wp = NULL; + FILE *f; + char_u *tmp = vim_tempname(); + qf_info_T *qi = NULL; + win_T *wp = NULL; f = os_fopen((char *)tmp, "w"); if (f == NULL) { @@ -1039,14 +1068,15 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose, } apply_autocmds(EVENT_QUICKFIXCMDPOST, (char_u *)"cscope", - curbuf->b_fname, TRUE, curbuf); - if (use_ll) + curbuf->b_fname, TRUE, curbuf); + if (use_ll) { /* * In the location list window, use the displayed location * list. Otherwise, use the location list for the window. */ qi = (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL) ? wp->w_llist_ref : wp->w_llist; + } qf_jump(qi, 0, 0, forceit); } } @@ -1059,11 +1089,11 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose, size_t matched = 0; // read output - cs_fill_results((char *)pat, totmatches, nummatches, &matches, - &contexts, &matched); + cs_fill_results(pat, totmatches, nummatches, &matches, &contexts, &matched); xfree(nummatches); - if (matches == NULL) + if (matches == NULL) { return FALSE; + } (void)cs_manage_matches(matches, contexts, matched, Store); @@ -1086,10 +1116,10 @@ static int cs_help(exarg_T *eap) space_cnt = 0; } (void)smsg(_("%-5s: %s%*s (Usage: %s)"), - cmdp->name, - help, space_cnt, " ", - cmdp->usage); - if (strcmp(cmdp->name, "find") == 0) + cmdp->name, + help, space_cnt, " ", + cmdp->usage); + if (strcmp(cmdp->name, "find") == 0) { MSG_PUTS(_("\n" " a: Find assignments to this symbol\n" " c: Find functions calling this function\n" @@ -1100,6 +1130,7 @@ static int cs_help(exarg_T *eap) " i: Find files #including this file\n" " s: Find this C symbol\n" " t: Find this text string\n")); + } cmdp++; } @@ -1121,8 +1152,7 @@ static void clear_csinfo(size_t i) } /// Insert a new cscope database filename into the filelist. -static int cs_insert_filelist(char *fname, char *ppath, char *flags, - FileInfo *file_info) +static int cs_insert_filelist(char *fname, char *ppath, char *flags, FileInfo *file_info) { size_t i = 0; bool empty_found = false; @@ -1130,8 +1160,9 @@ static int cs_insert_filelist(char *fname, char *ppath, char *flags, for (size_t j = 0; j < csinfo_size; j++) { if (csinfo[j].fname != NULL && os_fileid_equal_fileinfo(&(csinfo[j].file_id), file_info)) { - if (p_csverbose) + if (p_csverbose) { (void)EMSG(_("E568: duplicate cscope database not added")); + } return CSCOPE_FAILURE; } @@ -1154,8 +1185,9 @@ static int cs_insert_filelist(char *fname, char *ppath, char *flags, csinfo_size *= 2; csinfo = xrealloc(csinfo, sizeof(csinfo_T)*csinfo_size); } - for (size_t j = csinfo_size/2; j < csinfo_size; j++) + for (size_t j = csinfo_size/2; j < csinfo_size; j++) { clear_csinfo(j); + } } csinfo[i].fname = xmalloc(strlen(fname) + 1); @@ -1165,14 +1197,16 @@ static int cs_insert_filelist(char *fname, char *ppath, char *flags, if (ppath != NULL) { csinfo[i].ppath = xmalloc(strlen(ppath) + 1); (void)strcpy(csinfo[i].ppath, (const char *)ppath); - } else + } else { csinfo[i].ppath = NULL; + } if (flags != NULL) { csinfo[i].flags = xmalloc(strlen(flags) + 1); (void)strcpy(csinfo[i].flags, (const char *)flags); - } else + } else { csinfo[i].flags = NULL; + } os_fileinfo_id(file_info, &(csinfo[i].file_id)); assert(i <= INT_MAX); @@ -1181,25 +1215,28 @@ static int cs_insert_filelist(char *fname, char *ppath, char *flags, /// Find cscope command in command table. -static cscmd_T * cs_lookup_cmd(exarg_T *eap) +static cscmd_T *cs_lookup_cmd(exarg_T *eap) { cscmd_T *cmdp; char *stok; size_t len; - if (eap->arg == NULL) + if (eap->arg == NULL) { return NULL; + } // Store length of eap->arg before it gets modified by strtok(). eap_arg_len = (int)STRLEN(eap->arg); - if ((stok = strtok((char *)(eap->arg), (const char *)" ")) == NULL) + if ((stok = strtok((char *)(eap->arg), (const char *)" ")) == NULL) { return NULL; + } len = strlen(stok); for (cmdp = cs_cmds; cmdp->name != NULL; ++cmdp) { - if (strncmp((const char *)(stok), cmdp->name, len) == 0) + if (strncmp((const char *)(stok), cmdp->name, len) == 0) { return cmdp; + } } return NULL; } @@ -1224,21 +1261,23 @@ static int cs_kill(exarg_T *eap) || (strlen(stok) < 3 && stok[0] == '-' && ascii_isdigit((int)(stok[1])))) { num = atoi(stok); - if (num == -1) + if (num == -1) { killall = true; - else if (num >= 0) { + } else if (num >= 0) { i = (size_t)num; } else { // All negative values besides -1 are invalid. - if (p_csverbose) + if (p_csverbose) { (void)EMSG2(_("E261: cscope connection %s not found"), stok); + } return CSCOPE_FAILURE; } } else { // Else it must be part of a name. We will try to find a match // within all the names in the csinfo data structure for (i = 0; i < csinfo_size; i++) { - if (csinfo[i].fname != NULL && strstr(csinfo[i].fname, stok)) + if (csinfo[i].fname != NULL && strstr(csinfo[i].fname, stok)) { break; + } } } @@ -1250,8 +1289,9 @@ static int cs_kill(exarg_T *eap) } else { if (killall) { for (i = 0; i < csinfo_size; i++) { - if (csinfo[i].fname) + if (csinfo[i].fname) { cs_kill_execute(i, csinfo[i].fname); + } } } else { cs_kill_execute((size_t)i, stok); @@ -1263,10 +1303,10 @@ static int cs_kill(exarg_T *eap) /// Actually kills a specific cscope connection. -static void cs_kill_execute( - size_t i, // cscope table index - char *cname // cscope database name -) +/// +/// @param i cscope table index +/// @param cname cscope database name +static void cs_kill_execute(size_t i, char *cname) { if (p_csverbose) { msg_clr_eos(); @@ -1293,8 +1333,7 @@ static void cs_kill_execute( /// 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) +static char *cs_make_vim_style_matches(char *fname, char *slno, char *search, char *tagstr) { // vim style is ctags: // @@ -1339,8 +1378,7 @@ static char *cs_make_vim_style_matches(char *fname, char *slno, char *search, /// 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) +static char *cs_manage_matches(char **matches, char **contexts, size_t totmatches, mcmd_e cmd) { static char **mp = NULL; static char **cp = NULL; @@ -1352,16 +1390,18 @@ static char *cs_manage_matches(char **matches, char **contexts, case Store: assert(matches != NULL); assert(totmatches > 0); - if (mp != NULL || cp != NULL) + if (mp != NULL || cp != NULL) { (void)cs_manage_matches(NULL, NULL, 0, Free); + } mp = matches; cp = contexts; cnt = totmatches; next = 0; break; case Get: - if (next >= cnt) + if (next >= cnt) { return NULL; + } p = mp[next]; next++; @@ -1370,8 +1410,9 @@ static char *cs_manage_matches(char **matches, char **contexts, if (mp != NULL) { while (cnt--) { xfree(mp[cnt]); - if (cp != NULL) + if (cp != NULL) { xfree(cp[cnt]); + } } xfree(mp); xfree(cp); @@ -1396,8 +1437,8 @@ static char *cs_manage_matches(char **matches, char **contexts, /// Parse cscope output. -static char *cs_parse_results(size_t cnumber, char *buf, int bufsize, - char **context, char **linenumber, char **search) +static char *cs_parse_results(size_t cnumber, char *buf, int bufsize, char **context, + char **linenumber, char **search) { int ch; char *p; @@ -1421,8 +1462,9 @@ retry: // If the line's too long for the buffer, discard it. if ((p = strchr(buf, '\n')) == NULL) { - while ((ch = getc(csinfo[cnumber].fr_fp)) != EOF && ch != '\n') + while ((ch = getc(csinfo[cnumber].fr_fp)) != EOF && ch != '\n') { ; + } return NULL; } *p = '\0'; @@ -1430,14 +1472,18 @@ retry: /* * cscope output is in the following format: * - * <filename> <context> <line number> <pattern> + * <filename> <context> <line number> <pattern> */ - if ((name = strtok((char *)buf, (const char *)" ")) == NULL) + char *saveptr = NULL; + if ((name = os_strtok(buf, (const char *)" ", &saveptr)) == NULL) { return NULL; - if ((*context = strtok(NULL, (const char *)" ")) == NULL) + } + if ((*context = os_strtok(NULL, (const char *)" ", &saveptr)) == NULL) { return NULL; - if ((*linenumber = strtok(NULL, (const char *)" ")) == NULL) + } + if ((*linenumber = os_strtok(NULL, (const char *)" ", &saveptr)) == NULL) { return NULL; + } *search = *linenumber + strlen(*linenumber) + 1; // +1 to skip \0 // --- nvi --- @@ -1463,25 +1509,29 @@ static void cs_file_results(FILE *f, int *nummatches_a) char *buf = xmalloc(CSREAD_BUFSIZE); for (size_t i = 0; i < csinfo_size; i++) { - if (nummatches_a[i] < 1) + if (nummatches_a[i] < 1) { continue; + } for (int j = 0; j < nummatches_a[i]; j++) { if ((fullname = cs_parse_results(i, buf, CSREAD_BUFSIZE, &cntx, - &slno, &search)) == NULL) + &slno, &search)) == NULL) { continue; + } context = xmalloc(strlen(cntx) + 5); - if (strcmp(cntx, "<global>")==0) + if (strcmp(cntx, "<global>")==0) { strcpy(context, "<<global>>"); - else + } else { sprintf(context, "<<%s>>", cntx); + } - if (search == NULL) + if (search == NULL) { fprintf(f, "%s\t%s\t%s\n", fullname, slno, context); - else + } else { fprintf(f, "%s\t%s\t%s %s\n", fullname, slno, context, search); + } xfree(context); xfree(fullname); @@ -1495,9 +1545,8 @@ static void cs_file_results(FILE *f, int *nummatches_a) /// 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) +static void cs_fill_results(char *tagstr, size_t totmatches, int *nummatches_a, char ***matches_p, + char ***cntxts_p, size_t *matched) { char *buf; char *search, *slno; @@ -1514,22 +1563,24 @@ static void cs_fill_results(char *tagstr, size_t totmatches, int *nummatches_a, cntxts = xmalloc(sizeof(char *) * (size_t)totmatches); for (size_t i = 0; i < csinfo_size; i++) { - if (nummatches_a[i] < 1) + if (nummatches_a[i] < 1) { continue; + } for (int j = 0; j < nummatches_a[i]; j++) { if ((fullname = cs_parse_results(i, buf, CSREAD_BUFSIZE, &cntx, - &slno, &search)) == NULL) + &slno, &search)) == NULL) { continue; + } matches[totsofar] = cs_make_vim_style_matches(fullname, slno, search, tagstr); xfree(fullname); - if (strcmp(cntx, "<global>") == 0) + if (strcmp(cntx, "<global>") == 0) { cntxts[totsofar] = NULL; - else { + } else { cntxts[totsofar] = xstrdup(cntx); } @@ -1691,9 +1742,9 @@ static void cs_print_tags_priv(char **matches, char **cntxts, static int cs_read_prompt(size_t i) { int ch; - char *buf = NULL; // buffer for possible error message from cscope + char *buf = NULL; // buffer for possible error message from cscope size_t bufpos = 0; - char *cs_emsg = _("E609: Cscope error: %s"); + char *cs_emsg = _("E609: Cscope error: %s"); size_t cs_emsg_len = strlen(cs_emsg); static char *eprompt = "Press the RETURN key to continue:"; size_t epromptlen = strlen(eprompt); @@ -1886,10 +1937,12 @@ static void cs_release_csp(size_t i, bool freefnpp) } #endif - if (csinfo[i].fr_fp != NULL) + if (csinfo[i].fr_fp != NULL) { (void)fclose(csinfo[i].fr_fp); - if (csinfo[i].to_fp != NULL) + } + if (csinfo[i].to_fp != NULL) { (void)fclose(csinfo[i].to_fp); + } if (freefnpp) { xfree(csinfo[i].fname); @@ -1904,11 +1957,12 @@ static void cs_release_csp(size_t i, bool freefnpp) /// Calls cs_kill on all cscope connections then reinits. static int cs_reset(exarg_T *eap) { - char **dblist = NULL, **pplist = NULL, **fllist = NULL; + char **dblist = NULL, **pplist = NULL, **fllist = NULL; char buf[25]; // for snprintf " (#%zu)" - if (csinfo_size == 0) + if (csinfo_size == 0) { return CSCOPE_SUCCESS; + } // malloc our db and ppath list dblist = xmalloc(csinfo_size * sizeof(char *)); @@ -1919,8 +1973,9 @@ static int cs_reset(exarg_T *eap) dblist[i] = csinfo[i].fname; pplist[i] = csinfo[i].ppath; fllist[i] = csinfo[i].flags; - if (csinfo[i].fname != NULL) + if (csinfo[i].fname != NULL) { cs_release_csp(i, FALSE); + } } // rebuild the cscope connection list @@ -1959,8 +2014,8 @@ static int cs_reset(exarg_T *eap) /// Contrast this with my development system (Digital Unix), which does. static char *cs_resolve_file(size_t i, char *name) { - char *fullname; - char_u *csdir = NULL; + char *fullname; + char_u *csdir = NULL; /* * Ppath is freed when we destroy the cscope connection. @@ -1975,8 +2030,8 @@ static char *cs_resolve_file(size_t i, char *name) // path in path resolution. csdir = xmalloc(MAXPATHL); STRLCPY(csdir, csinfo[i].fname, - path_tail((char_u *)csinfo[i].fname) - - (char_u *)csinfo[i].fname + 1); + path_tail((char_u *)csinfo[i].fname) + - (char_u *)csinfo[i].fname + 1); len += STRLEN(csdir); } @@ -1985,8 +2040,7 @@ static char *cs_resolve_file(size_t i, char *name) // happens, you are screwed up and need to fix how you're using cscope. if (csinfo[i].ppath != NULL && (strncmp(name, csinfo[i].ppath, strlen(csinfo[i].ppath)) != 0) - && (name[0] != '/') - ) { + && (name[0] != '/')) { fullname = xmalloc(len); (void)sprintf(fullname, "%s/%s", csinfo[i].ppath, name); } else if (csdir != NULL && csinfo[i].fname != NULL && *csdir != NUL) { @@ -2005,15 +2059,15 @@ static char *cs_resolve_file(size_t i, char *name) /// Show all cscope connections. static int cs_show(exarg_T *eap) { - if (cs_cnt_connections() == 0) + if (cs_cnt_connections() == 0) { MSG_PUTS(_("no cscope connections\n")); - else { - MSG_PUTS_ATTR( - _(" # pid database name prepend path\n"), - HL_ATTR(HLF_T)); + } else { + MSG_PUTS_ATTR(_(" # pid database name prepend path\n"), + HL_ATTR(HLF_T)); for (size_t i = 0; i < csinfo_size; i++) { - if (csinfo[i].fname == NULL) + if (csinfo[i].fname == NULL) { continue; + } if (csinfo[i].ppath != NULL) { (void)smsg("%2zu %-5" PRId64 " %-34s %-32s", i, @@ -2033,8 +2087,9 @@ static int cs_show(exarg_T *eap) /// Only called when VIM exits to quit any cscope sessions. void cs_end(void) { - for (size_t i = 0; i < csinfo_size; i++) + for (size_t i = 0; i < csinfo_size; i++) { cs_release_csp(i, true); + } xfree(csinfo); csinfo_size = 0; } diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 9333d781cd..3f93bb9a09 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -5,6 +5,7 @@ #include <lua.h> #include <lualib.h> +#include "cjson/lua_cjson.h" #include "luv/luv.h" #include "mpack/lmpack.h" #include "nvim/api/private/defs.h" @@ -40,7 +41,6 @@ #include "nvim/undo.h" #include "nvim/version.h" #include "nvim/vim.h" -#include "cjson/lua_cjson.h" static int in_fast_callback = 0; diff --git a/src/nvim/lua/xdiff.c b/src/nvim/lua/xdiff.c index 2a1f39083c..3955fbe72c 100644 --- a/src/nvim/lua/xdiff.c +++ b/src/nvim/lua/xdiff.c @@ -53,8 +53,8 @@ static int write_string(void *priv, mmbuffer_t *mb, int nbuf) static int hunk_locations_cb(long start_a, long count_a, long start_b, long count_b, void *cb_data) { // Mimic extra offsets done by xdiff, see: - // src/nvim/xdiff/xemit.c:284 - // src/nvim/xdiff/xutils.c:(356,368) + // src/xdiff/xemit.c:284 + // src/xdiff/xutils.c:(356,368) if (count_a > 0) { start_a += 1; } @@ -83,8 +83,8 @@ static int hunk_locations_cb(long start_a, long count_a, long start_b, long coun static int call_on_hunk_cb(long start_a, long count_a, long start_b, long count_b, void *cb_data) { // Mimic extra offsets done by xdiff, see: - // src/nvim/xdiff/xemit.c:284 - // src/nvim/xdiff/xutils.c:(356,368) + // src/xdiff/xemit.c:284 + // src/xdiff/xutils.c:(356,368) if (count_a > 0) { start_a += 1; } diff --git a/src/nvim/main.c b/src/nvim/main.c index d977589ad7..f801351d2d 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1306,35 +1306,6 @@ static void set_window_layout(mparm_T *paramp) } } -/* - * Read all the plugin files. - * Only when compiled with +eval, since most plugins need it. - */ -static void load_plugins(void) -{ - if (p_lpl) { - char_u *rtp_copy = NULL; - char_u *const plugin_pattern_vim = (char_u *)"plugin/**/*.vim"; // NOLINT - char_u *const plugin_pattern_lua = (char_u *)"plugin/**/*.lua"; // NOLINT - - // don't use source_runtime() yet so we can check for :packloadall below - source_in_path(p_rtp, plugin_pattern_vim, DIP_ALL | DIP_NOAFTER); - source_in_path(p_rtp, plugin_pattern_lua, DIP_ALL | DIP_NOAFTER); - TIME_MSG("loading rtp plugins"); - xfree(rtp_copy); - - // 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(plugin_pattern_vim, DIP_ALL | DIP_AFTER); - source_runtime(plugin_pattern_lua, DIP_ALL | DIP_AFTER); - TIME_MSG("loading after plugins"); - } -} /* * "-q errorfile": Load the error file now. diff --git a/src/nvim/menu.c b/src/nvim/menu.c index 2b1a250604..de8503f9d0 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -64,7 +64,7 @@ static vimmenu_T **get_root_menu(const char_u *const name) /// @param eap Ex command arguments void ex_menu(exarg_T *eap) { - char_u *menu_path; + char *menu_path; int modes; char_u *map_to; // command mapped to the menu entry int noremap; @@ -166,7 +166,7 @@ void ex_menu(exarg_T *eap) } - menu_path = arg; + menu_path = (char *)arg; if (*menu_path == '.') { EMSG2(_(e_invarg2), menu_path); goto theend; @@ -178,25 +178,25 @@ void ex_menu(exarg_T *eap) * If there is only a menu name, display menus with that name. */ if (*map_to == NUL && !unmenu && enable == kNone) { - show_menus(menu_path, modes); + show_menus((char_u *)menu_path, modes); goto theend; } else if (*map_to != NUL && (unmenu || enable != kNone)) { EMSG(_(e_trailing)); goto theend; } - vimmenu_T **root_menu_ptr = get_root_menu(menu_path); + vimmenu_T **root_menu_ptr = get_root_menu((char_u *)menu_path); if (enable != kNone) { // Change sensitivity of the menu. // For the PopUp menu, remove a menu for each mode separately. // Careful: menu_enable_recurse() changes menu_path. if (STRCMP(menu_path, "*") == 0) { // meaning: do all menus - menu_path = (char_u *)""; + menu_path = ""; } if (menu_is_popup(menu_path)) { - for (i = 0; i < MENU_INDEX_TIP; ++i) { + for (i = 0; i < MENU_INDEX_TIP; i++) { if (modes & (1 << i)) { p = popup_mode_name(menu_path, i); menu_enable_recurse(*root_menu_ptr, p, MENU_ALL_MODES, enable); @@ -204,20 +204,20 @@ void ex_menu(exarg_T *eap) } } } - menu_enable_recurse(*root_menu_ptr, menu_path, modes, enable); + menu_enable_recurse(*root_menu_ptr, (char_u *)menu_path, modes, enable); } else if (unmenu) { /* * Delete menu(s). */ if (STRCMP(menu_path, "*") == 0) { // meaning: remove all menus - menu_path = (char_u *)""; + menu_path = ""; } /* * For the PopUp menu, remove a menu for each mode separately. */ if (menu_is_popup(menu_path)) { - for (i = 0; i < MENU_INDEX_TIP; ++i) { + for (i = 0; i < MENU_INDEX_TIP; i++) { if (modes & (1 << i)) { p = popup_mode_name(menu_path, i); remove_menu(root_menu_ptr, p, MENU_ALL_MODES, true); @@ -227,7 +227,7 @@ void ex_menu(exarg_T *eap) } // Careful: remove_menu() changes menu_path - remove_menu(root_menu_ptr, menu_path, modes, false); + remove_menu(root_menu_ptr, (char_u *)menu_path, modes, false); } else { /* * Add menu(s). @@ -245,13 +245,13 @@ void ex_menu(exarg_T *eap) menuarg.modes = modes; menuarg.noremap[0] = noremap; menuarg.silent[0] = silent; - add_menu_path(menu_path, &menuarg, pri_tab, map_to); + add_menu_path((char_u *)menu_path, &menuarg, pri_tab, map_to); /* * For the PopUp menu, add a menu for each mode separately. */ if (menu_is_popup(menu_path)) { - for (i = 0; i < MENU_INDEX_TIP; ++i) { + for (i = 0; i < MENU_INDEX_TIP; i++) { if (modes & (1 << i)) { p = popup_mode_name(menu_path, i); // Include all modes, to make ":amenu" work @@ -1273,12 +1273,12 @@ int get_menu_cmd_modes(const char *cmd, bool forceit, int *noremap, int *unmenu) * Modify a menu name starting with "PopUp" to include the mode character. * Returns the name in allocated memory. */ -static char_u *popup_mode_name(char_u *name, int idx) +static char_u *popup_mode_name(char *name, int idx) { size_t len = STRLEN(name); assert(len >= 4); - char_u *p = vim_strnsave(name, len + 1); + char_u *p = vim_strnsave((char_u *)name, len + 1); memmove(p + 6, p + 5, len - 4); p[5] = menu_mode_chars[idx]; @@ -1337,14 +1337,14 @@ static char_u *menu_text(const char_u *str, int *mnemonic, char_u **actext) bool menu_is_menubar(const char_u *const name) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { - return !menu_is_popup(name) + return !menu_is_popup((char *)name) && !menu_is_toolbar(name) && !menu_is_winbar(name) && *name != MNU_HIDDEN_CHAR; } // Return true if "name" is a popup menu name. -bool menu_is_popup(const char_u *const name) +bool menu_is_popup(const char *const name) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { return STRNCMP(name, "PopUp", 5) == 0; @@ -1374,7 +1374,7 @@ int menu_is_separator(char_u *name) static int menu_is_hidden(char_u *name) { return (name[0] == MNU_HIDDEN_CHAR) - || (menu_is_popup(name) && name[5] != NUL); + || (menu_is_popup((char *)name) && name[5] != NUL); } // Execute "menu". Use by ":emenu" and the window toolbar. @@ -1383,25 +1383,25 @@ static void execute_menu(const exarg_T *eap, vimmenu_T *menu) FUNC_ATTR_NONNULL_ARG(2) { int idx = -1; - char_u *mode; + char *mode; // Use the Insert mode entry when returning to Insert mode. if (((State & INSERT) || restart_edit) && !current_sctx.sc_sid) { - mode = (char_u *)"Insert"; + mode = "Insert"; idx = MENU_INDEX_INSERT; } else if (State & CMDLINE) { - mode = (char_u *)"Command"; + mode = "Command"; idx = MENU_INDEX_CMDLINE; } else if (get_real_state() & VISUAL) { /* Detect real visual mode -- if we are really in visual mode we * don't need to do any guesswork to figure out what the selection * is. Just execute the visual binding for the menu. */ - mode = (char_u *)"Visual"; + mode = "Visual"; idx = MENU_INDEX_VISUAL; } else if (eap != NULL && eap->addr_count) { pos_T tpos; - mode = (char_u *)"Visual"; + mode = "Visual"; idx = MENU_INDEX_VISUAL; /* GEDDES: This is not perfect - but it is a @@ -1442,7 +1442,7 @@ static void execute_menu(const exarg_T *eap, vimmenu_T *menu) } if (idx == -1 || eap == NULL) { - mode = (char_u *)"Normal"; + mode = "Normal"; idx = MENU_INDEX_NORMAL; } diff --git a/src/nvim/move.c b/src/nvim/move.c index ca3dd34204..c4f8e81fa3 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -794,7 +794,7 @@ void curs_columns(win_T *wp, int may_scroll) // column char_u *const sbr = get_showbreak_value(wp); if (*sbr && *get_cursor_pos_ptr() == NUL - && wp->w_wcol == (int)vim_strsize(sbr)) { + && wp->w_wcol == vim_strsize(sbr)) { wp->w_wcol = 0; } } diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 7b72efce23..e1669a8c19 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -5,8 +5,8 @@ /// /// Management of runtime files (including packages) -#include "nvim/ascii.h" #include "nvim/api/private/helpers.h" +#include "nvim/ascii.h" #include "nvim/charset.h" #include "nvim/eval.h" #include "nvim/ex_cmds.h" @@ -169,9 +169,9 @@ int do_in_path(char_u *path, char_u *name, int flags, DoInRuntimepathCB callback int do_in_cached_path(char_u *name, int flags, DoInRuntimepathCB callback, void *cookie) { runtime_search_path_validate(); - char_u *tail; + char_u *tail; int num_files; - char_u **files; + char_u **files; int i; bool did_one = false; @@ -332,40 +332,56 @@ int do_in_path_and_pp(char_u *path, char_u *name, int flags, DoInRuntimepathCB c return done; } -static void push_path(RuntimeSearchPath *search_path, char *entry, bool after) +static void push_path(RuntimeSearchPath *search_path, Map(String, handle_T) *rtp_used, + char *entry, bool after) { - kv_push(*search_path, ((SearchPathItem){ entry, after })); + handle_T h = map_get(String, handle_T)(rtp_used, cstr_as_string((char *)entry)); + if (h == 0) { + char *allocated = xstrdup(entry); + map_put(String, handle_T)(rtp_used, cstr_as_string(allocated), 1); + kv_push(*search_path, ((SearchPathItem){ allocated, after })); + } } -static void expand_pack_entry(RuntimeSearchPath *search_path, CharVec *after_path, - char_u *pack_entry) +static void expand_rtp_entry(RuntimeSearchPath *search_path, Map(String, handle_T) *rtp_used, + char *entry, bool after) { - static char_u buf[MAXPATHL], buf2[MAXPATHL]; - char *start_dir = "/pack/*/start/*"; // NOLINT - if (STRLEN(pack_entry) + STRLEN(start_dir) + 1 < MAXPATHL) { - xstrlcpy((char *)buf, (char *)pack_entry, MAXPATHL); - xstrlcpy((char *)buf2, (char *)pack_entry, MAXPATHL); - xstrlcat((char *)buf, start_dir, sizeof buf); - xstrlcat((char *)buf2, "/start/*", sizeof buf); // NOLINT - int num_files; - char_u **files; - - char_u *(pat[]) = { buf, buf2 }; - if (gen_expand_wildcards(2, pat, &num_files, &files, EW_DIR) == OK) { - for (int i = 0; i < num_files; i++) { - push_path(search_path, xstrdup((char *)files[i]), false); - size_t after_size = STRLEN(files[i])+7; - char *after = xmallocz(after_size); - xstrlcpy(after, (char *)files[i], after_size); - xstrlcat(after, "/after", after_size); - if (os_isdir((char_u *)after)) { - kv_push(*after_path, after); - } else { - xfree(after); - } - } - FreeWild(num_files, files); + if (map_get(String, handle_T)(rtp_used, cstr_as_string(entry))) { + return; + } + + if (!*entry) { + push_path(search_path, rtp_used, entry, after); + } + + int num_files; + char_u **files; + char_u *(pat[]) = { (char_u *)entry }; + if (gen_expand_wildcards(1, pat, &num_files, &files, EW_DIR) == OK) { + for (int i = 0; i < num_files; i++) { + push_path(search_path, rtp_used, (char *)files[i], after); } + FreeWild(num_files, files); + } +} + +static void expand_pack_entry(RuntimeSearchPath *search_path, Map(String, handle_T) *rtp_used, + CharVec *after_path, char_u *pack_entry) +{ + static char buf[MAXPATHL]; + char *(start_pat[]) = { "/pack/*/start/*", "/start/*" }; // NOLINT + for (int i = 0; i < 2; i++) { + if (STRLEN(pack_entry) + STRLEN(start_pat[i]) + 1 > MAXPATHL) { + continue; + } + xstrlcpy(buf, (char *)pack_entry, MAXPATHL); + xstrlcat(buf, start_pat[i], sizeof buf); + expand_rtp_entry(search_path, rtp_used, buf, false); + size_t after_size = STRLEN(buf)+7; + char *after = xmallocz(after_size); + xstrlcpy(after, buf, after_size); + xstrlcat(after, "/after", after_size); + kv_push(*after_path, after); } } @@ -382,8 +398,10 @@ static bool path_is_after(char_u *buf, size_t buflen) RuntimeSearchPath runtime_search_path_build(void) { kvec_t(String) pack_entries = KV_INITIAL_VALUE; + // TODO(bfredl): these should just be sets, when Set(String) is do merge to + // master. Map(String, handle_T) pack_used = MAP_INIT; - // TODO(bfredl): add a set of existing rtp entries to not duplicate those + Map(String, handle_T) rtp_used = MAP_INIT; RuntimeSearchPath search_path = KV_INITIAL_VALUE; CharVec after_path = KV_INITIAL_VALUE; @@ -410,37 +428,40 @@ RuntimeSearchPath runtime_search_path_build(void) break; } - push_path(&search_path, xstrdup((char *)buf), false); + // fact: &rtp entries can contain wild chars + expand_rtp_entry(&search_path, &rtp_used, (char *)buf, false); handle_T *h = map_ref(String, handle_T)(&pack_used, cstr_as_string((char *)buf), false); if (h) { (*h)++; - expand_pack_entry(&search_path, &after_path, buf); + expand_pack_entry(&search_path, &rtp_used, &after_path, buf); } } for (size_t i = 0; i < kv_size(pack_entries); i++) { handle_T h = map_get(String, handle_T)(&pack_used, kv_A(pack_entries, i)); if (h == 0) { - expand_pack_entry(&search_path, &after_path, (char_u *)kv_A(pack_entries, i).data); + expand_pack_entry(&search_path, &rtp_used, &after_path, (char_u *)kv_A(pack_entries, i).data); } } // "after" packages for (size_t i = 0; i < kv_size(after_path); i++) { - push_path(&search_path, kv_A(after_path, i), true); + expand_rtp_entry(&search_path, &rtp_used, kv_A(after_path, i), true); + xfree(kv_A(after_path, i)); } // "after" dirs in rtp for (; *rtp_entry != NUL;) { copy_option_part((char_u **)&rtp_entry, buf, MAXPATHL, ","); - push_path(&search_path, xstrdup((char *)buf), path_is_after(buf, STRLEN(buf))); + expand_rtp_entry(&search_path, &rtp_used, (char *)buf, path_is_after(buf, STRLEN(buf))); } // strings are not owned kv_destroy(pack_entries); kv_destroy(after_path); map_destroy(String, handle_T)(&pack_used); + map_destroy(String, handle_T)(&rtp_used); return search_path; } @@ -452,11 +473,11 @@ void runtime_search_path_invalidate(void) void runtime_search_path_free(RuntimeSearchPath path) { - for (size_t j = 0; j < kv_size(path); j++) { - SearchPathItem item = kv_A(path, j); - xfree(item.path); - } - kv_destroy(path); + for (size_t j = 0; j < kv_size(path); j++) { + SearchPathItem item = kv_A(path, j); + xfree(item.path); + } + kv_destroy(path); } void runtime_search_path_validate(void) @@ -521,7 +542,10 @@ static void source_all_matches(char_u *pat) } /// Add the package directory to 'runtimepath' -static int add_pack_dir_to_rtp(char_u *fname) +/// +/// @param fname the package path +/// @param is_pack whether the added dir is a "pack/*/start/*/" style package +static int add_pack_dir_to_rtp(char_u *fname, bool is_pack) { char_u *p4, *p3, *p2, *p1, *p; char_u *buf = NULL; @@ -599,7 +623,7 @@ static int add_pack_dir_to_rtp(char_u *fname) // check if rtp/pack/name/start/name/after exists afterdir = concat_fnames((char *)fname, "after", true); size_t afterlen = 0; - if (os_isdir((char_u *)afterdir)) { + if (is_pack ? pack_has_entries((char_u *)afterdir) : os_isdir((char_u *)afterdir)) { afterlen = strlen(afterdir) + 1; // add one for comma } @@ -720,7 +744,7 @@ static void add_pack_plugin(bool opt, char_u *fname, void *cookie) xfree(buf); if (!found) { // directory is not yet in 'runtimepath', add it - if (add_pack_dir_to_rtp(fname) == FAIL) { + if (add_pack_dir_to_rtp(fname, false) == FAIL) { return; } } @@ -741,6 +765,41 @@ static void add_opt_pack_plugin(char_u *fname, void *cookie) add_pack_plugin(true, fname, cookie); } + +/// Add all packages in the "start" directory to 'runtimepath'. +void add_pack_start_dirs(void) +{ + do_in_path(p_pp, NULL, DIP_ALL + DIP_DIR, add_pack_start_dir, NULL); +} + +static bool pack_has_entries(char_u *buf) +{ + int num_files; + char_u **files; + char_u *(pat[]) = { (char_u *)buf }; + if (gen_expand_wildcards(1, pat, &num_files, &files, EW_DIR) == OK) { + FreeWild(num_files, files); + } + return num_files > 0; +} + +static void add_pack_start_dir(char_u *fname, void *cookie) +{ + static char_u buf[MAXPATHL]; + char *(start_pat[]) = { "/start/*", "/pack/*/start/*" }; // NOLINT + for (int i = 0; i < 2; i++) { + if (STRLEN(fname) + STRLEN(start_pat[i]) + 1 > MAXPATHL) { + continue; + } + xstrlcpy((char *)buf, (char *)fname, MAXPATHL); + xstrlcat((char *)buf, start_pat[i], sizeof buf); + if (pack_has_entries(buf)) { + add_pack_dir_to_rtp(buf, true); + } + } +} + + /// Load plugins from all packages in the "start" directory. void load_start_packages(void) { @@ -759,10 +818,43 @@ void ex_packloadall(exarg_T *eap) // 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. + add_pack_start_dirs(); load_start_packages(); } } +/// Read all the plugin files at startup +void load_plugins(void) +{ + if (p_lpl) { + char_u *rtp_copy = p_rtp; + char_u *const plugin_pattern_vim = (char_u *)"plugin/**/*.vim"; // NOLINT + char_u *const plugin_pattern_lua = (char_u *)"plugin/**/*.lua"; // NOLINT + + if (!did_source_packages) { + rtp_copy = vim_strsave(p_rtp); + add_pack_start_dirs(); + } + + // don't use source_runtime() yet so we can check for :packloadall below + source_in_path(rtp_copy, plugin_pattern_vim, DIP_ALL | DIP_NOAFTER); + source_in_path(rtp_copy, plugin_pattern_lua, DIP_ALL | DIP_NOAFTER); + TIME_MSG("loading rtp plugins"); + + // Only source "start" packages if not done already with a :packloadall + // command. + if (!did_source_packages) { + xfree(rtp_copy); + load_start_packages(); + } + TIME_MSG("loading packages"); + + source_runtime(plugin_pattern_vim, DIP_ALL | DIP_AFTER); + source_runtime(plugin_pattern_lua, DIP_ALL | DIP_AFTER); + TIME_MSG("loading after plugins"); + } +} + /// ":packadd[!] {name}" void ex_packadd(exarg_T *eap) { diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 98d8722ec8..fcd8fb1118 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -4545,8 +4545,8 @@ void draw_virt_text(buf_T *buf, int col_off, int *end_col, int max_col) } } -static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode, - int max_col, int vcol) +static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode, int max_col, + int vcol) { LineState s = LINE_STATE(""); int virt_attr = 0; diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 79a3db4843..11c1aa1760 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -1,28 +1,26 @@ // 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 <math.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" -#include "nvim/file_search.h" +#include "nvim/assert.h" #include "nvim/buffer.h" #include "nvim/charset.h" #include "nvim/diff.h" #include "nvim/edit.h" #include "nvim/eval.h" +#include "nvim/eval/encode.h" #include "nvim/ex_cmds.h" #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" +#include "nvim/file_search.h" #include "nvim/fileio.h" -#include "nvim/func_attr.h" #include "nvim/fold.h" #include "nvim/func_attr.h" #include "nvim/getchar.h" @@ -35,8 +33,10 @@ #include "nvim/message.h" #include "nvim/misc1.h" #include "nvim/move.h" -#include "nvim/option.h" #include "nvim/ops.h" +#include "nvim/option.h" +#include "nvim/os/os.h" +#include "nvim/os/shell.h" #include "nvim/os_unix.h" #include "nvim/path.h" #include "nvim/quickfix.h" @@ -44,12 +44,11 @@ #include "nvim/screen.h" #include "nvim/search.h" #include "nvim/spell.h" +#include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tag.h" +#include "nvim/vim.h" #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. char_u *vim_strsave(const char_u *string) @@ -84,8 +83,7 @@ char_u *vim_strsave_escaped(const char_u *string, const char_u *esc_chars) * characters where rem_backslash() would remove the backslash. * Escape the characters with "cc". */ -char_u *vim_strsave_escaped_ext(const char_u *string, const char_u *esc_chars, - char_u cc, bool bsl) +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 { /* @@ -100,9 +98,10 @@ char_u *vim_strsave_escaped_ext(const char_u *string, const char_u *esc_chars, p += l - 1; continue; } - if (vim_strchr(esc_chars, *p) != NULL || (bsl && rem_backslash(p))) - ++length; /* count a backslash */ - ++length; /* count an ordinary char */ + if (vim_strchr(esc_chars, *p) != NULL || (bsl && rem_backslash(p))) { + ++length; // count a backslash + } + ++length; // count an ordinary char } char_u *escaped_string = xmalloc(length); @@ -112,11 +111,12 @@ char_u *vim_strsave_escaped_ext(const char_u *string, const char_u *esc_chars, if (l > 1) { memcpy(p2, p, l); p2 += l; - p += l - 1; /* skip multibyte char */ + p += l - 1; // skip multibyte char continue; } - if (vim_strchr(esc_chars, *p) != NULL || (bsl && rem_backslash(p))) + if (vim_strchr(esc_chars, *p) != NULL || (bsl && rem_backslash(p))) { *p2++ = cc; + } *p2++ = *p; } *p2 = NUL; @@ -182,12 +182,11 @@ char *vim_strnsave_unquoted(const char *const string, const size_t length) * 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(const 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 { - char_u *d; - char_u *escaped_string; + char_u *d; + char_u *escaped_string; size_t l; int csh_like; bool fish_like; @@ -202,7 +201,7 @@ char_u *vim_strsave_shellescape(const char_u *string, // itself must be escaped to get a literal '\'. fish_like = fish_like_shell(); - /* First count the number of extra bytes required. */ + // 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)) { #ifdef WIN32 @@ -217,12 +216,13 @@ char_u *vim_strsave_shellescape(const char_u *string, } if ((*p == '\n' && (csh_like || do_newline)) || (*p == '!' && (csh_like || do_special))) { - ++length; /* insert backslash */ - if (csh_like && do_special) - ++length; /* insert backslash */ + ++length; // insert backslash + if (csh_like && do_special) { + ++length; // insert backslash + } } if (do_special && find_cmdline_var(p, &l) >= 0) { - ++length; /* insert backslash */ + ++length; // insert backslash p += l - 1; } if (*p == '\\' && fish_like) { @@ -230,7 +230,7 @@ char_u *vim_strsave_shellescape(const char_u *string, } } - /* Allocate memory for the result and fill it. */ + // Allocate memory for the result and fill it. escaped_string = xmalloc(length); d = escaped_string; @@ -264,15 +264,17 @@ char_u *vim_strsave_shellescape(const char_u *string, if ((*p == '\n' && (csh_like || do_newline)) || (*p == '!' && (csh_like || do_special))) { *d++ = '\\'; - if (csh_like && do_special) + if (csh_like && do_special) { *d++ = '\\'; + } *d++ = *p++; continue; } if (do_special && find_cmdline_var(p, &l) >= 0) { - *d++ = '\\'; /* insert backslash */ - while (--l != SIZE_MAX) /* copy the var */ + *d++ = '\\'; // insert backslash + while (--l != SIZE_MAX) { // copy the var *d++ = *p++; + } continue; } if (*p == '\\' && fish_like) { @@ -285,11 +287,11 @@ char_u *vim_strsave_shellescape(const char_u *string, } // add terminating quote and finish with a NUL -# ifdef WIN32 +#ifdef WIN32 if (!p_ssl) { *d++ = '"'; } else -# endif +#endif *d++ = '\''; *d = NUL; @@ -384,11 +386,12 @@ char *strcase_save(const char *const orig, bool upper) void del_trailing_spaces(char_u *ptr) FUNC_ATTR_NONNULL_ALL { - char_u *q; + char_u *q; q = ptr + STRLEN(ptr); - while (--q > ptr && ascii_iswhite(q[0]) && q[-1] != '\\' && q[-1] != Ctrl_V) + while (--q > ptr && ascii_iswhite(q[0]) && q[-1] != '\\' && q[-1] != Ctrl_V) { *q = NUL; + } } #if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)) @@ -404,14 +407,16 @@ int vim_stricmp(const char *s1, const char *s2) for (;; ) { i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2); - if (i != 0) - return i; /* this character different */ - if (*s1 == NUL) - break; /* strings match until NUL */ + if (i != 0) { + return i; // this character different + } + if (*s1 == NUL) { + break; // strings match until NUL + } ++s1; ++s2; } - return 0; /* strings match */ + return 0; // strings match } #endif @@ -428,15 +433,17 @@ int vim_strnicmp(const char *s1, const char *s2, size_t len) while (len > 0) { i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2); - if (i != 0) - return i; /* this character different */ - if (*s1 == NUL) - break; /* strings match until NUL */ + if (i != 0) { + return i; // this character different + } + if (*s1 == NUL) { + break; // strings match until NUL + } ++s1; ++s2; --len; } - return 0; /* strings match */ + return 0; // strings match } #endif @@ -490,10 +497,13 @@ bool has_non_ascii(const char_u *s) { const char_u *p; - if (s != NULL) - for (p = s; *p != NUL; ++p) - if (*p >= 128) + if (s != NULL) { + for (p = s; *p != NUL; ++p) { + if (*p >= 128) { return true; + } + } + } return false; } @@ -504,7 +514,7 @@ bool has_non_ascii_len(const char *const s, const size_t len) { if (s != NULL) { for (size_t i = 0; i < len; i++) { - if ((uint8_t) s[i] >= 128) { + if ((uint8_t)s[i] >= 128) { return true; } } @@ -527,7 +537,7 @@ char_u *concat_str(const char_u *restrict str1, const char_u *restrict str2) static const char *const e_printf = - N_("E766: Insufficient arguments for printf()"); + N_("E766: Insufficient arguments for printf()"); /// Get number argument from idxp entry in tvs /// @@ -606,15 +616,14 @@ 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"); + 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) { @@ -735,8 +744,8 @@ int vim_snprintf(char *str, size_t str_m, const char *fmt, ...) // 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 *infinity_str(bool positive, char fmt_spec, int force_sign, + int space_for_positive) { static const char *table[] = { "-inf", "inf", "+inf", " inf", @@ -765,8 +774,7 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) /// /// @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_typval( - char *str, size_t str_m, const char *fmt, va_list ap, typval_T *const tvs) +int vim_vsnprintf_typval(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; @@ -800,7 +808,7 @@ int vim_vsnprintf_typval( char length_modifier = '\0'; // temporary buffer for simple numeric->string conversion -# define TMP_LEN 350 // 1e308 seems reasonable as the maximum printable +#define TMP_LEN 350 // 1e308 seems reasonable as the maximum printable char tmp[TMP_LEN]; // string address in case of string argument @@ -832,15 +840,22 @@ int vim_vsnprintf_typval( // 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; + 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; } @@ -905,444 +920,447 @@ int vim_vsnprintf_typval( // 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; + 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 'b': case 'B': - case 'd': case 'u': case 'o': case 'x': case 'X': - if (tvs && length_modifier == '\0') { - length_modifier = '2'; - } + case 'b': + case 'B': + 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; - } + // '%' 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 '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) { - char_u *p1; - size_t i = 0; - - for (p1 = (char_u *)str_arg; *p1; - p1 += mb_ptr2len(p1)) { - i += (size_t)utf_ptr2cells(p1); - if (i > precision) { - break; - } - } - str_arg_l = (size_t)(p1 - (char_u *)str_arg); + 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) { + char_u *p1; + size_t i = 0; + + for (p1 = (char_u *)str_arg; *p1; + p1 += mb_ptr2len(p1)) { + i += (size_t)utf_ptr2cells(p1); + if (i > precision) { + break; } } - break; - - default: - break; + str_arg_l = (size_t)(p1 - (char_u *)str_arg); + } } 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': { - arg = (int)(tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int)); - break; - } - case 'h': { - // char and short arguments are passed as int16_t - arg = (int16_t)(tvs ? 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 + 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': + arg = (int)(tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int)); + break; + case 'h': + // char and short arguments are passed as int16_t + arg = (int16_t)(tvs ? 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 + 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': { - uarg = (unsigned int)(tvs + break; + } + if (arg > 0) { + arg_sign = 1; + } else if (arg < 0) { + arg_sign = -1; + } + } else { + // unsigned + switch (length_modifier) { + case '\0': + uarg = (unsigned int)(tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, unsigned int)); - break; - } - case 'h': { - uarg = (uint16_t)(tvs + break; + case 'h': + uarg = (uint16_t)(tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, unsigned int)); - break; - } - case 'l': { - uarg = (tvs + 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 + 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 + break; + case 'z': + uarg = (tvs ? (size_t)tv_nr(tvs, &arg_idx) : va_arg(ap, size_t)); - break; - } - } - arg_sign = (uarg != 0); + break; } + arg_sign = (uarg != 0); + } - str_arg = tmp; - str_arg_l = 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; - } + // 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 ... + if (fmt_spec == 'd') { + if (force_sign && arg_sign >= 0) { + tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; } - - zero_padding_insertion_ind = str_arg_l; - if (!precision_specified) { - precision = 1; // default precision is 1 + // 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; } - 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; - } - } + // alternate form should have no effect for p * conversion, but ... + } - 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); + 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; } } - 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; + 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)); - { - 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; - } + // 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++; } - // 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; - } + 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; } - 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; + { + 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; + } - if (xisinf(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 (xisnan(f)) { - // Not a number: nan or NAN - memmove(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan", 4); - str_arg_l = 3; - zero_padding = 0; - } else { - // Regular float number - format[0] = '%'; - size_t l = 1; - if (force_sign) { - format[l++] = space_for_positive ? ' ' : '+'; - } - if (precision_specified) { - size_t max_prec = TMP_LEN - 10; + 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; + } - // 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); - } + if (xisinf(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 (xisnan(f)) { + // Not a number: nan or NAN + memmove(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan", 4); + str_arg_l = 3; + zero_padding = 0; + } else { + // Regular float number + format[0] = '%'; + size_t l = 1; + if (force_sign) { + format[l++] = space_for_positive ? ' ' : '+'; + } + if (precision_specified) { + size_t max_prec = TMP_LEN - 10; - // Cast to char to avoid a conversion warning on Ubuntu 12.04. - assert(l + 1 < sizeof(format)); - format[l] = (char)(fmt_spec == 'F' ? 'f' : fmt_spec); - format[l + 1] = NUL; + // 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); + } - str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); - assert(str_arg_l < sizeof(tmp)); + // Cast to char to avoid a conversion warning on Ubuntu 12.04. + assert(l + 1 < sizeof(format)); + format[l] = (char)(fmt_spec == 'F' ? 'f' : fmt_spec); + format[l + 1] = NUL; - if (remove_trailing_zeroes) { - int i; - char *tp; + str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); + assert(str_arg_l < sizeof(tmp)); - // 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 (remove_trailing_zeroes) { + int i; + char *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--; - } + // 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--; } - } 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); + 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 (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; + + 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; } + } + 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; + 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) { diff --git a/src/nvim/tag.c b/src/nvim/tag.c index c63cdad098..768cca284b 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -10,9 +10,7 @@ #include <stdbool.h> #include <string.h> -#include "nvim/vim.h" #include "nvim/ascii.h" -#include "nvim/tag.h" #include "nvim/buffer.h" #include "nvim/charset.h" #include "nvim/cursor.h" @@ -22,18 +20,21 @@ #include "nvim/ex_cmds2.h" #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" +#include "nvim/file_search.h" #include "nvim/fileio.h" #include "nvim/fold.h" +#include "nvim/garray.h" #include "nvim/if_cscope.h" #include "nvim/mark.h" #include "nvim/mbyte.h" +#include "nvim/memory.h" #include "nvim/message.h" #include "nvim/misc1.h" -#include "nvim/file_search.h" -#include "nvim/garray.h" -#include "nvim/memory.h" #include "nvim/move.h" #include "nvim/option.h" +#include "nvim/os/input.h" +#include "nvim/os/os.h" +#include "nvim/os/time.h" #include "nvim/os_unix.h" #include "nvim/path.h" #include "nvim/quickfix.h" @@ -41,30 +42,29 @@ #include "nvim/screen.h" #include "nvim/search.h" #include "nvim/strings.h" +#include "nvim/tag.h" #include "nvim/ui.h" +#include "nvim/vim.h" #include "nvim/window.h" -#include "nvim/os/os.h" -#include "nvim/os/time.h" -#include "nvim/os/input.h" /* * Structure to hold pointers to various items in a tag line. */ typedef struct tag_pointers { // filled in by parse_tag_line(): - char_u *tagname; // start of tag name (skip "file:") - char_u *tagname_end; // char after tag name - char_u *fname; // first char of file name - char_u *fname_end; // char after file name - char_u *command; // first char of command + char_u *tagname; // start of tag name (skip "file:") + char_u *tagname_end; // char after tag name + char_u *fname; // first char of file name + char_u *fname_end; // char after file name + char_u *command; // first char of command // filled in by parse_match(): - char_u *command_end; // first char after command - char_u *tag_fname; // file name of the tags file. This is used + char_u *command_end; // first char after command + char_u *tag_fname; // file name of the tags file. This is used // when 'tr' is set. - char_u *tagkind; // "kind:" value - char_u *tagkind_end; // end of tagkind - char_u *user_data; // user_data string - char_u *user_data_end; // end of user_data + char_u *tagkind; // "kind:" value + char_u *tagkind_end; // end of tagkind + char_u *user_data; // user_data string + char_u *user_data_end; // end of user_data linenr_T tagline; // "line:" value } tagptrs_T; @@ -72,11 +72,11 @@ typedef struct tag_pointers { * Structure to hold info about the tag pattern being used. */ typedef struct { - char_u *pat; /* the pattern */ - int len; /* length of pat[] */ - char_u *head; /* start of pattern head */ - int headlen; /* length of head[] */ - regmatch_T regmatch; /* regexp program, may be NULL */ + char_u *pat; // the pattern + int len; // length of pat[] + char_u *head; // start of pattern head + int headlen; // length of head[] + regmatch_T regmatch; // regexp program, may be NULL } pat_T; // The matching tags are first stored in one of the hash tables. In @@ -93,11 +93,11 @@ typedef struct { #define MT_MASK 7 // mask for printing priority #define MT_COUNT 16 -static char *mt_names[MT_COUNT/2] = -{"FSC", "F C", "F ", "FS ", " SC", " C", " ", " S "}; +static char *mt_names[MT_COUNT/2] = +{ "FSC", "F C", "F ", "FS ", " SC", " C", " ", " S " }; -#define NOTAGFILE 99 /* return value for jumpto_tag */ -static char_u *nofile_fname = NULL; /* fname for NOTAGFILE error */ +#define NOTAGFILE 99 // return value for jumpto_tag +static char_u *nofile_fname = NULL; // fname for NOTAGFILE error #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -111,7 +111,7 @@ static char_u *recurmsg static char_u *tfu_inv_ret_msg = (char_u *)N_("E987: invalid return value from tagfunc"); -static char_u *tagmatchname = NULL; /* name of last used tag */ +static char_u *tagmatchname = NULL; // name of last used tag /* * Tag for preview window is remembered separately, to avoid messing up the @@ -124,36 +124,31 @@ static int tfu_in_use = false; // disallow recursive call of tagfunc // Used instead of NUL to separate tag fields in the growarrays. #define TAG_SEP 0x02 -/* - * Jump to tag; handling of tag commands and tag stack - * - * *tag != NUL: ":tag {tag}", jump to new tag, add to tag stack - * - * type == DT_TAG: ":tag [tag]", jump to newer position or same tag again - * type == DT_HELP: like DT_TAG, but don't use regexp. - * type == DT_POP: ":pop" or CTRL-T, jump to old position - * type == DT_NEXT: jump to next match of same tag - * type == DT_PREV: jump to previous match of same tag - * type == DT_FIRST: jump to first match of same tag - * type == DT_LAST: jump to last match of same tag - * type == DT_SELECT: ":tselect [tag]", select tag from a list of all matches - * type == DT_JUMP: ":tjump [tag]", jump to tag or select tag from a list - * type == DT_CSCOPE: use cscope to find the tag - * type == DT_LTAG: use location list for displaying tag matches - * type == DT_FREE: free cached matches - * - * for cscope, returns TRUE if we jumped to tag or aborted, FALSE otherwise - */ -int -do_tag( - char_u *tag, // tag (pattern) to jump to - int type, - int count, - int forceit, // :ta with ! - int verbose // print "tag not found" message -) +/// Jump to tag; handling of tag commands and tag stack +/// +/// *tag != NUL: ":tag {tag}", jump to new tag, add to tag stack +/// +/// type == DT_TAG: ":tag [tag]", jump to newer position or same tag again +/// type == DT_HELP: like DT_TAG, but don't use regexp. +/// type == DT_POP: ":pop" or CTRL-T, jump to old position +/// type == DT_NEXT: jump to next match of same tag +/// type == DT_PREV: jump to previous match of same tag +/// type == DT_FIRST: jump to first match of same tag +/// type == DT_LAST: jump to last match of same tag +/// type == DT_SELECT: ":tselect [tag]", select tag from a list of all matches +/// type == DT_JUMP: ":tjump [tag]", jump to tag or select tag from a list +/// type == DT_CSCOPE: use cscope to find the tag +/// type == DT_LTAG: use location list for displaying tag matches +/// type == DT_FREE: free cached matches +/// +/// for cscope, returns TRUE if we jumped to tag or aborted, FALSE otherwise +/// +/// @param tag tag (pattern) to jump to +/// @param forceit :ta with ! +/// @param verbose print "tag not found" message +int do_tag(char_u *tag, int type, int count, int forceit, int verbose) { - taggy_T *tagstack = curwin->w_tagstack; + taggy_T *tagstack = curwin->w_tagstack; int tagstackidx = curwin->w_tagstackidx; int tagstacklen = curwin->w_tagstacklen; int cur_match = 0; @@ -170,16 +165,16 @@ do_tag( fmark_T saved_fmark; int jumped_to_tag = false; int new_num_matches; - char_u **new_matches; + char_u **new_matches; int use_tagstack; int skip_msg = false; char_u *buf_ffname = curbuf->b_ffname; // name for priority computation int use_tfu = 1; - /* remember the matches for the last used tag */ + // remember the matches for the last used tag static int num_matches = 0; - static int max_num_matches = 0; /* limit used for match search */ - static char_u **matches = NULL; + static int max_num_matches = 0; // limit used for match search + static char_u **matches = NULL; static int flags; if (tfu_in_use) { @@ -189,7 +184,7 @@ do_tag( #ifdef EXITFREE if (type == DT_FREE) { - /* remove the list of matches */ + // remove the list of matches FreeWild(num_matches, matches); cs_free_tags(); num_matches = 0; @@ -207,7 +202,7 @@ do_tag( free_string_option(nofile_fname); nofile_fname = NULL; - clearpos(&saved_fmark.mark); /* shutup gcc 4.0 */ + 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. @@ -226,7 +221,7 @@ do_tag( use_tagstack = true; } - /* new pattern, add to the tag stack */ + // new pattern, add to the tag stack if (*tag != NUL && (type == DT_TAG || type == DT_SELECT || type == DT_JUMP || type == DT_LTAG @@ -252,7 +247,7 @@ do_tag( tagstack_clear_entry(&tagstack[--tagstacklen]); } - /* if the tagstack is full: remove oldest entry */ + // if the tagstack is full: remove oldest entry if (++tagstacklen > TAGSTACKSIZE) { tagstacklen = TAGSTACKSIZE; tagstack_clear_entry(&tagstack[0]); @@ -293,7 +288,7 @@ do_tag( * way to the bottom now. */ tagstackidx = 0; - } else if (tagstackidx >= tagstacklen) { // count == 0? + } else if (tagstackidx >= tagstacklen) { // count == 0? EMSG(_(topmsg)); goto end_do_tag; } @@ -321,8 +316,9 @@ do_tag( curwin->w_cursor.col = saved_fmark.mark.col; curwin->w_set_curswant = true; check_cursor(); - if ((fdo_flags & FDO_TAG) && old_KeyTyped) + if ((fdo_flags & FDO_TAG) && old_KeyTyped) { foldOpenCursor(); + } // remove the old list of matches FreeWild(num_matches, matches); @@ -333,8 +329,7 @@ do_tag( } if (type == DT_TAG - || type == DT_LTAG - ) { + || type == DT_LTAG) { if (g_do_tagpreview != 0) { cur_match = ptag_entry.cur_match; cur_fnum = ptag_entry.cur_fnum; @@ -350,7 +345,7 @@ do_tag( tagstackidx = tagstacklen - 1; EMSG(_(topmsg)); save_pos = false; - } else if (tagstackidx < 0) { // must have been count == 0 + } else if (tagstackidx < 0) { // must have been count == 0 EMSG(_(bottommsg)); tagstackidx = 0; goto end_do_tag; @@ -367,23 +362,28 @@ do_tag( cur_match = ptag_entry.cur_match; cur_fnum = ptag_entry.cur_fnum; } else { - if (--tagstackidx < 0) + if (--tagstackidx < 0) { tagstackidx = 0; + } cur_match = tagstack[tagstackidx].cur_match; cur_fnum = tagstack[tagstackidx].cur_fnum; } switch (type) { - case DT_FIRST: cur_match = count - 1; break; + case DT_FIRST: + cur_match = count - 1; break; case DT_SELECT: case DT_JUMP: case DT_CSCOPE: - case DT_LAST: cur_match = MAXCOL - 1; break; - case DT_NEXT: cur_match += count; break; - case DT_PREV: cur_match -= count; break; + case DT_LAST: + cur_match = MAXCOL - 1; break; + case DT_NEXT: + cur_match += count; break; + case DT_PREV: + cur_match -= count; break; } - if (cur_match >= MAXCOL) + if (cur_match >= MAXCOL) { cur_match = MAXCOL - 1; - else if (cur_match < 0) { + } else if (cur_match < 0) { EMSG(_("E425: Cannot go before first matching tag")); skip_msg = true; cur_match = 0; @@ -424,8 +424,9 @@ do_tag( if (cur_fnum != curbuf->b_fnum) { buf_T *buf = buflist_findnr(cur_fnum); - if (buf != NULL) + if (buf != NULL) { buf_ffname = buf->b_ffname; + } } /* @@ -433,7 +434,7 @@ do_tag( */ for (;; ) { int other_name; - char_u *name; + char_u *name; // When desired match not found yet, try to find it (and others). if (use_tagstack) { @@ -466,8 +467,9 @@ do_tag( if (!no_regexp && *name == '/') { flags = TAG_REGEXP; ++name; - } else + } else { flags = TAG_NOIC; + } if (type == DT_CSCOPE) { flags = TAG_CSCOPE; @@ -490,9 +492,9 @@ do_tag( * to the start. Avoids that the order changes when using * ":tnext" and jumping to another file. */ if (!new_tag && !other_name) { - int j, k; - int idx = 0; - tagptrs_T tagp, tagp2; + int j, k; + int idx = 0; + tagptrs_T tagp, tagp2; // Find the position of each old match in the new list. Need // to use parse_match() to find the tag line. @@ -517,8 +519,9 @@ do_tag( } if (num_matches <= 0) { - if (verbose) + if (verbose) { EMSG2(_("E426: tag not found: %s"), name); + } g_do_tagpreview = 0; } else { bool ask_for_selection = false; @@ -533,7 +536,7 @@ do_tag( } else if (type == DT_SELECT || (type == DT_JUMP && num_matches > 1)) { print_tag_list(new_tag, use_tagstack, num_matches, matches); ask_for_selection = true; - } else if (type == DT_LTAG) { + } else if (type == DT_LTAG) { if (add_llist_tags(tag, num_matches, matches) == FAIL) { goto end_do_tag; } @@ -563,16 +566,17 @@ do_tag( * There will be an EMSG("file doesn't exist") below then. */ if ((type == DT_NEXT || type == DT_FIRST) && nofile_fname == NULL) { - if (num_matches == 1) + if (num_matches == 1) { EMSG(_("E427: There is only one matching tag")); - else + } else { EMSG(_("E428: Cannot go beyond last matching tag")); + } skip_msg = true; } cur_match = num_matches - 1; } if (use_tagstack) { - tagptrs_T tagp2; + tagptrs_T tagp2; tagstack[tagstackidx].cur_match = cur_match; tagstack[tagstackidx].cur_fnum = cur_fnum; @@ -581,12 +585,12 @@ do_tag( if (use_tfu && parse_match(matches[cur_match], &tagp2) == OK && tagp2.user_data) { XFREE_CLEAR(tagstack[tagstackidx].user_data); - tagstack[tagstackidx].user_data = vim_strnsave( - tagp2.user_data, tagp2.user_data_end - tagp2.user_data); + tagstack[tagstackidx].user_data = vim_strnsave(tagp2.user_data, + tagp2.user_data_end - tagp2.user_data); } tagstackidx++; - } else if (g_do_tagpreview != 0) { + } else if (g_do_tagpreview != 0) { ptag_entry.cur_match = cur_match; ptag_entry.cur_fnum = cur_fnum; } @@ -595,8 +599,9 @@ do_tag( * Only when going to try the next match, report that the previous * file didn't exist. Otherwise an EMSG() is given below. */ - if (nofile_fname != NULL && error_cur_match != cur_match) + if (nofile_fname != NULL && error_cur_match != cur_match) { smsg(_("File \"%s\" does not exist"), nofile_fname); + } ic = (matches[cur_match][0] & MT_IC_OFF); @@ -631,7 +636,7 @@ do_tag( // Let the SwapExists event know what tag we are jumping to. vim_snprintf((char *)IObuff, IOSIZE, ":ta %s\r", name); - set_vim_var_string(VV_SWAPCOMMAND, (char *) IObuff, -1); + set_vim_var_string(VV_SWAPCOMMAND, (char *)IObuff, -1); /* * Jump to the desired match. @@ -648,11 +653,12 @@ do_tag( && (max_num_matches != MAXCOL || cur_match < num_matches - 1))) { error_cur_match = cur_match; - if (use_tagstack) + if (use_tagstack) { --tagstackidx; - if (type == DT_PREV) + } + if (type == DT_PREV) { --cur_match; - else { + } else { type = DT_NEXT; ++cur_match; } @@ -662,8 +668,9 @@ do_tag( } else { /* We may have jumped to another window, check that * tagstackidx is still valid. */ - if (use_tagstack && tagstackidx > curwin->w_tagstacklen) + if (use_tagstack && tagstackidx > curwin->w_tagstacklen) { tagstackidx = curwin->w_tagstackidx; + } jumped_to_tag = true; } } @@ -684,331 +691,322 @@ end_do_tag: // // List all the matching tags. // -static void -print_tag_list( - int new_tag, - int use_tagstack, - int num_matches, - char_u **matches) +static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char_u **matches) { - taggy_T *tagstack = curwin->w_tagstack; - int tagstackidx = curwin->w_tagstackidx; - int i; - char_u *p; - char_u *command_end; - tagptrs_T tagp; - int taglen; - int attr; - - // Assume that the first match indicates how long the tags can - // be, and align the file names to that. - parse_match(matches[0], &tagp); - taglen = (int)(tagp.tagname_end - tagp.tagname + 2); - if (taglen < 18) { - taglen = 18; - } - if (taglen > Columns - 25) { - taglen = MAXCOL; - } - if (msg_col == 0) { - msg_didout = false; // overwrite previous message - } - msg_start(); - msg_puts_attr(_(" # pri kind tag"), HL_ATTR(HLF_T)); - msg_clr_eos(); + taggy_T *tagstack = curwin->w_tagstack; + int tagstackidx = curwin->w_tagstackidx; + int i; + char_u *p; + char_u *command_end; + tagptrs_T tagp; + int taglen; + int attr; + + // Assume that the first match indicates how long the tags can + // be, and align the file names to that. + parse_match(matches[0], &tagp); + taglen = (int)(tagp.tagname_end - tagp.tagname + 2); + if (taglen < 18) { + taglen = 18; + } + if (taglen > Columns - 25) { + taglen = MAXCOL; + } + if (msg_col == 0) { + msg_didout = false; // overwrite previous message + } + msg_start(); + msg_puts_attr(_(" # pri kind tag"), HL_ATTR(HLF_T)); + msg_clr_eos(); + taglen_advance(taglen); + msg_puts_attr(_("file\n"), HL_ATTR(HLF_T)); + + for (i = 0; i < num_matches && !got_int; i++) { + parse_match(matches[i], &tagp); + if (!new_tag && ( + (g_do_tagpreview != 0 + && i == ptag_entry.cur_match) + || (use_tagstack + && i == tagstack[tagstackidx].cur_match))) { + *IObuff = '>'; + } else { + *IObuff = ' '; + } + vim_snprintf((char *)IObuff + 1, IOSIZE - 1, + "%2d %s ", i + 1, + mt_names[matches[i][0] & MT_MASK]); + msg_puts((char *)IObuff); + if (tagp.tagkind != NULL) { + msg_outtrans_len(tagp.tagkind, + (int)(tagp.tagkind_end - tagp.tagkind)); + } + msg_advance(13); + msg_outtrans_len_attr(tagp.tagname, + (int)(tagp.tagname_end - tagp.tagname), + HL_ATTR(HLF_T)); + msg_putchar(' '); taglen_advance(taglen); - msg_puts_attr(_("file\n"), HL_ATTR(HLF_T)); - - for (i = 0; i < num_matches && !got_int; i++) { - parse_match(matches[i], &tagp); - if (!new_tag && ( - (g_do_tagpreview != 0 - && i == ptag_entry.cur_match) - || (use_tagstack - && i == tagstack[tagstackidx].cur_match))) { - *IObuff = '>'; - } else { - *IObuff = ' '; + + // Find out the actual file name. If it is long, truncate + // it and put "..." in the middle + p = tag_full_fname(&tagp); + if (p != NULL) { + msg_outtrans_attr(p, HL_ATTR(HLF_D)); + XFREE_CLEAR(p); + } + if (msg_col > 0) { + msg_putchar('\n'); + } + if (got_int) { + break; + } + msg_advance(15); + + // print any extra fields + command_end = tagp.command_end; + if (command_end != NULL) { + p = command_end + 3; + while (*p && *p != '\r' && *p != '\n') { + while (*p == TAB) { + p++; } - vim_snprintf((char *)IObuff + 1, IOSIZE - 1, - "%2d %s ", i + 1, - mt_names[matches[i][0] & MT_MASK]); - msg_puts((char *)IObuff); - if (tagp.tagkind != NULL) { - msg_outtrans_len(tagp.tagkind, - (int)(tagp.tagkind_end - tagp.tagkind)); + + // skip "file:" without a value (static tag) + if (STRNCMP(p, "file:", 5) == 0 && ascii_isspace(p[5])) { + p += 5; + continue; } - msg_advance(13); - msg_outtrans_len_attr(tagp.tagname, - (int)(tagp.tagname_end - tagp.tagname), - HL_ATTR(HLF_T)); - msg_putchar(' '); - taglen_advance(taglen); - - // Find out the actual file name. If it is long, truncate - // it and put "..." in the middle - p = tag_full_fname(&tagp); - if (p != NULL) { - msg_outtrans_attr(p, HL_ATTR(HLF_D)); - XFREE_CLEAR(p); + // skip "kind:<kind>" and "<kind>" + if (p == tagp.tagkind + || (p + 5 == tagp.tagkind + && STRNCMP(p, "kind:", 5) == 0)) { + p = tagp.tagkind_end; + continue; } - if (msg_col > 0) { + // print all other extra fields + attr = HL_ATTR(HLF_CM); + while (*p && *p != '\r' && *p != '\n') { + if (msg_col + ptr2cells(p) >= Columns) { msg_putchar('\n'); + if (got_int) { + break; + } + msg_advance(15); + } + p = msg_outtrans_one(p, attr); + if (*p == TAB) { + msg_puts_attr(" ", attr); + break; + } + if (*p == ':') { + attr = 0; + } } + } + if (msg_col > 15) { + msg_putchar('\n'); if (got_int) { - break; + break; } msg_advance(15); + } + } else { + for (p = tagp.command; + *p && *p != '\r' && *p != '\n'; + p++) { + } + command_end = p; + } - // print any extra fields - command_end = tagp.command_end; - if (command_end != NULL) { - p = command_end + 3; - while (*p && *p != '\r' && *p != '\n') { - while (*p == TAB) { - p++; - } - - // skip "file:" without a value (static tag) - if (STRNCMP(p, "file:", 5) == 0 && ascii_isspace(p[5])) { - p += 5; - continue; - } - // skip "kind:<kind>" and "<kind>" - if (p == tagp.tagkind - || (p + 5 == tagp.tagkind - && STRNCMP(p, "kind:", 5) == 0)) { - p = tagp.tagkind_end; - continue; - } - // print all other extra fields - attr = HL_ATTR(HLF_CM); - while (*p && *p != '\r' && *p != '\n') { - if (msg_col + ptr2cells(p) >= Columns) { - msg_putchar('\n'); - if (got_int) { - break; - } - msg_advance(15); - } - p = msg_outtrans_one(p, attr); - if (*p == TAB) { - msg_puts_attr(" ", attr); - break; - } - if (*p == ':') { - attr = 0; - } - } - } - if (msg_col > 15) { - msg_putchar('\n'); - if (got_int) { - break; - } - msg_advance(15); - } - } else { - for (p = tagp.command; - *p && *p != '\r' && *p != '\n'; - p++) { - } - command_end = p; - } - - // Put the info (in several lines) at column 15. - // Don't display "/^" and "?^". - p = tagp.command; - if (*p == '/' || *p == '?') { - p++; - if (*p == '^') { - p++; - } - } - // Remove leading whitespace from pattern - while (p != command_end && ascii_isspace(*p)) { - p++; - } + // Put the info (in several lines) at column 15. + // Don't display "/^" and "?^". + p = tagp.command; + if (*p == '/' || *p == '?') { + p++; + if (*p == '^') { + p++; + } + } + // Remove leading whitespace from pattern + while (p != command_end && ascii_isspace(*p)) { + p++; + } - while (p != command_end) { - if (msg_col + (*p == TAB ? 1 : ptr2cells(p)) > Columns) { - msg_putchar('\n'); - } - if (got_int) { - break; - } - msg_advance(15); + while (p != command_end) { + if (msg_col + (*p == TAB ? 1 : ptr2cells(p)) > Columns) { + msg_putchar('\n'); + } + if (got_int) { + break; + } + msg_advance(15); - // skip backslash used for escaping a command char or - // a backslash - if (*p == '\\' && (*(p + 1) == *tagp.command - || *(p + 1) == '\\')) { - p++; - } + // skip backslash used for escaping a command char or + // a backslash + if (*p == '\\' && (*(p + 1) == *tagp.command + || *(p + 1) == '\\')) { + p++; + } - if (*p == TAB) { - msg_putchar(' '); - p++; - } else { - p = msg_outtrans_one(p, 0); - } + if (*p == TAB) { + msg_putchar(' '); + p++; + } else { + p = msg_outtrans_one(p, 0); + } - // don't display the "$/;\"" and "$?;\"" - if (p == command_end - 2 && *p == '$' - && *(p + 1) == *tagp.command) { - break; - } - // don't display matching '/' or '?' - if (p == command_end - 1 && *p == *tagp.command - && (*p == '/' || *p == '?')) { - break; - } - } - if (msg_col) { - msg_putchar('\n'); - } - os_breakcheck(); + // don't display the "$/;\"" and "$?;\"" + if (p == command_end - 2 && *p == '$' + && *(p + 1) == *tagp.command) { + break; + } + // don't display matching '/' or '?' + if (p == command_end - 1 && *p == *tagp.command + && (*p == '/' || *p == '?')) { + break; + } } - if (got_int) { - got_int = false; // only stop the listing + if (msg_col) { + msg_putchar('\n'); } + os_breakcheck(); + } + if (got_int) { + got_int = false; // only stop the listing + } } // // Add the matching tags to the location list for the current // window. // -static int -add_llist_tags( - char_u *tag, - int num_matches, - char_u **matches) +static int add_llist_tags(char_u *tag, int num_matches, char_u **matches) { - list_T *list; - char_u tag_name[128 + 1]; - char_u *fname; - char_u *cmd; - int i; - char_u *p; - tagptrs_T tagp; - - fname = xmalloc(MAXPATHL + 1); - cmd = xmalloc(CMDBUFFSIZE + 1); - list = tv_list_alloc(0); - - for (i = 0; i < num_matches; i++) { - int len, cmd_len; - long lnum; - dict_T *dict; - - parse_match(matches[i], &tagp); - - // Save the tag name - len = (int)(tagp.tagname_end - tagp.tagname); - if (len > 128) { - len = 128; - } - xstrlcpy((char *)tag_name, (const char *)tagp.tagname, len + 1); - tag_name[len] = NUL; + list_T *list; + char_u tag_name[128 + 1]; + char_u *fname; + char_u *cmd; + int i; + char_u *p; + tagptrs_T tagp; - // Save the tag file name - p = tag_full_fname(&tagp); - if (p == NULL) { - continue; - } - xstrlcpy((char *)fname, (const char *)p, MAXPATHL); - XFREE_CLEAR(p); - - // Get the line number or the search pattern used to locate - // the tag. - lnum = 0; - if (isdigit(*tagp.command)) { - // Line number is used to locate the tag - lnum = atol((char *)tagp.command); - } else { - char_u *cmd_start, *cmd_end; + fname = xmalloc(MAXPATHL + 1); + cmd = xmalloc(CMDBUFFSIZE + 1); + list = tv_list_alloc(0); - // Search pattern is used to locate the tag + for (i = 0; i < num_matches; i++) { + int len, cmd_len; + long lnum; + dict_T *dict; - // Locate the end of the command - cmd_start = tagp.command; - cmd_end = tagp.command_end; - if (cmd_end == NULL) { - for (p = tagp.command; - *p && *p != '\r' && *p != '\n'; p++) { - } - cmd_end = p; - } + parse_match(matches[i], &tagp); - // Now, cmd_end points to the character after the - // command. Adjust it to point to the last - // character of the command. - cmd_end--; + // Save the tag name + len = (int)(tagp.tagname_end - tagp.tagname); + if (len > 128) { + len = 128; + } + xstrlcpy((char *)tag_name, (const char *)tagp.tagname, len + 1); + tag_name[len] = NUL; - // Skip the '/' and '?' characters at the - // beginning and end of the search pattern. - if (*cmd_start == '/' || *cmd_start == '?') { - cmd_start++; - } + // Save the tag file name + p = tag_full_fname(&tagp); + if (p == NULL) { + continue; + } + xstrlcpy((char *)fname, (const char *)p, MAXPATHL); + XFREE_CLEAR(p); + + // Get the line number or the search pattern used to locate + // the tag. + lnum = 0; + if (isdigit(*tagp.command)) { + // Line number is used to locate the tag + lnum = atol((char *)tagp.command); + } else { + char_u *cmd_start, *cmd_end; - if (*cmd_end == '/' || *cmd_end == '?') { - cmd_end--; - } + // Search pattern is used to locate the tag - len = 0; - cmd[0] = NUL; + // Locate the end of the command + cmd_start = tagp.command; + cmd_end = tagp.command_end; + if (cmd_end == NULL) { + for (p = tagp.command; + *p && *p != '\r' && *p != '\n'; p++) { + } + cmd_end = p; + } - // If "^" is present in the tag search pattern, then - // copy it first. - if (*cmd_start == '^') { - STRCPY(cmd, "^"); - cmd_start++; - len++; - } + // Now, cmd_end points to the character after the + // command. Adjust it to point to the last + // character of the command. + cmd_end--; - // Precede the tag pattern with \V to make it very - // nomagic. - STRCAT(cmd, "\\V"); - len += 2; + // Skip the '/' and '?' characters at the + // beginning and end of the search pattern. + if (*cmd_start == '/' || *cmd_start == '?') { + cmd_start++; + } - cmd_len = (int)(cmd_end - cmd_start + 1); - if (cmd_len > (CMDBUFFSIZE - 5)) { - cmd_len = CMDBUFFSIZE - 5; - } - snprintf((char *)cmd + len, CMDBUFFSIZE + 1 - len, - "%.*s", cmd_len, cmd_start); - len += cmd_len; - - if (cmd[len - 1] == '$') { - // Replace '$' at the end of the search pattern - // with '\$' - cmd[len - 1] = '\\'; - cmd[len] = '$'; - len++; - } + if (*cmd_end == '/' || *cmd_end == '?') { + cmd_end--; + } - cmd[len] = NUL; - } + len = 0; + cmd[0] = NUL; - dict = tv_dict_alloc(); - tv_list_append_dict(list, dict); + // If "^" is present in the tag search pattern, then + // copy it first. + if (*cmd_start == '^') { + STRCPY(cmd, "^"); + cmd_start++; + len++; + } - 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); - } + // Precede the tag pattern with \V to make it very + // nomagic. + STRCAT(cmd, "\\V"); + len += 2; + + cmd_len = (int)(cmd_end - cmd_start + 1); + if (cmd_len > (CMDBUFFSIZE - 5)) { + cmd_len = CMDBUFFSIZE - 5; + } + snprintf((char *)cmd + len, CMDBUFFSIZE + 1 - len, + "%.*s", cmd_len, cmd_start); + len += cmd_len; + + if (cmd[len - 1] == '$') { + // Replace '$' at the end of the search pattern + // with '\$' + cmd[len - 1] = '\\'; + cmd[len] = '$'; + len++; + } + + cmd[len] = NUL; } - vim_snprintf((char *)IObuff, IOSIZE, "ltag %s", tag); - set_errorlist(curwin, list, ' ', IObuff, NULL); + dict = tv_dict_alloc(); + tv_list_append_dict(list, dict); - tv_list_free(list); - XFREE_CLEAR(fname); - XFREE_CLEAR(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); + } + } - return OK; + vim_snprintf((char *)IObuff, IOSIZE, "ltag %s", tag); + set_errorlist(curwin, list, ' ', IObuff, NULL); + + tv_list_free(list); + XFREE_CLEAR(fname); + XFREE_CLEAR(cmd); + + return OK; } /* @@ -1024,8 +1022,9 @@ static void taglen_advance(int l) if (l == MAXCOL) { msg_putchar('\n'); msg_advance(24); - } else + } else { msg_advance(13 + l); + } } /* @@ -1034,18 +1033,19 @@ static void taglen_advance(int l) void do_tags(exarg_T *eap) { int i; - char_u *name; - taggy_T *tagstack = curwin->w_tagstack; + char_u *name; + taggy_T *tagstack = curwin->w_tagstack; int tagstackidx = curwin->w_tagstackidx; int tagstacklen = curwin->w_tagstacklen; - /* Highlight title */ + // Highlight title MSG_PUTS_TITLE(_("\n # TO tag FROM line in file/text")); for (i = 0; i < tagstacklen; ++i) { if (tagstack[i].tagname != NULL) { name = fm_getname(&(tagstack[i].fmark), 30); - if (name == NULL) /* file name not available */ + if (name == NULL) { // file name not available continue; + } msg_putchar('\n'); vim_snprintf((char *)IObuff, IOSIZE, "%c%2d %2d %-15s %5ld ", @@ -1059,10 +1059,11 @@ void do_tags(exarg_T *eap) ? HL_ATTR(HLF_D) : 0); xfree(name); } - ui_flush(); /* show one line at a time */ + ui_flush(); // show one line at a time } - if (tagstackidx == tagstacklen) /* idx at top of stack */ + if (tagstackidx == tagstacklen) { // idx at top of stack MSG_PUTS("\n>"); + } } @@ -1078,15 +1079,17 @@ static int tag_strnicmp(char_u *s1, char_u *s2, size_t len) while (len > 0) { i = TOUPPER_ASC(*s1) - TOUPPER_ASC(*s2); - if (i != 0) - return i; /* this character different */ - if (*s1 == NUL) - break; /* strings match until NUL */ + if (i != 0) { + return i; // this character different + } + if (*s1 == NUL) { + break; // strings match until NUL + } ++s1; ++s2; --len; } - return 0; /* strings match */ + return 0; // strings match } @@ -1100,48 +1103,54 @@ static void prepare_pats(pat_T *pats, int has_re) if (has_re) { /* When the pattern starts with '^' or "\\<", binary searching can be * used (much faster). */ - if (pats->pat[0] == '^') + if (pats->pat[0] == '^') { pats->head = pats->pat + 1; - else if (pats->pat[0] == '\\' && pats->pat[1] == '<') + } else if (pats->pat[0] == '\\' && pats->pat[1] == '<') { pats->head = pats->pat + 2; - if (pats->head == pats->pat) + } + if (pats->head == pats->pat) { pats->headlen = 0; - else + } else { for (pats->headlen = 0; pats->head[pats->headlen] != NUL; - ++pats->headlen) + ++pats->headlen) { if (vim_strchr((char_u *)(p_magic ? ".[~*\\$" : "\\$"), - pats->head[pats->headlen]) != NULL) + pats->head[pats->headlen]) != NULL) { break; - if (p_tl != 0 && pats->headlen > p_tl) /* adjust for 'taglength' */ + } + } + } + if (p_tl != 0 && pats->headlen > p_tl) { // adjust for 'taglength' pats->headlen = p_tl; + } } - if (has_re) + if (has_re) { pats->regmatch.regprog = vim_regcomp(pats->pat, p_magic ? RE_MAGIC : 0); - else + } else { pats->regmatch.regprog = NULL; + } } -// -// Call the user-defined function to generate a list of tags used by -// find_tags(). -// -// Return OK if at least 1 tag has been successfully found, -// NOTDONE if the function returns v:null, and FAIL otherwise. -// -static int find_tagfunc_tags( - char_u *pat, // pattern supplied to the user-defined function - garray_T *ga, // the tags will be placed here - int *match_count, // here the number of tags found will be placed - int flags, // flags from find_tags (TAG_*) - char_u *buf_ffname) // name of buffer for priority +/// Call the user-defined function to generate a list of tags used by +/// find_tags(). +/// +/// Return OK if at least 1 tag has been successfully found, +/// NOTDONE if the function returns v:null, and FAIL otherwise. +/// +/// @param pat pattern supplied to the user-defined function +/// @param ga the tags will be placed here +/// @param match_count here the number of tags found will be placed +/// @param flags flags from find_tags (TAG_*) +/// @param buf_ffname name of buffer for priority +static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int flags, + char_u *buf_ffname) { - pos_T save_pos; - list_T *taglist; - int ntags = 0; - int result = FAIL; - typval_T args[4]; - typval_T rettv; + pos_T save_pos; + list_T *taglist; + int ntags = 0; + int result = FAIL; + typval_T args[4]; + typval_T rettv; char_u flagString[4]; taggy_T *tag = &curwin->w_tagstack[curwin->w_tagstackidx]; @@ -1195,12 +1204,12 @@ static int find_tagfunc_tags( taglist = rettv.vval.v_list; TV_LIST_ITER_CONST(taglist, li, { - char_u *res_name; - char_u *res_fname; - char_u *res_cmd; - char_u *res_kind; - int has_extra = 0; - int name_only = flags & TAG_NAMES; + char_u *res_name; + char_u *res_fname; + char_u *res_cmd; + char_u *res_kind; + int has_extra = 0; + int name_only = flags & TAG_NAMES; if (TV_LIST_ITEM_TV(li)->v_type != VAR_DICT) { EMSG(_(tfu_inv_ret_msg)); @@ -1326,50 +1335,46 @@ static int find_tagfunc_tags( return result; } -/* - * find_tags() - search for tags in tags files - * - * Return FAIL if search completely failed (*num_matches will be 0, *matchesp - * will be NULL), OK otherwise. - * - * There is a priority in which type of tag is recognized. - * - * 6. A static or global tag with a full matching tag for the current file. - * 5. A global tag with a full matching tag for another file. - * 4. A static tag with a full matching tag for another file. - * 3. A static or global tag with an ignore-case matching tag for the - * current file. - * 2. A global tag with an ignore-case matching tag for another file. - * 1. A static tag with an ignore-case matching tag for another file. - * - * Tags in an emacs-style tags file are always global. - * - * flags: - * TAG_HELP only search for help tags - * TAG_NAMES only return name of tag - * 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 - * TAG_NO_TAGFUNC do not call the 'tagfunc' function - */ -int -find_tags( - char_u *pat, // pattern to search for - int *num_matches, // return: number of matches found - char_u ***matchesp, // return: array of matches found - int flags, - int mincount, /* MAXCOL: find all matches - other: minimal number of matches */ - char_u *buf_ffname /* name of buffer for priority */ -) +/// find_tags() - search for tags in tags files +/// +/// Return FAIL if search completely failed (*num_matches will be 0, *matchesp +/// will be NULL), OK otherwise. +/// +/// There is a priority in which type of tag is recognized. +/// +/// 6. A static or global tag with a full matching tag for the current file. +/// 5. A global tag with a full matching tag for another file. +/// 4. A static tag with a full matching tag for another file. +/// 3. A static or global tag with an ignore-case matching tag for the +/// current file. +/// 2. A global tag with an ignore-case matching tag for another file. +/// 1. A static tag with an ignore-case matching tag for another file. +/// +/// Tags in an emacs-style tags file are always global. +/// +/// flags: +/// TAG_HELP only search for help tags +/// TAG_NAMES only return name of tag +/// 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 +/// TAG_NO_TAGFUNC do not call the 'tagfunc' function +/// +/// @param pat pattern to search for +/// @param num_matches return: number of matches found +/// @param matchesp return: array of matches found +/// @param mincount MAXCOL: find all matches other: minimal number of matches */ +/// @param buf_ffname name of buffer for priority +int find_tags(char_u *pat, int *num_matches, char_u ***matchesp, int flags, int mincount, + char_u *buf_ffname) { - FILE *fp; - char_u *lbuf; /* line buffer */ - int lbuf_size = LSIZE; /* length of lbuf */ - char_u *tag_fname; /* name of tag file */ - tagname_T tn; /* info for get_tagfname() */ - int first_file; /* trying first tag file */ + FILE *fp; + char_u *lbuf; // line buffer + int lbuf_size = LSIZE; // length of lbuf + char_u *tag_fname; // name of tag file + tagname_T tn; // info for get_tagfname() + int first_file; // trying first tag file tagptrs_T tagp; bool did_open = false; // did open a tag file bool stop_searching = false; // stop when match found or error @@ -1377,8 +1382,8 @@ find_tags( int is_static; // current tag line is static int is_current; // file name matches bool eof = false; // found end-of-file - char_u *p; - char_u *s; + 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 @@ -1396,17 +1401,17 @@ find_tags( off_T offset; int round; enum { - TS_START, /* at start of file */ - TS_LINEAR /* linear searching forward, till EOF */ - , TS_BINARY, /* binary searching */ - TS_SKIP_BACK, /* skipping backwards */ - TS_STEP_FORWARD /* stepping forwards */ - } state; /* Current search state */ + TS_START, // at start of file + TS_LINEAR // linear searching forward, till EOF + , TS_BINARY, // binary searching + TS_SKIP_BACK, // skipping backwards + TS_STEP_FORWARD // stepping forwards + } state; // Current search state int cmplen; - int match; /* matches */ - int match_no_ic = 0; /* matches with rm_ic == FALSE */ - int match_re; /* match with regexp */ + int match; // matches + int match_no_ic = 0; // matches with rm_ic == FALSE + int match_re; // match with regexp int matchoff = 0; int save_emsg_off; @@ -1416,16 +1421,16 @@ find_tags( 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; + 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_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 *saved_pat = NULL; // copy of pat[] bool is_txt = false; - pat_T orgpat; /* holds unconverted pattern info */ + pat_T orgpat; // holds unconverted pattern info vimconv_T vimconv; int findall = (mincount == MAXCOL || mincount == TAG_MANY); @@ -1447,22 +1452,22 @@ find_tags( // Change the value of 'ignorecase' according to 'tagcase' for the // duration of this function. switch (curbuf->b_tc_flags ? curbuf->b_tc_flags : tc_flags) { - case TC_FOLLOWIC: - break; - case TC_IGNORE: - p_ic = true; - break; - 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: - abort(); + case TC_FOLLOWIC: + break; + case TC_IGNORE: + p_ic = true; + break; + 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: + abort(); } help_save = curbuf->b_help; @@ -1480,7 +1485,7 @@ find_tags( hash_init(&ht_match[mtt]); } - STRCPY(tag_fname, "from cscope"); /* for error messages */ + STRCPY(tag_fname, "from cscope"); // for error messages /* * Initialize a few variables @@ -1506,15 +1511,17 @@ find_tags( orgpat.len -= 3; } } - if (p_tl != 0 && orgpat.len > p_tl) /* adjust for 'taglength' */ + if (p_tl != 0 && orgpat.len > p_tl) { // adjust for 'taglength' orgpat.len = p_tl; + } save_emsg_off = emsg_off; - emsg_off = TRUE; /* don't want error for invalid RE here */ + emsg_off = TRUE; // don't want error for invalid RE here prepare_pats(&orgpat, has_re); emsg_off = save_emsg_off; - if (has_re && orgpat.regmatch.regprog == NULL) + if (has_re && orgpat.regmatch.regprog == NULL) { goto findtag_end; + } // This is only to avoid a compiler warning for using search_info // uninitialised. @@ -1580,8 +1587,9 @@ find_tags( /* When searching for a specific language skip tags files * for other languages. */ if (help_lang_find != NULL - && STRICMP(help_lang, help_lang_find) != 0) + && STRICMP(help_lang, help_lang_find) != 0) { continue; + } /* For CTRL-] in a help file prefer a match with the same * language. */ @@ -1591,23 +1599,26 @@ find_tags( && (i = (int)STRLEN(curbuf->b_fname)) > 4 && curbuf->b_fname[i - 1] == 'x' && curbuf->b_fname[i - 4] == '.' - && STRNICMP(curbuf->b_fname + i - 3, help_lang, 2) == 0) + && STRNICMP(curbuf->b_fname + i - 3, help_lang, 2) == 0) { help_pri = 0; - else { + } else { help_pri = 1; for (s = p_hlg; *s != NUL; ++s) { - if (STRNICMP(s, help_lang, 2) == 0) + if (STRNICMP(s, help_lang, 2) == 0) { break; + } ++help_pri; - if ((s = vim_strchr(s, ',')) == NULL) + if ((s = vim_strchr(s, ',')) == NULL) { break; + } } if (s == NULL || *s == NUL) { /* Language not in 'helplang': use last, prefer English, * unless found already. */ ++help_pri; - if (STRICMP(help_lang, "en") != 0) + if (STRICMP(help_lang, "en") != 0) { ++help_pri; + } } } } @@ -1624,7 +1635,7 @@ find_tags( } did_open = true; // remember that we found at least one file - state = TS_START; /* we're at the start of the file */ + state = TS_START; // we're at the start of the file /* * Read and parse the lines in the file one by one @@ -1636,8 +1647,9 @@ find_tags( } else { fast_breakcheck(); } - if ((flags & TAG_INS_COMP)) /* Double brackets for gcc */ + if ((flags & TAG_INS_COMP)) { // Double brackets for gcc ins_compl_check_keys(30, false); + } if (got_int || compl_interrupted) { stop_searching = true; break; @@ -1649,18 +1661,20 @@ find_tags( retval = OK; break; } - if (get_it_again) + if (get_it_again) { goto line_read_in; + } /* * For binary search: compute the next offset to use. */ if (state == TS_BINARY) { offset = search_info.low_offset + ((search_info.high_offset - search_info.low_offset) / 2); - if (offset == search_info.curr_offset) - break; /* End the binary search without a match. */ - else + if (offset == search_info.curr_offset) { + break; // End the binary search without a match. + } else { search_info.curr_offset = offset; + } } else if (state == TS_SKIP_BACK) { // Skipping back (after a match during binary search). search_info.curr_offset -= lbuf_size * 2; @@ -1676,7 +1690,7 @@ find_tags( * start of the next line. */ if (state == TS_BINARY || state == TS_SKIP_BACK) { - /* Adjust the search file offset to the correct position */ + // Adjust the search file offset to the correct position search_info.curr_offset_used = search_info.curr_offset; vim_fseek(fp, search_info.curr_offset, SEEK_SET); eof = vim_fgets(lbuf, lbuf_size, fp); @@ -1691,13 +1705,13 @@ find_tags( } eof = vim_fgets(lbuf, lbuf_size, fp); } - /* skip empty and blank lines */ + // skip empty and blank lines while (!eof && vim_isblankline(lbuf)) { search_info.curr_offset = vim_ftell(fp); eof = vim_fgets(lbuf, lbuf_size, fp); } if (eof) { - /* Hit end of file. Skip backwards. */ + // Hit end of file. Skip backwards. state = TS_SKIP_BACK; search_info.match_offset = vim_ftell(fp); search_info.curr_offset = search_info.curr_offset_used; @@ -1708,7 +1722,7 @@ find_tags( * Not jumping around in the file: Read the next line. */ else { - /* skip empty and blank lines */ + // skip empty and blank lines do { eof = use_cscope ? cs_fgets(lbuf, lbuf_size) @@ -1716,13 +1730,13 @@ find_tags( } while (!eof && vim_isblankline(lbuf)); if (eof) { - break; /* end of file */ + break; // end of file } } line_read_in: if (vimconv.vc_type != CONV_NONE) { - char_u *conv_line; + char_u *conv_line; int len; /* Convert every line. Converting the pattern from 'enc' to @@ -1730,7 +1744,7 @@ line_read_in: * not recognized. */ conv_line = string_convert(&vimconv, lbuf, NULL); if (conv_line != NULL) { - /* Copy or swap lbuf and conv_line. */ + // Copy or swap lbuf and conv_line. len = (int)STRLEN(conv_line) + 1; if (len > lbuf_size) { xfree(lbuf); @@ -1754,30 +1768,33 @@ line_read_in: * case is folded lower case letters sort before "_". */ if (STRNCMP(lbuf, "!_TAG_", 6) <= 0 || (lbuf[0] == '!' && ASCII_ISLOWER(lbuf[1]))) { - if (STRNCMP(lbuf, "!_TAG_", 6) != 0) + if (STRNCMP(lbuf, "!_TAG_", 6) != 0) { /* Non-header item before the header, e.g. "!" itself. */ goto parse_line; + } /* * Read header line. */ - if (STRNCMP(lbuf, "!_TAG_FILE_SORTED\t", 18) == 0) + if (STRNCMP(lbuf, "!_TAG_FILE_SORTED\t", 18) == 0) { tag_file_sorted = lbuf[18]; + } if (STRNCMP(lbuf, "!_TAG_FILE_ENCODING\t", 20) == 0) { /* Prepare to convert every line from the specified * encoding to 'encoding'. */ - for (p = lbuf + 20; *p > ' ' && *p < 127; ++p) + for (p = lbuf + 20; *p > ' ' && *p < 127; ++p) { ; + } *p = NUL; convert_setup(&vimconv, lbuf + 20, p_enc); } - /* Read the next line. Unrecognized flags are ignored. */ + // Read the next line. Unrecognized flags are ignored. continue; } - /* Headers ends. */ + // Headers ends. /* * When there is no tag head, or ignoring case, need to do a @@ -1788,18 +1805,19 @@ line_read_in: * flag set. * For cscope, it's always linear. */ - if (linear || use_cscope) + if (linear || use_cscope) { state = TS_LINEAR; - else if (tag_file_sorted == NUL) + } else if (tag_file_sorted == NUL) { state = TS_BINARY; - else if (tag_file_sorted == '1') + } else if (tag_file_sorted == '1') { state = TS_BINARY; - else if (tag_file_sorted == '2') { + } else if (tag_file_sorted == '2') { state = TS_BINARY; sortic = true; orgpat.regmatch.rm_ic = (p_ic || !noic); - } else + } else { state = TS_LINEAR; + } if (state == TS_BINARY && orgpat.regmatch.rm_ic && !sortic) { /* Binary search won't work for ignoring case, use linear @@ -1865,20 +1883,23 @@ parse_line: * there is no regexp, or the tag is too short. */ cmplen = (int)(tagp.tagname_end - tagp.tagname); - if (p_tl != 0 && cmplen > p_tl) /* adjust for 'taglength' */ + if (p_tl != 0 && cmplen > p_tl) { // adjust for 'taglength' cmplen = p_tl; - if (has_re && orgpat.headlen < cmplen) + } + if (has_re && orgpat.headlen < cmplen) { cmplen = orgpat.headlen; - else if (state == TS_LINEAR && orgpat.headlen != cmplen) + } else if (state == TS_LINEAR && orgpat.headlen != cmplen) { continue; + } if (state == TS_BINARY) { /* * Simplistic check for unsorted tags file. */ i = (int)tagp.tagname[0]; - if (sortic) + if (sortic) { i = TOUPPER_ASC(tagp.tagname[0]); + } if (i < search_info.low_char || i > search_info.high_char) { sort_error = true; } @@ -1886,21 +1907,23 @@ parse_line: /* * Compare the current tag with the searched tag. */ - if (sortic) + if (sortic) { tagcmp = tag_strnicmp(tagp.tagname, orgpat.head, - (size_t)cmplen); - else + (size_t)cmplen); + } else { tagcmp = STRNCMP(tagp.tagname, orgpat.head, cmplen); + } /* * A match with a shorter tag means to search forward. * A match with a longer tag means to search backward. */ if (tagcmp == 0) { - if (cmplen < orgpat.headlen) + if (cmplen < orgpat.headlen) { tagcmp = -1; - else if (cmplen > orgpat.headlen) + } else if (cmplen > orgpat.headlen) { tagcmp = 1; + } } if (tagcmp == 0) { @@ -1915,37 +1938,40 @@ parse_line: 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) + if (sortic) { search_info.low_char = TOUPPER_ASC(tagp.tagname[0]); - else + } else { search_info.low_char = tagp.tagname[0]; + } continue; } } if (tagcmp > 0 && search_info.curr_offset != search_info.high_offset) { search_info.high_offset = search_info.curr_offset; - if (sortic) + if (sortic) { search_info.high_char = TOUPPER_ASC(tagp.tagname[0]); - else + } else { search_info.high_char = tagp.tagname[0]; + } continue; } - /* No match yet and are at the end of the binary search. */ + // No match yet and are at the end of the binary search. break; - } else if (state == TS_SKIP_BACK) { + } else if (state == TS_SKIP_BACK) { assert(cmplen >= 0); - if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0) + if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0) { state = TS_STEP_FORWARD; - else + } else { /* Have to skip back more. Restore the curr_offset * used, otherwise we get stuck at a long line. */ search_info.curr_offset = search_info.curr_offset_used; + } continue; - } else if (state == TS_STEP_FORWARD) { + } else if (state == TS_STEP_FORWARD) { assert(cmplen >= 0); if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0) { if ((off_T)vim_ftell(fp) > search_info.match_offset) { @@ -1954,23 +1980,27 @@ parse_line: continue; // before first match } } - } else - /* skip this match if it can't match */ - assert(cmplen >= 0); - if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0) + } else { + // skip this match if it can't match + assert(cmplen >= 0); + } + if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0) { continue; + } // Can be a matching tag, isolate the file name and command. tagp.fname = tagp.tagname_end + 1; tagp.fname_end = vim_strchr(tagp.fname, TAB); tagp.command = tagp.fname_end + 1; - if (tagp.fname_end == NULL) + if (tagp.fname_end == NULL) { i = FAIL; - else + } else { i = OK; - } else + } + } else { i = parse_tag_line(lbuf, - &tagp); + &tagp); + } if (i == FAIL) { line_error = true; break; @@ -1981,20 +2011,23 @@ parse_line: * a regexp). */ cmplen = (int)(tagp.tagname_end - tagp.tagname); - if (p_tl != 0 && cmplen > p_tl) /* adjust for 'taglength' */ + if (p_tl != 0 && cmplen > p_tl) { // adjust for 'taglength' cmplen = p_tl; - /* if tag length does not match, don't try comparing */ - if (orgpat.len != cmplen) + } + // if tag length does not match, don't try comparing + if (orgpat.len != cmplen) { match = FALSE; - else { + } else { if (orgpat.regmatch.rm_ic) { assert(cmplen >= 0); match = mb_strnicmp(tagp.tagname, orgpat.pat, (size_t)cmplen) == 0; - if (match) + if (match) { match_no_ic = (STRNCMP(tagp.tagname, orgpat.pat, - cmplen) == 0); - } else + cmplen) == 0); + } + } else { match = (STRNCMP(tagp.tagname, orgpat.pat, cmplen) == 0); + } } /* @@ -2012,7 +2045,7 @@ parse_line: if (orgpat.regmatch.rm_ic) { orgpat.regmatch.rm_ic = FALSE; match_no_ic = vim_regexec(&orgpat.regmatch, tagp.tagname, - (colnr_T)0); + (colnr_T)0); orgpat.regmatch.rm_ic = TRUE; } } @@ -2025,7 +2058,7 @@ parse_line: int len = 0; if (use_cscope) { - /* Don't change the ordering, always use the same table. */ + // Don't change the ordering, always use the same table. mtt = MT_GL_OTH; } else { // Decide in which array to store this match. @@ -2035,27 +2068,31 @@ parse_line: // Decide in which of the sixteen tables to store this match. if (is_static) { - if (is_current) + if (is_current) { mtt = MT_ST_CUR; - else + } else { mtt = MT_ST_OTH; + } } else { - if (is_current) + if (is_current) { mtt = MT_GL_CUR; - else + } else { mtt = MT_GL_OTH; + } } - if (orgpat.regmatch.rm_ic && !match_no_ic) + if (orgpat.regmatch.rm_ic && !match_no_ic) { mtt += MT_IC_OFF; - if (match_re) + } + if (match_re) { mtt += MT_RE_OFF; + } } // 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 +#define ML_EXTRA 3 // Append the help-heuristic number after the tagname, for // sorting it later. The heuristic is ignored for // detecting duplicates. @@ -2074,7 +2111,7 @@ parse_line: + help_pri); *tagp.tagname_end = TAB; - } else if (name_only) { + } else if (name_only) { if (get_it_again) { char_u *temp_end = tagp.command; @@ -2148,7 +2185,7 @@ parse_line: 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; + [ga_match[mtt].ga_len++] = mfp; match_count++; } else { // duplicate tag, drop it @@ -2156,9 +2193,10 @@ parse_line: } } } - if (use_cscope && eof) + if (use_cscope && eof) { break; - } /* forever */ + } + } // forever if (line_error) { EMSG2(_("E431: Format error in tags file \"%s\""), tag_fname); @@ -2169,10 +2207,12 @@ parse_line: line_error = false; } - if (!use_cscope) + if (!use_cscope) { fclose(fp); - if (vimconv.vc_type != CONV_NONE) + } + if (vimconv.vc_type != CONV_NONE) { convert_setup(&vimconv, NULL, NULL); + } tag_file_sorted = NUL; if (sort_error) { @@ -2188,27 +2228,31 @@ parse_line: stop_searching = true; } - if (stop_searching || use_cscope) + if (stop_searching || use_cscope) { break; + } + } // end of for-each-file loop - } /* end of for-each-file loop */ - - if (!use_cscope) + if (!use_cscope) { tagname_free(&tn); + } /* stop searching when already did a linear search, or when TAG_NOIC * used, and 'ignorecase' not set or already did case-ignore search */ - if (stop_searching || linear || (!p_ic && noic) || orgpat.regmatch.rm_ic) + if (stop_searching || linear || (!p_ic && noic) || orgpat.regmatch.rm_ic) { break; - if (use_cscope) + } + if (use_cscope) { break; - orgpat.regmatch.rm_ic = TRUE; /* try another time while ignoring case */ + } + orgpat.regmatch.rm_ic = TRUE; // try another time while ignoring case } if (!stop_searching) { - if (!did_open && verbose) /* never opened any tags file */ + if (!did_open && verbose) { // never opened any tags file EMSG(_("E433: No tags file")); - retval = OK; /* It's OK even when no tag found */ + } + retval = OK; // It's OK even when no tag found } findtag_end: @@ -2220,13 +2264,15 @@ findtag_end: * Move the matches from the ga_match[] arrays into one list of * matches. When retval == FAIL, free the matches. */ - if (retval == FAIL) + if (retval == FAIL) { match_count = 0; + } - if (match_count > 0) + if (match_count > 0) { matches = xmalloc(match_count * sizeof(char_u *)); - else + } else { matches = NULL; + } match_count = 0; for (mtt = 0; mtt < MT_COUNT; mtt++) { for (i = 0; i < ga_match[mtt].ga_len; i++) { @@ -2245,7 +2291,7 @@ findtag_end: } } } - matches[match_count++] = (char_u *)mfp; + matches[match_count++] = mfp; } } @@ -2275,7 +2321,7 @@ static void found_tagfile_cb(char_u *fname, void *cookie) char_u *const tag_fname = vim_strsave(fname); #ifdef BACKSLASH_IN_FILENAME - slash_adjust(tag_fname); + slash_adjust(tag_fname); #endif simplify_filename(tag_fname); GA_APPEND(char_u *, &tag_fnames, tag_fname); @@ -2293,24 +2339,22 @@ void free_tag_stuff(void) #endif -/* - * Get the next name of a tag file from the tag file list. - * For help files, use "tags" file only. - * - * Return FAIL if no more tag file names, OK otherwise. - */ -int -get_tagfname( - tagname_T *tnp, // holds status info - int first, // TRUE when first file name is wanted - char_u *buf // pointer to buffer of MAXPATHL chars -) +/// Get the next name of a tag file from the tag file list. +/// For help files, use "tags" file only. +/// +/// @param tnp holds status info +/// @param first TRUE when first file name is wanted +/// @param buf pointer to buffer of MAXPATHL chars +/// +/// @return FAIL if no more tag file names, OK otherwise. +int get_tagfname(tagname_T *tnp, int first, char_u *buf) { - char_u *fname = NULL; - char_u *r_ptr; + char_u *fname = NULL; + char_u *r_ptr; - if (first) + if (first) { memset(tnp, 0, sizeof(tagname_T)); + } if (curbuf->b_help) { /* @@ -2328,8 +2372,9 @@ get_tagfname( if (tnp->tn_hf_idx >= tag_fnames.ga_len) { /* Not found in 'runtimepath', use 'helpfile', if it exists and * wasn't used yet, replacing "help.txt" with "tags". */ - if (tnp->tn_hf_idx > tag_fnames.ga_len || *p_hf == NUL) + if (tnp->tn_hf_idx > tag_fnames.ga_len || *p_hf == NUL) { return FAIL; + } ++tnp->tn_hf_idx; STRCPY(buf, p_hf); STRCPY(path_tail(buf), "tags"); @@ -2367,14 +2412,15 @@ get_tagfname( for (;; ) { if (tnp->tn_did_filefind_init) { fname = vim_findfile(tnp->tn_search_ctx); - if (fname != NULL) + if (fname != NULL) { break; + } tnp->tn_did_filefind_init = FALSE; } else { - char_u *filename = NULL; + char_u *filename = NULL; - /* Stop when used all parts of 'tags'. */ + // Stop when used all parts of 'tags'. if (*tnp->tn_np == NUL) { vim_findfile_cleanup(tnp->tn_search_ctx); tnp->tn_search_ctx = NULL; @@ -2395,12 +2441,13 @@ get_tagfname( *filename++ = NUL; tnp->tn_search_ctx = vim_findfile_init(buf, filename, - r_ptr, 100, - FALSE, /* don't free visited list */ - FINDFILE_FILE, /* we search for a file */ - tnp->tn_search_ctx, TRUE, curbuf->b_ffname); - if (tnp->tn_search_ctx != NULL) + r_ptr, 100, + FALSE, // don't free visited list + FINDFILE_FILE, // we search for a file + tnp->tn_search_ctx, TRUE, curbuf->b_ffname); + if (tnp->tn_search_ctx != NULL) { tnp->tn_did_filefind_init = TRUE; + } } } @@ -2420,43 +2467,44 @@ void tagname_free(tagname_T *tnp) ga_clear_strings(&tag_fnames); } -/* - * Parse one line from the tags file. Find start/end of tag name, start/end of - * file name and start of search pattern. - * - * If is_etag is TRUE, tagp->fname and tagp->fname_end are not set. - * - * Return FAIL if there is a format error in this line, OK otherwise. - */ -static int -parse_tag_line( - char_u *lbuf, // line to be parsed - tagptrs_T *tagp -) +/// Parse one line from the tags file. Find start/end of tag name, start/end of +/// file name and start of search pattern. +/// +/// If is_etag is TRUE, tagp->fname and tagp->fname_end are not set. +/// +/// @param lbuf line to be parsed +/// +/// @return FAIL if there is a format error in this line, OK otherwise. +static int parse_tag_line(char_u *lbuf, tagptrs_T *tagp) { - char_u *p; + char_u *p; - /* Isolate the tagname, from lbuf up to the first white */ + // Isolate the tagname, from lbuf up to the first white tagp->tagname = lbuf; p = vim_strchr(lbuf, TAB); - if (p == NULL) + if (p == NULL) { return FAIL; + } tagp->tagname_end = p; - /* Isolate file name, from first to second white space */ - if (*p != NUL) + // Isolate file name, from first to second white space + if (*p != NUL) { ++p; + } tagp->fname = p; p = vim_strchr(p, TAB); - if (p == NULL) + if (p == NULL) { return FAIL; + } tagp->fname_end = p; - /* find start of search command, after second white space */ - if (*p != NUL) + // find start of search command, after second white space + if (*p != NUL) { ++p; - if (*p == NUL) + } + if (*p == NUL) { return FAIL; + } tagp->command = p; return OK; @@ -2466,12 +2514,12 @@ parse_tag_line( * Check if tagname is a static tag * * Static tags produced by the older ctags program have the format: - * 'file:tag file /pattern'. + * 'file:tag file /pattern'. * This is only recognized when both occurrence of 'file' are the same, to * avoid recognizing "string::string" or ":exit". * * Static tags produced by the new ctags program have the format: - * 'tag file /pattern/;"<Tab>file:' " + * 'tag file /pattern/;"<Tab>file:' " * * Return TRUE if it is a static tag and adjust *tagname to the real tag. * Return FALSE if it is not a static tag. @@ -2484,8 +2532,9 @@ static bool test_for_static(tagptrs_T *tagp) p = tagp->command; while ((p = vim_strchr(p, '\t')) != NULL) { ++p; - if (STRNCMP(p, "file:", 5) == 0) + if (STRNCMP(p, "file:", 5) == 0) { return TRUE; + } } return FALSE; @@ -2501,32 +2550,29 @@ static size_t matching_line_len(const char_u *const lbuf) return (p - lbuf) + STRLEN(p); } -/* - * Parse a line from a matching tag. Does not change the line itself. - * - * The line that we get looks like this: - * 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> - * - * Return OK or FAIL. - */ -static int -parse_match( - char_u *lbuf, // input: matching line - tagptrs_T *tagp // output: pointers into the line -) +/// Parse a line from a matching tag. Does not change the line itself. +/// +/// The line that we get looks like this: +/// 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> +/// +/// @param lbuf input: matching line +/// @param tagp output: pointers into the line +/// +/// @return OK or FAIL. +static int parse_match(char_u *lbuf, tagptrs_T *tagp) { int retval; - char_u *p; - char_u *pc, *pt; + char_u *p; + char_u *pc, *pt; tagp->tag_fname = lbuf + 1; lbuf += STRLEN(tagp->tag_fname) + 2; - /* Find search pattern and the file name for non-etags. */ + // Find search pattern and the file name for non-etags. retval = parse_tag_line(lbuf, - tagp); + tagp); tagp->tagkind = NULL; tagp->user_data = NULL; @@ -2534,7 +2580,7 @@ parse_match( tagp->command_end = NULL; if (retval == OK) { - /* Try to find a kind field: "kind:<kind>" or just "<kind>"*/ + // Try to find a kind field: "kind:<kind>" or just "<kind>" p = tagp->command; if (find_extra(&p) == OK) { tagp->command_end = p; @@ -2562,8 +2608,9 @@ parse_match( if (pc == NULL || (pt != NULL && pc > pt)) { tagp->tagkind = p; } - if (pt == NULL) + if (pt == NULL) { break; + } p = pt; MB_PTR_ADV(p); } @@ -2602,32 +2649,30 @@ static char_u *tag_full_fname(tagptrs_T *tagp) return fullname; } -/* - * Jump to a tag that has been found in one of the tag files - * - * returns OK for success, NOTAGFILE when file not found, FAIL otherwise. - */ -static int jumpto_tag( - const char_u *lbuf_arg, // line from the tags file for this tag - int forceit, // :ta with ! - int keep_help // keep help flag (FALSE for cscope) -) +/// Jump to a tag that has been found in one of the tag files +/// +/// @param lbuf_arg line from the tags file for this tag +/// @param forceit :ta with ! +/// @param keep_help keep help flag (FALSE for cscope) +/// +/// @return OK for success, NOTAGFILE when file not found, FAIL otherwise. +static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help) { int save_magic; bool save_p_ws; int save_p_scs, save_p_ic; linenr_T save_lnum; - char_u *str; - char_u *pbuf; /* search pattern buffer */ - char_u *pbuf_end; - char_u *tofree_fname = NULL; - char_u *fname; + char_u *str; + char_u *pbuf; // search pattern buffer + char_u *pbuf_end; + char_u *tofree_fname = NULL; + char_u *fname; tagptrs_T tagp; int retval = FAIL; int getfile_result = GETFILE_UNUSED; int search_options; - win_T *curwin_save = NULL; - char_u *full_fname = NULL; + win_T *curwin_save = NULL; + char_u *full_fname = NULL; const bool old_KeyTyped = KeyTyped; // getting the file may reset it const int l_g_do_tagpreview = g_do_tagpreview; const size_t len = matching_line_len(lbuf_arg) + 1; @@ -2636,7 +2681,7 @@ static int jumpto_tag( pbuf = xmalloc(LSIZE); - /* parse the match line into the tagp structure */ + // parse the match line into the tagp structure if (parse_match(lbuf, &tagp) == FAIL) { tagp.fname_end = NULL; goto erret; @@ -2646,7 +2691,7 @@ static int jumpto_tag( *tagp.fname_end = NUL; fname = tagp.fname; - /* copy the command to pbuf[], remove trailing CR/NL */ + // copy the command to pbuf[], remove trailing CR/NL str = tagp.command; for (pbuf_end = pbuf; *str && *str != '\n' && *str != '\r'; ) { *pbuf_end++ = *str++; @@ -2680,8 +2725,8 @@ static int jumpto_tag( * autocommand event (e.g., http://sys/file). */ if (!os_path_exists(fname) - && !has_autocmd(EVENT_BUFREADCMD, fname, NULL) - ) { + && !has_autocmd(EVENT_BUFREADCMD, fname, + NULL)) { retval = NOTAGFILE; xfree(nofile_fname); nofile_fname = vim_strsave(fname); @@ -2692,8 +2737,8 @@ static int jumpto_tag( if (l_g_do_tagpreview != 0) { - postponed_split = 0; /* don't split again below */ - curwin_save = curwin; /* Save current window */ + postponed_split = 0; // don't split again below + curwin_save = curwin; // Save current window /* * If we are reusing a window, we may change dir when @@ -2750,10 +2795,11 @@ static int jumpto_tag( if (keep_help) { /* A :ta from a help file will keep the b_help flag set. For ":ptag" * we need to use the flag from the window where we came from. */ - if (l_g_do_tagpreview != 0) + if (l_g_do_tagpreview != 0) { keep_help_flag = curwin_save->w_buffer->b_help; - else + } else { keep_help_flag = curbuf->b_help; + } } if (getfile_result == GETFILE_UNUSED) { @@ -2777,10 +2823,11 @@ static int jumpto_tag( * command. If 'cpoptions' does not contain 't', the search pattern * is not stored. */ - if (vim_strchr(p_cpo, CPO_TAGPAT) != NULL) + if (vim_strchr(p_cpo, CPO_TAGPAT) != NULL) { search_options = 0; - else + } else { search_options = SEARCH_KEEP; + } /* * If the command is a search, try here. @@ -2791,14 +2838,15 @@ static int jumpto_tag( * anything following. */ str = pbuf; - if (pbuf[0] == '/' || pbuf[0] == '?') + if (pbuf[0] == '/' || pbuf[0] == '?') { str = skip_regexp(pbuf + 1, pbuf[0], FALSE, NULL) + 1; - if (str > pbuf_end - 1) { /* search command with nothing following */ + } + if (str > pbuf_end - 1) { // search command with nothing following save_p_ws = p_ws; save_p_ic = p_ic; save_p_scs = p_scs; - p_ws = true; /* need 'wrapscan' for backward searches */ - p_ic = FALSE; /* don't ignore case now */ + p_ws = true; // need 'wrapscan' for backward searches + p_ic = FALSE; // don't ignore case now p_scs = FALSE; save_lnum = curwin->w_cursor.lnum; if (tagp.tagline > 0) { @@ -2898,15 +2946,17 @@ static int jumpto_tag( * For a help buffer: Put the cursor line at the top of the window, * the help subject will be below it. */ - if (curbuf->b_help) + if (curbuf->b_help) { set_topline(curwin, curwin->w_cursor.lnum); - if ((fdo_flags & FDO_TAG) && old_KeyTyped) + } + if ((fdo_flags & FDO_TAG) && old_KeyTyped) { foldOpenCursor(); + } } if (l_g_do_tagpreview != 0 && curwin != curwin_save && win_valid(curwin_save)) { - /* Return cursor to where we were */ + // Return cursor to where we were validate_cursor(); redraw_later(curwin, VALID); win_enter(curwin_save, true); @@ -2935,11 +2985,10 @@ erret: // If 'tagrelative' option set, change fname (name of file containing tag) // according to tag_fname (name of tag file containing fname). // Returns a pointer to allocated memory. -static char_u *expand_tag_fname(char_u *fname, char_u *const tag_fname, - const bool expand) +static char_u *expand_tag_fname(char_u *fname, char_u *const tag_fname, const bool expand) { - char_u *p; - char_u *expanded_fname = NULL; + char_u *p; + char_u *expanded_fname = NULL; expand_T xpc; /* @@ -2949,9 +2998,10 @@ static char_u *expand_tag_fname(char_u *fname, char_u *const tag_fname, ExpandInit(&xpc); xpc.xp_context = EXPAND_FILES; expanded_fname = ExpandOne(&xpc, fname, NULL, - WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE); - if (expanded_fname != NULL) + WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE); + if (expanded_fname != NULL) { fname = expanded_fname; + } } char_u *retval; @@ -2961,13 +3011,14 @@ static char_u *expand_tag_fname(char_u *fname, char_u *const tag_fname, retval = xmalloc(MAXPATHL); STRCPY(retval, tag_fname); STRLCPY(retval + (p - tag_fname), fname, - MAXPATHL - (p - tag_fname)); + MAXPATHL - (p - tag_fname)); /* * Translate names like "src/a/../b/file.c" into "src/b/file.c". */ simplify_filename(retval); - } else + } else { retval = vim_strsave(fname); + } xfree(expanded_fname); @@ -2984,9 +3035,9 @@ static int test_for_current(char_u *fname, char_u *fname_end, char_u *tag_fname, { int c; int retval = FALSE; - char_u *fullname; + char_u *fullname; - if (buf_ffname != NULL) { /* if the buffer has a name */ + if (buf_ffname != NULL) { // if the buffer has a name { c = *fname_end; *fname_end = NUL; @@ -3053,13 +3104,8 @@ static void tagstack_clear_entry(taggy_T *item) XFREE_CLEAR(item->user_data); } -int -expand_tags ( - int tagnames, /* expand tag names */ - char_u *pat, - int *num_file, - char_u ***file -) +/// @param tagnames expand tag names +int expand_tags(int tagnames, char_u *pat, int *num_file, char_u ***file) { int i; int extra_flag; @@ -3116,17 +3162,13 @@ expand_tags ( } -/* - * Add a tag field to the dictionary "dict". - * Return OK or FAIL. - */ -static int -add_tag_field( - dict_T *dict, - const char *field_name, - const char_u *start, // start of the value - const char_u *end // after the value; can be NULL -) +/// Add a tag field to the dictionary "dict". +/// Return OK or FAIL. +/// +/// @param start start of the value +/// @param end after the value; can be NULL +static int add_tag_field(dict_T *dict, const char *field_name, const char_u *start, + const char_u *end) FUNC_ATTR_NONNULL_ARG(1, 2) { int len = 0; @@ -3145,12 +3187,14 @@ add_tag_field( if (start != NULL) { if (end == NULL) { end = start + STRLEN(start); - while (end > start && (end[-1] == '\r' || end[-1] == '\n')) + while (end > start && (end[-1] == '\r' || end[-1] == '\n')) { --end; + } } len = (int)(end - start); - if (len > MAXPATHL - 1) + if (len > MAXPATHL - 1) { len = MAXPATHL - 1; + } STRLCPY(buf, start, len + 1); } buf[len] = NUL; @@ -3165,9 +3209,9 @@ add_tag_field( int get_tags(list_T *list, char_u *pat, char_u *buf_fname) { int num_matches, i, ret; - char_u **matches; - char_u *full_fname; - dict_T *dict; + char_u **matches; + char_u *full_fname; + dict_T *dict; tagptrs_T tp; bool is_static; @@ -3178,7 +3222,7 @@ int get_tags(list_T *list, char_u *pat, char_u *buf_fname) int parse_result = parse_match(matches[i], &tp); // Avoid an unused variable warning in release builds. - (void) parse_result; + (void)parse_result; assert(parse_result == OK); is_static = test_for_static(&tp); @@ -3216,29 +3260,35 @@ int get_tags(list_T *list, char_u *pat, char_u *buf_fname) // skip "file:" (static tag) p += 4; } else if (!ascii_iswhite(*p)) { - char_u *s, *n; + char_u *s, *n; int len; /* Add extra field as a dict entry. Fields are * separated by Tabs. */ n = p; - while (*p != NUL && *p >= ' ' && *p < 127 && *p != ':') + while (*p != NUL && *p >= ' ' && *p < 127 && *p != ':') { ++p; + } len = (int)(p - n); if (*p == ':' && len > 0) { s = ++p; - while (*p != NUL && *p >= ' ') + while (*p != NUL && *p >= ' ') { ++p; + } n[len] = NUL; - if (add_tag_field(dict, (char *)n, s, p) == FAIL) + if (add_tag_field(dict, (char *)n, s, p) == FAIL) { ret = FAIL; + } n[len] = ':'; - } else - /* Skip field without colon. */ - while (*p != NUL && *p >= ' ') + } else { + // Skip field without colon. + while (*p != NUL && *p >= ' ') { ++p; - if (*p == NUL) + } + } + if (*p == NUL) { break; + } } } } @@ -3319,14 +3369,8 @@ static void tagstack_shift(win_T *wp) } // Push a new item to the tag stack -static void tagstack_push_item( - win_T *wp, - char_u *tagname, - int cur_fnum, - int cur_match, - pos_T mark, - int fnum, - char_u *user_data) +static void tagstack_push_item(win_T *wp, char_u *tagname, int cur_fnum, int cur_match, pos_T mark, + int fnum, char_u *user_data) { taggy_T *tagstack = wp->w_tagstack; int idx = wp->w_tagstacklen; // top of the stack @@ -3382,13 +3426,12 @@ static void tagstack_push_items(win_T *wp, list_T *l) if (mark.col > 0) { mark.col--; } - tagstack_push_item( - wp, - tagname, - (int)tv_dict_get_number(itemdict, "bufnr"), - (int)tv_dict_get_number(itemdict, "matchnr") - 1, - mark, fnum, - (char_u *)tv_dict_get_string(itemdict, "user_data", true)); + tagstack_push_item(wp, + tagname, + (int)tv_dict_get_number(itemdict, "bufnr"), + (int)tv_dict_get_number(itemdict, "matchnr") - 1, + mark, fnum, + (char_u *)tv_dict_get_string(itemdict, "user_data", true)); } } diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 3335fa500a..6f19a9209e 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -37,45 +37,44 @@ // Some code from pangoterm http://www.leonerd.org.uk/code/pangoterm #include <assert.h> -#include <stdio.h> -#include <stdint.h> #include <stdbool.h> - +#include <stdint.h> +#include <stdio.h> #include <vterm.h> -#include "nvim/log.h" -#include "nvim/vim.h" -#include "nvim/terminal.h" -#include "nvim/message.h" -#include "nvim/memory.h" -#include "nvim/option.h" -#include "nvim/highlight.h" -#include "nvim/macros.h" -#include "nvim/mbyte.h" +#include "nvim/api/private/helpers.h" +#include "nvim/ascii.h" #include "nvim/buffer.h" #include "nvim/change.h" -#include "nvim/ascii.h" +#include "nvim/edit.h" +#include "nvim/event/loop.h" +#include "nvim/event/time.h" +#include "nvim/ex_cmds.h" +#include "nvim/ex_docmd.h" +#include "nvim/fileio.h" #include "nvim/getchar.h" -#include "nvim/ui.h" -#include "nvim/syntax.h" -#include "nvim/screen.h" +#include "nvim/highlight.h" #include "nvim/keymap.h" -#include "nvim/edit.h" -#include "nvim/mouse.h" -#include "nvim/memline.h" +#include "nvim/log.h" +#include "nvim/macros.h" +#include "nvim/main.h" #include "nvim/map.h" +#include "nvim/mbyte.h" +#include "nvim/memline.h" +#include "nvim/memory.h" +#include "nvim/message.h" #include "nvim/misc1.h" +#include "nvim/mouse.h" #include "nvim/move.h" -#include "nvim/main.h" +#include "nvim/option.h" +#include "nvim/os/input.h" +#include "nvim/screen.h" #include "nvim/state.h" -#include "nvim/ex_docmd.h" -#include "nvim/ex_cmds.h" +#include "nvim/syntax.h" +#include "nvim/terminal.h" +#include "nvim/ui.h" +#include "nvim/vim.h" #include "nvim/window.h" -#include "nvim/fileio.h" -#include "nvim/event/loop.h" -#include "nvim/event/time.h" -#include "nvim/os/input.h" -#include "nvim/api/private/helpers.h" typedef struct terminal_state { VimState state; @@ -210,7 +209,7 @@ Terminal *terminal_open(buf_T *buf, TerminalOptions opts) buf->b_p_ma = false; // 'nomodifiable' buf->b_p_ul = -1; // 'undolevels' buf->b_p_scbk = // 'scrollback' (initialize local from global) - (p_scbk < 0) ? 10000 : MAX(1, p_scbk); + (p_scbk < 0) ? 10000 : MAX(1, p_scbk); buf->b_p_tw = 0; // 'textwidth' set_option_value("wrap", false, NULL, OPT_LOCAL); set_option_value("list", false, NULL, OPT_LOCAL); @@ -452,56 +451,56 @@ static int terminal_execute(VimState *state, int key) TerminalState *s = (TerminalState *)state; switch (key) { - case K_LEFTMOUSE: - case K_LEFTDRAG: - case K_LEFTRELEASE: - case K_MOUSEMOVE: - case K_MIDDLEMOUSE: - case K_MIDDLEDRAG: - case K_MIDDLERELEASE: - case K_RIGHTMOUSE: - case K_RIGHTDRAG: - case K_RIGHTRELEASE: - case K_MOUSEDOWN: - case K_MOUSEUP: - if (send_mouse_event(s->term, key)) { - return 0; - } - break; - - case K_EVENT: - // We cannot let an event free the terminal yet. It is still needed. - s->term->refcount++; - state_handle_k_event(); - s->term->refcount--; - if (s->term->buf_handle == 0) { - s->close = true; - return 0; - } - break; + case K_LEFTMOUSE: + case K_LEFTDRAG: + case K_LEFTRELEASE: + case K_MOUSEMOVE: + case K_MIDDLEMOUSE: + case K_MIDDLEDRAG: + case K_MIDDLERELEASE: + case K_RIGHTMOUSE: + case K_RIGHTDRAG: + case K_RIGHTRELEASE: + case K_MOUSEDOWN: + case K_MOUSEUP: + if (send_mouse_event(s->term, key)) { + return 0; + } + break; + + case K_EVENT: + // We cannot let an event free the terminal yet. It is still needed. + s->term->refcount++; + state_handle_k_event(); + s->term->refcount--; + if (s->term->buf_handle == 0) { + s->close = true; + return 0; + } + break; - case K_COMMAND: - do_cmdline(NULL, getcmdkeycmd, NULL, 0); - break; + case K_COMMAND: + do_cmdline(NULL, getcmdkeycmd, NULL, 0); + break; - case Ctrl_N: - if (s->got_bsl) { - return 0; - } - FALLTHROUGH; + case Ctrl_N: + if (s->got_bsl) { + return 0; + } + FALLTHROUGH; - default: - if (key == Ctrl_BSL && !s->got_bsl) { - s->got_bsl = true; - break; - } - if (s->term->closed) { - s->close = true; - return 0; - } + default: + if (key == Ctrl_BSL && !s->got_bsl) { + s->got_bsl = true; + break; + } + if (s->term->closed) { + s->close = true; + return 0; + } - s->got_bsl = false; - terminal_send_key(s->term, key); + s->got_bsl = false; + terminal_send_key(s->term, key); } if (curbuf->terminal == NULL) { @@ -554,30 +553,30 @@ static bool is_filter_char(int c) { unsigned int flag = 0; switch (c) { - case 0x08: - flag = TPF_BS; - break; - case 0x09: - flag = TPF_HT; - break; - case 0x0A: - case 0x0D: - break; - case 0x0C: - flag = TPF_FF; - break; - case 0x1b: - flag = TPF_ESC; - break; - case 0x7F: - flag = TPF_DEL; - break; - default: - if (c < ' ') { - flag = TPF_C0; - } else if (c >= 0x80 && c <= 0x9F) { - flag = TPF_C1; - } + case 0x08: + flag = TPF_BS; + break; + case 0x09: + flag = TPF_HT; + break; + case 0x0A: + case 0x0D: + break; + case 0x0C: + flag = TPF_FF; + break; + case 0x1b: + flag = TPF_ESC; + break; + case 0x7F: + flag = TPF_DEL; + break; + default: + if (c < ' ') { + flag = TPF_C0; + } else if (c >= 0x80 && c <= 0x9F) { + flag = TPF_C1; + } } return !!(tpf_flags & flag); } @@ -666,8 +665,7 @@ static int get_rgb(VTermState *state, VTermColor color) } -void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, - int *term_attrs) +void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, int *term_attrs) { int height, width; vterm_get_size(term->vt, &height, &width); @@ -701,12 +699,12 @@ void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, bool bg_set = vt_bg_idx && vt_bg_idx <= 16 && term->color_set[vt_bg_idx-1]; int hl_attrs = (cell.attrs.bold ? HL_BOLD : 0) - | (cell.attrs.italic ? HL_ITALIC : 0) - | (cell.attrs.reverse ? HL_INVERSE : 0) - | (cell.attrs.underline ? HL_UNDERLINE : 0) - | (cell.attrs.strike ? HL_STRIKETHROUGH: 0) - | ((fg_indexed && !fg_set) ? HL_FG_INDEXED : 0) - | ((bg_indexed && !bg_set) ? HL_BG_INDEXED : 0); + | (cell.attrs.italic ? HL_ITALIC : 0) + | (cell.attrs.reverse ? HL_INVERSE : 0) + | (cell.attrs.underline ? HL_UNDERLINE : 0) + | (cell.attrs.strike ? HL_STRIKETHROUGH: 0) + | ((fg_indexed && !fg_set) ? HL_FG_INDEXED : 0) + | ((bg_indexed && !bg_set) ? HL_BG_INDEXED : 0); int attr_id = 0; @@ -757,12 +755,11 @@ static int term_damage(VTermRect rect, void *data) static int term_moverect(VTermRect dest, VTermRect src, void *data) { invalidate_terminal(data, MIN(dest.start_row, src.start_row), - MAX(dest.end_row, src.end_row)); + MAX(dest.end_row, src.end_row)); return 1; } -static int term_movecursor(VTermPos new, VTermPos old, int visible, - void *data) +static int term_movecursor(VTermPos new, VTermPos old, int visible, void *data) { Terminal *term = data; term->cursor.row = new.row; @@ -791,26 +788,26 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *data) Terminal *term = data; switch (prop) { - case VTERM_PROP_ALTSCREEN: - break; - - case VTERM_PROP_CURSORVISIBLE: - term->cursor.visible = val->boolean; - invalidate_terminal(term, term->cursor.row, term->cursor.row + 1); - break; + case VTERM_PROP_ALTSCREEN: + break; + + case VTERM_PROP_CURSORVISIBLE: + term->cursor.visible = val->boolean; + invalidate_terminal(term, term->cursor.row, term->cursor.row + 1); + break; + + case VTERM_PROP_TITLE: { + buf_T *buf = handle_get_buffer(term->buf_handle); + buf_set_term_title(buf, val->string); + break; + } - case VTERM_PROP_TITLE: { - buf_T *buf = handle_get_buffer(term->buf_handle); - buf_set_term_title(buf, val->string); - break; - } + case VTERM_PROP_MOUSE: + term->forward_mouse = (bool)val->number; + break; - case VTERM_PROP_MOUSE: - term->forward_mouse = (bool)val->number; - break; - - default: - return 0; + default: + return 0; } return 1; @@ -844,12 +841,11 @@ static int term_sb_push(int cols, const VTermScreenCell *cells, void *data) // 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)); - + 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); + sizeof(term->sb_buffer[0]) * term->sb_current); } if (!sbrow) { @@ -894,7 +890,7 @@ static int term_sb_pop(int cols, VTermScreenCell *cells, void *data) 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)); + sizeof(term->sb_buffer[0]) * (term->sb_current)); size_t cols_to_copy = (size_t)cols; if (cols_to_copy > sbrow->cols) { @@ -919,35 +915,41 @@ static int term_sb_pop(int cols, VTermScreenCell *cells, void *data) static void convert_modifiers(int key, VTermModifier *statep) { - if (mod_mask & MOD_MASK_SHIFT) { *statep |= VTERM_MOD_SHIFT; } - if (mod_mask & MOD_MASK_CTRL) { *statep |= VTERM_MOD_CTRL; } - if (mod_mask & MOD_MASK_ALT) { *statep |= VTERM_MOD_ALT; } + if (mod_mask & MOD_MASK_SHIFT) { + *statep |= VTERM_MOD_SHIFT; + } + if (mod_mask & MOD_MASK_CTRL) { + *statep |= VTERM_MOD_CTRL; + } + if (mod_mask & MOD_MASK_ALT) { + *statep |= VTERM_MOD_ALT; + } switch (key) { - case K_S_TAB: - case K_S_UP: - case K_S_DOWN: - case K_S_LEFT: - case K_S_RIGHT: - case K_S_F1: - case K_S_F2: - case K_S_F3: - case K_S_F4: - case K_S_F5: - case K_S_F6: - case K_S_F7: - case K_S_F8: - case K_S_F9: - case K_S_F10: - case K_S_F11: - case K_S_F12: - *statep |= VTERM_MOD_SHIFT; - break; - - case K_C_LEFT: - case K_C_RIGHT: - *statep |= VTERM_MOD_CTRL; - break; + case K_S_TAB: + case K_S_UP: + case K_S_DOWN: + case K_S_LEFT: + case K_S_RIGHT: + case K_S_F1: + case K_S_F2: + case K_S_F3: + case K_S_F4: + case K_S_F5: + case K_S_F6: + case K_S_F7: + case K_S_F8: + case K_S_F9: + case K_S_F10: + case K_S_F11: + case K_S_F12: + *statep |= VTERM_MOD_SHIFT; + break; + + case K_C_LEFT: + case K_C_RIGHT: + *statep |= VTERM_MOD_CTRL; + break; } } @@ -956,115 +958,212 @@ static VTermKey convert_key(int key, VTermModifier *statep) convert_modifiers(key, statep); switch (key) { - case K_BS: return VTERM_KEY_BACKSPACE; - case K_S_TAB: FALLTHROUGH; - case TAB: return VTERM_KEY_TAB; - case Ctrl_M: return VTERM_KEY_ENTER; - case ESC: return VTERM_KEY_ESCAPE; - - case K_S_UP: FALLTHROUGH; - case K_UP: return VTERM_KEY_UP; - case K_S_DOWN: FALLTHROUGH; - case K_DOWN: return VTERM_KEY_DOWN; - case K_S_LEFT: FALLTHROUGH; - case K_C_LEFT: FALLTHROUGH; - case K_LEFT: return VTERM_KEY_LEFT; - case K_S_RIGHT: FALLTHROUGH; - case K_C_RIGHT: FALLTHROUGH; - case K_RIGHT: return VTERM_KEY_RIGHT; - - case K_INS: return VTERM_KEY_INS; - case K_DEL: return VTERM_KEY_DEL; - case K_HOME: return VTERM_KEY_HOME; - case K_END: return VTERM_KEY_END; - case K_PAGEUP: return VTERM_KEY_PAGEUP; - case K_PAGEDOWN: return VTERM_KEY_PAGEDOWN; - - case K_K0: FALLTHROUGH; - case K_KINS: return VTERM_KEY_KP_0; - case K_K1: FALLTHROUGH; - case K_KEND: return VTERM_KEY_KP_1; - case K_K2: FALLTHROUGH; - case K_KDOWN: return VTERM_KEY_KP_2; - case K_K3: FALLTHROUGH; - case K_KPAGEDOWN: return VTERM_KEY_KP_3; - case K_K4: FALLTHROUGH; - case K_KLEFT: return VTERM_KEY_KP_4; - case K_K5: FALLTHROUGH; - case K_KORIGIN: return VTERM_KEY_KP_5; - case K_K6: FALLTHROUGH; - case K_KRIGHT: return VTERM_KEY_KP_6; - case K_K7: FALLTHROUGH; - case K_KHOME: return VTERM_KEY_KP_7; - case K_K8: FALLTHROUGH; - case K_KUP: return VTERM_KEY_KP_8; - case K_K9: FALLTHROUGH; - case K_KPAGEUP: return VTERM_KEY_KP_9; - case K_KDEL: FALLTHROUGH; - case K_KPOINT: return VTERM_KEY_KP_PERIOD; - case K_KENTER: return VTERM_KEY_KP_ENTER; - case K_KPLUS: return VTERM_KEY_KP_PLUS; - case K_KMINUS: return VTERM_KEY_KP_MINUS; - case K_KMULTIPLY: return VTERM_KEY_KP_MULT; - case K_KDIVIDE: return VTERM_KEY_KP_DIVIDE; - - case K_S_F1: FALLTHROUGH; - case K_F1: return VTERM_KEY_FUNCTION(1); - case K_S_F2: FALLTHROUGH; - case K_F2: return VTERM_KEY_FUNCTION(2); - case K_S_F3: FALLTHROUGH; - case K_F3: return VTERM_KEY_FUNCTION(3); - case K_S_F4: FALLTHROUGH; - case K_F4: return VTERM_KEY_FUNCTION(4); - case K_S_F5: FALLTHROUGH; - case K_F5: return VTERM_KEY_FUNCTION(5); - case K_S_F6: FALLTHROUGH; - case K_F6: return VTERM_KEY_FUNCTION(6); - case K_S_F7: FALLTHROUGH; - case K_F7: return VTERM_KEY_FUNCTION(7); - case K_S_F8: FALLTHROUGH; - case K_F8: return VTERM_KEY_FUNCTION(8); - case K_S_F9: FALLTHROUGH; - case K_F9: return VTERM_KEY_FUNCTION(9); - case K_S_F10: FALLTHROUGH; - case K_F10: return VTERM_KEY_FUNCTION(10); - case K_S_F11: FALLTHROUGH; - case K_F11: return VTERM_KEY_FUNCTION(11); - case K_S_F12: FALLTHROUGH; - case K_F12: return VTERM_KEY_FUNCTION(12); - - case K_F13: return VTERM_KEY_FUNCTION(13); - case K_F14: return VTERM_KEY_FUNCTION(14); - case K_F15: return VTERM_KEY_FUNCTION(15); - case K_F16: return VTERM_KEY_FUNCTION(16); - case K_F17: return VTERM_KEY_FUNCTION(17); - case K_F18: return VTERM_KEY_FUNCTION(18); - case K_F19: return VTERM_KEY_FUNCTION(19); - case K_F20: return VTERM_KEY_FUNCTION(20); - case K_F21: return VTERM_KEY_FUNCTION(21); - case K_F22: return VTERM_KEY_FUNCTION(22); - case K_F23: return VTERM_KEY_FUNCTION(23); - case K_F24: return VTERM_KEY_FUNCTION(24); - case K_F25: return VTERM_KEY_FUNCTION(25); - case K_F26: return VTERM_KEY_FUNCTION(26); - case K_F27: return VTERM_KEY_FUNCTION(27); - case K_F28: return VTERM_KEY_FUNCTION(28); - case K_F29: return VTERM_KEY_FUNCTION(29); - case K_F30: return VTERM_KEY_FUNCTION(30); - case K_F31: return VTERM_KEY_FUNCTION(31); - case K_F32: return VTERM_KEY_FUNCTION(32); - case K_F33: return VTERM_KEY_FUNCTION(33); - case K_F34: return VTERM_KEY_FUNCTION(34); - case K_F35: return VTERM_KEY_FUNCTION(35); - case K_F36: return VTERM_KEY_FUNCTION(36); - case K_F37: return VTERM_KEY_FUNCTION(37); - - default: return VTERM_KEY_NONE; + case K_BS: + return VTERM_KEY_BACKSPACE; + case K_S_TAB: + FALLTHROUGH; + case TAB: + return VTERM_KEY_TAB; + case Ctrl_M: + return VTERM_KEY_ENTER; + case ESC: + return VTERM_KEY_ESCAPE; + + case K_S_UP: + FALLTHROUGH; + case K_UP: + return VTERM_KEY_UP; + case K_S_DOWN: + FALLTHROUGH; + case K_DOWN: + return VTERM_KEY_DOWN; + case K_S_LEFT: + FALLTHROUGH; + case K_C_LEFT: + FALLTHROUGH; + case K_LEFT: + return VTERM_KEY_LEFT; + case K_S_RIGHT: + FALLTHROUGH; + case K_C_RIGHT: + FALLTHROUGH; + case K_RIGHT: + return VTERM_KEY_RIGHT; + + case K_INS: + return VTERM_KEY_INS; + case K_DEL: + return VTERM_KEY_DEL; + case K_HOME: + return VTERM_KEY_HOME; + case K_END: + return VTERM_KEY_END; + case K_PAGEUP: + return VTERM_KEY_PAGEUP; + case K_PAGEDOWN: + return VTERM_KEY_PAGEDOWN; + + case K_K0: + FALLTHROUGH; + case K_KINS: + return VTERM_KEY_KP_0; + case K_K1: + FALLTHROUGH; + case K_KEND: + return VTERM_KEY_KP_1; + case K_K2: + FALLTHROUGH; + case K_KDOWN: + return VTERM_KEY_KP_2; + case K_K3: + FALLTHROUGH; + case K_KPAGEDOWN: + return VTERM_KEY_KP_3; + case K_K4: + FALLTHROUGH; + case K_KLEFT: + return VTERM_KEY_KP_4; + case K_K5: + FALLTHROUGH; + case K_KORIGIN: + return VTERM_KEY_KP_5; + case K_K6: + FALLTHROUGH; + case K_KRIGHT: + return VTERM_KEY_KP_6; + case K_K7: + FALLTHROUGH; + case K_KHOME: + return VTERM_KEY_KP_7; + case K_K8: + FALLTHROUGH; + case K_KUP: + return VTERM_KEY_KP_8; + case K_K9: + FALLTHROUGH; + case K_KPAGEUP: + return VTERM_KEY_KP_9; + case K_KDEL: + FALLTHROUGH; + case K_KPOINT: + return VTERM_KEY_KP_PERIOD; + case K_KENTER: + return VTERM_KEY_KP_ENTER; + case K_KPLUS: + return VTERM_KEY_KP_PLUS; + case K_KMINUS: + return VTERM_KEY_KP_MINUS; + case K_KMULTIPLY: + return VTERM_KEY_KP_MULT; + case K_KDIVIDE: + return VTERM_KEY_KP_DIVIDE; + + case K_S_F1: + FALLTHROUGH; + case K_F1: + return VTERM_KEY_FUNCTION(1); + case K_S_F2: + FALLTHROUGH; + case K_F2: + return VTERM_KEY_FUNCTION(2); + case K_S_F3: + FALLTHROUGH; + case K_F3: + return VTERM_KEY_FUNCTION(3); + case K_S_F4: + FALLTHROUGH; + case K_F4: + return VTERM_KEY_FUNCTION(4); + case K_S_F5: + FALLTHROUGH; + case K_F5: + return VTERM_KEY_FUNCTION(5); + case K_S_F6: + FALLTHROUGH; + case K_F6: + return VTERM_KEY_FUNCTION(6); + case K_S_F7: + FALLTHROUGH; + case K_F7: + return VTERM_KEY_FUNCTION(7); + case K_S_F8: + FALLTHROUGH; + case K_F8: + return VTERM_KEY_FUNCTION(8); + case K_S_F9: + FALLTHROUGH; + case K_F9: + return VTERM_KEY_FUNCTION(9); + case K_S_F10: + FALLTHROUGH; + case K_F10: + return VTERM_KEY_FUNCTION(10); + case K_S_F11: + FALLTHROUGH; + case K_F11: + return VTERM_KEY_FUNCTION(11); + case K_S_F12: + FALLTHROUGH; + case K_F12: + return VTERM_KEY_FUNCTION(12); + + case K_F13: + return VTERM_KEY_FUNCTION(13); + case K_F14: + return VTERM_KEY_FUNCTION(14); + case K_F15: + return VTERM_KEY_FUNCTION(15); + case K_F16: + return VTERM_KEY_FUNCTION(16); + case K_F17: + return VTERM_KEY_FUNCTION(17); + case K_F18: + return VTERM_KEY_FUNCTION(18); + case K_F19: + return VTERM_KEY_FUNCTION(19); + case K_F20: + return VTERM_KEY_FUNCTION(20); + case K_F21: + return VTERM_KEY_FUNCTION(21); + case K_F22: + return VTERM_KEY_FUNCTION(22); + case K_F23: + return VTERM_KEY_FUNCTION(23); + case K_F24: + return VTERM_KEY_FUNCTION(24); + case K_F25: + return VTERM_KEY_FUNCTION(25); + case K_F26: + return VTERM_KEY_FUNCTION(26); + case K_F27: + return VTERM_KEY_FUNCTION(27); + case K_F28: + return VTERM_KEY_FUNCTION(28); + case K_F29: + return VTERM_KEY_FUNCTION(29); + case K_F30: + return VTERM_KEY_FUNCTION(30); + case K_F31: + return VTERM_KEY_FUNCTION(31); + case K_F32: + return VTERM_KEY_FUNCTION(32); + case K_F33: + return VTERM_KEY_FUNCTION(33); + case K_F34: + return VTERM_KEY_FUNCTION(34); + case K_F35: + return VTERM_KEY_FUNCTION(35); + case K_F36: + return VTERM_KEY_FUNCTION(36); + case K_F37: + return VTERM_KEY_FUNCTION(37); + + default: + return VTERM_KEY_NONE; } } -static void mouse_action(Terminal *term, int button, int row, int col, - bool drag, VTermModifier mod) +static void mouse_action(Terminal *term, int button, int row, int col, bool drag, VTermModifier mod) { if (term->pressed_button && (term->pressed_button != button || !drag)) { // release the previous button @@ -1100,16 +1199,26 @@ static bool send_mouse_event(Terminal *term, int c) bool drag = false; switch (c) { - case K_LEFTDRAG: drag = true; FALLTHROUGH; - case K_LEFTMOUSE: button = 1; break; - case K_MOUSEMOVE: drag = true; button = 0; break; - case K_MIDDLEDRAG: drag = true; FALLTHROUGH; - case K_MIDDLEMOUSE: button = 2; break; - case K_RIGHTDRAG: drag = true; FALLTHROUGH; - case K_RIGHTMOUSE: button = 3; break; - case K_MOUSEDOWN: button = 4; break; - case K_MOUSEUP: button = 5; break; - default: return false; + case K_LEFTDRAG: + drag = true; FALLTHROUGH; + case K_LEFTMOUSE: + button = 1; break; + case K_MOUSEMOVE: + drag = true; button = 0; break; + case K_MIDDLEDRAG: + drag = true; FALLTHROUGH; + case K_MIDDLEMOUSE: + button = 2; break; + case K_RIGHTDRAG: + drag = true; FALLTHROUGH; + case K_RIGHTMOUSE: + button = 3; break; + case K_MOUSEDOWN: + button = 4; break; + case K_MOUSEUP: + button = 5; break; + default: + return false; } mouse_action(term, button, row, col - offset, drag, 0); @@ -1162,7 +1271,7 @@ static void fetch_row(Terminal *term, int row, int end_col) if (cell.chars[0]) { for (int i = 0; cell.chars[i]; i++) { cell_len += utf_char2bytes((int)cell.chars[i], - (uint8_t *)ptr + cell_len); + (uint8_t *)ptr + cell_len); } } else { *ptr = ' '; @@ -1181,8 +1290,7 @@ static void fetch_row(Terminal *term, int row, int end_col) term->textbuf[line_len] = 0; } -static bool fetch_cell(Terminal *term, int row, int col, - VTermScreenCell *cell) +static bool fetch_cell(Terminal *term, int row, int col, VTermScreenCell *cell) { if (row < 0) { ScrollbackLine *sbrow = term->sb_buffer[-row - 1]; @@ -1197,8 +1305,8 @@ static bool fetch_cell(Terminal *term, int row, int col, return false; } } else { - vterm_screen_get_cell(term->vts, (VTermPos){.row = row, .col = col}, - cell); + vterm_screen_get_cell(term->vts, (VTermPos){ .row = row, .col = col }, + cell); } return true; } diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index cc789cb6bd..9eb64f68ef 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -344,6 +344,7 @@ let s:filename_checks = { \ 'nanorc': ['/etc/nanorc', 'file.nanorc', 'any/etc/nanorc'], \ 'ncf': ['file.ncf'], \ 'netrc': ['.netrc'], + \ 'nginx': ['file.nginx', 'nginxfile.conf', 'filenginx.conf', 'any/etc/nginx/file', 'any/usr/local/nginx/conf/file', 'any/nginx/file.conf'], \ 'ninja': ['file.ninja'], \ 'nqc': ['file.nqc'], \ 'nroff': ['file.tr', 'file.nr', 'file.roff', 'file.tmac', 'file.mom', 'tmac.file'], diff --git a/src/nvim/ugrid.c b/src/nvim/ugrid.c index 9e4aaff878..ef84cdf334 100644 --- a/src/nvim/ugrid.c +++ b/src/nvim/ugrid.c @@ -2,14 +2,14 @@ // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com #include <assert.h> +#include <limits.h> #include <stdbool.h> #include <stdio.h> -#include <limits.h> #include "nvim/assert.h" -#include "nvim/vim.h" -#include "nvim/ui.h" #include "nvim/ugrid.h" +#include "nvim/ui.h" +#include "nvim/vim.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ugrid.c.generated.h" @@ -79,8 +79,7 @@ void ugrid_scroll(UGrid *grid, int top, int bot, int left, int right, int count) } } -static void clear_region(UGrid *grid, int top, int bot, int left, int right, - sattr_T attr) +static void clear_region(UGrid *grid, int top, int bot, int left, int right, sattr_T attr) { for (int row = top; row <= bot; row++) { UGRID_FOREACH_CELL(grid, row, left, right+1, { diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 09709d0f43..aad72af025 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -3,40 +3,40 @@ #include <assert.h> #include <inttypes.h> +#include <limits.h> #include <stdbool.h> #include <string.h> -#include <limits.h> -#include "nvim/vim.h" -#include "nvim/log.h" +#include "nvim/ascii.h" #include "nvim/aucmd.h" -#include "nvim/ui.h" #include "nvim/charset.h" #include "nvim/cursor.h" +#include "nvim/cursor_shape.h" #include "nvim/diff.h" +#include "nvim/event/loop.h" #include "nvim/ex_cmds2.h" #include "nvim/ex_getln.h" #include "nvim/fold.h" +#include "nvim/garray.h" +#include "nvim/highlight.h" +#include "nvim/log.h" #include "nvim/main.h" -#include "nvim/ascii.h" -#include "nvim/misc1.h" #include "nvim/mbyte.h" -#include "nvim/garray.h" #include "nvim/memory.h" +#include "nvim/misc1.h" #include "nvim/move.h" #include "nvim/normal.h" #include "nvim/option.h" -#include "nvim/os_unix.h" -#include "nvim/event/loop.h" -#include "nvim/os/time.h" #include "nvim/os/input.h" #include "nvim/os/signal.h" +#include "nvim/os/time.h" +#include "nvim/os_unix.h" #include "nvim/popupmnu.h" #include "nvim/screen.h" -#include "nvim/highlight.h" +#include "nvim/ui.h" #include "nvim/ui_compositor.h" +#include "nvim/vim.h" #include "nvim/window.h" -#include "nvim/cursor_shape.h" #ifdef FEAT_TUI # include "nvim/tui/tui.h" #else @@ -70,9 +70,9 @@ static int pending_has_mouse = -1; static size_t uilog_seen = 0; static char uilog_last_event[1024] = { 0 }; -#ifndef EXITFREE -#define entered_free_all_mem false -#endif +# ifndef EXITFREE +# define entered_free_all_mem false +# endif # define UI_LOG(funname) \ do { \ @@ -95,7 +95,7 @@ static char uilog_last_event[1024] = { 0 }; // UI_CALL invokes a function on all registered UI instances. // This is called by code generated by generators/gen_api_ui_events.lua // C code should use ui_call_{funname} instead. -# define UI_CALL(cond, funname, ...) \ +#define UI_CALL(cond, funname, ...) \ do { \ bool any_call = false; \ for (size_t i = 0; i < ui_count; i++) { \ @@ -115,7 +115,7 @@ static char uilog_last_event[1024] = { 0 }; #endif #ifndef EXITFREE -#undef entered_free_all_mem +# undef entered_free_all_mem #endif void ui_init(void) @@ -382,8 +382,8 @@ void ui_set_ext_option(UI *ui, UIExtension ext, bool active) } } -void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol, - int clearattr, bool wrap) +void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol, int clearattr, + bool wrap) { assert(0 <= row && row < grid->Rows); LineFlags flags = wrap ? kLineFlagWrap : 0; @@ -515,23 +515,23 @@ void ui_check_mouse(void) // normal editing mode (not at hit-return message). for (char_u *p = p_mouse; *p; p++) { switch (*p) { - case 'a': - if (vim_strchr((char_u *)MOUSE_A, checkfor) != NULL) { - has_mouse = true; - return; - } - break; - case MOUSE_HELP: - if (checkfor != MOUSE_RETURN && curbuf->b_help) { - has_mouse = true; - return; - } - break; - default: - if (checkfor == *p) { - has_mouse = true; - return; - } + case 'a': + if (vim_strchr((char_u *)MOUSE_A, checkfor) != NULL) { + has_mouse = true; + return; + } + break; + case MOUSE_HELP: + if (checkfor != MOUSE_RETURN && curbuf->b_help) { + has_mouse = true; + return; + } + break; + default: + if (checkfor == *p) { + has_mouse = true; + return; + } } } } diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c index bc64414ecf..3402df817a 100644 --- a/src/nvim/ui_bridge.c +++ b/src/nvim/ui_bridge.c @@ -5,18 +5,18 @@ // Used by the built-in TUI and libnvim-based UIs. #include <assert.h> +#include <limits.h> #include <stdbool.h> #include <stdio.h> -#include <limits.h> +#include "nvim/api/private/helpers.h" #include "nvim/log.h" #include "nvim/main.h" -#include "nvim/vim.h" -#include "nvim/ui.h" #include "nvim/memory.h" -#include "nvim/ui_bridge.h" #include "nvim/ugrid.h" -#include "nvim/api/private/helpers.h" +#include "nvim/ui.h" +#include "nvim/ui_bridge.h" +#include "nvim/vim.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ui_bridge.c.generated.h" @@ -26,8 +26,7 @@ // Schedule a function call on the UI bridge thread. #define UI_BRIDGE_CALL(ui, name, argc, ...) \ - ((UIBridgeData *)ui)->scheduler( \ - event_create(ui_bridge_##name##_event, argc, __VA_ARGS__), UI(ui)) + ((UIBridgeData *)ui)->scheduler(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) @@ -138,8 +137,8 @@ static void ui_bridge_stop_event(void **argv) ui->stop(ui); } -static void ui_bridge_hl_attr_define(UI *ui, Integer id, HlAttrs attrs, - HlAttrs cterm_attrs, Array info) +static void ui_bridge_hl_attr_define(UI *ui, Integer id, HlAttrs attrs, HlAttrs cterm_attrs, + Array info) { HlAttrs *a = xmalloc(sizeof(HlAttrs)); *a = attrs; @@ -163,11 +162,9 @@ static void ui_bridge_raw_line_event(void **argv) xfree(argv[8]); xfree(argv[9]); } -static void ui_bridge_raw_line(UI *ui, Integer grid, Integer row, - Integer startcol, Integer endcol, - Integer clearcol, Integer clearattr, - LineFlags flags, const schar_T *chunk, - const sattr_T *attrs) +static void ui_bridge_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Integer endcol, + Integer clearcol, Integer clearattr, LineFlags flags, + const schar_T *chunk, const sattr_T *attrs) { size_t ncol = (size_t)(endcol-startcol); schar_T *c = xmemdup(chunk, ncol * sizeof(schar_T)); diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c index 9c9aec1cf5..7a0f68cfeb 100644 --- a/src/nvim/ui_compositor.c +++ b/src/nvim/ui_compositor.c @@ -7,27 +7,27 @@ // Layer-based compositing: https://en.wikipedia.org/wiki/Digital_compositing #include <assert.h> +#include <limits.h> #include <stdbool.h> #include <stdio.h> -#include <limits.h> +#include "nvim/api/private/helpers.h" +#include "nvim/ascii.h" +#include "nvim/highlight.h" #include "nvim/lib/kvec.h" #include "nvim/log.h" +#include "nvim/lua/executor.h" #include "nvim/main.h" -#include "nvim/ascii.h" -#include "nvim/vim.h" -#include "nvim/ui.h" -#include "nvim/highlight.h" #include "nvim/memory.h" #include "nvim/message.h" +#include "nvim/os/os.h" #include "nvim/popupmnu.h" -#include "nvim/ui_compositor.h" -#include "nvim/ugrid.h" #include "nvim/screen.h" #include "nvim/syntax.h" -#include "nvim/api/private/helpers.h" -#include "nvim/lua/executor.h" -#include "nvim/os/os.h" +#include "nvim/ugrid.h" +#include "nvim/ui.h" +#include "nvim/ui_compositor.h" +#include "nvim/vim.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ui_compositor.c.generated.h" @@ -123,8 +123,8 @@ bool ui_comp_should_draw(void) /// TODO(bfredl): later on the compositor should just use win_float_pos events, /// though that will require slight event order adjustment: emit the win_pos /// events in the beginning of update_screen(0), rather than in ui_flush() -bool ui_comp_put_grid(ScreenGrid *grid, int row, int col, int height, int width, - bool valid, bool on_top) +bool ui_comp_put_grid(ScreenGrid *grid, int row, int col, int height, int width, bool valid, + bool on_top) { bool moved; @@ -257,8 +257,7 @@ static void ui_comp_raise_grid(ScreenGrid *grid, size_t new_index) } } -static void ui_comp_grid_cursor_goto(UI *ui, Integer grid_handle, - Integer r, Integer c) +static void ui_comp_grid_cursor_goto(UI *ui, Integer grid_handle, Integer r, Integer c) { if (!ui_comp_should_draw() || !ui_comp_set_grid((int)grid_handle)) { return; @@ -304,8 +303,7 @@ ScreenGrid *ui_comp_mouse_focus(int row, int col) /// Baseline implementation. This is always correct, but we can sometimes /// do something more efficient (where efficiency means smaller deltas to /// the downstream UI.) -static void compose_line(Integer row, Integer startcol, Integer endcol, - LineFlags flags) +static void compose_line(Integer row, Integer startcol, Integer endcol, LineFlags flags) { // If rightleft is set, startcol may be -1. In such cases, the assertions // will fail because no overlap is found. Adjust startcol to prevent it. @@ -447,8 +445,8 @@ static void compose_line(Integer row, Integer startcol, Integer endcol, (const sattr_T *)attrbuf+skipstart); } -static void compose_debug(Integer startrow, Integer endrow, Integer startcol, - Integer endcol, int syn_id, bool delay) +static void compose_debug(Integer startrow, Integer endrow, Integer startcol, Integer endcol, + int syn_id, bool delay) { if (!(rdb_flags & RDB_COMPOSITOR)) { return; @@ -479,8 +477,7 @@ static void debug_delay(Integer lines) } -static void compose_area(Integer startrow, Integer endrow, - Integer startcol, Integer endcol) +static void compose_area(Integer startrow, Integer endrow, Integer startcol, Integer endcol) { compose_debug(startrow, endrow, startcol, endcol, dbghl_recompose, true); endrow = MIN(endrow, default_grid.Rows); @@ -505,11 +502,9 @@ void ui_comp_compose_grid(ScreenGrid *grid) } } -static void ui_comp_raw_line(UI *ui, Integer grid, Integer row, - Integer startcol, Integer endcol, - Integer clearcol, Integer clearattr, - LineFlags flags, const schar_T *chunk, - const sattr_T *attrs) +static void ui_comp_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Integer endcol, + Integer clearcol, Integer clearattr, LineFlags flags, + const schar_T *chunk, const sattr_T *attrs) { if (!ui_comp_should_draw() || !ui_comp_set_grid((int)grid)) { return; @@ -529,11 +524,11 @@ static void ui_comp_raw_line(UI *ui, Integer grid, Integer row, // when resizing nvim, a window will be attempted to be drawn on the older // and possibly larger global screen size. if (row >= default_grid.Rows) { - DLOG("compositor: invalid row %"PRId64" on grid %"PRId64, row, grid); + DLOG("compositor: invalid row %" PRId64 " on grid %" PRId64, row, grid); return; } if (clearcol > default_grid.Columns) { - DLOG("compositor: invalid last column %"PRId64" on grid %"PRId64, + DLOG("compositor: invalid last column %" PRId64 " on grid %" PRId64, clearcol, grid); if (startcol >= default_grid.Columns) { return; @@ -572,8 +567,8 @@ void ui_comp_set_screen_valid(bool valid) } } -static void ui_comp_msg_set_pos(UI *ui, Integer grid, Integer row, - Boolean scrolled, String sep_char) +static void ui_comp_msg_set_pos(UI *ui, Integer grid, Integer row, Boolean scrolled, + String sep_char) { msg_grid.comp_row = (int)row; if (scrolled && row > 0) { @@ -617,9 +612,8 @@ static bool curgrid_covered_above(int row) return kv_size(layers)-(above_msg?1:0) > curgrid->comp_index+1; } -static void ui_comp_grid_scroll(UI *ui, Integer grid, Integer top, - Integer bot, Integer left, Integer right, - Integer rows, Integer cols) +static void ui_comp_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integer left, + Integer right, Integer rows, Integer cols) { if (!ui_comp_should_draw() || !ui_comp_set_grid((int)grid)) { return; @@ -653,8 +647,7 @@ static void ui_comp_grid_scroll(UI *ui, Integer grid, Integer top, } } -static void ui_comp_grid_resize(UI *ui, Integer grid, - Integer width, Integer height) +static void ui_comp_grid_resize(UI *ui, Integer grid, Integer width, Integer height) { if (grid == 1) { ui_composed_call_grid_resize(1, width, height); diff --git a/src/nvim/undo.c b/src/nvim/undo.c index fb96d7e6ff..af214815f8 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -71,52 +71,51 @@ /* Uncomment the next line for including the u_check() function. This warns * for errors in the debug information. */ -/* #define U_DEBUG 1 */ -#define UH_MAGIC 0x18dade /* value for uh_magic when in use */ -#define UE_MAGIC 0xabc123 /* value for ue_magic when in use */ +// #define U_DEBUG 1 +#define UH_MAGIC 0x18dade // value for uh_magic when in use +#define UE_MAGIC 0xabc123 // value for ue_magic when in use #include <assert.h> +#include <fcntl.h> #include <inttypes.h> #include <limits.h> #include <stdbool.h> #include <string.h> -#include <fcntl.h> #include "auto/config.h" - -#include "nvim/buffer.h" #include "nvim/ascii.h" +#include "nvim/buffer.h" +#include "nvim/buffer_updates.h" #include "nvim/change.h" -#include "nvim/undo.h" #include "nvim/cursor.h" #include "nvim/edit.h" +#include "nvim/extmark.h" #include "nvim/fileio.h" #include "nvim/fold.h" -#include "nvim/buffer_updates.h" -#include "nvim/pos.h" // MAXLNUM +#include "nvim/garray.h" +#include "nvim/lib/kvec.h" #include "nvim/mark.h" -#include "nvim/extmark.h" #include "nvim/memline.h" +#include "nvim/memory.h" #include "nvim/message.h" #include "nvim/misc1.h" -#include "nvim/memory.h" -#include "nvim/garray.h" #include "nvim/option.h" +#include "nvim/os/os.h" +#include "nvim/os/time.h" #include "nvim/os_unix.h" #include "nvim/path.h" +#include "nvim/pos.h" // MAXLNUM #include "nvim/sha256.h" #include "nvim/state.h" #include "nvim/strings.h" #include "nvim/types.h" -#include "nvim/os/os.h" -#include "nvim/os/time.h" -#include "nvim/lib/kvec.h" +#include "nvim/undo.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "undo.c.generated.h" #endif -/* used in undo_end() to report number of added and deleted lines */ +// used in undo_end() to report number of added and deleted lines static long u_newcount, u_oldcount; /* @@ -136,13 +135,12 @@ static int seen_b_u_curhead; static int seen_b_u_newhead; static int header_count; -static void u_check_tree(u_header_T *uhp, - u_header_T *exp_uh_next, - u_header_T *exp_uh_alt_prev) { +static void u_check_tree(u_header_T *uhp, u_header_T *exp_uh_next, u_header_T *exp_uh_alt_prev) { u_entry_T *uep; - if (uhp == NULL) + if (uhp == NULL) { return; + } ++header_count; if (uhp == curbuf->b_u_curhead && ++seen_b_u_curhead > 1) { EMSG("b_u_curhead found twice (looping?)"); @@ -153,22 +151,22 @@ static void u_check_tree(u_header_T *uhp, return; } - if (uhp->uh_magic != UH_MAGIC) + if (uhp->uh_magic != UH_MAGIC) { EMSG("uh_magic wrong (may be using freed memory)"); - else { - /* Check pointers back are correct. */ + } else { + // Check pointers back are correct. if (uhp->uh_next.ptr != exp_uh_next) { EMSG("uh_next wrong"); smsg("expected: 0x%x, actual: 0x%x", - exp_uh_next, uhp->uh_next.ptr); + exp_uh_next, uhp->uh_next.ptr); } if (uhp->uh_alt_prev.ptr != exp_uh_alt_prev) { EMSG("uh_alt_prev wrong"); smsg("expected: 0x%x, actual: 0x%x", - exp_uh_alt_prev, uhp->uh_alt_prev.ptr); + exp_uh_alt_prev, uhp->uh_alt_prev.ptr); } - /* Check the undo tree at this header. */ + // Check the undo tree at this header. for (uep = uhp->uh_entry; uep != NULL; uep = uep->ue_next) { if (uep->ue_magic != UE_MAGIC) { EMSG("ue_magic wrong (may be using freed memory)"); @@ -176,10 +174,10 @@ static void u_check_tree(u_header_T *uhp, } } - /* Check the next alt tree. */ + // Check the next alt tree. u_check_tree(uhp->uh_alt_next.ptr, uhp->uh_next.ptr, uhp); - /* Check the next header in this branch. */ + // Check the next header in this branch. u_check_tree(uhp->uh_prev.ptr, uhp, NULL); } } @@ -192,14 +190,16 @@ static void u_check(int newhead_may_be_NULL) { u_check_tree(curbuf->b_u_oldhead, NULL, NULL); if (seen_b_u_newhead == 0 && curbuf->b_u_oldhead != NULL - && !(newhead_may_be_NULL && curbuf->b_u_newhead == NULL)) + && !(newhead_may_be_NULL && curbuf->b_u_newhead == NULL)) { EMSGN("b_u_newhead invalid: 0x%x", curbuf->b_u_newhead); - if (curbuf->b_u_curhead != NULL && seen_b_u_curhead == 0) + } + if (curbuf->b_u_curhead != NULL && seen_b_u_curhead == 0) { EMSGN("b_u_curhead invalid: 0x%x", curbuf->b_u_curhead); + } if (header_count != curbuf->b_u_numhead) { EMSG("b_u_numhead invalid"); smsg("expected: %" PRId64 ", actual: %" PRId64, - (int64_t)header_count, (int64_t)curbuf->b_u_numhead); + (int64_t)header_count, (int64_t)curbuf->b_u_numhead); } } @@ -228,11 +228,12 @@ int u_save_cursor(void) int u_save(linenr_T top, linenr_T bot) { if (top >= bot || bot > (curbuf->b_ml.ml_line_count + 1)) { - return FAIL; /* rely on caller to do error messages */ + return FAIL; // rely on caller to do error messages } - if (top + 2 == bot) + if (top + 2 == bot) { u_saveline((linenr_T)(top + 1)); + } return u_savecommon(curbuf, top, bot, (linenr_T)0, false); } @@ -268,9 +269,8 @@ int u_inssub(linenr_T lnum) */ int u_savedel(linenr_T lnum, long nlines) { - return u_savecommon( - curbuf, lnum - 1, lnum + nlines, - nlines == curbuf->b_ml.ml_line_count ? 2 : lnum, false); + return u_savecommon(curbuf, lnum - 1, lnum + nlines, + nlines == curbuf->b_ml.ml_line_count ? 2 : lnum, false); } /// Return true when undo is allowed. Otherwise print an error message and @@ -327,16 +327,14 @@ static inline void zero_fmark_additional_data(fmark_T *fmarks) * Careful: may trigger autocommands that reload the buffer. * Returns FAIL when lines could not be saved, OK otherwise. */ -int u_savecommon(buf_T *buf, - linenr_T top, linenr_T bot, - linenr_T newbot, int reload) +int u_savecommon(buf_T *buf, linenr_T top, linenr_T bot, linenr_T newbot, int reload) { linenr_T lnum; long i; - u_header_T *uhp; - u_header_T *old_curhead; - u_entry_T *uep; - u_entry_T *prev_uep; + u_header_T *uhp; + u_header_T *old_curhead; + u_entry_T *uep; + u_entry_T *prev_uep; long size; if (!reload) { @@ -381,8 +379,9 @@ int u_savecommon(buf_T *buf, #ifdef U_DEBUG uhp->uh_magic = UH_MAGIC; #endif - } else + } else { uhp = NULL; + } /* * If we undid more than we redid, move the entry lists before and @@ -399,7 +398,7 @@ int u_savecommon(buf_T *buf, */ while (buf->b_u_numhead > get_undolevel(buf) && buf->b_u_oldhead != NULL) { - u_header_T *uhfree = buf->b_u_oldhead; + u_header_T *uhfree = buf->b_u_oldhead; if (uhfree == old_curhead) { // Can't reconnect the branch, delete all of it. @@ -459,11 +458,12 @@ int u_savecommon(buf_T *buf, uhp->uh_walk = 0; uhp->uh_entry = NULL; uhp->uh_getbot_entry = NULL; - uhp->uh_cursor = curwin->w_cursor; /* save cursor pos. for undo */ - if (virtual_active() && curwin->w_cursor.coladd > 0) + uhp->uh_cursor = curwin->w_cursor; // save cursor pos. for undo + if (virtual_active() && curwin->w_cursor.coladd > 0) { uhp->uh_cursor_vcol = getviscol(); - else + } else { uhp->uh_cursor_vcol = -1; + } // save changed and buffer empty flag for undo uhp->uh_flags = (buf->b_changed ? UH_CHANGED : 0) + @@ -499,8 +499,9 @@ int u_savecommon(buf_T *buf, uep = u_get_headentry(buf); prev_uep = NULL; for (i = 0; i < 10; ++i) { - if (uep == NULL) + if (uep == NULL) { break; + } /* If lines have been inserted/deleted we give up. * Also when the line was included in a multi-line save. */ @@ -509,14 +510,14 @@ int u_savecommon(buf_T *buf, != (uep->ue_bot == 0 ? buf->b_ml.ml_line_count + 1 : uep->ue_bot)) - : uep->ue_lcount != buf->b_ml.ml_line_count) + : uep->ue_lcount != buf->b_ml.ml_line_count) || (uep->ue_size > 1 && top >= uep->ue_top && top + 2 <= uep->ue_top + uep->ue_size + 1)) { break; } - /* If it's the same line we can skip saving it again. */ + // If it's the same line we can skip saving it again. if (uep->ue_size == 1 && uep->ue_top == top) { if (i > 0) { /* It's not the last entry: get ue_bot for the last @@ -609,25 +610,25 @@ int u_savecommon(buf_T *buf, // magic at start of undofile -# define UF_START_MAGIC "Vim\237UnDo\345" -# define UF_START_MAGIC_LEN 9 +#define UF_START_MAGIC "Vim\237UnDo\345" +#define UF_START_MAGIC_LEN 9 // magic at start of header -# define UF_HEADER_MAGIC 0x5fd0 +#define UF_HEADER_MAGIC 0x5fd0 // magic after last header -# define UF_HEADER_END_MAGIC 0xe7aa +#define UF_HEADER_END_MAGIC 0xe7aa // magic at start of entry -# define UF_ENTRY_MAGIC 0xf518 +#define UF_ENTRY_MAGIC 0xf518 // magic after last entry -# define UF_ENTRY_END_MAGIC 0x3581 +#define UF_ENTRY_END_MAGIC 0x3581 // 2-byte undofile version number -# define UF_VERSION 3 +#define UF_VERSION 3 -/* extra fields for header */ -# define UF_LAST_SAVE_NR 1 +// extra fields for header +#define UF_LAST_SAVE_NR 1 -/* extra fields for uhp */ -# define UHP_SAVE_NR 1 +// extra fields for uhp +#define UHP_SAVE_NR 1 static char_u e_not_open[] = N_("E828: Cannot open undo file for writing: %s"); @@ -640,7 +641,7 @@ void u_compute_hash(buf_T *buf, char_u *hash) { context_sha256_T ctx; linenr_T lnum; - char_u *p; + char_u *p; sha256_start(&ctx); for (lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) { @@ -688,7 +689,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading) // Loop over 'undodir'. When reading find the first file that exists. // When not reading use the first directory that exists or ".". - dirp = (char *) p_udir; + dirp = (char *)p_udir; while (*dirp != NUL) { size_t dir_len = copy_option_part((char_u **)&dirp, (char_u *)dir_name, MAXPATHL, ","); @@ -698,7 +699,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading) const size_t ffname_len = strlen(ffname); undo_file_name = xmalloc(ffname_len + 6); memmove(undo_file_name, ffname, ffname_len + 1); - char *const tail = (char *) path_tail((char_u *) undo_file_name); + char *const tail = (char *)path_tail((char_u *)undo_file_name); const size_t tail_len = strlen(tail); memmove(tail + 1, tail, tail_len + 1); *tail = '.'; @@ -754,8 +755,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading) /// /// @param[in] mesg Identifier of the corruption kind. /// @param[in] file_name File in which error occurred. -static void corruption_error(const char *const mesg, - const char *const file_name) +static void corruption_error(const char *const mesg, const char *const file_name) FUNC_ATTR_NONNULL_ALL { EMSG3(_("E825: Corrupted undo file (%s): %s"), mesg, file_name); @@ -763,8 +763,8 @@ static void corruption_error(const char *const mesg, static void u_free_uhp(u_header_T *uhp) { - u_entry_T *nuep; - u_entry_T *uep; + u_entry_T *nuep; + u_entry_T *uep; uep = uhp->uh_entry; while (uep != NULL) { @@ -890,8 +890,7 @@ static bool serialize_uhp(bufinfo_T *bi, u_header_T *uhp) return true; } -static u_header_T *unserialize_uhp(bufinfo_T *bi, - const char *file_name) +static u_header_T *unserialize_uhp(bufinfo_T *bi, const char *file_name) { u_header_T *uhp = xmalloc(sizeof(u_header_T)); memset(uhp, 0, sizeof(u_header_T)); @@ -999,7 +998,7 @@ static bool serialize_extmark(bufinfo_T *bi, ExtmarkUndoObject extup) undo_write_bytes(bi, (uintmax_t)extup.type, 4); if (!undo_write(bi, (uint8_t *)&(extup.data.splice), sizeof(ExtmarkSplice))) { - return false; + return false; } } else if (extup.type == kExtmarkMove) { undo_write_bytes(bi, (uintmax_t)UF_ENTRY_MAGIC, 2); @@ -1013,8 +1012,7 @@ static bool serialize_extmark(bufinfo_T *bi, ExtmarkUndoObject extup) return true; } -static ExtmarkUndoObject *unserialize_extmark(bufinfo_T *bi, bool *error, - const char *filename) +static ExtmarkUndoObject *unserialize_extmark(bufinfo_T *bi, bool *error, const char *filename) { UndoObjectType type; uint8_t *buf = NULL; @@ -1039,7 +1037,7 @@ static ExtmarkUndoObject *unserialize_extmark(bufinfo_T *bi, bool *error, } extup->data.move = *(ExtmarkMove *)buf; } else { - goto error; + goto error; } xfree(buf); @@ -1080,8 +1078,7 @@ static bool serialize_uep(bufinfo_T *bi, u_entry_T *uep) return true; } -static u_entry_T *unserialize_uep(bufinfo_T * bi, bool *error, - const char *file_name) +static u_entry_T *unserialize_uep(bufinfo_T * bi, bool *error, const char *file_name) { u_entry_T *uep = xmalloc(sizeof(u_entry_T)); memset(uep, 0, sizeof(u_entry_T)); @@ -1171,24 +1168,23 @@ static void unserialize_visualinfo(bufinfo_T *bi, visualinfo_T *info) /// @param[in] buf Buffer for which undo file is written. /// @param[in] hash Hash value of the buffer text. Must have #UNDO_HASH_SIZE /// size. -void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, - char_u *const hash) +void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, char_u *const hash) FUNC_ATTR_NONNULL_ARG(3, 4) { - u_header_T *uhp; + u_header_T *uhp; char *file_name; int mark; #ifdef U_DEBUG int headers_written = 0; #endif int fd; - FILE *fp = NULL; + FILE *fp = NULL; int perm; bool write_ok = false; bufinfo_T bi; if (name == NULL) { - file_name = u_get_undo_file_name((char *) buf->b_ffname, false); + file_name = u_get_undo_file_name((char *)buf->b_ffname, false); if (file_name == NULL) { if (p_verbose > 0) { verbose_enter(); @@ -1198,7 +1194,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, return; } } else { - file_name = (char *) name; + file_name = (char *)name; } /* @@ -1221,16 +1217,18 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, * file, and delete it. */ if (os_path_exists((char_u *)file_name)) { if (name == NULL || !forceit) { - /* Check we can read it and it's an undo file. */ + // Check we can read it and it's an undo file. fd = os_open(file_name, O_RDONLY, 0); if (fd < 0) { if (name != NULL || p_verbose > 0) { - if (name == NULL) + if (name == NULL) { verbose_enter(); + } smsg(_("Will not overwrite with undo file, cannot read: %s"), file_name); - if (name == NULL) + if (name == NULL) { verbose_leave(); + } } goto theend; } else { @@ -1240,12 +1238,14 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, if (len < UF_START_MAGIC_LEN || memcmp(mbuf, UF_START_MAGIC, UF_START_MAGIC_LEN) != 0) { if (name != NULL || p_verbose > 0) { - if (name == NULL) + if (name == NULL) { verbose_enter(); + } smsg(_("Will not overwrite, this is not an undo file: %s"), file_name); - if (name == NULL) + if (name == NULL) { verbose_leave(); + } } goto theend; } @@ -1276,7 +1276,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, } #ifdef U_DEBUG - /* Check there is no problem in undo info before writing. */ + // Check there is no problem in undo info before writing. u_check(FALSE); #endif @@ -1323,7 +1323,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, mark = ++lastmark; uhp = buf->b_u_oldhead; while (uhp != NULL) { - /* Serialize current UHP if we haven't seen it */ + // Serialize current UHP if we haven't seen it if (uhp->uh_walk != mark) { uhp->uh_walk = mark; #ifdef U_DEBUG @@ -1334,19 +1334,20 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, } } - /* Now walk through the tree - algorithm from undo_time(). */ - if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != mark) + // Now walk through the tree - algorithm from undo_time(). + if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != mark) { uhp = uhp->uh_prev.ptr; - else if (uhp->uh_alt_next.ptr != NULL - && uhp->uh_alt_next.ptr->uh_walk != mark) + } else if (uhp->uh_alt_next.ptr != NULL + && uhp->uh_alt_next.ptr->uh_walk != mark) { uhp = uhp->uh_alt_next.ptr; - else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL - && uhp->uh_next.ptr->uh_walk != mark) + } else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL + && uhp->uh_next.ptr->uh_walk != mark) { uhp = uhp->uh_next.ptr; - else if (uhp->uh_alt_prev.ptr != NULL) + } else if (uhp->uh_alt_prev.ptr != NULL) { uhp = uhp->uh_alt_prev.ptr; - else + } else { uhp = uhp->uh_next.ptr; + } } if (undo_write_bytes(&bi, (uintmax_t)UF_HEADER_END_MAGIC, 2)) { @@ -1361,14 +1362,15 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, write_error: fclose(fp); - if (!write_ok) + if (!write_ok) { EMSG2(_("E829: write error in undo file: %s"), file_name); + } #ifdef HAVE_ACL if (buf->b_ffname != NULL) { vim_acl_T 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(buf->b_ffname); mch_set_acl((char_u *)file_name, acl); mch_free_acl(acl); @@ -1376,8 +1378,9 @@ write_error: #endif theend: - if (file_name != name) + if (file_name != name) { xfree(file_name); + } } /// Loads the undo tree from an undo file. @@ -1385,8 +1388,7 @@ theend: /// a bit more verbose. /// Otherwise use curbuf->b_ffname to generate the undo file name. /// "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text. -void u_read_undo(char *name, const char_u *hash, - const char_u *orig_name FUNC_ATTR_UNUSED) +void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_ATTR_UNUSED) FUNC_ATTR_NONNULL_ARG(2) { u_header_T **uhp_table = NULL; @@ -1394,7 +1396,7 @@ void u_read_undo(char *name, const char_u *hash, char *file_name; if (name == NULL) { - file_name = u_get_undo_file_name((char *) curbuf->b_ffname, true); + file_name = u_get_undo_file_name((char *)curbuf->b_ffname, true); if (file_name == NULL) { return; } @@ -1418,7 +1420,7 @@ void u_read_undo(char *name, const char_u *hash, } #endif } else { - file_name = (char *) name; + file_name = (char *)name; } if (p_verbose > 0) { @@ -1465,7 +1467,7 @@ void u_read_undo(char *name, const char_u *hash, verbose_enter(); } give_warning((char_u *) - _("File contents changed, cannot use undo info"), true); + _("File contents changed, cannot use undo info"), true); if (name == NULL) { verbose_leave(); } @@ -1508,15 +1510,15 @@ void u_read_undo(char *name, const char_u *hash, } int what = undo_read_byte(&bi); switch (what) { - case UF_LAST_SAVE_NR: - last_save_nr = undo_read_4c(&bi); - break; + case UF_LAST_SAVE_NR: + last_save_nr = undo_read_4c(&bi); + break; - default: - // field not supported, skip - while (--len >= 0) { - (void)undo_read_byte(&bi); - } + default: + // field not supported, skip + while (--len >= 0) { + (void)undo_read_byte(&bi); + } } } @@ -1559,7 +1561,7 @@ void u_read_undo(char *name, const char_u *hash, size_t amount = num_head * sizeof(int) + 1; int *uhp_table_used = xmalloc(amount); memset(uhp_table_used, 0, amount); -# define SET_FLAG(j) ++ uhp_table_used[j] +# define SET_FLAG(j) ++uhp_table_used[j] #else # define SET_FLAG(j) #endif @@ -1666,10 +1668,11 @@ void u_read_undo(char *name, const char_u *hash, error: xfree(line_ptr); if (uhp_table != NULL) { - for (long i = 0; i < num_read_uhps; i++) + for (long i = 0; i < num_read_uhps; i++) { if (uhp_table[i] != NULL) { u_free_uhp(uhp_table[i]); } + } xfree(uhp_table); } @@ -1844,7 +1847,7 @@ bool u_undo_and_forget(int count) 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_next.ptr ? - curbuf->b_u_curhead->uh_next.ptr->uh_seq : 0; + 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; } @@ -1876,8 +1879,9 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event) u_newcount = 0; u_oldcount = 0; - if (curbuf->b_ml.ml_flags & ML_EMPTY) + if (curbuf->b_ml.ml_flags & ML_EMPTY) { u_oldcount = -1; + } while (count--) { /* Do the change warning now, so that it triggers FileChangedRO when * needed. This may cause the file to be reloaded, that must happen @@ -1894,7 +1898,7 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event) } // nothing to undo if (curbuf->b_u_numhead == 0 || curbuf->b_u_curhead == NULL) { - /* stick curbuf->b_u_curhead at end */ + // stick curbuf->b_u_curhead at end curbuf->b_u_curhead = curbuf->b_u_oldhead; beep_flush(); if (count == startcount - 1) { @@ -1919,8 +1923,9 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event) /* Advance for next redo. Set "newhead" when at the end of the * redoable changes. */ - if (curbuf->b_u_curhead->uh_prev.ptr == NULL) + if (curbuf->b_u_curhead->uh_prev.ptr == NULL) { curbuf->b_u_newhead = curbuf->b_u_curhead; + } curbuf->b_u_curhead = curbuf->b_u_curhead->uh_prev.ptr; } } @@ -1941,8 +1946,8 @@ void undo_time(long step, bool sec, bool file, bool absolute) long closest_start; long closest_seq = 0; long val; - u_header_T *uhp = NULL; - u_header_T *last; + u_header_T *uhp = NULL; + u_header_T *last; int mark; int nomark = 0; // shut up compiler int round; @@ -1958,8 +1963,9 @@ void undo_time(long step, bool sec, bool file, bool absolute) u_newcount = 0; u_oldcount = 0; - if (curbuf->b_ml.ml_flags & ML_EMPTY) + if (curbuf->b_ml.ml_flags & ML_EMPTY) { u_oldcount = -1; + } /* "target" is the node below which we want to be. * Init "closest" to a value we can't reach. */ @@ -1975,23 +1981,26 @@ void undo_time(long step, bool sec, bool file, bool absolute) * the last write, count that as moving one file-write, so * that ":earlier 1f" undoes all changes since the last save. */ uhp = curbuf->b_u_curhead; - if (uhp != NULL) + if (uhp != NULL) { uhp = uhp->uh_next.ptr; - else + } else { uhp = curbuf->b_u_newhead; - if (uhp != NULL && uhp->uh_save_nr != 0) + } + if (uhp != NULL && uhp->uh_save_nr != 0) { /* "uh_save_nr" was set in the last block, that means * there were no changes since the last write */ target = curbuf->b_u_save_nr_cur + step; - else - /* count the changes since the last write as one step */ + } else { + // count the changes since the last write as one step target = curbuf->b_u_save_nr_cur + step + 1; - if (target <= 0) + } + if (target <= 0) { /* Go to before first write: before the oldest change. Use * the sequence number for that. */ dofile = false; + } } else { - /* Moving forward to a newer write. */ + // Moving forward to a newer write. target = curbuf->b_u_save_nr_cur + step; if (target > curbuf->b_u_save_nr_last) { /* Go to after last write: after the latest change. Use @@ -2000,11 +2009,13 @@ void undo_time(long step, bool sec, bool file, bool absolute) dofile = false; } } - } else + } else { target = curbuf->b_u_seq_cur + step; + } if (step < 0) { - if (target < 0) + if (target < 0) { target = 0; + } closest = -1; } else { if (dosec) { @@ -2044,10 +2055,11 @@ void undo_time(long step, bool sec, bool file, bool absolute) mark = ++lastmark; nomark = ++lastmark; - if (curbuf->b_u_curhead == NULL) /* at leaf of the tree */ + if (curbuf->b_u_curhead == NULL) { // at leaf of the tree uhp = curbuf->b_u_newhead; - else + } else { uhp = curbuf->b_u_curhead; + } while (uhp != NULL) { uhp->uh_walk = mark; @@ -2065,17 +2077,17 @@ void undo_time(long step, bool sec, bool file, bool absolute) * "b_u_seq_cur"). When the timestamp is equal find the * highest/lowest sequence number. */ if ((step < 0 ? uhp->uh_seq <= curbuf->b_u_seq_cur - : uhp->uh_seq > curbuf->b_u_seq_cur) + : uhp->uh_seq > curbuf->b_u_seq_cur) && ((dosec && val == closest) ? (step < 0 ? uhp->uh_seq < closest_seq - : uhp->uh_seq > closest_seq) - : closest == closest_start + : uhp->uh_seq > closest_seq) + : closest == closest_start || (val > target ? (closest > target ? val - target <= closest - target : val - target <= target - closest) - : (closest > target + : (closest > target ? target - val <= closest - target : target - val <= target - closest)))) { closest = val; @@ -2090,38 +2102,41 @@ void undo_time(long step, bool sec, bool file, bool absolute) break; } - /* go down in the tree if we haven't been there */ + // go down in the tree if we haven't been there if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != nomark - && uhp->uh_prev.ptr->uh_walk != mark) + && uhp->uh_prev.ptr->uh_walk != mark) { uhp = uhp->uh_prev.ptr; - - /* go to alternate branch if we haven't been there */ + } + // go to alternate branch if we haven't been there else if (uhp->uh_alt_next.ptr != NULL && uhp->uh_alt_next.ptr->uh_walk != nomark - && uhp->uh_alt_next.ptr->uh_walk != mark) + && uhp->uh_alt_next.ptr->uh_walk != mark) { uhp = uhp->uh_alt_next.ptr; - + } /* go up in the tree if we haven't been there and we are at the * start of alternate branches */ else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL && uhp->uh_next.ptr->uh_walk != nomark && uhp->uh_next.ptr->uh_walk != mark) { - /* If still at the start we don't go through this change. */ - if (uhp == curbuf->b_u_curhead) + // If still at the start we don't go through this change. + if (uhp == curbuf->b_u_curhead) { uhp->uh_walk = nomark; + } uhp = uhp->uh_next.ptr; } else { - /* need to backtrack; mark this node as useless */ + // need to backtrack; mark this node as useless uhp->uh_walk = nomark; - if (uhp->uh_alt_prev.ptr != NULL) + if (uhp->uh_alt_prev.ptr != NULL) { uhp = uhp->uh_alt_prev.ptr; - else + } else { uhp = uhp->uh_next.ptr; + } } } - if (uhp != NULL) /* found it */ + if (uhp != NULL) { // found it break; + } if (absolute) { EMSGN(_("E830: Undo number %" PRId64 " not found"), step); @@ -2129,10 +2144,11 @@ void undo_time(long step, bool sec, bool file, bool absolute) } if (closest == closest_start) { - if (step < 0) + if (step < 0) { MSG(_("Already at oldest change")); - else + } else { MSG(_("Already at newest change")); + } return; } @@ -2153,10 +2169,11 @@ target_zero: change_warning(curbuf, 0); uhp = curbuf->b_u_curhead; - if (uhp == NULL) + if (uhp == NULL) { uhp = curbuf->b_u_newhead; - else + } else { uhp = uhp->uh_next.ptr; + } if (uhp == NULL || (target > 0 && uhp->uh_walk != mark) || (uhp->uh_seq == target && !above)) { @@ -2264,21 +2281,21 @@ target_zero: /// @param do_buf_event If `true`, send buffer updates. static void u_undoredo(int undo, bool do_buf_event) { - char_u **newarray = NULL; + char_u **newarray = NULL; linenr_T oldsize; linenr_T newsize; linenr_T top, bot; linenr_T lnum; linenr_T newlnum = MAXLNUM; long i; - u_entry_T *uep, *nuep; - u_entry_T *newlist = NULL; + u_entry_T *uep, *nuep; + u_entry_T *newlist = NULL; int old_flags; int new_flags; fmark_T namedm[NMARKS]; visualinfo_T visualinfo; bool empty_buffer; // buffer became empty - u_header_T *curhead = curbuf->b_u_curhead; + u_header_T *curhead = curbuf->b_u_curhead; /* Don't want autocommands using the undo structures here, they are * invalid till the end. */ @@ -2307,8 +2324,9 @@ static void u_undoredo(int undo, bool do_buf_event) for (uep = curhead->uh_entry; uep != NULL; uep = nuep) { top = uep->ue_top; bot = uep->ue_bot; - if (bot == 0) + if (bot == 0) { bot = curbuf->b_ml.ml_line_count + 1; + } if (top > curbuf->b_ml.ml_line_count || top >= bot || bot > curbuf->b_ml.ml_line_count + 1) { unblock_autocmds(); @@ -2317,8 +2335,8 @@ static void u_undoredo(int undo, bool do_buf_event) return; } - oldsize = bot - top - 1; /* number of lines before undo */ - newsize = uep->ue_size; /* number of lines after undo */ + oldsize = bot - top - 1; // number of lines before undo + newsize = uep->ue_size; // number of lines after undo if (top < newlnum) { /* If the saved cursor is somewhere in this undo block, move it to @@ -2332,13 +2350,15 @@ static void u_undoredo(int undo, bool do_buf_event) /* Use the first line that actually changed. Avoids that * undoing auto-formatting puts the cursor in the previous * line. */ - for (i = 0; i < newsize && i < oldsize; ++i) - if (STRCMP(uep->ue_array[i], ml_get(top + 1 + i)) != 0) + for (i = 0; i < newsize && i < oldsize; ++i) { + if (STRCMP(uep->ue_array[i], ml_get(top + 1 + i)) != 0) { break; + } + } if (i == newsize && newlnum == MAXLNUM && uep->ue_next == NULL) { newlnum = top; curwin->w_cursor.lnum = newlnum + 1; - } else if (i < newsize) { + } else if (i < newsize) { newlnum = top + i; curwin->w_cursor.lnum = newlnum + 1; } @@ -2347,12 +2367,12 @@ static void u_undoredo(int undo, bool do_buf_event) empty_buffer = false; - /* delete the lines between top and bot and save them in newarray */ + // delete the lines between top and bot and save them in newarray if (oldsize > 0) { newarray = xmalloc(sizeof(char_u *) * (size_t)oldsize); - /* delete backwards, it goes faster in most cases */ + // delete backwards, it goes faster in most cases for (lnum = bot - 1, i = oldsize; --i >= 0; --lnum) { - /* what can we do when we run out of memory? */ + // what can we do when we run out of memory? newarray[i] = u_save_line(lnum); /* remember we deleted the last line in the buffer, and a * dummy empty line will be inserted */ @@ -2361,10 +2381,11 @@ static void u_undoredo(int undo, bool do_buf_event) } ml_delete(lnum, false); } - } else + } else { newarray = NULL; + } - /* insert the lines in u_array between top and bot */ + // insert the lines in u_array between top and bot if (newsize) { for (lnum = top, i = 0; i < newsize; ++i, ++lnum) { /* @@ -2395,13 +2416,15 @@ static void u_undoredo(int undo, bool do_buf_event) changed_lines(top + 1, 0, bot, newsize - oldsize, do_buf_event); - /* set '[ and '] mark */ - if (top + 1 < curbuf->b_op_start.lnum) + // set '[ and '] mark + if (top + 1 < curbuf->b_op_start.lnum) { curbuf->b_op_start.lnum = top + 1; - if (newsize == 0 && top + 1 > curbuf->b_op_end.lnum) + } + if (newsize == 0 && top + 1 > curbuf->b_op_end.lnum) { curbuf->b_op_end.lnum = top + 1; - else if (top + newsize > curbuf->b_op_end.lnum) + } else if (top + newsize > curbuf->b_op_end.lnum) { curbuf->b_op_end.lnum = top + newsize; + } u_newcount += newsize; u_oldcount += oldsize; @@ -2424,7 +2447,7 @@ static void u_undoredo(int undo, bool do_buf_event) undo_info = kv_A(curhead->uh_extmark, i); extmark_apply_undo(undo_info, undo); } - // redo + // redo } else { for (i = 0; i < (int)kv_size(curhead->uh_extmark); i++) { undo_info = kv_A(curhead->uh_extmark, i); @@ -2482,17 +2505,20 @@ static void u_undoredo(int undo, bool do_buf_event) * Otherwise the cursor should go to the first undone line. */ if (curhead->uh_cursor.lnum + 1 == curwin->w_cursor.lnum - && curwin->w_cursor.lnum > 1) + && curwin->w_cursor.lnum > 1) { --curwin->w_cursor.lnum; + } if (curwin->w_cursor.lnum <= curbuf->b_ml.ml_line_count) { if (curhead->uh_cursor.lnum == curwin->w_cursor.lnum) { curwin->w_cursor.col = curhead->uh_cursor.col; - if (virtual_active() && curhead->uh_cursor_vcol >= 0) + if (virtual_active() && curhead->uh_cursor_vcol >= 0) { coladvance((colnr_T)curhead->uh_cursor_vcol); - else + } else { curwin->w_cursor.coladd = 0; - } else + } + } else { beginline(BL_SOL | BL_FIX); + } } else { /* We get here with the current cursor line being past the end (eg * after adding lines at the end of the file, and then undoing it). @@ -2502,23 +2528,25 @@ static void u_undoredo(int undo, bool do_buf_event) curwin->w_cursor.coladd = 0; } - /* Make sure the cursor is on an existing line and column. */ + // Make sure the cursor is on an existing line and column. check_cursor(); - /* Remember where we are for "g-" and ":earlier 10s". */ + // Remember where we are for "g-" and ":earlier 10s". curbuf->b_u_seq_cur = curhead->uh_seq; - if (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 = curhead->uh_next.ptr ? - curhead->uh_next.ptr->uh_seq : 0; + curhead->uh_next.ptr->uh_seq : 0; + } - /* Remember where we are for ":earlier 1f" and ":later 1f". */ + // Remember where we are for ":earlier 1f" and ":later 1f". if (curhead->uh_save_nr != 0) { - if (undo) + if (undo) { curbuf->b_u_save_nr_cur = curhead->uh_save_nr - 1; - else + } else { curbuf->b_u_save_nr_cur = curhead->uh_save_nr; + } } /* The timestamp can be the same for multiple changes, just use the one of @@ -2534,17 +2562,18 @@ static void u_undoredo(int undo, bool do_buf_event) /// If we deleted or added lines, report the number of less/more lines. /// Otherwise, report the number of changes (this may be incorrect /// in some cases, but it's better than nothing). -static void u_undo_end( - bool did_undo, ///< just did an undo - bool absolute, ///< used ":undo N" - bool quiet) +/// +/// @param did_undo just did an undo +/// @param absolute used ":undo N" +static void u_undo_end(bool did_undo, bool absolute, bool quiet) { - char *msgstr; - u_header_T *uhp; + char *msgstr; + u_header_T *uhp; char_u msgbuf[80]; - if ((fdo_flags & FDO_UNDO) && KeyTyped) + if ((fdo_flags & FDO_UNDO) && KeyTyped) { foldOpenCursor(); + } if (quiet || global_busy // no messages until global is finished @@ -2552,28 +2581,30 @@ static void u_undo_end( return; } - if (curbuf->b_ml.ml_flags & ML_EMPTY) + if (curbuf->b_ml.ml_flags & ML_EMPTY) { --u_newcount; + } u_oldcount -= u_newcount; - if (u_oldcount == -1) + if (u_oldcount == -1) { msgstr = N_("more line"); - else if (u_oldcount < 0) + } else if (u_oldcount < 0) { msgstr = N_("more lines"); - else if (u_oldcount == 1) + } else if (u_oldcount == 1) { msgstr = N_("line less"); - else if (u_oldcount > 1) + } else if (u_oldcount > 1) { msgstr = N_("fewer lines"); - else { + } else { u_oldcount = u_newcount; - if (u_newcount == 1) + if (u_newcount == 1) { msgstr = N_("change"); - else + } else { msgstr = N_("changes"); + } } if (curbuf->b_u_curhead != NULL) { - /* For ":undo N" we prefer a "after #N" message. */ + // For ":undo N" we prefer a "after #N" message. if (absolute && curbuf->b_u_curhead->uh_next.ptr != NULL) { uhp = curbuf->b_u_curhead->uh_next.ptr; did_undo = false; @@ -2600,14 +2631,13 @@ static void u_undo_end( } } - smsg_attr_keep( - 0, - _("%" PRId64 " %s; %s #%" PRId64 " %s"), - u_oldcount < 0 ? (int64_t)-u_oldcount : (int64_t)u_oldcount, - _(msgstr), - did_undo ? _("before") : _("after"), - uhp == NULL ? (int64_t)0L : (int64_t)uhp->uh_seq, - msgbuf); + smsg_attr_keep(0, + _("%" PRId64 " %s; %s #%" PRId64 " %s"), + u_oldcount < 0 ? (int64_t)-u_oldcount : (int64_t)u_oldcount, + _(msgstr), + did_undo ? _("before") : _("after"), + uhp == NULL ? (int64_t)0L : (int64_t)uhp->uh_seq, + msgbuf); } /// u_sync: stop adding to the current entry list @@ -2634,7 +2664,7 @@ void u_sync(bool force) void ex_undolist(exarg_T *eap) { garray_T ga; - u_header_T *uhp; + u_header_T *uhp; int mark; int nomark; int changes = 1; @@ -2657,28 +2687,29 @@ void ex_undolist(exarg_T *eap) add_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff), uhp->uh_time); if (uhp->uh_save_nr > 0) { - while (STRLEN(IObuff) < 33) + while (STRLEN(IObuff) < 33) { STRCAT(IObuff, " "); + } vim_snprintf_add((char *)IObuff, IOSIZE, - " %3ld", uhp->uh_save_nr); + " %3ld", uhp->uh_save_nr); } GA_APPEND(char_u *, &ga, vim_strsave(IObuff)); } uhp->uh_walk = mark; - /* go down in the tree if we haven't been there */ + // go down in the tree if we haven't been there if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != nomark && uhp->uh_prev.ptr->uh_walk != mark) { uhp = uhp->uh_prev.ptr; ++changes; } - /* go to alternate branch if we haven't been there */ + // go to alternate branch if we haven't been there else if (uhp->uh_alt_next.ptr != NULL && uhp->uh_alt_next.ptr->uh_walk != nomark - && uhp->uh_alt_next.ptr->uh_walk != mark) + && uhp->uh_alt_next.ptr->uh_walk != mark) { uhp = uhp->uh_alt_next.ptr; - + } /* go up in the tree if we haven't been there and we are at the * start of alternate branches */ else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL @@ -2687,20 +2718,20 @@ void ex_undolist(exarg_T *eap) uhp = uhp->uh_next.ptr; --changes; } else { - /* need to backtrack; mark this node as done */ + // need to backtrack; mark this node as done uhp->uh_walk = nomark; - if (uhp->uh_alt_prev.ptr != NULL) + if (uhp->uh_alt_prev.ptr != NULL) { uhp = uhp->uh_alt_prev.ptr; - else { + } else { uhp = uhp->uh_next.ptr; --changes; } } } - if (GA_EMPTY(&ga)) + if (GA_EMPTY(&ga)) { MSG(_("Nothing to undo")); - else { + } else { sort_strings((char_u **)ga.ga_data, ga.ga_len); msg_start(); @@ -2757,17 +2788,18 @@ void u_unchanged(buf_T *buf) */ void u_find_first_changed(void) { - u_header_T *uhp = curbuf->b_u_newhead; - u_entry_T *uep; + u_header_T *uhp = curbuf->b_u_newhead; + u_entry_T *uep; linenr_T lnum; - if (curbuf->b_u_curhead != NULL || uhp == NULL) - return; /* undid something in an autocmd? */ - - /* Check that the last undo block was for the whole file. */ + if (curbuf->b_u_curhead != NULL || uhp == NULL) { + return; // undid something in an autocmd? + } + // Check that the last undo block was for the whole file. uep = uhp->uh_entry; - if (uep->ue_top != 0 || uep->ue_bot != 0) + if (uep->ue_top != 0 || uep->ue_bot != 0) { return; + } for (lnum = 1; lnum < curbuf->b_ml.ml_line_count && lnum <= uep->ue_size; lnum++) { @@ -2778,7 +2810,7 @@ void u_find_first_changed(void) } } if (curbuf->b_ml.ml_line_count != uep->ue_size) { - /* lines added or deleted at the end, put the cursor there */ + // lines added or deleted at the end, put the cursor there clearpos(&(uhp->uh_cursor)); uhp->uh_cursor.lnum = lnum; } @@ -2790,27 +2822,30 @@ void u_find_first_changed(void) */ void u_update_save_nr(buf_T *buf) { - u_header_T *uhp; + u_header_T *uhp; ++buf->b_u_save_nr_last; buf->b_u_save_nr_cur = buf->b_u_save_nr_last; uhp = buf->b_u_curhead; - if (uhp != NULL) + if (uhp != NULL) { uhp = uhp->uh_next.ptr; - else + } else { uhp = buf->b_u_newhead; - if (uhp != NULL) + } + if (uhp != NULL) { uhp->uh_save_nr = buf->b_u_save_nr_last; + } } static void u_unch_branch(u_header_T *uhp) { - u_header_T *uh; + u_header_T *uh; for (uh = uhp; uh != NULL; uh = uh->uh_prev.ptr) { uh->uh_flags |= UH_CHANGED; - if (uh->uh_alt_next.ptr != NULL) - u_unch_branch(uh->uh_alt_next.ptr); /* recursive */ + if (uh->uh_alt_next.ptr != NULL) { + u_unch_branch(uh->uh_alt_next.ptr); // recursive + } } } @@ -2829,11 +2864,11 @@ static u_entry_T *u_get_headentry(buf_T *buf) /* * u_getbot(): compute the line number of the previous u_save - * It is called only when b_u_synced is false. + * It is called only when b_u_synced is false. */ static void u_getbot(buf_T *buf) { - u_entry_T *uep; + u_entry_T *uep; linenr_T extra; uep = u_get_headentry(buf); // check for corrupt undo list @@ -2864,95 +2899,91 @@ static void u_getbot(buf_T *buf) buf->b_u_synced = true; } -/* - * Free one header "uhp" and its entry list and adjust the pointers. - */ -static void -u_freeheader( - buf_T *buf, - u_header_T *uhp, - u_header_T **uhpp // if not NULL reset when freeing this header -) +/// Free one header "uhp" and its entry list and adjust the pointers. +/// +/// @param uhpp if not NULL reset when freeing this header +static void u_freeheader(buf_T *buf, u_header_T *uhp, u_header_T **uhpp) { - u_header_T *uhap; + u_header_T *uhap; /* When there is an alternate redo list free that branch completely, * because we can never go there. */ - if (uhp->uh_alt_next.ptr != NULL) + if (uhp->uh_alt_next.ptr != NULL) { u_freebranch(buf, uhp->uh_alt_next.ptr, uhpp); + } - if (uhp->uh_alt_prev.ptr != NULL) + if (uhp->uh_alt_prev.ptr != NULL) { uhp->uh_alt_prev.ptr->uh_alt_next.ptr = NULL; + } - /* Update the links in the list to remove the header. */ - if (uhp->uh_next.ptr == NULL) + // Update the links in the list to remove the header. + if (uhp->uh_next.ptr == NULL) { buf->b_u_oldhead = uhp->uh_prev.ptr; - else + } else { uhp->uh_next.ptr->uh_prev.ptr = uhp->uh_prev.ptr; + } - if (uhp->uh_prev.ptr == NULL) + if (uhp->uh_prev.ptr == NULL) { buf->b_u_newhead = uhp->uh_next.ptr; - else + } else { for (uhap = uhp->uh_prev.ptr; uhap != NULL; - uhap = uhap->uh_alt_next.ptr) + uhap = uhap->uh_alt_next.ptr) { uhap->uh_next.ptr = uhp->uh_next.ptr; + } + } u_freeentries(buf, uhp, uhpp); } -/* - * Free an alternate branch and any following alternate branches. - */ -static void -u_freebranch( - buf_T *buf, - u_header_T *uhp, - u_header_T **uhpp // if not NULL reset when freeing this header -) +/// Free an alternate branch and any following alternate branches. +/// +/// @param uhpp if not NULL reset when freeing this header +static void u_freebranch(buf_T *buf, u_header_T *uhp, u_header_T **uhpp) { - u_header_T *tofree, *next; + u_header_T *tofree, *next; /* If this is the top branch we may need to use u_freeheader() to update * all the pointers. */ if (uhp == buf->b_u_oldhead) { - while (buf->b_u_oldhead != NULL) + while (buf->b_u_oldhead != NULL) { u_freeheader(buf, buf->b_u_oldhead, uhpp); + } return; } - if (uhp->uh_alt_prev.ptr != NULL) + if (uhp->uh_alt_prev.ptr != NULL) { uhp->uh_alt_prev.ptr->uh_alt_next.ptr = NULL; + } next = uhp; while (next != NULL) { tofree = next; - if (tofree->uh_alt_next.ptr != NULL) - u_freebranch(buf, tofree->uh_alt_next.ptr, uhpp); /* recursive */ + if (tofree->uh_alt_next.ptr != NULL) { + u_freebranch(buf, tofree->uh_alt_next.ptr, uhpp); // recursive + } next = tofree->uh_prev.ptr; u_freeentries(buf, tofree, uhpp); } } -/* - * Free all the undo entries for one header and the header itself. - * This means that "uhp" is invalid when returning. - */ -static void -u_freeentries( - buf_T *buf, - u_header_T *uhp, - u_header_T **uhpp // if not NULL reset when freeing this header -) +/// Free all the undo entries for one header and the header itself. +/// This means that "uhp" is invalid when returning. +/// +/// @param uhpp if not NULL reset when freeing this header +static void u_freeentries(buf_T *buf, u_header_T *uhp, u_header_T **uhpp) { - u_entry_T *uep, *nuep; + u_entry_T *uep, *nuep; - /* Check for pointers to the header that become invalid now. */ - if (buf->b_u_curhead == uhp) + // Check for pointers to the header that become invalid now. + if (buf->b_u_curhead == uhp) { buf->b_u_curhead = NULL; - if (buf->b_u_newhead == uhp) - buf->b_u_newhead = NULL; /* freeing the newest entry */ - if (uhpp != NULL && uhp == *uhpp) + } + if (buf->b_u_newhead == uhp) { + buf->b_u_newhead = NULL; // freeing the newest entry + } + if (uhpp != NULL && uhp == *uhpp) { *uhpp = NULL; + } for (uep = uhp->uh_entry; uep != NULL; uep = nuep) { nuep = uep->ue_next; @@ -2973,8 +3004,9 @@ u_freeentries( */ static void u_freeentry(u_entry_T *uep, long n) { - while (n > 0) + while (n > 0) { xfree(uep->ue_array[--n]); + } xfree((char_u *)uep->ue_array); #ifdef U_DEBUG uep->ue_magic = 0; @@ -2999,16 +3031,19 @@ void u_clearall(buf_T *buf) */ void u_saveline(linenr_T lnum) { - if (lnum == curbuf->b_u_line_lnum) /* line is already saved */ + if (lnum == curbuf->b_u_line_lnum) { // line is already saved return; - if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) /* should never happen */ + } + if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) { // should never happen return; + } u_clearline(); curbuf->b_u_line_lnum = lnum; - if (curwin->w_cursor.lnum == lnum) + if (curwin->w_cursor.lnum == lnum) { curbuf->b_u_line_colnr = curwin->w_cursor.col; - else + } else { curbuf->b_u_line_colnr = 0; + } curbuf->b_u_line_ptr = u_save_line(lnum); } @@ -3033,7 +3068,7 @@ void u_clearline(void) void u_undoline(void) { colnr_T t; - char_u *oldp; + char_u *oldp; if (curbuf->b_u_line_ptr == NULL || curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count) { @@ -3054,8 +3089,9 @@ void u_undoline(void) curbuf->b_u_line_ptr = oldp; t = curbuf->b_u_line_colnr; - if (curwin->w_cursor.lnum == curbuf->b_u_line_lnum) + if (curwin->w_cursor.lnum == curbuf->b_u_line_lnum) { curbuf->b_u_line_colnr = curwin->w_cursor.col; + } curwin->w_cursor.col = t; curwin->w_cursor.lnum = curbuf->b_u_line_lnum; check_cursor_col(); @@ -3106,8 +3142,8 @@ bool bufIsChanged(buf_T *buf) { // In a "prompt" buffer we do respect 'modified', so that we can control // closing the window by setting or resetting that option. - return (!bt_dontwrite(buf) || bt_prompt(buf)) - && (buf->b_changed || file_ff_differs(buf, true)); + return (!bt_dontwrite(buf) || bt_prompt(buf)) + && (buf->b_changed || file_ff_differs(buf, true)); } // Return true if any buffer has changes. Also buffers that are not written. diff --git a/src/nvim/version.c b/src/nvim/version.c index 7c197f1b7f..bc06ef0b98 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -6,32 +6,32 @@ /// Nvim was forked from Vim 7.4.160. /// Vim originated from Stevie version 3.6 (Fish disk 217) by GRWalter (Fred). -#include <inttypes.h> #include <assert.h> +#include <inttypes.h> #include <limits.h> #include "nvim/api/private/helpers.h" -#include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/buffer.h" -#include "nvim/iconv.h" -#include "nvim/version.h" #include "nvim/charset.h" +#include "nvim/iconv.h" +#include "nvim/lua/executor.h" #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/screen.h" #include "nvim/strings.h" -#include "nvim/lua/executor.h" +#include "nvim/version.h" +#include "nvim/vim.h" // version info generated by the build system #include "auto/versiondef.h" // for ":version", ":intro", and "nvim --version" #ifndef NVIM_VERSION_MEDIUM -#define NVIM_VERSION_MEDIUM "v" 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 @@ -50,23 +50,23 @@ char *version_cflags = "Compilation: " NVIM_VERSION_CFLAGS; static char *features[] = { #ifdef HAVE_ACL -"+acl", + "+acl", #else -"-acl", + "-acl", #endif #if defined(HAVE_ICONV) -"+iconv", + "+iconv", #else -"-iconv", + "-iconv", #endif #ifdef FEAT_TUI -"+tui", + "+tui", #else -"-tui", + "-tui", #endif -NULL + NULL }; // clang-format off @@ -2019,7 +2019,7 @@ void ex_version(exarg_T *eap) /// @param wrap static void version_msg_wrap(char_u *s, int wrap) { - int len = (int)vim_strsize(s) + (wrap ? 2 : 0); + int len = vim_strsize(s) + (wrap ? 2 : 0); if (!got_int && (len < Columns) @@ -2070,7 +2070,7 @@ void list_in_columns(char_u **items, int size, int current) // Find the length of the longest item, use that + 1 as the column width. int i; for (i = 0; size < 0 ? items[i] != NULL : i < size; i++) { - int l = (int)vim_strsize(items[i]) + (i == current ? 2 : 0); + int l = vim_strsize(items[i]) + (i == current ? 2 : 0); if (l > width) { width = l; diff --git a/src/nvim/window.c b/src/nvim/window.c index c0f537aab3..ff97eaa757 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -853,12 +853,12 @@ void ui_ext_win_position(win_T *wp) bool east = c.anchor & kFloatAnchorEast; bool south = c.anchor & kFloatAnchorSouth; - int comp_row = (int)row - (south ? wp->w_height : 0); - int comp_col = (int)col - (east ? wp->w_width : 0); + int comp_row = (int)row - (south ? wp->w_height_outer : 0); + int comp_col = (int)col - (east ? wp->w_width_outer : 0); comp_row += grid->comp_row; comp_col += grid->comp_col; - comp_row = MAX(MIN(comp_row, Rows-wp->w_height_outer-1), 0); - comp_col = MAX(MIN(comp_col, Columns-wp->w_width_outer), 0); + comp_row = MAX(MIN(comp_row, Rows - wp->w_height_outer - 1), 0); + comp_col = MAX(MIN(comp_col, Columns - wp->w_width_outer), 0); wp->w_winrow = comp_row; wp->w_wincol = comp_col; bool valid = (wp->w_redr_type == 0); diff --git a/src/uncrustify.cfg b/src/uncrustify.cfg index 5d73e70ed0..db0c50ff22 100644 --- a/src/uncrustify.cfg +++ b/src/uncrustify.cfg @@ -1,4 +1,4 @@ -# Uncrustify-0.73.0-186-03faf73c +# Uncrustify-0.73.0-195-1f883c691 # # General options @@ -535,14 +535,21 @@ sp_inside_braces_struct = ignore # ignore/add/remove/force/not_defined sp_inside_braces_oc_dict = ignore # ignore/add/remove/force/not_defined # Add or remove space after open brace in an unnamed temporary -# direct-list-initialization. +# direct-list-initialization +# if statement is a brace_init_lst +# works only if sp_brace_brace is set to ignore. sp_after_type_brace_init_lst_open = ignore # ignore/add/remove/force/not_defined # Add or remove space before close brace in an unnamed temporary -# direct-list-initialization. +# direct-list-initialization +# if statement is a brace_init_lst +# works only if sp_brace_brace is set to ignore. sp_before_type_brace_init_lst_close = ignore # ignore/add/remove/force/not_defined -# Add or remove space inside an unnamed temporary direct-list-initialization. +# Add or remove space inside an unnamed temporary direct-list-initialization +# if statement is a brace_init_lst +# works only if sp_brace_brace is set to ignore +# works only if sp_before_type_brace_init_lst_close is set to ignore. sp_inside_type_brace_init_lst = ignore # ignore/add/remove/force/not_defined # Add or remove space inside '{' and '}'. diff --git a/src/xdiff/xdiffi.c b/src/xdiff/xdiffi.c index f35ac5d0b0..cfcbb5d982 100644 --- a/src/xdiff/xdiffi.c +++ b/src/xdiff/xdiffi.c @@ -1,6 +1,3 @@ -// 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 - /* * LibXDiff by Davide Libenzi ( File Differential Library ) * Copyright (C) 2003 Davide Libenzi diff --git a/src/xdiff/xemit.c b/src/xdiff/xemit.c index 23c6e2d993..b578e7a9d5 100644 --- a/src/xdiff/xemit.c +++ b/src/xdiff/xemit.c @@ -1,6 +1,3 @@ -// 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 - /* * LibXDiff by Davide Libenzi ( File Differential Library ) * Copyright (C) 2003 Davide Libenzi diff --git a/src/xdiff/xhistogram.c b/src/xdiff/xhistogram.c index 3c84f35626..8598a8550d 100644 --- a/src/xdiff/xhistogram.c +++ b/src/xdiff/xhistogram.c @@ -1,6 +1,3 @@ -// 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 - /* * Copyright (C) 2010, Google Inc. * and other copyright owners as documented in JGit's IP log. diff --git a/src/xdiff/xpatience.c b/src/xdiff/xpatience.c index 5f547ca5c0..f78c897ad8 100644 --- a/src/xdiff/xpatience.c +++ b/src/xdiff/xpatience.c @@ -1,6 +1,3 @@ -// 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 - /* * LibXDiff by Davide Libenzi ( File Differential Library ) * Copyright (C) 2003-2016 Davide Libenzi, Johannes E. Schindelin diff --git a/src/xdiff/xprepare.c b/src/xdiff/xprepare.c index f13822e4fa..abeb8fb84e 100644 --- a/src/xdiff/xprepare.c +++ b/src/xdiff/xprepare.c @@ -1,6 +1,3 @@ -// 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 - /* * LibXDiff by Davide Libenzi ( File Differential Library ) * Copyright (C) 2003 Davide Libenzi diff --git a/src/xdiff/xutils.c b/src/xdiff/xutils.c index 65aa50497d..f13a854536 100644 --- a/src/xdiff/xutils.c +++ b/src/xdiff/xutils.c @@ -1,6 +1,3 @@ -// 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 - /* * LibXDiff by Davide Libenzi ( File Differential Library ) * Copyright (C) 2003 Davide Libenzi diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 3768edcbef..6bcf8dd91f 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -12,10 +12,12 @@ local funcs = helpers.funcs local iswin = helpers.iswin local meths = helpers.meths local matches = helpers.matches +local mkdir_p = helpers.mkdir_p local ok, nvim_async, feed = helpers.ok, helpers.nvim_async, helpers.feed local is_os = helpers.is_os local parse_context = helpers.parse_context local request = helpers.request +local rmdir = helpers.rmdir local source = helpers.source local next_msg = helpers.next_msg local tmpname = helpers.tmpname @@ -1574,6 +1576,18 @@ describe('API', function() end) describe('nvim_list_runtime_paths', function() + setup(function() + local pathsep = helpers.get_pathsep() + mkdir_p('Xtest'..pathsep..'a') + mkdir_p('Xtest'..pathsep..'b') + end) + teardown(function() + rmdir 'Xtest' + end) + before_each(function() + meths.set_current_dir 'Xtest' + end) + it('returns nothing with empty &runtimepath', function() meths.set_option('runtimepath', '') eq({}, meths.list_runtime_paths()) @@ -1601,8 +1615,7 @@ describe('API', function() local long_path = ('/a'):rep(8192) meths.set_option('runtimepath', long_path) local paths_list = meths.list_runtime_paths() - neq({long_path}, paths_list) - eq({long_path:sub(1, #(paths_list[1]))}, paths_list) + eq({}, paths_list) end) end) diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua index 1d83eb799f..bf2559f8d7 100644 --- a/test/functional/core/startup_spec.lua +++ b/test/functional/core/startup_spec.lua @@ -20,6 +20,7 @@ local retry = helpers.retry local rmdir = helpers.rmdir local sleep = helpers.sleep local iswin = helpers.iswin +local startswith = helpers.startswith local write_file = helpers.write_file local meths = helpers.meths @@ -355,11 +356,50 @@ describe('startup', function() eq({'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]]) end) + it("handles the correct order with start packages and after/ after startup", function() + pack_clear [[ lua _G.test_loadorder = {} ]] + command [[ runtime! filen.lua ]] + eq({'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]]) + end) + + it("handles the correct order with globpath(&rtp, ...)", function() + pack_clear [[ set loadplugins | lua _G.test_loadorder = {} ]] + command [[ + for x in globpath(&rtp, "filen.lua",1,1) + call v:lua.dofile(x) + endfor + ]] + eq({'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]]) + + local rtp = meths.get_option'rtp' + ok(startswith(rtp, 'test/functional/fixtures/nvim,test/functional/fixtures/pack/*/start/*,test/functional/fixtures/start/*,test/functional/fixtures,test/functional/fixtures/middle,'), 'rtp='..rtp) + end) + it("handles the correct order with opt packages and after/", function() pack_clear [[ lua _G.test_loadorder = {} vim.cmd "packadd! superspecial\nruntime! filen.lua" ]] eq({'ordinary', 'SuperSpecial', 'FANCY', 'mittel', 'FANCY after', 'SuperSpecial after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]]) end) + it("handles the correct order with opt packages and after/ after startup", function() + pack_clear [[ lua _G.test_loadorder = {} ]] + command [[ + packadd! superspecial + runtime! filen.lua + ]] + eq({'ordinary', 'SuperSpecial', 'FANCY', 'mittel', 'FANCY after', 'SuperSpecial after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]]) + end) + + it("handles the correct order with opt packages and globpath(&rtp, ...)", function() + pack_clear [[ set loadplugins | lua _G.test_loadorder = {} ]] + command [[ + packadd! superspecial + for x in globpath(&rtp, "filen.lua",1,1) + call v:lua.dofile(x) + endfor + ]] + eq({'ordinary', 'SuperSpecial', 'FANCY', 'mittel', 'SuperSpecial after', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]]) + end) + it("handles the correct order with a package that changes packpath", function() pack_clear [[ lua _G.test_loadorder = {} vim.cmd "packadd! funky\nruntime! filen.lua" ]] eq({'ordinary', 'funky!', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]]) diff --git a/test/functional/editor/meta_key_spec.lua b/test/functional/editor/meta_key_spec.lua index 2a9541ba96..c219204409 100644 --- a/test/functional/editor/meta_key_spec.lua +++ b/test/functional/editor/meta_key_spec.lua @@ -11,15 +11,20 @@ describe('meta-keys #8226 #13042', function() end) it('ALT/META, normal-mode', function() - -- Unmapped ALT-chords behave as ESC+c + -- Unmapped ALT-chord behaves as ESC+c. insert('hello') feed('0<A-x><M-x>') expect('llo') + -- Unmapped ALT-chord resolves isolated (non-ALT) ESC mapping. #13086 #15869 + command('nnoremap <ESC> A<lt>ESC><Esc>') + command('nnoremap ; A;<Esc>') + feed('<A-;><M-;>') + expect('llo<ESC>;<ESC>;') -- Mapped ALT-chord behaves as mapped. command('nnoremap <M-l> Ameta-l<Esc>') command('nnoremap <A-j> Aalt-j<Esc>') feed('<A-j><M-l>') - expect('lloalt-jmeta-l') + expect('llo<ESC>;<ESC>;alt-jmeta-l') end) it('ALT/META, visual-mode', function() @@ -27,11 +32,15 @@ describe('meta-keys #8226 #13042', function() insert('peaches') feed('viw<A-x>viw<M-x>') expect('peach') + -- Unmapped ALT-chord resolves isolated (non-ALT) ESC mapping. #13086 #15869 + command('vnoremap <ESC> A<lt>ESC>') + feed('viw<A-;><ESC>viw<M-;><ESC>') + expect('peach<ESC>;<ESC>;') -- Mapped ALT-chord behaves as mapped. command('vnoremap <M-l> Ameta-l<Esc>') command('vnoremap <A-j> Aalt-j<Esc>') feed('viw<A-j>viw<M-l>') - expect('peachalt-jmeta-l') + expect('peach<ESC>;<ESC>;alt-jmeta-l') end) it('ALT/META insert-mode', function() diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua index 9397af9d9f..45aa4915cd 100644 --- a/test/functional/lua/diagnostic_spec.lua +++ b/test/functional/lua/diagnostic_spec.lua @@ -874,6 +874,26 @@ describe('vim.diagnostic', function() return count_extmarks(diagnostic_bufnr, diagnostic_ns) ]]) end) + + it('sets signs', function() + local result = exec_lua [[ + vim.diagnostic.config({ + signs = true, + }) + + local diagnostics = { + make_error('Error', 1, 1, 1, 2), + make_warning('Warning', 3, 3, 3, 3), + } + + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + + return vim.fn.sign_getplaced(diagnostic_bufnr, {group = '*'})[1].signs + ]] + + eq({2, 'DiagnosticSignError'}, {result[1].lnum, result[1].name}) + eq({4, 'DiagnosticSignWarn'}, {result[2].lnum, result[2].name}) + end) end) describe('show_line_diagnostics()', function() @@ -995,37 +1015,6 @@ describe('vim.diagnostic', function() end) end) - describe('set_signs()', function() - -- TODO(tjdevries): Find out why signs are not displayed when set from Lua...?? - pending('sets signs by default', function() - exec_lua [[ - vim.diagnostic.config({ - update_in_insert = true, - signs = true, - }) - - local diagnostics = { - make_error('Delayed Diagnostic', 1, 1, 1, 2), - make_error('Delayed Diagnostic', 3, 3, 3, 3), - } - - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) - - vim.diagnostic._set_signs(diagnostic_ns, diagnostic_bufnr, diagnostics) - -- return vim.fn.sign_getplaced() - ]] - - nvim("input", "o") - nvim("input", "<esc>") - - -- TODO(tjdevries): Find a way to get the signs to display in the test... - eq(nil, exec_lua [[ - return im.fn.sign_getplaced()[1].signs - ]]) - end) - end) - describe('setloclist()', function() it('sets diagnostics in lnum order', function() local loc_list = exec_lua [[ diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 572573a3a6..8f9b194690 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -132,37 +132,38 @@ local function test_rpc_server(config) end describe('LSP', function() - describe('server_name specified', function() - before_each(function() - clear_notrace() - -- Run an instance of nvim on the file which contains our "scripts". - -- Pass TEST_NAME to pick the script. - local test_name = "basic_init" - exec_lua([=[ - lsp = require('vim.lsp') - local test_name, fixture_filename, logfile = ... - function test__start_client() - return lsp.start_client { - cmd_env = { - NVIM_LOG_FILE = logfile; - }; - cmd = { - vim.v.progpath, '-Es', '-u', 'NONE', '--headless', - "-c", string.format("lua TEST_NAME = %q", test_name), - "-c", "luafile "..fixture_filename; - }; - root_dir = vim.loop.cwd(); - } - end - TEST_CLIENT1 = test__start_client() - ]=], test_name, fake_lsp_code, fake_lsp_logfile) - end) + before_each(function() + clear_notrace() - after_each(function() - exec_lua("lsp._vim_exit_handler()") - -- exec_lua("lsp.stop_all_clients(true)") - end) + -- Run an instance of nvim on the file which contains our "scripts". + -- Pass TEST_NAME to pick the script. + local test_name = "basic_init" + exec_lua([=[ + lsp = require('vim.lsp') + local test_name, fixture_filename, logfile = ... + function test__start_client() + return lsp.start_client { + cmd_env = { + NVIM_LOG_FILE = logfile; + }; + cmd = { + vim.v.progpath, '-Es', '-u', 'NONE', '--headless', + "-c", string.format("lua TEST_NAME = %q", test_name), + "-c", "luafile "..fixture_filename; + }; + root_dir = vim.loop.cwd(); + } + end + TEST_CLIENT1 = test__start_client() + ]=], test_name, fake_lsp_code, fake_lsp_logfile) + end) + + after_each(function() + exec_lua("lsp._vim_exit_handler()") + -- exec_lua("lsp.stop_all_clients(true)") + end) + describe('server_name specified', function() it('start_client(), stop_client()', function() retry(nil, 4000, function() eq(1, exec_lua('return #lsp.get_active_clients()')) @@ -334,7 +335,6 @@ describe('LSP', function() } end) it('workspace/configuration returns NIL per section if client was started without config.settings', function() - clear_notrace() fake_lsp_server_setup('workspace/configuration no settings') eq({ NIL, NIL, }, exec_lua [[ local result = { @@ -2022,83 +2022,6 @@ describe('LSP', function() end) end) - describe('lsp.util.make_floating_popup_options', function() - before_each(function() - exec_lua [[ - local bufnr = vim.uri_to_bufnr("file:///fake/uri") - local winheight = vim.fn.winheight(0) - for i = 1, winheight do - vim.api.nvim_buf_set_lines(bufnr, 0, 0, false, {''}) - end - vim.api.nvim_win_set_buf(0, bufnr) - vim.api.nvim_win_set_cursor(0, {winheight, 0}) - ]] - end) - - local function popup_row(opts) - return exec_lua([[ - return vim.lsp.util.make_floating_popup_options(...).row - ]], 2, 2, opts) - end - - local err_pattern = "^Error executing lua: %.%.%./util%.lua:0: invalid floating preview border: .*%. :help vim%.api%.nvim_open_win%(%)$" - - it('calculates default border height correctly', function() - eq(0, popup_row()) - end) - - it('calculates string border height correctly', function() - eq(0, popup_row({border = 'none'})) - eq(-2, popup_row({border = 'single'})) - eq(-2, popup_row({border = 'double'})) - eq(-2, popup_row({border = 'rounded'})) - eq(-2, popup_row({border = 'solid'})) - eq(-1, popup_row({border = 'shadow'})) - end) - - it('error on invalid string border', function() - matches(err_pattern, pcall_err(popup_row, {border = ''})) - matches(err_pattern, pcall_err(popup_row, {border = 'invalid'})) - end) - - it('error on invalid array border length', function() - matches(err_pattern, pcall_err(popup_row, {border = {}})) - matches(err_pattern, pcall_err(popup_row, {border = {'', '', ''}})) - matches(err_pattern, pcall_err(popup_row, {border = {'', '', '', '', ''}})) - end) - - it('error on invalid array border member type', function() - matches(err_pattern, pcall_err(popup_row, {border = {0}})) - end) - - it('calculates 8-array border height correctly', function() - eq(0, popup_row({border = {'', '', '', '', '', '', '', ''}})) - eq(-2, popup_row({border = {'', '~', '', '~', '', '~', '', '~'}})) - eq(-1, popup_row({border = {'', '', '', '~', '', '~', '', ''}})) - eq(0, popup_row({border = {'', '', '', {'~', 'NormalFloat'}, '', '', '', {'~', 'NormalFloat'}}})) - eq(-2, popup_row({border = {'', {'~', 'NormalFloat'}, '', '', '', {'~', 'NormalFloat'}, '', ''}})) - end) - - it('calculates 4-array border height correctly', function() - eq(0, popup_row({border = {'', '', '', ''}})) - eq(-2, popup_row({border = {'', '~', '', '~'}})) - eq(0, popup_row({border = {'', '', '', {'~', 'NormalFloat'}}})) - eq(-2, popup_row({border = {'', {'~', 'NormalFloat'}, '', ''}})) - end) - - it('calculates 2-array border height correctly', function() - eq(0, popup_row({border = {'', ''}})) - eq(-2, popup_row({border = {'', '~'}})) - eq(-2, popup_row({border = {'', {'~', 'NormalFloat'}}})) - end) - - it('calculates 1-array border height correctly', function() - eq(0, popup_row({border = {''}})) - eq(-2, popup_row({border = {'~'}})) - eq(-2, popup_row({border = {{'~', 'NormalFloat'}}})) - end) - end) - describe('lsp.util._make_floating_popup_size', function() before_each(function() exec_lua [[ contents = diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 267cc54447..e57c63bb0f 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -109,6 +109,21 @@ describe('float window', function() assert_alive() end) + it('closed immediately by autocmd after win_enter #15548', function() + eq('Error executing lua: [string "<nvim>"]:0: Window was closed immediately', + pcall_err(exec_lua, [[ + vim.cmd "autocmd BufLeave * ++once quit!" + local buf = vim.api.nvim_create_buf(true, true) + vim.api.nvim_open_win(buf, true, { + relative = "win", + row = 0, col = 0, + width = 1, height = 1, + noautocmd = false, + }) + ]])) + assert_alive() + end) + it('opened with correct height', function() local height = exec_lua([[ vim.api.nvim_set_option("winheight", 20) @@ -1868,6 +1883,293 @@ describe('float window', function() end end) + it('always anchor to corner including border', function() + screen:try_resize(40,13) + meths.buf_set_lines(0, 0, -1, true, {'just some example text', 'some more example text'}) + feed('ggeee') + command('below split') + if multigrid then + screen:expect([[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + {4:[No Name] [+] }| + [3:----------------------------------------]| + ## grid 2 + just some example text | + some more example text | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 4 + just some exampl^e text | + some more example text | + {0:~ }| + {0:~ }| + {0:~ }| + ]]) + else + screen:expect([[ + just some example text | + some more example text | + {0:~ }| + {0:~ }| + {0:~ }| + {5:[No Name] [+] }| + just some exampl^e text | + some more example text | + {0:~ }| + {0:~ }| + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + end + + local buf = meths.create_buf(false, false) + meths.buf_set_lines(buf, 0, -1, true, {' halloj! ', + ' BORDAA '}) + local win = meths.open_win(buf, false, {relative='cursor', width=9, height=2, row=1, col=-2, border="double"}) + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + {4:[No Name] [+] }| + [3:----------------------------------------]| + ## grid 2 + just some example text | + some more example text | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 4 + just some exampl^e text | + some more example text | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 6 + {5:╔═════════╗}| + {5:║}{1: halloj! }{5:║}| + {5:║}{1: BORDAA }{5:║}| + {5:╚═════════╝}| + ]], float_pos={ + [6] = {{id = 1003}, "NW", 4, 1, 14, true} + }} + else + screen:expect([[ + just some example text | + some more example text | + {0:~ }| + {0:~ }| + {0:~ }| + {5:[No Name] [+] }| + just some exampl^e text | + some more exam{5:╔═════════╗} | + {0:~ }{5:║}{1: halloj! }{5:║}{0: }| + {0:~ }{5:║}{1: BORDAA }{5:║}{0: }| + {0:~ }{5:╚═════════╝}{0: }| + {4:[No Name] [+] }| + | + ]]) + end + + meths.win_set_config(win, {relative='cursor', row=0, col=-2, anchor='NE'}) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + {4:[No Name] [+] }| + [3:----------------------------------------]| + ## grid 2 + just some example text | + some more example text | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 4 + just some exampl^e text | + some more example text | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 6 + {5:╔═════════╗}| + {5:║}{1: halloj! }{5:║}| + {5:║}{1: BORDAA }{5:║}| + {5:╚═════════╝}| + ]], float_pos={ + [6] = {{id = 1003}, "NE", 4, 0, 14, true} + }} + else + screen:expect([[ + just some example text | + some more example text | + {0:~ }| + {0:~ }| + {0:~ }| + {5:[No Name] [+] }| + jus{5:╔═════════╗}pl^e text | + som{5:║}{1: halloj! }{5:║}ple text | + {0:~ }{5:║}{1: BORDAA }{5:║}{0: }| + {0:~ }{5:╚═════════╝}{0: }| + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + end + + meths.win_set_config(win, {relative='cursor', row=1, col=-2, anchor='SE'}) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + {4:[No Name] [+] }| + [3:----------------------------------------]| + ## grid 2 + just some example text | + some more example text | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 4 + just some exampl^e text | + some more example text | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 6 + {5:╔═════════╗}| + {5:║}{1: halloj! }{5:║}| + {5:║}{1: BORDAA }{5:║}| + {5:╚═════════╝}| + ]], float_pos={ + [6] = {{id = 1003}, "SE", 4, 1, 14, true} + }} + else + screen:expect([[ + just some example text | + some more example text | + {0:~ }| + {0:~ }{5:╔═════════╗}{0: }| + {0:~ }{5:║}{1: halloj! }{5:║}{0: }| + {5:[No║}{1: BORDAA }{5:║ }| + jus{5:╚═════════╝}pl^e text | + some more example text | + {0:~ }| + {0:~ }| + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + end + + meths.win_set_config(win, {relative='cursor', row=0, col=-2, anchor='SW'}) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + {4:[No Name] [+] }| + [3:----------------------------------------]| + ## grid 2 + just some example text | + some more example text | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 4 + just some exampl^e text | + some more example text | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 6 + {5:╔═════════╗}| + {5:║}{1: halloj! }{5:║}| + {5:║}{1: BORDAA }{5:║}| + {5:╚═════════╝}| + ]], float_pos={ + [6] = {{id = 1003}, "SW", 4, 0, 14, true} + }} + else + screen:expect([[ + just some example text | + some more example text | + {0:~ }{5:╔═════════╗}{0: }| + {0:~ }{5:║}{1: halloj! }{5:║}{0: }| + {0:~ }{5:║}{1: BORDAA }{5:║}{0: }| + {5:[No Name] [+] ╚═════════╝ }| + just some exampl^e text | + some more example text | + {0:~ }| + {0:~ }| + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + end + end) + it('can be placed relative text in a window', function() screen:try_resize(30,5) local firstwin = meths.get_current_win().id |