aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2022-08-30 23:23:09 -0600
committerJosh Rahm <joshuarahm@gmail.com>2022-08-30 23:23:09 -0600
commit968aa6e3ed0497ea99f123c74c5fd0f3880ccc63 (patch)
tree32ac91852b82d040012d40a3f54f772723509968
parent242f75745009b3a0a2108d98ce6c02b6e13aac3f (diff)
parentf4274d0f62625683486d3912dcd6e8e45877c6a4 (diff)
downloadrneovim-968aa6e3ed0497ea99f123c74c5fd0f3880ccc63.tar.gz
rneovim-968aa6e3ed0497ea99f123c74c5fd0f3880ccc63.tar.bz2
rneovim-968aa6e3ed0497ea99f123c74c5fd0f3880ccc63.zip
Merge remote-tracking branch 'upstream/master' into userreg
-rw-r--r--CONTRIBUTING.md100
-rw-r--r--runtime/autoload/python.vim40
-rw-r--r--runtime/colors/blue.vim4
-rw-r--r--runtime/colors/darkblue.vim4
-rw-r--r--runtime/colors/delek.vim4
-rw-r--r--runtime/colors/desert.vim4
-rw-r--r--runtime/colors/elflord.vim4
-rw-r--r--runtime/colors/evening.vim4
-rw-r--r--runtime/colors/habamax.vim4
-rw-r--r--runtime/colors/industry.vim4
-rw-r--r--runtime/colors/koehler.vim4
-rw-r--r--runtime/colors/lunaperche.vim4
-rw-r--r--runtime/colors/morning.vim4
-rw-r--r--runtime/colors/murphy.vim4
-rw-r--r--runtime/colors/pablo.vim4
-rw-r--r--runtime/colors/peachpuff.vim4
-rw-r--r--runtime/colors/quiet.vim4
-rw-r--r--runtime/colors/ron.vim4
-rw-r--r--runtime/colors/shine.vim4
-rw-r--r--runtime/colors/slate.vim4
-rw-r--r--runtime/colors/torte.vim4
-rw-r--r--runtime/colors/zellner.vim4
-rw-r--r--runtime/doc/api.txt4
-rw-r--r--runtime/doc/builtin.txt80
-rw-r--r--runtime/doc/cmdline.txt8
-rw-r--r--runtime/doc/indent.txt27
-rw-r--r--runtime/doc/lsp.txt47
-rw-r--r--runtime/doc/lua.txt234
-rw-r--r--runtime/doc/options.txt83
-rw-r--r--runtime/doc/syntax.txt10
-rw-r--r--runtime/doc/treesitter.txt127
-rw-r--r--runtime/doc/usr_41.txt1
-rw-r--r--runtime/doc/vim_diff.txt3
-rw-r--r--runtime/doc/windows.txt2
-rw-r--r--runtime/filetype.vim10
-rw-r--r--runtime/indent/testdir/python.in18
-rw-r--r--runtime/indent/testdir/python.ok18
-rw-r--r--runtime/lua/vim/diagnostic.lua30
-rw-r--r--runtime/lua/vim/filetype.lua9
-rw-r--r--runtime/lua/vim/inspect.lua32
-rw-r--r--runtime/lua/vim/lsp.lua49
-rw-r--r--runtime/lua/vim/lsp/rpc.lua778
-rw-r--r--runtime/lua/vim/treesitter.lua123
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua109
-rw-r--r--runtime/lua/vim/treesitter/language.lua14
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua44
-rw-r--r--runtime/lua/vim/treesitter/query.lua13
-rw-r--r--runtime/plugin/matchparen.vim5
-rw-r--r--runtime/syntax/plsql.vim87
-rw-r--r--runtime/syntax/synload.vim2
-rw-r--r--runtime/syntax/syntax.vim3
-rwxr-xr-xscripts/check-includes.py64
-rwxr-xr-xscripts/gen_vimdoc.py2
-rw-r--r--src/nvim/api/autocmd.c4
-rw-r--r--src/nvim/api/buffer.c4
-rw-r--r--src/nvim/api/extmark.c4
-rw-r--r--src/nvim/api/private/dispatch.h9
-rw-r--r--src/nvim/api/private/helpers.c41
-rw-r--r--src/nvim/api/private/helpers.h1
-rw-r--r--src/nvim/api/ui.c6
-rw-r--r--src/nvim/api/vim.c78
-rw-r--r--src/nvim/api/vimscript.c4
-rw-r--r--src/nvim/api/win_config.c2
-rw-r--r--src/nvim/api/window.c4
-rw-r--r--src/nvim/arabic.c26
-rw-r--r--src/nvim/arglist.c32
-rw-r--r--src/nvim/autocmd.c52
-rw-r--r--src/nvim/autocmd.h3
-rw-r--r--src/nvim/buffer.c81
-rw-r--r--src/nvim/buffer_defs.h225
-rw-r--r--src/nvim/change.c231
-rw-r--r--src/nvim/charset.c97
-rw-r--r--src/nvim/cmdexpand.c1083
-rw-r--r--src/nvim/cmdhist.c20
-rw-r--r--src/nvim/context.c4
-rw-r--r--src/nvim/cursor.c18
-rw-r--r--src/nvim/cursor_shape.c2
-rw-r--r--src/nvim/debugger.c26
-rw-r--r--src/nvim/decoration.c4
-rw-r--r--src/nvim/diff.c108
-rw-r--r--src/nvim/digraph.c16
-rw-r--r--src/nvim/drawline.c48
-rw-r--r--src/nvim/drawscreen.c217
-rw-r--r--src/nvim/drawscreen.h14
-rw-r--r--src/nvim/edit.c852
-rw-r--r--src/nvim/eval.c77
-rw-r--r--src/nvim/eval.lua35
-rw-r--r--src/nvim/eval/executor.c3
-rw-r--r--src/nvim/eval/funcs.c830
-rw-r--r--src/nvim/eval/funcs.h17
-rw-r--r--src/nvim/eval/typval.c26
-rw-r--r--src/nvim/eval/typval.h3
-rw-r--r--src/nvim/eval/userfunc.c84
-rw-r--r--src/nvim/eval/vars.c34
-rw-r--r--src/nvim/ex_cmds.c153
-rw-r--r--src/nvim/ex_cmds2.c350
-rw-r--r--src/nvim/ex_cmds2.h2
-rw-r--r--src/nvim/ex_cmds_defs.h10
-rw-r--r--src/nvim/ex_docmd.c274
-rw-r--r--src/nvim/ex_eval.c287
-rw-r--r--src/nvim/ex_getln.c354
-rw-r--r--src/nvim/ex_session.c4
-rw-r--r--src/nvim/extmark.c4
-rw-r--r--src/nvim/file_search.c103
-rw-r--r--src/nvim/fileio.c285
-rw-r--r--src/nvim/fileio.h1
-rw-r--r--src/nvim/fold.c42
-rw-r--r--src/nvim/garray.c2
-rw-r--r--src/nvim/garray.h2
-rw-r--r--src/nvim/generators/c_grammar.lua1
-rw-r--r--src/nvim/generators/gen_api_dispatch.lua40
-rwxr-xr-xsrc/nvim/generators/gen_api_ui_events.lua6
-rw-r--r--src/nvim/generators/gen_eval.lua15
-rw-r--r--src/nvim/getchar.c136
-rw-r--r--src/nvim/globals.h54
-rw-r--r--src/nvim/grid.c31
-rw-r--r--src/nvim/hardcopy.c154
-rw-r--r--src/nvim/hashtab.c4
-rw-r--r--src/nvim/help.c18
-rw-r--r--src/nvim/highlight.c8
-rw-r--r--src/nvim/highlight_group.c132
-rw-r--r--src/nvim/if_cscope.c38
-rw-r--r--src/nvim/indent.c125
-rw-r--r--src/nvim/indent_c.c118
-rw-r--r--src/nvim/input.c2
-rw-r--r--src/nvim/insexpand.c2855
-rw-r--r--src/nvim/keycodes.c144
-rw-r--r--src/nvim/locale.c369
-rw-r--r--src/nvim/locale.h10
-rw-r--r--src/nvim/log.c6
-rw-r--r--src/nvim/lua/executor.c11
-rw-r--r--src/nvim/lua/stdlib.c53
-rw-r--r--src/nvim/lua/treesitter.c87
-rw-r--r--src/nvim/macros.h2
-rw-r--r--src/nvim/main.c98
-rw-r--r--src/nvim/mapping.c40
-rw-r--r--src/nvim/mark.c36
-rw-r--r--src/nvim/match.c30
-rw-r--r--src/nvim/mbyte.c113
-rw-r--r--src/nvim/memfile.c10
-rw-r--r--src/nvim/memline.c166
-rw-r--r--src/nvim/memory.c76
-rw-r--r--src/nvim/memory.h6
-rw-r--r--src/nvim/menu.c28
-rw-r--r--src/nvim/message.c184
-rw-r--r--src/nvim/mouse.c42
-rw-r--r--src/nvim/mouse.h2
-rw-r--r--src/nvim/move.c70
-rw-r--r--src/nvim/msgpack_rpc/channel.c22
-rw-r--r--src/nvim/msgpack_rpc/channel_defs.h2
-rw-r--r--src/nvim/msgpack_rpc/server.c2
-rw-r--r--src/nvim/msgpack_rpc/unpacker.c12
-rw-r--r--src/nvim/msgpack_rpc/unpacker.h2
-rw-r--r--src/nvim/normal.c111
-rw-r--r--src/nvim/normal.h4
-rw-r--r--src/nvim/ops.c807
-rw-r--r--src/nvim/option.c643
-rw-r--r--src/nvim/option_defs.h338
-rw-r--r--src/nvim/optionstr.c237
-rw-r--r--src/nvim/os/env.c23
-rw-r--r--src/nvim/os/fs.c10
-rw-r--r--src/nvim/os/shell.c8
-rw-r--r--src/nvim/path.c171
-rw-r--r--src/nvim/plines.c186
-rw-r--r--src/nvim/plines.h14
-rw-r--r--src/nvim/po/af.po4
-rw-r--r--src/nvim/po/ca.po6
-rw-r--r--src/nvim/po/cs.cp1250.po6
-rw-r--r--src/nvim/po/cs.po6
-rw-r--r--src/nvim/po/da.po4
-rw-r--r--src/nvim/po/de.po4
-rw-r--r--src/nvim/po/en_GB.po4
-rw-r--r--src/nvim/po/eo.po4
-rw-r--r--src/nvim/po/es.po6
-rw-r--r--src/nvim/po/fi.po4
-rw-r--r--src/nvim/po/fr.po4
-rw-r--r--src/nvim/po/ga.po4
-rw-r--r--src/nvim/po/it.po6
-rw-r--r--src/nvim/po/ko.UTF-8.po6
-rw-r--r--src/nvim/po/nb.po6
-rw-r--r--src/nvim/po/nl.po4
-rw-r--r--src/nvim/po/no.po6
-rw-r--r--src/nvim/po/pl.UTF-8.po6
-rw-r--r--src/nvim/po/pt_BR.po4
-rw-r--r--src/nvim/po/ru.po6
-rw-r--r--src/nvim/po/sk.cp1250.po6
-rw-r--r--src/nvim/po/sk.po6
-rw-r--r--src/nvim/po/sr.po4
-rw-r--r--src/nvim/po/sv.po4
-rw-r--r--src/nvim/po/tr.po4
-rw-r--r--src/nvim/po/uk.po4
-rw-r--r--src/nvim/po/vi.po6
-rw-r--r--src/nvim/po/zh_CN.UTF-8.po58
-rw-r--r--src/nvim/po/zh_TW.UTF-8.po366
-rw-r--r--src/nvim/popupmenu.c28
-rw-r--r--src/nvim/profile.c8
-rw-r--r--src/nvim/quickfix.c131
-rw-r--r--src/nvim/regexp.c12
-rw-r--r--src/nvim/regexp_bt.c3
-rw-r--r--src/nvim/regexp_nfa.c2
-rw-r--r--src/nvim/runtime.c349
-rw-r--r--src/nvim/runtime.h3
-rw-r--r--src/nvim/screen.c109
-rw-r--r--src/nvim/search.c2023
-rw-r--r--src/nvim/shada.c6
-rw-r--r--src/nvim/sign.c46
-rw-r--r--src/nvim/spell.c496
-rw-r--r--src/nvim/spell_defs.h6
-rw-r--r--src/nvim/spellfile.c275
-rw-r--r--src/nvim/spellsuggest.c20
-rw-r--r--src/nvim/statusline.c25
-rw-r--r--src/nvim/strings.c30
-rw-r--r--src/nvim/syntax.c417
-rw-r--r--src/nvim/tag.c199
-rw-r--r--src/nvim/terminal.c6
-rw-r--r--src/nvim/testdir/runtest.vim8
-rw-r--r--src/nvim/testdir/setup.vim2
-rw-r--r--src/nvim/testdir/test_autocmd.vim111
-rw-r--r--src/nvim/testdir/test_blob.vim2
-rw-r--r--src/nvim/testdir/test_buffer.vim206
-rw-r--r--src/nvim/testdir/test_bufline.vim22
-rw-r--r--src/nvim/testdir/test_cd.vim2
-rw-r--r--src/nvim/testdir/test_clientserver.vim6
-rw-r--r--src/nvim/testdir/test_cmdline.vim97
-rw-r--r--src/nvim/testdir/test_comments.vim277
-rw-r--r--src/nvim/testdir/test_cursor_func.vim2
-rw-r--r--src/nvim/testdir/test_diffmode.vim6
-rw-r--r--src/nvim/testdir/test_digraph.vim13
-rw-r--r--src/nvim/testdir/test_display.vim82
-rw-r--r--src/nvim/testdir/test_edit.vim61
-rw-r--r--src/nvim/testdir/test_excmd.vim8
-rw-r--r--src/nvim/testdir/test_expand.vim71
-rw-r--r--src/nvim/testdir/test_expand_func.vim7
-rw-r--r--src/nvim/testdir/test_expr.vim1
-rw-r--r--src/nvim/testdir/test_filechanged.vim6
-rw-r--r--src/nvim/testdir/test_filetype.vim4
-rw-r--r--src/nvim/testdir/test_functions.vim85
-rw-r--r--src/nvim/testdir/test_highlight.vim5
-rw-r--r--src/nvim/testdir/test_history.vim17
-rw-r--r--src/nvim/testdir/test_ins_complete.vim451
-rw-r--r--src/nvim/testdir/test_lambda.vim18
-rw-r--r--src/nvim/testdir/test_listdict.vim27
-rw-r--r--src/nvim/testdir/test_maparg.vim2
-rw-r--r--src/nvim/testdir/test_normal.vim1
-rw-r--r--src/nvim/testdir/test_options.vim58
-rw-r--r--src/nvim/testdir/test_preview.vim7
-rw-r--r--src/nvim/testdir/test_quickfix.vim6
-rw-r--r--src/nvim/testdir/test_startup.vim4
-rw-r--r--src/nvim/testdir/test_swap.vim25
-rw-r--r--src/nvim/testdir/test_syntax.vim18
-rw-r--r--src/nvim/testdir/test_textformat.vim272
-rw-r--r--src/nvim/testdir/test_trycatch.vim175
-rw-r--r--src/nvim/testdir/test_user_func.vim7
-rw-r--r--src/nvim/testdir/test_viminfo.vim21
-rw-r--r--src/nvim/testdir/test_vimscript.vim23
-rw-r--r--src/nvim/testing.c34
-rw-r--r--src/nvim/textformat.c1127
-rw-r--r--src/nvim/textformat.h10
-rw-r--r--src/nvim/textobject.c1742
-rw-r--r--src/nvim/textobject.h11
-rw-r--r--src/nvim/tui/input.c19
-rw-r--r--src/nvim/types.h11
-rw-r--r--src/nvim/ui.c7
-rw-r--r--src/nvim/ui.h2
-rw-r--r--src/nvim/ui_bridge.c4
-rw-r--r--src/nvim/ui_client.c2
-rw-r--r--src/nvim/undo.c16
-rw-r--r--src/nvim/usercmd.c40
-rw-r--r--src/nvim/usercmd.h6
-rw-r--r--src/nvim/version.c31
-rw-r--r--src/nvim/vim.h14
-rw-r--r--src/nvim/viml/parser/parser.h4
-rw-r--r--src/nvim/window.c158
-rw-r--r--test/functional/api/command_spec.lua6
-rw-r--r--test/functional/api/vim_spec.lua49
-rw-r--r--test/functional/autocmd/winscrolled_spec.lua14
-rw-r--r--test/functional/editor/K_spec.lua11
-rw-r--r--test/functional/editor/mode_insert_spec.lua8
-rw-r--r--test/functional/ex_cmds/normal_spec.lua17
-rw-r--r--test/functional/ex_cmds/source_spec.lua4
-rw-r--r--test/functional/ex_cmds/swapfile_preserve_recover_spec.lua124
-rw-r--r--test/functional/helpers.lua1
-rw-r--r--test/functional/legacy/buffer_spec.lua59
-rw-r--r--test/functional/legacy/cmdline_spec.lua84
-rw-r--r--test/functional/lua/diagnostic_spec.lua22
-rw-r--r--test/functional/lua/vim_spec.lua33
-rw-r--r--test/functional/plugin/lsp_spec.lua28
-rw-r--r--test/functional/plugin/man_spec.lua6
-rw-r--r--test/functional/terminal/tui_spec.lua193
-rw-r--r--test/functional/treesitter/highlight_spec.lua101
-rw-r--r--test/functional/treesitter/language_spec.lua38
-rw-r--r--test/functional/treesitter/node_spec.lua49
-rw-r--r--test/functional/treesitter/utils_spec.lua33
-rw-r--r--test/functional/ui/highlight_spec.lua45
-rw-r--r--test/functional/ui/messages_spec.lua6
-rw-r--r--test/functional/ui/multigrid_spec.lua11
-rw-r--r--test/functional/ui/popupmenu_spec.lua16
-rw-r--r--test/functional/ui/wildmode_spec.lua58
-rw-r--r--test/functional/ui/winbar_spec.lua7
-rw-r--r--test/functional/vimscript/eval_spec.lua103
-rw-r--r--test/functional/vimscript/input_spec.lua77
-rw-r--r--test/unit/path_spec.lua4
302 files changed, 15925 insertions, 11954 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 17622fa33a..582d5fbdd4 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -219,10 +219,10 @@ You can lint a single file (but this will _not_ exclude legacy errors):
### Style
- You can format files by using:
-```
- make format
-```
-This will format changed Lua and C files with all appropriate flags set.
+ ```
+ make format
+ ```
+ This will format changed Lua and C files with all appropriate flags set.
- Style rules are (mostly) defined by `src/uncrustify.cfg` which tries to match
the [style-guide]. To use the Nvim `gq` command with `uncrustify`:
```
@@ -245,15 +245,61 @@ This will format changed Lua and C files with all appropriate flags set.
```
git config blame.ignoreRevsFile .git-blame-ignore-revs
```
-- Use **[universal-ctags](https://github.com/universal-ctags/ctags).**
- ("Exuberant ctags", the typical `ctags` binary provided by your distro, is
- unmaintained and won't recognize many function signatures in Neovim source.)
+
+- Recommendation is to use **[clangd]**.
+ Can use the maintained config in [nvim-lspconfig/clangd].
- Explore the source code [on the web](https://sourcegraph.com/github.com/neovim/neovim).
-- If using [lua-language-server][], symlink `contrib/luarc.json` into the
+- If using [lua-language-server], symlink `contrib/luarc.json` into the
project root:
$ ln -s contrib/luarc.json .luarc.json
+### Includes
+
+For managing includes in C files, use [include-what-you-use].
+
+- [Install include-what-you-use][include-what-you-use-install]
+- Run with:
+ ```
+ make CMAKE_EXTRA_FLAGS=-DCMAKE_C_INCLUDE_WHAT_YOU_USE=include-what-you-use | tee iwyu.txt
+ ```
+
+See [#549][549] for more details.
+
+Documenting
+-----------
+
+Many parts of the `:help` documentation are autogenerated from C or Lua docstrings using the `./scripts/gen_vimdoc.py` script.
+You can filter the regeneration based on the target (api, lua, or lsp), or the file you changed, that need a doc refresh using `./scripts/gen_vimdoc.py -t <target>`.
+
+## Lua docstrings
+
+Lua documentation uses a subset of [EmmyLua] annotations. A rough outline of a function documentation is
+
+```lua
+--- {Brief}
+---
+--- {Long explanation}
+---
+---@param arg1 type {description}
+---@param arg2 type {description}
+{...}
+---
+---@return type {description}
+```
+
+If possible, always add type information (`table`, `string`, `number`, ...). Multiple valid types are separated by a bar (`string|table`). Indicate optional parameters via `type|nil`.
+
+If a function in your Lua module should not be documented (e.g. internal function or local function), you should set the doc comment to:
+
+```
+---@private
+```
+
+Mark functions that are deprecated as
+```
+---@deprecated
+```
Reviewing
---------
@@ -271,30 +317,36 @@ commits in the feature branch which aren't in the `master` branch; `-p`
shows each commit's diff. To show the whole surrounding function of a change
as context, use the `-W` argument as well.
+[549]: https://github.com/neovim/neovim/issues/549
+[1820]: https://github.com/neovim/neovim/pull/1820
+[3174]: https://github.com/neovim/neovim/issues/3174
+[ASan]: http://clang.llvm.org/docs/AddressSanitizer.html
+[Clang report]: https://neovim.io/doc/reports/clang/
+[GitHub Actions]: https://github.com/neovim/neovim/actions
+[clangd]: https://clangd.llvm.org
+[Merge a Vim patch]: https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-Vim
+[complexity:low]: https://github.com/neovim/neovim/issues?q=is%3Aopen+is%3Aissue+label%3Acomplexity%3Alow
+[conventional_commits]: https://www.conventionalcommits.org
+[EmmyLua]: https://github.com/sumneko/lua-language-server/wiki/Annotations
[gcc-warnings]: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
+[gh]: https://cli.github.com/
[git-bisect]: http://git-scm.com/book/en/v2/Git-Tools-Debugging-with-Git
[git-feature-branch]: https://www.atlassian.com/git/tutorials/comparing-workflows
[git-history-filtering]: https://www.atlassian.com/git/tutorials/git-log/filtering-the-commit-history
[git-history-rewriting]: http://git-scm.com/book/en/v2/Git-Tools-Rewriting-History
[git-rebasing]: http://git-scm.com/book/en/v2/Git-Branching-Rebasing
[github-issues]: https://github.com/neovim/neovim/issues
-[1820]: https://github.com/neovim/neovim/pull/1820
-[gh]: https://cli.github.com/
-[conventional_commits]: https://www.conventionalcommits.org
-[style-guide]: https://neovim.io/doc/user/dev_style.html#dev-style
-[ASan]: http://clang.llvm.org/docs/AddressSanitizer.html
-[run-tests]: https://github.com/neovim/neovim/blob/master/test/README.md#running-tests
-[wiki-faq]: https://github.com/neovim/neovim/wiki/FAQ
-[review-checklist]: https://github.com/neovim/neovim/wiki/Code-review-checklist
-[3174]: https://github.com/neovim/neovim/issues/3174
-[sourcehut]: https://builds.sr.ht/~jmk
-[GitHub Actions]: https://github.com/neovim/neovim/actions
-[Merge a Vim patch]: https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-Vim
-[Clang report]: https://neovim.io/doc/reports/clang/
-[complexity:low]: https://github.com/neovim/neovim/issues?q=is%3Aopen+is%3Aissue+label%3Acomplexity%3Alow
+[include-what-you-use-install]: https://github.com/include-what-you-use/include-what-you-use#how-to-install
+[include-what-you-use]: https://github.com/include-what-you-use/include-what-you-use#using-with-cmake
+[lua-language-server]: https://github.com/sumneko/lua-language-server/
[master error list]: https://raw.githubusercontent.com/neovim/doc/gh-pages/reports/clint/errors.json
-[wiki-contribute-help]: https://github.com/neovim/neovim/wiki/contribute-%3Ahelp
+[nvim-lspconfig/clangd]: https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#clangd
[pr-draft]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request
[pr-ready]: https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request
+[review-checklist]: https://github.com/neovim/neovim/wiki/Code-review-checklist
+[run-tests]: https://github.com/neovim/neovim/blob/master/test/README.md#running-tests
+[sourcehut]: https://builds.sr.ht/~jmk
+[style-guide]: https://neovim.io/doc/user/dev_style.html#dev-style
[uncrustify]: http://uncrustify.sourceforge.net/
-[lua-language-server]: https://github.com/sumneko/lua-language-server/
+[wiki-contribute-help]: https://github.com/neovim/neovim/wiki/contribute-%3Ahelp
+[wiki-faq]: https://github.com/neovim/neovim/wiki/FAQ
diff --git a/runtime/autoload/python.vim b/runtime/autoload/python.vim
index e45dbd9db8..1eaad09ef5 100644
--- a/runtime/autoload/python.vim
+++ b/runtime/autoload/python.vim
@@ -3,13 +3,19 @@
let s:keepcpo= &cpo
set cpo&vim
-" searchpair() can be slow, limit the time to 150 msec or what is put in
-" g:pyindent_searchpair_timeout
-let s:searchpair_timeout = get(g:, 'pyindent_searchpair_timeout', 150)
-
-" Identing inside parentheses can be very slow, regardless of the searchpair()
-" timeout, so let the user disable this feature if he doesn't need it
-let s:disable_parentheses_indenting = get(g:, 'pyindent_disable_parentheses_indenting', v:false)
+" need to inspect some old g:pyindent_* variables to be backward compatible
+let g:python_indent = extend(get(g:, 'python_indent', {}), #{
+ \ closed_paren_align_last_line: v:true,
+ \ open_paren: get(g:, 'pyindent_open_paren', 'shiftwidth() * 2'),
+ \ nested_paren: get(g:, 'pyindent_nested_paren', 'shiftwidth()'),
+ \ continue: get(g:, 'pyindent_continue', 'shiftwidth() * 2'),
+ "\ searchpair() can be slow, limit the time to 150 msec or what is put in
+ "\ g:python_indent.searchpair_timeout
+ \ searchpair_timeout: get(g:, 'pyindent_searchpair_timeout', 150),
+ "\ Identing inside parentheses can be very slow, regardless of the searchpair()
+ "\ timeout, so let the user disable this feature if he doesn't need it
+ \ disable_parentheses_indenting: get(g:, 'pyindent_disable_parentheses_indenting', v:false),
+ \ }, 'keep')
let s:maxoff = 50 " maximum number of lines to look backwards for ()
@@ -18,7 +24,7 @@ function s:SearchBracket(fromlnum, flags)
\ {-> synstack('.', col('.'))
\ ->map({_, id -> id->synIDattr('name')})
\ ->match('\%(Comment\|Todo\|String\)$') >= 0},
- \ [0, a:fromlnum - s:maxoff]->max(), s:searchpair_timeout)
+ \ [0, a:fromlnum - s:maxoff]->max(), g:python_indent.searchpair_timeout)
endfunction
" See if the specified line is already user-dedented from the expected value.
@@ -38,7 +44,7 @@ function python#GetIndent(lnum, ...)
if a:lnum > 1 && getline(a:lnum - 2) =~ '\\$'
return indent(a:lnum - 1)
endif
- return indent(a:lnum - 1) + (exists("g:pyindent_continue") ? eval(g:pyindent_continue) : (shiftwidth() * 2))
+ return indent(a:lnum - 1) + get(g:, 'pyindent_continue', g:python_indent.continue)->eval()
endif
" If the start of the line is in a string don't change the indent.
@@ -55,7 +61,7 @@ function python#GetIndent(lnum, ...)
return 0
endif
- if s:disable_parentheses_indenting == 1
+ if g:python_indent.disable_parentheses_indenting == 1
let plindent = indent(plnum)
let plnumstart = plnum
else
@@ -70,8 +76,12 @@ function python#GetIndent(lnum, ...)
" 100, 200, 300, 400)
call cursor(a:lnum, 1)
let [parlnum, parcol] = s:SearchBracket(a:lnum, 'nbW')
- if parlnum > 0 && parcol != col([parlnum, '$']) - 1
- return parcol
+ if parlnum > 0
+ if parcol != col([parlnum, '$']) - 1
+ return parcol
+ elseif getline(a:lnum) =~ '^\s*[])}]' && !g:python_indent.closed_paren_align_last_line
+ return indent(parlnum)
+ endif
endif
call cursor(plnum, 1)
@@ -123,9 +133,11 @@ function python#GetIndent(lnum, ...)
" When the start is inside parenthesis, only indent one 'shiftwidth'.
let [pp, _] = s:SearchBracket(a:lnum, 'bW')
if pp > 0
- return indent(plnum) + (exists("g:pyindent_nested_paren") ? eval(g:pyindent_nested_paren) : shiftwidth())
+ return indent(plnum)
+ \ + get(g:, 'pyindent_nested_paren', g:python_indent.nested_paren)->eval()
endif
- return indent(plnum) + (exists("g:pyindent_open_paren") ? eval(g:pyindent_open_paren) : (shiftwidth() * 2))
+ return indent(plnum)
+ \ + get(g:, 'pyindent_open_paren', g:python_indent.open_paren)->eval()
endif
if plnumstart == p
return indent(plnum)
diff --git a/runtime/colors/blue.vim b/runtime/colors/blue.vim
index 0d2f07c654..2fbce09b67 100644
--- a/runtime/colors/blue.vim
+++ b/runtime/colors/blue.vim
@@ -4,7 +4,7 @@
" Maintainer: Original maintainer Steven Vertigan <steven@vertigan.wattle.id.au>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Fri Aug 5 12:25:12 2022
+" Last Updated: Tue 23 Aug 2022 16:50:34 MSK
" Generated by Colortemplate v2.2.0
@@ -13,7 +13,7 @@ set background=dark
hi clear
let g:colors_name = 'blue'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
if (has('termguicolors') && &termguicolors) || has('gui_running')
let g:terminal_ansi_colors = ['#000000', '#cd0000', '#00cd00', '#cdcd00', '#0000ee', '#cd00cd', '#00cdcd', '#e5e5e5', '#7f7f7f', '#ff0000', '#00ff00', '#ffff00', '#5c5cff', '#ff00ff', '#00ffff', '#ffffff']
diff --git a/runtime/colors/darkblue.vim b/runtime/colors/darkblue.vim
index b4c286af37..9e96a4638c 100644
--- a/runtime/colors/darkblue.vim
+++ b/runtime/colors/darkblue.vim
@@ -4,7 +4,7 @@
" Maintainer: Original author Bohdan Vlasyuk <bohdan@vstu.edu.ua>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Mon Aug 8 15:21:06 2022
+" Last Updated: Tue 23 Aug 2022 16:50:35 MSK
" Generated by Colortemplate v2.2.0
@@ -13,7 +13,7 @@ set background=dark
hi clear
let g:colors_name = 'darkblue'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
if (has('termguicolors') && &termguicolors) || has('gui_running')
let g:terminal_ansi_colors = ['#000000', '#8b0000', '#90f020', '#ffa500', '#00008b', '#8b008b', '#008b8b', '#c0c0c0', '#808080', '#ffa0a0', '#90f020', '#ffff60', '#0030ff', '#ff00ff', '#90fff0', '#ffffff']
diff --git a/runtime/colors/delek.vim b/runtime/colors/delek.vim
index bd9c5cf52d..e21adf2795 100644
--- a/runtime/colors/delek.vim
+++ b/runtime/colors/delek.vim
@@ -4,7 +4,7 @@
" Maintainer: Original maintainer David Schweikert <david@schweikert.ch>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Mon Aug 8 15:21:07 2022
+" Last Updated: Tue 23 Aug 2022 16:50:36 MSK
" Generated by Colortemplate v2.2.0
@@ -13,7 +13,7 @@ set background=light
hi clear
let g:colors_name = 'delek'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
if (has('termguicolors') && &termguicolors) || has('gui_running')
let g:terminal_ansi_colors = ['#ffffff', '#0000ff', '#00cd00', '#cd00cd', '#008b8b', '#0000ff', '#ff1493', '#bcbcbc', '#ee0000', '#0000ff', '#00cd00', '#cd00cd', '#008b8b', '#0000ff', '#ff1493', '#000000']
diff --git a/runtime/colors/desert.vim b/runtime/colors/desert.vim
index e9b8108d19..510c2ee263 100644
--- a/runtime/colors/desert.vim
+++ b/runtime/colors/desert.vim
@@ -4,7 +4,7 @@
" Maintainer: Original maintainer Hans Fugal <hans@fugal.net>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Mon Aug 8 15:21:08 2022
+" Last Updated: Tue 23 Aug 2022 16:50:37 MSK
" Generated by Colortemplate v2.2.0
@@ -13,7 +13,7 @@ set background=dark
hi clear
let g:colors_name = 'desert'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
if (has('termguicolors') && &termguicolors) || has('gui_running')
let g:terminal_ansi_colors = ['#7f7f8c', '#cd5c5c', '#9acd32', '#bdb76b', '#75a0ff', '#eeee00', '#cd853f', '#666666', '#8a7f7f', '#ff0000', '#89fb98', '#f0e68c', '#6dceeb', '#ffde9b', '#ffa0a0', '#c2bfa5']
diff --git a/runtime/colors/elflord.vim b/runtime/colors/elflord.vim
index 4bfda2a083..dc0327b5fe 100644
--- a/runtime/colors/elflord.vim
+++ b/runtime/colors/elflord.vim
@@ -3,7 +3,7 @@
" Maintainer: original maintainer Ron Aaron <ron@ronware.org>
" Website: https://www.github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Mon Aug 8 15:21:08 2022
+" Last Updated: Tue 23 Aug 2022 16:50:37 MSK
" Generated by Colortemplate v2.2.0
@@ -12,7 +12,7 @@ set background=dark
hi clear
let g:colors_name = 'elflord'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
hi! link Terminal Normal
hi! link Boolean Constant
diff --git a/runtime/colors/evening.vim b/runtime/colors/evening.vim
index 7e0609e9c4..978444d79f 100644
--- a/runtime/colors/evening.vim
+++ b/runtime/colors/evening.vim
@@ -4,7 +4,7 @@
" Maintainer: Original maintainer Steven Vertigan <steven@vertigan.wattle.id.au>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Mon Aug 8 15:21:09 2022
+" Last Updated: Tue 23 Aug 2022 16:50:38 MSK
" Generated by Colortemplate v2.2.0
@@ -13,7 +13,7 @@ set background=dark
hi clear
let g:colors_name = 'evening'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
if (has('termguicolors') && &termguicolors) || has('gui_running')
let g:terminal_ansi_colors = ['#000000', '#ffa500', '#2e8b57', '#ffff00', '#006faf', '#8b008b', '#008b8b', '#bebebe', '#4d4d4d', '#ff5f5f', '#00ff00', '#ffff60', '#0087ff', '#ff80ff', '#00ffff', '#ffffff']
diff --git a/runtime/colors/habamax.vim b/runtime/colors/habamax.vim
index 169fc28021..b356260102 100644
--- a/runtime/colors/habamax.vim
+++ b/runtime/colors/habamax.vim
@@ -4,7 +4,7 @@
" Maintainer: Maxim Kim <habamax@gmail.com>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Mon Aug 8 15:21:10 2022
+" Last Updated: Tue 23 Aug 2022 16:50:38 MSK
" Generated by Colortemplate v2.2.0
@@ -13,7 +13,7 @@ set background=dark
hi clear
let g:colors_name = 'habamax'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
if (has('termguicolors') && &termguicolors) || has('gui_running')
let g:terminal_ansi_colors = ['#1c1c1c', '#d75f5f', '#87af87', '#afaf87', '#5f87af', '#af87af', '#5f8787', '#9e9e9e', '#767676', '#d7875f', '#afd7af', '#d7d787', '#87afd7', '#d7afd7', '#87afaf', '#bcbcbc']
diff --git a/runtime/colors/industry.vim b/runtime/colors/industry.vim
index 359600fa4a..c627d8c826 100644
--- a/runtime/colors/industry.vim
+++ b/runtime/colors/industry.vim
@@ -4,7 +4,7 @@
" Maintainer: Original maintainer Shian Lee.
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Mon Aug 8 15:21:11 2022
+" Last Updated: Tue 23 Aug 2022 16:50:39 MSK
" Generated by Colortemplate v2.2.0
@@ -13,7 +13,7 @@ set background=dark
hi clear
let g:colors_name = 'industry'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
if (has('termguicolors') && &termguicolors) || has('gui_running')
let g:terminal_ansi_colors = ['#303030', '#870000', '#5fd75f', '#afaf00', '#87afff', '#af00af', '#00afaf', '#6c6c6c', '#444444', '#ff0000', '#00ff00', '#ffff00', '#005fff', '#ff00ff', '#00ffff', '#ffffff']
diff --git a/runtime/colors/koehler.vim b/runtime/colors/koehler.vim
index 04476d1ee9..cc4eff6cdf 100644
--- a/runtime/colors/koehler.vim
+++ b/runtime/colors/koehler.vim
@@ -3,7 +3,7 @@
" Maintainer: original maintainer Ron Aaron <ron@ronware.org>
" Website: https://www.github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Mon Aug 8 15:21:12 2022
+" Last Updated: Tue 23 Aug 2022 16:50:39 MSK
" Generated by Colortemplate v2.2.0
@@ -12,7 +12,7 @@ set background=dark
hi clear
let g:colors_name = 'koehler'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
hi! link Terminal Normal
hi! link Boolean Constant
diff --git a/runtime/colors/lunaperche.vim b/runtime/colors/lunaperche.vim
index d6c73eb28c..2f2d4d949b 100644
--- a/runtime/colors/lunaperche.vim
+++ b/runtime/colors/lunaperche.vim
@@ -4,14 +4,14 @@
" Maintainer: Maxim Kim <habamax@gmail.com>
" Website: https://www.github.com/vim/colorschemes
" License: Vim License (see `:help license`)
-" Last Updated: Thu Aug 18 14:36:32 2022
+" Last Updated: Tue 23 Aug 2022 16:50:40 MSK
" Generated by Colortemplate v2.2.0
hi clear
let g:colors_name = 'lunaperche'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
hi! link helpVim Title
hi! link helpHeader Title
diff --git a/runtime/colors/morning.vim b/runtime/colors/morning.vim
index 5764d0df78..6ffecef422 100644
--- a/runtime/colors/morning.vim
+++ b/runtime/colors/morning.vim
@@ -4,7 +4,7 @@
" Maintainer: Original maintainer Bram Moolenaar <Bram@vim.org>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Mon Aug 8 15:21:13 2022
+" Last Updated: Tue 23 Aug 2022 16:50:41 MSK
" Generated by Colortemplate v2.2.0
@@ -13,7 +13,7 @@ set background=light
hi clear
let g:colors_name = 'morning'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
if (has('termguicolors') && &termguicolors) || has('gui_running')
let g:terminal_ansi_colors = ['#e4e4e4', '#a52a2a', '#ff00ff', '#6a0dad', '#008787', '#2e8b57', '#6a5acd', '#bcbcbc', '#0000ff', '#a52a2a', '#ff00ff', '#6a0dad', '#008787', '#2e8b57', '#6a5acd', '#000000']
diff --git a/runtime/colors/murphy.vim b/runtime/colors/murphy.vim
index b7cf6ce985..7b5defd3d0 100644
--- a/runtime/colors/murphy.vim
+++ b/runtime/colors/murphy.vim
@@ -4,7 +4,7 @@
" Maintainer: Original maintainer Ron Aaron <ron@ronware.org>.
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Mon Aug 8 15:21:14 2022
+" Last Updated: Tue 23 Aug 2022 16:50:41 MSK
" Generated by Colortemplate v2.2.0
@@ -13,7 +13,7 @@ set background=dark
hi clear
let g:colors_name = 'murphy'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
if (has('termguicolors') && &termguicolors) || has('gui_running')
let g:terminal_ansi_colors = ['#303030', '#ffa700', '#005f00', '#ffd7af', '#87afff', '#ffafaf', '#00afaf', '#bcbcbc', '#444444', '#ff0000', '#00875f', '#ffff00', '#005fff', '#ff00ff', '#00ffff', '#ffffff']
diff --git a/runtime/colors/pablo.vim b/runtime/colors/pablo.vim
index 521ea44aaf..eaf6deb22b 100644
--- a/runtime/colors/pablo.vim
+++ b/runtime/colors/pablo.vim
@@ -3,7 +3,7 @@
" Maintainer: Original maintainerRon Aaron <ron@ronware.org>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Mon Aug 8 15:21:15 2022
+" Last Updated: Tue 23 Aug 2022 16:50:42 MSK
" Generated by Colortemplate v2.2.0
@@ -12,7 +12,7 @@ set background=dark
hi clear
let g:colors_name = 'pablo'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
if (has('termguicolors') && &termguicolors) || has('gui_running')
let g:terminal_ansi_colors = ['#000000', '#cd0000', '#00cd00', '#cdcd00', '#0000ee', '#cd00cd', '#00cdcd', '#e5e5e5', '#7f7f7f', '#ff0000', '#00ff00', '#ffff00', '#5c5cff', '#ff00ff', '#00ffff', '#ffffff']
diff --git a/runtime/colors/peachpuff.vim b/runtime/colors/peachpuff.vim
index 3e896ffdeb..ad47c31e19 100644
--- a/runtime/colors/peachpuff.vim
+++ b/runtime/colors/peachpuff.vim
@@ -4,7 +4,7 @@
" Maintainer: Original maintainer David Ne\v{c}as (Yeti) <yeti@physics.muni.cz>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Mon Aug 8 15:21:16 2022
+" Last Updated: Tue 23 Aug 2022 16:50:42 MSK
" Generated by Colortemplate v2.2.0
@@ -13,7 +13,7 @@ set background=light
hi clear
let g:colors_name = 'peachpuff'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
if (has('termguicolors') && &termguicolors) || has('gui_running')
let g:terminal_ansi_colors = ['#ffdab9', '#a52a2a', '#c00058', '#cd00cd', '#008b8b', '#2e8b57', '#6a5acd', '#737373', '#406090', '#a52a2a', '#c00058', '#cd00cd', '#008b8b', '#2e8b57', '#6a5acd', '#000000']
diff --git a/runtime/colors/quiet.vim b/runtime/colors/quiet.vim
index 4c4baa994c..9f265726cc 100644
--- a/runtime/colors/quiet.vim
+++ b/runtime/colors/quiet.vim
@@ -4,14 +4,14 @@
" Maintainer: neutaaaaan <neutaaaaan-gh@protonmail.com>
" Website: https://github.com/vim/colorschemes
" License: Vim License (see `:help license`)`
-" Last Updated: 2022-08-14 15:17:11
+" Last Updated: Tue 23 Aug 2022 16:50:43 MSK
" Generated by Colortemplate v2.2.0
hi clear
let g:colors_name = 'quiet'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
hi! link Terminal Normal
hi! link StatusLineTerm StatusLine
diff --git a/runtime/colors/ron.vim b/runtime/colors/ron.vim
index a529d6c199..f622a6f991 100644
--- a/runtime/colors/ron.vim
+++ b/runtime/colors/ron.vim
@@ -3,7 +3,7 @@
" Maintainer: original maintainer Ron Aaron <ron@ronware.org>
" Website: https://www.github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Mon Aug 8 15:21:18 2022
+" Last Updated: Tue 23 Aug 2022 16:50:45 MSK
" Generated by Colortemplate v2.2.0
@@ -12,7 +12,7 @@ set background=dark
hi clear
let g:colors_name = 'ron'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
hi! link Terminal Normal
hi! link Boolean Constant
diff --git a/runtime/colors/shine.vim b/runtime/colors/shine.vim
index b84be280e1..331ca9487c 100644
--- a/runtime/colors/shine.vim
+++ b/runtime/colors/shine.vim
@@ -4,7 +4,7 @@
" Maintainer: Original maintainer is Yasuhiro Matsumoto <mattn@mail.goo.ne.jp>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Mon Aug 8 15:21:19 2022
+" Last Updated: Tue 23 Aug 2022 16:50:46 MSK
" Generated by Colortemplate v2.2.0
@@ -13,7 +13,7 @@ set background=light
hi clear
let g:colors_name = 'shine'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
if (has('termguicolors') && &termguicolors) || has('gui_running')
let g:terminal_ansi_colors = ['#000000', '#8b0000', '#006400', '#ffff00', '#00008b', '#6a0dad', '#008b8b', '#dadada', '#767676', '#ffafaf', '#90ee90', '#ffff60', '#add8e6', '#ff00ff', '#00ffff', '#ffffff']
diff --git a/runtime/colors/slate.vim b/runtime/colors/slate.vim
index 49dbc6387c..ecdaca1e2a 100644
--- a/runtime/colors/slate.vim
+++ b/runtime/colors/slate.vim
@@ -4,7 +4,7 @@
" Maintainer: Original maintainer Ralph Amissah <ralph@amissah.com>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Tue Aug 16 08:11:08 2022
+" Last Updated: Tue 23 Aug 2022 16:50:46 MSK
" Generated by Colortemplate v2.2.0
@@ -13,7 +13,7 @@ set background=dark
hi clear
let g:colors_name = 'slate'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
if (has('termguicolors') && &termguicolors) || has('gui_running')
let g:terminal_ansi_colors = ['#000000', '#cd0000', '#00cd00', '#cdcd00', '#0000ee', '#cd00cd', '#00cdcd', '#e5e5e5', '#7f7f7f', '#ff0000', '#00ff00', '#ffff00', '#5c5cff', '#ff00ff', '#00ffff', '#ffffff']
diff --git a/runtime/colors/torte.vim b/runtime/colors/torte.vim
index ce36507ae8..dbce11c921 100644
--- a/runtime/colors/torte.vim
+++ b/runtime/colors/torte.vim
@@ -4,7 +4,7 @@
" Maintainer: Original maintainer Thorsten Maerz <info@netztorte.de>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Mon Aug 8 15:21:22 2022
+" Last Updated: Tue 23 Aug 2022 16:50:47 MSK
" Generated by Colortemplate v2.2.0
@@ -13,7 +13,7 @@ set background=dark
hi clear
let g:colors_name = 'torte'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
if (has('termguicolors') && &termguicolors) || has('gui_running')
let g:terminal_ansi_colors = ['#000000', '#cd0000', '#00cd00', '#cdcd00', '#0000ee', '#cd00cd', '#00cdcd', '#e5e5e5', '#7f7f7f', '#ff0000', '#00ff00', '#ffff00', '#5c5cff', '#ff00ff', '#00ffff', '#ffffff']
diff --git a/runtime/colors/zellner.vim b/runtime/colors/zellner.vim
index 135591052c..db500c52f2 100644
--- a/runtime/colors/zellner.vim
+++ b/runtime/colors/zellner.vim
@@ -4,7 +4,7 @@
" Maintainer: Original maintainer Ron Aaron <ron@ronware.org>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Mon Aug 8 15:21:23 2022
+" Last Updated: Tue 23 Aug 2022 16:50:48 MSK
" Generated by Colortemplate v2.2.0
@@ -13,7 +13,7 @@ set background=light
hi clear
let g:colors_name = 'zellner'
-let s:t_Co = exists('&t_Co') ? (&t_Co ? &t_Co : 0) : -1
+let s:t_Co = exists('&t_Co') && !has('gui_running') ? (&t_Co ? &t_Co : 0) : -1
if (has('termguicolors') && &termguicolors) || has('gui_running')
let g:terminal_ansi_colors = ['#ffffff', '#a52a2a', '#ff00ff', '#a020f0', '#0000ff', '#0000ff', '#ff00ff', '#a9a9a9', '#ff0000', '#a52a2a', '#ff00ff', '#a020f0', '#0000ff', '#0000ff', '#ff00ff', '#000000']
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index a388592981..89baf84c86 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -750,7 +750,7 @@ nvim_eval_statusline({str}, {*opts}) *nvim_eval_statusline()*
• highlights: (boolean) Return highlight information.
• use_winbar: (boolean) Evaluate winbar instead of statusline.
• use_tabline: (boolean) Evaluate tabline instead of
- statusline. When |TRUE|, {winid} is ignored. Mutually
+ statusline. When true, {winid} is ignored. Mutually
exclusive with {use_winbar}.
Return: ~
@@ -759,7 +759,7 @@ nvim_eval_statusline({str}, {*opts}) *nvim_eval_statusline()*
• width: (number) Display width of the statusline.
• highlights: Array containing highlight information of the
statusline. Only included when the "highlights" key in {opts} is
- |TRUE|. Each element of the array is a |Dictionary| with these keys:
+ true. Each element of the array is a |Dictionary| with these keys:
• start: (number) Byte index (0-based) of first character that uses
the highlight.
• group: (string) Name of highlight group.
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 0be9e9b9d1..a2e15142e7 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -400,6 +400,7 @@ setbufvar({buf}, {varname}, {val}) set {varname} in buffer {buf} to {val}
setcellwidths({list}) none set character cell width overrides
setcharpos({expr}, {list}) Number set the {expr} position to {list}
setcharsearch({dict}) Dict set character search from {dict}
+setcmdline({str} [, {pos}]) Number set command-line
setcmdpos({pos}) Number set cursor position in command-line
setcursorcharpos({list}) Number move cursor to position in {list}
setenv({name}, {val}) none set environment variable
@@ -784,7 +785,8 @@ browsedir({title}, {initdir})
browsing is not possible, an empty string is returned.
bufadd({name}) *bufadd()*
- Add a buffer to the buffer list with String {name}.
+ Add a buffer to the buffer list with name {name} (must be a
+ String).
If a buffer for file {name} already exists, return that buffer
number. Otherwise return the buffer number of the newly
created buffer. When {name} is an empty string then a new
@@ -835,7 +837,8 @@ bufload({buf}) *bufload()*
Ensure the buffer {buf} is loaded. When the buffer name
refers to an existing file then the file is read. Otherwise
the buffer will be empty. If the buffer was already loaded
- then there is no change.
+ then there is no change. If the buffer is not related to a
+ file the no file is read (e.g., when 'buftype' is "nofile").
If there is an existing swap file for the file of the buffer,
there will be no dialog, the buffer will be loaded anyway.
The {buf} argument is used like with |bufexists()|.
@@ -1027,7 +1030,7 @@ chanclose({id} [, {stream}]) *chanclose()*
are closed. If the channel is a pty, this will then close the
pty master, sending SIGHUP to the job process.
For a socket, there is only one stream, and {stream} should be
- ommited.
+ omitted.
chansend({id}, {data}) *chansend()*
Send data to channel {id}. For a job, it writes it to the
@@ -1136,6 +1139,9 @@ chdir({dir}) *chdir()*
" ... do some work
call chdir(save_dir)
endif
+
+< Can also be used as a |method|: >
+ GetDir()->chdir()
<
cindent({lnum}) *cindent()*
Get the amount of indent for line {lnum} according the C
@@ -1526,6 +1532,18 @@ cursor({list})
Can also be used as a |method|: >
GetCursorPos()->cursor()
+debugbreak({pid}) *debugbreak()*
+ Specifically used to interrupt a program being debugged. It
+ will cause process {pid} to get a SIGTRAP. Behavior for other
+ processes is undefined. See |terminal-debugger|.
+ {Sends a SIGINT to a process {pid} other than MS-Windows}
+
+ Returns |TRUE| if successfully interrupted the program.
+ Otherwise returns |FALSE|.
+
+ Can also be used as a |method|: >
+ GetPid()->debugbreak()
+
deepcopy({expr} [, {noref}]) *deepcopy()* *E698*
Make a copy of {expr}. For Numbers and Strings this isn't
different from using {expr} directly.
@@ -1967,18 +1985,6 @@ exp({expr}) *exp()*
Can also be used as a |method|: >
Compute()->exp()
-debugbreak({pid}) *debugbreak()*
- Specifically used to interrupt a program being debugged. It
- will cause process {pid} to get a SIGTRAP. Behavior for other
- processes is undefined. See |terminal-debugger|.
- {Sends a SIGINT to a process {pid} other than MS-Windows}
-
- Returns |TRUE| if successfully interrupted the program.
- Otherwise returns |FALSE|.
-
- Can also be used as a |method|: >
- GetPid()->debugbreak()
-
expand({string} [, {nosuf} [, {list}]]) *expand()*
Expand wildcards and the following special keywords in
{string}. 'wildignorecase' applies.
@@ -2010,6 +2016,8 @@ expand({string} [, {nosuf} [, {list}]]) *expand()*
a function
<SID> "<SNR>123_" where "123" is the
current script ID |<SID>|
+ <script> sourced script file, or script file
+ where the current function was defined
<stack> call stack
<cword> word under the cursor
<cWORD> WORD under the cursor
@@ -2043,6 +2051,9 @@ expand({string} [, {nosuf} [, {list}]]) *expand()*
is not defined, an empty string is used. Using "%:p" in a
buffer with no name, results in the current directory, with a
'/' added.
+ When 'verbose' is set then expanding '%', '#' and <> items
+ will result in an error message if the argument cannot be
+ expanded.
When {string} does not start with '%', '#' or '<', it is
expanded like a file name is expanded on the command line.
@@ -2870,7 +2881,8 @@ getcmdcompltype() *getcmdcompltype()*
Only works when the command line is being edited, thus
requires use of |c_CTRL-\_e| or |c_CTRL-R_=|.
See |:command-completion| for the return string.
- Also see |getcmdtype()|, |setcmdpos()| and |getcmdline()|.
+ Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()| and
+ |setcmdline()|.
Returns an empty string when completion is not defined.
getcmdline() *getcmdline()*
@@ -2879,7 +2891,8 @@ getcmdline() *getcmdline()*
|c_CTRL-R_=|.
Example: >
:cmap <F7> <C-\>eescape(getcmdline(), ' \')<CR>
-< Also see |getcmdtype()|, |getcmdpos()| and |setcmdpos()|.
+< Also see |getcmdtype()|, |getcmdpos()|, |setcmdpos()| and
+ |setcmdline()|.
Returns an empty string when entering a password or using
|inputsecret()|.
@@ -2889,7 +2902,8 @@ getcmdpos() *getcmdpos()*
Only works when editing the command line, thus requires use of
|c_CTRL-\_e| or |c_CTRL-R_=| or an expression mapping.
Returns 0 otherwise.
- Also see |getcmdtype()|, |setcmdpos()| and |getcmdline()|.
+ Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()| and
+ |setcmdline()|.
getcmdscreenpos() *getcmdscreenpos()*
Return the screen position of the cursor in the command line
@@ -2898,7 +2912,8 @@ getcmdscreenpos() *getcmdscreenpos()*
Only works when editing the command line, thus requires use of
|c_CTRL-\_e| or |c_CTRL-R_=| or an expression mapping.
Returns 0 otherwise.
- Also see |getcmdpos()|, |setcmdpos()|.
+ Also see |getcmdpos()|, |setcmdpos()|, |getcmdline()| and
+ |setcmdline()|.
getcmdtype() *getcmdtype()*
Return the current command-line type. Possible return values
@@ -4963,7 +4978,7 @@ matchadd({group}, {pattern} [, {priority} [, {id} [, {dict}]]])
highlighted matches. The dict can have the following members:
conceal Special character to show instead of the
- match (only for |hl-Conceal| highlighed
+ match (only for |hl-Conceal| highlighted
matches, see |:syn-cchar|)
window Instead of the current window use the
window with this number or window ID.
@@ -6417,8 +6432,10 @@ search({pattern} [, {flags} [, {stopline} [, {timeout} [, {skip}]]]])
starts in column zero and then matches before the cursor are
skipped. When the 'c' flag is present in 'cpo' the next
search starts after the match. Without the 'c' flag the next
- search starts one column further. This matters for
- overlapping matches.
+ search starts one column after the start of the match. This
+ matters for overlapping matches. See |cpo-c|. You can also
+ insert "\ze" to change where the match ends, see |/\ze|.
+
When searching backwards and the 'z' flag is given then the
search starts in column zero, thus no match in the current
line will be found (unless wrapping around the end of the
@@ -6900,6 +6917,16 @@ setcharsearch({dict}) *setcharsearch()*
Can also be used as a |method|: >
SavedSearch()->setcharsearch()
+setcmdline({str} [, {pos}]) *setcmdline()*
+ Set the command line to {str} and set the cursor position to
+ {pos}.
+ If {pos} is omitted, the cursor is positioned after the text.
+ Returns 0 when successful, 1 when not editing the command
+ line.
+
+ Can also be used as a |method|: >
+ GetText()->setcmdline()
+
setcmdpos({pos}) *setcmdpos()*
Set the cursor position in the command line to byte position
{pos}. The first position is 1.
@@ -6912,8 +6939,8 @@ setcmdpos({pos}) *setcmdpos()*
before inserting the resulting text.
When the number is too big the cursor is put at the end of the
line. A number smaller than one has undefined results.
- Returns FALSE when successful, TRUE when not editing the
- command line.
+ Returns 0 when successful, 1 when not editing the command
+ line.
Can also be used as a |method|: >
GetPos()->setcmdpos()
@@ -7697,14 +7724,13 @@ stdpath({what}) *stdpath()* *E6100*
config String User configuration directory. |init.vim|
is stored here.
config_dirs List Other configuration directories.
- data String User data directory. The |shada-file|
- is stored here.
+ data String User data directory.
data_dirs List Other data directories.
log String Logs directory (for use by plugins too).
run String Run directory: temporary, local storage
for sockets, named pipes, etc.
state String Session state directory: storage for file
- drafts, undo, shada, etc.
+ drafts, undo, |shada|, etc.
Example: >
:echo stdpath("config")
diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt
index 29eff75bfa..f19671e713 100644
--- a/runtime/doc/cmdline.txt
+++ b/runtime/doc/cmdline.txt
@@ -881,7 +881,7 @@ Note: these are typed literally, they are not special keys!
file name of the sourced file. *E498*
When executing a function, is replaced with the call stack,
as with <stack> (this is for backwards compatibility, using
- <stack> is preferred).
+ <stack> or <script> is preferred).
Note that filename-modifiers are useless when <sfile> is
not used inside a script.
*:<stack>* *<stack>*
@@ -891,6 +891,12 @@ Note: these are typed literally, they are not special keys!
".." in between items. E.g.:
"function {function-name1}[{lnum}]..{function-name2}[{lnum}]"
If there is no call stack you get error *E489* .
+ *:<script>* *<script>*
+ <script> When executing a `:source` command, is replaced with the file
+ name of the sourced file. When executing a function, is
+ replaced with the file name of the script where it is
+ defined.
+ If the file name cannot be determined you get error *E1274* .
*:<slnum>* *<slnum>*
<slnum> When executing a `:source` command, is replaced with the
line number. *E842*
diff --git a/runtime/doc/indent.txt b/runtime/doc/indent.txt
index 1a1d8e30b0..c5411b5f16 100644
--- a/runtime/doc/indent.txt
+++ b/runtime/doc/indent.txt
@@ -979,25 +979,38 @@ indentation: >
PYTHON *ft-python-indent*
The amount of indent can be set for the following situations. The examples
-given are the defaults. Note that the variables are set to an expression, so
-that you can change the value of 'shiftwidth' later.
+given are the defaults. Note that the dictionary values are set to an
+expression, so that you can change the value of 'shiftwidth' later.
Indent after an open paren: >
- let g:pyindent_open_paren = 'shiftwidth() * 2'
+ let g:python_indent.open_paren = 'shiftwidth() * 2'
Indent after a nested paren: >
- let g:pyindent_nested_paren = 'shiftwidth()'
+ let g:python_indent.nested_paren = 'shiftwidth()'
Indent for a continuation line: >
- let g:pyindent_continue = 'shiftwidth() * 2'
+ let g:python_indent.continue = 'shiftwidth() * 2'
+
+By default, the closing paren on a multiline construct lines up under the first
+non-whitespace character of the previous line.
+If you prefer that it's lined up under the first character of the line that
+starts the multiline construct, reset this key: >
+ let g:python_indent.closed_paren_align_last_line = v:false
The method uses |searchpair()| to look back for unclosed parentheses. This
can sometimes be slow, thus it timeouts after 150 msec. If you notice the
indenting isn't correct, you can set a larger timeout in msec: >
- let g:pyindent_searchpair_timeout = 500
+ let g:python_indent.searchpair_timeout = 500
If looking back for unclosed parenthesis is still too slow, especially during
a copy-paste operation, or if you don't need indenting inside multi-line
parentheses, you can completely disable this feature: >
- let g:pyindent_disable_parentheses_indenting = 1
+ let g:python_indent.disable_parentheses_indenting = 1
+
+For backward compatibility, these variables are also supported: >
+ g:pyindent_open_paren
+ g:pyindent_nested_paren
+ g:pyindent_continue
+ g:pyindent_searchpair_timeout
+ g:pyindent_disable_parentheses_indenting
R *ft-r-indent*
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index 7fc0daa0ca..3393a1a1fd 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -126,13 +126,14 @@ FAQ *lsp-faq*
"after/ftplugin/python.vim".
- Q: How do I run a request synchronously (e.g. for formatting on file save)?
- A: Use the `_sync` variant of the function provided by |lsp-buf|, if it
- exists.
+ A: Check if the function has an `async` parameter and set the value to
+ false.
E.g. code formatting: >
" Auto-format *.rs (rust) files prior to saving them
- autocmd BufWritePre *.rs lua vim.lsp.buf.formatting_sync(nil, 1000)
+ " (async = false is the default for format)
+ autocmd BufWritePre *.rs lua vim.lsp.buf.format({ async = false })
<
*lsp-vs-treesitter*
@@ -468,7 +469,7 @@ LspCodeLens
|nvim_buf_set_extmark()|.
LspCodeLensSeparator *hl-LspCodeLensSeparator*
- Used to color the separator between two or more code lens.
+ Used to color the separator between two or more code lenses.
*lsp-highlight-signature*
@@ -825,7 +826,7 @@ start({config}, {opts}) *vim.lsp.start()*
re-uses a client if name and root_dir matches.
Return: ~
- (number) client_id
+ (number|nil) client_id
start_client({config}) *vim.lsp.start_client()*
Starts and initializes a client with the given configuration.
@@ -835,9 +836,16 @@ start_client({config}) *vim.lsp.start_client()*
The following parameters describe fields in the {config} table.
Parameters: ~
- {cmd} (required, string or list treated like
- |jobstart()|) Base command that initiates the LSP
- client.
+ {cmd} (table|string|fun(dispatchers: table):table)
+ command string or list treated like |jobstart|.
+ The command must launch the language server
+ process. `cmd` can also be a function that
+ creates an RPC client. The function receives a
+ dispatchers table and must return a table with
+ the functions `request`, `notify`, `is_closing`
+ and `terminate` See |vim.lsp.rpc.request| and
+ |vim.lsp.rpc.notify| For TCP there is a built-in
+ rpc client factory: |vim.lsp.rpc.connect|
{cmd_cwd} (string, default=|getcwd()|) Directory to launch
the `cmd` process. Not related to `root_dir`.
{cmd_env} (table) Environment flags to pass to the LSP on
@@ -1890,6 +1898,17 @@ should_log({level}) *vim.lsp.log.should_log()*
==============================================================================
Lua module: vim.lsp.rpc *lsp-rpc*
+connect({host}, {port}) *vim.lsp.rpc.connect()*
+ Create a LSP RPC client factory that connects via TCP to the given host
+ and port
+
+ Parameters: ~
+ {host} (string)
+ {port} (number)
+
+ Return: ~
+ (function)
+
format_rpc_error({err}) *vim.lsp.rpc.format_rpc_error()*
Constructs an error message from an LSP error object.
@@ -1904,7 +1923,7 @@ notify({method}, {params}) *vim.lsp.rpc.notify()*
Parameters: ~
{method} (string) The invoked LSP method
- {params} (table): Parameters for the invoked LSP method
+ {params} (table|nil): Parameters for the invoked LSP method
Return: ~
(bool) `true` if notification could be sent, `false` if not
@@ -1915,7 +1934,8 @@ request({method}, {params}, {callback}, {notify_reply_callback})
Parameters: ~
{method} (string) The invoked LSP method
- {params} (table) Parameters for the invoked LSP method
+ {params} (table|nil) Parameters for the invoked LSP
+ method
{callback} (function) Callback to invoke
{notify_reply_callback} (function|nil) Callback to invoke as soon as
a request is no longer pending
@@ -1962,11 +1982,8 @@ start({cmd}, {cmd_args}, {dispatchers}, {extra_spawn_params})
Methods:
• `notify()` |vim.lsp.rpc.notify()|
• `request()` |vim.lsp.rpc.request()|
-
- Members:
- • {pid} (number) The LSP server's PID.
- • {handle} A handle for low-level interaction with the LSP server
- process |vim.loop|.
+ • `is_closing()` returns a boolean indicating if the RPC is closing.
+ • `terminate()` terminates the RPC client.
==============================================================================
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 42f3a5e432..499b3f9a6f 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -881,6 +881,22 @@ vim.str_byteindex({str}, {index} [, {use_utf16}]) *vim.str_byteindex()*
An {index} in the middle of a UTF-16 sequence is rounded upwards to
the end of that sequence.
+vim.iconv({str}, {from}, {to}[, {opts}]) *vim.iconv()*
+ The result is a String, which is the text {str} converted from
+ encoding {from} to encoding {to}. When the conversion fails `nil` is
+ returned. When some characters could not be converted they
+ are replaced with "?".
+ The encoding names are whatever the iconv() library function
+ can accept, see ":Man 3 iconv".
+
+ Parameters: ~
+ {str} (string) Text to convert
+ {from} (string) Encoding of {str}
+ {to} (string) Target encoding
+
+ Returns: ~
+ Converted string if conversion succeeds, `nil` otherwise.
+
vim.schedule({callback}) *vim.schedule()*
Schedules {callback} to be invoked soon by the main event-loop. Useful
to avoid |textlock| or other temporary restrictions.
@@ -1075,17 +1091,13 @@ vim.env *vim.env*
print(vim.env.TERM)
<
+ *lua-options*
*lua-vim-options*
- *lua-vim-opt*
*lua-vim-set*
- *lua-vim-optlocal*
*lua-vim-setlocal*
-In Vimscript, there is a way to set options |set-option|. In Lua, the
-corresponding method is `vim.opt`.
-
-`vim.opt` provides several conveniences for setting and controlling options
-from within Lua.
+Vim options can be accessed through |vim.o|, which behaves like Vimscript
+|:set|.
Examples: ~
@@ -1094,62 +1106,145 @@ from within Lua.
`set number`
In Lua:
- `vim.opt.number = true`
+ `vim.o.number = true`
+
+ To set a string value:
+ In Vimscript:
+ `set wildignore=*.o,*.a,__pycache__`
+
+ In Lua:
+ `vim.o.wildignore = '*.o,*.a,__pycache__'`
+
+Similarly, there exist |vim.bo| and |vim.wo| for setting buffer-local and
+window-local options, respectively, similarly to |:setlocal|. There is also
+|vim.go| that only sets the global value of a |global-local| option, see
+|:setglobal|. The following table summarizes this relation.
+
+ lua command global_value local_value ~
+vim.o :set set set
+vim.bo/vim.wo :setlocal - set
+vim.go :setglobal set -
+
+
+vim.o *vim.o*
+ Get or set editor options, like |:set|. Invalid key is an error.
+
+ Example: >
+ vim.o.cmdheight = 4
+ print(vim.o.columns)
+ print(vim.o.foo) -- error: invalid key
+<
+vim.go *vim.go*
+ Get or set an |option|. Invalid key is an error.
+
+ This is a wrapper around |nvim_set_option_value()| and
+ |nvim_get_option_value()|.
+
+ NOTE: This is different from |vim.o| because this ONLY sets the global
+ option, which generally produces confusing behavior for options with
+ |global-local| values.
+
+ Example: >
+ vim.go.cmdheight = 4
+ print(vim.go.columns)
+ print(vim.go.bar) -- error: invalid key
+<
+vim.bo[{bufnr}] *vim.bo*
+ Get or set buffer-scoped |local-options| for the buffer with number {bufnr}.
+ If [{bufnr}] is omitted, use the current buffer. Invalid {bufnr} or key is
+ an error.
+
+ This is a wrapper around |nvim_set_option_value()| and
+ |nvim_get_option_value()| with `opts = {scope = local, buf = bufnr}` .
+
+ Example: >
+ local bufnr = vim.api.nvim_get_current_buf()
+ vim.bo[bufnr].buflisted = true -- same as vim.bo.buflisted = true
+ print(vim.bo.comments)
+ print(vim.bo.baz) -- error: invalid key
+<
+vim.wo[{winid}] *vim.wo*
+ Get or set window-scoped |local-options| for the window with handle {winid}.
+ If [{winid}] is omitted, use the current window. Invalid {winid} or key
+ is an error.
+
+ This is a wrapper around |nvim_set_option_value()| and
+ |nvim_get_option_value()| with `opts = {scope = local, win = winid}` .
+
+ Example: >
+ local winid = vim.api.nvim_get_current_win()
+ vim.wo[winid].number = true -- same as vim.wo.number = true
+ print(vim.wo.foldmarker)
+ print(vim.wo.quux) -- error: invalid key
+<
+
+
+
+ *lua-vim-opt*
+ *lua-vim-optlocal*
+ *lua-vim-optglobal*
+ *vim.opt*
+
+
+A special interface |vim.opt| exists for conveniently interacting with list-
+and map-style option from Lua: It allows accessing them as Lua tables and
+offers object-oriented method for adding and removing entries.
+
+ Examples: ~
- To set an array of values:
+ The following methods of setting a list-style option are equivalent:
In Vimscript:
`set wildignore=*.o,*.a,__pycache__`
- In Lua, there are two ways you can do this now. One is very similar to
- the Vimscript form:
- `vim.opt.wildignore = '*.o,*.a,__pycache__'`
+ In Lua using `vim.o`:
+ `vim.o.wildignore = '*.o,*.a,__pycache__'`
- However, vim.opt also supports a more elegent way of setting
- list-style options by using lua tables:
+ In Lua using `vim.opt`:
`vim.opt.wildignore = { '*.o', '*.a', '__pycache__' }`
To replicate the behavior of |:set+=|, use: >
- -- vim.opt supports appending options via the "+" operator
- vim.opt.wildignore = vim.opt.wildignore + { "*.pyc", "node_modules" }
-
- -- or using the `:append(...)` method
vim.opt.wildignore:append { "*.pyc", "node_modules" }
<
To replicate the behavior of |:set^=|, use: >
- -- vim.opt supports prepending options via the "^" operator
- vim.opt.wildignore = vim.opt.wildignore ^ { "new_first_value" }
-
- -- or using the `:prepend(...)` method
vim.opt.wildignore:prepend { "new_first_value" }
<
To replicate the behavior of |:set-=|, use: >
- -- vim.opt supports removing options via the "-" operator
- vim.opt.wildignore = vim.opt.wildignore - { "node_modules" }
-
- -- or using the `:remove(...)` method
vim.opt.wildignore:remove { "node_modules" }
<
- To set a map of values:
+ The following methods of setting a map-style option are equivalent:
In Vimscript:
`set listchars=space:_,tab:>~`
- In Lua:
+ In Lua using `vim.o`:
+ `vim.o.listchars = 'space:_,tab:>~'`
+
+ In Lua using `vim.opt`:
`vim.opt.listchars = { space = '_', tab = '>~' }`
+Note that |vim.opt| returns an `Option` object, not the value of the option,
+which is accessed through |Option:get()|:
+
+ Examples: ~
+
+ The following methods of getting a list-style option are equivalent:
+ In Vimscript:
+ `echo wildignore`
+
+ In Lua using `vim.o`:
+ `print(vim.o.wildignore)`
+
+ In Lua using `vim.opt`:
+ `vim.pretty_print(vim.opt.wildignore:get())`
+
+
In any of the above examples, to replicate the behavior |setlocal|, use
`vim.opt_local`. Additionally, to replicate the behavior of |setglobal|, use
`vim.opt_global`.
- *vim.opt*
-
-|vim.opt| returns an Option object.
-
-For example: `local listchar_object = vim.opt.listchars`
-An `Option` has the following methods:
*vim.opt:get()*
@@ -1162,7 +1257,7 @@ Option:get()
the values as entries in the array: >
vim.cmd [[set wildignore=*.pyc,*.o]]
- print(vim.inspect(vim.opt.wildignore:get()))
+ vim.pretty_print(vim.opt.wildignore:get())
-- { "*.pyc", "*.o", }
for _, ignore_pattern in ipairs(vim.opt.wildignore:get()) do
@@ -1175,7 +1270,7 @@ Option:get()
the names as keys and the values as entries: >
vim.cmd [[set listchars=space:_,tab:>~]]
- print(vim.inspect(vim.opt.listchars:get()))
+ vim.pretty_print(vim.opt.listchars:get())
-- { space = "_", tab = ">~", }
for char, representation in pairs(vim.opt.listchars:get()) do
@@ -1186,7 +1281,7 @@ Option:get()
as keys and `true` as entries. >
vim.cmd [[set formatoptions=njtcroql]]
- print(vim.inspect(vim.opt.formatoptions:get()))
+ vim.pretty_print(vim.opt.formatoptions:get())
-- { n = true, j = true, c = true, ... }
local format_opts = vim.opt.formatoptions:get()
@@ -1222,71 +1317,6 @@ Option:remove(value)
`vim.opt.wildignore = vim.opt.wildignore - '*.pyc'`
-In general, using `vim.opt` will provide the expected result when the user is
-used to interacting with editor |options| via `set`. There are still times
-where the user may want to set particular options via a shorthand in Lua,
-which is where |vim.o|, |vim.bo|, |vim.wo|, and |vim.go| come into play.
-
-The behavior of |vim.o|, |vim.bo|, |vim.wo|, and |vim.go| is designed to
-follow that of |:set|, |:setlocal|, and |:setglobal| which can be seen in the
-table below:
-
- lua command global_value local_value ~
-vim.o :set set set
-vim.bo/vim.wo :setlocal - set
-vim.go :setglobal set -
-
-vim.o *vim.o*
- Get or set editor options, like |:set|. Invalid key is an error.
-
- Example: >
- vim.o.cmdheight = 4
- print(vim.o.columns)
- print(vim.o.foo) -- error: invalid key
-<
-vim.go *vim.go*
- Get or set an |option|. Invalid key is an error.
-
- This is a wrapper around |nvim_set_option_value()| and
- |nvim_get_option_value()|.
-
- NOTE: This is different from |vim.o| because this ONLY sets the global
- option, which generally produces confusing behavior for options with
- |global-local| values.
-
- Example: >
- vim.go.cmdheight = 4
- print(vim.go.columns)
- print(vim.go.bar) -- error: invalid key
-<
-vim.bo[{bufnr}] *vim.bo*
- Get or set buffer-scoped |local-options| for the buffer with number {bufnr}.
- If [{bufnr}] is omitted, use the current buffer. Invalid {bufnr} or key is
- an error.
-
- This is a wrapper around |nvim_set_option_value()| and
- |nvim_get_option_value()| with `opts = {scope = local, buf = bufnr}` .
-
- Example: >
- local bufnr = vim.api.nvim_get_current_buf()
- vim.bo[bufnr].buflisted = true -- same as vim.bo.buflisted = true
- print(vim.bo.comments)
- print(vim.bo.baz) -- error: invalid key
-<
-vim.wo[{winid}] *vim.wo*
- Get or set window-scoped |local-options| for the window with handle {winid}.
- If [{winid}] is omitted, use the current window. Invalid {winid} or key
- is an error.
-
- This is a wrapper around |nvim_set_option_value()| and
- |nvim_get_option_value()| with `opts = {scope = local, win = winid}` .
-
- Example: >
- local winid = vim.api.nvim_get_current_win()
- vim.wo[winid].number = true -- same as vim.wo.number = true
- print(vim.wo.foldmarker)
- print(vim.wo.quux) -- error: invalid key
-<
==============================================================================
Lua module: vim *lua-vim*
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 6637464460..6a8ab21d74 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -2454,28 +2454,30 @@ A jump table for the options with a short description can be found at |Q_op|.
*'fillchars'* *'fcs'*
'fillchars' 'fcs' string (default "")
global or local to window |global-local|
- Characters to fill the statuslines and vertical separators.
- It is a comma-separated list of items:
+ Characters to fill the statuslines, vertical separators and special
+ lines in the window.
+ It is a comma-separated list of items. Each item has a name, a colon
+ and the value of that item:
item default Used for ~
- stl:c ' ' or '^' statusline of the current window
- stlnc:c ' ' or '=' statusline of the non-current windows
- wbr:c ' ' window bar
- horiz:c '─' or '-' horizontal separators |:split|
- horizup:c '┴' or '-' upwards facing horizontal separator
- horizdown:c '┬' or '-' downwards facing horizontal separator
- vert:c '│' or '|' vertical separators |:vsplit|
- vertleft:c '┤' or '|' left facing vertical separator
- vertright:c '├' or '|' right facing vertical separator
- verthoriz:c '┼' or '+' overlapping vertical and horizontal
+ stl ' ' or '^' statusline of the current window
+ stlnc ' ' or '=' statusline of the non-current windows
+ wbr ' ' window bar
+ horiz '─' or '-' horizontal separators |:split|
+ horizup '┴' or '-' upwards facing horizontal separator
+ horizdown '┬' or '-' downwards facing horizontal separator
+ vert '│' or '|' vertical separators |:vsplit|
+ vertleft '┤' or '|' left facing vertical separator
+ vertright '├' or '|' right facing vertical separator
+ verthoriz '┼' or '+' overlapping vertical and horizontal
separator
- fold:c '·' or '-' filling 'foldtext'
- foldopen:c '-' mark the beginning of a fold
- foldclose:c '+' show a closed fold
- foldsep:c '│' or '|' open fold middle marker
- diff:c '-' deleted lines of the 'diff' option
- msgsep:c ' ' message separator 'display'
- eob:c '~' empty lines at the end of a buffer
+ fold '·' or '-' filling 'foldtext'
+ foldopen '-' mark the beginning of a fold
+ foldclose '+' show a closed fold
+ foldsep '│' or '|' open fold middle marker
+ diff '-' deleted lines of the 'diff' option
+ msgsep ' ' message separator 'display'
+ eob '~' empty lines at the end of a buffer
Any one that is omitted will fall back to the default. For "stl" and
"stlnc" the space will be used when there is highlighting, '^' or '='
@@ -2500,19 +2502,19 @@ A jump table for the options with a short description can be found at |Q_op|.
The highlighting used for these items:
item highlight group ~
- stl:c StatusLine |hl-StatusLine|
- stlnc:c StatusLineNC |hl-StatusLineNC|
- wbr:c WinBar |hl-WinBar| or |hl-WinBarNC|
- horiz:c WinSeparator |hl-WinSeparator|
- horizup:c WinSeparator |hl-WinSeparator|
- horizdown:c WinSeparator |hl-WinSeparator|
- vert:c WinSeparator |hl-WinSeparator|
- vertleft:c WinSeparator |hl-WinSeparator|
- vertright:c WinSeparator |hl-WinSeparator|
- verthoriz:c WinSeparator |hl-WinSeparator|
- fold:c Folded |hl-Folded|
- diff:c DiffDelete |hl-DiffDelete|
- eob:c EndOfBuffer |hl-EndOfBuffer|
+ stl StatusLine |hl-StatusLine|
+ stlnc StatusLineNC |hl-StatusLineNC|
+ wbr WinBar |hl-WinBar| or |hl-WinBarNC|
+ horiz WinSeparator |hl-WinSeparator|
+ horizup WinSeparator |hl-WinSeparator|
+ horizdown WinSeparator |hl-WinSeparator|
+ vert WinSeparator |hl-WinSeparator|
+ vertleft WinSeparator |hl-WinSeparator|
+ vertright WinSeparator |hl-WinSeparator|
+ verthoriz WinSeparator |hl-WinSeparator|
+ fold Folded |hl-Folded|
+ diff DiffDelete |hl-DiffDelete|
+ eob EndOfBuffer |hl-EndOfBuffer|
*'fixendofline'* *'fixeol'* *'nofixendofline'* *'nofixeol'*
'fixendofline' 'fixeol' boolean (default on)
@@ -6989,15 +6991,18 @@ A jump table for the options with a short description can be found at |Q_op|.
*'wildmenu'* *'wmnu'* *'nowildmenu'* *'nowmnu'*
'wildmenu' 'wmnu' boolean (default on)
global
- Enables "enhanced mode" of command-line completion. When user hits
- <Tab> (or 'wildchar') to invoke completion, the possible matches are
- shown in a menu just above the command-line (see 'wildoptions'), with
- the first match highlighted (overwriting the statusline). Keys that
- show the previous/next match (<Tab>/CTRL-P/CTRL-N) highlight the
- match.
+ When 'wildmenu' is on, command-line completion operates in an enhanced
+ mode. On pressing 'wildchar' (usually <Tab>) to invoke completion,
+ the possible matches are shown.
+ When 'wildoptions' contains "pum", then the completion matches are
+ shown in a popup menu. Otherwise they are displayed just above the
+ command line, with the first match highlighted (overwriting the status
+ line, if there is one).
+ Keys that show the previous/next match, such as <Tab> or
+ CTRL-P/CTRL-N, cause the highlight to move to the appropriate match.
'wildmode' must specify "full": "longest" and "list" do not start
'wildmenu' mode. You can check the current mode with |wildmenumode()|.
- The menu is canceled when a key is hit that is not used for selecting
+ The menu is cancelled when a key is hit that is not used for selecting
a completion.
While the menu is active these keys have special meanings:
diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index b74611633f..6fcf292513 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -181,16 +181,16 @@ Vim will only load the first syntax file found, assuming that it sets
b:current_syntax.
-NAMING CONVENTIONS *group-name* *{group-name}* *E669* *W18*
+NAMING CONVENTIONS *group-name* *{group-name}* *E669* *E5248*
A syntax group name is to be used for syntax items that match the same kind of
thing. These are then linked to a highlight group that specifies the color.
A syntax group name doesn't specify any color or attributes itself.
-The name for a highlight or syntax group must consist of ASCII letters, digits
-and the underscore. As a regexp: "[a-zA-Z0-9_]*". However, Vim does not give
-an error when using other characters. The maximum length of a group name is
-about 200 bytes. *E1249*
+The name for a highlight or syntax group must consist of ASCII letters,
+digits, underscores, periods and `@` characters. As a regexp it is
+`[a-zA-Z0-9_.@]*`. The maximum length of a group name is about 200 bytes.
+*E1249*
To be able to allow each user to pick their favorite set of colors, there must
be preferred names for highlight groups that are common for many languages.
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 52531a1525..2c6c9e4ed8 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -323,16 +323,34 @@ for a buffer with this code: >
local query2 = [[ ... ]]
highlighter:set_query(query2)
-As mentioned above the supported predicate is currently only `eq?`. `match?`
-predicates behave like matching always fails. As an addition a capture which
-begin with an upper-case letter like `@WarningMsg` will map directly to this
-highlight group, if defined. Also if the predicate begins with upper-case and
-contains a dot only the part before the first will be interpreted as the
-highlight group. As an example, this warns of a binary expression with two
+
+ *lua-treesitter-highlight-groups*
+The capture names, with `@` included, are directly usable as highlight groups.
+A fallback system is implemented, so that more specific groups fallback to
+more generic ones. For instance, in a language that has separate doc
+comments, `@comment.doc` could be used. If this group is not defined, the
+highlighting for an ordinary `@comment` is used. This way, existing color
+schemes already work out of the box, but it is possible to add
+more specific variants for queries that make them available.
+
+As an additional rule, captures highlights can always be specialized by
+language, by appending the language name after an additional dot. For
+instance, to highlight comments differently per language: >
+
+ hi @comment.c guifg=Blue
+ hi @comment.lua @guifg=DarkBlue
+ hi link @comment.doc.java String
+<
+It is possible to use custom highlight groups. As an example, if we
+define the `@warning` group: >
+
+ hi link @warning WarningMsg
+<
+the following query warns of a binary expression with two
identical identifiers, highlighting both as |hl-WarningMsg|: >
- ((binary_expression left: (identifier) @WarningMsg.left right: (identifier) @WarningMsg.right)
- (eq? @WarningMsg.left @WarningMsg.right))
+ ((binary_expression left: (identifier) @warning.left right: (identifier) @warning.right)
+ (eq? @warning.left @warning.right))
<
Treesitter Highlighting Priority *lua-treesitter-highlight-priority*
@@ -352,6 +370,27 @@ attribute: >
==============================================================================
Lua module: vim.treesitter *lua-treesitter-core*
+ *get_captures_at_position()*
+get_captures_at_position({bufnr}, {row}, {col})
+ Gets a list of captures for a given cursor position
+
+ Parameters: ~
+ {bufnr} (number) The buffer number
+ {row} (number) The position row
+ {col} (number) The position column
+
+ Return: ~
+ (table) A table of captures
+
+get_node_range({node_or_range}) *get_node_range()*
+ Get the node's range or unpack a range table
+
+ Parameters: ~
+ {node_or_range} (table)
+
+ Return: ~
+ start_row, start_col, end_row, end_col
+
get_parser({bufnr}, {lang}, {opts}) *get_parser()*
Gets the parser for this bufnr / ft combination.
@@ -374,6 +413,34 @@ get_string_parser({str}, {lang}, {opts}) *get_string_parser()*
{lang} The language of this string
{opts} Options to pass to the created language tree
+is_ancestor({dest}, {source}) *is_ancestor()*
+ Determines whether a node is the ancestor of another
+
+ Parameters: ~
+ {dest} (table) the possible ancestor
+ {source} (table) the possible descendant node
+
+ Return: ~
+ (boolean) True if dest is an ancestor of source
+
+is_in_node_range({node}, {line}, {col}) *is_in_node_range()*
+ Determines whether (line, col) position is in node range
+
+ Parameters: ~
+ {node} Node defining the range
+ {line} A line (0-based)
+ {col} A column (0-based)
+
+node_contains({node}, {range}) *node_contains()*
+ Determines if a node contains a range
+
+ Parameters: ~
+ {node} (table) The node
+ {range} (table) The range
+
+ Return: ~
+ (boolean) True if the node contains the range
+
==============================================================================
Lua module: vim.treesitter.language *treesitter-language*
@@ -387,16 +454,20 @@ inspect_language({lang}) *inspect_language()*
Parameters: ~
{lang} The language.
-require_language({lang}, {path}, {silent}) *require_language()*
+ *require_language()*
+require_language({lang}, {path}, {silent}, {symbol_name})
Asserts that the provided language is installed, and optionally provide a
path for the parser
Parsers are searched in the `parser` runtime directory.
Parameters: ~
- {lang} The language the parser should parse
- {path} Optional path the parser is located at
- {silent} Don't throw an error if language not found
+ {lang} (string) The language the parser should parse
+ {path} (string|nil) Optional path the parser is located at
+ {silent} (boolean|nil) Don't throw an error if language not
+ found
+ {symbol_name} (string|nil) Internal symbol name for the language to
+ load
==============================================================================
@@ -423,12 +494,16 @@ add_predicate({name}, {handler}, {force}) *add_predicate()*
{handler} the handler function to be used signature will be (match,
pattern, bufnr, predicate)
-get_node_text({node}, {source}) *get_node_text()*
+get_node_text({node}, {source}, {opts}) *get_node_text()*
Gets the text corresponding to a given node
Parameters: ~
- {node} the node
- {source} The buffer or string from which the node is extracted
+ {node} (table) The node
+ {source} (table) The buffer or string from which the node is
+ extracted
+ {opts} (table) Optional parameters.
+ • concat: (boolean default true) Concatenate result in a
+ string
get_query({lang}, {query_name}) *get_query()*
Returns the runtime query {query_name} for {lang}.
@@ -676,6 +751,17 @@ LanguageTree:language_for_range({self}, {range})
{range} A text range, see |LanguageTree:contains|
{self}
+ *LanguageTree:named_node_for_range()*
+LanguageTree:named_node_for_range({self}, {range}, {opts})
+ Gets the smallest named node that contains {range}
+
+ Parameters: ~
+ {range} (table) A text range
+ {opts} (table) Options table
+ {opts.ignore_injections} (boolean) (default true) Ignore injected
+ languages.
+ {self}
+
LanguageTree:parse({self}) *LanguageTree:parse()*
Parses all defined regions using a treesitter parser for the language this
tree represents. This will run the injection query for this language to
@@ -736,6 +822,17 @@ LanguageTree:source({self}) *LanguageTree:source()*
Parameters: ~
{self}
+ *LanguageTree:tree_for_range()*
+LanguageTree:tree_for_range({self}, {range}, {opts})
+ Gets the tree that contains {range}
+
+ Parameters: ~
+ {range} (table) A text range
+ {opts} (table) Options table
+ {opts.ignore_injections} (boolean) (default true) Ignore injected
+ languages.
+ {self}
+
LanguageTree:trees({self}) *LanguageTree:trees()*
Returns all trees this language tree contains. Does not include child
languages.
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index 0c907bfb68..76c2f8454f 100644
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -872,6 +872,7 @@ Command line: *command-line-functions*
getcmdpos() get position of the cursor in the command line
getcmdscreenpos() get screen position of the cursor in the
command line
+ setcmdline() set the current command line
setcmdpos() set position of the cursor in the command line
getcmdtype() return the current command-line type
getcmdwintype() return the current command-line window type
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 53effa1443..0011cd9821 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -390,6 +390,9 @@ Highlight groups:
using |n| or |N|
|hl-CursorLine| is low-priority unless foreground color is set
|hl-VertSplit| superseded by |hl-WinSeparator|
+ Highlight groups names are allowed to contain the characters `.` and `@`.
+ It is an error to define a highlight group with a name that doesn't match
+ the regexp `[a-zA-Z0-9_.@]*` (see |group-name|).
Macro/|recording| behavior
Replay of a macro recorded during :lmap produces the same actions as when it
diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt
index 7355cec522..2627068a14 100644
--- a/runtime/doc/windows.txt
+++ b/runtime/doc/windows.txt
@@ -163,6 +163,8 @@ CTRL-W v *CTRL-W_v*
3. 'eadirection' isn't "ver", and
4. one of the other windows is wider than the current or new
window.
+ If N was given make the new window N columns wide, if
+ possible.
Note: In other places CTRL-Q does the same as CTRL-V, but here
it doesn't!
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index 52a20d5c10..98d9df8b5c 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -697,7 +697,10 @@ au BufNewFile,BufRead *.mo,*.gdmo setf gdmo
au BufNewFile,BufRead *.gd setf gdscript
" Godot resource
-au BufRead,BufNewFile *.tscn,*.tres setf gdresource
+au BufRead,BufNewFile *.tscn,*.tres setf gdresource
+
+" Godot shader
+au BufRead,BufNewFile *.gdshader,*.shader setf gdshader
" Gedcom
au BufNewFile,BufRead *.ged,lltxxxxx.txt setf gedcom
@@ -2095,6 +2098,11 @@ au BufNewFile,BufRead */.config/upstart/*.override setf upstart
" Vala
au BufNewFile,BufRead *.vala setf vala
+" VDM
+au BufRead,BufNewFile *.vdmpp,*.vpp setf vdmpp
+au BufRead,BufNewFile *.vdmrt setf vdmrt
+au BufRead,BufNewFile *.vdmsl,*.vdm setf vdmsl
+
" Vera
au BufNewFile,BufRead *.vr,*.vri,*.vrh setf vera
diff --git a/runtime/indent/testdir/python.in b/runtime/indent/testdir/python.in
index e6f05f22bc..57719ee430 100644
--- a/runtime/indent/testdir/python.in
+++ b/runtime/indent/testdir/python.in
@@ -1,6 +1,24 @@
# vim: set ft=python sw=4 et:
# START_INDENT
+dict = {
+'a': 1,
+'b': 2,
+'c': 3,
+}
+# END_INDENT
+
+# START_INDENT
+# INDENT_EXE let [g:python_indent.open_paren, g:python_indent.closed_paren_align_last_line] = ['shiftwidth()', v:false]
+dict = {
+'a': 1,
+'b': 2,
+'c': 3,
+}
+# END_INDENT
+
+# START_INDENT
+# INDENT_EXE let g:python_indent.open_paren = 'shiftwidth() * 2'
# INDENT_EXE syntax match pythonFoldMarkers /{{{\d*/ contained containedin=pythonComment
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx {{{1
diff --git a/runtime/indent/testdir/python.ok b/runtime/indent/testdir/python.ok
index df3de8f186..f5ebbc2285 100644
--- a/runtime/indent/testdir/python.ok
+++ b/runtime/indent/testdir/python.ok
@@ -1,6 +1,24 @@
# vim: set ft=python sw=4 et:
# START_INDENT
+dict = {
+ 'a': 1,
+ 'b': 2,
+ 'c': 3,
+ }
+# END_INDENT
+
+# START_INDENT
+# INDENT_EXE let [g:python_indent.open_paren, g:python_indent.closed_paren_align_last_line] = ['shiftwidth()', v:false]
+dict = {
+ 'a': 1,
+ 'b': 2,
+ 'c': 3,
+}
+# END_INDENT
+
+# START_INDENT
+# INDENT_EXE let g:python_indent.open_paren = 'shiftwidth() * 2'
# INDENT_EXE syntax match pythonFoldMarkers /{{{\d*/ contained containedin=pythonComment
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx {{{1
diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua
index 3f71d4f70d..db92085423 100644
--- a/runtime/lua/vim/diagnostic.lua
+++ b/runtime/lua/vim/diagnostic.lua
@@ -45,18 +45,24 @@ local bufnr_and_namespace_cacher_mt = {
end,
}
-local diagnostic_cache = setmetatable({}, {
- __index = function(t, bufnr)
- assert(bufnr > 0, 'Invalid buffer number')
- vim.api.nvim_buf_attach(bufnr, false, {
- on_detach = function()
- rawset(t, bufnr, nil) -- clear cache
- end,
- })
- t[bufnr] = {}
- return t[bufnr]
- end,
-})
+local diagnostic_cache
+do
+ local group = vim.api.nvim_create_augroup('DiagnosticBufDelete', {})
+ diagnostic_cache = setmetatable({}, {
+ __index = function(t, bufnr)
+ assert(bufnr > 0, 'Invalid buffer number')
+ vim.api.nvim_create_autocmd('BufDelete', {
+ group = group,
+ buffer = bufnr,
+ callback = function()
+ rawset(t, bufnr, nil)
+ end,
+ })
+ t[bufnr] = {}
+ return t[bufnr]
+ end,
+ })
+end
local diagnostic_cache_extmarks = setmetatable({}, bufnr_and_namespace_cacher_mt)
local diagnostic_attached_buffers = {}
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index 99c98764dd..fcd697a7c1 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -422,9 +422,11 @@ local extension = {
gdb = 'gdb',
gdmo = 'gdmo',
mo = 'gdmo',
- tres = 'gdresource',
tscn = 'gdresource',
+ tres = 'gdresource',
gd = 'gdscript',
+ gdshader = 'gdshader',
+ shader = 'gdshader',
ged = 'gedcom',
gmi = 'gemtext',
gemini = 'gemtext',
@@ -1011,6 +1013,11 @@ local extension = {
dsm = 'vb',
ctl = 'vb',
vbs = 'vb',
+ vdmpp = 'vdmpp',
+ vpp = 'vdmpp',
+ vdmrt = 'vdmrt',
+ vdmsl = 'vdmsl',
+ vdm = 'vdmsl',
vr = 'vera',
vri = 'vera',
vrh = 'vera',
diff --git a/runtime/lua/vim/inspect.lua b/runtime/lua/vim/inspect.lua
index 0a53fb203b..c232f69590 100644
--- a/runtime/lua/vim/inspect.lua
+++ b/runtime/lua/vim/inspect.lua
@@ -89,8 +89,38 @@ local function escape(str)
)
end
+-- List of lua keywords
+local luaKeywords = {
+ ['and'] = true,
+ ['break'] = true,
+ ['do'] = true,
+ ['else'] = true,
+ ['elseif'] = true,
+ ['end'] = true,
+ ['false'] = true,
+ ['for'] = true,
+ ['function'] = true,
+ ['goto'] = true,
+ ['if'] = true,
+ ['in'] = true,
+ ['local'] = true,
+ ['nil'] = true,
+ ['not'] = true,
+ ['or'] = true,
+ ['repeat'] = true,
+ ['return'] = true,
+ ['then'] = true,
+ ['true'] = true,
+ ['until'] = true,
+ ['while'] = true,
+}
+
local function isIdentifier(str)
- return type(str) == 'string' and not not str:match('^[_%a][_%a%d]*$')
+ return type(str) == 'string'
+ -- identifier must start with a letter and underscore, and be followed by letters, numbers, and underscores
+ and not not str:match('^[_%a][_%a%d]*$')
+ -- lua keywords are not valid identifiers
+ and not luaKeywords[str]
end
local flr = math.floor
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index fd64c1a495..1dc1a045fd 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -289,7 +289,12 @@ local function validate_client_config(config)
'flags.debounce_text_changes must be a number with the debounce time in milliseconds'
)
- local cmd, cmd_args = lsp._cmd_parts(config.cmd)
+ local cmd, cmd_args
+ if type(config.cmd) == 'function' then
+ cmd = config.cmd
+ else
+ cmd, cmd_args = lsp._cmd_parts(config.cmd)
+ end
local offset_encoding = valid_encodings.UTF16
if config.offset_encoding then
offset_encoding = validate_encoding(config.offset_encoding)
@@ -855,14 +860,17 @@ end
--- Used on all running clients.
--- The default implementation re-uses a client if name
--- and root_dir matches.
----@return number client_id
+---@return number|nil client_id
function lsp.start(config, opts)
opts = opts or {}
local reuse_client = opts.reuse_client
or function(client, conf)
return client.config.root_dir == conf.root_dir and client.name == conf.name
end
- config.name = config.name or (config.cmd[1] and vim.fs.basename(config.cmd[1])) or nil
+ config.name = config.name
+ if not config.name and type(config.cmd) == 'table' then
+ config.name = config.cmd[1] and vim.fs.basename(config.cmd[1]) or nil
+ end
local bufnr = api.nvim_get_current_buf()
for _, clients in ipairs({ uninitialized_clients, lsp.get_active_clients() }) do
for _, client in pairs(clients) do
@@ -893,8 +901,13 @@ end
--- The following parameters describe fields in the {config} table.
---
---
----@param cmd: (required, string or list treated like |jobstart()|) Base command
---- that initiates the LSP client.
+---@param cmd: (table|string|fun(dispatchers: table):table) command string or
+--- list treated like |jobstart|. The command must launch the language server
+--- process. `cmd` can also be a function that creates an RPC client.
+--- The function receives a dispatchers table and must return a table with the
+--- functions `request`, `notify`, `is_closing` and `terminate`
+--- See |vim.lsp.rpc.request| and |vim.lsp.rpc.notify|
+--- For TCP there is a built-in rpc client factory: |vim.lsp.rpc.connect|
---
---@param cmd_cwd: (string, default=|getcwd()|) Directory to launch
--- the `cmd` process. Not related to `root_dir`.
@@ -1164,11 +1177,16 @@ function lsp.start_client(config)
end
-- Start the RPC client.
- local rpc = lsp_rpc.start(cmd, cmd_args, dispatch, {
- cwd = config.cmd_cwd,
- env = config.cmd_env,
- detached = config.detached,
- })
+ local rpc
+ if type(cmd) == 'function' then
+ rpc = cmd(dispatch)
+ else
+ rpc = lsp_rpc.start(cmd, cmd_args, dispatch, {
+ cwd = config.cmd_cwd,
+ env = config.cmd_env,
+ detached = config.detached,
+ })
+ end
-- Return nil if client fails to start
if not rpc then
@@ -1464,14 +1482,13 @@ function lsp.start_client(config)
--- you request to stop a client which has previously been requested to
--- shutdown, it will automatically escalate and force shutdown.
---
- ---@param force (bool, optional)
+ ---@param force boolean|nil
function client.stop(force)
- local handle = rpc.handle
- if handle:is_closing() then
+ if rpc.is_closing() then
return
end
if force or not client.initialized or graceful_shutdown_failed then
- handle:kill(15)
+ rpc.terminate()
return
end
-- Sending a signal after a process has exited is acceptable.
@@ -1480,7 +1497,7 @@ function lsp.start_client(config)
rpc.notify('exit')
else
-- If there was an error in the shutdown request, then term to be safe.
- handle:kill(15)
+ rpc.terminate()
graceful_shutdown_failed = true
end
end)
@@ -1492,7 +1509,7 @@ function lsp.start_client(config)
---@returns (bool) true if client is stopped or in the process of being
---stopped; false otherwise
function client.is_stopped()
- return rpc.handle:is_closing()
+ return rpc.is_closing()
end
---@private
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index 0926912066..70f838f34d 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -241,6 +241,399 @@ function default_dispatchers.on_error(code, err)
local _ = log.error() and log.error('client_error:', client_errors[code], err)
end
+---@private
+local function create_read_loop(handle_body, on_no_chunk, on_error)
+ local parse_chunk = coroutine.wrap(request_parser_loop)
+ parse_chunk()
+ return function(err, chunk)
+ if err then
+ on_error(err)
+ return
+ end
+
+ if not chunk then
+ if on_no_chunk then
+ on_no_chunk()
+ end
+ return
+ end
+
+ while true do
+ local headers, body = parse_chunk(chunk)
+ if headers then
+ handle_body(body)
+ chunk = ''
+ else
+ break
+ end
+ end
+ end
+end
+
+---@class RpcClient
+---@field message_index number
+---@field message_callbacks table
+---@field notify_reply_callbacks table
+---@field transport table
+---@field dispatchers table
+
+---@class RpcClient
+local Client = {}
+
+---@private
+function Client:encode_and_send(payload)
+ local _ = log.debug() and log.debug('rpc.send', payload)
+ if self.transport.is_closing() then
+ return false
+ end
+ local encoded = vim.json.encode(payload)
+ self.transport.write(format_message_with_content_length(encoded))
+ return true
+end
+
+---@private
+--- Sends a notification to the LSP server.
+---@param method (string) The invoked LSP method
+---@param params (table|nil): Parameters for the invoked LSP method
+---@returns (bool) `true` if notification could be sent, `false` if not
+function Client:notify(method, params)
+ return self:encode_and_send({
+ jsonrpc = '2.0',
+ method = method,
+ params = params,
+ })
+end
+
+---@private
+--- sends an error object to the remote LSP process.
+function Client:send_response(request_id, err, result)
+ return self:encode_and_send({
+ id = request_id,
+ jsonrpc = '2.0',
+ error = err,
+ result = result,
+ })
+end
+
+---@private
+--- Sends a request to the LSP server and runs {callback} upon response.
+---
+---@param method (string) The invoked LSP method
+---@param params (table|nil) Parameters for the invoked LSP method
+---@param callback (function) Callback to invoke
+---@param notify_reply_callback (function|nil) Callback to invoke as soon as a request is no longer pending
+---@returns (bool, number) `(true, message_id)` if request could be sent, `false` if not
+function Client:request(method, params, callback, notify_reply_callback)
+ validate({
+ callback = { callback, 'f' },
+ notify_reply_callback = { notify_reply_callback, 'f', true },
+ })
+ self.message_index = self.message_index + 1
+ local message_id = self.message_index
+ local result = self:encode_and_send({
+ id = message_id,
+ jsonrpc = '2.0',
+ method = method,
+ params = params,
+ })
+ local message_callbacks = self.message_callbacks
+ local notify_reply_callbacks = self.notify_reply_callbacks
+ if result then
+ if message_callbacks then
+ message_callbacks[message_id] = schedule_wrap(callback)
+ else
+ return false
+ end
+ if notify_reply_callback and notify_reply_callbacks then
+ notify_reply_callbacks[message_id] = schedule_wrap(notify_reply_callback)
+ end
+ return result, message_id
+ else
+ return false
+ end
+end
+
+---@private
+function Client:on_error(errkind, ...)
+ assert(client_errors[errkind])
+ -- TODO what to do if this fails?
+ pcall(self.dispatchers.on_error, errkind, ...)
+end
+
+---@private
+function Client:pcall_handler(errkind, status, head, ...)
+ if not status then
+ self:on_error(errkind, head, ...)
+ return status, head
+ end
+ return status, head, ...
+end
+
+---@private
+function Client:try_call(errkind, fn, ...)
+ return self:pcall_handler(errkind, pcall(fn, ...))
+end
+
+-- TODO periodically check message_callbacks for old requests past a certain
+-- time and log them. This would require storing the timestamp. I could call
+-- them with an error then, perhaps.
+
+---@private
+function Client:handle_body(body)
+ local ok, decoded = pcall(vim.json.decode, body, { luanil = { object = true } })
+ if not ok then
+ self:on_error(client_errors.INVALID_SERVER_JSON, decoded)
+ return
+ end
+ local _ = log.debug() and log.debug('rpc.receive', decoded)
+
+ if type(decoded.method) == 'string' and decoded.id then
+ local err
+ -- Schedule here so that the users functions don't trigger an error and
+ -- we can still use the result.
+ schedule(function()
+ local status, result
+ status, result, err = self:try_call(
+ client_errors.SERVER_REQUEST_HANDLER_ERROR,
+ self.dispatchers.server_request,
+ decoded.method,
+ decoded.params
+ )
+ local _ = log.debug()
+ and log.debug(
+ 'server_request: callback result',
+ { status = status, result = result, err = err }
+ )
+ if status then
+ if not (result or err) then
+ -- TODO this can be a problem if `null` is sent for result. needs vim.NIL
+ error(
+ string.format(
+ 'method %q: either a result or an error must be sent to the server in response',
+ decoded.method
+ )
+ )
+ end
+ if err then
+ assert(
+ type(err) == 'table',
+ 'err must be a table. Use rpc_response_error to help format errors.'
+ )
+ local code_name = assert(
+ protocol.ErrorCodes[err.code],
+ 'Errors must use protocol.ErrorCodes. Use rpc_response_error to help format errors.'
+ )
+ err.message = err.message or code_name
+ end
+ else
+ -- On an exception, result will contain the error message.
+ err = rpc_response_error(protocol.ErrorCodes.InternalError, result)
+ result = nil
+ end
+ self:send_response(decoded.id, err, result)
+ end)
+ -- This works because we are expecting vim.NIL here
+ elseif decoded.id and (decoded.result ~= vim.NIL or decoded.error ~= vim.NIL) then
+ -- We sent a number, so we expect a number.
+ local result_id = assert(tonumber(decoded.id), 'response id must be a number')
+
+ -- Notify the user that a response was received for the request
+ local notify_reply_callbacks = self.notify_reply_callbacks
+ local notify_reply_callback = notify_reply_callbacks and notify_reply_callbacks[result_id]
+ if notify_reply_callback then
+ validate({
+ notify_reply_callback = { notify_reply_callback, 'f' },
+ })
+ notify_reply_callback(result_id)
+ notify_reply_callbacks[result_id] = nil
+ end
+
+ local message_callbacks = self.message_callbacks
+
+ -- Do not surface RequestCancelled to users, it is RPC-internal.
+ if decoded.error then
+ local mute_error = false
+ if decoded.error.code == protocol.ErrorCodes.RequestCancelled then
+ local _ = log.debug() and log.debug('Received cancellation ack', decoded)
+ mute_error = true
+ end
+
+ if mute_error then
+ -- Clear any callback since this is cancelled now.
+ -- This is safe to do assuming that these conditions hold:
+ -- - The server will not send a result callback after this cancellation.
+ -- - If the server sent this cancellation ACK after sending the result, the user of this RPC
+ -- client will ignore the result themselves.
+ if result_id and message_callbacks then
+ message_callbacks[result_id] = nil
+ end
+ return
+ end
+ end
+
+ local callback = message_callbacks and message_callbacks[result_id]
+ if callback then
+ message_callbacks[result_id] = nil
+ validate({
+ callback = { callback, 'f' },
+ })
+ if decoded.error then
+ decoded.error = setmetatable(decoded.error, {
+ __tostring = format_rpc_error,
+ })
+ end
+ self:try_call(
+ client_errors.SERVER_RESULT_CALLBACK_ERROR,
+ callback,
+ decoded.error,
+ decoded.result
+ )
+ else
+ self:on_error(client_errors.NO_RESULT_CALLBACK_FOUND, decoded)
+ local _ = log.error() and log.error('No callback found for server response id ' .. result_id)
+ end
+ elseif type(decoded.method) == 'string' then
+ -- Notification
+ self:try_call(
+ client_errors.NOTIFICATION_HANDLER_ERROR,
+ self.dispatchers.notification,
+ decoded.method,
+ decoded.params
+ )
+ else
+ -- Invalid server message
+ self:on_error(client_errors.INVALID_SERVER_MESSAGE, decoded)
+ end
+end
+
+---@private
+---@return RpcClient
+local function new_client(dispatchers, transport)
+ local state = {
+ message_index = 0,
+ message_callbacks = {},
+ notify_reply_callbacks = {},
+ transport = transport,
+ dispatchers = dispatchers,
+ }
+ return setmetatable(state, { __index = Client })
+end
+
+---@private
+---@param client RpcClient
+local function public_client(client)
+ local result = {}
+
+ ---@private
+ function result.is_closing()
+ return client.transport.is_closing()
+ end
+
+ ---@private
+ function result.terminate()
+ client.transport.terminate()
+ end
+
+ --- Sends a request to the LSP server and runs {callback} upon response.
+ ---
+ ---@param method (string) The invoked LSP method
+ ---@param params (table|nil) Parameters for the invoked LSP method
+ ---@param callback (function) Callback to invoke
+ ---@param notify_reply_callback (function|nil) Callback to invoke as soon as a request is no longer pending
+ ---@returns (bool, number) `(true, message_id)` if request could be sent, `false` if not
+ function result.request(method, params, callback, notify_reply_callback)
+ return client:request(method, params, callback, notify_reply_callback)
+ end
+
+ --- Sends a notification to the LSP server.
+ ---@param method (string) The invoked LSP method
+ ---@param params (table|nil): Parameters for the invoked LSP method
+ ---@returns (bool) `true` if notification could be sent, `false` if not
+ function result.notify(method, params)
+ return client:notify(method, params)
+ end
+
+ return result
+end
+
+---@private
+local function merge_dispatchers(dispatchers)
+ if dispatchers then
+ local user_dispatchers = dispatchers
+ dispatchers = {}
+ for dispatch_name, default_dispatch in pairs(default_dispatchers) do
+ local user_dispatcher = user_dispatchers[dispatch_name]
+ if user_dispatcher then
+ if type(user_dispatcher) ~= 'function' then
+ error(string.format('dispatcher.%s must be a function', dispatch_name))
+ end
+ -- server_request is wrapped elsewhere.
+ if
+ not (dispatch_name == 'server_request' or dispatch_name == 'on_exit') -- TODO this blocks the loop exiting for some reason.
+ then
+ user_dispatcher = schedule_wrap(user_dispatcher)
+ end
+ dispatchers[dispatch_name] = user_dispatcher
+ else
+ dispatchers[dispatch_name] = default_dispatch
+ end
+ end
+ else
+ dispatchers = default_dispatchers
+ end
+ return dispatchers
+end
+
+--- Create a LSP RPC client factory that connects via TCP to the given host
+--- and port
+---
+---@param host string
+---@param port number
+---@return function
+local function connect(host, port)
+ return function(dispatchers)
+ dispatchers = merge_dispatchers(dispatchers)
+ local tcp = uv.new_tcp()
+ local closing = false
+ local transport = {
+ write = function(msg)
+ tcp:write(msg)
+ end,
+ is_closing = function()
+ return closing
+ end,
+ terminate = function()
+ if not closing then
+ closing = true
+ tcp:shutdown()
+ tcp:close()
+ dispatchers.on_exit(0, 0)
+ end
+ end,
+ }
+ local client = new_client(dispatchers, transport)
+ tcp:connect(host, port, function(err)
+ if err then
+ vim.schedule(function()
+ vim.notify(
+ string.format('Could not connect to %s:%s, reason: %s', host, port, vim.inspect(err)),
+ vim.log.levels.WARN
+ )
+ end)
+ return
+ end
+ local handle_body = function(body)
+ client:handle_body(body)
+ end
+ tcp:read_start(create_read_loop(handle_body, transport.terminate, function(read_err)
+ client:on_error(client_errors.READ_ERROR, read_err)
+ end))
+ end)
+
+ return public_client(client)
+ end
+end
+
--- Starts an LSP server process and create an LSP RPC client object to
--- interact with it. Communication with the server is currently limited to stdio.
---
@@ -261,11 +654,8 @@ end
---@returns Methods:
--- - `notify()` |vim.lsp.rpc.notify()|
--- - `request()` |vim.lsp.rpc.request()|
----
----@returns Members:
---- - {pid} (number) The LSP server's PID.
---- - {handle} A handle for low-level interaction with the LSP server process
---- |vim.loop|.
+--- - `is_closing()` returns a boolean indicating if the RPC is closing.
+--- - `terminate()` terminates the RPC client.
local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
local _ = log.info()
and log.info('Starting RPC client', { cmd = cmd, args = cmd_args, extra = extra_spawn_params })
@@ -278,161 +668,64 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
if extra_spawn_params and extra_spawn_params.cwd then
assert(is_dir(extra_spawn_params.cwd), 'cwd must be a directory')
end
- if dispatchers then
- local user_dispatchers = dispatchers
- dispatchers = {}
- for dispatch_name, default_dispatch in pairs(default_dispatchers) do
- local user_dispatcher = user_dispatchers[dispatch_name]
- if user_dispatcher then
- if type(user_dispatcher) ~= 'function' then
- error(string.format('dispatcher.%s must be a function', dispatch_name))
- end
- -- server_request is wrapped elsewhere.
- if
- not (dispatch_name == 'server_request' or dispatch_name == 'on_exit') -- TODO this blocks the loop exiting for some reason.
- then
- user_dispatcher = schedule_wrap(user_dispatcher)
- end
- dispatchers[dispatch_name] = user_dispatcher
- else
- dispatchers[dispatch_name] = default_dispatch
- end
- end
- else
- dispatchers = default_dispatchers
- end
+ dispatchers = merge_dispatchers(dispatchers)
local stdin = uv.new_pipe(false)
local stdout = uv.new_pipe(false)
local stderr = uv.new_pipe(false)
-
- local message_index = 0
- local message_callbacks = {}
- local notify_reply_callbacks = {}
-
local handle, pid
- do
- ---@private
- --- Callback for |vim.loop.spawn()| Closes all streams and runs the `on_exit` dispatcher.
- ---@param code (number) Exit code
- ---@param signal (number) Signal that was used to terminate (if any)
- local function onexit(code, signal)
- stdin:close()
- stdout:close()
- stderr:close()
- handle:close()
- -- Make sure that message_callbacks/notify_reply_callbacks can be gc'd.
- message_callbacks = nil
- notify_reply_callbacks = nil
- dispatchers.on_exit(code, signal)
- end
- local spawn_params = {
- args = cmd_args,
- stdio = { stdin, stdout, stderr },
- detached = not is_win,
- }
- if extra_spawn_params then
- spawn_params.cwd = extra_spawn_params.cwd
- spawn_params.env = env_merge(extra_spawn_params.env)
- if extra_spawn_params.detached ~= nil then
- spawn_params.detached = extra_spawn_params.detached
- end
- end
- handle, pid = uv.spawn(cmd, spawn_params, onexit)
- if handle == nil then
- stdin:close()
- stdout:close()
- stderr:close()
- local msg = string.format('Spawning language server with cmd: `%s` failed', cmd)
- if string.match(pid, 'ENOENT') then
- msg = msg
- .. '. The language server is either not installed, missing from PATH, or not executable.'
- else
- msg = msg .. string.format(' with error message: %s', pid)
+
+ local client = new_client(dispatchers, {
+ write = function(msg)
+ stdin:write(msg)
+ end,
+ is_closing = function()
+ return handle == nil or handle:is_closing()
+ end,
+ terminate = function()
+ if handle then
+ handle:kill(15)
end
- vim.notify(msg, vim.log.levels.WARN)
- return
- end
- end
+ end,
+ })
---@private
- --- Encodes {payload} into a JSON-RPC message and sends it to the remote
- --- process.
- ---
- ---@param payload table
- ---@returns true if the payload could be scheduled, false if the main event-loop is in the process of closing.
- local function encode_and_send(payload)
- local _ = log.debug() and log.debug('rpc.send', payload)
- if handle == nil or handle:is_closing() then
- return false
- end
- local encoded = vim.json.encode(payload)
- stdin:write(format_message_with_content_length(encoded))
- return true
- end
-
- -- FIXME: DOC: Should be placed on the RPC client object returned by
- -- `start()`
- --
- --- Sends a notification to the LSP server.
- ---@param method (string) The invoked LSP method
- ---@param params (table): Parameters for the invoked LSP method
- ---@returns (bool) `true` if notification could be sent, `false` if not
- local function notify(method, params)
- return encode_and_send({
- jsonrpc = '2.0',
- method = method,
- params = params,
- })
+ --- Callback for |vim.loop.spawn()| Closes all streams and runs the `on_exit` dispatcher.
+ ---@param code (number) Exit code
+ ---@param signal (number) Signal that was used to terminate (if any)
+ local function onexit(code, signal)
+ stdin:close()
+ stdout:close()
+ stderr:close()
+ handle:close()
+ dispatchers.on_exit(code, signal)
end
-
- ---@private
- --- sends an error object to the remote LSP process.
- local function send_response(request_id, err, result)
- return encode_and_send({
- id = request_id,
- jsonrpc = '2.0',
- error = err,
- result = result,
- })
+ local spawn_params = {
+ args = cmd_args,
+ stdio = { stdin, stdout, stderr },
+ detached = not is_win,
+ }
+ if extra_spawn_params then
+ spawn_params.cwd = extra_spawn_params.cwd
+ spawn_params.env = env_merge(extra_spawn_params.env)
+ if extra_spawn_params.detached ~= nil then
+ spawn_params.detached = extra_spawn_params.detached
+ end
end
-
- -- FIXME: DOC: Should be placed on the RPC client object returned by
- -- `start()`
- --
- --- Sends a request to the LSP server and runs {callback} upon response.
- ---
- ---@param method (string) The invoked LSP method
- ---@param params (table) Parameters for the invoked LSP method
- ---@param callback (function) Callback to invoke
- ---@param notify_reply_callback (function|nil) Callback to invoke as soon as a request is no longer pending
- ---@returns (bool, number) `(true, message_id)` if request could be sent, `false` if not
- local function request(method, params, callback, notify_reply_callback)
- validate({
- callback = { callback, 'f' },
- notify_reply_callback = { notify_reply_callback, 'f', true },
- })
- message_index = message_index + 1
- local message_id = message_index
- local result = encode_and_send({
- id = message_id,
- jsonrpc = '2.0',
- method = method,
- params = params,
- })
- if result then
- if message_callbacks then
- message_callbacks[message_id] = schedule_wrap(callback)
- else
- return false
- end
- if notify_reply_callback and notify_reply_callbacks then
- notify_reply_callbacks[message_id] = schedule_wrap(notify_reply_callback)
- end
- return result, message_id
+ handle, pid = uv.spawn(cmd, spawn_params, onexit)
+ if handle == nil then
+ stdin:close()
+ stdout:close()
+ stderr:close()
+ local msg = string.format('Spawning language server with cmd: `%s` failed', cmd)
+ if string.match(pid, 'ENOENT') then
+ msg = msg
+ .. '. The language server is either not installed, missing from PATH, or not executable.'
else
- return false
+ msg = msg .. string.format(' with error message: %s', pid)
end
+ vim.notify(msg, vim.log.levels.WARN)
+ return
end
stderr:read_start(function(_, chunk)
@@ -441,195 +734,22 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
end
end)
- ---@private
- local function on_error(errkind, ...)
- assert(client_errors[errkind])
- -- TODO what to do if this fails?
- pcall(dispatchers.on_error, errkind, ...)
- end
- ---@private
- local function pcall_handler(errkind, status, head, ...)
- if not status then
- on_error(errkind, head, ...)
- return status, head
- end
- return status, head, ...
+ local handle_body = function(body)
+ client:handle_body(body)
end
- ---@private
- local function try_call(errkind, fn, ...)
- return pcall_handler(errkind, pcall(fn, ...))
- end
-
- -- TODO periodically check message_callbacks for old requests past a certain
- -- time and log them. This would require storing the timestamp. I could call
- -- them with an error then, perhaps.
+ stdout:read_start(create_read_loop(handle_body, nil, function(err)
+ client:on_error(client_errors.READ_ERROR, err)
+ end))
- ---@private
- local function handle_body(body)
- local ok, decoded = pcall(vim.json.decode, body, { luanil = { object = true } })
- if not ok then
- on_error(client_errors.INVALID_SERVER_JSON, decoded)
- return
- end
- local _ = log.debug() and log.debug('rpc.receive', decoded)
-
- if type(decoded.method) == 'string' and decoded.id then
- local err
- -- Schedule here so that the users functions don't trigger an error and
- -- we can still use the result.
- schedule(function()
- local status, result
- status, result, err = try_call(
- client_errors.SERVER_REQUEST_HANDLER_ERROR,
- dispatchers.server_request,
- decoded.method,
- decoded.params
- )
- local _ = log.debug()
- and log.debug(
- 'server_request: callback result',
- { status = status, result = result, err = err }
- )
- if status then
- if not (result or err) then
- -- TODO this can be a problem if `null` is sent for result. needs vim.NIL
- error(
- string.format(
- 'method %q: either a result or an error must be sent to the server in response',
- decoded.method
- )
- )
- end
- if err then
- assert(
- type(err) == 'table',
- 'err must be a table. Use rpc_response_error to help format errors.'
- )
- local code_name = assert(
- protocol.ErrorCodes[err.code],
- 'Errors must use protocol.ErrorCodes. Use rpc_response_error to help format errors.'
- )
- err.message = err.message or code_name
- end
- else
- -- On an exception, result will contain the error message.
- err = rpc_response_error(protocol.ErrorCodes.InternalError, result)
- result = nil
- end
- send_response(decoded.id, err, result)
- end)
- -- This works because we are expecting vim.NIL here
- elseif decoded.id and (decoded.result ~= vim.NIL or decoded.error ~= vim.NIL) then
- -- We sent a number, so we expect a number.
- local result_id = assert(tonumber(decoded.id), 'response id must be a number')
-
- -- Notify the user that a response was received for the request
- local notify_reply_callback = notify_reply_callbacks and notify_reply_callbacks[result_id]
- if notify_reply_callback then
- validate({
- notify_reply_callback = { notify_reply_callback, 'f' },
- })
- notify_reply_callback(result_id)
- notify_reply_callbacks[result_id] = nil
- end
-
- -- Do not surface RequestCancelled to users, it is RPC-internal.
- if decoded.error then
- local mute_error = false
- if decoded.error.code == protocol.ErrorCodes.RequestCancelled then
- local _ = log.debug() and log.debug('Received cancellation ack', decoded)
- mute_error = true
- end
-
- if mute_error then
- -- Clear any callback since this is cancelled now.
- -- This is safe to do assuming that these conditions hold:
- -- - The server will not send a result callback after this cancellation.
- -- - If the server sent this cancellation ACK after sending the result, the user of this RPC
- -- client will ignore the result themselves.
- if result_id and message_callbacks then
- message_callbacks[result_id] = nil
- end
- return
- end
- end
-
- local callback = message_callbacks and message_callbacks[result_id]
- if callback then
- message_callbacks[result_id] = nil
- validate({
- callback = { callback, 'f' },
- })
- if decoded.error then
- decoded.error = setmetatable(decoded.error, {
- __tostring = format_rpc_error,
- })
- end
- try_call(
- client_errors.SERVER_RESULT_CALLBACK_ERROR,
- callback,
- decoded.error,
- decoded.result
- )
- else
- on_error(client_errors.NO_RESULT_CALLBACK_FOUND, decoded)
- local _ = log.error()
- and log.error('No callback found for server response id ' .. result_id)
- end
- elseif type(decoded.method) == 'string' then
- -- Notification
- try_call(
- client_errors.NOTIFICATION_HANDLER_ERROR,
- dispatchers.notification,
- decoded.method,
- decoded.params
- )
- else
- -- Invalid server message
- on_error(client_errors.INVALID_SERVER_MESSAGE, decoded)
- end
- end
-
- local request_parser = coroutine.wrap(request_parser_loop)
- request_parser()
- stdout:read_start(function(err, chunk)
- if err then
- -- TODO better handling. Can these be intermittent errors?
- on_error(client_errors.READ_ERROR, err)
- return
- end
- -- This should signal that we are done reading from the client.
- if not chunk then
- return
- end
- -- Flush anything in the parser by looping until we don't get a result
- -- anymore.
- while true do
- local headers, body = request_parser(chunk)
- -- If we successfully parsed, then handle the response.
- if headers then
- handle_body(body)
- -- Set chunk to empty so that we can call request_parser to get
- -- anything existing in the parser to flush.
- chunk = ''
- else
- break
- end
- end
- end)
-
- return {
- pid = pid,
- handle = handle,
- request = request,
- notify = notify,
- }
+ return public_client(client)
end
return {
start = start,
+ connect = connect,
rpc_response_error = rpc_response_error,
format_rpc_error = format_rpc_error,
client_errors = client_errors,
+ create_read_loop = create_read_loop,
}
-- vim:sw=2 ts=2 et
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 70f2c425ed..6431162799 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -118,4 +118,127 @@ function M.get_string_parser(str, lang, opts)
return LanguageTree.new(str, lang, opts)
end
+--- Determines whether a node is the ancestor of another
+---
+---@param dest table the possible ancestor
+---@param source table the possible descendant node
+---
+---@returns (boolean) True if dest is an ancestor of source
+function M.is_ancestor(dest, source)
+ if not (dest and source) then
+ return false
+ end
+
+ local current = source
+ while current ~= nil do
+ if current == dest then
+ return true
+ end
+
+ current = current:parent()
+ end
+
+ return false
+end
+
+--- Get the node's range or unpack a range table
+---
+---@param node_or_range table
+---
+---@returns start_row, start_col, end_row, end_col
+function M.get_node_range(node_or_range)
+ if type(node_or_range) == 'table' then
+ return unpack(node_or_range)
+ else
+ return node_or_range:range()
+ end
+end
+
+---Determines whether (line, col) position is in node range
+---
+---@param node Node defining the range
+---@param line A line (0-based)
+---@param col A column (0-based)
+function M.is_in_node_range(node, line, col)
+ local start_line, start_col, end_line, end_col = M.get_node_range(node)
+ if line >= start_line and line <= end_line then
+ if line == start_line and line == end_line then
+ return col >= start_col and col < end_col
+ elseif line == start_line then
+ return col >= start_col
+ elseif line == end_line then
+ return col < end_col
+ else
+ return true
+ end
+ else
+ return false
+ end
+end
+
+---Determines if a node contains a range
+---@param node table The node
+---@param range table The range
+---
+---@returns (boolean) True if the node contains the range
+function M.node_contains(node, range)
+ local start_row, start_col, end_row, end_col = node:range()
+ local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2])
+ local end_fits = end_row > range[3] or (end_row == range[3] and end_col >= range[4])
+
+ return start_fits and end_fits
+end
+
+---Gets a list of captures for a given cursor position
+---@param bufnr number The buffer number
+---@param row number The position row
+---@param col number The position column
+---
+---@returns (table) A table of captures
+function M.get_captures_at_position(bufnr, row, col)
+ if bufnr == 0 then
+ bufnr = a.nvim_get_current_buf()
+ end
+ local buf_highlighter = M.highlighter.active[bufnr]
+
+ if not buf_highlighter then
+ return {}
+ end
+
+ local matches = {}
+
+ buf_highlighter.tree:for_each_tree(function(tstree, tree)
+ if not tstree then
+ return
+ end
+
+ local root = tstree:root()
+ local root_start_row, _, root_end_row, _ = root:range()
+
+ -- Only worry about trees within the line range
+ if root_start_row > row or root_end_row < row then
+ return
+ end
+
+ local q = buf_highlighter:get_query(tree:lang())
+
+ -- Some injected languages may not have highlight queries.
+ if not q:query() then
+ return
+ end
+
+ local iter = q:query():iter_captures(root, buf_highlighter.bufnr, row, row + 1)
+
+ for capture, node, metadata in iter do
+ if M.is_in_node_range(node, row, col) then
+ local c = q._query.captures[capture] -- name of the capture in the query
+ if c ~= nil then
+ table.insert(matches, { capture = c, priority = metadata.priority })
+ end
+ end
+ end
+ end, true)
+ return matches
+end
+
return M
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index e27a5fa9c3..1f242b0fdd 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -12,105 +12,18 @@ TSHighlighterQuery.__index = TSHighlighterQuery
local ns = a.nvim_create_namespace('treesitter/highlighter')
-local _default_highlights = {}
-local _link_default_highlight_once = function(from, to)
- if not _default_highlights[from] then
- _default_highlights[from] = true
- a.nvim_set_hl(0, from, { link = to, default = true })
- end
-
- return from
-end
-
--- If @definition.special does not exist use @definition instead
-local subcapture_fallback = {
- __index = function(self, capture)
- local rtn
- local shortened = capture
- while not rtn and shortened do
- shortened = shortened:match('(.*)%.')
- rtn = shortened and rawget(self, shortened)
- end
- rawset(self, capture, rtn or '__notfound')
- return rtn
- end,
-}
-
-TSHighlighter.hl_map = setmetatable({
- ['error'] = 'Error',
- ['text.underline'] = 'Underlined',
- ['todo'] = 'Todo',
- ['debug'] = 'Debug',
-
- -- Miscs
- ['comment'] = 'Comment',
- ['punctuation.delimiter'] = 'Delimiter',
- ['punctuation.bracket'] = 'Delimiter',
- ['punctuation.special'] = 'Delimiter',
-
- -- Constants
- ['constant'] = 'Constant',
- ['constant.builtin'] = 'Special',
- ['constant.macro'] = 'Define',
- ['define'] = 'Define',
- ['macro'] = 'Macro',
- ['string'] = 'String',
- ['string.regex'] = 'String',
- ['string.escape'] = 'SpecialChar',
- ['character'] = 'Character',
- ['character.special'] = 'SpecialChar',
- ['number'] = 'Number',
- ['boolean'] = 'Boolean',
- ['float'] = 'Float',
-
- -- Functions
- ['function'] = 'Function',
- ['function.special'] = 'Function',
- ['function.builtin'] = 'Special',
- ['function.macro'] = 'Macro',
- ['parameter'] = 'Identifier',
- ['method'] = 'Function',
- ['field'] = 'Identifier',
- ['property'] = 'Identifier',
- ['constructor'] = 'Special',
-
- -- Keywords
- ['conditional'] = 'Conditional',
- ['repeat'] = 'Repeat',
- ['label'] = 'Label',
- ['operator'] = 'Operator',
- ['keyword'] = 'Keyword',
- ['exception'] = 'Exception',
-
- ['type'] = 'Type',
- ['type.builtin'] = 'Type',
- ['type.qualifier'] = 'Type',
- ['type.definition'] = 'Typedef',
- ['storageclass'] = 'StorageClass',
- ['structure'] = 'Structure',
- ['include'] = 'Include',
- ['preproc'] = 'PreProc',
-}, subcapture_fallback)
-
----@private
-local function is_highlight_name(capture_name)
- local firstc = string.sub(capture_name, 1, 1)
- return firstc ~= string.lower(firstc)
-end
-
---@private
function TSHighlighterQuery.new(lang, query_string)
local self = setmetatable({}, { __index = TSHighlighterQuery })
self.hl_cache = setmetatable({}, {
__index = function(table, capture)
- local hl, is_vim_highlight = self:_get_hl_from_capture(capture)
- if not is_vim_highlight then
- hl = _link_default_highlight_once(lang .. hl, hl)
+ local name = self._query.captures[capture]
+ local id = 0
+ if not vim.startswith(name, '_') then
+ id = a.nvim_get_hl_id_by_name('@' .. name .. '.' .. lang)
end
- local id = a.nvim_get_hl_id_by_name(hl)
-
rawset(table, capture, id)
return id
end,
@@ -130,20 +43,6 @@ function TSHighlighterQuery:query()
return self._query
end
----@private
---- Get the hl from capture.
---- Returns a tuple { highlight_name: string, is_builtin: bool }
-function TSHighlighterQuery:_get_hl_from_capture(capture)
- local name = self._query.captures[capture]
-
- if is_highlight_name(name) then
- -- From "Normal.left" only keep "Normal"
- return vim.split(name, '.', true)[1], true
- else
- return TSHighlighter.hl_map[name] or 0, false
- end
-end
-
--- Creates a new highlighter using @param tree
---
---@param tree The language tree to use for highlighting
diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua
index dfb6f5be84..d14b825603 100644
--- a/runtime/lua/vim/treesitter/language.lua
+++ b/runtime/lua/vim/treesitter/language.lua
@@ -6,10 +6,11 @@ local M = {}
---
--- Parsers are searched in the `parser` runtime directory.
---
----@param lang The language the parser should parse
----@param path Optional path the parser is located at
----@param silent Don't throw an error if language not found
-function M.require_language(lang, path, silent)
+---@param lang string The language the parser should parse
+---@param path string|nil Optional path the parser is located at
+---@param silent boolean|nil Don't throw an error if language not found
+---@param symbol_name string|nil Internal symbol name for the language to load
+function M.require_language(lang, path, silent, symbol_name)
if vim._ts_has_language(lang) then
return true
end
@@ -21,7 +22,6 @@ function M.require_language(lang, path, silent)
return false
end
- -- TODO(bfredl): help tag?
error("no parser for '" .. lang .. "' language, see :help treesitter-parsers")
end
path = paths[1]
@@ -29,10 +29,10 @@ function M.require_language(lang, path, silent)
if silent then
return pcall(function()
- vim._ts_add_language(path, lang)
+ vim._ts_add_language(path, lang, symbol_name)
end)
else
- vim._ts_add_language(path, lang)
+ vim._ts_add_language(path, lang, symbol_name)
end
return true
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index 4d3b0631a2..70317a9f94 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -299,7 +299,7 @@ function LanguageTree:included_regions()
end
---@private
-local function get_node_range(node, id, metadata)
+local function get_range_from_metadata(node, id, metadata)
if metadata[id] and metadata[id].range then
return metadata[id].range
end
@@ -362,7 +362,7 @@ function LanguageTree:_get_injections()
elseif name == 'combined' then
combined = true
elseif name == 'content' and #ranges == 0 then
- table.insert(ranges, get_node_range(node, id, metadata))
+ table.insert(ranges, get_range_from_metadata(node, id, metadata))
-- Ignore any tags that start with "_"
-- Allows for other tags to be used in matches
elseif string.sub(name, 1, 1) ~= '_' then
@@ -371,7 +371,7 @@ function LanguageTree:_get_injections()
end
if #ranges == 0 then
- table.insert(ranges, get_node_range(node, id, metadata))
+ table.insert(ranges, get_range_from_metadata(node, id, metadata))
end
end
end
@@ -549,6 +549,44 @@ function LanguageTree:contains(range)
return false
end
+--- Gets the tree that contains {range}
+---
+---@param range table A text range
+---@param opts table Options table
+---@param opts.ignore_injections boolean (default true) Ignore injected languages.
+function LanguageTree:tree_for_range(range, opts)
+ opts = opts or {}
+ local ignore = vim.F.if_nil(opts.ignore_injections, true)
+
+ if not ignore then
+ for _, child in pairs(self._children) do
+ for _, tree in pairs(child:trees()) do
+ if tree_contains(tree, range) then
+ return tree
+ end
+ end
+ end
+ end
+
+ for _, tree in pairs(self._trees) do
+ if tree_contains(tree, range) then
+ return tree
+ end
+ end
+
+ return nil
+end
+
+--- Gets the smallest named node that contains {range}
+---
+---@param range table A text range
+---@param opts table Options table
+---@param opts.ignore_injections boolean (default true) Ignore injected languages.
+function LanguageTree:named_node_for_range(range, opts)
+ local tree = self:tree_for_range(range, opts)
+ return tree:root():named_descendant_for_range(unpack(range))
+end
+
--- Gets the appropriate language that contains {range}
---
---@param range A text range, see |LanguageTree:contains|
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index 103e85abfd..697e2e7691 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -181,9 +181,14 @@ end
--- Gets the text corresponding to a given node
---
----@param node the node
----@param source The buffer or string from which the node is extracted
-function M.get_node_text(node, source)
+---@param node table The node
+---@param source table The buffer or string from which the node is extracted
+---@param opts table Optional parameters.
+--- - concat: (boolean default true) Concatenate result in a string
+function M.get_node_text(node, source, opts)
+ opts = opts or {}
+ local concat = vim.F.if_nil(opts.concat, true)
+
local start_row, start_col, start_byte = node:start()
local end_row, end_col, end_byte = node:end_()
@@ -210,7 +215,7 @@ function M.get_node_text(node, source)
end
end
- return table.concat(lines, '\n')
+ return concat and table.concat(lines, '\n') or lines
elseif type(source) == 'string' then
return source:sub(start_byte + 1, end_byte)
end
diff --git a/runtime/plugin/matchparen.vim b/runtime/plugin/matchparen.vim
index cc4f38f669..ce2225c5f8 100644
--- a/runtime/plugin/matchparen.vim
+++ b/runtime/plugin/matchparen.vim
@@ -5,8 +5,7 @@
" Exit quickly when:
" - this plugin was already loaded (or disabled)
" - when 'compatible' is set
-" - the "CursorMoved" autocmd event is not available.
-if exists("g:loaded_matchparen") || &cp || !exists("##CursorMoved")
+if exists("g:loaded_matchparen") || &cp
finish
endif
let g:loaded_matchparen = 1
@@ -20,7 +19,7 @@ endif
augroup matchparen
" Replace all matchparen autocommands
- autocmd! CursorMoved,CursorMovedI,WinEnter * call s:Highlight_Matching_Pair()
+ autocmd! CursorMoved,CursorMovedI,WinEnter,WinScrolled * call s:Highlight_Matching_Pair()
autocmd! WinLeave * call s:Remove_Matches()
if exists('##TextChanged')
autocmd! TextChanged,TextChangedI * call s:Highlight_Matching_Pair()
diff --git a/runtime/syntax/plsql.vim b/runtime/syntax/plsql.vim
index 7b36c0a180..21681d59e4 100644
--- a/runtime/syntax/plsql.vim
+++ b/runtime/syntax/plsql.vim
@@ -4,12 +4,13 @@
" Previous Maintainer: Jeff Lanzarotta (jefflanzarotta at yahoo dot com)
" Previous Maintainer: C. Laurence Gonsalves (clgonsal@kami.com)
" URL: https://github.com/lee-lindley/vim_plsql_syntax
-" Last Change: April 28, 2022
+" Last Change: Aug 21, 2022
" History Lee Lindley (lee dot lindley at gmail dot com)
+" use get with default 0 instead of exists per Bram suggestion
+" make procedure folding optional
" updated to 19c keywords. refined quoting.
" separated reserved, non-reserved keywords and functions
-" revised folding, giving up on procedure folding due to issue
-" with multiple ways to enter <begin>.
+" revised folding
" Eugene Lysyonok (lysyonok at inbox ru)
" Added folding.
" Geoff Evans & Bill Pribyl (bill at plnet dot org)
@@ -23,12 +24,19 @@
" To enable folding (It does setlocal foldmethod=syntax)
" let plsql_fold = 1
"
+" To disable folding procedure/functions (recommended if you habitually
+" do not put the method name on the END statement)
+" let plsql_disable_procedure_fold = 1
+"
" From my vimrc file -- turn syntax and syntax folding on,
" associate file suffixes as plsql, open all the folds on file open
+" syntax enable
" let plsql_fold = 1
" au BufNewFile,BufRead *.sql,*.pls,*.tps,*.tpb,*.pks,*.pkb,*.pkg,*.trg set filetype=plsql
" au BufNewFile,BufRead *.sql,*.pls,*.tps,*.tpb,*.pks,*.pkb,*.pkg,*.trg syntax on
" au Syntax plsql normal zR
+" au Syntax plsql set foldcolumn=2 "optional if you want to see choosable folds on the left
+
if exists("b:current_syntax")
finish
@@ -49,12 +57,12 @@ syn match plsqlIdentifier "[a-z][a-z0-9$_#]*"
syn match plsqlHostIdentifier ":[a-z][a-z0-9$_#]*"
" When wanted, highlight the trailing whitespace.
-if exists("plsql_space_errors")
- if !exists("plsql_no_trail_space_error")
+if get(g:,"plsql_space_errors",0) == 1
+ if get(g:,"plsql_no_trail_space_error",0) == 0
syn match plsqlSpaceError "\s\+$"
endif
- if !exists("plsql_no_tab_space_error")
+ if get(g:,"plsql_no_tab_space_error",0) == 0
syn match plsqlSpaceError " \+\t"me=e-1
endif
endif
@@ -134,7 +142,8 @@ syn keyword plsqlKeyword CPU_TIME CRASH CREATE_FILE_DEST CREATE_STORED_OUTLINES
syn keyword plsqlKeyword CREDENTIALS CRITICAL CROSS CROSSEDITION CSCONVERT CUBE CUBE_AJ CUBE_GB CUBE_SJ
syn keyword plsqlKeyword CUME_DIST CUME_DISTM CURRENT CURRENTV CURRENT_DATE CURRENT_INSTANCE CURRENT_PARTSET_KEY
syn keyword plsqlKeyword CURRENT_SCHEMA CURRENT_SHARD_KEY CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER
-syn keyword plsqlKeyword CURSOR CURSOR_SHARING_EXACT CURSOR_SPECIFIC_SEGMENT CV CYCLE DAGG_OPTIM_GSETS
+syn match plsqlKeyword "\<CURSOR\>"
+syn keyword plsqlKeyword CURSOR_SHARING_EXACT CURSOR_SPECIFIC_SEGMENT CV CYCLE DAGG_OPTIM_GSETS
syn keyword plsqlKeyword DANGLING DATA DATABASE DATABASES DATAFILE DATAFILES DATAMOVEMENT DATAOBJNO
syn keyword plsqlKeyword DATAOBJ_TO_MAT_PARTITION DATAOBJ_TO_PARTITION DATAPUMP DATASTORE DATA_LINK_DML
syn keyword plsqlKeyword DATA_SECURITY_REWRITE_LIMIT DATA_VALIDATE DATE_MODE DAYS DBA DBA_RECYCLEBIN
@@ -515,7 +524,7 @@ syn match plsqlFunction "\.DELETE\>"hs=s+1
syn match plsqlFunction "\.PREV\>"hs=s+1
syn match plsqlFunction "\.NEXT\>"hs=s+1
-if exists("plsql_legacy_sql_keywords")
+if get(g:,"plsql_legacy_sql_keywords",0) == 1
" Some of Oracle's SQL keywords.
syn keyword plsqlSQLKeyword ABORT ACCESS ACCESSED ADD AFTER ALL ALTER AND ANY
syn keyword plsqlSQLKeyword ASC ATTRIBUTE AUDIT AUTHORIZATION AVG BASE_TABLE
@@ -565,7 +574,7 @@ syn keyword plsqlException SUBSCRIPT_OUTSIDE_LIMIT SYS_INVALID_ROWID
syn keyword plsqlException TIMEOUT_ON_RESOURCE TOO_MANY_ROWS VALUE_ERROR
syn keyword plsqlException ZERO_DIVIDE
-if exists("plsql_highlight_triggers")
+if get(g:,"plsql_highlight_triggers",0) == 1
syn keyword plsqlTrigger INSERTING UPDATING DELETING
endif
@@ -576,7 +585,7 @@ syn match plsqlISAS "\<\(IS\|AS\)\>"
" Various types of comments.
syntax region plsqlCommentL start="--" skip="\\$" end="$" keepend extend contains=@plsqlCommentGroup,plsqlSpaceError
-if exists("plsql_fold")
+if get(g:,"plsql_fold",0) == 1
syntax region plsqlComment
\ start="/\*" end="\*/"
\ extend
@@ -612,7 +621,7 @@ syn region plsqlQuotedIdentifier matchgroup=plsqlOperator start=+n\?"+ end=+
syn cluster plsqlIdentifiers contains=plsqlIdentifier,plsqlQuotedIdentifier
" quoted string literals
-if exists("plsql_fold")
+if get(g:,"plsql_fold",0) == 1
syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?'+ skip=+''+ end=+'+ fold keepend extend
syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'\z([^[(<{]\)+ end=+\z1'+ fold keepend extend
syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'<+ end=+>'+ fold keepend extend
@@ -639,10 +648,10 @@ syn match plsqlAttribute "%\(BULK_EXCEPTIONS\|BULK_ROWCOUNT\|ISOPEN\|FOUND\|NOTF
" This'll catch mis-matched close-parens.
syn cluster plsqlParenGroup contains=plsqlParenError,@plsqlCommentGroup,plsqlCommentSkip,plsqlIntLiteral,plsqlFloatLiteral,plsqlNumbersCom
-if exists("plsql_bracket_error")
+if get(g:,"plsql_bracket_error",0) == 1
" I suspect this code was copied from c.vim and never properly considered. Do
" we even use braces or brackets in sql or pl/sql?
- if exists("plsql_fold")
+ if get(g:,"plsql_fold",0) == 1
syn region plsqlParen start='(' end=')' contains=ALLBUT,@plsqlParenGroup,plsqlErrInBracket fold keepend extend transparent
else
syn region plsqlParen transparent start='(' end=')' contains=ALLBUT,@plsqlParenGroup,plsqlErrInBracket
@@ -652,7 +661,7 @@ if exists("plsql_bracket_error")
syn region plsqlBracket transparent start='\[' end=']' contains=ALLBUT,@plsqlParenGroup,plsqlErrInParen
syn match plsqlErrInBracket contained "[);{}]"
else
- if exists("plsql_fold")
+ if get(g:,"plsql_fold",0) == 1
syn region plsqlParen start='(' end=')' contains=ALLBUT,@plsqlParenGroup,plsqlErrInParen fold keepend extend transparent
else
syn region plsqlParen transparent start='(' end=')' contains=ALLBUT,@plsqlParenGroup,plsqlErrInParen
@@ -673,12 +682,12 @@ syn match plsqlConditional "\<END\>\_s\+\<IF\>"
syn match plsqlCase "\<END\>\_s\+\<CASE\>"
syn match plsqlCase "\<CASE\>"
-if exists("plsql_fold")
+if get(g:,"plsql_fold",0) == 1
setlocal foldmethod=syntax
syn sync fromstart
syn cluster plsqlProcedureGroup contains=plsqlProcedure
- syn cluster plsqlOnlyGroup contains=@plsqlProcedure,plsqlConditionalBlock,plsqlLoopBlock,plsqlBlock
+ syn cluster plsqlOnlyGroup contains=@plsqlProcedure,plsqlConditionalBlock,plsqlLoopBlock,plsqlBlock,plsqlCursor
syntax region plsqlUpdateSet
\ start="\(\<update\>\_s\+\(\<set\>\)\@![a-z][a-z0-9$_#]*\_s\+\(\(\<set\>\)\@![a-z][a-z0-9$_#]*\_s\+\)\?\)\|\(\<when\>\_s\+\<matched\>\_s\+\<then\>\_s\+\<update\>\_s\+\)\<set\>"
@@ -698,24 +707,40 @@ if exists("plsql_fold")
\ transparent
\ contains=ALLBUT,@plsqlOnlyGroup,plsqlUpdateSet
- " this is brute force and requires you have the procedure/function name in the END
- " statement. ALthough Oracle makes it optional, we cannot. If you do not
- " have it, then you can fold the BEGIN/END block of the procedure but not
- " the specification of it (other than a paren group). You also cannot fold
- " BEGIN/END blocks in the procedure body. Local procedures will fold as
- " long as the END statement includes the procedure/function name.
- " As for why we cannot make it work any other way, I don't know. It is
- " something to do with both plsqlBlock and plsqlProcedure both consuming BEGIN and END,
- " even if we use a lookahead for one of them.
- syntax region plsqlProcedure
- "\ start="\(create\(\_s\+or\_s\+replace\)\?\_s\+\)\?\<\(procedure\|function\)\>\_s\+\z([a-z][a-z0-9$_#]*\)"
- \ start="\<\(procedure\|function\)\>\_s\+\(\z([a-z][a-z0-9$_#]*\)\)\([^;]\|\n\)\{-}\<\(is\|as\)\>\_.\{-}\(\<end\>\_s\+\2\_s*;\)\@="
- \ end="\<end\>\_s\+\z1\_s*;"
+ if get(g:,"plsql_disable_procedure_fold",0) == 0
+ " this is brute force and requires you have the procedure/function name in the END
+ " statement. ALthough Oracle makes it optional, we cannot. If you do not
+ " have it, then you can fold the BEGIN/END block of the procedure but not
+ " the specification of it (other than a paren group). You also cannot fold
+ " BEGIN/END blocks in the procedure body. Local procedures will fold as
+ " long as the END statement includes the procedure/function name.
+ " As for why we cannot make it work any other way, I don't know. It is
+ " something to do with both plsqlBlock and plsqlProcedure both consuming BEGIN and END,
+ " even if we use a lookahead for one of them.
+ "
+ " If you habitualy do not put the method name in the END statement,
+ " this can be expensive because it searches to end of file on every
+ " procedure/function declaration
+ "
+ "\ start="\(create\(\_s\+or\_s\+replace\)\?\_s\+\)\?\<\(procedure\|function\)\>\_s\+\z([a-z][a-z0-9$_#]*\)"
+ syntax region plsqlProcedure
+ \ start="\<\(procedure\|function\)\>\_s\+\(\z([a-z][a-z0-9$_#]*\)\)\([^;]\|\n\)\{-}\<\(is\|as\)\>\_.\{-}\(\<end\>\_s\+\2\_s*;\)\@="
+ \ end="\<end\>\_s\+\z1\_s*;"
+ \ fold
+ \ keepend
+ \ extend
+ \ transparent
+ \ contains=ALLBUT,plsqlBlock
+ endif
+
+ syntax region plsqlCursor
+ \ start="\<cursor\>\_s\+[a-z][a-z0-9$_#]*\(\_s*([^)]\+)\)\?\(\_s\+return\_s\+\S\+\)\?\_s\+is"
+ \ end=";"
\ fold
\ keepend
\ extend
\ transparent
- \ contains=ALLBUT,plsqlBlock
+ \ contains=ALLBUT,@plsqlOnlyGroup
syntax region plsqlBlock
\ start="\<begin\>"
@@ -802,7 +827,7 @@ hi def link plsqlTrigger Function
hi def link plsqlTypeAttribute StorageClass
hi def link plsqlTodo Todo
" to be able to change them after loading, need override whether defined or not
-if exists("plsql_legacy_sql_keywords")
+if get(g:,"plsql_legacy_sql_keywords",0) == 1
hi link plsqlSQLKeyword Function
hi link plsqlSymbol Normal
hi link plsqlParen Normal
diff --git a/runtime/syntax/synload.vim b/runtime/syntax/synload.vim
index b88cd95103..056e38bf79 100644
--- a/runtime/syntax/synload.vim
+++ b/runtime/syntax/synload.vim
@@ -30,7 +30,7 @@ fun! s:SynSet()
unlet b:current_syntax
endif
- let s = expand("<amatch>")
+ 0verbose let s = expand("<amatch>")
if s == "ON"
" :set syntax=ON
if &filetype == ""
diff --git a/runtime/syntax/syntax.vim b/runtime/syntax/syntax.vim
index ac7dc314b9..55a2ee6d71 100644
--- a/runtime/syntax/syntax.vim
+++ b/runtime/syntax/syntax.vim
@@ -28,8 +28,9 @@ endif
" Set up the connection between FileType and Syntax autocommands.
" This makes the syntax automatically set when the file type is detected.
+" Avoid an error when 'verbose' is set and <amatch> expansion fails.
augroup syntaxset
- au! FileType * exe "set syntax=" . expand("<amatch>")
+ au! FileType * 0verbose exe "set syntax=" . expand("<amatch>")
augroup END
diff --git a/scripts/check-includes.py b/scripts/check-includes.py
deleted file mode 100755
index ed1fe407c5..0000000000
--- a/scripts/check-includes.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-import re
-import os
-
-from subprocess import Popen, PIPE
-from argparse import ArgumentParser
-
-
-GENERATED_INCLUDE_RE = re.compile(
- r'^\s*#\s*include\s*"([/a-z_0-9.]+\.generated\.h)"(\s+//.*)?$')
-
-
-def main(argv):
- argparser = ArgumentParser()
- argparser.add_argument('--generated-includes-dir', action='append',
- help='Directory where generated includes are located.')
- argparser.add_argument('--file', type=open, help='File to check.')
- argparser.add_argument('iwyu_args', nargs='*',
- help='IWYU arguments, must go after --.')
- args = argparser.parse_args(argv)
-
- with args.file:
- iwyu = Popen(['include-what-you-use', '-xc'] + args.iwyu_args + ['/dev/stdin'],
- stdin=PIPE, stdout=PIPE, stderr=PIPE)
-
- for line in args.file:
- match = GENERATED_INCLUDE_RE.match(line)
- if match:
- for d in args.generated_includes_dir:
- try:
- f = open(os.path.join(d, match.group(1)))
- except IOError:
- continue
- else:
- with f:
- for generated_line in f:
- iwyu.stdin.write(generated_line)
- break
- else:
- raise IOError('Failed to find {0}'.format(match.group(1)))
- else:
- iwyu.stdin.write(line)
-
- iwyu.stdin.close()
-
- out = iwyu.stdout.read()
- err = iwyu.stderr.read()
-
- ret = iwyu.wait()
-
- if ret != 2:
- print('IWYU failed with exit code {0}:'.format(ret))
- print('{0} stdout {0}'.format('=' * ((80 - len(' stdout ')) // 2)))
- print(out)
- print('{0} stderr {0}'.format('=' * ((80 - len(' stderr ')) // 2)))
- print(err)
- return 1
- return 0
-
-
-if __name__ == '__main__':
- raise SystemExit(main(sys.argv[1:]))
diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index bca3dd816f..23ed0e3f08 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -801,7 +801,7 @@ def extract_from_xml(filename, target, width, fmt_vimhelp):
prefix = '%s(' % name
suffix = '%s)' % ', '.join('{%s}' % a[1] for a in params
- if a[0] not in ('void', 'Error'))
+ if a[0] not in ('void', 'Error', 'Arena'))
if not fmt_vimhelp:
c_decl = '%s %s(%s);' % (return_type, name, ', '.join(c_args))
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index 79ae7994f7..1cf0211f43 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -887,12 +887,12 @@ static bool check_autocmd_string_array(Array arr, char *k, Error *err)
static bool unpack_string_or_array(Array *array, Object *v, char *k, bool required, Error *err)
{
if (v->type == kObjectTypeString) {
- ADD(*array, copy_object(*v));
+ ADD(*array, copy_object(*v, NULL));
} else if (v->type == kObjectTypeArray) {
if (!check_autocmd_string_array(v->data.array, k, err)) {
return false;
}
- *array = copy_array(v->data.array);
+ *array = copy_array(v->data.array, NULL);
} else {
if (required) {
api_set_error(err,
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 5e90e40dd3..199650fc55 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -1021,7 +1021,7 @@ void nvim_buf_del_var(Buffer buffer, String name, Error *err)
/// @param buffer Buffer handle, or 0 for current buffer
/// @param[out] err Error details, if any
/// @return Buffer name
-String nvim_buf_get_name(Buffer buffer, Error *err)
+String nvim_buf_get_name(Buffer buffer, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
String rv = STRING_INIT;
@@ -1031,7 +1031,7 @@ String nvim_buf_get_name(Buffer buffer, Error *err)
return rv;
}
- return cstr_to_string((char *)buf->b_ffname);
+ return cstr_as_string(buf->b_ffname);
}
/// Sets the full file name for a buffer
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index 933aa85530..09b004637f 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -51,7 +51,7 @@ Integer nvim_create_namespace(String name)
}
id = next_namespace_id++;
if (name.size > 0) {
- String name_alloc = copy_string(name);
+ String name_alloc = copy_string(name, NULL);
map_put(String, handle_T)(&namespace_ids, name_alloc, id);
}
return (Integer)id;
@@ -993,7 +993,7 @@ void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, Erro
decor_provider_clear(p);
// regardless of what happens, it seems good idea to redraw
- redraw_all_later(NOT_VALID); // TODO(bfredl): too soon?
+ redraw_all_later(UPD_NOT_VALID); // TODO(bfredl): too soon?
struct {
const char *name;
diff --git a/src/nvim/api/private/dispatch.h b/src/nvim/api/private/dispatch.h
index 4b7c394944..f92b205531 100644
--- a/src/nvim/api/private/dispatch.h
+++ b/src/nvim/api/private/dispatch.h
@@ -5,18 +5,23 @@
typedef Object (*ApiDispatchWrapper)(uint64_t channel_id,
Array args,
+ Arena *arena,
Error *error);
/// The rpc_method_handlers table, used in msgpack_rpc_dispatch(), stores
/// functions of this type.
-typedef struct {
+struct MsgpackRpcRequestHandler {
const char *name;
ApiDispatchWrapper fn;
bool fast; // Function is safe to be executed immediately while running the
// uv loop (the loop is run very frequently due to breakcheck).
// If "fast" is false, the function is deferred, i e the call will
// be put in the event queue, for safe handling later.
-} MsgpackRpcRequestHandler;
+ bool arena_return; // return value is allocated in the arena (or statically)
+ // and should not be freed as such.
+};
+
+extern const MsgpackRpcRequestHandler method_handlers[];
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/private/dispatch.h.generated.h"
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index c466fc53e1..ebcf6cca6d 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -58,6 +58,7 @@ void try_enter(TryState *const tstate)
.private_msg_list = NULL,
.trylevel = trylevel,
.got_int = got_int,
+ .did_throw = did_throw,
.need_rethrow = need_rethrow,
.did_emsg = did_emsg,
};
@@ -65,6 +66,7 @@ void try_enter(TryState *const tstate)
current_exception = NULL;
trylevel = 1;
got_int = false;
+ did_throw = false;
need_rethrow = false;
did_emsg = false;
}
@@ -85,6 +87,7 @@ bool try_leave(const TryState *const tstate, Error *const err)
assert(trylevel == 0);
assert(!need_rethrow);
assert(!got_int);
+ assert(!did_throw);
assert(!did_emsg);
assert(msg_list == &tstate->private_msg_list);
assert(*msg_list == NULL);
@@ -93,6 +96,7 @@ bool try_leave(const TryState *const tstate, Error *const err)
current_exception = tstate->current_exception;
trylevel = tstate->trylevel;
got_int = tstate->got_int;
+ did_throw = tstate->did_throw;
need_rethrow = tstate->need_rethrow;
did_emsg = tstate->did_emsg;
return ret;
@@ -127,7 +131,7 @@ bool try_end(Error *err)
force_abort = false;
if (got_int) {
- if (current_exception) {
+ if (did_throw) {
// If we got an interrupt, discard the current exception
discard_current_exception();
}
@@ -146,7 +150,7 @@ bool try_end(Error *err)
if (should_free) {
xfree(msg);
}
- } else if (current_exception) {
+ } else if (did_throw) {
api_set_error(err, kErrorTypeException, "%s", current_exception->value);
discard_current_exception();
}
@@ -618,6 +622,7 @@ void api_clear_error(Error *value)
value->type = kErrorTypeNone;
}
+/// @returns a shared value. caller must not modify it!
Dictionary api_metadata(void)
{
static Dictionary metadata = ARRAY_DICT_INIT;
@@ -630,7 +635,7 @@ Dictionary api_metadata(void)
init_type_metadata(&metadata);
}
- return copy_object(DICTIONARY_OBJ(metadata)).data.dictionary;
+ return metadata;
}
static void init_function_metadata(Dictionary *metadata)
@@ -715,36 +720,40 @@ static void init_type_metadata(Dictionary *metadata)
PUT(*metadata, "types", DICTIONARY_OBJ(types));
}
-String copy_string(String str)
+// all the copy_[object] functions allow arena=NULL,
+// then global allocations are used, and the resulting object
+// should be freed with an api_free_[object] function
+
+String copy_string(String str, Arena *arena)
{
if (str.data != NULL) {
- return (String){ .data = xmemdupz(str.data, str.size), .size = str.size };
+ return (String){ .data = arena_memdupz(arena, str.data, str.size), .size = str.size };
} else {
return (String)STRING_INIT;
}
}
-Array copy_array(Array array)
+Array copy_array(Array array, Arena *arena)
{
- Array rv = ARRAY_DICT_INIT;
+ Array rv = arena_array(arena, array.size);
for (size_t i = 0; i < array.size; i++) {
- ADD(rv, copy_object(array.items[i]));
+ ADD(rv, copy_object(array.items[i], arena));
}
return rv;
}
-Dictionary copy_dictionary(Dictionary dict)
+Dictionary copy_dictionary(Dictionary dict, Arena *arena)
{
- Dictionary rv = ARRAY_DICT_INIT;
+ Dictionary rv = arena_dict(arena, dict.size);
for (size_t i = 0; i < dict.size; i++) {
KeyValuePair item = dict.items[i];
- PUT(rv, item.key.data, copy_object(item.value));
+ PUT_C(rv, copy_string(item.key, arena).data, copy_object(item.value, arena));
}
return rv;
}
/// Creates a deep clone of an object
-Object copy_object(Object obj)
+Object copy_object(Object obj, Arena *arena)
{
switch (obj.type) {
case kObjectTypeBuffer:
@@ -757,13 +766,13 @@ Object copy_object(Object obj)
return obj;
case kObjectTypeString:
- return STRING_OBJ(copy_string(obj.data.string));
+ return STRING_OBJ(copy_string(obj.data.string, arena));
case kObjectTypeArray:
- return ARRAY_OBJ(copy_array(obj.data.array));
+ return ARRAY_OBJ(copy_array(obj.data.array, arena));
case kObjectTypeDictionary:
- return DICTIONARY_OBJ(copy_dictionary(obj.data.dictionary));
+ return DICTIONARY_OBJ(copy_dictionary(obj.data.dictionary, arena));
case kObjectTypeLuaRef:
return LUAREF_OBJ(api_new_luaref(obj.data.luaref));
@@ -844,7 +853,7 @@ HlMessage parse_hl_msg(Array chunks, Error *err)
goto free_exit;
}
- String str = copy_string(chunk.items[0].data.string);
+ String str = copy_string(chunk.items[0].data.string, NULL);
int attr = 0;
if (chunk.size == 2) {
diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h
index 4608554448..2157ad0ec2 100644
--- a/src/nvim/api/private/helpers.h
+++ b/src/nvim/api/private/helpers.h
@@ -134,6 +134,7 @@ typedef struct {
const msglist_T *const *msg_list;
int trylevel;
int got_int;
+ bool did_throw;
int need_rethrow;
int did_emsg;
} TryState;
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 6f7bfa244a..e34dcbdb46 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -965,7 +965,7 @@ static Array translate_contents(UI *ui, Array contents)
} else {
ADD(new_item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT));
}
- ADD(new_item, copy_object(item.items[1]));
+ ADD(new_item, copy_object(item.items[1], NULL));
ADD(new_contents, ARRAY_OBJ(new_item));
}
return new_contents;
@@ -978,7 +978,7 @@ static Array translate_firstarg(UI *ui, Array args)
ADD(new_args, ARRAY_OBJ(translate_contents(ui, contents)));
for (size_t i = 1; i < args.size; i++) {
- ADD(new_args, copy_object(args.items[i]));
+ ADD(new_args, copy_object(args.items[i], NULL));
}
return new_args;
}
@@ -1024,7 +1024,7 @@ static void remote_ui_event(UI *ui, char *name, Array args)
Array items = args.items[0].data.array;
Array new_items = ARRAY_DICT_INIT;
for (size_t i = 0; i < items.size; i++) {
- ADD(new_items, copy_object(items.items[i].data.array.items[0]));
+ ADD(new_items, copy_object(items.items[i].data.array.items[0], NULL));
}
ADD_C(new_args, ARRAY_OBJ(new_items));
push_call(ui, "wildmenu_show", new_args);
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index ce91c1b4af..b164106cef 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -198,7 +198,7 @@ void nvim_set_hl_ns(Integer ns_id, Error *err)
ns_hl_global = (NS)ns_id;
hl_check_ns();
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
}
/// Set active namespace for highlights while redrawing.
@@ -1479,14 +1479,14 @@ void nvim_del_keymap(uint64_t channel_id, String mode, String lhs, Error *err)
/// 1 is the |api-metadata| map (Dictionary).
///
/// @returns 2-tuple [{channel-id}, {api-metadata}]
-Array nvim_get_api_info(uint64_t channel_id)
+Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
FUNC_API_SINCE(1) FUNC_API_FAST FUNC_API_REMOTE_ONLY
{
- Array rv = ARRAY_DICT_INIT;
+ Array rv = arena_array(arena, 2);
assert(channel_id <= INT64_MAX);
- ADD(rv, INTEGER_OBJ((int64_t)channel_id));
- ADD(rv, DICTIONARY_OBJ(api_metadata()));
+ ADD_C(rv, INTEGER_OBJ((int64_t)channel_id));
+ ADD_C(rv, DICTIONARY_OBJ(api_metadata()));
return rv;
}
@@ -1545,9 +1545,9 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version,
FUNC_API_SINCE(4) FUNC_API_REMOTE_ONLY
{
Dictionary info = ARRAY_DICT_INIT;
- PUT(info, "name", copy_object(STRING_OBJ(name)));
+ PUT(info, "name", copy_object(STRING_OBJ(name), NULL));
- version = copy_dictionary(version);
+ version = copy_dictionary(version, NULL);
bool has_major = false;
for (size_t i = 0; i < version.size; i++) {
if (strequal(version.items[i].key.data, "major")) {
@@ -1560,9 +1560,9 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version,
}
PUT(info, "version", DICTIONARY_OBJ(version));
- PUT(info, "type", copy_object(STRING_OBJ(type)));
- PUT(info, "methods", DICTIONARY_OBJ(copy_dictionary(methods)));
- PUT(info, "attributes", DICTIONARY_OBJ(copy_dictionary(attributes)));
+ PUT(info, "type", copy_object(STRING_OBJ(type), NULL));
+ PUT(info, "methods", DICTIONARY_OBJ(copy_dictionary(methods, NULL)));
+ PUT(info, "attributes", DICTIONARY_OBJ(copy_dictionary(attributes, NULL)));
rpc_set_client_info(channel_id, info);
}
@@ -1629,11 +1629,11 @@ Array nvim_list_chans(void)
/// an error, it is a three-element array with the zero-based index of the call
/// which resulted in an error, the error type and the error message. If an
/// error occurred, the values from all preceding calls will still be returned.
-Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err)
+Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *err)
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
{
- Array rv = ARRAY_DICT_INIT;
- Array results = ARRAY_DICT_INIT;
+ Array rv = arena_array(arena, 2);
+ Array results = arena_array(arena, calls.size);
Error nested_error = ERROR_INIT;
size_t i; // also used for freeing the variables
@@ -1642,21 +1642,21 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err)
api_set_error(err,
kErrorTypeValidation,
"Items in calls array must be arrays");
- goto validation_error;
+ goto theend;
}
Array call = calls.items[i].data.array;
if (call.size != 2) {
api_set_error(err,
kErrorTypeValidation,
"Items in calls array must be arrays of size 2");
- goto validation_error;
+ goto theend;
}
if (call.items[0].type != kObjectTypeString) {
api_set_error(err,
kErrorTypeValidation,
"Name must be String");
- goto validation_error;
+ goto theend;
}
String name = call.items[0].data.string;
@@ -1664,7 +1664,7 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err)
api_set_error(err,
kErrorTypeValidation,
"Args must be Array");
- goto validation_error;
+ goto theend;
}
Array args = call.items[1].data.array;
@@ -1676,29 +1676,32 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err)
if (ERROR_SET(&nested_error)) {
break;
}
- Object result = handler.fn(channel_id, args, &nested_error);
+
+ Object result = handler.fn(channel_id, args, arena, &nested_error);
if (ERROR_SET(&nested_error)) {
// error handled after loop
break;
}
-
- ADD(results, result);
+ // TODO(bfredl): wastefull copy. It could be avoided to encoding to msgpack
+ // directly here. But `result` might become invalid when next api function
+ // is called in the loop.
+ ADD_C(results, copy_object(result, arena));
+ if (!handler.arena_return) {
+ api_free_object(result);
+ }
}
- ADD(rv, ARRAY_OBJ(results));
+ ADD_C(rv, ARRAY_OBJ(results));
if (ERROR_SET(&nested_error)) {
- Array errval = ARRAY_DICT_INIT;
- ADD(errval, INTEGER_OBJ((Integer)i));
- ADD(errval, INTEGER_OBJ(nested_error.type));
- ADD(errval, STRING_OBJ(cstr_to_string(nested_error.msg)));
- ADD(rv, ARRAY_OBJ(errval));
+ Array errval = arena_array(arena, 3);
+ ADD_C(errval, INTEGER_OBJ((Integer)i));
+ ADD_C(errval, INTEGER_OBJ(nested_error.type));
+ ADD_C(errval, STRING_OBJ(copy_string(cstr_as_string(nested_error.msg), arena)));
+ ADD_C(rv, ARRAY_OBJ(errval));
} else {
- ADD(rv, NIL);
+ ADD_C(rv, NIL);
}
- goto theend;
-validation_error:
- api_free_array(results);
theend:
api_clear_error(&nested_error);
return rv;
@@ -1751,7 +1754,7 @@ static void write_msg(String message, bool to_err)
/// @return its argument.
Object nvim__id(Object obj)
{
- return copy_object(obj);
+ return copy_object(obj, NULL);
}
/// Returns array given as argument.
@@ -1764,7 +1767,7 @@ Object nvim__id(Object obj)
/// @return its argument.
Array nvim__id_array(Array arr)
{
- return copy_object(ARRAY_OBJ(arr)).data.array;
+ return copy_array(arr, NULL);
}
/// Returns dictionary given as argument.
@@ -1777,7 +1780,7 @@ Array nvim__id_array(Array arr)
/// @return its argument.
Dictionary nvim__id_dictionary(Dictionary dct)
{
- return copy_object(DICTIONARY_OBJ(dct)).data.dictionary;
+ return copy_dictionary(dct, NULL);
}
/// Returns floating-point value given as argument.
@@ -1803,6 +1806,7 @@ Dictionary nvim__stats(void)
PUT(rv, "log_skip", INTEGER_OBJ(g_stats.log_skip));
PUT(rv, "lua_refcount", INTEGER_OBJ(nlua_get_global_ref_count()));
PUT(rv, "redraw", INTEGER_OBJ(g_stats.redraw));
+ PUT(rv, "arena_alloc_count", INTEGER_OBJ((Integer)arena_alloc_count));
return rv;
}
@@ -2040,7 +2044,7 @@ Array nvim_get_mark(String name, Dictionary opts, Error *err)
// Marks are from an open buffer it fnum is non zero
if (mark->fmark.fnum != 0) {
bufnr = mark->fmark.fnum;
- filename = (char *)buflist_nr2name(bufnr, true, true);
+ filename = buflist_nr2name(bufnr, true, true);
allocated = true;
// Marks comes from shada
} else {
@@ -2088,7 +2092,7 @@ Array nvim_get_mark(String name, Dictionary opts, Error *err)
/// 'fillchars'). Treated as single-width even if it isn't.
/// - highlights: (boolean) Return highlight information.
/// - use_winbar: (boolean) Evaluate winbar instead of statusline.
-/// - use_tabline: (boolean) Evaluate tabline instead of statusline. When |TRUE|, {winid}
+/// - use_tabline: (boolean) Evaluate tabline instead of statusline. When true, {winid}
/// is ignored. Mutually exclusive with {use_winbar}.
///
/// @param[out] err Error details, if any.
@@ -2096,7 +2100,7 @@ Array nvim_get_mark(String name, Dictionary opts, Error *err)
/// - str: (string) Characters that will be displayed on the statusline.
/// - width: (number) Display width of the statusline.
/// - highlights: Array containing highlight information of the statusline. Only included when
-/// the "highlights" key in {opts} is |TRUE|. Each element of the array is a
+/// the "highlights" key in {opts} is true. Each element of the array is a
/// |Dictionary| with these keys:
/// - start: (number) Byte index (0-based) of first character that uses the highlight.
/// - group: (string) Name of highlight group.
@@ -2228,7 +2232,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
// If first character doesn't have a defined highlight,
// add the default highlight at the beginning of the highlight list
- if (hltab->start == NULL || ((char *)hltab->start - buf) != 0) {
+ if (hltab->start == NULL || (hltab->start - buf) != 0) {
Dictionary hl_info = ARRAY_DICT_INIT;
grpname = get_default_stl_hl(wp, use_winbar);
diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c
index a28bfd2ab9..f6d0e39327 100644
--- a/src/nvim/api/vimscript.c
+++ b/src/nvim/api/vimscript.c
@@ -137,7 +137,7 @@ Object nvim_eval(String expr, Error *err)
if (!recursive) {
force_abort = false;
suppress_errthrow = false;
- current_exception = NULL;
+ did_throw = false;
// `did_emsg` is set by emsg(), which cancels execution.
did_emsg = false;
}
@@ -196,7 +196,7 @@ static Object _call_function(String fn, Array args, dict_T *self, Error *err)
if (!recursive) {
force_abort = false;
suppress_errthrow = false;
- current_exception = NULL;
+ did_throw = false;
// `did_emsg` is set by emsg(), which cancels execution.
did_emsg = false;
}
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index 6c37df6af8..96c560efa1 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -202,7 +202,7 @@ void nvim_win_set_config(Window window, Dict(float_config) *config, Error *err)
if (!win_new_float(win, false, fconfig, err)) {
return;
}
- redraw_later(win, NOT_VALID);
+ redraw_later(win, UPD_NOT_VALID);
} else {
win_config_float(win, fconfig);
win->w_pos_changed = true;
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index 580dfd8639..5203003369 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -118,7 +118,7 @@ void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err)
// make sure cursor is in visible range even if win != curwin
update_topline_win(win);
- redraw_later(win, VALID);
+ redraw_later(win, UPD_VALID);
win->w_redr_status = true;
}
@@ -449,5 +449,5 @@ void nvim_win_set_hl_ns(Window window, Integer ns_id, Error *err)
win->w_ns_hl = (NS)ns_id;
win->w_hl_needs_update = true;
- redraw_later(win, NOT_VALID);
+ redraw_later(win, UPD_NOT_VALID);
}
diff --git a/src/nvim/arabic.c b/src/nvim/arabic.c
index 06536e6e2b..b57019286f 100644
--- a/src/nvim/arabic.c
+++ b/src/nvim/arabic.c
@@ -320,22 +320,22 @@ int arabic_shape(int c, int *ccp, int *c1p, int prev_c, int prev_c1, int next_c)
int backward_combine = !prev_laa && can_join(prev_c, c);
int forward_combine = can_join(c, next_c);
- if (backward_combine && forward_combine) {
- curr_c = (int)curr_a->medial;
- }
- if (backward_combine && !forward_combine) {
- curr_c = (int)curr_a->final;
- }
- if (!backward_combine && forward_combine) {
- curr_c = (int)curr_a->initial;
- }
- if (!backward_combine && !forward_combine) {
- curr_c = (int)curr_a->isolated;
+ if (backward_combine) {
+ if (forward_combine) {
+ curr_c = (int)curr_a->medial;
+ } else {
+ curr_c = (int)curr_a->final;
+ }
+ } else {
+ if (forward_combine) {
+ curr_c = (int)curr_a->initial;
+ } else {
+ curr_c = (int)curr_a->isolated;
+ }
}
}
- // Sanity check -- curr_c should, in the future, never be 0.
- // We should, in the future, insert a fatal error here.
+ // Character missing from the table means using original character.
if (curr_c == NUL) {
curr_c = c;
}
diff --git a/src/nvim/arglist.c b/src/nvim/arglist.c
index 0be83f0c05..70b2e71949 100644
--- a/src/nvim/arglist.c
+++ b/src/nvim/arglist.c
@@ -157,7 +157,7 @@ void alist_add(alist_T *al, char *fname, int set_fnum)
#ifdef BACKSLASH_IN_FILENAME
slash_adjust(fname);
#endif
- AARGLIST(al)[al->al_ga.ga_len].ae_fname = (char_u *)fname;
+ AARGLIST(al)[al->al_ga.ga_len].ae_fname = fname;
if (set_fnum > 0) {
AARGLIST(al)[al->al_ga.ga_len].ae_fnum =
buflist_add(fname, BLN_LISTED | (set_fnum == 2 ? BLN_CURBUF : 0));
@@ -202,7 +202,7 @@ static char *do_one_arg(char *str)
for (p = str; *str; str++) {
// When the backslash is used for escaping the special meaning of a
// character we need to keep it until wildcard expansion.
- if (rem_backslash((char_u *)str)) {
+ if (rem_backslash(str)) {
*p++ = *str++;
*p++ = *str;
} else {
@@ -226,7 +226,7 @@ static char *do_one_arg(char *str)
/// growarray "gap".
static void get_arglist(garray_T *gap, char *str, int escaped)
{
- ga_init(gap, (int)sizeof(char_u *), 20);
+ ga_init(gap, (int)sizeof(char *), 20);
while (*str != NUL) {
GA_APPEND(char *, gap, str);
@@ -244,12 +244,12 @@ static void get_arglist(garray_T *gap, char *str, int escaped)
/// "fnames[fcountp]". When "wig" is true, removes files matching 'wildignore'.
///
/// @return FAIL or OK.
-int get_arglist_exp(char_u *str, int *fcountp, char ***fnamesp, bool wig)
+int get_arglist_exp(char *str, int *fcountp, char ***fnamesp, bool wig)
{
garray_T ga;
int i;
- get_arglist(&ga, (char *)str, true);
+ get_arglist(&ga, str, true);
if (wig) {
i = expand_wildcards(ga.ga_len, ga.ga_data,
@@ -297,7 +297,7 @@ static void alist_add_list(int count, char **files, int after, bool will_edit)
}
for (int i = 0; i < count; i++) {
const int flags = BLN_LISTED | (will_edit ? BLN_CURBUF : 0);
- ARGLIST[after + i].ae_fname = (char_u *)files[i];
+ ARGLIST[after + i].ae_fname = files[i];
ARGLIST[after + i].ae_fnum = buflist_add(files[i], flags);
}
ALIST(curwin)->al_ga.ga_len += count;
@@ -377,7 +377,7 @@ static int do_arglist(char *str, int what, int after, bool will_edit)
vim_regfree(regmatch.regprog);
xfree(p);
if (!didone) {
- semsg(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]);
+ semsg(_(e_nomatch2), ((char **)new_ga.ga_data)[i]);
}
}
ga_clear(&new_ga);
@@ -472,7 +472,7 @@ void ex_args(exarg_T *eap)
} else if (eap->cmdidx == CMD_args) {
// ":args": list arguments.
if (ARGCOUNT > 0) {
- char **items = xmalloc(sizeof(char_u *) * (size_t)ARGCOUNT);
+ char **items = xmalloc(sizeof(char *) * (size_t)ARGCOUNT);
// Overwrite the command, for a short list there is no scrolling
// required and no wait_return().
gotocmdline(true);
@@ -489,10 +489,8 @@ void ex_args(exarg_T *eap)
ga_grow(gap, GARGCOUNT);
for (int i = 0; i < GARGCOUNT; i++) {
if (GARGLIST[i].ae_fname != NULL) {
- AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname =
- vim_strsave(GARGLIST[i].ae_fname);
- AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum =
- GARGLIST[i].ae_fnum;
+ AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname = xstrdup(GARGLIST[i].ae_fname);
+ AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum = GARGLIST[i].ae_fnum;
gap->ga_len++;
}
}
@@ -742,7 +740,7 @@ char *alist_name(aentry_T *aep)
// Use the name from the associated buffer if it exists.
bp = buflist_findnr(aep->ae_fnum);
if (bp == NULL || bp->b_fname == NULL) {
- return (char *)aep->ae_fname;
+ return aep->ae_fname;
}
return bp->b_fname;
}
@@ -1074,7 +1072,7 @@ char *arg_all(void)
}
/// "argc([window id])" function
-void f_argc(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_argc(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type == VAR_UNKNOWN) {
// use the current window
@@ -1095,13 +1093,13 @@ void f_argc(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "argidx()" function
-void f_argidx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_argidx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = curwin->w_arg_idx;
}
/// "arglistid()" function
-void f_arglistid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_arglistid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = -1;
win_T *wp = find_tabwin(&argvars[0], &argvars[1]);
@@ -1123,7 +1121,7 @@ static void get_arglist_as_rettv(aentry_T *arglist, int argcount, typval_T *rett
}
/// "argv(nr)" function
-void f_argv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_argv(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
aentry_T *arglist = NULL;
int argcount = -1;
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 579c6c029f..1c1de214cd 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -686,7 +686,7 @@ const char *event_nr2name(event_T event)
static bool event_ignored(event_T event)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- char *p = (char *)p_ei;
+ char *p = p_ei;
while (*p != NUL) {
if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ',')) {
@@ -703,7 +703,7 @@ static bool event_ignored(event_T event)
// Return OK when the contents of p_ei is valid, FAIL otherwise.
int check_ei(void)
{
- char *p = (char *)p_ei;
+ char *p = p_ei;
while (*p) {
if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ',')) {
@@ -724,8 +724,8 @@ int check_ei(void)
// Returns the old value of 'eventignore' in allocated memory.
char *au_event_disable(char *what)
{
- char *save_ei = (char *)vim_strsave(p_ei);
- char *new_ei = (char *)vim_strnsave(p_ei, STRLEN(p_ei) + STRLEN(what));
+ char *save_ei = xstrdup(p_ei);
+ char *new_ei = xstrnsave(p_ei, STRLEN(p_ei) + STRLEN(what));
if (*what == ',' && *p_ei == NUL) {
STRCPY(new_ei, what + 1);
} else {
@@ -1119,6 +1119,7 @@ int autocmd_register(int64_t id, event_T event, char *pat, int patlen, int group
if (event == EVENT_WINSCROLLED && !has_event(EVENT_WINSCROLLED)) {
curwin->w_last_topline = curwin->w_topline;
curwin->w_last_leftcol = curwin->w_leftcol;
+ curwin->w_last_skipcol = curwin->w_skipcol;
curwin->w_last_width = curwin->w_width;
curwin->w_last_height = curwin->w_height;
}
@@ -1720,9 +1721,9 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
fname = NULL;
} else {
if (event == EVENT_SYNTAX) {
- fname = (char *)buf->b_p_syn;
+ fname = buf->b_p_syn;
} else if (event == EVENT_FILETYPE) {
- fname = (char *)buf->b_p_ft;
+ fname = buf->b_p_ft;
} else {
if (buf->b_sfname != NULL) {
sfname = xstrdup(buf->b_sfname);
@@ -1811,16 +1812,15 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
char *tail = path_tail(fname);
// Find first autocommand that matches
- AutoPatCmd patcmd;
- patcmd.curpat = first_autopat[(int)event];
- patcmd.nextcmd = NULL;
- patcmd.group = group;
- patcmd.fname = fname;
- patcmd.sfname = sfname;
- patcmd.tail = tail;
- patcmd.event = event;
- patcmd.arg_bufnr = autocmd_bufnr;
- patcmd.next = NULL;
+ AutoPatCmd patcmd = {
+ .curpat = first_autopat[(int)event],
+ .group = group,
+ .fname = fname,
+ .sfname = sfname,
+ .tail = tail,
+ .event = event,
+ .arg_bufnr = autocmd_bufnr,
+ };
auto_next_pat(&patcmd, false);
// found one, start executing the autocommands
@@ -1984,9 +1984,12 @@ void auto_next_pat(AutoPatCmd *apc, int stop_at_last)
AutoPat *ap;
AutoCmd *cp;
char *s;
- char **const sourcing_namep = &SOURCING_NAME;
- XFREE_CLEAR(*sourcing_namep);
+ estack_T *const entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1;
+
+ // Clear the exestack entry for this ETYPE_AUCMD entry.
+ XFREE_CLEAR(entry->es_name);
+ entry->es_info.aucmd = NULL;
for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next) {
apc->curpat = NULL;
@@ -2011,14 +2014,18 @@ void auto_next_pat(AutoPatCmd *apc, int stop_at_last)
const size_t sourcing_name_len
= (STRLEN(s) + strlen(name) + (size_t)ap->patlen + 1);
- *sourcing_namep = xmalloc(sourcing_name_len);
- snprintf(*sourcing_namep, sourcing_name_len, s, name, ap->pat);
+ char *const namep = xmalloc(sourcing_name_len);
+ snprintf(namep, sourcing_name_len, s, name, ap->pat);
if (p_verbose >= 8) {
verbose_enter();
- smsg(_("Executing %s"), *sourcing_namep);
+ smsg(_("Executing %s"), namep);
verbose_leave();
}
+ // Update the exestack entry for this autocmd.
+ entry->es_name = namep;
+ entry->es_info.aucmd = apc;
+
apc->curpat = ap;
apc->nextcmd = ap->cmds;
// mark last command
@@ -2051,7 +2058,7 @@ static bool call_autocmd_callback(const AutoCmd *ac, const AutoPatCmd *apc)
PUT(data, "buf", INTEGER_OBJ(autocmd_bufnr));
if (apc->data) {
- PUT(data, "data", copy_object(*apc->data));
+ PUT(data, "data", copy_object(*apc->data, NULL));
}
int group = apc->curpat->group;
@@ -2150,6 +2157,7 @@ char *getnextac(int c, void *cookie, int indent, bool do_concat)
// lua code, so that it works properly
autocmd_nested = ac->nested;
current_sctx = ac->script_ctx;
+ acp->script_ctx = current_sctx;
if (ac->exec.type == CALLABLE_CB) {
if (call_autocmd_callback(ac, acp)) {
diff --git a/src/nvim/autocmd.h b/src/nvim/autocmd.h
index d559d8c3d2..75a8a7aaa1 100644
--- a/src/nvim/autocmd.h
+++ b/src/nvim/autocmd.h
@@ -29,7 +29,7 @@ struct AutoCmd_S {
bool nested; // If autocommands nest here
bool last; // last command in list
int64_t id; // ID used for uniquely tracking an autocmd.
- sctx_T script_ctx; // script context where defined
+ sctx_T script_ctx; // script context where it is defined
char *desc; // Description for the autocmd.
AutoCmd *next; // Next AutoCmd in list
};
@@ -59,6 +59,7 @@ struct AutoPatCmd_S {
char *sfname; // sfname to match with
char *tail; // tail of fname
event_T event; // current event
+ sctx_T script_ctx; // script context where it is defined
int arg_bufnr; // initially equal to <abuf>, set to zero when buf is deleted
Object *data; // arbitrary data
AutoPatCmd *next; // chain of active apc-s for auto-invalidation
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index ab5b32bf3e..514be4c56b 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -165,11 +165,12 @@ static int read_buffer(int read_stdin, exarg_T *eap, int flags)
///
/// @param read_stdin read file from stdin
/// @param eap for forced 'ff' and 'fenc' or NULL
-/// @param flags extra flags for readfile()
+/// @param flags_arg extra flags for readfile()
///
/// @return FAIL for failure, OK otherwise.
-int open_buffer(int read_stdin, exarg_T *eap, int flags)
+int open_buffer(int read_stdin, exarg_T *eap, int flags_arg)
{
+ int flags = flags_arg;
int retval = OK;
bufref_T old_curbuf;
long old_tw = curbuf->b_p_tw;
@@ -224,6 +225,13 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags)
// mark cursor position as being invalid
curwin->w_valid = 0;
+ // A buffer without an actual file should not use the buffer name to read a
+ // file.
+ if (bt_nofileread(curbuf)) {
+ flags |= READ_NOFILE;
+ }
+
+ // Read the file if there is one.
if (curbuf->b_ffname != NULL) {
#ifdef UNIX
int save_bin = curbuf->b_p_bin;
@@ -804,6 +812,18 @@ static void free_buffer(buf_T *buf)
}
}
+/// Free the b_wininfo list for buffer "buf".
+static void clear_wininfo(buf_T *buf)
+{
+ wininfo_T *wip;
+
+ while (buf->b_wininfo != NULL) {
+ wip = buf->b_wininfo;
+ buf->b_wininfo = wip->wi_next;
+ free_wininfo(wip, buf);
+ }
+}
+
/// Free stuff in the buffer for ":bdel" and when wiping out the buffer.
///
/// @param buf Buffer pointer
@@ -838,18 +858,6 @@ static void free_buffer_stuff(buf_T *buf, int free_flags)
buf_updates_unload(buf, false);
}
-/// Free the b_wininfo list for buffer "buf".
-static void clear_wininfo(buf_T *buf)
-{
- wininfo_T *wip;
-
- while (buf->b_wininfo != NULL) {
- wip = buf->b_wininfo;
- buf->b_wininfo = wip->wi_next;
- free_wininfo(wip, buf);
- }
-}
-
/// Go to another buffer. Handles the result of the ATTENTION dialog.
void goto_buffer(exarg_T *eap, int start, int dir, int count)
{
@@ -1623,7 +1631,7 @@ void enter_buffer(buf_T *buf)
}
curbuf->b_last_used = time(NULL);
- redraw_later(curwin, NOT_VALID);
+ redraw_later(curwin, UPD_NOT_VALID);
}
/// Change to the directory of the current buffer.
@@ -3166,14 +3174,14 @@ void maketitle(void)
use_sandbox = was_set_insecurely(curwin, "titlestring", 0);
build_stl_str_hl(curwin, buf, sizeof(buf),
- (char *)p_titlestring, use_sandbox,
+ p_titlestring, use_sandbox,
0, maxlen, NULL, NULL);
title_str = buf;
if (called_emsg > called_emsg_before) {
set_string_option_direct("titlestring", -1, "", OPT_FREE, SID_ERROR);
}
} else {
- title_str = (char *)p_titlestring;
+ title_str = p_titlestring;
}
} else {
// Format: "fname + (path) (1 of 2) - VIM".
@@ -3280,13 +3288,13 @@ void maketitle(void)
use_sandbox = was_set_insecurely(curwin, "iconstring", 0);
build_stl_str_hl(curwin, icon_str, sizeof(buf),
- (char *)p_iconstring, use_sandbox,
+ p_iconstring, use_sandbox,
0, 0, NULL, NULL);
if (called_emsg > called_emsg_before) {
set_string_option_direct("iconstring", -1, "", OPT_FREE, SID_ERROR);
}
} else {
- icon_str = (char *)p_iconstring;
+ icon_str = p_iconstring;
}
} else {
char *buf_p;
@@ -3826,7 +3834,8 @@ bool bt_terminal(const buf_T *const buf)
}
/// @return true if "buf" is a "nofile", "acwrite", "terminal" or "prompt"
-/// buffer. This means the buffer name is not a file name.
+/// buffer. This means the buffer name may not be a file name,
+/// at least not for writing the buffer.
bool bt_nofilename(const buf_T *const buf)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -3836,6 +3845,17 @@ bool bt_nofilename(const buf_T *const buf)
|| buf->b_p_bt[0] == 'p');
}
+/// @return true if "buf" is a "nofile", "quickfix", "terminal" or "prompt"
+/// buffer. This means the buffer is not to be read from a file.
+static bool bt_nofileread(const buf_T *const buf)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ return buf != NULL && ((buf->b_p_bt[0] == 'n' && buf->b_p_bt[2] == 'f')
+ || buf->b_p_bt[0] == 't'
+ || buf->b_p_bt[0] == 'q'
+ || buf->b_p_bt[0] == 'p');
+}
+
/// @return true if "buf" has 'buftype' set to "nofile".
bool bt_nofile(const buf_T *const buf)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
@@ -4034,7 +4054,7 @@ void buf_signcols_add_check(buf_T *buf, sign_entry_T *added)
buf->b_signcols.max++;
}
buf->b_signcols.size++;
- redraw_buf_later(buf, NOT_VALID);
+ redraw_buf_later(buf, UPD_NOT_VALID);
return;
}
@@ -4055,7 +4075,7 @@ void buf_signcols_add_check(buf_T *buf, sign_entry_T *added)
buf->b_signcols.size = linesum;
buf->b_signcols.max = linesum;
buf->b_signcols.sentinel = added->se_lnum;
- redraw_buf_later(buf, NOT_VALID);
+ redraw_buf_later(buf, UPD_NOT_VALID);
}
}
@@ -4074,7 +4094,7 @@ int buf_signcols(buf_T *buf, int maximum)
if (signcols != buf->b_signcols.size) {
buf->b_signcols.size = signcols;
buf->b_signcols.max = maximum;
- redraw_buf_later(buf, NOT_VALID);
+ redraw_buf_later(buf, UPD_NOT_VALID);
}
buf->b_signcols.valid = true;
@@ -4183,14 +4203,19 @@ void wipe_buffer(buf_T *buf, bool aucmd)
/// @param bufnr Buffer to switch to, or 0 to create a new buffer.
///
/// @see curbufIsChanged()
-void buf_open_scratch(handle_T bufnr, char *bufname)
+///
+/// @return FAIL for failure, OK otherwise
+int buf_open_scratch(handle_T bufnr, char *bufname)
{
- (void)do_ecmd((int)bufnr, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL);
+ if (do_ecmd((int)bufnr, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL) == FAIL) {
+ return FAIL;
+ }
apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf);
(void)setfname(curbuf, bufname, NULL, true);
apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, curbuf);
- set_option_value("bh", 0L, "hide", OPT_LOCAL);
- set_option_value("bt", 0L, "nofile", OPT_LOCAL);
- set_option_value("swf", 0L, NULL, OPT_LOCAL);
+ set_option_value_give_err("bh", 0L, "hide", OPT_LOCAL);
+ set_option_value_give_err("bt", 0L, "nofile", OPT_LOCAL);
+ set_option_value_give_err("swf", 0L, NULL, OPT_LOCAL);
RESET_BINDING(curwin);
+ return OK;
}
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index c9d1efdd56..3d6e1712de 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -116,11 +116,11 @@ typedef uint64_t disptick_T; // display tick type
* The taggy struct is used to store the information about a :tag command.
*/
typedef struct taggy {
- char_u *tagname; // tag name
+ char *tagname; // tag name
fmark_T fmark; // cursor position BEFORE ":tag"
int cur_match; // match number
int cur_fnum; // buffer number used for cur_match
- char_u *user_data; // used with tagfunc
+ char *user_data; // used with tagfunc
} taggy_T;
typedef struct buffblock buffblock_T;
@@ -131,7 +131,7 @@ typedef struct buffheader buffheader_T;
*/
struct buffblock {
buffblock_T *b_next; // pointer to next buffblock
- char_u b_str[1]; // contents (actually longer)
+ char b_str[1]; // contents (actually longer)
};
/*
@@ -159,39 +159,39 @@ typedef struct {
#define w_p_arab w_onebuf_opt.wo_arab // 'arabic'
int wo_bri;
#define w_p_bri w_onebuf_opt.wo_bri // 'breakindent'
- char_u *wo_briopt;
+ char *wo_briopt;
#define w_p_briopt w_onebuf_opt.wo_briopt // 'breakindentopt'
int wo_diff;
#define w_p_diff w_onebuf_opt.wo_diff // 'diff'
- char_u *wo_fdc;
+ char *wo_fdc;
#define w_p_fdc w_onebuf_opt.wo_fdc // 'foldcolumn'
- char_u *wo_fdc_save;
+ char *wo_fdc_save;
#define w_p_fdc_save w_onebuf_opt.wo_fdc_save // 'fdc' saved for diff mode
int wo_fen;
#define w_p_fen w_onebuf_opt.wo_fen // 'foldenable'
int wo_fen_save;
// 'foldenable' saved for diff mode
#define w_p_fen_save w_onebuf_opt.wo_fen_save
- char_u *wo_fdi;
+ char *wo_fdi;
#define w_p_fdi w_onebuf_opt.wo_fdi // 'foldignore'
long wo_fdl;
#define w_p_fdl w_onebuf_opt.wo_fdl // 'foldlevel'
long wo_fdl_save;
// 'foldlevel' state saved for diff mode
#define w_p_fdl_save w_onebuf_opt.wo_fdl_save
- char_u *wo_fdm;
+ char *wo_fdm;
#define w_p_fdm w_onebuf_opt.wo_fdm // 'foldmethod'
- char_u *wo_fdm_save;
+ char *wo_fdm_save;
#define w_p_fdm_save w_onebuf_opt.wo_fdm_save // 'fdm' saved for diff mode
long wo_fml;
#define w_p_fml w_onebuf_opt.wo_fml // 'foldminlines'
long wo_fdn;
#define w_p_fdn w_onebuf_opt.wo_fdn // 'foldnestmax'
- char_u *wo_fde;
+ char *wo_fde;
#define w_p_fde w_onebuf_opt.wo_fde // 'foldexpr'
- char_u *wo_fdt;
+ char *wo_fdt;
#define w_p_fdt w_onebuf_opt.wo_fdt // 'foldtext'
- char_u *wo_fmr;
+ char *wo_fmr;
#define w_p_fmr w_onebuf_opt.wo_fmr // 'foldmarker'
int wo_lbr;
#define w_p_lbr w_onebuf_opt.wo_lbr // 'linebreak'
@@ -201,7 +201,7 @@ typedef struct {
#define w_p_nu w_onebuf_opt.wo_nu // 'number'
int wo_rnu;
#define w_p_rnu w_onebuf_opt.wo_rnu // 'relativenumber'
- char_u *wo_ve;
+ char *wo_ve;
#define w_p_ve w_onebuf_opt.wo_ve // 'virtualedit'
unsigned wo_ve_flags;
#define w_ve_flags w_onebuf_opt.wo_ve_flags // flags for 'virtualedit'
@@ -215,7 +215,7 @@ typedef struct {
#define w_p_pvw w_onebuf_opt.wo_pvw // 'previewwindow'
int wo_rl;
#define w_p_rl w_onebuf_opt.wo_rl // 'rightleft'
- char_u *wo_rlc;
+ char *wo_rlc;
#define w_p_rlc w_onebuf_opt.wo_rlc // 'rightleftcmd'
long wo_scr;
#define w_p_scr w_onebuf_opt.wo_scr // 'scroll'
@@ -225,13 +225,13 @@ typedef struct {
#define w_p_cuc w_onebuf_opt.wo_cuc // 'cursorcolumn'
int wo_cul;
#define w_p_cul w_onebuf_opt.wo_cul // 'cursorline'
- char_u *wo_culopt;
+ char *wo_culopt;
#define w_p_culopt w_onebuf_opt.wo_culopt // 'cursorlineopt'
- char_u *wo_cc;
+ char *wo_cc;
#define w_p_cc w_onebuf_opt.wo_cc // 'colorcolumn'
- char_u *wo_sbr;
+ char *wo_sbr;
#define w_p_sbr w_onebuf_opt.wo_sbr // 'showbreak'
- char_u *wo_stl;
+ char *wo_stl;
#define w_p_stl w_onebuf_opt.wo_stl // 'statusline'
char *wo_wbr;
#define w_p_wbr w_onebuf_opt.wo_wbr // 'winbar'
@@ -245,7 +245,7 @@ typedef struct {
#define w_p_wrap w_onebuf_opt.wo_wrap // 'wrap'
int wo_wrap_save; // 'wrap' state saved for diff mode
#define w_p_wrap_save w_onebuf_opt.wo_wrap_save
- char_u *wo_cocu; // 'concealcursor'
+ char *wo_cocu; // 'concealcursor'
#define w_p_cocu w_onebuf_opt.wo_cocu
long wo_cole; // 'conceallevel'
#define w_p_cole w_onebuf_opt.wo_cole
@@ -253,14 +253,14 @@ typedef struct {
#define w_p_crb w_onebuf_opt.wo_crb // 'cursorbind'
int wo_crb_save; // 'cursorbind' state saved for diff mode
#define w_p_crb_save w_onebuf_opt.wo_crb_save
- char_u *wo_scl;
+ char *wo_scl;
#define w_p_scl w_onebuf_opt.wo_scl // 'signcolumn'
- char_u *wo_winhl;
+ char *wo_winhl;
#define w_p_winhl w_onebuf_opt.wo_winhl // 'winhighlight'
- char_u *wo_fcs;
-#define w_p_fcs w_onebuf_opt.wo_fcs // 'fillchars'
- char_u *wo_lcs;
+ char *wo_lcs;
#define w_p_lcs w_onebuf_opt.wo_lcs // 'listchars'
+ char *wo_fcs;
+#define w_p_fcs w_onebuf_opt.wo_fcs // 'fillchars'
long wo_winbl;
#define w_p_winbl w_onebuf_opt.wo_winbl // 'winblend'
@@ -308,8 +308,8 @@ typedef struct arglist {
//
// TODO(Felipe): move aentry_T to another header
typedef struct argentry {
- char_u *ae_fname; // file name as specified
- int ae_fnum; // buffer number with expanded file name
+ char *ae_fname; // file name as specified
+ int ae_fnum; // buffer number with expanded file name
} aentry_T;
#define ALIST(win) (win)->w_alist
@@ -325,8 +325,8 @@ typedef struct argentry {
* Used for the typeahead buffer: typebuf.
*/
typedef struct {
- char_u *tb_buf; // buffer for typed characters
- char_u *tb_noremap; // mapping flags for characters in tb_buf[]
+ uint8_t *tb_buf; // buffer for typed characters
+ uint8_t *tb_noremap; // mapping flags for characters in tb_buf[]
int tb_buflen; // size of tb_buf[]
int tb_off; // current position in tb_buf[]
int tb_len; // number of valid bytes in tb_buf[]
@@ -352,11 +352,11 @@ typedef struct {
*/
typedef struct mapblock mapblock_T;
struct mapblock {
- mapblock_T *m_next; // next mapblock in list
- char_u *m_keys; // mapped from, lhs
- char_u *m_str; // mapped to, rhs
- char_u *m_orig_str; // rhs as entered by the user
- LuaRef m_luaref; // lua function reference as rhs
+ mapblock_T *m_next; // next mapblock in list
+ uint8_t *m_keys; // mapped from, lhs
+ char *m_str; // mapped to, rhs
+ char *m_orig_str; // rhs as entered by the user
+ LuaRef m_luaref; // lua function reference as rhs
int m_keylen; // strlen(m_keys)
int m_mode; // valid mode
int m_simplified; // m_keys was simplified, do no use this map
@@ -366,8 +366,8 @@ struct mapblock {
char m_nowait; // <nowait> used
char m_expr; // <expr> used, m_str is an expression
sctx_T m_script_ctx; // SCTX where map was defined
- char *m_desc; // description of keymap
- bool m_replace_keycodes; // replace termcodes in lua function
+ char *m_desc; // description of mapping
+ bool m_replace_keycodes; // replace keycodes in result of expression
};
/// Used for highlighting in the status line.
@@ -440,14 +440,14 @@ typedef struct {
garray_T b_syn_clusters; // table for syntax clusters
int b_spell_cluster_id; // @Spell cluster ID or 0
int b_nospell_cluster_id; // @NoSpell cluster ID or 0
- int b_syn_containedin; // TRUE when there is an item with a
+ int b_syn_containedin; // true when there is an item with a
// "containedin" argument
int b_syn_sync_flags; // flags about how to sync
int16_t b_syn_sync_id; // group to sync on
linenr_T b_syn_sync_minlines; // minimal sync lines offset
linenr_T b_syn_sync_maxlines; // maximal sync lines offset
linenr_T b_syn_sync_linebreaks; // offset for multi-line pattern
- char_u *b_syn_linecont_pat; // line continuation pattern
+ char *b_syn_linecont_pat; // line continuation pattern
regprog_T *b_syn_linecont_prog; // line continuation program
syn_time_T b_syn_linecont_time;
int b_syn_linecont_ic; // ignore-case flag for above
@@ -476,17 +476,17 @@ typedef struct {
disptick_T b_sst_lasttick; // last display tick
// for spell checking
- garray_T b_langp; // list of pointers to slang_T, see spell.c
- bool b_spell_ismw[256]; // flags: is midword char
- char_u *b_spell_ismw_mb; // multi-byte midword chars
- char_u *b_p_spc; // 'spellcapcheck'
+ garray_T b_langp; // list of pointers to slang_T, see spell.c
+ bool b_spell_ismw[256]; // flags: is midword char
+ char *b_spell_ismw_mb; // multi-byte midword chars
+ char *b_p_spc; // 'spellcapcheck'
regprog_T *b_cap_prog; // program for 'spellcapcheck'
- char_u *b_p_spf; // 'spellfile'
- char_u *b_p_spl; // 'spelllang'
- char_u *b_p_spo; // 'spelloptions'
- int b_cjk; // all CJK letters as OK
- char_u b_syn_chartab[32]; // syntax iskeyword option
- char_u *b_syn_isk; // iskeyword option
+ char *b_p_spf; // 'spellfile'
+ char *b_p_spl; // 'spelllang'
+ char *b_p_spo; // 'spelloptions'
+ int b_cjk; // all CJK letters as OK
+ uint8_t b_syn_chartab[32]; // syntax iskeyword option
+ char *b_syn_isk; // iskeyword option
} synblock_T;
/// Type used for changedtick_di member in buf_T
@@ -600,7 +600,7 @@ struct file_buffer {
fmark_T b_namedm[NMARKS]; // current named marks (mark.c)
- // These variables are set when VIsual_active becomes FALSE
+ // These variables are set when VIsual_active becomes false
visualinfo_T b_visual;
int b_visual_mode_eval; // b_visual.vi_mode for visualmode()
@@ -653,10 +653,8 @@ struct file_buffer {
time_t b_u_time_cur; // uh_time of header below which we are now
long b_u_save_nr_cur; // file write nr after which we are now
- /*
- * variables for "U" command in undo.c
- */
- char_u *b_u_line_ptr; // saved line for "U" command
+ // variables for "U" command in undo.c
+ char *b_u_line_ptr; // saved line for "U" command
linenr_T b_u_line_lnum; // line number of line in u_line
colnr_T b_u_line_colnr; // optional column number
@@ -686,73 +684,73 @@ struct file_buffer {
int b_p_ai; ///< 'autoindent'
int b_p_ai_nopaste; ///< b_p_ai saved for paste mode
- char_u *b_p_bkc; ///< 'backupco
+ char *b_p_bkc; ///< 'backupco
unsigned int b_bkc_flags; ///< flags for 'backupco
int b_p_ci; ///< 'copyindent'
int b_p_bin; ///< 'binary'
int b_p_bomb; ///< 'bomb'
- char_u *b_p_bh; ///< 'bufhidden'
- char_u *b_p_bt; ///< 'buftype'
+ char *b_p_bh; ///< 'bufhidden'
+ char *b_p_bt; ///< 'buftype'
int b_has_qf_entry; ///< quickfix exists for buffer
int b_p_bl; ///< 'buflisted'
long b_p_channel; ///< 'channel'
int b_p_cin; ///< 'cindent'
- char_u *b_p_cino; ///< 'cinoptions'
- char_u *b_p_cink; ///< 'cinkeys'
- char_u *b_p_cinw; ///< 'cinwords'
- char_u *b_p_cinsd; ///< 'cinscopedecls'
- char_u *b_p_com; ///< 'comments'
- char_u *b_p_cms; ///< 'commentstring'
- char_u *b_p_cpt; ///< 'complete'
+ char *b_p_cino; ///< 'cinoptions'
+ char *b_p_cink; ///< 'cinkeys'
+ char *b_p_cinw; ///< 'cinwords'
+ char *b_p_cinsd; ///< 'cinscopedecls'
+ char *b_p_com; ///< 'comments'
+ char *b_p_cms; ///< 'commentstring'
+ char *b_p_cpt; ///< 'complete'
#ifdef BACKSLASH_IN_FILENAME
- char_u *b_p_csl; ///< 'completeslash'
+ char *b_p_csl; ///< 'completeslash'
#endif
- char_u *b_p_cfu; ///< 'completefunc'
- char_u *b_p_ofu; ///< 'omnifunc'
- char_u *b_p_tfu; ///< 'tagfunc'
- char_u *b_p_urf; ///< 'userregfunc'
+ char *b_p_cfu; ///< 'completefunc'
+ char *b_p_ofu; ///< 'omnifunc'
+ char *b_p_tfu; ///< 'tagfunc'
+ char *b_p_urf; ///< 'userregfunc'
int b_p_eol; ///< 'endofline'
int b_p_fixeol; ///< 'fixendofline'
int b_p_et; ///< 'expandtab'
int b_p_et_nobin; ///< b_p_et saved for binary mode
int b_p_et_nopaste; ///< b_p_et saved for paste mode
- char_u *b_p_fenc; ///< 'fileencoding'
- char_u *b_p_ff; ///< 'fileformat'
- char_u *b_p_ft; ///< 'filetype'
- char_u *b_p_fo; ///< 'formatoptions'
- char_u *b_p_flp; ///< 'formatlistpat'
+ char *b_p_fenc; ///< 'fileencoding'
+ char *b_p_ff; ///< 'fileformat'
+ char *b_p_ft; ///< 'filetype'
+ char *b_p_fo; ///< 'formatoptions'
+ char *b_p_flp; ///< 'formatlistpat'
int b_p_inf; ///< 'infercase'
- char_u *b_p_isk; ///< 'iskeyword'
- char_u *b_p_def; ///< 'define' local value
- char_u *b_p_inc; ///< 'include'
- char_u *b_p_inex; ///< 'includeexpr'
+ char *b_p_isk; ///< 'iskeyword'
+ char *b_p_def; ///< 'define' local value
+ char *b_p_inc; ///< 'include'
+ char *b_p_inex; ///< 'includeexpr'
uint32_t b_p_inex_flags; ///< flags for 'includeexpr'
- char_u *b_p_inde; ///< 'indentexpr'
+ char *b_p_inde; ///< 'indentexpr'
uint32_t b_p_inde_flags; ///< flags for 'indentexpr'
- char_u *b_p_indk; ///< 'indentkeys'
- char_u *b_p_fp; ///< 'formatprg'
- char_u *b_p_fex; ///< 'formatexpr'
+ char *b_p_indk; ///< 'indentkeys'
+ char *b_p_fp; ///< 'formatprg'
+ char *b_p_fex; ///< 'formatexpr'
uint32_t b_p_fex_flags; ///< flags for 'formatexpr'
- char_u *b_p_kp; ///< 'keywordprg'
+ char *b_p_kp; ///< 'keywordprg'
int b_p_lisp; ///< 'lisp'
- char_u *b_p_menc; ///< 'makeencoding'
- char_u *b_p_mps; ///< 'matchpairs'
+ char *b_p_menc; ///< 'makeencoding'
+ char *b_p_mps; ///< 'matchpairs'
int b_p_ml; ///< 'modeline'
int b_p_ml_nobin; ///< b_p_ml saved for binary mode
int b_p_ma; ///< 'modifiable'
- char_u *b_p_nf; ///< 'nrformats'
+ char *b_p_nf; ///< 'nrformats'
int b_p_pi; ///< 'preserveindent'
- char_u *b_p_qe; ///< 'quoteescape'
+ char *b_p_qe; ///< 'quoteescape'
int b_p_ro; ///< 'readonly'
long b_p_sw; ///< 'shiftwidth'
long b_p_scbk; ///< 'scrollback'
int b_p_si; ///< 'smartindent'
long b_p_sts; ///< 'softtabstop'
long b_p_sts_nopaste; ///< b_p_sts saved for paste mode
- char_u *b_p_sua; ///< 'suffixesadd'
+ char *b_p_sua; ///< 'suffixesadd'
int b_p_swf; ///< 'swapfile'
long b_p_smc; ///< 'synmaxcol'
- char_u *b_p_syn; ///< 'syntax'
+ char *b_p_syn; ///< 'syntax'
long b_p_ts; ///< 'tabstop'
long b_p_tw; ///< 'textwidth'
long b_p_tw_nobin; ///< b_p_tw saved for binary mode
@@ -760,29 +758,29 @@ struct file_buffer {
long b_p_wm; ///< 'wrapmargin'
long b_p_wm_nobin; ///< b_p_wm saved for binary mode
long b_p_wm_nopaste; ///< b_p_wm saved for paste mode
- char_u *b_p_vsts; ///< 'varsofttabstop'
- long *b_p_vsts_array; ///< 'varsofttabstop' in internal format
- char_u *b_p_vsts_nopaste; ///< b_p_vsts saved for paste mode
- char_u *b_p_vts; ///< 'vartabstop'
- long *b_p_vts_array; ///< 'vartabstop' in internal format
- char_u *b_p_keymap; ///< 'keymap'
+ char *b_p_vsts; ///< 'varsofttabstop'
+ long *b_p_vsts_array; ///< 'varsofttabstop' in internal format
+ char *b_p_vsts_nopaste; ///< b_p_vsts saved for paste mode
+ char *b_p_vts; ///< 'vartabstop'
+ long *b_p_vts_array; ///< 'vartabstop' in internal format
+ char *b_p_keymap; ///< 'keymap'
// local values for options which are normally global
- char_u *b_p_gp; ///< 'grepprg' local value
- char_u *b_p_mp; ///< 'makeprg' local value
- char_u *b_p_efm; ///< 'errorformat' local value
- char_u *b_p_ep; ///< 'equalprg' local value
- char_u *b_p_path; ///< 'path' local value
+ char *b_p_gp; ///< 'grepprg' local value
+ char *b_p_mp; ///< 'makeprg' local value
+ char *b_p_efm; ///< 'errorformat' local value
+ char *b_p_ep; ///< 'equalprg' local value
+ char *b_p_path; ///< 'path' local value
int b_p_ar; ///< 'autoread' local value
- char_u *b_p_tags; ///< 'tags' local value
- char_u *b_p_tc; ///< 'tagcase' local value
+ char *b_p_tags; ///< 'tags' local value
+ char *b_p_tc; ///< 'tagcase' local value
unsigned b_tc_flags; ///< flags for 'tagcase'
- char_u *b_p_dict; ///< 'dictionary' local value
- char_u *b_p_tsr; ///< 'thesaurus' local value
- char_u *b_p_tsrfu; ///< 'thesaurusfunc' local value
+ char *b_p_dict; ///< 'dictionary' local value
+ char *b_p_tsr; ///< 'thesaurus' local value
+ char *b_p_tsrfu; ///< 'thesaurusfunc' local value
long b_p_ul; ///< 'undolevels' local value
int b_p_udf; ///< 'undofile'
- char_u *b_p_lw; ///< 'lispwords' local value
+ char *b_p_lw; ///< 'lispwords' local value
// end of buffer options
@@ -850,7 +848,7 @@ struct file_buffer {
* spell buffer - used for spell info, never displayed and doesn't have a
* file name.
*/
- bool b_help; // TRUE for help file buffer (when set b_p_bt
+ bool b_help; // true for help file buffer (when set b_p_bt
// is "help")
bool b_spell; // True for a spell file buffer, most fields
// are not used! Use the B_SPELL macro to
@@ -975,15 +973,15 @@ struct tabpage_S {
* When the display is changed (e.g., when clearing the screen) w_lines_valid
* is changed to exclude invalid entries.
* When making changes to the buffer, wl_valid is reset to indicate wl_size
- * may not reflect what is actually in the buffer. When wl_valid is FALSE,
+ * may not reflect what is actually in the buffer. When wl_valid is false,
* the entries can only be used to count the number of displayed lines used.
* wl_lnum and wl_lastlnum are invalid too.
*/
typedef struct w_line {
linenr_T wl_lnum; // buffer line number for logical line
uint16_t wl_size; // height in screen lines
- char wl_valid; // TRUE values are valid for text in buffer
- char wl_folded; // TRUE when this is a range of folded lines
+ char wl_valid; // true values are valid for text in buffer
+ char wl_folded; // true when this is a range of folded lines
linenr_T wl_lastlnum; // last buffer line number for logical line
} wline_T;
@@ -1230,8 +1228,8 @@ struct window_S {
*/
linenr_T w_topline; /* buffer line number of the line at the
top of the window */
- char w_topline_was_set; /* flag set to TRUE when topline is set,
- e.g. by winrestview() */
+ char w_topline_was_set; // flag set to true when topline is set,
+ // e.g. by winrestview()
int w_topfill; // number of filler lines above w_topline
int w_old_topfill; // w_topfill at last redraw
bool w_botfill; // true when filler lines are actually
@@ -1243,9 +1241,10 @@ struct window_S {
colnr_T w_skipcol; // starting column when a single line
// doesn't fit in the window
- // four fields that are only used when there is a WinScrolled autocommand
+ // five fields that are only used when there is a WinScrolled autocommand
linenr_T w_last_topline; ///< last known value for w_topline
colnr_T w_last_leftcol; ///< last known value for w_leftcol
+ colnr_T w_last_skipcol; ///< last known value for w_skipcol
int w_last_width; ///< last known value for w_width
int w_last_height; ///< last known value for w_height
@@ -1354,7 +1353,7 @@ struct window_S {
int w_redr_type; // type of redraw to be performed on win
int w_upd_rows; // number of window lines to update when
- // w_redr_type is REDRAW_TOP
+ // w_redr_type is UPD_REDRAW_TOP
linenr_T w_redraw_top; // when != 0: first line needing redraw
linenr_T w_redraw_bot; // when != 0: last line needing redraw
bool w_redr_status; // if true statusline/winbar must be redrawn
@@ -1366,7 +1365,7 @@ struct window_S {
linenr_T w_ru_topline; // topline shown in ruler
linenr_T w_ru_line_count; // line count used for ruler
int w_ru_topfill; // topfill shown in ruler
- char w_ru_empty; // TRUE if ruler shows 0-1 (empty line)
+ char w_ru_empty; // true if ruler shows 0-1 (empty line)
int w_alt_fnum; // alternate file (for # and CTRL-^)
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 5184dc0689..85ab92e49b 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -26,6 +26,7 @@
#include "nvim/plines.h"
#include "nvim/search.h"
#include "nvim/state.h"
+#include "nvim/textformat.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
@@ -96,8 +97,7 @@ void changed(void)
// Create a swap file if that is wanted.
// Don't do this for "nofile" and "nowrite" buffer types.
- if (curbuf->b_may_swap
- && !bt_dontwrite(curbuf)) {
+ if (curbuf->b_may_swap && !bt_dontwrite(curbuf)) {
bool save_need_wait_return = need_wait_return;
need_wait_return = false;
@@ -223,8 +223,8 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T
FOR_ALL_TAB_WINDOWS(tp, wp) {
if (wp->w_buffer == curbuf) {
// Mark this window to be redrawn later.
- if (wp->w_redr_type < VALID) {
- wp->w_redr_type = VALID;
+ if (wp->w_redr_type < UPD_VALID) {
+ wp->w_redr_type = UPD_VALID;
}
// Check if a change in the buffer has invalidated the cached
@@ -301,17 +301,17 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T
// requires a redraw.
if (wp->w_p_rnu && xtra != 0) {
wp->w_last_cursor_lnum_rnu = 0;
- redraw_later(wp, VALID);
+ redraw_later(wp, UPD_VALID);
}
// Cursor line highlighting probably need to be updated with
- // "VALID" if it's below the change.
+ // "UPD_VALID" if it's below the change.
// If the cursor line is inside the change we need to redraw more.
if (wp->w_p_cul) {
if (xtra == 0) {
- redraw_later(wp, VALID);
+ redraw_later(wp, UPD_VALID);
} else if (lnum <= wp->w_last_cursorline) {
- redraw_later(wp, SOME_VALID);
+ redraw_later(wp, UPD_SOME_VALID);
}
}
}
@@ -319,8 +319,8 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T
// Call update_screen() later, which checks out what needs to be redrawn,
// since it notices b_mod_set and then uses b_mod_*.
- if (must_redraw < VALID) {
- must_redraw = VALID;
+ if (must_redraw < UPD_VALID) {
+ must_redraw = UPD_VALID;
}
// when the cursor line is changed always trigger CursorMoved
@@ -364,7 +364,7 @@ void changed_bytes(linenr_T lnum, colnr_T col)
if (curwin->w_p_diff) {
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_p_diff && wp != curwin) {
- redraw_later(wp, VALID);
+ redraw_later(wp, UPD_VALID);
linenr_T wlnum = diff_lnum_win(lnum, wp);
if (wlnum > 0) {
changedOneline(wp->w_buffer, wlnum);
@@ -493,7 +493,7 @@ void changed_lines(linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T xtra, bo
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_p_diff && wp != curwin) {
- redraw_later(wp, VALID);
+ redraw_later(wp, UPD_VALID);
wlnum = diff_lnum_win(lnum, wp);
if (wlnum > 0) {
changed_lines_buf(wp->w_buffer, wlnum,
@@ -534,21 +534,72 @@ void unchanged(buf_T *buf, int ff, bool always_inc_changedtick)
}
}
+/// Save the current values of 'fileformat' and 'fileencoding', so that we know
+/// the file must be considered changed when the value is different.
+void save_file_ff(buf_T *buf)
+{
+ buf->b_start_ffc = (unsigned char)(*buf->b_p_ff);
+ buf->b_start_eol = buf->b_p_eol;
+ buf->b_start_bomb = buf->b_p_bomb;
+
+ // Only use free/alloc when necessary, they take time.
+ if (buf->b_start_fenc == NULL
+ || STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0) {
+ xfree(buf->b_start_fenc);
+ buf->b_start_fenc = xstrdup(buf->b_p_fenc);
+ }
+}
+
+/// Return true if 'fileformat' and/or 'fileencoding' has a different value
+/// from when editing started (save_file_ff() called).
+/// Also when 'endofline' was changed and 'binary' is set, or when 'bomb' was
+/// changed and 'binary' is not set.
+/// Also when 'endofline' was changed and 'fixeol' is not set.
+/// When "ignore_empty" is true don't consider a new, empty buffer to be
+/// changed.
+bool file_ff_differs(buf_T *buf, bool ignore_empty)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ // In a buffer that was never loaded the options are not valid.
+ if (buf->b_flags & BF_NEVERLOADED) {
+ return false;
+ }
+ if (ignore_empty
+ && (buf->b_flags & BF_NEW)
+ && buf->b_ml.ml_line_count == 1
+ && *ml_get_buf(buf, (linenr_T)1, false) == NUL) {
+ return false;
+ }
+ if (buf->b_start_ffc != *buf->b_p_ff) {
+ return true;
+ }
+ if ((buf->b_p_bin || !buf->b_p_fixeol) && buf->b_start_eol != buf->b_p_eol) {
+ return true;
+ }
+ if (!buf->b_p_bin && buf->b_start_bomb != buf->b_p_bomb) {
+ return true;
+ }
+ if (buf->b_start_fenc == NULL) {
+ return *buf->b_p_fenc != NUL;
+ }
+ return STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0;
+}
+
/// Insert string "p" at the cursor position. Stops at a NUL byte.
/// Handles Replace mode and multi-byte characters.
-void ins_bytes(char_u *p)
+void ins_bytes(char *p)
{
ins_bytes_len(p, STRLEN(p));
}
/// Insert string "p" with length "len" at the cursor position.
/// Handles Replace mode and multi-byte characters.
-void ins_bytes_len(char_u *p, size_t len)
+void ins_bytes_len(char *p, size_t len)
{
size_t n;
for (size_t i = 0; i < len; i += n) {
// avoid reading past p[len]
- n = (size_t)utfc_ptr2len_len(p + i, (int)(len - i));
+ n = (size_t)utfc_ptr2len_len((char_u *)p + i, (int)(len - i));
ins_char_bytes(p + i, n);
}
}
@@ -560,18 +611,18 @@ void ins_bytes_len(char_u *p, size_t len)
/// convert bytes to a character.
void ins_char(int c)
{
- char_u buf[MB_MAXBYTES + 1];
- size_t n = (size_t)utf_char2bytes(c, (char *)buf);
+ char buf[MB_MAXBYTES + 1];
+ size_t n = (size_t)utf_char2bytes(c, buf);
// When "c" is 0x100, 0x200, etc. we don't want to insert a NUL byte.
// Happens for CTRL-Vu9900.
if (buf[0] == 0) {
buf[0] = '\n';
}
- ins_char_bytes((char_u *)buf, n);
+ ins_char_bytes(buf, n);
}
-void ins_char_bytes(char_u *buf, size_t charlen)
+void ins_char_bytes(char *buf, size_t charlen)
{
// Break tabs if needed.
if (virtual_active() && curwin->w_cursor.coladd > 0) {
@@ -580,7 +631,7 @@ void ins_char_bytes(char_u *buf, size_t charlen)
size_t col = (size_t)curwin->w_cursor.col;
linenr_T lnum = curwin->w_cursor.lnum;
- char_u *oldp = ml_get(lnum);
+ char *oldp = (char *)ml_get(lnum);
size_t linelen = STRLEN(oldp) + 1; // length of old line including NUL
// The lengths default to the values for when not replacing.
@@ -610,7 +661,7 @@ void ins_char_bytes(char_u *buf, size_t charlen)
if (vcol > new_vcol && oldp[col + oldlen] == TAB) {
break;
}
- oldlen += (size_t)utfc_ptr2len((char *)oldp + col + oldlen);
+ oldlen += (size_t)utfc_ptr2len(oldp + col + oldlen);
// Deleted a bit too much, insert spaces.
if (vcol > new_vcol) {
newlen += (size_t)(vcol - new_vcol);
@@ -619,7 +670,7 @@ void ins_char_bytes(char_u *buf, size_t charlen)
curwin->w_p_list = old_list;
} else if (oldp[col] != NUL) {
// normal replace
- oldlen = (size_t)utfc_ptr2len((char *)oldp + col);
+ oldlen = (size_t)utfc_ptr2len(oldp + col);
}
// Push the replaced bytes onto the replace stack, so that they can be
@@ -632,7 +683,7 @@ void ins_char_bytes(char_u *buf, size_t charlen)
}
}
- char_u *newp = xmalloc(linelen + newlen - oldlen);
+ char *newp = xmalloc(linelen + newlen - oldlen);
// Copy bytes before the cursor.
if (col > 0) {
@@ -640,7 +691,7 @@ void ins_char_bytes(char_u *buf, size_t charlen)
}
// Copy bytes after the changed character(s).
- char_u *p = newp + col;
+ char *p = newp + col;
if (linelen > col + oldlen) {
memmove(p + newlen, oldp + col + oldlen,
(size_t)(linelen - col - oldlen));
@@ -655,7 +706,7 @@ void ins_char_bytes(char_u *buf, size_t charlen)
}
// Replace the line in the buffer.
- ml_replace(lnum, (char *)newp, false);
+ ml_replace(lnum, newp, false);
// mark the buffer as changed and prepare for displaying
inserted_bytes(lnum, (colnr_T)col, (int)oldlen, (int)newlen);
@@ -665,7 +716,7 @@ void ins_char_bytes(char_u *buf, size_t charlen)
if (p_sm && (State & MODE_INSERT)
&& msg_silent == 0
&& !ins_compl_active()) {
- showmatch(utf_ptr2char((char *)buf));
+ showmatch(utf_ptr2char(buf));
}
if (!p_ri || (State & REPLACE_FLAG)) {
@@ -678,7 +729,7 @@ void ins_char_bytes(char_u *buf, size_t charlen)
/// Insert a string at the cursor position.
/// Note: Does NOT handle Replace mode.
/// Caller must have prepared for undo.
-void ins_str(char_u *s)
+void ins_str(char *s)
{
int newlen = (int)STRLEN(s);
linenr_T lnum = curwin->w_cursor.lnum;
@@ -688,10 +739,10 @@ void ins_str(char_u *s)
}
colnr_T col = curwin->w_cursor.col;
- char_u *oldp = ml_get(lnum);
+ char *oldp = (char *)ml_get(lnum);
int oldlen = (int)STRLEN(oldp);
- char_u *newp = (char_u *)xmalloc((size_t)oldlen + (size_t)newlen + 1);
+ char *newp = xmalloc((size_t)oldlen + (size_t)newlen + 1);
if (col > 0) {
memmove(newp, oldp, (size_t)col);
}
@@ -699,7 +750,7 @@ void ins_str(char_u *s)
int bytes = oldlen - col + 1;
assert(bytes >= 0);
memmove(newp + col + newlen, oldp + col, (size_t)bytes);
- ml_replace(lnum, (char *)newp, false);
+ ml_replace(lnum, newp, false);
inserted_bytes(lnum, col, 0, newlen);
curwin->w_cursor.col += newlen;
}
@@ -723,9 +774,9 @@ int del_char(bool fixpos)
int del_chars(long count, int fixpos)
{
int bytes = 0;
- char_u *p = get_cursor_pos_ptr();
+ char *p = (char *)get_cursor_pos_ptr();
for (long i = 0; i < count && *p != NUL; i++) {
- int l = utfc_ptr2len((char *)p);
+ int l = utfc_ptr2len(p);
bytes += l;
p += l;
}
@@ -746,7 +797,7 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine)
linenr_T lnum = curwin->w_cursor.lnum;
colnr_T col = curwin->w_cursor.col;
bool fixpos = fixpos_arg;
- char_u *oldp = ml_get(lnum);
+ char *oldp = (char *)ml_get(lnum);
colnr_T oldlen = (colnr_T)STRLEN(oldp);
// Can't do anything when the cursor is on the NUL after the line.
@@ -766,7 +817,7 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine)
// If 'delcombine' is set and deleting (less than) one character, only
// delete the last combining character.
if (p_deco && use_delcombine
- && utfc_ptr2len((char *)oldp + col) >= count) {
+ && utfc_ptr2len(oldp + col) >= count) {
int cc[MAX_MCO];
(void)utfc_ptr2char(oldp + col, cc);
@@ -775,9 +826,9 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine)
int n = col;
do {
col = n;
- count = utf_ptr2len((char *)oldp + n);
+ count = utf_ptr2len(oldp + n);
n += count;
- } while (utf_composinglike(oldp + col, oldp + n));
+ } while (utf_composinglike((char_u *)oldp + col, (char_u *)oldp + n));
fixpos = false;
}
}
@@ -792,7 +843,7 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine)
&& (get_ve_flags() & VE_ONEMORE) == 0) {
curwin->w_cursor.col--;
curwin->w_cursor.coladd = 0;
- curwin->w_cursor.col -= utf_head_off(oldp, oldp + curwin->w_cursor.col);
+ curwin->w_cursor.col -= utf_head_off((char_u *)oldp, (char_u *)oldp + curwin->w_cursor.col);
}
count = oldlen - col;
movelen = 1;
@@ -801,7 +852,7 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine)
// If the old line has been allocated the deletion can be done in the
// existing line. Otherwise a new line has to be allocated.
bool was_alloced = ml_line_alloced(); // check if oldp was allocated
- char_u *newp;
+ char *newp;
if (was_alloced) {
ml_add_deleted_len(curbuf->b_ml.ml_line_ptr, oldlen);
newp = oldp; // use same allocated memory
@@ -811,7 +862,7 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine)
}
memmove(newp + col, oldp + col + count, (size_t)movelen);
if (!was_alloced) {
- ml_replace(lnum, (char *)newp, false);
+ ml_replace(lnum, newp, false);
}
// mark the buffer as changed and prepare for displaying
@@ -823,10 +874,10 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine)
/// Copy the indent from ptr to the current line (and fill to size).
/// Leaves the cursor on the first non-blank in the line.
/// @return true if the line was changed.
-int copy_indent(int size, char_u *src)
+int copy_indent(int size, char *src)
{
- char_u *p = NULL;
- char_u *line = NULL;
+ char *p = NULL;
+ char *line = NULL;
int ind_len;
int line_len = 0;
int tab_pad;
@@ -838,7 +889,7 @@ int copy_indent(int size, char_u *src)
ind_len = 0;
int ind_done = 0;
int ind_col = 0;
- char_u *s = src;
+ char *s = src;
// Count/copy the usable portion of the source line.
while (todo > 0 && ascii_iswhite(*s)) {
@@ -924,7 +975,7 @@ int copy_indent(int size, char_u *src)
memmove(p, get_cursor_line_ptr(), (size_t)line_len);
// Replace the line
- ml_replace(curwin->w_cursor.lnum, (char *)line, false);
+ ml_replace(curwin->w_cursor.lnum, line, false);
// Put the cursor after the indent.
curwin->w_cursor.col = ind_len;
@@ -955,8 +1006,8 @@ int copy_indent(int size, char_u *src)
/// @return true on success, false on failure
int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
{
- char_u *next_line = NULL; // copy of the next line
- char_u *p_extra = NULL; // what goes to next line
+ char *next_line = NULL; // copy of the next line
+ char *p_extra = NULL; // what goes to next line
colnr_T less_cols = 0; // less columns for mark in new line
colnr_T less_cols_off = 0; // columns to skip for mark adjust
pos_T old_cursor; // old cursor position
@@ -969,9 +1020,9 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
int comment_start = 0; // start index of the comment leader
char *lead_flags; // position in 'comments' for comment leader
char *leader = NULL; // copy of comment leader
- char_u *allocated = NULL; // allocated memory
+ char *allocated = NULL; // allocated memory
char *p;
- char_u saved_char = NUL; // init for GCC
+ char saved_char = NUL; // init for GCC
pos_T *pos;
bool do_si = may_do_si();
bool do_cindent;
@@ -985,7 +1036,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
colnr_T mincol = curwin->w_cursor.col + 1;
// make a copy of the current line so we can mess with it
- char_u *saved_line = vim_strsave(get_cursor_line_ptr());
+ char *saved_line = (char *)vim_strsave(get_cursor_line_ptr());
if (State & VREPLACE_FLAG) {
// With MODE_VREPLACE we make a copy of the next line, which we will be
@@ -996,9 +1047,9 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
// the line, replacing what was there before and pushing the right
// stuff onto the replace stack. -- webb.
if (curwin->w_cursor.lnum < orig_line_count) {
- next_line = vim_strsave(ml_get(curwin->w_cursor.lnum + 1));
+ next_line = (char *)vim_strsave(ml_get(curwin->w_cursor.lnum + 1));
} else {
- next_line = vim_strsave((char_u *)"");
+ next_line = xstrdup("");
}
// In MODE_VREPLACE state, a NL replaces the rest of the line, and
@@ -1008,9 +1059,9 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
// autoindent etc) a bit later.
replace_push(NUL); // Call twice because BS over NL expects it
replace_push(NUL);
- p = (char *)saved_line + curwin->w_cursor.col;
+ p = saved_line + curwin->w_cursor.col;
while (*p != NUL) {
- p += replace_push_mb((char_u *)p);
+ p += replace_push_mb(p);
}
saved_line[curwin->w_cursor.col] = NUL;
}
@@ -1018,7 +1069,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
if ((State & MODE_INSERT) && (State & VREPLACE_FLAG) == 0) {
p_extra = saved_line + curwin->w_cursor.col;
if (do_si) { // need first char after new line break
- p = skipwhite((char *)p_extra);
+ p = skipwhite(p_extra);
first_char = (unsigned char)(*p);
}
extra_len = (int)STRLEN(p_extra);
@@ -1058,7 +1109,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
char *ptr;
old_cursor = curwin->w_cursor;
- ptr = (char *)saved_line;
+ ptr = saved_line;
if (flags & OPENLINE_DO_COM) {
lead_len = get_leader_len(ptr, NULL, false, true);
} else {
@@ -1142,7 +1193,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
// Don't do this if the previous line ended in ';' or
// '}'.
} else if (last_char != ';' && last_char != '}'
- && cin_is_cinword((char_u *)ptr)) {
+ && cin_is_cinword(ptr)) {
did_si = true;
}
}
@@ -1192,13 +1243,13 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
// This may then be inserted in front of the new line.
end_comment_pending = NUL;
if (flags & OPENLINE_DO_COM) {
- lead_len = get_leader_len((char *)saved_line, &lead_flags, dir == BACKWARD, true);
+ lead_len = get_leader_len(saved_line, &lead_flags, dir == BACKWARD, true);
if (lead_len == 0 && curbuf->b_p_cin && do_cindent && dir == FORWARD
&& (!has_format_option(FO_NO_OPEN_COMS) || (flags & OPENLINE_FORMAT))) {
// Check for a line comment after code.
comment_start = check_linecomment(saved_line);
if (comment_start != MAXCOL) {
- lead_len = get_leader_len((char *)saved_line + comment_start, &lead_flags, false, true);
+ lead_len = get_leader_len(saved_line + comment_start, &lead_flags, false, true);
if (lead_len != 0) {
lead_len += comment_start;
if (did_do_comment != NULL) {
@@ -1213,13 +1264,13 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
if (lead_len > 0) {
char *lead_repl = NULL; // replaces comment leader
int lead_repl_len = 0; // length of *lead_repl
- char_u lead_middle[COM_MAX_LEN]; // middle-comment string
- char_u lead_end[COM_MAX_LEN]; // end-comment string
- char_u *comment_end = NULL; // where lead_end has been found
+ char lead_middle[COM_MAX_LEN]; // middle-comment string
+ char lead_end[COM_MAX_LEN]; // end-comment string
+ char *comment_end = NULL; // where lead_end has been found
int extra_space = false; // append extra space
int current_flag;
int require_blank = false; // requires blank after middle
- char_u *p2;
+ char *p2;
// If the comment leader has the start, middle or end flag, it may not
// be used or may be replaced with the middle leader.
@@ -1261,15 +1312,15 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
size_t n = copy_option_part(&p, (char *)lead_end, COM_MAX_LEN, ",");
if (end_comment_pending == -1) { // we can set it now
- end_comment_pending = lead_end[n - 1];
+ end_comment_pending = (unsigned char)lead_end[n - 1];
}
// If the end of the comment is in the same line, don't use
// the comment leader.
if (dir == FORWARD) {
- for (p = (char *)saved_line + lead_len; *p; p++) {
+ for (p = saved_line + lead_len; *p; p++) {
if (STRNCMP(p, lead_end, n) == 0) {
- comment_end = (char_u *)p;
+ comment_end = p;
lead_len = 0;
break;
}
@@ -1302,17 +1353,17 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
// Remember where the end is, might want to use it to find the
// start (for C-comments).
if (dir == FORWARD) {
- comment_end = (char_u *)skipwhite((char *)saved_line);
+ comment_end = skipwhite(saved_line);
lead_len = 0;
break;
}
// Doing "O" on the end of a comment inserts the middle leader.
// Find the string for the middle leader, searching backwards.
- while (p > (char *)curbuf->b_p_com && *p != ',') {
+ while (p > curbuf->b_p_com && *p != ',') {
p--;
}
- for (lead_repl = p; lead_repl > (char *)curbuf->b_p_com
+ for (lead_repl = p; lead_repl > curbuf->b_p_com
&& lead_repl[-1] != ':'; lead_repl--) {}
lead_repl_len = (int)(p - lead_repl);
@@ -1321,7 +1372,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
extra_space = true;
// Check whether we allow automatic ending of comments
- for (p2 = (char_u *)p; *p2 && *p2 != ':'; p2++) {
+ for (p2 = p; *p2 && *p2 != ':'; p2++) {
if (*p2 == COM_AUTO_END) {
end_comment_pending = -1; // means we want to set it
}
@@ -1331,7 +1382,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
while (*p2 && *p2 != ',') {
p2++;
}
- end_comment_pending = p2[-1];
+ end_comment_pending = (unsigned char)p2[-1];
}
break;
}
@@ -1357,7 +1408,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
+ 1;
assert(bytes >= 0);
leader = xmalloc((size_t)bytes);
- allocated = (char_u *)leader; // remember to free it later
+ allocated = leader; // remember to free it later
STRLCPY(leader, saved_line, lead_len + 1);
@@ -1391,7 +1442,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
// Compute the length of the replaced characters in
// screen characters, not bytes.
{
- int repl_size = vim_strnsize((char_u *)lead_repl, lead_repl_len);
+ int repl_size = vim_strnsize(lead_repl, lead_repl_len);
int old_size = 0;
char *endp = p;
int l;
@@ -1436,13 +1487,13 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
// screen characters, not bytes. Move the part that is
// not to be overwritten.
{
- int repl_size = vim_strnsize((char_u *)lead_repl, lead_repl_len);
+ int repl_size = vim_strnsize(lead_repl, lead_repl_len);
int i;
int l;
for (i = 0; i < lead_len && p[i] != NUL; i += l) {
l = utfc_ptr2len(p + i);
- if (vim_strnsize((char_u *)p, i + l) > repl_size) {
+ if (vim_strnsize(p, i + l) > repl_size) {
break;
}
}
@@ -1485,7 +1536,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
// Recompute the indent, it may have changed.
if (curbuf->b_p_ai || do_si) {
- newindent = get_indent_str_vtab((char_u *)leader,
+ newindent = get_indent_str_vtab(leader,
curbuf->b_p_ts,
curbuf->b_p_vts_array, false);
}
@@ -1568,7 +1619,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
}
if (curbuf->b_p_ai || (flags & OPENLINE_DELSPACES)) {
while ((*p_extra == ' ' || *p_extra == '\t')
- && !utf_iscomposing(utf_ptr2char((char *)p_extra + 1))) {
+ && !utf_iscomposing(utf_ptr2char(p_extra + 1))) {
if (REPLACE_NORMAL(State)) {
replace_push(*p_extra);
}
@@ -1582,7 +1633,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
}
if (p_extra == NULL) {
- p_extra = (char_u *)""; // append empty line
+ p_extra = ""; // append empty line
}
// concatenate leader and p_extra, if there is a leader
@@ -1602,7 +1653,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
}
}
STRCAT(leader, p_extra);
- p_extra = (char_u *)leader;
+ p_extra = leader;
did_ai = true; // So truncating blanks works with comments
less_cols -= lead_len;
} else {
@@ -1615,7 +1666,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
curwin->w_cursor.lnum--;
}
if ((State & VREPLACE_FLAG) == 0 || old_cursor.lnum >= orig_line_count) {
- if (ml_append(curwin->w_cursor.lnum, (char *)p_extra, (colnr_T)0, false) == FAIL) {
+ if (ml_append(curwin->w_cursor.lnum, p_extra, (colnr_T)0, false) == FAIL) {
goto theend;
}
// Postpone calling changed_lines(), because it would mess up folding
@@ -1637,7 +1688,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
(void)u_save_cursor(); // errors are ignored!
vr_lines_changed++;
}
- ml_replace(curwin->w_cursor.lnum, (char *)p_extra, true);
+ ml_replace(curwin->w_cursor.lnum, p_extra, true);
changed_bytes(curwin->w_cursor.lnum, 0);
// TODO(vigoux): extmark_splice_cols here??
curwin->w_cursor.lnum--;
@@ -1702,7 +1753,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
if (trunc_line && !(flags & OPENLINE_KEEPTRAIL)) {
truncate_spaces(saved_line);
}
- ml_replace(curwin->w_cursor.lnum, (char *)saved_line, false);
+ ml_replace(curwin->w_cursor.lnum, saved_line, false);
int new_len = (int)STRLEN(saved_line);
@@ -1787,10 +1838,10 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
// stuff onto the replace stack (via ins_char()).
if (State & VREPLACE_FLAG) {
// Put new line in p_extra
- p_extra = vim_strsave(get_cursor_line_ptr());
+ p_extra = (char *)vim_strsave(get_cursor_line_ptr());
// Put back original line
- ml_replace(curwin->w_cursor.lnum, (char *)next_line, false);
+ ml_replace(curwin->w_cursor.lnum, next_line, false);
// Insert new stuff into line again
curwin->w_cursor.col = 0;
@@ -1814,16 +1865,16 @@ theend:
/// If "fixpos" is true fix the cursor position when done.
void truncate_line(int fixpos)
{
- char_u *newp;
+ char *newp;
linenr_T lnum = curwin->w_cursor.lnum;
colnr_T col = curwin->w_cursor.col;
if (col == 0) {
- newp = vim_strsave((char_u *)"");
+ newp = xstrdup("");
} else {
- newp = vim_strnsave(ml_get(lnum), (size_t)col);
+ newp = (char *)vim_strnsave(ml_get(lnum), (size_t)col);
}
- ml_replace(lnum, (char *)newp, false);
+ ml_replace(lnum, newp, false);
// mark the buffer as changed and prepare for displaying
changed_bytes(lnum, curwin->w_cursor.col);
@@ -1900,7 +1951,7 @@ int get_leader_len(char *line, char **flags, bool backward, bool include_space)
while (line[i] != NUL) {
// scan through the 'comments' option for a match
int found_one = false;
- for (list = (char *)curbuf->b_p_com; *list;) {
+ for (list = curbuf->b_p_com; *list;) {
// Get one option part into part_buf[]. Advance "list" to next
// one. Put "string" at start of string.
if (!got_com && flags != NULL) {
@@ -2037,7 +2088,7 @@ int get_last_leader_offset(char *line, char **flags)
while (--i >= lower_check_bound) {
// scan through the 'comments' option for a match
int found_one = false;
- for (list = (char *)curbuf->b_p_com; *list;) {
+ for (list = curbuf->b_p_com; *list;) {
char *flags_save = list;
// Get one option part into part_buf[]. Advance list to next one.
@@ -2122,7 +2173,7 @@ int get_last_leader_offset(char *line, char **flags)
}
len1 = (int)STRLEN(com_leader);
- for (list = (char *)curbuf->b_p_com; *list;) {
+ for (list = curbuf->b_p_com; *list;) {
char *flags_save = list;
(void)copy_option_part(&list, part_buf2, COM_MAX_LEN, ",");
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 6238d85b3a..4efd8a4ad1 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -140,16 +140,16 @@ int buf_init_chartab(buf_T *buf, int global)
const char_u *p;
if (i == 0) {
// first round: 'isident'
- p = p_isi;
+ p = (char_u *)p_isi;
} else if (i == 1) {
// second round: 'isprint'
- p = p_isp;
+ p = (char_u *)p_isp;
} else if (i == 2) {
// third round: 'isfname'
- p = p_isf;
+ p = (char_u *)p_isf;
} else { // i == 3
// fourth round: 'iskeyword'
- p = buf->b_p_isk;
+ p = (char_u *)buf->b_p_isk;
}
while (*p) {
@@ -246,7 +246,7 @@ int buf_init_chartab(buf_T *buf, int global)
}
c = *p;
- p = skip_to_option_part(p);
+ p = (char_u *)skip_to_option_part((char *)p);
if ((c == ',') && (*p == NUL)) {
// Trailing comma is not allowed.
@@ -313,7 +313,7 @@ size_t transstr_len(const char *const s, bool untab)
const size_t l = (size_t)utfc_ptr2len(p);
if (l > 1) {
int pcc[MAX_MCO + 1];
- pcc[0] = utfc_ptr2char((const char_u *)p, &pcc[1]);
+ pcc[0] = utfc_ptr2char(p, &pcc[1]);
if (vim_isprintc(pcc[0])) {
len += l;
@@ -359,7 +359,7 @@ size_t transstr_buf(const char *const s, char *const buf, const size_t len, bool
break; // Exceeded `buf` size.
}
int pcc[MAX_MCO + 1];
- pcc[0] = utfc_ptr2char((const char_u *)p, &pcc[1]);
+ pcc[0] = utfc_ptr2char(p, &pcc[1]);
if (vim_isprintc(pcc[0])) {
memmove(buf_p, p, l);
@@ -709,7 +709,7 @@ int ptr2cells(const char *p_in)
/// @return number of character cells.
int vim_strsize(char *s)
{
- return vim_strnsize((char_u *)s, MAXCOL);
+ return vim_strnsize(s, MAXCOL);
}
/// Return the number of character cells string "s[len]" will take on the
@@ -721,13 +721,13 @@ int vim_strsize(char *s)
/// @param len
///
/// @return Number of character cells.
-int vim_strnsize(char_u *s, int len)
+int vim_strnsize(char *s, int len)
{
assert(s != NULL);
int size = 0;
while (*s != NUL && --len >= 0) {
- int l = utfc_ptr2len((char *)s);
- size += ptr2cells((char *)s);
+ int l = utfc_ptr2len(s);
+ size += ptr2cells(s);
s += l;
len -= l - 1;
}
@@ -930,14 +930,18 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
posptr -= utf_head_off(line, posptr);
}
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, wp, pos->lnum, 0, line, line);
+
// This function is used very often, do some speed optimizations.
// When 'list', 'linebreak', 'showbreak' and 'breakindent' are not set
- // use a simple loop.
+ // and there are no virtual text use a simple loop.
// Also use this when 'list' is set but tabs take their normal size.
if ((!wp->w_p_list || (wp->w_p_lcs_chars.tab1 != NUL))
&& !wp->w_p_lbr
&& *get_showbreak_value(wp) == NUL
- && !wp->w_p_bri) {
+ && !wp->w_p_bri
+ && !cts.cts_has_virt_text) {
for (;;) {
head = 0;
int c = *ptr;
@@ -984,25 +988,29 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
} else {
for (;;) {
// A tab gets expanded, depending on the current column
+ // Other things also take up space.
head = 0;
- incr = win_lbr_chartabsize(wp, line, ptr, vcol, &head);
+ incr = win_lbr_chartabsize(&cts, &head);
// make sure we don't go past the end of the line
- if (*ptr == NUL) {
+ if (*cts.cts_ptr == NUL) {
// NUL at end of line only takes one column
incr = 1;
break;
}
- if ((posptr != NULL) && (ptr >= posptr)) {
+ if ((posptr != NULL) && ((char_u *)cts.cts_ptr >= posptr)) {
// character at pos->col
break;
}
- vcol += incr;
- MB_PTR_ADV(ptr);
+ cts.cts_vcol += incr;
+ MB_PTR_ADV(cts.cts_ptr);
}
+ vcol = cts.cts_vcol;
+ ptr = (char_u *)cts.cts_ptr;
}
+ clear_chartabsize_arg(&cts);
if (start != NULL) {
*start = vcol + head;
@@ -1013,6 +1021,8 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
}
if (cursor != NULL) {
+ // cursor is after inserted text
+ vcol += cts.cts_cur_text_width;
if ((*ptr == TAB)
&& (State & MODE_NORMAL)
&& !wp->w_p_list
@@ -1147,7 +1157,7 @@ char *skipwhite(const char *const p)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
FUNC_ATTR_NONNULL_RET
{
- return (char *)skipwhite_len((char_u *)p, STRLEN(p));
+ return skipwhite_len(p, STRLEN(p));
}
/// Like `skipwhite`, but skip up to `len` characters.
@@ -1158,27 +1168,27 @@ char *skipwhite(const char *const p)
///
/// @return Pointer to character after the skipped whitespace, or the `len`-th
/// character in the string.
-char_u *skipwhite_len(const char_u *p, size_t len)
+char *skipwhite_len(const char *p, size_t len)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
FUNC_ATTR_NONNULL_RET
{
for (; len > 0 && ascii_iswhite(*p); len--) {
p++;
}
- return (char_u *)p;
+ return (char *)p;
}
// getwhitecols: return the number of whitespace
// columns (bytes) at the start of a given line
intptr_t getwhitecols_curline(void)
{
- return getwhitecols(get_cursor_line_ptr());
+ return getwhitecols((char *)get_cursor_line_ptr());
}
-intptr_t getwhitecols(const char_u *p)
+intptr_t getwhitecols(const char *p)
FUNC_ATTR_PURE
{
- return (char_u *)skipwhite((char *)p) - p;
+ return skipwhite(p) - p;
}
/// Skip over digits
@@ -1222,10 +1232,10 @@ const char *skipbin(const char *q)
///
/// @return Pointer to the character after the skipped digits and hex
/// characters.
-char_u *skiphex(char_u *q)
+char *skiphex(char *q)
FUNC_ATTR_PURE
{
- char_u *p = q;
+ char *p = q;
while (ascii_isxdigit(*p)) {
// skip to next non-digit
p++;
@@ -1238,10 +1248,10 @@ char_u *skiphex(char_u *q)
/// @param q
///
/// @return Pointer to the digit or (NUL after the string).
-char_u *skiptodigit(char_u *q)
+char *skiptodigit(char *q)
FUNC_ATTR_PURE
{
- char_u *p = q;
+ char *p = q;
while (*p != NUL && !ascii_isdigit(*p)) {
// skip to next digit
p++;
@@ -1272,10 +1282,10 @@ const char *skiptobin(const char *q)
/// @param q
///
/// @return Pointer to the hex character or (NUL after the string).
-char_u *skiptohex(char_u *q)
+char *skiptohex(char *q)
FUNC_ATTR_PURE
{
- char_u *p = q;
+ char *p = q;
while (*p != NUL && !ascii_isxdigit(*p)) {
// skip to next digit
p++;
@@ -1288,13 +1298,13 @@ char_u *skiptohex(char_u *q)
/// @param[in] p Text to skip over.
///
/// @return Pointer to the next whitespace or NUL character.
-char_u *skiptowhite(const char_u *p)
+char *skiptowhite(const char *p)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
{
while (*p != ' ' && *p != '\t' && *p != NUL) {
p++;
}
- return (char_u *)p;
+ return (char *)p;
}
/// skiptowhite_esc: Like skiptowhite(), but also skip escaped chars
@@ -1319,11 +1329,11 @@ char *skiptowhite_esc(char *p)
/// @param[in] p Text to skip over.
///
/// @return Pointer to the next '\n' or NUL character.
-char_u *skip_to_newline(const char_u *const p)
+char *skip_to_newline(const char *const p)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
FUNC_ATTR_NONNULL_RET
{
- return (char_u *)xstrchrnul((const char *)p, NL);
+ return xstrchrnul(p, NL);
}
/// Gets a number from a string and skips over it, signalling overflow.
@@ -1412,10 +1422,10 @@ int32_t getdigits_int32(char **pp, bool strict, long def)
/// Check that "lbuf" is empty or only contains blanks.
///
/// @param lbuf line buffer to check
-bool vim_isblankline(char_u *lbuf)
+bool vim_isblankline(char *lbuf)
FUNC_ATTR_PURE
{
- char_u *p = (char_u *)skipwhite((char *)lbuf);
+ char *p = skipwhite(lbuf);
return *p == NUL || *p == '\r' || *p == '\n';
}
@@ -1654,8 +1664,9 @@ int hex2nr(int c)
}
/// Convert two hex characters to a byte.
-/// Return -1 if one of the characters is not hex.
-int hexhex2nr(char_u *p)
+///
+/// @return -1 if one of the characters is not hex.
+int hexhex2nr(const char *p)
FUNC_ATTR_PURE
{
if (!ascii_isxdigit(p[0]) || !ascii_isxdigit(p[1])) {
@@ -1677,12 +1688,12 @@ int hexhex2nr(char_u *p)
/// characters.
///
/// @param str file path string to check
-bool rem_backslash(const char_u *str)
+bool rem_backslash(const char *str)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
#ifdef BACKSLASH_IN_FILENAME
return str[0] == '\\'
- && str[1] < 0x80
+ && (uint8_t)str[1] < 0x80
&& (str[1] == ' '
|| (str[1] != NUL
&& str[1] != '*'
@@ -1697,7 +1708,7 @@ bool rem_backslash(const char_u *str)
/// Halve the number of backslashes in a file name argument.
///
/// @param p
-void backslash_halve(char_u *p)
+void backslash_halve(char *p)
{
for (; *p; p++) {
if (rem_backslash(p)) {
@@ -1711,11 +1722,11 @@ void backslash_halve(char_u *p)
/// @param p
///
/// @return String with the number of backslashes halved.
-char_u *backslash_halve_save(const char_u *p)
+char *backslash_halve_save(const char *p)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
// TODO(philix): simplify and improve backslash_halve_save algorithm
- char_u *res = vim_strsave(p);
+ char *res = xstrdup(p);
backslash_halve(res);
return res;
}
diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c
index e82e98ba4e..5c54404aab 100644
--- a/src/nvim/cmdexpand.c
+++ b/src/nvim/cmdexpand.c
@@ -23,6 +23,7 @@
#include "nvim/help.h"
#include "nvim/highlight_group.h"
#include "nvim/if_cscope.h"
+#include "nvim/locale.h"
#include "nvim/lua/executor.h"
#include "nvim/mapping.h"
#include "nvim/menu.h"
@@ -275,6 +276,150 @@ void cmdline_pum_cleanup(CmdlineInfo *cclp)
wildmenu_cleanup(cclp);
}
+/// Get the next or prev cmdline completion match. The index of the match is set
+/// in "p_findex"
+static char_u *get_next_or_prev_match(int mode, expand_T *xp, int *p_findex, char_u *orig_save)
+{
+ if (xp->xp_numfiles <= 0) {
+ return NULL;
+ }
+
+ int findex = *p_findex;
+
+ if (mode == WILD_PREV) {
+ if (findex == -1) {
+ findex = xp->xp_numfiles;
+ }
+ findex--;
+ } else { // mode == WILD_NEXT
+ findex++;
+ }
+
+ // When wrapping around, return the original string, set findex to -1.
+ if (findex < 0) {
+ if (orig_save == NULL) {
+ findex = xp->xp_numfiles - 1;
+ } else {
+ findex = -1;
+ }
+ }
+ if (findex >= xp->xp_numfiles) {
+ if (orig_save == NULL) {
+ findex = 0;
+ } else {
+ findex = -1;
+ }
+ }
+ if (compl_match_array) {
+ compl_selected = findex;
+ cmdline_pum_display(false);
+ } else if (p_wmnu) {
+ redraw_wildmenu(xp, xp->xp_numfiles, xp->xp_files, findex, cmd_showtail);
+ }
+ *p_findex = findex;
+
+ return vim_strsave(findex == -1 ? orig_save : (char_u *)xp->xp_files[findex]);
+}
+
+/// Start the command-line expansion and get the matches.
+static char_u *ExpandOne_start(int mode, expand_T *xp, char_u *str, int options)
+{
+ int non_suf_match; // number without matching suffix
+ char_u *ss = NULL;
+
+ // Do the expansion.
+ if (ExpandFromContext(xp, str, &xp->xp_numfiles, &xp->xp_files, options) == FAIL) {
+#ifdef FNAME_ILLEGAL
+ // Illegal file name has been silently skipped. But when there
+ // are wildcards, the real problem is that there was no match,
+ // causing the pattern to be added, which has illegal characters.
+ if (!(options & WILD_SILENT) && (options & WILD_LIST_NOTFOUND)) {
+ semsg(_(e_nomatch2), str);
+ }
+#endif
+ } else if (xp->xp_numfiles == 0) {
+ if (!(options & WILD_SILENT)) {
+ semsg(_(e_nomatch2), str);
+ }
+ } else {
+ // Escape the matches for use on the command line.
+ ExpandEscape(xp, str, xp->xp_numfiles, xp->xp_files, options);
+
+ // Check for matching suffixes in file names.
+ if (mode != WILD_ALL && mode != WILD_ALL_KEEP
+ && mode != WILD_LONGEST) {
+ if (xp->xp_numfiles) {
+ non_suf_match = xp->xp_numfiles;
+ } else {
+ non_suf_match = 1;
+ }
+ if ((xp->xp_context == EXPAND_FILES
+ || xp->xp_context == EXPAND_DIRECTORIES)
+ && xp->xp_numfiles > 1) {
+ // More than one match; check suffix.
+ // The files will have been sorted on matching suffix in
+ // expand_wildcards, only need to check the first two.
+ non_suf_match = 0;
+ for (int i = 0; i < 2; i++) {
+ if (match_suffix((char_u *)xp->xp_files[i])) {
+ non_suf_match++;
+ }
+ }
+ }
+ if (non_suf_match != 1) {
+ // Can we ever get here unless it's while expanding
+ // interactively? If not, we can get rid of this all
+ // together. Don't really want to wait for this message
+ // (and possibly have to hit return to continue!).
+ if (!(options & WILD_SILENT)) {
+ emsg(_(e_toomany));
+ } else if (!(options & WILD_NO_BEEP)) {
+ beep_flush();
+ }
+ }
+ if (!(non_suf_match != 1 && mode == WILD_EXPAND_FREE)) {
+ ss = vim_strsave((char_u *)xp->xp_files[0]);
+ }
+ }
+ }
+
+ return ss;
+}
+
+/// Return the longest common part in the list of cmdline completion matches.
+static char *find_longest_match(expand_T *xp, int options)
+{
+ size_t len = 0;
+
+ for (size_t mb_len; xp->xp_files[0][len]; len += mb_len) {
+ mb_len = (size_t)utfc_ptr2len(&xp->xp_files[0][len]);
+ int c0 = utf_ptr2char(&xp->xp_files[0][len]);
+ int i;
+ for (i = 1; i < xp->xp_numfiles; i++) {
+ int ci = utf_ptr2char(&xp->xp_files[i][len]);
+
+ if (p_fic && (xp->xp_context == EXPAND_DIRECTORIES
+ || xp->xp_context == EXPAND_FILES
+ || xp->xp_context == EXPAND_SHELLCMD
+ || xp->xp_context == EXPAND_BUFFERS)) {
+ if (mb_tolower(c0) != mb_tolower(ci)) {
+ break;
+ }
+ } else if (c0 != ci) {
+ break;
+ }
+ }
+ if (i < xp->xp_numfiles) {
+ if (!(options & WILD_NO_BEEP)) {
+ vim_beep(BO_WILD);
+ }
+ break;
+ }
+ }
+
+ return xstrndup(xp->xp_files[0], len);
+}
+
/// Do wildcard expansion on the string 'str'.
/// Chars that should not be expanded must be preceded with a backslash.
/// Return a pointer to allocated memory containing the new string.
@@ -295,6 +440,10 @@ void cmdline_pum_cleanup(CmdlineInfo *cclp)
/// mode = WILD_ALL: return all matches concatenated
/// mode = WILD_LONGEST: return longest matched part
/// mode = WILD_ALL_KEEP: get all matches, keep matches
+/// mode = WILD_APPLY: apply the item selected in the cmdline completion
+/// popup menu and close the menu.
+/// mode = WILD_CANCEL: cancel and close the cmdline completion popup and
+/// use the original text.
///
/// options = WILD_LIST_NOTFOUND: list entries without a match
/// options = WILD_HOME_REPLACE: do home_replace() for buffer names
@@ -316,56 +465,17 @@ char_u *ExpandOne(expand_T *xp, char_u *str, char_u *orig, int options, int mode
static char_u *orig_save = NULL; // kept value of orig
int orig_saved = false;
int i;
- int non_suf_match; // number without matching suffix
// first handle the case of using an old match
if (mode == WILD_NEXT || mode == WILD_PREV) {
- if (xp->xp_numfiles > 0) {
- if (mode == WILD_PREV) {
- if (findex == -1) {
- findex = xp->xp_numfiles;
- }
- findex--;
- } else { // mode == WILD_NEXT
- findex++;
- }
-
- // When wrapping around, return the original string, set findex to
- // -1.
- if (findex < 0) {
- if (orig_save == NULL) {
- findex = xp->xp_numfiles - 1;
- } else {
- findex = -1;
- }
- }
- if (findex >= xp->xp_numfiles) {
- if (orig_save == NULL) {
- findex = 0;
- } else {
- findex = -1;
- }
- }
- if (compl_match_array) {
- compl_selected = findex;
- cmdline_pum_display(false);
- } else if (p_wmnu) {
- redraw_wildmenu(xp, xp->xp_numfiles, xp->xp_files, findex, cmd_showtail);
- }
- if (findex == -1) {
- return vim_strsave(orig_save);
- }
- return vim_strsave((char_u *)xp->xp_files[findex]);
- } else {
- return NULL;
- }
+ return get_next_or_prev_match(mode, xp, &findex, orig_save);
}
if (mode == WILD_CANCEL) {
ss = vim_strsave(orig_save ? orig_save : (char_u *)"");
} else if (mode == WILD_APPLY) {
- ss = vim_strsave(findex == -1 ? (orig_save ? orig_save : (char_u *)"") :
- (char_u *)xp->xp_files[findex]);
+ ss = vim_strsave(findex == -1 ? (orig_save ? orig_save : (char_u *)"")
+ : (char_u *)xp->xp_files[findex]);
}
// free old names
@@ -385,93 +495,12 @@ char_u *ExpandOne(expand_T *xp, char_u *str, char_u *orig, int options, int mode
orig_save = orig;
orig_saved = true;
- // Do the expansion.
- if (ExpandFromContext(xp, str, &xp->xp_numfiles, &xp->xp_files, options) == FAIL) {
-#ifdef FNAME_ILLEGAL
- // Illegal file name has been silently skipped. But when there
- // are wildcards, the real problem is that there was no match,
- // causing the pattern to be added, which has illegal characters.
- if (!(options & WILD_SILENT) && (options & WILD_LIST_NOTFOUND)) {
- semsg(_(e_nomatch2), str);
- }
-#endif
- } else if (xp->xp_numfiles == 0) {
- if (!(options & WILD_SILENT)) {
- semsg(_(e_nomatch2), str);
- }
- } else {
- // Escape the matches for use on the command line.
- ExpandEscape(xp, str, xp->xp_numfiles, xp->xp_files, options);
-
- // Check for matching suffixes in file names.
- if (mode != WILD_ALL && mode != WILD_ALL_KEEP
- && mode != WILD_LONGEST) {
- if (xp->xp_numfiles) {
- non_suf_match = xp->xp_numfiles;
- } else {
- non_suf_match = 1;
- }
- if ((xp->xp_context == EXPAND_FILES
- || xp->xp_context == EXPAND_DIRECTORIES)
- && xp->xp_numfiles > 1) {
- // More than one match; check suffix.
- // The files will have been sorted on matching suffix in
- // expand_wildcards, only need to check the first two.
- non_suf_match = 0;
- for (i = 0; i < 2; i++) {
- if (match_suffix((char_u *)xp->xp_files[i])) {
- non_suf_match++;
- }
- }
- }
- if (non_suf_match != 1) {
- // Can we ever get here unless it's while expanding
- // interactively? If not, we can get rid of this all
- // together. Don't really want to wait for this message
- // (and possibly have to hit return to continue!).
- if (!(options & WILD_SILENT)) {
- emsg(_(e_toomany));
- } else if (!(options & WILD_NO_BEEP)) {
- beep_flush();
- }
- }
- if (!(non_suf_match != 1 && mode == WILD_EXPAND_FREE)) {
- ss = vim_strsave((char_u *)xp->xp_files[0]);
- }
- }
- }
+ ss = ExpandOne_start(mode, xp, str, options);
}
// Find longest common part
if (mode == WILD_LONGEST && xp->xp_numfiles > 0) {
- size_t len = 0;
-
- for (size_t mb_len; xp->xp_files[0][len]; len += mb_len) {
- mb_len = (size_t)utfc_ptr2len(&xp->xp_files[0][len]);
- int c0 = utf_ptr2char(&xp->xp_files[0][len]);
- for (i = 1; i < xp->xp_numfiles; i++) {
- int ci = utf_ptr2char(&xp->xp_files[i][len]);
-
- if (p_fic && (xp->xp_context == EXPAND_DIRECTORIES
- || xp->xp_context == EXPAND_FILES
- || xp->xp_context == EXPAND_SHELLCMD
- || xp->xp_context == EXPAND_BUFFERS)) {
- if (mb_tolower(c0) != mb_tolower(ci)) {
- break;
- }
- } else if (c0 != ci) {
- break;
- }
- }
- if (i < xp->xp_numfiles) {
- if (!(options & WILD_NO_BEEP)) {
- vim_beep(BO_WILD);
- }
- break;
- }
- }
-
- ss = (char_u *)xstrndup(xp->xp_files[0], len);
+ ss = (char_u *)find_longest_match(xp, options);
findex = -1; // next p_wc gets first one
}
@@ -641,7 +670,7 @@ int showmatches(expand_T *xp, int wildmenu)
lastlen = 999;
for (k = i; k < num_files; k += lines) {
if (xp->xp_context == EXPAND_TAGS_LISTFILES) {
- msg_outtrans_attr((char_u *)files_found[k], HL_ATTR(HLF_D));
+ msg_outtrans_attr(files_found[k], HL_ATTR(HLF_D));
p = (char_u *)files_found[k] + STRLEN(files_found[k]) + 1;
msg_advance(maxlen + 1);
msg_puts((const char *)p);
@@ -662,27 +691,27 @@ int showmatches(expand_T *xp, int wildmenu)
// $HOME has been replaced with ~/.
char_u *exp_path = expand_env_save_opt((char_u *)files_found[k], true);
char_u *path = exp_path != NULL ? exp_path : (char_u *)files_found[k];
- char_u *halved_slash = backslash_halve_save(path);
- j = os_isdir(halved_slash);
+ char_u *halved_slash = (char_u *)backslash_halve_save((char *)path);
+ j = os_isdir((char *)halved_slash);
xfree(exp_path);
if (halved_slash != path) {
xfree(halved_slash);
}
} else {
// Expansion was done here, file names are literal.
- j = os_isdir((char_u *)files_found[k]);
+ j = os_isdir(files_found[k]);
}
if (showtail) {
p = (char_u *)L_SHOWFILE(k);
} else {
home_replace(NULL, files_found[k], (char *)NameBuff, MAXPATHL, true);
- p = NameBuff;
+ p = (char_u *)NameBuff;
}
} else {
j = false;
p = (char_u *)L_SHOWFILE(k);
}
- lastlen = msg_outtrans_attr(p, j ? attr : 0);
+ lastlen = msg_outtrans_attr((char *)p, j ? attr : 0);
}
if (msg_col > 0) { // when not wrapped around
msg_clr_eos();
@@ -758,7 +787,7 @@ static bool expand_showtail(expand_T *xp)
for (s = (char_u *)xp->xp_pattern; s < end; s++) {
// Skip escaped wildcards. Only when the backslash is not a path
// separator, on DOS the '*' "path\*\file" must not be skipped.
- if (rem_backslash(s)) {
+ if (rem_backslash((char *)s)) {
s++;
} else if (vim_strchr("*?[", *s) != NULL) {
return false;
@@ -951,65 +980,23 @@ void set_expand_context(expand_T *xp)
set_cmd_context(xp, ccline->cmdbuff, ccline->cmdlen, ccline->cmdpos, true);
}
-/// This is all pretty much copied from do_one_cmd(), with all the extra stuff
-/// we don't need/want deleted. Maybe this could be done better if we didn't
-/// repeat all this stuff. The only problem is that they may not stay
-/// perfectly compatible with each other, but then the command line syntax
-/// probably won't change that much -- webb.
+/// Sets the index of a built-in or user defined command "cmd" in eap->cmdidx.
+/// For user defined commands, the completion context is set in "xp" and the
+/// completion flags in "complp".
///
-/// @param buff buffer for command string
-static const char *set_one_cmd_context(expand_T *xp, const char *buff)
+/// @return a pointer to the text after the command or NULL for failure.
+static const char *set_cmd_index(const char *cmd, exarg_T *eap, expand_T *xp, int *complp)
{
+ const char *p = NULL;
size_t len = 0;
- exarg_T ea;
- int context = EXPAND_NOTHING;
- bool forceit = false;
- bool usefilter = false; // Filter instead of file name.
-
- ExpandInit(xp);
- xp->xp_pattern = (char *)buff;
- xp->xp_line = (char *)buff;
- xp->xp_context = EXPAND_COMMANDS; // Default until we get past command
- ea.argt = 0;
-
- // 2. skip comment lines and leading space, colons or bars
- const char *cmd;
- for (cmd = buff; vim_strchr(" \t:|", *cmd) != NULL; cmd++) {}
- xp->xp_pattern = (char *)cmd;
-
- if (*cmd == NUL) {
- return NULL;
- }
- if (*cmd == '"') { // ignore comment lines
- xp->xp_context = EXPAND_NOTHING;
- return NULL;
- }
-
- // 3. parse a range specifier of the form: addr [,addr] [;addr] ..
- cmd = (const char *)skip_range(cmd, &xp->xp_context);
-
- // 4. parse command
- xp->xp_pattern = (char *)cmd;
- if (*cmd == NUL) {
- return NULL;
- }
- if (*cmd == '"') {
- xp->xp_context = EXPAND_NOTHING;
- return NULL;
- }
-
- if (*cmd == '|' || *cmd == '\n') {
- return cmd + 1; // There's another command
- }
// Isolate the command and search for it in the command table.
// Exceptions:
// - the 'k' command can directly be followed by any character, but
// do accept "keepmarks", "keepalt" and "keepjumps".
// - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
- const char *p;
if (*cmd == 'k' && cmd[1] != 'e') {
- ea.cmdidx = CMD_k;
+ eap->cmdidx = CMD_k;
p = cmd + 1;
} else {
p = cmd;
@@ -1040,7 +1027,7 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
return NULL;
}
- ea.cmdidx = excmd_get_cmdidx(cmd, len);
+ eap->cmdidx = excmd_get_cmdidx(cmd, len);
if (cmd[0] >= 'A' && cmd[0] <= 'Z') {
while (ASCII_ISALNUM(*p) || *p == '*') { // Allow * wild card
@@ -1055,227 +1042,131 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
return NULL;
}
- if (ea.cmdidx == CMD_SIZE) {
+ if (eap->cmdidx == CMD_SIZE) {
if (*cmd == 's' && vim_strchr("cgriI", cmd[1]) != NULL) {
- ea.cmdidx = CMD_substitute;
+ eap->cmdidx = CMD_substitute;
p = cmd + 1;
} else if (cmd[0] >= 'A' && cmd[0] <= 'Z') {
- ea.cmd = (char *)cmd;
- p = (const char *)find_ucmd(&ea, (char *)p, NULL, xp, &context);
+ eap->cmd = (char *)cmd;
+ p = (const char *)find_ucmd(eap, (char *)p, NULL, xp, complp);
if (p == NULL) {
- ea.cmdidx = CMD_SIZE; // Ambiguous user command.
+ eap->cmdidx = CMD_SIZE; // Ambiguous user command.
}
}
}
- if (ea.cmdidx == CMD_SIZE) {
+ if (eap->cmdidx == CMD_SIZE) {
// Not still touching the command and it was an illegal one
xp->xp_context = EXPAND_UNSUCCESSFUL;
return NULL;
}
- xp->xp_context = EXPAND_NOTHING; // Default now that we're past command
-
- if (*p == '!') { // forced commands
- forceit = true;
- p++;
- }
-
- // 5. parse arguments
- if (!IS_USER_CMDIDX(ea.cmdidx)) {
- ea.argt = excmd_get_argt(ea.cmdidx);
- }
-
- const char *arg = (const char *)skipwhite(p);
+ return p;
+}
- // Skip over ++argopt argument
- if ((ea.argt & EX_ARGOPT) && *arg != NUL && strncmp(arg, "++", 2) == 0) {
- p = arg;
- while (*p && !ascii_isspace(*p)) {
- MB_PTR_ADV(p);
- }
- arg = (const char *)skipwhite(p);
- }
+/// Set the completion context for a command argument with wild card characters.
+static void set_context_for_wildcard_arg(exarg_T *eap, const char *arg, bool usefilter,
+ expand_T *xp, int *complp)
+{
+ bool in_quote = false;
+ const char *bow = NULL; // Beginning of word.
+ size_t len = 0;
- if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) {
- if (*arg == '>') { // Append.
- if (*++arg == '>') {
- arg++;
+ // Allow spaces within back-quotes to count as part of the argument
+ // being expanded.
+ xp->xp_pattern = skipwhite(arg);
+ const char *p = (const char *)xp->xp_pattern;
+ while (*p != NUL) {
+ int c = utf_ptr2char(p);
+ if (c == '\\' && p[1] != NUL) {
+ p++;
+ } else if (c == '`') {
+ if (!in_quote) {
+ xp->xp_pattern = (char *)p;
+ bow = p + 1;
}
- arg = (const char *)skipwhite(arg);
- } else if (*arg == '!' && ea.cmdidx == CMD_write) { // :w !filter
- arg++;
- usefilter = true;
- }
- }
-
- if (ea.cmdidx == CMD_read) {
- usefilter = forceit; // :r! filter if forced
- if (*arg == '!') { // :r !filter
- arg++;
- usefilter = true;
- }
- }
-
- if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) {
- while (*arg == *cmd) { // allow any number of '>' or '<'
- arg++;
- }
- arg = (const char *)skipwhite(arg);
- }
-
- // Does command allow "+command"?
- if ((ea.argt & EX_CMDARG) && !usefilter && *arg == '+') {
- // Check if we're in the +command
- p = arg + 1;
- arg = (const char *)skip_cmd_arg((char *)arg, false);
-
- // Still touching the command after '+'?
- if (*arg == NUL) {
- return p;
- }
-
- // Skip space(s) after +command to get to the real argument.
- arg = (const char *)skipwhite(arg);
- }
-
- // Check for '|' to separate commands and '"' to start comments.
- // Don't do this for ":read !cmd" and ":write !cmd".
- if ((ea.argt & EX_TRLBAR) && !usefilter) {
- p = arg;
- // ":redir @" is not the start of a comment
- if (ea.cmdidx == CMD_redir && p[0] == '@' && p[1] == '"') {
- p += 2;
- }
- while (*p) {
- if (*p == Ctrl_V) {
- if (p[1] != NUL) {
- p++;
- }
- } else if ((*p == '"' && !(ea.argt & EX_NOTRLCOM))
- || *p == '|'
- || *p == '\n') {
- if (*(p - 1) != '\\') {
- if (*p == '|' || *p == '\n') {
- return p + 1;
- }
- return NULL; // It's a comment
+ in_quote = !in_quote;
+ // An argument can contain just about everything, except
+ // characters that end the command and white space.
+ } else if (c == '|' || c == '\n' || c == '"' || ascii_iswhite(c)) {
+ len = 0; // avoid getting stuck when space is in 'isfname'
+ while (*p != NUL) {
+ c = utf_ptr2char(p);
+ if (c == '`' || vim_isfilec_or_wc(c)) {
+ break;
}
+ len = (size_t)utfc_ptr2len(p);
+ MB_PTR_ADV(p);
}
- MB_PTR_ADV(p);
- }
- }
-
- if (!(ea.argt & EX_EXTRA) && *arg != NUL && strchr("|\"", *arg) == NULL) {
- // no arguments allowed but there is something
- return NULL;
- }
-
- // Find start of last argument (argument just before cursor):
- p = buff;
- xp->xp_pattern = (char *)p;
- len = strlen(buff);
- while (*p && p < buff + len) {
- if (*p == ' ' || *p == TAB) {
- // Argument starts after a space.
- xp->xp_pattern = (char *)++p;
- } else {
- if (*p == '\\' && *(p + 1) != NUL) {
- p++; // skip over escaped character
+ if (in_quote) {
+ bow = p;
+ } else {
+ xp->xp_pattern = (char *)p;
}
- MB_PTR_ADV(p);
+ p -= len;
}
+ MB_PTR_ADV(p);
}
- if (ea.argt & EX_XFILE) {
- int in_quote = false;
- const char *bow = NULL; // Beginning of word.
-
- // Allow spaces within back-quotes to count as part of the argument
- // being expanded.
- xp->xp_pattern = skipwhite(arg);
- p = (const char *)xp->xp_pattern;
- while (*p != NUL) {
- int c = utf_ptr2char(p);
- if (c == '\\' && p[1] != NUL) {
- p++;
- } else if (c == '`') {
- if (!in_quote) {
- xp->xp_pattern = (char *)p;
- bow = p + 1;
- }
- in_quote = !in_quote;
- // An argument can contain just about everything, except
- // characters that end the command and white space.
- } else if (c == '|' || c == '\n' || c == '"' || ascii_iswhite(c)) {
- len = 0; // avoid getting stuck when space is in 'isfname'
- while (*p != NUL) {
- c = utf_ptr2char(p);
- if (c == '`' || vim_isfilec_or_wc(c)) {
- break;
- }
- len = (size_t)utfc_ptr2len(p);
- MB_PTR_ADV(p);
- }
- if (in_quote) {
- bow = p;
- } else {
- xp->xp_pattern = (char *)p;
- }
- p -= len;
- }
- MB_PTR_ADV(p);
- }
-
- // If we are still inside the quotes, and we passed a space, just
- // expand from there.
- if (bow != NULL && in_quote) {
- xp->xp_pattern = (char *)bow;
- }
- xp->xp_context = EXPAND_FILES;
+ // If we are still inside the quotes, and we passed a space, just
+ // expand from there.
+ if (bow != NULL && in_quote) {
+ xp->xp_pattern = (char *)bow;
+ }
+ xp->xp_context = EXPAND_FILES;
- // For a shell command more chars need to be escaped.
- if (usefilter || ea.cmdidx == CMD_bang || ea.cmdidx == CMD_terminal) {
+ // For a shell command more chars need to be escaped.
+ if (usefilter || eap->cmdidx == CMD_bang || eap->cmdidx == CMD_terminal) {
#ifndef BACKSLASH_IN_FILENAME
- xp->xp_shell = true;
+ xp->xp_shell = true;
#endif
- // When still after the command name expand executables.
- if (xp->xp_pattern == skipwhite(arg)) {
- xp->xp_context = EXPAND_SHELLCMD;
- }
+ // When still after the command name expand executables.
+ if (xp->xp_pattern == skipwhite(arg)) {
+ xp->xp_context = EXPAND_SHELLCMD;
}
+ }
- // Check for environment variable.
- if (*xp->xp_pattern == '$') {
- for (p = (const char *)xp->xp_pattern + 1; *p != NUL; p++) {
- if (!vim_isIDc((uint8_t)(*p))) {
- break;
- }
- }
- if (*p == NUL) {
- xp->xp_context = EXPAND_ENV_VARS;
- xp->xp_pattern++;
- // Avoid that the assignment uses EXPAND_FILES again.
- if (context != EXPAND_USER_DEFINED && context != EXPAND_USER_LIST) {
- context = EXPAND_ENV_VARS;
- }
+ // Check for environment variable.
+ if (*xp->xp_pattern == '$') {
+ for (p = (const char *)xp->xp_pattern + 1; *p != NUL; p++) {
+ if (!vim_isIDc((uint8_t)(*p))) {
+ break;
}
}
- // Check for user names.
- if (*xp->xp_pattern == '~') {
- for (p = (const char *)xp->xp_pattern + 1; *p != NUL && *p != '/'; p++) {}
- // Complete ~user only if it partially matches a user name.
- // A full match ~user<Tab> will be replaced by user's home
- // directory i.e. something like ~user<Tab> -> /home/user/
- if (*p == NUL && p > (const char *)xp->xp_pattern + 1
- && match_user((char_u *)xp->xp_pattern + 1) >= 1) {
- xp->xp_context = EXPAND_USER;
- xp->xp_pattern++;
+ if (*p == NUL) {
+ xp->xp_context = EXPAND_ENV_VARS;
+ xp->xp_pattern++;
+ // Avoid that the assignment uses EXPAND_FILES again.
+ if (*complp != EXPAND_USER_DEFINED && *complp != EXPAND_USER_LIST) {
+ *complp = EXPAND_ENV_VARS;
}
}
}
+ // Check for user names.
+ if (*xp->xp_pattern == '~') {
+ for (p = (const char *)xp->xp_pattern + 1; *p != NUL && *p != '/'; p++) {}
+ // Complete ~user only if it partially matches a user name.
+ // A full match ~user<Tab> will be replaced by user's home
+ // directory i.e. something like ~user<Tab> -> /home/user/
+ if (*p == NUL && p > (const char *)xp->xp_pattern + 1
+ && match_user((char_u *)xp->xp_pattern + 1) >= 1) {
+ xp->xp_context = EXPAND_USER;
+ xp->xp_pattern++;
+ }
+ }
+}
- // 6. switch on command name
- switch (ea.cmdidx) {
+/// Set the completion context in "xp" for command "cmd" with index "cmdidx".
+/// The argument to the command is "arg" and the argument flags is "argt".
+/// For user-defined commands and for environment variables, "context" has the
+/// completion type.
+///
+/// @return a pointer to the next command, or NULL if there is no next command.
+static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, const char *arg,
+ uint32_t argt, int context, expand_T *xp, bool forceit)
+{
+ const char *p;
+
+ switch (cmdidx) {
case CMD_find:
case CMD_sfind:
case CMD_tabfind:
@@ -1348,14 +1239,13 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
if (*arg == NUL || !ends_excmd(*arg)) {
// also complete "None"
set_context_in_echohl_cmd(xp, arg);
- arg = (const char *)skipwhite((char *)skiptowhite((const char_u *)arg));
+ arg = (const char *)skipwhite(skiptowhite(arg));
if (*arg != NUL) {
xp->xp_context = EXPAND_NOTHING;
- arg = (const char *)skip_regexp((char_u *)arg + 1, (uint8_t)(*arg),
- p_magic, NULL);
+ arg = (const char *)skip_regexp((char *)arg + 1, (uint8_t)(*arg), p_magic, NULL);
}
}
- return (const char *)find_nextcmd((char_u *)arg);
+ return (const char *)find_nextcmd(arg);
// All completion for the +cmdline_compl feature goes here.
@@ -1391,7 +1281,7 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
if (delim) {
// Skip "from" part.
arg++;
- arg = (const char *)skip_regexp((char_u *)arg, delim, p_magic, NULL);
+ arg = (const char *)skip_regexp((char *)arg, delim, p_magic, NULL);
}
// Skip "to" part.
while (arg[0] != NUL && (uint8_t)arg[0] != delim) {
@@ -1498,7 +1388,7 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
case CMD_lexpr:
case CMD_laddexpr:
case CMD_lgetexpr:
- set_context_for_expression(xp, (char *)arg, ea.cmdidx);
+ set_context_for_expression(xp, (char *)arg, cmdidx);
break;
case CMD_unlet:
@@ -1531,7 +1421,7 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
case CMD_cscope:
case CMD_lcscope:
case CMD_scscope:
- set_context_in_cscope_cmd(xp, arg, ea.cmdidx);
+ set_context_in_cscope_cmd(xp, arg, cmdidx);
break;
case CMD_sign:
set_context_in_sign_cmd(xp, (char_u *)arg);
@@ -1561,7 +1451,7 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
case CMD_USER_BUF:
if (context != EXPAND_NOTHING) {
// EX_XFILE: file names are handled above.
- if (!(ea.argt & EX_XFILE)) {
+ if (!(argt & EX_XFILE)) {
if (context == EXPAND_MENUS) {
return (const char *)set_context_in_menu_cmd(xp, cmd, (char *)arg, forceit);
} else if (context == EXPAND_COMMANDS) {
@@ -1607,7 +1497,7 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
case CMD_xmap:
case CMD_xnoremap:
return (const char *)set_context_in_map_cmd(xp, (char *)cmd, (char_u *)arg, forceit, false,
- false, ea.cmdidx);
+ false, cmdidx);
case CMD_unmap:
case CMD_nunmap:
case CMD_vunmap:
@@ -1618,7 +1508,7 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
case CMD_sunmap:
case CMD_xunmap:
return (const char *)set_context_in_map_cmd(xp, (char *)cmd, (char_u *)arg, forceit, false,
- true, ea.cmdidx);
+ true, cmdidx);
case CMD_mapclear:
case CMD_nmapclear:
case CMD_vmapclear:
@@ -1639,12 +1529,12 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
case CMD_iabbrev:
case CMD_inoreabbrev:
return (const char *)set_context_in_map_cmd(xp, (char *)cmd, (char_u *)arg, forceit, true,
- false, ea.cmdidx);
+ false, cmdidx);
case CMD_unabbreviate:
case CMD_cunabbrev:
case CMD_iunabbrev:
return (const char *)set_context_in_map_cmd(xp, (char *)cmd, (char_u *)arg, forceit, true,
- true, ea.cmdidx);
+ true, cmdidx);
case CMD_menu:
case CMD_noremenu:
case CMD_unmenu:
@@ -1702,7 +1592,7 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
#ifdef HAVE_WORKING_LIBINTL
case CMD_language:
- p = (const char *)skiptowhite((const char_u *)arg);
+ p = (const char *)skiptowhite(arg);
if (*p == NUL) {
xp->xp_context = EXPAND_LANGUAGE;
xp->xp_pattern = (char *)arg;
@@ -1763,6 +1653,182 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
return NULL;
}
+/// This is all pretty much copied from do_one_cmd(), with all the extra stuff
+/// we don't need/want deleted. Maybe this could be done better if we didn't
+/// repeat all this stuff. The only problem is that they may not stay
+/// perfectly compatible with each other, but then the command line syntax
+/// probably won't change that much -- webb.
+///
+/// @param buff buffer for command string
+static const char *set_one_cmd_context(expand_T *xp, const char *buff)
+{
+ size_t len = 0;
+ exarg_T ea;
+ int context = EXPAND_NOTHING;
+ bool forceit = false;
+ bool usefilter = false; // Filter instead of file name.
+
+ ExpandInit(xp);
+ xp->xp_pattern = (char *)buff;
+ xp->xp_line = (char *)buff;
+ xp->xp_context = EXPAND_COMMANDS; // Default until we get past command
+ ea.argt = 0;
+
+ // 1. skip comment lines and leading space, colons or bars
+ const char *cmd;
+ for (cmd = buff; vim_strchr(" \t:|", *cmd) != NULL; cmd++) {}
+ xp->xp_pattern = (char *)cmd;
+
+ if (*cmd == NUL) {
+ return NULL;
+ }
+ if (*cmd == '"') { // ignore comment lines
+ xp->xp_context = EXPAND_NOTHING;
+ return NULL;
+ }
+
+ // 3. skip over a range specifier of the form: addr [,addr] [;addr] ..
+ cmd = (const char *)skip_range(cmd, &xp->xp_context);
+ xp->xp_pattern = (char *)cmd;
+ if (*cmd == NUL) {
+ return NULL;
+ }
+ if (*cmd == '"') {
+ xp->xp_context = EXPAND_NOTHING;
+ return NULL;
+ }
+
+ if (*cmd == '|' || *cmd == '\n') {
+ return cmd + 1; // There's another command
+ }
+
+ // Get the command index.
+ const char *p = set_cmd_index(cmd, &ea, xp, &context);
+ if (p == NULL) {
+ return NULL;
+ }
+
+ xp->xp_context = EXPAND_NOTHING; // Default now that we're past command
+
+ if (*p == '!') { // forced commands
+ forceit = true;
+ p++;
+ }
+
+ // 6. parse arguments
+ if (!IS_USER_CMDIDX(ea.cmdidx)) {
+ ea.argt = excmd_get_argt(ea.cmdidx);
+ }
+
+ const char *arg = (const char *)skipwhite(p);
+
+ // Skip over ++argopt argument
+ if ((ea.argt & EX_ARGOPT) && *arg != NUL && strncmp(arg, "++", 2) == 0) {
+ p = arg;
+ while (*p && !ascii_isspace(*p)) {
+ MB_PTR_ADV(p);
+ }
+ arg = (const char *)skipwhite(p);
+ }
+
+ if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) {
+ if (*arg == '>') { // append
+ if (*++arg == '>') {
+ arg++;
+ }
+ arg = (const char *)skipwhite(arg);
+ } else if (*arg == '!' && ea.cmdidx == CMD_write) { // :w !filter
+ arg++;
+ usefilter = true;
+ }
+ }
+
+ if (ea.cmdidx == CMD_read) {
+ usefilter = forceit; // :r! filter if forced
+ if (*arg == '!') { // :r !filter
+ arg++;
+ usefilter = true;
+ }
+ }
+
+ if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) {
+ while (*arg == *cmd) { // allow any number of '>' or '<'
+ arg++;
+ }
+ arg = (const char *)skipwhite(arg);
+ }
+
+ // Does command allow "+command"?
+ if ((ea.argt & EX_CMDARG) && !usefilter && *arg == '+') {
+ // Check if we're in the +command
+ p = arg + 1;
+ arg = (const char *)skip_cmd_arg((char *)arg, false);
+
+ // Still touching the command after '+'?
+ if (*arg == NUL) {
+ return p;
+ }
+
+ // Skip space(s) after +command to get to the real argument.
+ arg = (const char *)skipwhite(arg);
+ }
+
+ // Check for '|' to separate commands and '"' to start comments.
+ // Don't do this for ":read !cmd" and ":write !cmd".
+ if ((ea.argt & EX_TRLBAR) && !usefilter) {
+ p = arg;
+ // ":redir @" is not the start of a comment
+ if (ea.cmdidx == CMD_redir && p[0] == '@' && p[1] == '"') {
+ p += 2;
+ }
+ while (*p) {
+ if (*p == Ctrl_V) {
+ if (p[1] != NUL) {
+ p++;
+ }
+ } else if ((*p == '"' && !(ea.argt & EX_NOTRLCOM))
+ || *p == '|'
+ || *p == '\n') {
+ if (*(p - 1) != '\\') {
+ if (*p == '|' || *p == '\n') {
+ return p + 1;
+ }
+ return NULL; // It's a comment
+ }
+ }
+ MB_PTR_ADV(p);
+ }
+ }
+
+ if (!(ea.argt & EX_EXTRA) && *arg != NUL && strchr("|\"", *arg) == NULL) {
+ // no arguments allowed but there is something
+ return NULL;
+ }
+
+ // Find start of last argument (argument just before cursor):
+ p = buff;
+ xp->xp_pattern = (char *)p;
+ len = strlen(buff);
+ while (*p && p < buff + len) {
+ if (*p == ' ' || *p == TAB) {
+ // argument starts after a space
+ xp->xp_pattern = (char *)++p;
+ } else {
+ if (*p == '\\' && *(p + 1) != NUL) {
+ p++; // skip over escaped character
+ }
+ MB_PTR_ADV(p);
+ }
+ }
+
+ if (ea.argt & EX_XFILE) {
+ set_context_for_wildcard_arg(&ea, arg, usefilter, xp, &context);
+ }
+
+ // Switch on command name.
+ return set_context_by_cmdname(cmd, ea.cmdidx, arg, ea.argt, context, xp, forceit);
+}
+
/// @param str start of command line
/// @param len length of command line (excl. NUL)
/// @param col position of cursor
@@ -1848,6 +1914,66 @@ int expand_cmdline(expand_T *xp, char_u *str, int col, int *matchcount, char ***
return EXPAND_OK;
}
+/// Expand file or directory names.
+static int expand_files_and_dirs(expand_T *xp, char_u *pat, char ***file, int *num_file, int flags,
+ int options)
+{
+ bool free_pat = false;
+
+ // for ":set path=" and ":set tags=" halve backslashes for escaped space
+ if (xp->xp_backslash != XP_BS_NONE) {
+ free_pat = true;
+ pat = vim_strsave(pat);
+ for (int i = 0; pat[i]; i++) {
+ if (pat[i] == '\\') {
+ if (xp->xp_backslash == XP_BS_THREE
+ && pat[i + 1] == '\\'
+ && pat[i + 2] == '\\'
+ && pat[i + 3] == ' ') {
+ STRMOVE(pat + i, pat + i + 3);
+ }
+ if (xp->xp_backslash == XP_BS_ONE
+ && pat[i + 1] == ' ') {
+ STRMOVE(pat + i, pat + i + 1);
+ }
+ }
+ }
+ }
+
+ if (xp->xp_context == EXPAND_FILES) {
+ flags |= EW_FILE;
+ } else if (xp->xp_context == EXPAND_FILES_IN_PATH) {
+ flags |= (EW_FILE | EW_PATH);
+ } else {
+ flags = (flags | EW_DIR) & ~EW_FILE;
+ }
+ if (options & WILD_ICASE) {
+ flags |= EW_ICASE;
+ }
+
+ // Expand wildcards, supporting %:h and the like.
+ int ret = expand_wildcards_eval(&pat, num_file, file, flags);
+ if (free_pat) {
+ xfree(pat);
+ }
+#ifdef BACKSLASH_IN_FILENAME
+ if (p_csl[0] != NUL && (options & WILD_IGNORE_COMPLETESLASH) == 0) {
+ for (int j = 0; j < *num_file; j++) {
+ char *ptr = (*file)[j];
+ while (*ptr != NUL) {
+ if (p_csl[0] == 's' && *ptr == '\\') {
+ *ptr = '/';
+ } else if (p_csl[0] == 'b' && *ptr == '/') {
+ *ptr = '\\';
+ }
+ ptr += utfc_ptr2len(ptr);
+ }
+ }
+ }
+#endif
+ return ret;
+}
+
/// Function given to ExpandGeneric() to obtain the possible arguments of the
/// ":behave {mswin,xterm}" command.
static char *get_behave_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
@@ -1905,6 +2031,67 @@ static char *get_healthcheck_names(expand_T *xp FUNC_ATTR_UNUSED, int idx)
return NULL;
}
+/// Do the expansion based on xp->xp_context and "rmp".
+static int ExpandOther(expand_T *xp, regmatch_T *rmp, int *num_file, char ***file)
+{
+ typedef CompleteListItemGetter ExpandFunc;
+ static struct expgen {
+ int context;
+ ExpandFunc func;
+ int ic;
+ int escaped;
+ } tab[] = {
+ { EXPAND_COMMANDS, get_command_name, false, true },
+ { EXPAND_BEHAVE, get_behave_arg, true, true },
+ { EXPAND_MAPCLEAR, get_mapclear_arg, true, true },
+ { EXPAND_MESSAGES, get_messages_arg, true, true },
+ { EXPAND_HISTORY, get_history_arg, true, true },
+ { EXPAND_USER_COMMANDS, get_user_commands, false, true },
+ { EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, false, true },
+ { EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, false, true },
+ { EXPAND_USER_NARGS, get_user_cmd_nargs, false, true },
+ { EXPAND_USER_COMPLETE, get_user_cmd_complete, false, true },
+ { EXPAND_USER_VARS, get_user_var_name, false, true },
+ { EXPAND_FUNCTIONS, get_function_name, false, true },
+ { EXPAND_USER_FUNC, get_user_func_name, false, true },
+ { EXPAND_EXPRESSION, get_expr_name, false, true },
+ { EXPAND_MENUS, get_menu_name, false, true },
+ { EXPAND_MENUNAMES, get_menu_names, false, true },
+ { EXPAND_SYNTAX, get_syntax_name, true, true },
+ { EXPAND_SYNTIME, get_syntime_arg, true, true },
+ { EXPAND_HIGHLIGHT, (ExpandFunc)get_highlight_name, true, false },
+ { EXPAND_EVENTS, expand_get_event_name, true, false },
+ { EXPAND_AUGROUP, expand_get_augroup_name, true, false },
+ { EXPAND_CSCOPE, get_cscope_name, true, true },
+ { EXPAND_SIGN, get_sign_name, true, true },
+ { EXPAND_PROFILE, get_profile_name, true, true },
+#ifdef HAVE_WORKING_LIBINTL
+ { EXPAND_LANGUAGE, get_lang_arg, true, false },
+ { EXPAND_LOCALES, get_locales, true, false },
+#endif
+ { EXPAND_ENV_VARS, get_env_name, true, true },
+ { EXPAND_USER, get_users, true, false },
+ { EXPAND_ARGLIST, get_arglist_name, true, false },
+ { EXPAND_CHECKHEALTH, get_healthcheck_names, true, false },
+ };
+ int ret = FAIL;
+
+ // Find a context in the table and call the ExpandGeneric() with the
+ // right function to do the expansion.
+ for (int i = 0; i < (int)ARRAY_SIZE(tab); i++) {
+ if (xp->xp_context == tab[i].context) {
+ if (tab[i].ic) {
+ rmp->rm_ic = true;
+ }
+ ExpandGeneric(xp, rmp, num_file, file, tab[i].func, tab[i].escaped);
+ ret = OK;
+ break;
+ }
+ }
+
+ return ret;
+}
+
/// Do the expansion based on xp->xp_context and "pat".
///
/// @param options WILD_ flags
@@ -1937,62 +2124,7 @@ static int ExpandFromContext(expand_T *xp, char_u *pat, int *num_file, char ***f
if (xp->xp_context == EXPAND_FILES
|| xp->xp_context == EXPAND_DIRECTORIES
|| xp->xp_context == EXPAND_FILES_IN_PATH) {
- // Expand file or directory names.
- bool free_pat = false;
- int i;
-
- // for ":set path=" and ":set tags=" halve backslashes for escaped space
- if (xp->xp_backslash != XP_BS_NONE) {
- free_pat = true;
- pat = vim_strsave(pat);
- for (i = 0; pat[i]; i++) {
- if (pat[i] == '\\') {
- if (xp->xp_backslash == XP_BS_THREE
- && pat[i + 1] == '\\'
- && pat[i + 2] == '\\'
- && pat[i + 3] == ' ') {
- STRMOVE(pat + i, pat + i + 3);
- }
- if (xp->xp_backslash == XP_BS_ONE
- && pat[i + 1] == ' ') {
- STRMOVE(pat + i, pat + i + 1);
- }
- }
- }
- }
-
- if (xp->xp_context == EXPAND_FILES) {
- flags |= EW_FILE;
- } else if (xp->xp_context == EXPAND_FILES_IN_PATH) {
- flags |= (EW_FILE | EW_PATH);
- } else {
- flags = (flags | EW_DIR) & ~EW_FILE;
- }
- if (options & WILD_ICASE) {
- flags |= EW_ICASE;
- }
-
- // Expand wildcards, supporting %:h and the like.
- ret = expand_wildcards_eval(&pat, num_file, file, flags);
- if (free_pat) {
- xfree(pat);
- }
-#ifdef BACKSLASH_IN_FILENAME
- if (p_csl[0] != NUL && (options & WILD_IGNORE_COMPLETESLASH) == 0) {
- for (int i = 0; i < *num_file; i++) {
- char_u *ptr = (*file)[i];
- while (*ptr != NUL) {
- if (p_csl[0] == 's' && *ptr == '\\') {
- *ptr = '/';
- } else if (p_csl[0] == 'b' && *ptr == '/') {
- *ptr = '\\';
- }
- ptr += utfc_ptr2len(ptr);
- }
- }
- }
-#endif
- return ret;
+ return expand_files_and_dirs(xp, pat, file, num_file, flags, options);
}
*file = NULL;
@@ -2029,19 +2161,19 @@ static int ExpandFromContext(expand_T *xp, char_u *pat, int *num_file, char ***f
}
if (xp->xp_context == EXPAND_COLORS) {
char *directories[] = { "colors", NULL };
- return ExpandRTDir(pat, DIP_START + DIP_OPT + DIP_LUA, num_file, file, directories);
+ return ExpandRTDir((char *)pat, DIP_START + DIP_OPT + DIP_LUA, num_file, file, directories);
}
if (xp->xp_context == EXPAND_COMPILER) {
char *directories[] = { "compiler", NULL };
- return ExpandRTDir(pat, DIP_LUA, num_file, file, directories);
+ return ExpandRTDir((char *)pat, DIP_LUA, num_file, file, directories);
}
if (xp->xp_context == EXPAND_OWNSYNTAX) {
char *directories[] = { "syntax", NULL };
- return ExpandRTDir(pat, 0, num_file, file, directories);
+ return ExpandRTDir((char *)pat, 0, num_file, file, directories);
}
if (xp->xp_context == EXPAND_FILETYPE) {
char *directories[] = { "syntax", "indent", "ftplugin", NULL };
- return ExpandRTDir(pat, DIP_LUA, num_file, file, directories);
+ return ExpandRTDir((char *)pat, DIP_LUA, num_file, file, directories);
}
if (xp->xp_context == EXPAND_USER_LIST) {
return ExpandUserList(xp, num_file, file);
@@ -2050,7 +2182,7 @@ static int ExpandFromContext(expand_T *xp, char_u *pat, int *num_file, char ***f
return ExpandUserLua(xp, num_file, file);
}
if (xp->xp_context == EXPAND_PACKADD) {
- return ExpandPackAddDir(pat, num_file, file);
+ return ExpandPackAddDir((char *)pat, num_file, file);
}
// When expanding a function name starting with s:, match the <SNR>nr_
@@ -2085,60 +2217,7 @@ static int ExpandFromContext(expand_T *xp, char_u *pat, int *num_file, char ***f
} else if (xp->xp_context == EXPAND_USER_DEFINED) {
ret = ExpandUserDefined(xp, &regmatch, num_file, file);
} else {
- typedef CompleteListItemGetter ExpandFunc;
- static struct expgen {
- int context;
- ExpandFunc func;
- int ic;
- int escaped;
- } tab[] = {
- { EXPAND_COMMANDS, get_command_name, false, true },
- { EXPAND_BEHAVE, get_behave_arg, true, true },
- { EXPAND_MAPCLEAR, get_mapclear_arg, true, true },
- { EXPAND_MESSAGES, get_messages_arg, true, true },
- { EXPAND_HISTORY, get_history_arg, true, true },
- { EXPAND_USER_COMMANDS, get_user_commands, false, true },
- { EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, false, true },
- { EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, false, true },
- { EXPAND_USER_NARGS, get_user_cmd_nargs, false, true },
- { EXPAND_USER_COMPLETE, get_user_cmd_complete, false, true },
- { EXPAND_USER_VARS, get_user_var_name, false, true },
- { EXPAND_FUNCTIONS, get_function_name, false, true },
- { EXPAND_USER_FUNC, get_user_func_name, false, true },
- { EXPAND_EXPRESSION, get_expr_name, false, true },
- { EXPAND_MENUS, get_menu_name, false, true },
- { EXPAND_MENUNAMES, get_menu_names, false, true },
- { EXPAND_SYNTAX, get_syntax_name, true, true },
- { EXPAND_SYNTIME, get_syntime_arg, true, true },
- { EXPAND_HIGHLIGHT, (ExpandFunc)get_highlight_name, true, true },
- { EXPAND_EVENTS, expand_get_event_name, true, false },
- { EXPAND_AUGROUP, expand_get_augroup_name, true, false },
- { EXPAND_CSCOPE, get_cscope_name, true, true },
- { EXPAND_SIGN, get_sign_name, true, true },
- { EXPAND_PROFILE, get_profile_name, true, true },
-#ifdef HAVE_WORKING_LIBINTL
- { EXPAND_LANGUAGE, get_lang_arg, true, false },
- { EXPAND_LOCALES, get_locales, true, false },
-#endif
- { EXPAND_ENV_VARS, get_env_name, true, true },
- { EXPAND_USER, get_users, true, false },
- { EXPAND_ARGLIST, get_arglist_name, true, false },
- { EXPAND_CHECKHEALTH, get_healthcheck_names, true, false },
- };
-
- // Find a context in the table and call the ExpandGeneric() with the
- // right function to do the expansion.
- ret = FAIL;
- for (int i = 0; i < (int)ARRAY_SIZE(tab); i++) {
- if (xp->xp_context == tab[i].context) {
- if (tab[i].ic) {
- regmatch.rm_ic = true;
- }
- ExpandGeneric(xp, &regmatch, num_file, file, tab[i].func, tab[i].escaped);
- ret = OK;
- break;
- }
- }
+ ret = ExpandOther(xp, &regmatch, num_file, file);
}
vim_regfree(regmatch.regprog);
@@ -2494,7 +2573,7 @@ static int ExpandUserLua(expand_T *xp, int *num_file, char ***file)
/// Expand `file` for all comma-separated directories in `path`.
/// Adds matches to `ga`.
-void globpath(char *path, char_u *file, garray_T *ga, int expand_options)
+void globpath(char *path, char *file, garray_T *ga, int expand_options)
{
expand_T xpc;
ExpandInit(&xpc);
@@ -2732,7 +2811,7 @@ void wildmenu_cleanup(CmdlineInfo *cclp)
p_ls = save_p_ls;
p_wmh = save_p_wmh;
last_status(false);
- update_screen(VALID); // redraw the screen NOW
+ update_screen(UPD_VALID); // redraw the screen NOW
redrawcmd();
save_p_ls = -1;
wild_menu_showing = 0;
@@ -2751,7 +2830,7 @@ void wildmenu_cleanup(CmdlineInfo *cclp)
}
/// "getcompletion()" function
-void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_getcompletion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char_u *pat;
expand_T xpc;
diff --git a/src/nvim/cmdhist.c b/src/nvim/cmdhist.c
index 13f97ba1e8..1426054d0b 100644
--- a/src/nvim/cmdhist.c
+++ b/src/nvim/cmdhist.c
@@ -90,14 +90,14 @@ static char *(history_names[]) = {
/// arguments of the ":history command.
char *get_history_arg(expand_T *xp, int idx)
{
- static char_u compl[2] = { NUL, NUL };
- char *short_names = ":=@>?/";
- int short_names_count = (int)STRLEN(short_names);
- int history_name_count = ARRAY_SIZE(history_names) - 1;
+ const char *short_names = ":=@>?/";
+ const int short_names_count = (int)STRLEN(short_names);
+ const int history_name_count = ARRAY_SIZE(history_names) - 1;
if (idx < short_names_count) {
- compl[0] = (char_u)short_names[idx];
- return (char *)compl;
+ xp->xp_buf[0] = short_names[idx];
+ xp->xp_buf[1] = NUL;
+ return xp->xp_buf;
}
if (idx < short_names_count + history_name_count) {
return history_names[idx - short_names_count];
@@ -494,7 +494,7 @@ static int del_history_idx(int histype, int idx)
}
/// "histadd()" function
-void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_histadd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
HistoryType histype;
@@ -517,7 +517,7 @@ void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "histdel()" function
-void f_histdel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_histdel(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int n;
const char *const str = tv_get_string_chk(&argvars[0]); // NULL on type error
@@ -540,7 +540,7 @@ void f_histdel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "histget()" function
-void f_histget(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_histget(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
HistoryType type;
int idx;
@@ -562,7 +562,7 @@ void f_histget(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "histnr()" function
-void f_histnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_histnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const histname = tv_get_string_chk(&argvars[0]);
HistoryType i = histname == NULL
diff --git a/src/nvim/context.c b/src/nvim/context.c
index e3ae9355bf..34692cdf64 100644
--- a/src/nvim/context.c
+++ b/src/nvim/context.c
@@ -345,7 +345,7 @@ Dictionary ctx_to_dict(Context *ctx)
PUT(rv, "jumps", ARRAY_OBJ(sbuf_to_array(ctx->jumps)));
PUT(rv, "bufs", ARRAY_OBJ(sbuf_to_array(ctx->bufs)));
PUT(rv, "gvars", ARRAY_OBJ(sbuf_to_array(ctx->gvars)));
- PUT(rv, "funcs", ARRAY_OBJ(copy_array(ctx->funcs)));
+ PUT(rv, "funcs", ARRAY_OBJ(copy_array(ctx->funcs, NULL)));
return rv;
}
@@ -381,7 +381,7 @@ int ctx_from_dict(Dictionary dict, Context *ctx)
ctx->gvars = array_to_sbuf(item.value.data.array);
} else if (strequal(item.key.data, "funcs")) {
types |= kCtxFuncs;
- ctx->funcs = copy_object(item.value).data.array;
+ ctx->funcs = copy_object(item.value, NULL).data.array;
}
}
diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c
index d4670dedc7..ed0488cf76 100644
--- a/src/nvim/cursor.c
+++ b/src/nvim/cursor.c
@@ -137,14 +137,18 @@ static int coladvance2(pos_T *pos, bool addspaces, bool finetune, colnr_T wcol_a
}
}
- char_u *ptr = line;
- while (col <= wcol && *ptr != NUL) {
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, pos->lnum, 0, line, line);
+ while (cts.cts_vcol <= wcol && *cts.cts_ptr != NUL) {
// Count a tab for what it's worth (if list mode not on)
- csize = win_lbr_chartabsize(curwin, line, ptr, col, &head);
- MB_PTR_ADV(ptr);
- col += csize;
+ csize = win_lbr_chartabsize(&cts, &head);
+ MB_PTR_ADV(cts.cts_ptr);
+ cts.cts_vcol += csize;
}
- idx = (int)(ptr - line);
+ col = cts.cts_vcol;
+ idx = (int)(cts.cts_ptr - (char *)line);
+ clear_chartabsize_arg(&cts);
+
// Handle all the special cases. The virtual_active() check
// is needed to ensure that a virtual position off the end of
// a line has the correct indexing. The one_more comparison
@@ -471,7 +475,7 @@ bool leftcol_changed(void)
if (retval) {
curwin->w_set_curswant = true;
}
- redraw_later(curwin, NOT_VALID);
+ redraw_later(curwin, UPD_NOT_VALID);
return retval;
}
diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c
index 9c33b1a806..73ad99876a 100644
--- a/src/nvim/cursor_shape.c
+++ b/src/nvim/cursor_shape.c
@@ -120,7 +120,7 @@ char *parse_shape_opt(int what)
}
}
// Repeat for all comma separated parts.
- char *modep = (char *)p_guicursor;
+ char *modep = p_guicursor;
while (modep != NULL && *modep != NUL) {
colonp = vim_strchr(modep, ':');
commap = vim_strchr(modep, ',');
diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c
index a061bd961b..36df62b502 100644
--- a/src/nvim/debugger.c
+++ b/src/nvim/debugger.c
@@ -47,7 +47,7 @@ struct debuggy {
/// Debug mode. Repeatedly get Ex commands, until told to continue normal
/// execution.
-void do_debug(char_u *cmd)
+void do_debug(char *cmd)
{
int save_msg_scroll = msg_scroll;
int save_State = State;
@@ -239,11 +239,11 @@ void do_debug(char_u *cmd)
last_cmd = CMD_STEP;
break;
case CMD_BACKTRACE:
- do_showbacktrace(cmd);
+ do_showbacktrace((char_u *)cmd);
continue;
case CMD_FRAME:
if (*p == NUL) {
- do_showbacktrace(cmd);
+ do_showbacktrace((char_u *)cmd);
} else {
p = skipwhite(p);
do_setdebugtracelevel((char_u *)p);
@@ -275,7 +275,7 @@ void do_debug(char_u *cmd)
RedrawingDisabled--;
no_wait_return--;
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
need_wait_return = false;
msg_scroll = save_msg_scroll;
lines_left = Rows - 1;
@@ -414,7 +414,7 @@ void dbg_check_breakpoint(exarg_T *eap)
debug_breakpoint_name + (*p == NUL ? 0 : 3),
(int64_t)debug_breakpoint_lnum);
debug_breakpoint_name = NULL;
- do_debug((char_u *)eap->cmd);
+ do_debug(eap->cmd);
} else {
debug_skipped = true;
debug_skipped_name = debug_breakpoint_name;
@@ -422,7 +422,7 @@ void dbg_check_breakpoint(exarg_T *eap)
}
} else if (ex_nesting_level <= debug_break_level) {
if (!eap->skip) {
- do_debug((char_u *)eap->cmd);
+ do_debug(eap->cmd);
} else {
debug_skipped = true;
debug_skipped_name = NULL;
@@ -703,7 +703,7 @@ void ex_breaklist(exarg_T *eap)
smsg(_("%3d %s %s line %" PRId64),
bp->dbg_nr,
bp->dbg_type == DBG_FUNC ? "func" : "file",
- bp->dbg_type == DBG_FUNC ? bp->dbg_name : NameBuff,
+ bp->dbg_type == DBG_FUNC ? bp->dbg_name : (char_u *)NameBuff,
(int64_t)bp->dbg_lnum);
} else {
smsg(_("%3d expr %s"), bp->dbg_nr, bp->dbg_name);
@@ -718,9 +718,9 @@ void ex_breaklist(exarg_T *eap)
/// @param file true for a file, false for a function
/// @param fname file or function name
/// @param after after this line number
-linenr_T dbg_find_breakpoint(bool file, char_u *fname, linenr_T after)
+linenr_T dbg_find_breakpoint(bool file, char *fname, linenr_T after)
{
- return debuggy_find(file, fname, after, &dbg_breakp, NULL);
+ return debuggy_find(file, (char_u *)fname, after, &dbg_breakp, NULL);
}
/// @param file true for a file, false for a function
@@ -728,9 +728,9 @@ linenr_T dbg_find_breakpoint(bool file, char_u *fname, linenr_T after)
/// @param fp[out] forceit
///
/// @returns true if profiling is on for a function or sourced file.
-bool has_profiling(bool file, char_u *fname, bool *fp)
+bool has_profiling(bool file, char *fname, bool *fp)
{
- return debuggy_find(file, fname, (linenr_T)0, &prof_ga, fp)
+ return debuggy_find(file, (char_u *)fname, (linenr_T)0, &prof_ga, fp)
!= (linenr_T)0;
}
@@ -825,9 +825,9 @@ static linenr_T debuggy_find(bool file, char_u *fname, linenr_T after, garray_T
}
/// Called when a breakpoint was encountered.
-void dbg_breakpoint(char_u *name, linenr_T lnum)
+void dbg_breakpoint(char *name, linenr_T lnum)
{
// We need to check if this line is actually executed in do_one_cmd()
- debug_breakpoint_name = name;
+ debug_breakpoint_name = (char_u *)name;
debug_breakpoint_lnum = lnum;
}
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index a93fb599c4..9f3e5a8638 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -547,7 +547,7 @@ int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines)
}
int virt_lines = 0;
- int row = (int)MAX(lnum - 2, 0);
+ int row = MAX(lnum - 2, 0);
int end_row = (int)lnum;
MarkTreeIter itr[1] = { 0 };
marktree_itr_get(buf->b_marktree, row, 0, itr);
@@ -558,7 +558,7 @@ int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines)
} else if (marktree_decor_level(mark) < kDecorLevelVirtLine) {
goto next_mark;
}
- bool above = mark.pos.row > (int)(lnum - 2);
+ bool above = mark.pos.row > (lnum - 2);
Decoration *decor = mark.decor_full;
if (decor && decor->virt_lines_above == above) {
virt_lines += (int)kv_size(decor->virt_lines);
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 5485d528f7..1cfb535fe8 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -120,7 +120,7 @@ void diff_buf_delete(buf_T *buf)
// don't redraw right away, more might change or buffer state
// is invalid right now
need_diff_redraw = true;
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
}
}
}
@@ -573,9 +573,9 @@ static void diff_check_unchanged(tabpage_T *tp, diff_T *dp)
if (dir == BACKWARD) {
off_org = dp->df_count[i_org] - 1;
}
- char_u *line_org = vim_strsave(ml_get_buf(tp->tp_diffbuf[i_org],
- dp->df_lnum[i_org] + off_org,
- false));
+ char *line_org = (char *)vim_strsave(ml_get_buf(tp->tp_diffbuf[i_org],
+ dp->df_lnum[i_org] + off_org,
+ false));
int i_new;
for (i_new = i_org + 1; i_new < DB_COUNT; i_new++) {
@@ -592,9 +592,9 @@ static void diff_check_unchanged(tabpage_T *tp, diff_T *dp)
break;
}
- if (diff_cmp(line_org, ml_get_buf(tp->tp_diffbuf[i_new],
- dp->df_lnum[i_new] + off_new,
- false)) != 0) {
+ if (diff_cmp((char_u *)line_org, ml_get_buf(tp->tp_diffbuf[i_new],
+ dp->df_lnum[i_new] + off_new,
+ false)) != 0) {
break;
}
}
@@ -659,7 +659,7 @@ void diff_redraw(bool dofold)
continue;
}
- redraw_later(wp, SOME_VALID);
+ redraw_later(wp, UPD_SOME_VALID);
if (wp != curwin) {
wp_other = wp;
}
@@ -797,8 +797,8 @@ static int diff_write(buf_T *buf, diffin_T *din)
}
// Always use 'fileformat' set to "unix".
- char_u *save_ff = buf->b_p_ff;
- buf->b_p_ff = vim_strsave((char_u *)FF_UNIX);
+ char *save_ff = buf->b_p_ff;
+ buf->b_p_ff = xstrdup(FF_UNIX);
const bool save_cmod_flags = cmdmod.cmod_flags;
// Writing the buffer is an implementation detail of performing the diff,
// so it shouldn't update the '[ and '] marks.
@@ -1148,7 +1148,7 @@ static int diff_file(diffio_T *dio)
(diff_flags & DIFF_IBLANK) ? "-B " : "",
(diff_flags & DIFF_ICASE) ? "-i " : "",
tmp_orig, tmp_new);
- append_redir(cmd, len, (char *)p_srr, tmp_diff);
+ append_redir(cmd, len, p_srr, tmp_diff);
block_autocmds(); // Avoid ShellCmdPost stuff
(void)call_shell((char_u *)cmd,
kShellOptFilter | kShellOptSilent | kShellOptDoOut,
@@ -1374,7 +1374,7 @@ static void set_diff_option(win_T *wp, int value)
curwin = wp;
curbuf = curwin->w_buffer;
curbuf->b_ro_locked++;
- set_option_value("diff", (long)value, NULL, OPT_LOCAL);
+ set_option_value_give_err("diff", (long)value, NULL, OPT_LOCAL);
curbuf->b_ro_locked--;
curwin = old_curwin;
curbuf = curwin->w_buffer;
@@ -1413,7 +1413,7 @@ void diff_win_options(win_T *wp, int addbuf)
if (wp->w_p_diff_saved) {
free_string_option(wp->w_p_fdm_save);
}
- wp->w_p_fdm_save = vim_strsave(wp->w_p_fdm);
+ wp->w_p_fdm_save = xstrdup(wp->w_p_fdm);
}
set_string_option_direct_in_win(wp, "fdm", -1, "diff", OPT_LOCAL | OPT_FREE, 0);
@@ -1424,12 +1424,12 @@ void diff_win_options(win_T *wp, int addbuf)
if (wp->w_p_diff_saved) {
free_string_option(wp->w_p_fdc_save);
}
- wp->w_p_fdc_save = vim_strsave(wp->w_p_fdc);
+ wp->w_p_fdc_save = xstrdup(wp->w_p_fdc);
}
free_string_option(wp->w_p_fdc);
- wp->w_p_fdc = (char_u *)xstrdup("2");
+ wp->w_p_fdc = xstrdup("2");
assert(diff_foldcolumn >= 0 && diff_foldcolumn <= 9);
- snprintf((char *)wp->w_p_fdc, STRLEN(wp->w_p_fdc) + 1, "%d", diff_foldcolumn);
+ snprintf(wp->w_p_fdc, STRLEN(wp->w_p_fdc) + 1, "%d", diff_foldcolumn);
wp->w_p_fen = true;
wp->w_p_fdl = 0;
foldUpdateAll(wp);
@@ -1448,7 +1448,7 @@ void diff_win_options(win_T *wp, int addbuf)
if (addbuf) {
diff_buf_add(wp->w_buffer);
}
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
}
/// Set options not to show diffs. For the current window or all windows.
@@ -1480,11 +1480,9 @@ void ex_diffoff(exarg_T *eap)
}
}
free_string_option(wp->w_p_fdm);
- wp->w_p_fdm = vim_strsave(*wp->w_p_fdm_save
- ? wp->w_p_fdm_save
- : (char_u *)"manual");
+ wp->w_p_fdm = xstrdup(*wp->w_p_fdm_save ? wp->w_p_fdm_save : "manual");
free_string_option(wp->w_p_fdc);
- wp->w_p_fdc = vim_strsave(wp->w_p_fdc_save);
+ wp->w_p_fdc = xstrdup(wp->w_p_fdc_save);
if (wp->w_p_fdl == 0) {
wp->w_p_fdl = wp->w_p_fdl_save;
@@ -1541,8 +1539,8 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
diff_T *dp = curtab->tp_first_diff;
diff_T *dn, *dpl;
diffout_T *dout = &dio->dio_diff;
- char_u linebuf[LBUFLEN]; // only need to hold the diff line
- char_u *line;
+ char linebuf[LBUFLEN]; // only need to hold the diff line
+ char *line;
linenr_T off;
int i;
int notset = true; // block "*dp" not set yet
@@ -1578,9 +1576,9 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
if (line_idx >= dout->dout_ga.ga_len) {
break; // did last line
}
- line = ((char_u **)dout->dout_ga.ga_data)[line_idx++];
+ line = ((char **)dout->dout_ga.ga_data)[line_idx++];
} else {
- if (vim_fgets(linebuf, LBUFLEN, fd)) {
+ if (vim_fgets((char_u *)linebuf, LBUFLEN, fd)) {
break; // end of file
}
line = linebuf;
@@ -1602,9 +1600,9 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
} else if ((STRNCMP(line, "@@ ", 3) == 0)) {
diffstyle = DIFF_UNIFIED;
} else if ((STRNCMP(line, "--- ", 4) == 0) // -V501
- && (vim_fgets(linebuf, LBUFLEN, fd) == 0) // -V501
+ && (vim_fgets((char_u *)linebuf, LBUFLEN, fd) == 0) // -V501
&& (STRNCMP(line, "+++ ", 4) == 0)
- && (vim_fgets(linebuf, LBUFLEN, fd) == 0) // -V501
+ && (vim_fgets((char_u *)linebuf, LBUFLEN, fd) == 0) // -V501
&& (STRNCMP(line, "@@ ", 3) == 0)) {
diffstyle = DIFF_UNIFIED;
} else {
@@ -1618,7 +1616,7 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
if (!isdigit(*line)) {
continue; // not the start of a diff block
}
- if (parse_diff_ed(line, hunk) == FAIL) {
+ if (parse_diff_ed((char_u *)line, hunk) == FAIL) {
continue;
}
} else {
@@ -1626,7 +1624,7 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
if (STRNCMP(line, "@@ ", 3) != 0) {
continue; // not the start of a diff block
}
- if (parse_diff_unified(line, hunk) == FAIL) {
+ if (parse_diff_unified((char_u *)line, hunk) == FAIL) {
continue;
}
}
@@ -1922,11 +1920,11 @@ static bool diff_equal_entry(diff_T *dp, int idx1, int idx2)
}
for (int i = 0; i < dp->df_count[idx1]; i++) {
- char_u *line = vim_strsave(ml_get_buf(curtab->tp_diffbuf[idx1],
- dp->df_lnum[idx1] + i, false));
+ char *line = (char *)vim_strsave(ml_get_buf(curtab->tp_diffbuf[idx1],
+ dp->df_lnum[idx1] + i, false));
- int cmp = diff_cmp(line, ml_get_buf(curtab->tp_diffbuf[idx2],
- dp->df_lnum[idx2] + i, false));
+ int cmp = diff_cmp((char_u *)line, ml_get_buf(curtab->tp_diffbuf[idx2],
+ dp->df_lnum[idx2] + i, false));
xfree(line);
if (cmp != 0) {
@@ -2141,7 +2139,7 @@ int diffopt_changed(void)
long diff_algorithm_new = 0;
long diff_indent_heuristic = 0;
- char *p = (char *)p_dip;
+ char *p = p_dip;
while (*p != NUL) {
if (STRNCMP(p, "filler", 6) == 0) {
p += 6;
@@ -2283,7 +2281,7 @@ bool diffopt_filler(void)
bool diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- char_u *line_new;
+ char *line_new;
int si_org;
int si_new;
int ei_org;
@@ -2292,7 +2290,7 @@ bool diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)
int l;
// Make a copy of the line, the next ml_get() will invalidate it.
- char_u *line_org = vim_strsave(ml_get_buf(wp->w_buffer, lnum, false));
+ char *line_org = (char *)vim_strsave(ml_get_buf(wp->w_buffer, lnum, false));
int idx = diff_buf_idx(wp->w_buffer);
if (idx == DB_COUNT) {
@@ -2324,8 +2322,8 @@ bool diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)
continue;
}
added = false;
- line_new = ml_get_buf(curtab->tp_diffbuf[i],
- dp->df_lnum[i] + off, false);
+ line_new = (char *)ml_get_buf(curtab->tp_diffbuf[i],
+ dp->df_lnum[i] + off, false);
// Search for start of difference
si_org = si_new = 0;
@@ -2337,10 +2335,10 @@ bool diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)
|| ((diff_flags & DIFF_IWHITEALL)
&& (ascii_iswhite(line_org[si_org])
|| ascii_iswhite(line_new[si_new])))) {
- si_org = (int)((char_u *)skipwhite((char *)line_org + si_org) - line_org);
- si_new = (int)((char_u *)skipwhite((char *)line_new + si_new) - line_new);
+ si_org = (int)(skipwhite(line_org + si_org) - line_org);
+ si_new = (int)(skipwhite(line_new + si_new) - line_new);
} else {
- if (!diff_equal_char(line_org + si_org, line_new + si_new, &l)) {
+ if (!diff_equal_char((char_u *)line_org + si_org, (char_u *)line_new + si_new, &l)) {
break;
}
si_org += l;
@@ -2350,8 +2348,8 @@ bool diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)
// Move back to first byte of character in both lines (may
// have "nn^" in line_org and "n^ in line_new).
- si_org -= utf_head_off(line_org, line_org + si_org);
- si_new -= utf_head_off(line_new, line_new + si_new);
+ si_org -= utf_head_off((char_u *)line_org, (char_u *)line_org + si_org);
+ si_new -= utf_head_off((char_u *)line_new, (char_u *)line_new + si_new);
if (*startp > si_org) {
*startp = si_org;
@@ -2380,11 +2378,11 @@ bool diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)
ei_new--;
}
} else {
- const char_u *p1 = line_org + ei_org;
- const char_u *p2 = line_new + ei_new;
+ const char_u *p1 = (char_u *)line_org + ei_org;
+ const char_u *p2 = (char_u *)line_new + ei_new;
- p1 -= utf_head_off(line_org, p1);
- p2 -= utf_head_off(line_new, p2);
+ p1 -= utf_head_off((char_u *)line_org, p1);
+ p2 -= utf_head_off((char_u *)line_new, p2);
if (!diff_equal_char(p1, p2, &l)) {
break;
@@ -2513,7 +2511,7 @@ void ex_diffgetput(exarg_T *eap)
diff_T *dfree;
int i;
int added;
- char_u *p;
+ char *p;
aco_save_T aco;
buf_T *buf;
linenr_T start_skip;
@@ -2567,18 +2565,18 @@ void ex_diffgetput(exarg_T *eap)
}
} else {
// Buffer number or pattern given. Ignore trailing white space.
- p = (char_u *)eap->arg + STRLEN(eap->arg);
- while (p > (char_u *)eap->arg && ascii_iswhite(p[-1])) {
+ p = eap->arg + STRLEN(eap->arg);
+ while (p > eap->arg && ascii_iswhite(p[-1])) {
p--;
}
- for (i = 0; ascii_isdigit(eap->arg[i]) && (char_u *)eap->arg + i < p; i++) {}
+ for (i = 0; ascii_isdigit(eap->arg[i]) && eap->arg + i < p; i++) {}
- if ((char_u *)eap->arg + i == p) {
+ if (eap->arg + i == p) {
// digits only
i = (int)atol(eap->arg);
} else {
- i = buflist_findpat(eap->arg, (char *)p, false, true, false);
+ i = buflist_findpat(eap->arg, p, false, true, false);
if (i < 0) {
// error message already given
@@ -2720,8 +2718,8 @@ void ex_diffgetput(exarg_T *eap)
if (nr > curtab->tp_diffbuf[idx_from]->b_ml.ml_line_count) {
break;
}
- p = vim_strsave(ml_get_buf(curtab->tp_diffbuf[idx_from], nr, false));
- ml_append(lnum + i - 1, (char *)p, 0, false);
+ p = (char *)vim_strsave(ml_get_buf(curtab->tp_diffbuf[idx_from], nr, false));
+ ml_append(lnum + i - 1, p, 0, false);
xfree(p);
added++;
if (buf_empty && (curbuf->b_ml.ml_line_count == 2)) {
diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c
index 0f511bd37c..e4528f9038 100644
--- a/src/nvim/digraph.c
+++ b/src/nvim/digraph.c
@@ -1695,7 +1695,7 @@ static void digraph_header(const char *msg)
if (msg_col > 0) {
msg_putchar('\n');
}
- msg_outtrans_attr((const char_u *)msg, HL_ATTR(HLF_CM));
+ msg_outtrans_attr(msg, HL_ATTR(HLF_CM));
msg_putchar('\n');
}
@@ -1856,7 +1856,7 @@ static void printdigraph(const digr_T *dp, result_T *previous)
p += utf_char2bytes(dp->result, (char *)p);
*p = NUL;
- msg_outtrans_attr(buf, HL_ATTR(HLF_8));
+ msg_outtrans_attr((char *)buf, HL_ATTR(HLF_8));
p = buf;
if (char2cells(dp->result) == 1) {
*p++ = ' ';
@@ -1917,7 +1917,7 @@ static bool digraph_set_common(const typval_T *argchars, const typval_T *argdigr
}
/// "digraph_get()" function
-void f_digraph_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_digraph_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL; // Return empty string for failure
@@ -1938,7 +1938,7 @@ void f_digraph_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "digraph_getlist()" function
-void f_digraph_getlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_digraph_getlist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
bool flag_list_all;
@@ -1957,7 +1957,7 @@ void f_digraph_getlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "digraph_set()" function
-void f_digraph_set(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_digraph_set(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_BOOL;
rettv->vval.v_bool = kBoolVarFalse;
@@ -1970,7 +1970,7 @@ void f_digraph_set(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "digraph_setlist()" function
-void f_digraph_setlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_digraph_setlist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_BOOL;
rettv->vval.v_bool = kBoolVarFalse;
@@ -2096,10 +2096,10 @@ void ex_loadkeymap(exarg_T *eap)
if ((*p != '"') && (*p != NUL)) {
kmap_T *kp = GA_APPEND_VIA_PTR(kmap_T, &curbuf->b_kmap_ga);
- s = skiptowhite(p);
+ s = (char_u *)skiptowhite((char *)p);
kp->from = vim_strnsave(p, (size_t)(s - p));
p = (char_u *)skipwhite((char *)s);
- s = skiptowhite(p);
+ s = (char_u *)skiptowhite((char *)p);
kp->to = vim_strnsave(p, (size_t)(s - p));
if ((STRLEN(kp->from) + STRLEN(kp->to) >= KMAP_LLEN)
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index 2b1b2607fb..b6c4400c60 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -116,7 +116,7 @@ static int line_putchar(buf_T *buf, LineState *s, schar_T *dest, int maxcells, b
if (cells > maxcells) {
return -1;
}
- u8c = utfc_ptr2char(p, u8cc);
+ u8c = utfc_ptr2char((char *)p, u8cc);
if (*p == TAB) {
cells = MIN(tabstop_padding(vcol, buf->b_p_ts, buf->b_p_vts_array), maxcells);
for (int c = 0; c < cells; c++) {
@@ -141,7 +141,7 @@ static int line_putchar(buf_T *buf, LineState *s, schar_T *dest, int maxcells, b
nc = utf_ptr2char((char *)p + c_len);
s->prev_c1 = u8cc[0];
} else {
- pc = utfc_ptr2char(p + c_len, pcc);
+ pc = utfc_ptr2char((char *)p + c_len, pcc);
nc = s->prev_c;
pc1 = pcc[0];
}
@@ -277,7 +277,7 @@ static bool use_cursor_line_sign(win_T *wp, linenr_T lnum)
}
// Get information needed to display the sign in line 'lnum' in window 'wp'.
-// If 'nrcol' is TRUE, the sign is going to be displayed in the number column.
+// If 'nrcol' is true, the sign is going to be displayed in the number column.
// Otherwise the sign is going to be displayed in the sign column.
//
// @param count max number of signs
@@ -870,7 +870,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (has_spell && !number_only) {
// For checking first word with a capital skip white space.
if (cap_col == 0) {
- cap_col = (int)getwhitecols(line);
+ cap_col = (int)getwhitecols((char *)line);
}
// To be able to spell-check over line boundaries copy the end of the
@@ -940,12 +940,19 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
if (v > 0 && !number_only) {
char_u *prev_ptr = ptr;
- while (vcol < v && *ptr != NUL) {
- c = win_lbr_chartabsize(wp, line, ptr, (colnr_T)vcol, NULL);
- vcol += c;
- prev_ptr = ptr;
- MB_PTR_ADV(ptr);
+ chartabsize_T cts;
+ int charsize;
+
+ init_chartabsize_arg(&cts, wp, lnum, (colnr_T)vcol, line, ptr);
+ while (cts.cts_vcol < v && *cts.cts_ptr != NUL) {
+ charsize = win_lbr_chartabsize(&cts, NULL);
+ cts.cts_vcol += charsize;
+ prev_ptr = (char_u *)cts.cts_ptr;
+ MB_PTR_ADV(cts.cts_ptr);
}
+ vcol = cts.cts_vcol;
+ ptr = (char_u *)cts.cts_ptr;
+ clear_chartabsize_arg(&cts);
// When:
// - 'cuc' is set, or
@@ -963,11 +970,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// Handle a character that's not completely on the screen: Put ptr at
// that character but skip the first few screen characters.
if (vcol > v) {
- vcol -= c;
+ vcol -= charsize;
ptr = prev_ptr;
// If the character fits on the screen, don't need to skip it.
// Except for a TAB.
- if (utf_ptr2cells((char *)ptr) >= c || *ptr == TAB) {
+ if (utf_ptr2cells((char *)ptr) >= charsize || *ptr == TAB) {
n_skip = (int)(v - vcol);
}
}
@@ -1164,7 +1171,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (wp->w_p_rl) { // reverse line numbers
// like rl_mirror(), but keep the space at the end
char_u *p2 = (char_u *)skipwhite((char *)extra);
- p2 = skiptowhite(p2) - 1;
+ p2 = (char_u *)skiptowhite((char *)p2) - 1;
for (char_u *p1 = (char_u *)skipwhite((char *)extra); p1 < p2; p1++, p2--) {
const char_u t = *p1;
*p1 = *p2;
@@ -1247,7 +1254,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
char_attr = 0;
} else if (filler_todo > 0) {
- // draw "deleted" diff line(s)
+ // Draw "deleted" diff line(s)
if (char2cells(wp->w_p_fcs_chars.diff) > 1) {
c_extra = '-';
c_final = NUL;
@@ -1482,7 +1489,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (mb_l > n_extra) {
mb_l = 1;
} else if (mb_l > 1) {
- mb_c = utfc_ptr2char(p_extra, u8cc);
+ mb_c = utfc_ptr2char((char *)p_extra, u8cc);
mb_utf8 = true;
c = 0xc0;
}
@@ -1533,7 +1540,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
mb_l = utfc_ptr2len((char *)ptr);
mb_utf8 = false;
if (mb_l > 1) {
- mb_c = utfc_ptr2char(ptr, u8cc);
+ mb_c = utfc_ptr2char((char *)ptr, u8cc);
// Overlong encoded ASCII or ASCII with composing char
// is displayed normally, except a NUL.
if (mb_c < 0x80) {
@@ -1591,7 +1598,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
nc = utf_ptr2char((char *)ptr + mb_l);
prev_c1 = u8cc[0];
} else {
- pc = utfc_ptr2char(ptr + mb_l, pcc);
+ pc = utfc_ptr2char((char *)ptr + mb_l, pcc);
nc = prev_c;
pc1 = pcc[0];
}
@@ -1798,8 +1805,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
&& !vim_isbreak((int)(*ptr))) {
int mb_off = utf_head_off(line, ptr - 1);
char_u *p = ptr - (mb_off + 1);
- // TODO(neovim): is passing p for start of the line OK?
- n_extra = win_lbr_chartabsize(wp, line, p, (colnr_T)vcol, NULL) - 1;
+ chartabsize_T cts;
+
+ init_chartabsize_arg(&cts, wp, lnum, (colnr_T)vcol, line, p);
+ n_extra = win_lbr_chartabsize(&cts, NULL) - 1;
// We have just drawn the showbreak value, no need to add
// space for it again.
@@ -1825,6 +1834,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
c = ' ';
}
}
+ clear_chartabsize_arg(&cts);
}
in_multispace = c == ' ' && ((ptr > line + 1 && ptr[-2] == ' ') || *ptr == ' ');
@@ -2082,7 +2092,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (wp->w_p_cole > 0
&& (wp != curwin || lnum != wp->w_cursor.lnum || conceal_cursor_line(wp))
&& ((syntax_flags & HL_CONCEAL) != 0 || has_match_conc > 0 || decor_conceal > 0)
- && !(lnum_in_visual_area && vim_strchr((char *)wp->w_p_cocu, 'v') == NULL)) {
+ && !(lnum_in_visual_area && vim_strchr(wp->w_p_cocu, 'v') == NULL)) {
char_attr = conceal_attr;
if (((prev_syntax_id != syntax_seqnr && (syntax_flags & HL_CONCEAL) != 0)
|| has_match_conc > 1 || decor_conceal > 1)
diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c
index 2abff6c894..29ff261461 100644
--- a/src/nvim/drawscreen.c
+++ b/src/nvim/drawscreen.c
@@ -20,7 +20,7 @@
//
// Commands that scroll a window change w_topline and must call
// check_cursor() to move the cursor into the visible part of the window, and
-// call redraw_later(wp, VALID) to have the window displayed by update_screen()
+// call redraw_later(wp, UPD_VALID) to have the window displayed by update_screen()
// later.
//
// Commands that change text in the buffer must call changed_bytes() or
@@ -32,23 +32,23 @@
//
// Commands that change how a window is displayed (e.g., setting 'list') or
// invalidate the contents of a window in another way (e.g., change fold
-// settings), must call redraw_later(wp, NOT_VALID) to have the whole window
+// settings), must call redraw_later(wp, UPD_NOT_VALID) to have the whole window
// redisplayed by update_screen() later.
//
// Commands that change how a buffer is displayed (e.g., setting 'tabstop')
-// must call redraw_curbuf_later(NOT_VALID) to have all the windows for the
+// must call redraw_curbuf_later(UPD_NOT_VALID) to have all the windows for the
// buffer redisplayed by update_screen() later.
//
// Commands that change highlighting and possibly cause a scroll too must call
-// redraw_later(wp, SOME_VALID) to update the whole window but still use
+// redraw_later(wp, UPD_SOME_VALID) to update the whole window but still use
// scrolling to avoid redrawing everything. But the length of displayed lines
-// must not change, use NOT_VALID then.
+// must not change, use UPD_NOT_VALID then.
//
-// Commands that move the window position must call redraw_later(wp, NOT_VALID).
+// Commands that move the window position must call redraw_later(wp, UPD_NOT_VALID).
// TODO(neovim): should minimize redrawing by scrolling when possible.
//
// Commands that change everything (e.g., resizing the screen) must call
-// redraw_all_later(NOT_VALID) or redraw_all_later(CLEAR).
+// redraw_all_later(UPD_NOT_VALID) or redraw_all_later(UPD_CLEAR).
//
// Things that are handled indirectly:
// - When messages scroll the screen up, msg_scrolled will be set and
@@ -193,7 +193,7 @@ retry:
default_grid.col_offset = 0;
default_grid.handle = DEFAULT_GRID_HANDLE;
- must_redraw = CLEAR; // need to clear the screen later
+ must_redraw = UPD_CLEAR; // need to clear the screen later
RedrawingDisabled--;
@@ -235,18 +235,18 @@ void screenclear(void)
clear_cmdline = false;
mode_displayed = false;
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
redraw_cmdline = true;
redraw_tabline = true;
redraw_popupmenu = true;
pum_invalidate();
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_floating) {
- wp->w_redr_type = CLEAR;
+ wp->w_redr_type = UPD_CLEAR;
}
}
- if (must_redraw == CLEAR) {
- must_redraw = NOT_VALID; // no need to clear again
+ if (must_redraw == UPD_CLEAR) {
+ must_redraw = UPD_NOT_VALID; // no need to clear again
}
compute_cmdrow();
msg_row = cmdline_row; // put cursor on last line for messages
@@ -341,7 +341,7 @@ void screen_resize(int width, int height)
}
if (State & MODE_CMDLINE) {
redraw_popupmenu = false;
- update_screen(NOT_VALID);
+ update_screen(UPD_NOT_VALID);
redrawcmdline();
if (pum_drawn()) {
cmdline_pum_display(false);
@@ -355,7 +355,7 @@ void screen_resize(int width, int height)
redraw_popupmenu = false;
ins_compl_show_pum();
}
- update_screen(NOT_VALID);
+ update_screen(UPD_NOT_VALID);
if (redrawing()) {
setcursor();
}
@@ -371,7 +371,7 @@ void screen_resize(int width, int height)
/// Most code shouldn't call this directly, rather use redraw_later() and
/// and redraw_all_later() to mark parts of the screen as needing a redraw.
///
-/// @param type set to a NOT_VALID to force redraw of entire screen
+/// @param type set to a UPD_NOT_VALID to force redraw of entire screen
int update_screen(int type)
{
static bool did_intro = false;
@@ -403,15 +403,15 @@ int update_screen(int type)
}
// Need to update w_lines[].
- if (curwin->w_lines_valid == 0 && type < NOT_VALID) {
- type = NOT_VALID;
+ if (curwin->w_lines_valid == 0 && type < UPD_NOT_VALID) {
+ type = UPD_NOT_VALID;
}
// Postpone the redrawing when it's not needed and when being called
// recursively.
if (!redrawing() || updating_screen) {
must_redraw = type;
- if (type > INVERTED_ALL) {
+ if (type > UPD_INVERTED_ALL) {
curwin->w_lines_valid = 0; // don't use w_lines[].wl_size now
}
return FAIL;
@@ -428,7 +428,7 @@ int update_screen(int type)
msg_scrolled_at_flush = 0;
}
- if (type >= CLEAR || !default_grid.valid) {
+ if (type >= UPD_CLEAR || !default_grid.valid) {
ui_comp_set_screen_valid(false);
}
@@ -445,8 +445,8 @@ int update_screen(int type)
}
if (msg_use_msgsep()) {
msg_grid.throttled = false;
- // CLEAR is already handled
- if (type == NOT_VALID && !ui_has(kUIMultigrid) && msg_scrolled) {
+ // UPD_CLEAR is already handled
+ if (type == UPD_NOT_VALID && !ui_has(kUIMultigrid) && msg_scrolled) {
ui_comp_set_screen_valid(false);
for (int i = valid; i < Rows - p_ch; i++) {
grid_clear_line(&default_grid, default_grid.line_offset[i],
@@ -457,7 +457,7 @@ int update_screen(int type)
continue;
}
if (W_ENDROW(wp) > valid) {
- wp->w_redr_type = MAX(wp->w_redr_type, NOT_VALID);
+ wp->w_redr_type = MAX(wp->w_redr_type, UPD_NOT_VALID);
}
if (!is_stl_global && W_ENDROW(wp) + wp->w_status_height > valid) {
wp->w_redr_status = true;
@@ -469,35 +469,37 @@ int update_screen(int type)
}
msg_grid_set_pos(Rows - (int)p_ch, false);
msg_grid_invalid = false;
- } else if (msg_scrolled > Rows - 5) { // clearing is faster
- type = CLEAR;
- } else if (type != CLEAR) {
- check_for_delay(false);
- grid_ins_lines(&default_grid, 0, msg_scrolled, Rows, 0, Columns);
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_floating) {
- continue;
- }
- if (wp->w_winrow < msg_scrolled) {
- if (W_ENDROW(wp) > msg_scrolled
- && wp->w_redr_type < REDRAW_TOP
- && wp->w_lines_valid > 0
- && wp->w_topline == wp->w_lines[0].wl_lnum) {
- wp->w_upd_rows = msg_scrolled - wp->w_winrow;
- wp->w_redr_type = REDRAW_TOP;
- } else {
- wp->w_redr_type = NOT_VALID;
- if (wp->w_winrow + wp->w_winbar_height <= msg_scrolled) {
- wp->w_redr_status = true;
+ } else if (type != UPD_CLEAR) {
+ if (msg_scrolled > Rows - 5) { // redrawing is faster
+ type = UPD_NOT_VALID;
+ } else {
+ check_for_delay(false);
+ grid_ins_lines(&default_grid, 0, msg_scrolled, Rows, 0, Columns);
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (wp->w_floating) {
+ continue;
+ }
+ if (wp->w_winrow < msg_scrolled) {
+ if (W_ENDROW(wp) > msg_scrolled
+ && wp->w_redr_type < UPD_REDRAW_TOP
+ && wp->w_lines_valid > 0
+ && wp->w_topline == wp->w_lines[0].wl_lnum) {
+ wp->w_upd_rows = msg_scrolled - wp->w_winrow;
+ wp->w_redr_type = UPD_REDRAW_TOP;
+ } else {
+ wp->w_redr_type = UPD_NOT_VALID;
+ if (wp->w_winrow + wp->w_winbar_height <= msg_scrolled) {
+ wp->w_redr_status = true;
+ }
}
}
}
+ if (is_stl_global && Rows - p_ch - 1 <= msg_scrolled) {
+ curwin->w_redr_status = true;
+ }
+ redraw_cmdline = true;
+ redraw_tabline = true;
}
- if (is_stl_global && Rows - p_ch - 1 <= msg_scrolled) {
- curwin->w_redr_status = true;
- }
- redraw_cmdline = true;
- redraw_tabline = true;
}
msg_scrolled = 0;
msg_scrolled_at_flush = 0;
@@ -517,10 +519,10 @@ int update_screen(int type)
hl_changed = true;
}
- if (type == CLEAR) { // first clear screen
+ if (type == UPD_CLEAR) { // first clear screen
screenclear(); // will reset clear_cmdline
cmdline_screen_cleared(); // clear external cmdline state
- type = NOT_VALID;
+ type = UPD_NOT_VALID;
// must_redraw may be set indirectly, avoid another redraw later
must_redraw = 0;
} else if (!default_grid.valid) {
@@ -530,7 +532,7 @@ int update_screen(int type)
// After disabling msgsep the grid might not have been deallocated yet,
// hence we also need to check msg_grid.chars
- if (type == NOT_VALID && (msg_use_grid() || msg_grid.chars)) {
+ if (type == UPD_NOT_VALID && (msg_use_grid() || msg_grid.chars)) {
grid_fill(&default_grid, Rows - (int)p_ch, Rows, 0, Columns, ' ', ' ', 0);
}
@@ -551,23 +553,23 @@ int update_screen(int type)
// Force redraw when width of 'number' or 'relativenumber' column
// changes.
- if (curwin->w_redr_type < NOT_VALID
+ if (curwin->w_redr_type < UPD_NOT_VALID
&& curwin->w_nrwidth != ((curwin->w_p_nu || curwin->w_p_rnu)
? number_width(curwin) : 0)) {
- curwin->w_redr_type = NOT_VALID;
+ curwin->w_redr_type = UPD_NOT_VALID;
}
// Only start redrawing if there is really something to do.
- if (type == INVERTED) {
+ if (type == UPD_INVERTED) {
update_curswant();
}
if (curwin->w_redr_type < type
- && !((type == VALID
+ && !((type == UPD_VALID
&& curwin->w_lines[0].wl_valid
&& curwin->w_topfill == curwin->w_old_topfill
&& curwin->w_botfill == curwin->w_old_botfill
&& curwin->w_topline == curwin->w_lines[0].wl_lnum)
- || (type == INVERTED
+ || (type == UPD_INVERTED
&& VIsual_active
&& curwin->w_old_cursor_lnum == curwin->w_cursor.lnum
&& curwin->w_old_visual_mode == VIsual_mode
@@ -577,11 +579,11 @@ int update_screen(int type)
}
// Redraw the tab pages line if needed.
- if (redraw_tabline || type >= NOT_VALID) {
- update_window_hl(curwin, type >= NOT_VALID);
+ if (redraw_tabline || type >= UPD_NOT_VALID) {
+ update_window_hl(curwin, type >= UPD_NOT_VALID);
FOR_ALL_TABS(tp) {
if (tp != curtab) {
- update_window_hl(tp->tp_curwin, type >= NOT_VALID);
+ update_window_hl(tp->tp_curwin, type >= UPD_NOT_VALID);
}
}
draw_tabline();
@@ -590,7 +592,7 @@ int update_screen(int type)
// Correct stored syntax highlighting info for changes in each displayed
// buffer. Each buffer must only be done once.
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- update_window_hl(wp, type >= NOT_VALID || hl_changed);
+ update_window_hl(wp, type >= UPD_NOT_VALID || hl_changed);
buf_T *buf = wp->w_buffer;
if (buf->b_mod_set) {
@@ -612,9 +614,9 @@ int update_screen(int type)
screen_search_hl.rm.regprog = NULL;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_redr_type == CLEAR && wp->w_floating && wp->w_grid_alloc.chars) {
+ if (wp->w_redr_type == UPD_CLEAR && wp->w_floating && wp->w_grid_alloc.chars) {
grid_invalidate(&wp->w_grid_alloc);
- wp->w_redr_type = NOT_VALID;
+ wp->w_redr_type = UPD_NOT_VALID;
}
win_check_ns_hl(wp);
@@ -622,7 +624,7 @@ int update_screen(int type)
// reallocate grid if needed.
win_grid_alloc(wp);
- if (wp->w_redr_border || wp->w_redr_type >= NOT_VALID) {
+ if (wp->w_redr_border || wp->w_redr_type >= UPD_NOT_VALID) {
win_redr_border(wp);
}
@@ -746,6 +748,8 @@ void show_cursor_info(bool always)
if (!always && !redrawing()) {
return;
}
+
+ win_check_ns_hl(curwin);
if ((*p_stl != NUL || *curwin->w_p_stl != NUL)
&& (curwin->w_status_height || global_stl_height())) {
redraw_custom_statusline(curwin);
@@ -762,6 +766,7 @@ void show_cursor_info(bool always)
maketitle();
}
+ win_check_ns_hl(NULL);
// Redraw the tab pages line if needed.
if (redraw_tabline) {
draw_tabline();
@@ -957,20 +962,20 @@ static void draw_sep_connectors_win(win_T *wp)
///
/// How the window is redrawn depends on wp->w_redr_type. Each type also
/// implies the one below it.
-/// NOT_VALID redraw the whole window
-/// SOME_VALID redraw the whole window but do scroll when possible
-/// REDRAW_TOP redraw the top w_upd_rows window lines, otherwise like VALID
-/// INVERTED redraw the changed part of the Visual area
-/// INVERTED_ALL redraw the whole Visual area
-/// VALID 1. scroll up/down to adjust for a changed w_topline
-/// 2. update lines at the top when scrolled down
-/// 3. redraw changed text:
-/// - if wp->w_buffer->b_mod_set set, update lines between
-/// b_mod_top and b_mod_bot.
-/// - if wp->w_redraw_top non-zero, redraw lines between
-/// wp->w_redraw_top and wp->w_redr_bot.
-/// - continue redrawing when syntax status is invalid.
-/// 4. if scrolled up, update lines at the bottom.
+/// UPD_NOT_VALID redraw the whole window
+/// UPD_SOME_VALID redraw the whole window but do scroll when possible
+/// UPD_REDRAW_TOP redraw the top w_upd_rows window lines, otherwise like UPD_VALID
+/// UPD_INVERTED redraw the changed part of the Visual area
+/// UPD_INVERTED_ALL redraw the whole Visual area
+/// UPD_VALID 1. scroll up/down to adjust for a changed w_topline
+/// 2. update lines at the top when scrolled down
+/// 3. redraw changed text:
+/// - if wp->w_buffer->b_mod_set set, update lines between
+/// b_mod_top and b_mod_bot.
+/// - if wp->w_redraw_top non-zero, redraw lines between
+/// wp->w_redraw_top and wp->w_redr_bot.
+/// - continue redrawing when syntax status is invalid.
+/// 4. if scrolled up, update lines at the bottom.
/// This results in three areas that may need updating:
/// top: from first row to top_end (when scrolled down)
/// mid: from mid_start to mid_end (update inversion or changed text)
@@ -1016,7 +1021,7 @@ win_update_start:
type = wp->w_redr_type;
- if (type >= NOT_VALID) {
+ if (type >= UPD_NOT_VALID) {
wp->w_redr_status = true;
wp->w_lines_valid = 0;
}
@@ -1047,7 +1052,7 @@ win_update_start:
// changes.
i = (wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) : 0;
if (wp->w_nrwidth != i) {
- type = NOT_VALID;
+ type = UPD_NOT_VALID;
wp->w_nrwidth = i;
if (buf->terminal) {
@@ -1059,7 +1064,7 @@ win_update_start:
// When there are both inserted/deleted lines and specific lines to be
// redrawn, w_redraw_top and w_redraw_bot may be invalid, just redraw
// everything (only happens when redrawing is off for while).
- type = NOT_VALID;
+ type = UPD_NOT_VALID;
} else {
// Set mod_top to the first line that needs displaying because of
// changes. Set mod_bot to the first line after the changes.
@@ -1173,7 +1178,7 @@ win_update_start:
// When only displaying the lines at the top, set top_end. Used when
// window has scrolled down for msg_scrolled.
- if (type == REDRAW_TOP) {
+ if (type == UPD_REDRAW_TOP) {
j = 0;
for (i = 0; i < wp->w_lines_valid; i++) {
j += wp->w_lines[i].wl_size;
@@ -1184,10 +1189,10 @@ win_update_start:
}
if (top_end == 0) {
// not found (cannot happen?): redraw everything
- type = NOT_VALID;
+ type = UPD_NOT_VALID;
} else {
- // top area defined, the rest is VALID
- type = VALID;
+ // top area defined, the rest is UPD_VALID
+ type = UPD_VALID;
}
}
@@ -1197,8 +1202,8 @@ win_update_start:
// 2: wp->w_topline is below wp->w_lines[0].wl_lnum: may scroll up
// 3: wp->w_topline is wp->w_lines[0].wl_lnum: find first entry in
// w_lines[] that needs updating.
- if ((type == VALID || type == SOME_VALID
- || type == INVERTED || type == INVERTED_ALL)
+ if ((type == UPD_VALID || type == UPD_SOME_VALID
+ || type == UPD_INVERTED || type == UPD_INVERTED_ALL)
&& !wp->w_botfill && !wp->w_old_botfill) {
if (mod_top != 0
&& wp->w_topline == mod_top
@@ -1339,25 +1344,25 @@ win_update_start:
mid_end = wp->w_grid.rows;
}
} else {
- // Not VALID or INVERTED: redraw all lines.
+ // Not UPD_VALID or UPD_INVERTED: redraw all lines.
mid_start = 0;
mid_end = wp->w_grid.rows;
}
- if (type == SOME_VALID) {
- // SOME_VALID: redraw all lines.
+ if (type == UPD_SOME_VALID) {
+ // UPD_SOME_VALID: redraw all lines.
mid_start = 0;
mid_end = wp->w_grid.rows;
- type = NOT_VALID;
+ type = UPD_NOT_VALID;
}
// check if we are updating or removing the inverted part
if ((VIsual_active && buf == curwin->w_buffer)
- || (wp->w_old_cursor_lnum != 0 && type != NOT_VALID)) {
+ || (wp->w_old_cursor_lnum != 0 && type != UPD_NOT_VALID)) {
linenr_T from, to;
if (VIsual_active) {
- if (VIsual_mode != wp->w_old_visual_mode || type == INVERTED_ALL) {
+ if (VIsual_mode != wp->w_old_visual_mode || type == UPD_INVERTED_ALL) {
// If the type of Visual selection changed, redraw the whole
// selection. Also when the ownership of the X selection is
// gained or lost.
@@ -1887,7 +1892,7 @@ win_update_start:
int scr_row = wp->w_grid.rows - 1;
// Last line isn't finished: Display "@@@" in the last screen line.
- grid_puts_len(&wp->w_grid, (char_u *)"@@", MIN(wp->w_grid.cols, 2), scr_row, 0, at_attr);
+ grid_puts_len(&wp->w_grid, "@@", MIN(wp->w_grid.cols, 2), scr_row, 0, at_attr);
grid_fill(&wp->w_grid, scr_row, scr_row + 1, 2, wp->w_grid.cols,
'@', ' ', at_attr);
@@ -1920,15 +1925,16 @@ win_update_start:
wp->w_botline = lnum;
}
- // make sure the rest of the screen is blank
- // write the 'eob' character to rows that aren't part of the file.
+ // Make sure the rest of the screen is blank.
+ // write the "eob" character from 'fillchars' to rows that aren't part
+ // of the file.
win_draw_end(wp, wp->w_p_fcs_chars.eob, ' ', false, row, wp->w_grid.rows,
HLF_EOB);
}
kvi_destroy(line_providers);
- if (wp->w_redr_type >= REDRAW_TOP) {
+ if (wp->w_redr_type >= UPD_REDRAW_TOP) {
draw_vsep_win(wp);
draw_hsep_win(wp);
draw_sep_connectors_win(wp);
@@ -1985,13 +1991,13 @@ win_update_start:
/// Redraw a window later, with update_screen(type).
///
/// Set must_redraw only if not already set to a higher value.
-/// e.g. if must_redraw is CLEAR, type NOT_VALID will do nothing.
+/// e.g. if must_redraw is UPD_CLEAR, type UPD_NOT_VALID will do nothing.
void redraw_later(win_T *wp, int type)
FUNC_ATTR_NONNULL_ALL
{
if (!exiting && wp->w_redr_type < type) {
wp->w_redr_type = type;
- if (type >= NOT_VALID) {
+ if (type >= UPD_NOT_VALID) {
wp->w_lines_valid = 0;
}
if (must_redraw < type) { // must_redraw is the maximum of all windows
@@ -2015,7 +2021,7 @@ void redraw_all_later(int type)
void screen_invalidate_highlights(void)
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
wp->w_grid_alloc.valid = false;
}
}
@@ -2056,7 +2062,7 @@ void redraw_buf_range_later(buf_T *buf, linenr_T firstline, linenr_T lastline)
if (wp->w_redraw_bot == 0 || wp->w_redraw_bot < lastline) {
wp->w_redraw_bot = lastline;
}
- redraw_later(wp, VALID);
+ redraw_later(wp, UPD_VALID);
}
}
}
@@ -2070,8 +2076,8 @@ void redraw_buf_status_later(buf_T *buf)
|| (wp == curwin && global_stl_height())
|| wp->w_winbar_height)) {
wp->w_redr_status = true;
- if (must_redraw < VALID) {
- must_redraw = VALID;
+ if (must_redraw < UPD_VALID) {
+ must_redraw = UPD_VALID;
}
}
}
@@ -2086,7 +2092,7 @@ void status_redraw_all(void)
if ((!is_stl_global && wp->w_status_height) || (is_stl_global && wp == curwin)
|| wp->w_winbar_height) {
wp->w_redr_status = true;
- redraw_later(wp, VALID);
+ redraw_later(wp, UPD_VALID);
}
}
}
@@ -2106,7 +2112,7 @@ void status_redraw_buf(buf_T *buf)
if (wp->w_buffer == buf && ((!is_stl_global && wp->w_status_height)
|| (is_stl_global && wp == curwin) || wp->w_winbar_height)) {
wp->w_redr_status = true;
- redraw_later(wp, VALID);
+ redraw_later(wp, UPD_VALID);
}
}
}
@@ -2116,10 +2122,13 @@ void redraw_statuslines(void)
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_redr_status) {
+ win_check_ns_hl(wp);
win_redr_winbar(wp);
win_redr_status(wp);
}
}
+
+ win_check_ns_hl(NULL);
if (redraw_tabline) {
draw_tabline();
}
@@ -2162,6 +2171,6 @@ void redrawWinline(win_T *wp, linenr_T lnum)
if (wp->w_redraw_bot == 0 || wp->w_redraw_bot < lnum) {
wp->w_redraw_bot = lnum;
}
- redraw_later(wp, VALID);
+ redraw_later(wp, UPD_VALID);
}
}
diff --git a/src/nvim/drawscreen.h b/src/nvim/drawscreen.h
index 3eac1caaa1..ef99899581 100644
--- a/src/nvim/drawscreen.h
+++ b/src/nvim/drawscreen.h
@@ -6,13 +6,13 @@
/// flags for update_screen()
/// The higher the value, the higher the priority
enum {
- VALID = 10, ///< buffer not changed, or changes marked with b_mod_*
- INVERTED = 20, ///< redisplay inverted part that changed
- INVERTED_ALL = 25, ///< redisplay whole inverted part
- REDRAW_TOP = 30, ///< display first w_upd_rows screen lines
- SOME_VALID = 35, ///< like NOT_VALID but may scroll
- NOT_VALID = 40, ///< buffer needs complete redraw
- CLEAR = 50, ///< screen messed up, clear it
+ UPD_VALID = 10, ///< buffer not changed, or changes marked with b_mod_*
+ UPD_INVERTED = 20, ///< redisplay inverted part that changed
+ UPD_INVERTED_ALL = 25, ///< redisplay whole inverted part
+ UPD_REDRAW_TOP = 30, ///< display first w_upd_rows screen lines
+ UPD_SOME_VALID = 35, ///< like UPD_NOT_VALID but may scroll
+ UPD_NOT_VALID = 40, ///< buffer needs complete redraw
+ UPD_CLEAR = 50, ///< screen messed up, clear it
};
/// While redrawing the screen this flag is set. It means the screen size
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 6583ac8584..aee8389900 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -56,6 +56,8 @@
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/terminal.h"
+#include "nvim/textformat.h"
+#include "nvim/textobject.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/vim.h"
@@ -92,6 +94,10 @@ typedef struct insert_state {
#define BACKSPACE_WORD_NOT_SPACE 3
#define BACKSPACE_LINE 4
+/// Set when doing something for completion that may call edit() recursively,
+/// which is not allowed.
+static bool compl_busy = false;
+
static colnr_T Insstart_textlen; // length of line when insert started
static colnr_T Insstart_blank_vcol; // vcol for first inserted blank
static bool update_Insstart_orig = true; // set Insstart_orig to Insstart
@@ -104,8 +110,6 @@ static int did_restart_edit; // "restart_edit" when calling edit()
static bool can_cindent; // may do cindenting on this line
-static int old_indent = 0; // for ^^D command in insert mode
-
static int revins_on; // reverse insert mode on
static int revins_chars; // how much to skip after edit
static int revins_legal; // was the last char 'legal'?
@@ -115,8 +119,6 @@ static bool ins_need_undo; // call u_save() before inserting a
// char. Set when edit() is called.
// after that arrow_used is used.
-static bool did_add_space = false; // auto_format() added an extra space
- // under the cursor
static TriState dont_sync_undo = kFalse; // CTRL-G U prevents syncing undo
// for the next left/right cursor key
@@ -448,7 +450,7 @@ static int insert_check(VimState *state)
&& (curwin->w_cursor.lnum != curwin->w_topline
|| curwin->w_topfill > 0)) {
if (curwin->w_topfill > 0) {
- --curwin->w_topfill;
+ curwin->w_topfill--;
} else if (hasFolding(curwin->w_topline, NULL, &s->old_topline)) {
set_topline(curwin, s->old_topline + 1);
} else {
@@ -624,16 +626,17 @@ static int insert_execute(VimState *state, int key)
}
if (cindent_on() && ctrl_x_mode_none()) {
+ s->line_is_white = inindent(0);
// A key name preceded by a bang means this key is not to be
// inserted. Skip ahead to the re-indenting below.
- // A key name preceded by a star means that indenting has to be
- // done before inserting the key.
- s->line_is_white = inindent(0);
- if (in_cinkeys(s->c, '!', s->line_is_white)) {
- insert_do_cindent(s);
+ if (in_cinkeys(s->c, '!', s->line_is_white)
+ && stop_arrow() == OK) {
+ do_c_expr_indent();
return 1; // continue
}
+ // A key name preceded by a star means that indenting has to be
+ // done before inserting the key.
if (can_cindent && in_cinkeys(s->c, '*', s->line_is_white)
&& stop_arrow() == OK) {
do_c_expr_indent();
@@ -1090,7 +1093,7 @@ check_pum:
// but it is under other ^X modes
if (*curbuf->b_p_cpt == NUL
&& (ctrl_x_mode_normal() || ctrl_x_mode_whole_line())
- && !(compl_cont_status & CONT_LOCAL)) {
+ && !compl_status_local()) {
goto normalchar;
}
@@ -1176,9 +1179,11 @@ normalchar:
static void insert_do_complete(InsertState *s)
{
compl_busy = true;
+ disable_fold_update++; // don't redraw folds here
if (ins_complete(s->c, true) == FAIL) {
- compl_cont_status = 0;
+ compl_status_clear();
}
+ disable_fold_update--;
compl_busy = false;
can_si = may_do_si(); // allow smartindenting
}
@@ -1518,8 +1523,7 @@ void edit_unputchar(void)
if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT) {
redrawWinline(curwin, curwin->w_cursor.lnum);
} else {
- grid_puts(&curwin->w_grid, pc_bytes, pc_row - msg_scrolled, pc_col,
- pc_attr);
+ grid_puts(&curwin->w_grid, (char *)pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr);
}
}
}
@@ -1554,7 +1558,7 @@ void display_dollar(colnr_T col)
* Call this function before moving the cursor from the normal insert position
* in insert mode.
*/
-static void undisplay_dollar(void)
+void undisplay_dollar(void)
{
if (dollar_vcol >= 0) {
dollar_vcol = -1;
@@ -1568,7 +1572,7 @@ static void undisplay_dollar(void)
/// type == INDENT_DEC decrease indent (for CTRL-D)
/// type == INDENT_SET set indent to "amount"
///
-/// @param round if TRUE, round the indent to 'shiftwidth' (only with _INC and _Dec).
+/// @param round if true, round the indent to 'shiftwidth' (only with _INC and _Dec).
/// @param replaced replaced character, put on replace stack
/// @param call_changed_bytes call changed_bytes()
void change_indent(int type, int amount, int round, int replaced, int call_changed_bytes)
@@ -1592,7 +1596,7 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
// for the following tricks we don't want list mode
save_p_list = curwin->w_p_list;
- curwin->w_p_list = FALSE;
+ curwin->w_p_list = false;
vc = getvcol_nolist(&curwin->w_cursor);
vcol = vc;
@@ -1660,28 +1664,28 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
} else if (!(State & MODE_INSERT)) {
new_cursor_col = curwin->w_cursor.col;
} else {
- /*
- * Compute the screen column where the cursor should be.
- */
+ // Compute the screen column where the cursor should be.
vcol = get_indent() - vcol;
curwin->w_virtcol = (colnr_T)((vcol < 0) ? 0 : vcol);
- /*
- * Advance the cursor until we reach the right screen column.
- */
- vcol = last_vcol = 0;
- new_cursor_col = -1;
+ // Advance the cursor until we reach the right screen column.
+ last_vcol = 0;
ptr = get_cursor_line_ptr();
- while (vcol <= (int)curwin->w_virtcol) {
- last_vcol = vcol;
- if (new_cursor_col >= 0) {
- new_cursor_col += utfc_ptr2len((char *)ptr + new_cursor_col);
- } else {
- new_cursor_col++;
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, 0, 0, ptr, ptr);
+ while (cts.cts_vcol <= (int)curwin->w_virtcol) {
+ last_vcol = cts.cts_vcol;
+ if (cts.cts_vcol > 0) {
+ MB_PTR_ADV(cts.cts_ptr);
+ }
+ if (*cts.cts_ptr == NUL) {
+ break;
}
- vcol += lbr_chartabsize(ptr, ptr + new_cursor_col, (colnr_T)vcol);
+ cts.cts_vcol += lbr_chartabsize(&cts);
}
vcol = last_vcol;
+ new_cursor_col = (int)(cts.cts_ptr - cts.cts_line);
+ clear_chartabsize_arg(&cts);
/*
* May need to insert spaces to be able to position the cursor on
@@ -1693,7 +1697,7 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
ptr = xmallocz(i);
memset(ptr, ' ', i);
new_cursor_col += (int)i;
- ins_str(ptr);
+ ins_str((char *)ptr);
xfree(ptr);
}
@@ -1711,7 +1715,7 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
} else {
curwin->w_cursor.col = (colnr_T)new_cursor_col;
}
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
changed_cline_bef_curs();
/*
@@ -1773,7 +1777,7 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
backspace_until_column(0);
// Insert new stuff into line again
- ins_bytes(new_line);
+ ins_bytes((char *)new_line);
xfree(new_line);
@@ -1792,7 +1796,7 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
/// Truncate the space at the end of a line. This is to be used only in an
/// insert mode. It handles fixing the replace stack for MODE_REPLACE and
/// MODE_VREPLACE modes.
-void truncate_spaces(char_u *line)
+void truncate_spaces(char *line)
{
int i;
@@ -1971,7 +1975,7 @@ static void insert_special(int c, int allow_modmask, int ctrlv)
// inserted with ins_str(), so as not to replace characters in replace
// mode.
// Only use mod_mask for special keys, to avoid things like <S-Space>,
- // unless 'allow_modmask' is TRUE.
+ // unless 'allow_modmask' is true.
if (mod_mask & MOD_MASK_CMD) { // Command-key never produces a normal key.
allow_modmask = true;
}
@@ -1984,7 +1988,7 @@ static void insert_special(int c, int allow_modmask, int ctrlv)
return;
}
p[len - 1] = NUL;
- ins_str(p);
+ ins_str((char *)p);
AppendToRedobuffLit((char *)p, -1);
ctrlv = false;
}
@@ -2005,9 +2009,6 @@ static void insert_special(int c, int allow_modmask, int ctrlv)
*/
#define ISSPECIAL(c) ((c) < ' ' || (c) >= DEL || (c) == '0' || (c) == '^')
-#define WHITECHAR(cc) (ascii_iswhite(cc) \
- && !utf_iscomposing(utf_ptr2char((char *)get_cursor_pos_ptr() + 1)))
-
///
/// "flags": INSCHAR_FORMAT - force formatting
/// INSCHAR_CTRLV - char typed just after CTRL-V
@@ -2115,7 +2116,7 @@ void insertchar(int c, int flags, int second_indent)
// Insert the end-comment string, except for the last
// character, which will get inserted as normal later.
- ins_bytes_len(lead_end, (size_t)(end_len - 1));
+ ins_bytes_len((char *)lead_end, (size_t)(end_len - 1));
}
}
}
@@ -2175,7 +2176,7 @@ void insertchar(int c, int flags, int second_indent)
do_digraph(-1); // clear digraphs
do_digraph(buf[i - 1]); // may be the start of a digraph
buf[i] = NUL;
- ins_str(buf);
+ ins_str((char *)buf);
if (flags & INSCHAR_CTRLV) {
redo_literal(*buf);
i = 1;
@@ -2193,7 +2194,7 @@ void insertchar(int c, int flags, int second_indent)
utf_char2bytes(c, (char *)buf);
buf[cc] = NUL;
- ins_char_bytes((char_u *)buf, (size_t)cc);
+ ins_char_bytes(buf, (size_t)cc);
AppendCharToRedobuff(c);
} else {
ins_char(c);
@@ -2206,597 +2207,6 @@ void insertchar(int c, int flags, int second_indent)
}
}
-/// Format text at the current insert position.
-///
-/// If the INSCHAR_COM_LIST flag is present, then the value of second_indent
-/// will be the comment leader length sent to open_line().
-///
-/// @param c character to be inserted (can be NUL)
-static void internal_format(int textwidth, int second_indent, int flags, int format_only, int c)
-{
- int cc;
- int save_char = NUL;
- bool haveto_redraw = false;
- const bool fo_ins_blank = has_format_option(FO_INS_BLANK);
- const bool fo_multibyte = has_format_option(FO_MBYTE_BREAK);
- const bool fo_rigor_tw = has_format_option(FO_RIGOROUS_TW);
- const bool fo_white_par = has_format_option(FO_WHITE_PAR);
- bool first_line = true;
- colnr_T leader_len;
- bool no_leader = false;
- int do_comments = (flags & INSCHAR_DO_COM);
- int has_lbr = curwin->w_p_lbr;
-
- // make sure win_lbr_chartabsize() counts correctly
- curwin->w_p_lbr = false;
-
- /*
- * When 'ai' is off we don't want a space under the cursor to be
- * deleted. Replace it with an 'x' temporarily.
- */
- if (!curbuf->b_p_ai
- && !(State & VREPLACE_FLAG)) {
- cc = gchar_cursor();
- if (ascii_iswhite(cc)) {
- save_char = cc;
- pchar_cursor('x');
- }
- }
-
- /*
- * Repeat breaking lines, until the current line is not too long.
- */
- while (!got_int) {
- int startcol; // Cursor column at entry
- int wantcol; // column at textwidth border
- int foundcol; // column for start of spaces
- int end_foundcol = 0; // column for start of word
- colnr_T len;
- colnr_T virtcol;
- int orig_col = 0;
- char_u *saved_text = NULL;
- colnr_T col;
- colnr_T end_col;
- bool did_do_comment = false;
-
- virtcol = get_nolist_virtcol()
- + char2cells(c != NUL ? c : gchar_cursor());
- if (virtcol <= (colnr_T)textwidth) {
- break;
- }
-
- if (no_leader) {
- do_comments = false;
- } else if (!(flags & INSCHAR_FORMAT)
- && has_format_option(FO_WRAP_COMS)) {
- do_comments = true;
- }
-
- // Don't break until after the comment leader
- if (do_comments) {
- char_u *line = get_cursor_line_ptr();
- leader_len = get_leader_len((char *)line, NULL, false, true);
- if (leader_len == 0 && curbuf->b_p_cin) {
- // Check for a line comment after code.
- int comment_start = check_linecomment(line);
- if (comment_start != MAXCOL) {
- leader_len = get_leader_len((char *)line + comment_start, NULL, false, true);
- if (leader_len != 0) {
- leader_len += comment_start;
- }
- }
- }
- } else {
- leader_len = 0;
- }
-
- // If the line doesn't start with a comment leader, then don't
- // start one in a following broken line. Avoids that a %word
- // moved to the start of the next line causes all following lines
- // to start with %.
- if (leader_len == 0) {
- no_leader = true;
- }
- if (!(flags & INSCHAR_FORMAT)
- && leader_len == 0
- && !has_format_option(FO_WRAP)) {
- break;
- }
- if ((startcol = curwin->w_cursor.col) == 0) {
- break;
- }
-
- // find column of textwidth border
- coladvance((colnr_T)textwidth);
- wantcol = curwin->w_cursor.col;
-
- curwin->w_cursor.col = startcol;
- foundcol = 0;
- int skip_pos = 0;
-
- /*
- * Find position to break at.
- * Stop at first entered white when 'formatoptions' has 'v'
- */
- while ((!fo_ins_blank && !has_format_option(FO_INS_VI))
- || (flags & INSCHAR_FORMAT)
- || curwin->w_cursor.lnum != Insstart.lnum
- || curwin->w_cursor.col >= Insstart.col) {
- if (curwin->w_cursor.col == startcol && c != NUL) {
- cc = c;
- } else {
- cc = gchar_cursor();
- }
- if (WHITECHAR(cc)) {
- // remember position of blank just before text
- end_col = curwin->w_cursor.col;
-
- // find start of sequence of blanks
- int wcc = 0; // counter for whitespace chars
- while (curwin->w_cursor.col > 0 && WHITECHAR(cc)) {
- dec_cursor();
- cc = gchar_cursor();
-
- // Increment count of how many whitespace chars in this
- // group; we only need to know if it's more than one.
- if (wcc < 2) {
- wcc++;
- }
- }
- if (curwin->w_cursor.col == 0 && WHITECHAR(cc)) {
- break; // only spaces in front of text
- }
-
- // Don't break after a period when 'formatoptions' has 'p' and
- // there are less than two spaces.
- if (has_format_option(FO_PERIOD_ABBR) && cc == '.' && wcc < 2) {
- continue;
- }
-
- // Don't break until after the comment leader
- if (curwin->w_cursor.col < leader_len) {
- break;
- }
-
- if (has_format_option(FO_ONE_LETTER)) {
- // do not break after one-letter words
- if (curwin->w_cursor.col == 0) {
- break; // one-letter word at begin
- }
- // do not break "#a b" when 'tw' is 2
- if (curwin->w_cursor.col <= leader_len) {
- break;
- }
- col = curwin->w_cursor.col;
- dec_cursor();
- cc = gchar_cursor();
-
- if (WHITECHAR(cc)) {
- continue; // one-letter, continue
- }
- curwin->w_cursor.col = col;
- }
-
- inc_cursor();
-
- end_foundcol = end_col + 1;
- foundcol = curwin->w_cursor.col;
- if (curwin->w_cursor.col <= (colnr_T)wantcol) {
- break;
- }
- } else if ((cc >= 0x100 || !utf_allow_break_before(cc)) && fo_multibyte) {
- int ncc;
- bool allow_break;
-
- // Break after or before a multi-byte character.
- if (curwin->w_cursor.col != startcol) {
- // Don't break until after the comment leader
- if (curwin->w_cursor.col < leader_len) {
- break;
- }
- col = curwin->w_cursor.col;
- inc_cursor();
- ncc = gchar_cursor();
- allow_break = utf_allow_break(cc, ncc);
-
- // If we have already checked this position, skip!
- if (curwin->w_cursor.col != skip_pos && allow_break) {
- foundcol = curwin->w_cursor.col;
- end_foundcol = foundcol;
- if (curwin->w_cursor.col <= (colnr_T)wantcol) {
- break;
- }
- }
- curwin->w_cursor.col = col;
- }
-
- if (curwin->w_cursor.col == 0) {
- break;
- }
-
- ncc = cc;
- col = curwin->w_cursor.col;
-
- dec_cursor();
- cc = gchar_cursor();
-
- if (WHITECHAR(cc)) {
- continue; // break with space
- }
- // Don't break until after the comment leader.
- if (curwin->w_cursor.col < leader_len) {
- break;
- }
-
- curwin->w_cursor.col = col;
- skip_pos = curwin->w_cursor.col;
-
- allow_break = utf_allow_break(cc, ncc);
-
- // Must handle this to respect line break prohibition.
- if (allow_break) {
- foundcol = curwin->w_cursor.col;
- end_foundcol = foundcol;
- }
- if (curwin->w_cursor.col <= (colnr_T)wantcol) {
- const bool ncc_allow_break = utf_allow_break_before(ncc);
-
- if (allow_break) {
- break;
- }
- if (!ncc_allow_break && !fo_rigor_tw) {
- // Enable at most 1 punct hang outside of textwidth.
- if (curwin->w_cursor.col == startcol) {
- // We are inserting a non-breakable char, postpone
- // line break check to next insert.
- end_foundcol = foundcol = 0;
- break;
- }
-
- // Neither cc nor ncc is NUL if we are here, so
- // it's safe to inc_cursor.
- col = curwin->w_cursor.col;
-
- inc_cursor();
- cc = ncc;
- ncc = gchar_cursor();
- // handle insert
- ncc = (ncc != NUL) ? ncc : c;
-
- allow_break = utf_allow_break(cc, ncc);
-
- if (allow_break) {
- // Break only when we are not at end of line.
- end_foundcol = foundcol = ncc == NUL? 0 : curwin->w_cursor.col;
- break;
- }
- curwin->w_cursor.col = col;
- }
- }
- }
- if (curwin->w_cursor.col == 0) {
- break;
- }
- dec_cursor();
- }
-
- if (foundcol == 0) { // no spaces, cannot break line
- curwin->w_cursor.col = startcol;
- break;
- }
-
- // Going to break the line, remove any "$" now.
- undisplay_dollar();
-
- // Offset between cursor position and line break is used by replace
- // stack functions. MODE_VREPLACE does not use this, and backspaces
- // over the text instead.
- if (State & VREPLACE_FLAG) {
- orig_col = startcol; // Will start backspacing from here
- } else {
- replace_offset = startcol - end_foundcol;
- }
-
- /*
- * adjust startcol for spaces that will be deleted and
- * characters that will remain on top line
- */
- curwin->w_cursor.col = foundcol;
- while ((cc = gchar_cursor(), WHITECHAR(cc))
- && (!fo_white_par || curwin->w_cursor.col < startcol)) {
- inc_cursor();
- }
- startcol -= curwin->w_cursor.col;
- if (startcol < 0) {
- startcol = 0;
- }
-
- if (State & VREPLACE_FLAG) {
- // In MODE_VREPLACE state, we will backspace over the text to be
- // wrapped, so save a copy now to put on the next line.
- saved_text = vim_strsave(get_cursor_pos_ptr());
- curwin->w_cursor.col = orig_col;
- saved_text[startcol] = NUL;
-
- // Backspace over characters that will move to the next line
- if (!fo_white_par) {
- backspace_until_column(foundcol);
- }
- } else {
- // put cursor after pos. to break line
- if (!fo_white_par) {
- curwin->w_cursor.col = foundcol;
- }
- }
-
- /*
- * Split the line just before the margin.
- * Only insert/delete lines, but don't really redraw the window.
- */
- open_line(FORWARD, OPENLINE_DELSPACES + OPENLINE_MARKFIX
- + (fo_white_par ? OPENLINE_KEEPTRAIL : 0)
- + (do_comments ? OPENLINE_DO_COM : 0)
- + OPENLINE_FORMAT
- + ((flags & INSCHAR_COM_LIST) ? OPENLINE_COM_LIST : 0),
- ((flags & INSCHAR_COM_LIST) ? second_indent : old_indent),
- &did_do_comment);
- if (!(flags & INSCHAR_COM_LIST)) {
- old_indent = 0;
- }
-
- // If a comment leader was inserted, may also do this on a following
- // line.
- if (did_do_comment) {
- no_leader = false;
- }
-
- replace_offset = 0;
- if (first_line) {
- if (!(flags & INSCHAR_COM_LIST)) {
- // This section is for auto-wrap of numeric lists. When not
- // in insert mode (i.e. format_lines()), the INSCHAR_COM_LIST
- // flag will be set and open_line() will handle it (as seen
- // above). The code here (and in get_number_indent()) will
- // recognize comments if needed...
- if (second_indent < 0 && has_format_option(FO_Q_NUMBER)) {
- second_indent = get_number_indent(curwin->w_cursor.lnum - 1);
- }
- if (second_indent >= 0) {
- if (State & VREPLACE_FLAG) {
- change_indent(INDENT_SET, second_indent, false, NUL, true);
- } else if (leader_len > 0 && second_indent - leader_len > 0) {
- int padding = second_indent - leader_len;
-
- // We started at the first_line of a numbered list
- // that has a comment. the open_line() function has
- // inserted the proper comment leader and positioned
- // the cursor at the end of the split line. Now we
- // add the additional whitespace needed after the
- // comment leader for the numbered list.
- for (int i = 0; i < padding; i++) {
- ins_str((char_u *)" ");
- }
- changed_bytes(curwin->w_cursor.lnum, leader_len);
- } else {
- (void)set_indent(second_indent, SIN_CHANGED);
- }
- }
- }
- first_line = false;
- }
-
- if (State & VREPLACE_FLAG) {
- // In MODE_VREPLACE state we have backspaced over the text to be
- // moved, now we re-insert it into the new line.
- ins_bytes(saved_text);
- xfree(saved_text);
- } else {
- /*
- * Check if cursor is not past the NUL off the line, cindent
- * may have added or removed indent.
- */
- curwin->w_cursor.col += startcol;
- len = (colnr_T)STRLEN(get_cursor_line_ptr());
- if (curwin->w_cursor.col > len) {
- curwin->w_cursor.col = len;
- }
- }
-
- haveto_redraw = true;
- can_cindent = true;
- // moved the cursor, don't autoindent or cindent now
- did_ai = false;
- did_si = false;
- can_si = false;
- can_si_back = false;
- line_breakcheck();
- }
-
- if (save_char != NUL) { // put back space after cursor
- pchar_cursor((char_u)save_char);
- }
-
- curwin->w_p_lbr = has_lbr;
-
- if (!format_only && haveto_redraw) {
- update_topline(curwin);
- redraw_curbuf_later(VALID);
- }
-}
-
-/// Called after inserting or deleting text: When 'formatoptions' includes the
-/// 'a' flag format from the current line until the end of the paragraph.
-/// Keep the cursor at the same position relative to the text.
-/// The caller must have saved the cursor line for undo, following ones will be
-/// saved here.
-///
-/// @param trailblank when true also format with trailing blank
-/// @param prev_line may start in previous line
-void auto_format(bool trailblank, bool prev_line)
-{
- pos_T pos;
- colnr_T len;
- char_u *old;
- char_u *new, *pnew;
- int wasatend;
- int cc;
-
- if (!has_format_option(FO_AUTO)) {
- return;
- }
-
- pos = curwin->w_cursor;
- old = get_cursor_line_ptr();
-
- // may remove added space
- check_auto_format(false);
-
- // Don't format in Insert mode when the cursor is on a trailing blank, the
- // user might insert normal text next. Also skip formatting when "1" is
- // in 'formatoptions' and there is a single character before the cursor.
- // Otherwise the line would be broken and when typing another non-white
- // next they are not joined back together.
- wasatend = (pos.col == (colnr_T)STRLEN(old));
- if (*old != NUL && !trailblank && wasatend) {
- dec_cursor();
- cc = gchar_cursor();
- if (!WHITECHAR(cc) && curwin->w_cursor.col > 0
- && has_format_option(FO_ONE_LETTER)) {
- dec_cursor();
- }
- cc = gchar_cursor();
- if (WHITECHAR(cc)) {
- curwin->w_cursor = pos;
- return;
- }
- curwin->w_cursor = pos;
- }
-
- // With the 'c' flag in 'formatoptions' and 't' missing: only format
- // comments.
- if (has_format_option(FO_WRAP_COMS) && !has_format_option(FO_WRAP)
- && get_leader_len((char *)old, NULL, false, true) == 0) {
- return;
- }
-
- /*
- * May start formatting in a previous line, so that after "x" a word is
- * moved to the previous line if it fits there now. Only when this is not
- * the start of a paragraph.
- */
- if (prev_line && !paragraph_start(curwin->w_cursor.lnum)) {
- --curwin->w_cursor.lnum;
- if (u_save_cursor() == FAIL) {
- return;
- }
- }
-
- /*
- * Do the formatting and restore the cursor position. "saved_cursor" will
- * be adjusted for the text formatting.
- */
- saved_cursor = pos;
- format_lines((linenr_T) - 1, false);
- curwin->w_cursor = saved_cursor;
- saved_cursor.lnum = 0;
-
- if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {
- // "cannot happen"
- curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- coladvance(MAXCOL);
- } else {
- check_cursor_col();
- }
-
- // Insert mode: If the cursor is now after the end of the line while it
- // previously wasn't, the line was broken. Because of the rule above we
- // need to add a space when 'w' is in 'formatoptions' to keep a paragraph
- // formatted.
- if (!wasatend && has_format_option(FO_WHITE_PAR)) {
- new = get_cursor_line_ptr();
- len = (colnr_T)STRLEN(new);
- if (curwin->w_cursor.col == len) {
- pnew = vim_strnsave(new, (size_t)len + 2);
- pnew[len] = ' ';
- pnew[len + 1] = NUL;
- ml_replace(curwin->w_cursor.lnum, (char *)pnew, false);
- // remove the space later
- did_add_space = true;
- } else {
- // may remove added space
- check_auto_format(false);
- }
- }
-
- check_cursor();
-}
-
-/// When an extra space was added to continue a paragraph for auto-formatting,
-/// delete it now. The space must be under the cursor, just after the insert
-/// position.
-///
-/// @param end_insert true when ending Insert mode
-static void check_auto_format(bool end_insert)
-{
- int c = ' ';
- int cc;
-
- if (did_add_space) {
- cc = gchar_cursor();
- if (!WHITECHAR(cc)) {
- // Somehow the space was removed already.
- did_add_space = false;
- } else {
- if (!end_insert) {
- inc_cursor();
- c = gchar_cursor();
- dec_cursor();
- }
- if (c != NUL) {
- // The space is no longer at the end of the line, delete it.
- del_char(false);
- did_add_space = false;
- }
- }
- }
-}
-
-/// Find out textwidth to be used for formatting:
-/// if 'textwidth' option is set, use it
-/// else if 'wrapmargin' option is set, use curwin->w_width_inner-'wrapmargin'
-/// if invalid value, use 0.
-/// Set default to window width (maximum 79) for "gq" operator.
-///
-/// @param ff force formatting (for "gq" command)
-int comp_textwidth(bool ff)
-{
- int textwidth = (int)curbuf->b_p_tw;
- if (textwidth == 0 && curbuf->b_p_wm) {
- // The width is the window width minus 'wrapmargin' minus all the
- // things that add to the margin.
- textwidth = curwin->w_width_inner - (int)curbuf->b_p_wm;
- if (cmdwin_type != 0) {
- textwidth -= 1;
- }
- textwidth -= win_fdccol_count(curwin);
- textwidth -= win_signcol_count(curwin);
-
- if (curwin->w_p_nu || curwin->w_p_rnu) {
- textwidth -= 8;
- }
- }
- if (textwidth < 0) {
- textwidth = 0;
- }
- if (ff && textwidth == 0) {
- textwidth = curwin->w_width_inner - 1;
- if (textwidth > 79) {
- textwidth = 79;
- }
- }
- return textwidth;
-}
-
/*
* Put a character in the redo buffer, for when just after a CTRL-V.
*/
@@ -2986,7 +2396,7 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove)
check_cursor_col(); // make sure it is not past the line
for (;;) {
if (gchar_cursor() == NUL && curwin->w_cursor.col > 0) {
- --curwin->w_cursor.col;
+ curwin->w_cursor.col--;
}
cc = gchar_cursor();
if (!ascii_iswhite(cc)) {
@@ -3003,7 +2413,7 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove)
tpos = curwin->w_cursor;
tpos.col++;
if (cc != NUL && gchar_pos(&tpos) == NUL) {
- ++curwin->w_cursor.col; // put cursor back on the NUL
+ curwin->w_cursor.col++; // put cursor back on the NUL
}
}
@@ -3075,11 +2485,11 @@ void beginline(int flags)
char_u *ptr;
for (ptr = get_cursor_line_ptr(); ascii_iswhite(*ptr)
- && !((flags & BL_FIX) && ptr[1] == NUL); ++ptr) {
- ++curwin->w_cursor.col;
+ && !((flags & BL_FIX) && ptr[1] == NUL); ptr++) {
+ curwin->w_cursor.col++;
}
}
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
}
}
@@ -3123,7 +2533,7 @@ int oneright(void)
}
curwin->w_cursor.col += l;
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
return OK;
}
@@ -3158,7 +2568,7 @@ int oneleft(void)
}
}
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
return OK;
}
@@ -3166,8 +2576,8 @@ int oneleft(void)
return FAIL;
}
- curwin->w_set_curswant = TRUE;
- --curwin->w_cursor.col;
+ curwin->w_set_curswant = true;
+ curwin->w_cursor.col--;
// if the character on the left of the current cursor is a multi-byte
// character, move to its first byte
@@ -3175,7 +2585,7 @@ int oneleft(void)
return OK;
}
-/// @oaram upd_topline When TRUE: update topline
+/// @oaram upd_topline When true: update topline
int cursor_up(long n, int upd_topline)
{
linenr_T lnum;
@@ -3230,7 +2640,7 @@ int cursor_up(long n, int upd_topline)
/// Cursor down a number of logical lines.
///
-/// @param upd_topline When TRUE: update topline
+/// @param upd_topline When true: update topline
int cursor_down(long n, int upd_topline)
{
linenr_T lnum;
@@ -3288,12 +2698,12 @@ int cursor_down(long n, int upd_topline)
/// @param no_esc Don't add an ESC at the end
int stuff_inserted(int c, long count, int no_esc)
{
- char_u *esc_ptr;
- char_u *ptr;
- char_u *last_ptr;
- char_u last = NUL;
+ char *esc_ptr;
+ char *ptr;
+ char *last_ptr;
+ char last = NUL;
- ptr = get_last_insert();
+ ptr = (char *)get_last_insert();
if (ptr == NULL) {
emsg(_(e_noinstext));
return FAIL;
@@ -3303,7 +2713,7 @@ int stuff_inserted(int c, long count, int no_esc)
if (c != NUL) {
stuffcharReadbuff(c);
}
- if ((esc_ptr = STRRCHR(ptr, ESC)) != NULL) {
+ if ((esc_ptr = strrchr(ptr, ESC)) != NULL) {
// remove the ESC.
*esc_ptr = NUL;
}
@@ -3437,17 +2847,16 @@ void replace_push(int c)
replace_stack_nr++;
}
-/*
- * Push a character onto the replace stack. Handles a multi-byte character in
- * reverse byte order, so that the first byte is popped off first.
- * Return the number of bytes done (includes composing characters).
- */
-int replace_push_mb(char_u *p)
+/// Push a character onto the replace stack. Handles a multi-byte character in
+/// reverse byte order, so that the first byte is popped off first.
+///
+/// @return the number of bytes done (includes composing characters).
+int replace_push_mb(char *p)
{
- int l = utfc_ptr2len((char *)p);
+ int l = utfc_ptr2len(p);
int j;
- for (j = l - 1; j >= 0; --j) {
+ for (j = l - 1; j >= 0; j--) {
replace_push(p[j]);
}
return l;
@@ -3508,7 +2917,7 @@ static void mb_replace_pop_ins(int cc)
for (i = 1; i < n; i++) {
buf[i] = (char_u)replace_pop();
}
- ins_bytes_len(buf, (size_t)n);
+ ins_bytes_len((char *)buf, (size_t)n);
} else {
ins_char(cc);
}
@@ -3531,7 +2940,7 @@ static void mb_replace_pop_ins(int cc)
buf[i] = (char_u)replace_pop();
}
if (utf_iscomposing(utf_ptr2char((char *)buf))) {
- ins_bytes_len(buf, (size_t)n);
+ ins_bytes_len((char *)buf, (size_t)n);
} else {
// Not a composing char, put it back.
for (i = n - 1; i >= 0; i--) {
@@ -3580,7 +2989,7 @@ static void replace_do_bs(int limit_col)
// Get the number of screen cells used by the character we are
// going to delete.
getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL);
- orig_vcols = win_chartabsize(curwin, get_cursor_pos_ptr(), start_vcol);
+ orig_vcols = win_chartabsize(curwin, (char *)get_cursor_pos_ptr(), start_vcol);
}
(void)del_char_after_col(limit_col);
if (l_State & VREPLACE_FLAG) {
@@ -3595,7 +3004,7 @@ static void replace_do_bs(int limit_col)
ins_len = (int)STRLEN(p) - orig_len;
vcol = start_vcol;
for (i = 0; i < ins_len; i++) {
- vcol += win_chartabsize(curwin, p + i, vcol);
+ vcol += win_chartabsize(curwin, (char *)p + i, vcol);
i += utfc_ptr2len((char *)p) - 1;
}
vcol -= start_vcol;
@@ -3657,7 +3066,7 @@ void fix_indent(void)
/// Check that "cinkeys" contains the key "keytyped",
/// when == '*': Only if key is preceded with '*' (indent before insert)
/// when == '!': Only if key is preceded with '!' (don't insert)
-/// when == ' ': Only if key is not preceded with '*' (indent afterwards)
+/// when == ' ': Only if key is not preceded with '*' or '!' (indent afterwards)
///
/// "keytyped" can have a few special values:
/// KEY_OPEN_FORW :
@@ -3682,9 +3091,9 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
}
if (*curbuf->b_p_inde != NUL) {
- look = curbuf->b_p_indk; // 'indentexpr' set: use 'indentkeys'
+ look = (char_u *)curbuf->b_p_indk; // 'indentexpr' set: use 'indentkeys'
} else {
- look = curbuf->b_p_cink; // 'indentexpr' empty: use 'cinkeys'
+ look = (char_u *)curbuf->b_p_cink; // 'indentexpr' empty: use 'cinkeys'
}
while (*look) {
/*
@@ -3697,7 +3106,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
case '!':
try_match = (*look == '!'); break;
default:
- try_match = (*look != '*'); break;
+ try_match = (*look != '*') && (*look != '!'); break;
}
if (*look == '*' || *look == '!') {
look++;
@@ -3871,10 +3280,8 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
}
}
- /*
- * Skip over ", ".
- */
- look = skip_to_option_part(look);
+ // Skip over ", ".
+ look = (char_u *)skip_to_option_part((char *)look);
}
return false;
}
@@ -4000,13 +3407,13 @@ static void ins_reg(void)
no_mapping++;
allow_keys++;
regname = plain_vgetc();
- LANGMAP_ADJUST(regname, TRUE);
+ LANGMAP_ADJUST(regname, true);
if (regname == Ctrl_R || regname == Ctrl_O || regname == Ctrl_P) {
// Get a third key for literal register insertion
literally = regname;
add_to_showcmd_c(literally);
regname = plain_vgetc();
- LANGMAP_ADJUST(regname, TRUE);
+ LANGMAP_ADJUST(regname, true);
}
no_mapping--;
allow_keys--;
@@ -4044,7 +3451,7 @@ static void ins_reg(void)
need_redraw = true; // remove the '"'
} else if (stop_insert_mode) {
// When the '=' register was used and a function was invoked that
- // did ":stopinsert" then stuff_empty() returns FALSE but we won't
+ // did ":stopinsert" then stuff_empty() returns false but we won't
// insert anything, need to remove the '"'
need_redraw = true;
}
@@ -4195,7 +3602,7 @@ static bool ins_esc(long *count, int cmdchar, bool nomove)
// Repeat the insert
return false;
}
- stop_insert(&curwin->w_cursor, TRUE, nomove);
+ stop_insert(&curwin->w_cursor, true, nomove);
undisplay_dollar();
}
@@ -4264,7 +3671,7 @@ static void ins_ctrl_(void)
{
if (revins_on && revins_chars && revins_scol >= 0) {
while (gchar_cursor() != NUL && revins_chars--) {
- ++curwin->w_cursor.col;
+ curwin->w_cursor.col++;
}
}
p_ri = !p_ri;
@@ -4393,9 +3800,9 @@ static void ins_shift(int c, int lastc)
if (lastc == '^') {
old_indent = get_indent(); // remember curr. indent
}
- change_indent(INDENT_SET, 0, TRUE, 0, TRUE);
+ change_indent(INDENT_SET, 0, true, 0, true);
} else {
- change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0, TRUE);
+ change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, true, 0, true);
}
if (did_ai && *skipwhite((char *)get_cursor_line_ptr()) != NUL) {
@@ -4567,7 +3974,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
}
}
- do_join(2, FALSE, FALSE, FALSE, false);
+ do_join(2, false, false, false, false);
if (temp == NUL && gchar_cursor() != NUL) {
inc_cursor();
}
@@ -4669,7 +4076,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
if (State & VREPLACE_FLAG) {
ins_char(' ');
} else {
- ins_str((char_u *)" ");
+ ins_str(" ");
if ((State & REPLACE_FLAG)) {
replace_push(NUL);
}
@@ -4713,7 +4120,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
} else {
const int l_p_deco = p_deco;
if (l_p_deco) {
- (void)utfc_ptr2char(get_cursor_pos_ptr(), cpc);
+ (void)utfc_ptr2char((char *)get_cursor_pos_ptr(), cpc);
}
(void)del_char(false);
// If there are combining characters and 'delcombine' is set
@@ -4849,7 +4256,7 @@ static void ins_mousescroll(int dir)
}
}
- curwin->w_redr_status = TRUE;
+ curwin->w_redr_status = true;
curwin = old_curwin;
curbuf = curwin->w_buffer;
@@ -4880,7 +4287,7 @@ static void ins_left(void)
revins_legal++;
}
revins_chars++;
- } else if (vim_strchr((char *)p_ww, '[') != NULL && curwin->w_cursor.lnum > 1) {
+ } else if (vim_strchr(p_ww, '[') != NULL && curwin->w_cursor.lnum > 1) {
// if 'whichwrap' set for cursor in insert mode may go to previous line.
// always break undo when moving upwards/downwards, else undo may break
start_arrow(&tpos);
@@ -4973,7 +4380,7 @@ static void ins_right(void)
if (revins_chars) {
revins_chars--;
}
- } else if (vim_strchr((char *)p_ww, ']') != NULL
+ } else if (vim_strchr(p_ww, ']') != NULL
&& curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
// if 'whichwrap' set for cursor in insert mode, may move the
// cursor to the next line
@@ -5017,13 +4424,13 @@ static void ins_up(bool startcol)
undisplay_dollar();
tpos = curwin->w_cursor;
- if (cursor_up(1L, TRUE) == OK) {
+ if (cursor_up(1L, true) == OK) {
if (startcol) {
coladvance(getvcol_nolist(&Insstart));
}
if (old_topline != curwin->w_topline
|| old_topfill != curwin->w_topfill) {
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
}
start_arrow(&tpos);
can_cindent = true;
@@ -5065,13 +4472,13 @@ static void ins_down(bool startcol)
undisplay_dollar();
tpos = curwin->w_cursor;
- if (cursor_down(1L, TRUE) == OK) {
+ if (cursor_down(1L, true) == OK) {
if (startcol) {
coladvance(getvcol_nolist(&Insstart));
}
if (old_topline != curwin->w_topline
|| old_topfill != curwin->w_topfill) {
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
}
start_arrow(&tpos);
can_cindent = true;
@@ -5175,7 +4582,7 @@ static bool ins_tab(void)
if (State & VREPLACE_FLAG) {
ins_char(' ');
} else {
- ins_str((char_u *)" ");
+ ins_str(" ");
if (State & REPLACE_FLAG) { // no char replaced
replace_push(NUL);
}
@@ -5233,11 +4640,15 @@ static bool ins_tab(void)
getvcol(curwin, &fpos, &vcol, NULL, NULL);
getvcol(curwin, cursor, &want_vcol, NULL, NULL);
+ char_u *tab = (char_u *)"\t";
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, 0, vcol, tab, tab);
+
// Use as many TABs as possible. Beware of 'breakindent', 'showbreak'
// and 'linebreak' adding extra virtual columns.
while (ascii_iswhite(*ptr)) {
- i = lbr_chartabsize(NULL, (char_u *)"\t", vcol);
- if (vcol + i > want_vcol) {
+ i = lbr_chartabsize(&cts);
+ if (cts.cts_vcol + i > want_vcol) {
break;
}
if (*ptr != TAB) {
@@ -5252,19 +4663,24 @@ static bool ins_tab(void)
}
fpos.col++;
ptr++;
- vcol += i;
+ cts.cts_vcol += i;
}
+ vcol = cts.cts_vcol;
+ clear_chartabsize_arg(&cts);
if (change_col >= 0) {
int repl_off = 0;
- char_u *line = ptr;
-
// Skip over the spaces we need.
- while (vcol < want_vcol && *ptr == ' ') {
- vcol += lbr_chartabsize(line, ptr, vcol);
- ptr++;
+ init_chartabsize_arg(&cts, curwin, 0, vcol, ptr, ptr);
+ while (cts.cts_vcol < want_vcol && *cts.cts_ptr == ' ') {
+ cts.cts_vcol += lbr_chartabsize(&cts);
+ cts.cts_ptr++;
repl_off++;
}
+ ptr = (char_u *)cts.cts_ptr;
+ vcol = cts.cts_vcol;
+ clear_chartabsize_arg(&cts);
+
if (vcol > want_vcol) {
// Must have a char with 'showbreak' just before it.
ptr--;
@@ -5300,7 +4716,7 @@ static bool ins_tab(void)
// Insert each char in saved_line from changed_col to
// ptr-cursor
- ins_bytes_len(saved_line + change_col, (size_t)(cursor->col - change_col));
+ ins_bytes_len((char *)saved_line + change_col, (size_t)(cursor->col - change_col));
}
}
@@ -5400,7 +4816,7 @@ static int ins_digraph(void)
if (IS_SPECIAL(c) || mod_mask) { // special key
clear_showcmd();
- insert_special(c, TRUE, FALSE);
+ insert_special(c, true, false);
return NUL;
}
if (c != ESC) {
@@ -5444,7 +4860,6 @@ static int ins_digraph(void)
int ins_copychar(linenr_T lnum)
{
int c;
- int temp;
char_u *ptr, *prev_ptr;
char_u *line;
@@ -5454,17 +4869,23 @@ int ins_copychar(linenr_T lnum)
}
// try to advance to the cursor column
- temp = 0;
- line = ptr = ml_get(lnum);
- prev_ptr = ptr;
+ line = ml_get(lnum);
+ prev_ptr = line;
validate_virtcol();
- while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL) {
- prev_ptr = ptr;
- temp += lbr_chartabsize_adv(line, &ptr, (colnr_T)temp);
+
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, lnum, 0, line, line);
+ while (cts.cts_vcol < curwin->w_virtcol && *cts.cts_ptr != NUL) {
+ prev_ptr = (char_u *)cts.cts_ptr;
+ cts.cts_vcol += lbr_chartabsize_adv(&cts);
}
- if ((colnr_T)temp > curwin->w_virtcol) {
+
+ if (cts.cts_vcol > curwin->w_virtcol) {
ptr = prev_ptr;
+ } else {
+ ptr = (char_u *)cts.cts_ptr;
}
+ clear_chartabsize_arg(&cts);
c = utf_ptr2char((char *)ptr);
if (c == NUL) {
@@ -5486,7 +4907,7 @@ static int ins_ctrl_ey(int tc)
} else {
scrollup_clamp();
}
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
} else {
c = ins_copychar(curwin->w_cursor.lnum + (c == Ctrl_Y ? -1 : 1));
if (c != NUL) {
@@ -5501,7 +4922,7 @@ static int ins_ctrl_ey(int tc)
}
tw_save = curbuf->b_p_tw;
curbuf->b_p_tw = -1;
- insert_special(c, TRUE, FALSE);
+ insert_special(c, true, false);
curbuf->b_p_tw = tw_save;
revins_chars++;
revins_legal++;
@@ -5550,7 +4971,7 @@ static void ins_try_si(int c)
i = get_indent();
curwin->w_cursor = old_pos;
if (State & VREPLACE_FLAG) {
- change_indent(INDENT_SET, i, FALSE, NUL, TRUE);
+ change_indent(INDENT_SET, i, false, NUL, true);
} else {
(void)set_indent(i, SIN_CHANGED);
}
@@ -5575,7 +4996,7 @@ static void ins_try_si(int c)
curwin->w_cursor = old_pos;
}
if (temp) {
- shift_line(TRUE, FALSE, 1, TRUE);
+ shift_line(true, false, 1, true);
}
}
}
@@ -5653,11 +5074,16 @@ static char_u *do_insert_char_pre(int c)
return res;
}
-bool can_cindent_get(void)
+bool get_can_cindent(void)
{
return can_cindent;
}
+void set_can_cindent(bool val)
+{
+ can_cindent = val;
+}
+
/// Trigger "event" and take care of fixing undo.
int ins_apply_autocmds(event_T event)
{
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 05497e86ce..e31e26832e 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -6,12 +6,6 @@
#include <math.h>
#include <stdlib.h>
-#include "auto/config.h"
-
-#ifdef HAVE_LOCALE_H
-# include <locale.h>
-#endif
-
#include "nvim/ascii.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
@@ -36,6 +30,7 @@
#include "nvim/ex_session.h"
#include "nvim/getchar.h"
#include "nvim/highlight_group.h"
+#include "nvim/locale.h"
#include "nvim/lua/executor.h"
#include "nvim/mark.h"
#include "nvim/memline.h"
@@ -101,7 +96,7 @@ static garray_T ga_loaded = { 0, 0, sizeof(char *), 4, NULL };
/// Info used by a ":for" loop.
typedef struct {
- int fi_semicolon; // TRUE if ending in '; var]'
+ int fi_semicolon; // true if ending in '; var]'
int fi_varcount; // nr of variables in the list
listwatch_T fi_lw; // keep an eye on the item used.
list_T *fi_list; // list being used
@@ -631,7 +626,7 @@ int eval_charconvert(const char *const enc_from, const char *const enc_to,
set_vim_var_string(VV_CC_TO, enc_to, -1);
set_vim_var_string(VV_FNAME_IN, fname_from, -1);
set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
- if (eval_to_bool((char *)p_ccv, &err, NULL, false)) {
+ if (eval_to_bool(p_ccv, &err, NULL, false)) {
err = true;
}
set_vim_var_string(VV_CC_FROM, NULL, -1);
@@ -651,7 +646,7 @@ int eval_printexpr(const char *const fname, const char *const args)
set_vim_var_string(VV_FNAME_IN, fname, -1);
set_vim_var_string(VV_CMDARG, args, -1);
- if (eval_to_bool((char *)p_pexpr, &err, NULL, false)) {
+ if (eval_to_bool(p_pexpr, &err, NULL, false)) {
err = true;
}
set_vim_var_string(VV_FNAME_IN, NULL, -1);
@@ -671,7 +666,7 @@ void eval_diff(const char *const origfile, const char *const newfile, const char
set_vim_var_string(VV_FNAME_IN, origfile, -1);
set_vim_var_string(VV_FNAME_NEW, newfile, -1);
set_vim_var_string(VV_FNAME_OUT, outfile, -1);
- (void)eval_to_bool((char *)p_dex, &err, NULL, false);
+ (void)eval_to_bool(p_dex, &err, NULL, false);
set_vim_var_string(VV_FNAME_IN, NULL, -1);
set_vim_var_string(VV_FNAME_NEW, NULL, -1);
set_vim_var_string(VV_FNAME_OUT, NULL, -1);
@@ -691,11 +686,11 @@ void eval_patch(const char *const origfile, const char *const difffile, const ch
}
/// Top level evaluation function, returning a boolean.
-/// Sets "error" to TRUE if there was an error.
+/// Sets "error" to true if there was an error.
///
/// @param skip only parse, don't execute
///
-/// @return TRUE or FALSE.
+/// @return true or false.
int eval_to_bool(char *arg, bool *error, char **nextcmd, int skip)
{
typval_T tv;
@@ -895,7 +890,7 @@ char *eval_to_string(char *arg, char **nextcmd, bool convert)
/// Call eval_to_string() without using current local variables and using
/// textlock.
///
-/// @param use_sandbox when TRUE, use the sandbox.
+/// @param use_sandbox when true, use the sandbox.
char *eval_to_string_safe(char *arg, char **nextcmd, int use_sandbox)
{
char *retval;
@@ -1812,7 +1807,7 @@ notify:
/// Evaluate the expression used in a ":for var in expr" command.
/// "arg" points to "var".
///
-/// @param[out] *errp set to TRUE for an error, FALSE otherwise;
+/// @param[out] *errp set to true for an error, false otherwise;
///
/// @return a pointer that holds the info. Null when there is an error.
void *eval_for_line(const char *arg, bool *errp, char **nextcmdp, int skip)
@@ -2047,7 +2042,7 @@ void set_context_for_expression(expand_T *xp, char *arg, cmdidx_T cmdidx)
|| cmdidx == CMD_echomsg)
&& xp->xp_context == EXPAND_EXPRESSION) {
for (;;) {
- char *const n = (char *)skiptowhite((char_u *)arg);
+ char *const n = skiptowhite(arg);
if (n == arg || ascii_iswhite_or_nul(*skipwhite(n))) {
break;
@@ -2184,7 +2179,7 @@ char *get_user_var_name(expand_T *xp, int idx)
/// Does not use 'cpo' and always uses 'magic'.
///
-/// @return TRUE if "pat" matches "text".
+/// @return true if "pat" matches "text".
int pattern_match(char *pat, char *text, bool ic)
{
int matches = 0;
@@ -2192,7 +2187,7 @@ int pattern_match(char *pat, char *text, bool ic)
// avoid 'l' flag in 'cpoptions'
char *save_cpo = p_cpo;
- p_cpo = "";
+ p_cpo = empty_option;
regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
if (regmatch.regprog != NULL) {
regmatch.rm_ic = ic;
@@ -2263,13 +2258,13 @@ static int eval_func(char **const arg, char *const name, const int name_len, typ
// TODO(ZyX-I): move to eval/expressions
-/// The "evaluate" argument: When FALSE, the argument is only parsed but not
+/// The "evaluate" argument: When false, the argument is only parsed but not
/// executed. The function may return OK, but the rettv will be of type
/// VAR_UNKNOWN. The function still returns FAIL for a syntax error.
/// Handle zero level expression.
/// This calls eval1() and handles error message and nextcmd.
-/// Put the result in "rettv" when returning OK and "evaluate" is TRUE.
+/// Put the result in "rettv" when returning OK and "evaluate" is true.
/// Note: "rettv.v_lock" is not set.
///
/// @return OK or FAIL.
@@ -2663,7 +2658,7 @@ static int eval5(char **arg, typval_T *rettv, int evaluate)
tv_clear(&var2);
return FAIL;
}
- p = (char *)concat_str((const char_u *)s1, (const char_u *)s2);
+ p = concat_str(s1, s2);
tv_clear(rettv);
rettv->v_type = VAR_STRING;
rettv->vval.v_string = p;
@@ -4966,7 +4961,7 @@ theend:
return retval;
}
-void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref, FunPtr fptr)
+void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref)
{
char *s;
char *name;
@@ -5226,12 +5221,12 @@ dict_T *get_win_info(win_T *wp, int16_t tpnr, int16_t winnr)
tv_dict_add_nr(dict, S_LEN("tabnr"), tpnr);
tv_dict_add_nr(dict, S_LEN("winnr"), winnr);
tv_dict_add_nr(dict, S_LEN("winid"), wp->handle);
- tv_dict_add_nr(dict, S_LEN("height"), wp->w_height);
+ tv_dict_add_nr(dict, S_LEN("height"), wp->w_height_inner);
tv_dict_add_nr(dict, S_LEN("winrow"), wp->w_winrow + 1);
tv_dict_add_nr(dict, S_LEN("topline"), wp->w_topline);
tv_dict_add_nr(dict, S_LEN("botline"), wp->w_botline - 1);
tv_dict_add_nr(dict, S_LEN("winbar"), wp->w_winbar_height);
- tv_dict_add_nr(dict, S_LEN("width"), wp->w_width);
+ tv_dict_add_nr(dict, S_LEN("width"), wp->w_width_inner);
tv_dict_add_nr(dict, S_LEN("bufnr"), wp->w_buffer->b_fnum);
tv_dict_add_nr(dict, S_LEN("wincol"), wp->w_wincol + 1);
tv_dict_add_nr(dict, S_LEN("textoff"), win_col_off(wp));
@@ -5988,7 +5983,7 @@ void timer_due_cb(TimeWatcher *tw, void *data)
// Handle error message
if (called_emsg > called_emsg_before && did_emsg) {
timer->emsg_count++;
- if (current_exception != NULL) {
+ if (did_throw) {
discard_current_exception();
}
}
@@ -6784,14 +6779,14 @@ static char *make_expanded_name(const char *in_start, char *expr_start, char *ex
return retval;
}
-/// @return TRUE if character "c" can be used in a variable or function name.
+/// @return true if character "c" can be used in a variable or function name.
/// Does not include '{' or '}' for magic braces.
int eval_isnamec(int c)
{
return ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR;
}
-/// @return TRUE if character "c" can be used as the first character in a
+/// @return true if character "c" can be used as the first character in a
/// variable or function name (excluding '{' and '}').
int eval_isnamec1(int c)
{
@@ -6844,7 +6839,7 @@ void set_vim_var_char(int c)
/// Set v:count to "count" and v:count1 to "count1".
///
-/// @param set_prevcount if TRUE, first set v:prevcount from v:count.
+/// @param set_prevcount if true, first set v:prevcount from v:count.
void set_vcount(long count, long count1, int set_prevcount)
{
if (set_prevcount) {
@@ -7403,7 +7398,7 @@ hashtab_T *find_var_ht_dict(const char *name, const size_t name_len, const char
bool should_free;
// should_free is ignored as script_sctx will be resolved to a fnmae
// & new_script_item will consume it.
- char *sc_name = (char *)get_scriptname(last_set, &should_free);
+ char *sc_name = get_scriptname(last_set, &should_free);
new_script_item(sc_name, &current_sctx.sc_sid);
}
}
@@ -7530,9 +7525,9 @@ int var_item_copy(const vimconv_T *const conv, typval_T *const from, typval_T *c
} else {
to->v_type = VAR_STRING;
to->v_lock = VAR_UNLOCKED;
- if ((to->vval.v_string = (char *)string_convert((vimconv_T *)conv,
- (char_u *)from->vval.v_string,
- NULL))
+ if ((to->vval.v_string = string_convert((vimconv_T *)conv,
+ from->vval.v_string,
+ NULL))
== NULL) {
to->vval.v_string = xstrdup(from->vval.v_string);
}
@@ -7983,7 +7978,7 @@ void option_last_set_msg(LastSet last_set)
{
if (last_set.script_ctx.sc_sid != 0) {
bool should_free;
- char *p = (char *)get_scriptname(last_set, &should_free);
+ char *p = get_scriptname(last_set, &should_free);
verbose_enter();
msg_puts(_("\n\tLast set from "));
msg_puts(p);
@@ -8080,7 +8075,7 @@ repeat:
}
// Append a path separator to a directory.
- if (os_isdir((char_u *)(*fnamep))) {
+ if (os_isdir(*fnamep)) {
// Make room for one or two extra characters.
*fnamep = xstrnsave(*fnamep, STRLEN(*fnamep) + 2);
xfree(*bufp); // free any allocated file name
@@ -8146,6 +8141,7 @@ repeat:
// Only replace it when it starts with '~'
if (*dirname == '~') {
s = xstrdup(dirname);
+ assert(s != NULL); // suppress clang "Argument with 'nonnull' attribute passed null"
*fnamep = s;
xfree(*bufp);
*bufp = s;
@@ -8164,7 +8160,7 @@ repeat:
while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h') {
valid |= VALID_HEAD;
*usedlen += 2;
- s = (char *)get_past_head((char_u *)(*fnamep));
+ s = get_past_head(*fnamep);
while (tail > s && after_pathsep(s, tail)) {
MB_PTR_BACK(*fnamep, tail);
}
@@ -8323,7 +8319,7 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, char *flags
// Make 'cpoptions' empty, so that the 'l' flag doesn't work here
char *save_cpo = p_cpo;
- p_cpo = (char *)empty_option;
+ p_cpo = empty_option;
ga_init(&ga, 1, 200);
@@ -8383,11 +8379,16 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, char *flags
char *ret = xstrdup(ga.ga_data == NULL ? str : ga.ga_data);
ga_clear(&ga);
- if ((char_u *)p_cpo == empty_option) {
+ if (p_cpo == empty_option) {
p_cpo = save_cpo;
} else {
// Darn, evaluating {sub} expression or {expr} changed the value.
- free_string_option((char_u *)save_cpo);
+ // If it's still empty it was changed and restored, need to restore in
+ // the complicated way.
+ if (*p_cpo == NUL) {
+ set_option_value_give_err("cpo", 0L, save_cpo, 0);
+ }
+ free_string_option(save_cpo);
}
return ret;
@@ -8593,7 +8594,7 @@ void ex_checkhealth(exarg_T *eap)
if (vimruntime_env == NULL) {
emsg(_("E5009: $VIMRUNTIME is empty or unset"));
} else {
- bool rtp_ok = NULL != strstr((char *)p_rtp, vimruntime_env);
+ bool rtp_ok = NULL != strstr(p_rtp, vimruntime_env);
if (rtp_ok) {
semsg(_("E5009: Invalid $VIMRUNTIME: %s"), vimruntime_env);
} else {
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index e4e9b34ec6..3e89489459 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -23,7 +23,7 @@ end
return {
funcs={
abs={args=1, base=1},
- acos={args=1, base=1, func="float_op_wrapper", data="&acos"}, -- WJMc
+ acos={args=1, base=1, float_func="acos"}, -- WJMc
add={args=2, base=1},
['and']={args=2, base=1},
api_info={},
@@ -33,7 +33,7 @@ return {
argidx={},
arglistid={args={0, 2}},
argv={args={0, 2}},
- asin={args=1, base=1, func="float_op_wrapper", data="&asin"}, -- WJMc
+ asin={args=1, base=1, float_func="asin"}, -- WJMc
assert_beeps={args=1, base=1},
assert_equal={args={2, 3}, base=2},
assert_equalfile={args={2, 3}, base=1},
@@ -47,7 +47,7 @@ return {
assert_notmatch={args={2, 3}, base=2},
assert_report={args=1, base=1},
assert_true={args={1, 2}, base=1},
- atan={args=1, base=1, func="float_op_wrapper", data="&atan"},
+ atan={args=1, base=1, float_func="atan"},
atan2={args=2, base=1},
browse={args=4},
browsedir={args=2},
@@ -67,7 +67,7 @@ return {
byteidx={args=2, base=1},
byteidxcomp={args=2, base=1},
call={args={2, 3}, base=1},
- ceil={args=1, base=1, func="float_op_wrapper", data="&ceil"},
+ ceil={args=1, base=1, float_func="ceil"},
changenr={},
chanclose={args={1, 2}},
chansend={args=2},
@@ -85,8 +85,8 @@ return {
complete_info={args={0, 1}, base=1},
confirm={args={1, 4}, base=1},
copy={args=1, base=1},
- cos={args=1, base=1, func="float_op_wrapper", data="&cos"},
- cosh={args=1, base=1, func="float_op_wrapper", data="&cosh"},
+ cos={args=1, base=1, float_func="cos"},
+ cosh={args=1, base=1, float_func="cosh"},
count={args={2, 4}, base=1},
cscope_connection={args={0, 3}},
ctxget={args={0, 1}},
@@ -117,7 +117,7 @@ return {
execute={args={1, 2}, base=1},
exepath={args=1, base=1},
exists={args=1, base=1},
- exp={args=1, base=1, func="float_op_wrapper", data="&exp"},
+ exp={args=1, base=1, float_func="exp"},
expand={args={1, 3}, base=1},
expandcmd={args=1, base=1},
extend={args={2, 3}, base=1},
@@ -130,7 +130,7 @@ return {
findfile={args={1, 3}, base=1},
flatten={args={1, 2}, base=1},
float2nr={args=1, base=1},
- floor={args=1, base=1, func="float_op_wrapper", data="&floor"},
+ floor={args=1, base=1, float_func="floor"},
fmod={args=2, base=1},
fnameescape={args=1, base=1},
fnamemodify={args=2, base=1},
@@ -245,8 +245,8 @@ return {
lispindent={args=1, base=1},
list2str={args={1, 2}, base=1},
localtime={},
- log={args=1, base=1, func="float_op_wrapper", data="&log"},
- log10={args=1, base=1, func="float_op_wrapper", data="&log10"},
+ log={args=1, base=1, float_func="log"},
+ log10={args=1, base=1, float_func="log10"},
luaeval={args={1, 2}, base=1},
map={args=2, base=1},
maparg={args={1, 4}, base=1},
@@ -304,7 +304,7 @@ return {
['repeat']={args=2, base=1},
resolve={args=1, base=1},
reverse={args=1, base=1},
- round={args=1, base=1, func="float_op_wrapper", data="&round"},
+ round={args=1, base=1, float_func="round"},
rpcnotify={args=varargs(2)},
rpcrequest={args=varargs(2)},
rpcstart={args={1, 2}},
@@ -332,6 +332,7 @@ return {
setcharpos={args=2, base=2},
setcharsearch={args=1, base=1},
setcmdpos={args=1, base=1},
+ setcmdline={args={1, 2}, base=1},
setcursorcharpos={args={1, 3}, base=1},
setenv={args=2, base=2},
setfperm={args=2, base=1},
@@ -358,8 +359,8 @@ return {
sign_unplace={args={1, 2}, base=1},
sign_unplacelist={args=1, base=1},
simplify={args=1, base=1},
- sin={args=1, base=1, func="float_op_wrapper", data="&sin"},
- sinh={args=1, base=1, func="float_op_wrapper", data="&sinh"},
+ sin={args=1, base=1, float_func="sin"},
+ sinh={args=1, base=1, float_func="sinh"},
sockconnect={args={2,3}},
sort={args={1, 3}, base=1},
soundfold={args=1, base=1},
@@ -367,7 +368,7 @@ return {
spellbadword={args={0, 1}, base=1},
spellsuggest={args={1, 3}, base=1},
split={args={1, 3}, base=1},
- sqrt={args=1, base=1, func="float_op_wrapper", data="&sqrt"},
+ sqrt={args=1, base=1, float_func="sqrt"},
srand={args={0, 1}, base=1},
stdpath={args=1},
str2float={args=1, base=1},
@@ -402,8 +403,8 @@ return {
tabpagewinnr={args={1, 2}, base=1},
tagfiles={},
taglist={args={1, 2}, base=1},
- tan={args=1, base=1, func="float_op_wrapper", data="&tan"},
- tanh={args=1, base=1, func="float_op_wrapper", data="&tanh"},
+ tan={args=1, base=1, float_func="tan"},
+ tanh={args=1, base=1, float_func="tanh"},
tempname={},
termopen={args={1, 2}},
test_garbagecollect_now={},
@@ -417,7 +418,7 @@ return {
toupper={args=1, base=1},
tr={args=3, base=1},
trim={args={1, 3}, base=1},
- trunc={args=1, base=1, func="float_op_wrapper", data="&trunc"},
+ trunc={args=1, base=1, float_func="trunc"},
type={args=1, base=1},
undofile={args=1, base=1},
undotree={},
diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c
index b461456a3a..0e0d0fe696 100644
--- a/src/nvim/eval/executor.c
+++ b/src/nvim/eval/executor.c
@@ -108,8 +108,7 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, const char *cons
const char *tvs = tv_get_string(tv1);
char numbuf[NUMBUFLEN];
char *const s =
- (char *)concat_str((const char_u *)tvs, (const char_u *)tv_get_string_buf(tv2,
- numbuf));
+ concat_str(tvs, tv_get_string_buf(tv2, numbuf));
tv_clear(tv1);
tv1->v_type = VAR_STRING;
tv1->vval.v_string = s;
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 1e39042a53..c39ad2d268 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -234,7 +234,7 @@ int call_internal_method(const char_u *const fname, const int argcount, typval_T
return ERROR_NONE;
}
-/// @return TRUE for a non-zero Number and a non-empty String.
+/// @return true for a non-zero Number and a non-empty String.
static int non_zero_arg(typval_T *argvars)
{
return ((argvars[0].v_type == VAR_NUMBER
@@ -251,26 +251,25 @@ static int non_zero_arg(typval_T *argvars)
/// Some versions of glibc on i386 have an optimization that makes it harder to
/// call math functions indirectly from inside an inlined function, causing
/// compile-time errors. Avoid `inline` in that case. #3072
-static void float_op_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void float_op_wrapper(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
float_T f;
- float_T (*function)(float_T) = (float_T (*)(float_T)) fptr;
rettv->v_type = VAR_FLOAT;
if (tv_get_float_chk(argvars, &f)) {
- rettv->vval.v_float = function(f);
+ rettv->vval.v_float = fptr.float_func(f);
} else {
rettv->vval.v_float = 0.0;
}
}
-static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void api_wrapper(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (check_secure()) {
return;
}
- ApiDispatchWrapper fn = (ApiDispatchWrapper)fptr;
+ MsgpackRpcRequestHandler handler = *fptr.api_handler;
Array args = ARRAY_DICT_INIT;
@@ -279,7 +278,8 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
Error err = ERROR_INIT;
- Object result = fn(VIML_INTERNAL_CALL, args, &err);
+ Arena res_arena = ARENA_EMPTY;
+ Object result = handler.fn(VIML_INTERNAL_CALL, args, &res_arena, &err);
if (ERROR_SET(&err)) {
semsg_multiline((const char *)e_api_error, err.msg);
@@ -292,15 +292,19 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
end:
api_free_array(args);
- api_free_object(result);
+ if (handler.arena_return) {
+ arena_mem_free(arena_finish(&res_arena));
+ } else {
+ api_free_object(result);
+ }
api_clear_error(&err);
}
/// "abs(expr)" function
-static void f_abs(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_abs(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type == VAR_FLOAT) {
- float_op_wrapper(argvars, rettv, (FunPtr)&fabs);
+ float_op_wrapper(argvars, rettv, (EvalFuncData){ .float_func = &fabs });
} else {
bool error = false;
@@ -316,7 +320,7 @@ static void f_abs(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "add(list, item)" function
-static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_add(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = 1; // Default: failed.
if (argvars[0].v_type == VAR_LIST) {
@@ -344,22 +348,21 @@ static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "and(expr, expr)" function
-static void f_and(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_and(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL)
& tv_get_number_chk(&argvars[1], NULL);
}
/// "api_info()" function
-static void f_api_info(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_api_info(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
Dictionary metadata = api_metadata();
(void)object_to_vim(DICTIONARY_OBJ(metadata), rettv, NULL);
- api_free_dictionary(metadata);
}
/// "append(lnum, string/list)" function
-static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_append(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const linenr_T lnum = tv_get_lnum(&argvars[0]);
@@ -367,7 +370,7 @@ static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "appendbufline(buf, lnum, string/list)" function
-static void f_appendbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_appendbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
buf_T *const buf = tv_get_buf(&argvars[0], false);
if (buf == NULL) {
@@ -379,7 +382,7 @@ static void f_appendbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "atan2()" function
-static void f_atan2(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_atan2(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
float_T fx;
float_T fy;
@@ -393,16 +396,16 @@ static void f_atan2(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "browse(save, title, initdir, default)" function
-static void f_browse(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_browse(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_string = NULL;
rettv->v_type = VAR_STRING;
}
/// "browsedir(title, initdir)" function
-static void f_browsedir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_browsedir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- f_browse(argvars, rettv, NULL);
+ f_browse(argvars, rettv, fptr);
}
/// Find a buffer by number or exact name.
@@ -431,7 +434,7 @@ static buf_T *find_buffer(typval_T *avar)
}
/// "bufadd(expr)" function
-static void f_bufadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_bufadd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char_u *name = (char_u *)tv_get_string(&argvars[0]);
@@ -439,13 +442,13 @@ static void f_bufadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "bufexists(expr)" function
-static void f_bufexists(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_bufexists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL);
}
/// "buflisted(expr)" function
-static void f_buflisted(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_buflisted(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
buf_T *buf;
@@ -454,7 +457,7 @@ static void f_buflisted(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "bufload(expr)" function
-static void f_bufload(typval_T *argvars, typval_T *unused, FunPtr fptr)
+static void f_bufload(typval_T *argvars, typval_T *unused, EvalFuncData fptr)
{
buf_T *buf = get_buf_arg(&argvars[0]);
@@ -469,7 +472,7 @@ static void f_bufload(typval_T *argvars, typval_T *unused, FunPtr fptr)
}
/// "bufloaded(expr)" function
-static void f_bufloaded(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_bufloaded(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
buf_T *buf;
@@ -478,7 +481,7 @@ static void f_bufloaded(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "bufname(expr)" function
-static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_bufname(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const buf_T *buf;
rettv->v_type = VAR_STRING;
@@ -494,7 +497,7 @@ static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "bufnr(expr)" function
-static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_bufnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const buf_T *buf;
bool error = false;
@@ -554,13 +557,13 @@ static void buf_win_common(typval_T *argvars, typval_T *rettv, bool get_nr)
}
/// "bufwinid(nr)" function
-static void f_bufwinid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_bufwinid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
buf_win_common(argvars, rettv, false);
}
/// "bufwinnr(nr)" function
-static void f_bufwinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_bufwinnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
buf_win_common(argvars, rettv, true);
}
@@ -588,7 +591,7 @@ buf_T *tv_get_buf(typval_T *tv, int curtab_only)
int save_magic = p_magic;
p_magic = true;
char *save_cpo = p_cpo;
- p_cpo = "";
+ p_cpo = empty_option;
buf_T *buf = buflist_findnr(buflist_findpat((char *)name, (char *)name + STRLEN(name),
true, false, curtab_only));
@@ -630,7 +633,7 @@ buf_T *get_buf_arg(typval_T *arg)
}
/// "byte2line(byte)" function
-static void f_byte2line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_byte2line(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
long boff = tv_get_number(&argvars[0]) - 1;
if (boff < 0) {
@@ -665,19 +668,19 @@ static void byteidx(typval_T *argvars, typval_T *rettv, int comp)
}
/// "byteidx()" function
-static void f_byteidx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_byteidx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
byteidx(argvars, rettv, false);
}
/// "byteidxcomp()" function
-static void f_byteidxcomp(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_byteidxcomp(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
byteidx(argvars, rettv, true);
}
/// "call(func, arglist [, dict])" function
-static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_call(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[1].v_type != VAR_LIST) {
emsg(_(e_listreq));
@@ -726,13 +729,13 @@ static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "changenr()" function
-static void f_changenr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_changenr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = curbuf->b_u_seq_cur;
}
/// "chanclose(id[, stream])" function
-static void f_chanclose(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_chanclose(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -771,7 +774,7 @@ static void f_chanclose(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "chansend(id, data)" function
-static void f_chansend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_chansend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -812,7 +815,7 @@ static void f_chansend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "char2nr(string)" function
-static void f_char2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_char2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[1].v_type != VAR_UNKNOWN) {
if (!tv_check_num(&argvars[1])) {
@@ -846,11 +849,12 @@ static void get_col(typval_T *argvars, typval_T *rettv, bool charcol)
// col(".") when the cursor is on the NUL at the end of the line
// because of "coladd" can be seen as an extra column.
if (virtual_active() && fp == &curwin->w_cursor) {
- char_u *p = get_cursor_pos_ptr();
+ char *p = (char *)get_cursor_pos_ptr();
if (curwin->w_cursor.coladd >=
- (colnr_T)win_chartabsize(curwin, p, curwin->w_virtcol - curwin->w_cursor.coladd)) {
+ (colnr_T)win_chartabsize(curwin, p,
+ curwin->w_virtcol - curwin->w_cursor.coladd)) {
int l;
- if (*p != NUL && p[(l = utfc_ptr2len((char *)p))] == NUL) {
+ if (*p != NUL && p[(l = utfc_ptr2len(p))] == NUL) {
col += l;
}
}
@@ -861,20 +865,21 @@ static void get_col(typval_T *argvars, typval_T *rettv, bool charcol)
}
/// "charcol()" function
-static void f_charcol(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_charcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
get_col(argvars, rettv, true);
}
/// "charidx()" function
-static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_charidx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = -1;
if (argvars[0].v_type != VAR_STRING
|| argvars[1].v_type != VAR_NUMBER
|| (argvars[2].v_type != VAR_UNKNOWN
- && argvars[2].v_type != VAR_NUMBER)) {
+ && argvars[2].v_type != VAR_NUMBER
+ && argvars[2].v_type != VAR_BOOL)) {
emsg(_(e_invarg));
return;
}
@@ -913,7 +918,7 @@ static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "chdir(dir)" function
-static void f_chdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_chdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
@@ -948,7 +953,7 @@ static void f_chdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "cindent(lnum)" function
-static void f_cindent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_cindent(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
pos_T pos = curwin->w_cursor;
linenr_T lnum = tv_get_lnum(argvars);
@@ -976,13 +981,13 @@ win_T *get_optional_window(typval_T *argvars, int idx)
}
/// "col(string)" function
-static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_col(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
get_col(argvars, rettv, false);
}
/// "confirm(message, buttons[, default [, type]])" function
-static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_confirm(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char buf[NUMBUFLEN];
char buf2[NUMBUFLEN];
@@ -1035,13 +1040,13 @@ static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "copy()" function
-static void f_copy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_copy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
var_item_copy(NULL, &argvars[0], rettv, false, 0);
}
/// "count()" function
-static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
long n = 0;
int ic = 0;
@@ -1130,7 +1135,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
///
/// Checks the existence of a cscope connection.
-static void f_cscope_connection(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_cscope_connection(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int num = 0;
const char *dbpath = NULL;
@@ -1151,7 +1156,7 @@ static void f_cscope_connection(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "ctxget([{index}])" function
-static void f_ctxget(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_ctxget(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
size_t index = 0;
if (argvars[0].v_type == VAR_NUMBER) {
@@ -1175,7 +1180,7 @@ static void f_ctxget(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "ctxpop()" function
-static void f_ctxpop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_ctxpop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (!ctx_restore(NULL, kCtxAll)) {
emsg(_("Context stack is empty"));
@@ -1183,7 +1188,7 @@ static void f_ctxpop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "ctxpush([{types}])" function
-static void f_ctxpush(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_ctxpush(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int types = kCtxAll;
if (argvars[0].v_type == VAR_LIST) {
@@ -1214,7 +1219,7 @@ static void f_ctxpush(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "ctxset({context}[, {index}])" function
-static void f_ctxset(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_ctxset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type != VAR_DICT) {
semsg(_(e_invarg2), "expected dictionary as first argument");
@@ -1254,7 +1259,7 @@ static void f_ctxset(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "ctxsize()" function
-static void f_ctxsize(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_ctxsize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = (varnumber_T)ctx_size();
@@ -1326,13 +1331,13 @@ static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol)
/// Moves the cursor to the specified line and column.
///
/// @return 0 when the position could be set, -1 otherwise.
-static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_cursor(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
set_cursorpos(argvars, rettv, false);
}
/// "debugbreak()" function
-static void f_debugbreak(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_debugbreak(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = FAIL;
int pid = (int)tv_get_number(&argvars[0]);
@@ -1354,7 +1359,7 @@ static void f_debugbreak(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "deepcopy()" function
-static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_deepcopy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int noref = 0;
@@ -1371,7 +1376,7 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "delete()" function
-static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_delete(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = -1;
if (check_secure()) {
@@ -1407,7 +1412,7 @@ static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// dictwatcheradd(dict, key, funcref) function
-static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (check_secure()) {
return;
@@ -1445,7 +1450,7 @@ static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// dictwatcherdel(dict, key, funcref) function
-static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (check_secure()) {
return;
@@ -1480,7 +1485,7 @@ static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "deletebufline()" function
-static void f_deletebufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_deletebufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
buf_T *const buf = tv_get_buf(&argvars[0], false);
if (buf == NULL) {
@@ -1556,19 +1561,19 @@ static void f_deletebufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "did_filetype()" function
-static void f_did_filetype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_did_filetype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = did_filetype;
}
/// "diff_filler()" function
-static void f_diff_filler(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_diff_filler(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = MAX(0, diff_check(curwin, tv_get_lnum(argvars)));
}
/// "diff_hlID()" function
-static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_diff_hlID(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
linenr_T lnum = tv_get_lnum(argvars);
static linenr_T prev_lnum = 0;
@@ -1618,7 +1623,7 @@ static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "empty({expr})" function
-static void f_empty(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_empty(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
bool n = true;
@@ -1668,7 +1673,7 @@ static void f_empty(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "environ()" function
-static void f_environ(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_environ(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_alloc_ret(rettv);
@@ -1713,7 +1718,7 @@ static void f_environ(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "escape({string}, {chars})" function
-static void f_escape(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_escape(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char buf[NUMBUFLEN];
@@ -1724,7 +1729,7 @@ static void f_escape(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getenv()" function
-static void f_getenv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getenv(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char_u *p = (char_u *)vim_getenv(tv_get_string(&argvars[0]));
@@ -1738,7 +1743,7 @@ static void f_getenv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "eval()" function
-static void f_eval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_eval(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *s = tv_get_string_chk(&argvars[0]);
if (s != NULL) {
@@ -1759,13 +1764,13 @@ static void f_eval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "eventhandler()" function
-static void f_eventhandler(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_eventhandler(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = vgetc_busy;
}
/// "executable()" function
-static void f_executable(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_executable(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (tv_check_for_string(&argvars[0]) == FAIL) {
return;
@@ -1794,7 +1799,7 @@ static char *get_list_line(int c, void *cookie, int indent, bool do_concat)
return s == NULL ? NULL : xstrdup(s);
}
-static void execute_common(typval_T *argvars, typval_T *rettv, FunPtr fptr, int arg_off)
+static void execute_common(typval_T *argvars, typval_T *rettv, int arg_off)
{
const int save_msg_silent = msg_silent;
const int save_emsg_silent = emsg_silent;
@@ -1873,13 +1878,13 @@ static void execute_common(typval_T *argvars, typval_T *rettv, FunPtr fptr, int
}
/// "execute(command)" function
-static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_execute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- execute_common(argvars, rettv, fptr, 0);
+ execute_common(argvars, rettv, 0);
}
/// "win_execute(win_id, command)" function
-static void f_win_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_win_execute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
// Return an empty string if something fails.
rettv->v_type = VAR_STRING;
@@ -1889,12 +1894,12 @@ static void f_win_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tabpage_T *tp;
win_T *wp = win_id2wp_tp(id, &tp);
if (wp != NULL && tp != NULL) {
- WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, fptr, 1));
+ WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, 1));
}
}
/// "exepath()" function
-static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_exepath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (tv_check_for_nonempty_string(&argvars[0]) == FAIL) {
return;
@@ -1915,7 +1920,7 @@ static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "exists()" function
-static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_exists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int n = false;
@@ -1955,9 +1960,8 @@ static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "expand()" function
-static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- char *errormsg;
int options = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
bool error = false;
#ifdef BACKSLASH_IN_FILENAME
@@ -1977,10 +1981,17 @@ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
const char *s = tv_get_string(&argvars[0]);
if (*s == '%' || *s == '#' || *s == '<') {
- emsg_off++;
+ if (p_verbose == 0) {
+ emsg_off++;
+ }
size_t len;
- char_u *result = eval_vars((char_u *)s, (char_u *)s, &len, NULL, &errormsg, NULL);
- emsg_off--;
+ char *errormsg = NULL;
+ char_u *result = eval_vars((char_u *)s, (char_u *)s, &len, NULL, &errormsg, NULL, false);
+ if (p_verbose == 0) {
+ emsg_off--;
+ } else if (errormsg != NULL) {
+ emsg(errormsg);
+ }
if (rettv->v_type == VAR_LIST) {
tv_list_alloc_ret(rettv, (result != NULL));
if (result != NULL) {
@@ -2026,7 +2037,7 @@ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "menu_get(path [, modes])" function
-static void f_menu_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_menu_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_list_alloc_ret(rettv, kListLenMayKnow);
int modes = MENU_ALL_MODES;
@@ -2039,7 +2050,7 @@ static void f_menu_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// "expandcmd()" function
/// Expand all the special characters in a command string.
-static void f_expandcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_expandcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char *errormsg = NULL;
@@ -2063,7 +2074,7 @@ static void f_expandcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "flatten(list[, {maxdepth}])" function
-static void f_flatten(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_flatten(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
bool error = false;
@@ -2098,7 +2109,7 @@ static void f_flatten(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// "extend(list, list [, idx])" function
/// "extend(dict, dict [, action])" function
-static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const arg_errmsg = N_("extend() argument");
@@ -2174,7 +2185,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "feedkeys()" function
-static void f_feedkeys(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_feedkeys(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
// This is not allowed in the sandbox. If the commands would still be
// executed in the sandbox it would be OK, but it probably happens later,
@@ -2195,17 +2206,17 @@ static void f_feedkeys(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "filereadable()" function
-static void f_filereadable(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_filereadable(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const p = tv_get_string(&argvars[0]);
rettv->vval.v_number =
- (*p && !os_isdir((const char_u *)p) && os_file_is_readable(p));
+ (*p && !os_isdir(p) && os_file_is_readable(p));
}
/// @return 0 for not writable
/// 1 for writable file
/// 2 for a dir which we have rights to write into.
-static void f_filewritable(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_filewritable(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *filename = tv_get_string(&argvars[0]);
rettv->vval.v_number = os_file_is_writable(filename);
@@ -2214,7 +2225,7 @@ static void f_filewritable(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what)
{
char_u *fresult = NULL;
- char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
+ char_u *path = *curbuf->b_p_path == NUL ? p_path : (char_u *)curbuf->b_p_path;
int count = 1;
bool first = true;
bool error = false;
@@ -2255,7 +2266,7 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what)
find_what, (char_u *)curbuf->b_ffname,
(find_what == FINDFILE_DIR
? (char_u *)""
- : curbuf->b_p_sua));
+ : (char_u *)curbuf->b_p_sua));
first = false;
if (fresult != NULL && rettv->v_type == VAR_LIST) {
@@ -2270,25 +2281,25 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what)
}
/// "filter()" function
-static void f_filter(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_filter(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
filter_map(argvars, rettv, false);
}
/// "finddir({fname}[, {path}[, {count}]])" function
-static void f_finddir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_finddir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
findfilendir(argvars, rettv, FINDFILE_DIR);
}
/// "findfile({fname}[, {path}[, {count}]])" function
-static void f_findfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_findfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
findfilendir(argvars, rettv, FINDFILE_FILE);
}
/// "float2nr({float})" function
-static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_float2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
float_T f;
@@ -2304,7 +2315,7 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "fmod()" function
-static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_fmod(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
float_T fx;
float_T fy;
@@ -2318,14 +2329,14 @@ static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "fnameescape({string})" function
-static void f_fnameescape(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_fnameescape(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_string = vim_strsave_fnameescape(tv_get_string(&argvars[0]), VSE_NONE);
rettv->v_type = VAR_STRING;
}
/// "fnamemodify({fname}, {mods})" function
-static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_fnamemodify(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char_u *fbuf = NULL;
size_t len = 0;
@@ -2353,21 +2364,21 @@ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "foreground()" function
-static void f_foreground(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_foreground(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{}
-static void f_funcref(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_funcref(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- common_function(argvars, rettv, true, fptr);
+ common_function(argvars, rettv, true);
}
-static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_function(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- common_function(argvars, rettv, false, fptr);
+ common_function(argvars, rettv, false);
}
/// "garbagecollect()" function
-static void f_garbagecollect(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_garbagecollect(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
// This is postponed until we are back at the toplevel, because we may be
// using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]".
@@ -2379,7 +2390,7 @@ static void f_garbagecollect(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "get()" function
-static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
typval_T *tv = NULL;
bool what_is_dict = false;
@@ -2476,7 +2487,7 @@ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getbufinfo()" function
-static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getbufinfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
buf_T *argbuf = NULL;
bool filtered = false;
@@ -2538,7 +2549,7 @@ static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// Get line or list of lines from buffer "buf" into "rettv".
///
-/// @param retlist if TRUE, then the lines are returned as a Vim List.
+/// @param retlist if true, then the lines are returned as a Vim List.
///
/// @return range (from start to end) of lines in rettv from the specified
/// buffer.
@@ -2575,7 +2586,7 @@ static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retli
}
/// "getbufline()" function
-static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
buf_T *const buf = tv_get_buf_from_arg(&argvars[0]);
@@ -2588,7 +2599,7 @@ static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getchangelist()" function
-static void f_getchangelist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getchangelist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_list_alloc_ret(rettv, 2);
@@ -2693,13 +2704,13 @@ static void getpos_both(typval_T *argvars, typval_T *rettv, bool getcurpos, bool
}
/// "getcharpos()" function
-static void f_getcharpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getcharpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
getpos_both(argvars, rettv, false, true);
}
/// "getcharsearch()" function
-static void f_getcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getcharsearch(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_alloc_ret(rettv);
@@ -2710,42 +2721,8 @@ static void f_getcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tv_dict_add_nr(dict, S_LEN("until"), last_csearch_until());
}
-/// "getcmdcompltype()" function
-static void f_getcmdcompltype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
-{
- rettv->v_type = VAR_STRING;
- rettv->vval.v_string = (char *)get_cmdline_completion();
-}
-
-/// "getcmdline()" function
-static void f_getcmdline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
-{
- rettv->v_type = VAR_STRING;
- rettv->vval.v_string = (char *)get_cmdline_str();
-}
-
-/// "getcmdpos()" function
-static void f_getcmdpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
-{
- rettv->vval.v_number = get_cmdline_pos() + 1;
-}
-
-/// "getcmdscreenpos()" function
-static void f_getcmdscreenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
-{
- rettv->vval.v_number = get_cmdline_screen_pos() + 1;
-}
-
-/// "getcmdtype()" function
-static void f_getcmdtype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
-{
- rettv->v_type = VAR_STRING;
- rettv->vval.v_string = xmallocz(1);
- rettv->vval.v_string[0] = (char)get_cmdline_type();
-}
-
/// "getcmdwintype()" function
-static void f_getcmdwintype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getcmdwintype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
@@ -2762,7 +2739,7 @@ static void f_getcmdwintype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// @pre An argument may not be -1 if preceding arguments are not all -1.
///
/// @post The return value will be a string.
-static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getcwd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
// Possible scope of working directory to return.
CdScope scope = kCdScopeInvalid;
@@ -2875,14 +2852,14 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getfontname()" function
-static void f_getfontname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getfontname(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
}
/// "getfperm({fname})" function
-static void f_getfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getfperm(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char *perm = NULL;
char_u flags[] = "rwx";
@@ -2902,7 +2879,7 @@ static void f_getfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getfsize({fname})" function
-static void f_getfsize(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getfsize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *fname = tv_get_string(&argvars[0]);
@@ -2911,7 +2888,7 @@ static void f_getfsize(typval_T *argvars, typval_T *rettv, FunPtr fptr)
FileInfo file_info;
if (os_fileinfo(fname, &file_info)) {
uint64_t filesize = os_fileinfo_size(&file_info);
- if (os_isdir((const char_u *)fname)) {
+ if (os_isdir(fname)) {
rettv->vval.v_number = 0;
} else {
rettv->vval.v_number = (varnumber_T)filesize;
@@ -2927,7 +2904,7 @@ static void f_getfsize(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getftime({fname})" function
-static void f_getftime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getftime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *fname = tv_get_string(&argvars[0]);
@@ -2940,7 +2917,7 @@ static void f_getftime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getftype({fname})" function
-static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getftype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char_u *type = NULL;
char *t;
@@ -2974,7 +2951,7 @@ static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getjumplist()" function
-static void f_getjumplist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getjumplist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_list_alloc_ret(rettv, kListLenMayKnow);
win_T *const wp = find_tabwin(&argvars[0], &argvars[1]);
@@ -3005,7 +2982,7 @@ static void f_getjumplist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getline(lnum, [end])" function
-static void f_getline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
linenr_T end;
bool retlist;
@@ -3023,7 +3000,7 @@ static void f_getline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getmarklist()" function
-static void f_getmarklist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getmarklist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_list_alloc_ret(rettv, kListLenMayKnow);
@@ -3041,7 +3018,7 @@ static void f_getmarklist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getmousepos()" function
-static void f_getmousepos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getmousepos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int row = mouse_row;
int col = mouse_col;
@@ -3082,24 +3059,24 @@ static void f_getmousepos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getpid()" function
-static void f_getpid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getpid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = os_get_pid();
}
/// "getcurpos(string)" function
-static void f_getcurpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getcurpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
getpos_both(argvars, rettv, true, false);
}
-static void f_getcursorcharpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getcursorcharpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
getpos_both(argvars, rettv, true, true);
}
/// "getpos(string)" function
-static void f_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
getpos_both(argvars, rettv, false, false);
}
@@ -3125,7 +3102,7 @@ static int getreg_get_regname(typval_T *argvars)
}
/// "getreg()" function
-static void f_getreg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getreg(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int arg2 = false;
bool return_list = false;
@@ -3161,7 +3138,7 @@ static void f_getreg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getregtype()" function
-static void f_getregtype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getregtype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
// on error return an empty string
rettv->v_type = VAR_STRING;
@@ -3181,7 +3158,7 @@ static void f_getregtype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "gettabinfo()" function
-static void f_gettabinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_gettabinfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tabpage_T *tparg = NULL;
@@ -3213,7 +3190,7 @@ static void f_gettabinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "gettagstack()" function
-static void f_gettagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_gettagstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
win_T *wp = curwin; // default is current window
@@ -3230,7 +3207,7 @@ static void f_gettagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getwininfo()" function
-static void f_getwininfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getwininfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
win_T *wparg = NULL;
@@ -3275,7 +3252,7 @@ static void dummy_timer_close_cb(TimeWatcher *tw, void *data)
}
/// "wait(timeout, condition[, interval])" function
-static void f_wait(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_wait(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = -1;
@@ -3329,7 +3306,7 @@ static void f_wait(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "win_screenpos()" function
-static void f_win_screenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_win_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_list_alloc_ret(rettv, 2);
const win_T *const wp = find_win_by_nr_or_id(&argvars[0]);
@@ -3376,7 +3353,7 @@ static void win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags
}
/// "win_splitmove()" function
-static void f_win_splitmove(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_win_splitmove(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
win_T *wp = find_win_by_nr_or_id(&argvars[0]);
win_T *targetwin = find_win_by_nr_or_id(&argvars[1]);
@@ -3414,7 +3391,7 @@ static void f_win_splitmove(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getwinpos({timeout})" function
-static void f_getwinpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getwinpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_list_alloc_ret(rettv, 2);
tv_list_append_number(rettv->vval.v_list, -1);
@@ -3422,19 +3399,19 @@ static void f_getwinpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getwinposx()" function
-static void f_getwinposx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getwinposx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = -1;
}
/// "getwinposy()" function
-static void f_getwinposy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getwinposy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = -1;
}
/// "glob()" function
-static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_glob(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int options = WILD_SILENT|WILD_USE_NL;
expand_T xpc;
@@ -3483,7 +3460,7 @@ static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "globpath()" function
-static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_globpath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int flags = WILD_IGNORE_COMPLETESLASH; // Flags for globpath.
bool error = false;
@@ -3514,7 +3491,7 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (file != NULL && !error) {
garray_T ga;
ga_init(&ga, (int)sizeof(char_u *), 10);
- globpath((char *)tv_get_string(&argvars[0]), (char_u *)file, &ga, flags);
+ globpath((char *)tv_get_string(&argvars[0]), (char *)file, &ga, flags);
if (rettv->v_type == VAR_STRING) {
rettv->vval.v_string = ga_concat_strings_sep(&ga, "\n");
@@ -3533,7 +3510,7 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "glob2regpat()" function
-static void f_glob2regpat(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_glob2regpat(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const pat = tv_get_string_chk(&argvars[0]); // NULL on type error
@@ -3542,7 +3519,7 @@ static void f_glob2regpat(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "has()" function
-static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
static const char *const has_list[] = {
#if defined(BSD) && !defined(__APPLE__)
@@ -3765,7 +3742,7 @@ static bool has_wsl(void)
/// @pre An argument may not be -1 if preceding arguments are not all -1.
///
/// @post The return value will be either the number `1` or `0`.
-static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_haslocaldir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
// Possible scope of working directory to return.
CdScope scope = kCdScopeInvalid;
@@ -3855,19 +3832,19 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "highlightID(name)" function
-static void f_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_hlID(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = syn_name2id(tv_get_string(&argvars[0]));
}
/// "highlight_exists()" function
-static void f_hlexists(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_hlexists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = highlight_exists(tv_get_string(&argvars[0]));
}
/// "hostname()" function
-static void f_hostname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_hostname(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char hostname[256];
@@ -3877,7 +3854,7 @@ static void f_hostname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// iconv() function
-static void f_iconv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_iconv(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
vimconv_T vimconv;
@@ -3886,17 +3863,19 @@ static void f_iconv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
const char *const str = tv_get_string(&argvars[0]);
char buf1[NUMBUFLEN];
- char_u *const from = enc_canonize(enc_skip((char_u *)tv_get_string_buf(&argvars[1], buf1)));
+ char_u *const from =
+ (char_u *)enc_canonize(enc_skip((char *)tv_get_string_buf(&argvars[1], buf1)));
char buf2[NUMBUFLEN];
- char_u *const to = enc_canonize(enc_skip((char_u *)tv_get_string_buf(&argvars[2], buf2)));
+ char_u *const to =
+ (char_u *)enc_canonize(enc_skip((char *)tv_get_string_buf(&argvars[2], buf2)));
vimconv.vc_type = CONV_NONE;
- convert_setup(&vimconv, from, to);
+ convert_setup(&vimconv, (char *)from, (char *)to);
// If the encodings are equal, no conversion needed.
if (vimconv.vc_type == CONV_NONE) {
rettv->vval.v_string = xstrdup(str);
} else {
- rettv->vval.v_string = (char *)string_convert(&vimconv, (char_u *)str, NULL);
+ rettv->vval.v_string = string_convert(&vimconv, (char *)str, NULL);
}
convert_setup(&vimconv, NULL, NULL);
@@ -3905,7 +3884,7 @@ static void f_iconv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "indent()" function
-static void f_indent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_indent(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const linenr_T lnum = tv_get_lnum(argvars);
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) {
@@ -3916,7 +3895,7 @@ static void f_indent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "index()" function
-static void f_index(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_index(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
long idx = 0;
bool ic = false;
@@ -3991,19 +3970,19 @@ static bool inputsecret_flag = false;
/// "input()" function
/// Also handles inputsecret() when inputsecret is set.
-static void f_input(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_input(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
get_user_input(argvars, rettv, false, inputsecret_flag);
}
/// "inputdialog()" function
-static void f_inputdialog(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_inputdialog(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
get_user_input(argvars, rettv, true, inputsecret_flag);
}
/// "inputlist()" function
-static void f_inputlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_inputlist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type != VAR_LIST) {
semsg(_(e_listarg), "inputlist()");
@@ -4034,7 +4013,7 @@ static void f_inputlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static garray_T ga_userinput = { 0, 0, sizeof(tasave_T), 4, NULL };
/// "inputrestore()" function
-static void f_inputrestore(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_inputrestore(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (!GA_EMPTY(&ga_userinput)) {
ga_userinput.ga_len--;
@@ -4048,7 +4027,7 @@ static void f_inputrestore(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "inputsave()" function
-static void f_inputsave(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_inputsave(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
// Add an entry to the stack of typeahead storage.
tasave_T *p = GA_APPEND_VIA_PTR(tasave_T, &ga_userinput);
@@ -4056,17 +4035,17 @@ static void f_inputsave(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "inputsecret()" function
-static void f_inputsecret(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_inputsecret(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
cmdline_star++;
inputsecret_flag = true;
- f_input(argvars, rettv, NULL);
+ f_input(argvars, rettv, fptr);
cmdline_star--;
inputsecret_flag = false;
}
/// "insert()" function
-static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
list_T *l;
bool error = false;
@@ -4139,25 +4118,25 @@ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// "interrupt()" function
static void f_interrupt(typval_T *argvars FUNC_ATTR_UNUSED, typval_T *rettv FUNC_ATTR_UNUSED,
- FunPtr fptr FUNC_ATTR_UNUSED)
+ EvalFuncData fptr FUNC_ATTR_UNUSED)
{
got_int = true;
}
/// "invert(expr)" function
-static void f_invert(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_invert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = ~tv_get_number_chk(&argvars[0], NULL);
}
/// "isdirectory()" function
-static void f_isdirectory(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_isdirectory(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- rettv->vval.v_number = os_isdir((const char_u *)tv_get_string(&argvars[0]));
+ rettv->vval.v_number = os_isdir(tv_get_string(&argvars[0]));
}
/// "islocked()" function
-static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_islocked(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
lval_T lv;
@@ -4199,7 +4178,7 @@ static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "isinf()" function
-static void f_isinf(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_isinf(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type == VAR_FLOAT
&& xisinf(argvars[0].vval.v_float)) {
@@ -4208,14 +4187,14 @@ static void f_isinf(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "isnan()" function
-static void f_isnan(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_isnan(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = argvars[0].v_type == VAR_FLOAT
&& xisnan(argvars[0].vval.v_float);
}
/// "id()" function
-static void f_id(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_id(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
FUNC_ATTR_NONNULL_ALL
{
const int len = vim_vsnprintf_typval(NULL, 0, "%p", dummy_ap, argvars);
@@ -4225,7 +4204,7 @@ static void f_id(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "jobpid(id)" function
-static void f_jobpid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_jobpid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -4249,7 +4228,7 @@ static void f_jobpid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "jobresize(job, width, height)" function
-static void f_jobresize(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_jobresize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -4316,7 +4295,7 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en
if (!clear_env) {
typval_T temp_env = TV_INITIAL_VALUE;
- f_environ(NULL, &temp_env, NULL);
+ f_environ(NULL, &temp_env, (EvalFuncData){ .nullptr = NULL });
tv_dict_extend(env, temp_env.vval.v_dict, "force");
tv_dict_free(temp_env.vval.v_dict);
@@ -4405,7 +4384,7 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en
}
/// "jobstart()" function
-static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_jobstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -4480,7 +4459,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (new_cwd && *new_cwd != NUL) {
cwd = new_cwd;
// The new cwd must be a directory.
- if (!os_isdir((const char_u *)cwd)) {
+ if (!os_isdir(cwd)) {
semsg(_(e_invarg2), "expected valid directory");
shell_free_argv(argv);
return;
@@ -4525,7 +4504,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "jobstop()" function
-static void f_jobstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_jobstop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -4558,7 +4537,7 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "jobwait(ids[, timeout])" function
-static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_jobwait(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -4657,7 +4636,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// json_decode() function
-static void f_json_decode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_json_decode(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char numbuf[NUMBUFLEN];
const char *s = NULL;
@@ -4691,14 +4670,14 @@ static void f_json_decode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// json_encode() function
-static void f_json_encode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_json_encode(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = encode_tv2json(&argvars[0], NULL);
}
/// "last_buffer_nr()" function.
-static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int n = 0;
@@ -4712,7 +4691,7 @@ static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "len()" function
-static void f_len(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_len(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
switch (argvars[0].v_type) {
case VAR_STRING:
@@ -4783,19 +4762,19 @@ static void libcall_common(typval_T *argvars, typval_T *rettv, int out_type)
}
/// "libcall()" function
-static void f_libcall(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_libcall(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
libcall_common(argvars, rettv, VAR_STRING);
}
/// "libcallnr()" function
-static void f_libcallnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_libcallnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
libcall_common(argvars, rettv, VAR_NUMBER);
}
/// "line(string, [winid])" function
-static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_line(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
linenr_T lnum = 0;
pos_T *fp = NULL;
@@ -4826,7 +4805,7 @@ static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "line2byte(lnum)" function
-static void f_line2byte(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_line2byte(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const linenr_T lnum = tv_get_lnum(argvars);
if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1) {
@@ -4840,7 +4819,7 @@ static void f_line2byte(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "lispindent(lnum)" function
-static void f_lispindent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_lispindent(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const pos_T pos = curwin->w_cursor;
const linenr_T lnum = tv_get_lnum(argvars);
@@ -4854,13 +4833,13 @@ static void f_lispindent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "localtime()" function
-static void f_localtime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_localtime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = (varnumber_T)time(NULL);
}
/// luaeval() function implementation
-static void f_luaeval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_luaeval(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
FUNC_ATTR_NONNULL_ALL
{
const char *const str = tv_get_string_chk(&argvars[0]);
@@ -4872,7 +4851,7 @@ static void f_luaeval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "map()" function
-static void f_map(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_map(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
filter_map(argvars, rettv, true);
}
@@ -4894,7 +4873,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv,
// Make 'cpoptions' empty, the 'l' flag should not be used here.
char *save_cpo = p_cpo;
- p_cpo = "";
+ p_cpo = empty_option;
rettv->vval.v_number = -1;
switch (type) {
@@ -5090,31 +5069,31 @@ theend:
}
/// "match()" function
-static void f_match(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_match(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
find_some_match(argvars, rettv, kSomeMatch);
}
/// "matchend()" function
-static void f_matchend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_matchend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
find_some_match(argvars, rettv, kSomeMatchEnd);
}
/// "matchlist()" function
-static void f_matchlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_matchlist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
find_some_match(argvars, rettv, kSomeMatchList);
}
/// "matchstr()" function
-static void f_matchstr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_matchstr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
find_some_match(argvars, rettv, kSomeMatchStr);
}
/// "matchstrpos()" function
-static void f_matchstrpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_matchstrpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
find_some_match(argvars, rettv, kSomeMatchStrPos);
}
@@ -5169,19 +5148,19 @@ static void max_min(const typval_T *const tv, typval_T *const rettv, const bool
}
/// "max()" function
-static void f_max(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_max(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
max_min(argvars, rettv, true);
}
/// "min()" function
-static void f_min(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_min(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
max_min(argvars, rettv, false);
}
/// "mkdir()" function
-static void f_mkdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_mkdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int prot = 0755; // -V536
@@ -5226,7 +5205,7 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "mode()" function
-static void f_mode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_mode(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char buf[MODE_MAX_LENGTH];
@@ -5243,7 +5222,7 @@ static void f_mode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "msgpackdump()" function
-static void f_msgpackdump(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_msgpackdump(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
FUNC_ATTR_NONNULL_ALL
{
if (argvars[0].v_type != VAR_LIST) {
@@ -5382,7 +5361,7 @@ static void msgpackparse_unpack_blob(const blob_T *const blob, list_T *const ret
}
/// "msgpackparse" function
-static void f_msgpackparse(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_msgpackparse(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
FUNC_ATTR_NONNULL_ALL
{
if (argvars[0].v_type != VAR_LIST && argvars[0].v_type != VAR_BLOB) {
@@ -5398,7 +5377,7 @@ static void f_msgpackparse(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "nextnonblank()" function
-static void f_nextnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_nextnonblank(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
linenr_T lnum;
@@ -5415,7 +5394,7 @@ static void f_nextnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "nr2char()" function
-static void f_nr2char(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_nr2char(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[1].v_type != VAR_UNKNOWN) {
if (!tv_check_num(&argvars[1])) {
@@ -5446,14 +5425,14 @@ static void f_nr2char(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "or(expr, expr)" function
-static void f_or(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_or(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL)
| tv_get_number_chk(&argvars[1], NULL);
}
/// "pathshorten()" function
-static void f_pathshorten(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_pathshorten(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int trim_len = 1;
@@ -5475,7 +5454,7 @@ static void f_pathshorten(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "pow()" function
-static void f_pow(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_pow(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
float_T fx;
float_T fy;
@@ -5489,7 +5468,7 @@ static void f_pow(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "prevnonblank()" function
-static void f_prevnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_prevnonblank(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
linenr_T lnum = tv_get_lnum(argvars);
if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) {
@@ -5503,7 +5482,7 @@ static void f_prevnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "printf()" function
-static void f_printf(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_printf(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
@@ -5525,7 +5504,7 @@ static void f_printf(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "prompt_setcallback({buffer}, {callback})" function
-static void f_prompt_setcallback(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_prompt_setcallback(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
Callback prompt_callback = { .type = kCallbackNone };
@@ -5548,7 +5527,7 @@ static void f_prompt_setcallback(typval_T *argvars, typval_T *rettv, FunPtr fptr
}
/// "prompt_setinterrupt({buffer}, {callback})" function
-static void f_prompt_setinterrupt(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_prompt_setinterrupt(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
Callback interrupt_callback = { .type = kCallbackNone };
@@ -5571,7 +5550,7 @@ static void f_prompt_setinterrupt(typval_T *argvars, typval_T *rettv, FunPtr fpt
}
/// "prompt_getprompt({buffer})" function
-static void f_prompt_getprompt(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_prompt_getprompt(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
FUNC_ATTR_NONNULL_ALL
{
// return an empty string by default, e.g. it's not a prompt buffer
@@ -5591,7 +5570,7 @@ static void f_prompt_getprompt(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "prompt_setprompt({buffer}, {text})" function
-static void f_prompt_setprompt(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_prompt_setprompt(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (check_secure()) {
return;
@@ -5607,14 +5586,14 @@ static void f_prompt_setprompt(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "pum_getpos()" function
-static void f_pum_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_pum_getpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_alloc_ret(rettv);
pum_set_event_info(rettv->vval.v_dict);
}
/// "pumvisible()" function
-static void f_pumvisible(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_pumvisible(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (pum_visible()) {
rettv->vval.v_number = 1;
@@ -5622,7 +5601,7 @@ static void f_pumvisible(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "py3eval()" and "pyxeval()" functions (always python3)
-static void f_py3eval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_py3eval(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
script_host_eval("python3", argvars, rettv);
}
@@ -5694,7 +5673,7 @@ static inline uint32_t shuffle_xoshiro128starstar(uint32_t *const x, uint32_t *c
}
/// "rand()" function
-static void f_rand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_rand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
uint32_t result;
@@ -5705,7 +5684,7 @@ static void f_rand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// When no argument is given use the global seed list.
if (!initialized) {
// Initialize the global seed list.
- uint32_t x;
+ uint32_t x = 0;
init_srand(&x);
gx = splitmix32(&x);
@@ -5764,7 +5743,7 @@ theend:
}
/// "srand()" function
-static void f_srand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_srand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
uint32_t x = 0;
@@ -5786,19 +5765,19 @@ static void f_srand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "perleval()" function
-static void f_perleval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_perleval(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
script_host_eval("perl", argvars, rettv);
}
/// "rubyeval()" function
-static void f_rubyeval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_rubyeval(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
script_host_eval("ruby", argvars, rettv);
}
/// "range()" function
-static void f_range(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_range(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
varnumber_T end;
varnumber_T stride = 1;
@@ -5868,7 +5847,7 @@ theend:
}
/// "readdir()" function
-static void f_readdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_readdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_list_alloc_ret(rettv, kListLenUnknown);
@@ -5886,7 +5865,7 @@ static void f_readdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "readfile()" function
-static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_readfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
bool binary = false;
bool blob = false;
@@ -5913,7 +5892,7 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// their own about CR-LF conversion.
const char *const fname = tv_get_string(&argvars[0]);
- if (os_isdir((const char_u *)fname)) {
+ if (os_isdir(fname)) {
semsg(_(e_isadir2), fname);
return;
}
@@ -6069,7 +6048,7 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getreginfo()" function
-static void f_getreginfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_getreginfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int regname = getreg_get_regname(argvars);
if (regname == 0) {
@@ -6119,18 +6098,18 @@ static void f_getreginfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "reg_executing()" function
-static void f_reg_executing(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_reg_executing(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
return_register(reg_executing, rettv);
}
/// "reg_recording()" function
-static void f_reg_recording(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_reg_recording(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
return_register(reg_recording, rettv);
}
-static void f_reg_recorded(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_reg_recorded(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
return_register(reg_recorded, rettv);
}
@@ -6172,7 +6151,7 @@ static int list2proftime(typval_T *arg, proftime_T *tm) FUNC_ATTR_NONNULL_ALL
/// one argument it returns the time passed since the argument.
/// With two arguments it returns the time passed between
/// the two arguments.
-static void f_reltime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_reltime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
proftime_T res;
proftime_T start;
@@ -6214,7 +6193,7 @@ static void f_reltime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "reltimestr()" function
-static void f_reltimestr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_reltimestr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
FUNC_ATTR_NONNULL_ALL
{
proftime_T tm;
@@ -6227,7 +6206,7 @@ static void f_reltimestr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "remove()" function
-static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_remove(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const arg_errmsg = N_("remove() argument");
@@ -6243,7 +6222,7 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "rename({from}, {to})" function
-static void f_rename(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_rename(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (check_secure()) {
rettv->vval.v_number = -1;
@@ -6255,7 +6234,7 @@ static void f_rename(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "repeat()" function
-static void f_repeat(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_repeat(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
varnumber_T n = tv_get_number(&argvars[1]);
if (argvars[0].v_type == VAR_LIST) {
@@ -6292,7 +6271,7 @@ static void f_repeat(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "resolve()" function
-static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_resolve(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
const char *fname = tv_get_string(&argvars[0]);
@@ -6303,7 +6282,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr)
v = os_realpath(fname, v);
}
}
- rettv->vval.v_string = (char_u *)(v == NULL ? xstrdup(fname) : v);
+ rettv->vval.v_string = (v == NULL ? xstrdup(fname) : v);
#else
# ifdef HAVE_READLINK
{
@@ -6365,7 +6344,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (*q != NUL) {
cpy = remain;
remain = (remain
- ? (char *)concat_str((char_u *)q - 1, (char_u *)remain)
+ ? concat_str(q - 1, remain)
: xstrdup(q - 1));
xfree(cpy);
q[-1] = NUL;
@@ -6424,7 +6403,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr)
&& (p[2] == NUL
|| vim_ispathsep(p[2])))))) {
// Prepend "./".
- cpy = (char *)concat_str((const char_u *)"./", (const char_u *)p);
+ cpy = concat_str("./", p);
xfree(p);
p = cpy;
} else if (!is_relative_to_current) {
@@ -6461,7 +6440,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "reverse({list})" function
-static void f_reverse(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_reverse(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type == VAR_BLOB) {
blob_T *const b = argvars[0].vval.v_blob;
@@ -6486,7 +6465,7 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "reduce(list, { accumulator, element -> value } [, initial])" function
-static void f_reduce(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_reduce(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type != VAR_LIST && argvars[0].v_type != VAR_BLOB) {
emsg(_(e_listblobreq));
@@ -6786,7 +6765,7 @@ theend:
}
/// "rpcnotify()" function
-static void f_rpcnotify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_rpcnotify(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -6821,7 +6800,7 @@ static void f_rpcnotify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "rpcrequest()" function
-static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -6910,12 +6889,12 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
end:
- arena_mem_free(res_mem, NULL);
+ arena_mem_free(res_mem);
api_clear_error(&err);
}
/// "rpcstart()" function (DEPRECATED)
-static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_rpcstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -6982,7 +6961,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "rpcstop()" function
-static void f_rpcstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_rpcstop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -7000,7 +6979,7 @@ static void f_rpcstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// if called with a job, stop it, else closes the channel
uint64_t id = (uint64_t)argvars[0].vval.v_number;
if (find_job(id, false)) {
- f_jobstop(argvars, rettv, NULL);
+ f_jobstop(argvars, rettv, fptr);
} else {
const char *error;
rettv->vval.v_number =
@@ -7012,7 +6991,7 @@ static void f_rpcstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "screenattr()" function
-static void f_screenattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_screenattr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int row = (int)tv_get_number_chk(&argvars[0], NULL) - 1;
int col = (int)tv_get_number_chk(&argvars[1], NULL) - 1;
@@ -7030,7 +7009,7 @@ static void f_screenattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "screenchar()" function
-static void f_screenchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_screenchar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int row = (int)tv_get_number_chk(&argvars[0], NULL) - 1;
int col = (int)tv_get_number_chk(&argvars[1], NULL) - 1;
@@ -7048,7 +7027,7 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "screenchars()" function
-static void f_screenchars(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_screenchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int row = (int)tv_get_number_chk(&argvars[0], NULL) - 1;
int col = (int)tv_get_number_chk(&argvars[1], NULL) - 1;
@@ -7061,7 +7040,7 @@ static void f_screenchars(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
int pcc[MAX_MCO];
- int c = utfc_ptr2char(grid->chars[grid->line_offset[row] + (size_t)col], pcc);
+ int c = utfc_ptr2char((char *)grid->chars[grid->line_offset[row] + (size_t)col], pcc);
int composing_len = 0;
while (pcc[composing_len] != 0) {
composing_len++;
@@ -7076,13 +7055,13 @@ static void f_screenchars(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// "screencol()" function
///
/// First column is 1 to be consistent with virtcol().
-static void f_screencol(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_screencol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = ui_current_col() + 1;
}
/// "screenpos({winid}, {lnum}, {col})" function
-static void f_screenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_alloc_ret(rettv);
dict_T *dict = rettv->vval.v_dict;
@@ -7108,13 +7087,13 @@ static void f_screenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "screenrow()" function
-static void f_screenrow(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_screenrow(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = ui_current_row() + 1;
}
/// "screenstring()" function
-static void f_screenstring(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_screenstring(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_string = NULL;
rettv->v_type = VAR_STRING;
@@ -7133,7 +7112,7 @@ static void f_screenstring(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "search()" function
-static void f_search(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_search(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int flags = 0;
@@ -7141,7 +7120,7 @@ static void f_search(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "searchdecl()" function
-static void f_searchdecl(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_searchdecl(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int locally = 1;
int thisblock = 0;
@@ -7236,13 +7215,13 @@ theend:
}
/// "searchpair()" function
-static void f_searchpair(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_searchpair(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = searchpair_cmn(argvars, NULL);
}
/// "searchpairpos()" function
-static void f_searchpairpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_searchpairpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
pos_T match_pos;
int lnum = 0;
@@ -7284,7 +7263,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir
// Make 'cpoptions' empty, the 'l' flag should not be used here.
char *save_cpo = p_cpo;
- p_cpo = (char *)empty_option;
+ p_cpo = empty_option;
// Set the time limit, if there is one.
proftime_T tm = profile_setlimit(time_limit);
@@ -7410,18 +7389,23 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir
xfree(pat2);
xfree(pat3);
- if ((char_u *)p_cpo == empty_option) {
+ if (p_cpo == empty_option) {
p_cpo = save_cpo;
} else {
// Darn, evaluating the {skip} expression changed the value.
- free_string_option((char_u *)save_cpo);
+ // If it's still empty it was changed and restored, need to restore in
+ // the complicated way.
+ if (*p_cpo == NUL) {
+ set_option_value_give_err("cpo", 0L, save_cpo, 0);
+ }
+ free_string_option(save_cpo);
}
return retval;
}
/// "searchpos()" function
-static void f_searchpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_searchpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
pos_T match_pos;
int flags = 0;
@@ -7441,7 +7425,7 @@ static void f_searchpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "serverlist()" function
-static void f_serverlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_serverlist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
size_t n;
char **addrs = server_address_list(&n);
@@ -7455,7 +7439,7 @@ static void f_serverlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "serverstart()" function
-static void f_serverstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_serverstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL; // Address of the new server
@@ -7500,7 +7484,7 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "serverstop()" function
-static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_serverstop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (check_secure()) {
return;
@@ -7520,7 +7504,7 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "setbufline()" function
-static void f_setbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_setbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
linenr_T lnum;
buf_T *buf;
@@ -7535,7 +7519,7 @@ static void f_setbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// Set the cursor or mark position.
-/// If 'charpos' is TRUE, then use the column number as a character offset.
+/// If 'charpos' is true, then use the column number as a character offset.
/// Otherwise use the column number as a byte offset.
static void set_position(typval_T *argvars, typval_T *rettv, bool charpos)
{
@@ -7572,12 +7556,12 @@ static void set_position(typval_T *argvars, typval_T *rettv, bool charpos)
}
/// "setcharpos()" function
-static void f_setcharpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_setcharpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
set_position(argvars, rettv, true);
}
-static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_setcharsearch(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type != VAR_DICT) {
emsg(_(e_dictreq));
@@ -7589,7 +7573,7 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
char_u *const csearch = (char_u *)tv_dict_get_string(d, "char", false);
if (csearch != NULL) {
int pcc[MAX_MCO];
- const int c = utfc_ptr2char(csearch, pcc);
+ const int c = utfc_ptr2char((char *)csearch, pcc);
set_last_csearch(c, csearch, utfc_ptr2len((char *)csearch));
}
@@ -7605,24 +7589,14 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/// "setcmdpos()" function
-static void f_setcmdpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
-{
- const int pos = (int)tv_get_number(&argvars[0]) - 1;
-
- if (pos >= 0) {
- rettv->vval.v_number = set_cmdline_pos(pos);
- }
-}
-
/// "setcursorcharpos" function
-static void f_setcursorcharpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_setcursorcharpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
set_cursorpos(argvars, rettv, true);
}
/// "setenv()" function
-static void f_setenv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_setenv(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char namebuf[NUMBUFLEN];
char valbuf[NUMBUFLEN];
@@ -7637,7 +7611,7 @@ static void f_setenv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "setfperm({fname}, {mode})" function
-static void f_setfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_setfperm(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = 0;
@@ -7668,14 +7642,14 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "setline()" function
-static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_setline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
linenr_T lnum = tv_get_lnum(&argvars[0]);
set_buffer_lines(curbuf, lnum, false, &argvars[1], rettv);
}
/// "setpos()" function
-static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_setpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
set_position(argvars, rettv, false);
}
@@ -7711,7 +7685,7 @@ static int get_yank_type(char **const pp, MotionType *const yank_type, long *con
}
/// "setreg()" function
-static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_setreg(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
bool append = false;
@@ -7852,7 +7826,7 @@ free_lstval:
}
/// "settagstack()" function
-static void f_settagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_settagstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
static char *e_invact2 = N_("E962: Invalid action: '%s'");
char action = 'r';
@@ -7903,7 +7877,7 @@ static void f_settagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// f_sha256 - sha256({string}) function
-static void f_sha256(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_sha256(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *p = tv_get_string(&argvars[0]);
const char *hash = sha256_bytes((const uint8_t *)p, strlen(p), NULL, 0);
@@ -7914,7 +7888,7 @@ static void f_sha256(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "shellescape({string})" function
-static void f_shellescape(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_shellescape(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const bool do_special = non_zero_arg(&argvars[1]);
@@ -7925,7 +7899,7 @@ static void f_shellescape(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// shiftwidth() function
-static void f_shiftwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_shiftwidth(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = 0;
@@ -7941,7 +7915,7 @@ static void f_shiftwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "simplify()" function
-static void f_simplify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_simplify(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const p = tv_get_string(&argvars[0]);
rettv->vval.v_string = xstrdup(p);
@@ -7950,7 +7924,7 @@ static void f_simplify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "sockconnect()" function
-static void f_sockconnect(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_sockconnect(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type != VAR_STRING || argvars[1].v_type != VAR_STRING) {
emsg(_(e_invarg));
@@ -8002,7 +7976,7 @@ static void f_sockconnect(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "stdioopen()" function
-static void f_stdioopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_stdioopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type != VAR_DICT) {
emsg(_(e_invarg));
@@ -8036,7 +8010,7 @@ static void f_stdioopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "reltimefloat()" function
-static void f_reltimefloat(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_reltimefloat(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
FUNC_ATTR_NONNULL_ALL
{
proftime_T tm;
@@ -8049,7 +8023,7 @@ static void f_reltimefloat(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "soundfold({word})" function
-static void f_soundfold(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_soundfold(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
const char *const s = tv_get_string(&argvars[0]);
@@ -8057,7 +8031,7 @@ static void f_soundfold(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "spellbadword()" function
-static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_spellbadword(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const int wo_spell_save = curwin->w_p_spell;
@@ -8113,7 +8087,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "spellsuggest()" function
-static void f_spellsuggest(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_spellsuggest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
garray_T ga = GA_EMPTY_INIT_VALUE;
const int wo_spell_save = curwin->w_p_spell;
@@ -8160,7 +8134,7 @@ f_spellsuggest_return:
curwin->w_p_spell = wo_spell_save;
}
-static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_split(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
colnr_T col = 0;
bool keepempty = false;
@@ -8168,7 +8142,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// Make 'cpoptions' empty, the 'l' flag should not be used here.
char *save_cpo = p_cpo;
- p_cpo = "";
+ p_cpo = empty_option;
const char *str = tv_get_string(&argvars[0]);
const char *pat = NULL;
@@ -8239,7 +8213,7 @@ theend:
}
/// "stdpath(type)" function
-static void f_stdpath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_stdpath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
@@ -8271,7 +8245,7 @@ static void f_stdpath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "str2float()" function
-static void f_str2float(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_str2float(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char *p = skipwhite(tv_get_string(&argvars[0]));
bool isneg = (*p == '-');
@@ -8287,7 +8261,7 @@ static void f_str2float(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "str2list()" function
-static void f_str2list(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_str2list(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_list_alloc_ret(rettv, kListLenUnknown);
const char_u *p = (const char_u *)tv_get_string(&argvars[0]);
@@ -8298,7 +8272,7 @@ static void f_str2list(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "str2nr()" function
-static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_str2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int base = 10;
int what = 0;
@@ -8341,7 +8315,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "strftime({format}[, {time}])" function
-static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_strftime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
time_t seconds;
@@ -8361,13 +8335,12 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = xstrdup(_("(Invalid)"));
} else {
vimconv_T conv;
- char_u *enc;
conv.vc_type = CONV_NONE;
- enc = enc_locale();
+ char *enc = (char *)enc_locale();
convert_setup(&conv, p_enc, enc);
if (conv.vc_type != CONV_NONE) {
- p = (char *)string_convert(&conv, (char_u *)p, NULL);
+ p = string_convert(&conv, p, NULL);
}
char result_buf[256];
if (p != NULL) {
@@ -8381,7 +8354,7 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
convert_setup(&conv, enc, p_enc);
if (conv.vc_type != CONV_NONE) {
- rettv->vval.v_string = (char *)string_convert(&conv, (char_u *)result_buf, NULL);
+ rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
} else {
rettv->vval.v_string = xstrdup(result_buf);
}
@@ -8393,7 +8366,7 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "strgetchar()" function
-static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_strgetchar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = -1;
@@ -8421,7 +8394,7 @@ static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "stridx()" function
-static void f_stridx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_stridx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = -1;
@@ -8453,20 +8426,20 @@ static void f_stridx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "string()" function
-static void f_string(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_string(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = encode_tv2string(&argvars[0], NULL);
}
/// "strlen()" function
-static void f_strlen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_strlen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = (varnumber_T)strlen(tv_get_string(&argvars[0]));
}
/// "strchars()" function
-static void f_strchars(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_strchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *s = tv_get_string(&argvars[0]);
int skipcc = 0;
@@ -8489,7 +8462,7 @@ static void f_strchars(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "strdisplaywidth()" function
-static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const s = tv_get_string(&argvars[0]);
int col = 0;
@@ -8498,11 +8471,11 @@ static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
col = (int)tv_get_number(&argvars[1]);
}
- rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, (char_u *)s) - col);
+ rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, (char *)s) - col);
}
/// "strwidth()" function
-static void f_strwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_strwidth(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const s = tv_get_string(&argvars[0]);
@@ -8510,7 +8483,7 @@ static void f_strwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "strcharpart()" function
-static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_strcharpart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const p = tv_get_string(&argvars[0]);
const size_t slen = STRLEN(p);
@@ -8564,7 +8537,7 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "strpart()" function
-static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_strpart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
bool error = false;
@@ -8610,7 +8583,7 @@ static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "strptime({format}, {timestring})" function
-static void f_strptime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_strptime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char fmt_buf[NUMBUFLEN];
char str_buf[NUMBUFLEN];
@@ -8624,10 +8597,10 @@ static void f_strptime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
vimconv_T conv = {
.vc_type = CONV_NONE,
};
- char_u *enc = enc_locale();
+ char *enc = (char *)enc_locale();
convert_setup(&conv, p_enc, enc);
if (conv.vc_type != CONV_NONE) {
- fmt = (char *)string_convert(&conv, (char_u *)fmt, NULL);
+ fmt = string_convert(&conv, fmt, NULL);
}
if (fmt == NULL
|| os_strptime(str, fmt, &tmval) == NULL
@@ -8642,7 +8615,7 @@ static void f_strptime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "strridx()" function
-static void f_strridx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_strridx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char buf[NUMBUFLEN];
const char *const needle = tv_get_string_chk(&argvars[1]);
@@ -8685,14 +8658,14 @@ static void f_strridx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "strtrans()" function
-static void f_strtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_strtrans(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = transstr(tv_get_string(&argvars[0]), true);
}
/// "submatch()" function
-static void f_submatch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_submatch(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
bool error = false;
int no = (int)tv_get_number_chk(&argvars[0], &error);
@@ -8723,7 +8696,7 @@ static void f_submatch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "substitute()" function
-static void f_substitute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_substitute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char patbuf[NUMBUFLEN];
char subbuf[NUMBUFLEN];
@@ -8752,14 +8725,14 @@ static void f_substitute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "swapinfo(swap_filename)" function
-static void f_swapinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_swapinfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_alloc_ret(rettv);
get_b0_dict(tv_get_string(argvars), rettv->vval.v_dict);
}
/// "swapname(expr)" function
-static void f_swapname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_swapname(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
buf_T *buf = tv_get_buf(&argvars[0], false);
@@ -8773,7 +8746,7 @@ static void f_swapname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "synID(lnum, col, trans)" function
-static void f_synID(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_synID(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
// -1 on type error (both)
const linenr_T lnum = tv_get_lnum(argvars);
@@ -8792,7 +8765,7 @@ static void f_synID(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "synIDattr(id, what [, mode])" function
-static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_synIDattr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const int id = (int)tv_get_number(&argvars[0]);
const char *const what = tv_get_string(&argvars[1]);
@@ -8879,7 +8852,7 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "synIDtrans(id)" function
-static void f_synIDtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_synIDtrans(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int id = (int)tv_get_number(&argvars[0]);
@@ -8893,7 +8866,7 @@ static void f_synIDtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "synconcealed(lnum, col)" function
-static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_synconcealed(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int syntax_flags = 0;
int cchar;
@@ -8935,7 +8908,7 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "synstack(lnum, col)" function
-static void f_synstack(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_synstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_list_set_ret(rettv, NULL);
@@ -8959,18 +8932,18 @@ static void f_synstack(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// f_system - the VimL system() function
-static void f_system(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_system(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
get_system_output_as_rettv(argvars, rettv, false);
}
-static void f_systemlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_systemlist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
get_system_output_as_rettv(argvars, rettv, true);
}
/// "tabpagebuflist()" function
-static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
win_T *wp = NULL;
@@ -8992,7 +8965,7 @@ static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "tabpagenr()" function
-static void f_tabpagenr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_tabpagenr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int nr = 1;
@@ -9078,7 +9051,7 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar)
}
/// "tabpagewinnr()" function
-static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int nr = 1;
tabpage_T *const tp = find_tabpage((int)tv_get_number(&argvars[0]));
@@ -9091,14 +9064,14 @@ static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "tagfiles()" function
-static void f_tagfiles(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_tagfiles(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_list_alloc_ret(rettv, kListLenUnknown);
char *fname = xmalloc(MAXPATHL);
bool first = true;
tagname_T tn;
- while (get_tagfname(&tn, first, (char_u *)fname) == OK) {
+ while (get_tagfname(&tn, first, fname) == OK) {
tv_list_append_string(rettv->vval.v_list, fname, -1);
first = false;
}
@@ -9108,7 +9081,7 @@ static void f_tagfiles(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "taglist()" function
-static void f_taglist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_taglist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const tag_pattern = tv_get_string(&argvars[0]);
@@ -9126,14 +9099,14 @@ static void f_taglist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "tempname()" function
-static void f_tempname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_tempname(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = (char *)vim_tempname();
}
/// "termopen(cmd[, cwd])" function
-static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (check_secure()) {
return;
@@ -9176,7 +9149,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (new_cwd && *new_cwd != NUL) {
cwd = new_cwd;
// The new cwd must be a directory.
- if (!os_isdir((const char_u *)cwd)) {
+ if (!os_isdir(cwd)) {
semsg(_(e_invarg2), "expected valid directory");
shell_free_argv(argv);
return;
@@ -9256,7 +9229,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "timer_info([timer])" function
-static void f_timer_info(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_timer_info(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type != VAR_UNKNOWN) {
if (argvars[0].v_type != VAR_NUMBER) {
@@ -9274,7 +9247,7 @@ static void f_timer_info(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "timer_pause(timer, paused)" function
-static void f_timer_pause(typval_T *argvars, typval_T *unused, FunPtr fptr)
+static void f_timer_pause(typval_T *argvars, typval_T *unused, EvalFuncData fptr)
{
if (argvars[0].v_type != VAR_NUMBER) {
emsg(_(e_number_exp));
@@ -9294,7 +9267,7 @@ static void f_timer_pause(typval_T *argvars, typval_T *unused, FunPtr fptr)
}
/// "timer_start(timeout, callback, opts)" function
-static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_timer_start(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int repeat = 1;
@@ -9326,7 +9299,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "timer_stop(timerid)" function
-static void f_timer_stop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_timer_stop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type != VAR_NUMBER) {
emsg(_(e_number_exp));
@@ -9341,27 +9314,27 @@ static void f_timer_stop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
timer_stop(timer);
}
-static void f_timer_stopall(typval_T *argvars, typval_T *unused, FunPtr fptr)
+static void f_timer_stopall(typval_T *argvars, typval_T *unused, EvalFuncData fptr)
{
timer_stop_all();
}
/// "tolower(string)" function
-static void f_tolower(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_tolower(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = strcase_save(tv_get_string(&argvars[0]), false);
}
/// "toupper(string)" function
-static void f_toupper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_toupper(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = strcase_save(tv_get_string(&argvars[0]), true);
}
/// "tr(string, fromstr, tostr)" function
-static void f_tr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_tr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char buf[NUMBUFLEN];
char buf2[NUMBUFLEN];
@@ -9440,7 +9413,7 @@ error:
}
/// "trim({expr})" function
-static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_trim(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char buf1[NUMBUFLEN];
char buf2[NUMBUFLEN];
@@ -9456,6 +9429,11 @@ static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
+ if (argvars[1].v_type != VAR_UNKNOWN && argvars[1].v_type != VAR_STRING) {
+ semsg(_(e_invarg2), tv_get_string(&argvars[1]));
+ return;
+ }
+
if (argvars[1].v_type == VAR_STRING) {
mask = (const char_u *)tv_get_string_buf_chk(&argvars[1], buf2);
if (argvars[2].v_type != VAR_UNKNOWN) {
@@ -9522,7 +9500,7 @@ static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "type(expr)" function
-static void f_type(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_type(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int n = -1;
@@ -9554,7 +9532,7 @@ static void f_type(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "undofile(name)" function
-static void f_undofile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_undofile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
const char *const fname = tv_get_string(&argvars[0]);
@@ -9573,7 +9551,7 @@ static void f_undofile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "undotree()" function
-static void f_undotree(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_undotree(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_alloc_ret(rettv);
@@ -9591,7 +9569,7 @@ static void f_undotree(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "virtcol(string)" function
-static void f_virtcol(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
colnr_T vcol = 0;
int fnum = curbuf->b_fnum;
@@ -9616,7 +9594,7 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "visualmode()" function
-static void f_visualmode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_visualmode(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char_u str[2];
@@ -9632,7 +9610,7 @@ static void f_visualmode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "wildmenumode()" function
-static void f_wildmenumode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_wildmenumode(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (wild_menu_showing || ((State & MODE_CMDLINE) && cmdline_pum_active())) {
rettv->vval.v_number = 1;
@@ -9640,20 +9618,20 @@ static void f_wildmenumode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "win_findbuf()" function
-static void f_win_findbuf(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_win_findbuf(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_list_alloc_ret(rettv, kListLenMayKnow);
win_findbuf(argvars, rettv->vval.v_list);
}
/// "win_getid()" function
-static void f_win_getid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_win_getid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = win_getid(argvars);
}
/// "win_gettype(nr)" function
-static void f_win_gettype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_win_gettype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
win_T *wp = curwin;
@@ -9680,25 +9658,37 @@ static void f_win_gettype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "win_gotoid()" function
-static void f_win_gotoid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_win_gotoid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- rettv->vval.v_number = win_gotoid(argvars);
+ int id = (int)tv_get_number(&argvars[0]);
+
+ if (cmdwin_type != 0) {
+ emsg(_(e_cmdwin));
+ return;
+ }
+ FOR_ALL_TAB_WINDOWS(tp, wp) {
+ if (wp->handle == id) {
+ goto_tabpage_win(tp, wp);
+ rettv->vval.v_number = 1;
+ return;
+ }
+ }
}
/// "win_id2tabwin()" function
-static void f_win_id2tabwin(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_win_id2tabwin(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
win_id2tabwin(argvars, rettv);
}
/// "win_id2win()" function
-static void f_win_id2win(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_win_id2win(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = win_id2win(argvars);
}
/// "win_move_separator()" function
-static void f_win_move_separator(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_win_move_separator(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = false;
@@ -9713,7 +9703,7 @@ static void f_win_move_separator(typval_T *argvars, typval_T *rettv, FunPtr fptr
}
/// "win_move_statusline()" function
-static void f_win_move_statusline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_win_move_statusline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
win_T *wp;
int offset;
@@ -9731,7 +9721,7 @@ static void f_win_move_statusline(typval_T *argvars, typval_T *rettv, FunPtr fpt
}
/// "winbufnr(nr)" function
-static void f_winbufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_winbufnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
win_T *wp = find_win_by_nr_or_id(&argvars[0]);
if (wp == NULL) {
@@ -9742,25 +9732,25 @@ static void f_winbufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "wincol()" function
-static void f_wincol(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_wincol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
validate_cursor();
rettv->vval.v_number = curwin->w_wcol + 1;
}
/// "winheight(nr)" function
-static void f_winheight(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_winheight(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
win_T *wp = find_win_by_nr_or_id(&argvars[0]);
if (wp == NULL) {
rettv->vval.v_number = -1;
} else {
- rettv->vval.v_number = wp->w_height;
+ rettv->vval.v_number = wp->w_height_inner;
}
}
/// "winlayout()" function
-static void f_winlayout(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_winlayout(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tabpage_T *tp;
@@ -9779,20 +9769,20 @@ static void f_winlayout(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "winline()" function
-static void f_winline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_winline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
validate_cursor();
rettv->vval.v_number = curwin->w_wrow + 1;
}
/// "winnr()" function
-static void f_winnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_winnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = get_winnr(curtab, &argvars[0]);
}
/// "winrestcmd()" function
-static void f_winrestcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_winrestcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char_u buf[50];
@@ -9819,7 +9809,7 @@ static void f_winrestcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "winrestview()" function
-static void f_winrestview(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_winrestview(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
dict_T *dict = argvars[0].vval.v_dict;
@@ -9869,7 +9859,7 @@ static void f_winrestview(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "winsaveview()" function
-static void f_winsaveview(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_winsaveview(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_alloc_ret(rettv);
dict_T *dict = rettv->vval.v_dict;
@@ -9887,32 +9877,32 @@ static void f_winsaveview(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "winwidth(nr)" function
-static void f_winwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_winwidth(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
win_T *wp = find_win_by_nr_or_id(&argvars[0]);
if (wp == NULL) {
rettv->vval.v_number = -1;
} else {
- rettv->vval.v_number = wp->w_width;
+ rettv->vval.v_number = wp->w_width_inner;
}
}
/// "windowsversion()" function
-static void f_windowsversion(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_windowsversion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = xstrdup(windowsVersion);
}
/// "wordcount()" function
-static void f_wordcount(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_wordcount(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_alloc_ret(rettv);
cursor_pos_info(rettv->vval.v_dict);
}
/// "writefile()" function
-static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = -1;
@@ -9990,7 +9980,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "xor(expr, expr)" function
-static void f_xor(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void f_xor(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL)
^ tv_get_number_chk(&argvars[1], NULL);
diff --git a/src/nvim/eval/funcs.h b/src/nvim/eval/funcs.h
index 583ee0e75e..adff0b2441 100644
--- a/src/nvim/eval/funcs.h
+++ b/src/nvim/eval/funcs.h
@@ -1,11 +1,12 @@
#ifndef NVIM_EVAL_FUNCS_H
#define NVIM_EVAL_FUNCS_H
+#include "nvim/api/private/dispatch.h"
#include "nvim/buffer_defs.h"
#include "nvim/eval/typval.h"
/// Prototype of C function that implements VimL function
-typedef void (*VimLFunc)(typval_T *args, typval_T *rvar, FunPtr data);
+typedef void (*VimLFunc)(typval_T *args, typval_T *rvar, EvalFuncData data);
/// Special flags for base_arg @see EvalFuncDef
#define BASE_NONE 0 ///< Not a method (no base argument).
@@ -13,13 +14,13 @@ typedef void (*VimLFunc)(typval_T *args, typval_T *rvar, FunPtr data);
/// Structure holding VimL function definition
typedef struct {
- char *name; ///< Name of the function.
- uint8_t min_argc; ///< Minimal number of arguments.
- uint8_t max_argc; ///< Maximal number of arguments.
- uint8_t base_arg; ///< Method base arg # (1-indexed), BASE_NONE or BASE_LAST.
- bool fast; ///< Can be run in |api-fast| events
- VimLFunc func; ///< Function implementation.
- FunPtr data; ///< Userdata for function implementation.
+ char *name; ///< Name of the function.
+ uint8_t min_argc; ///< Minimal number of arguments.
+ uint8_t max_argc; ///< Maximal number of arguments.
+ uint8_t base_arg; ///< Method base arg # (1-indexed), BASE_NONE or BASE_LAST.
+ bool fast; ///< Can be run in |api-fast| events
+ VimLFunc func; ///< Function implementation.
+ EvalFuncData data; ///< Userdata for function implementation.
} EvalFuncDef;
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index 8822bb0491..d5b2b1f2ae 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -831,7 +831,7 @@ int tv_list_join(garray_T *const gap, list_T *const l, const char *const sep)
}
/// "join()" function
-void f_join(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_join(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type != VAR_LIST) {
emsg(_(e_listreq));
@@ -855,7 +855,7 @@ void f_join(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "list2str()" function
-void f_list2str(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_list2str(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
garray_T ga;
@@ -1247,15 +1247,15 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
; li != NULL;) {
listitem_T *const prev_li = TV_LIST_ITEM_PREV(l, li);
if (item_compare_func_ptr(&prev_li, &li) == 0) {
- if (info.item_compare_func_err) { // -V547
- emsg(_("E882: Uniq compare function failed"));
- break;
- }
li = tv_list_item_remove(l, li);
} else {
idx++;
li = TV_LIST_ITEM_NEXT(l, li);
}
+ if (info.item_compare_func_err) { // -V547
+ emsg(_("E882: Uniq compare function failed"));
+ break;
+ }
}
}
@@ -1267,13 +1267,13 @@ theend:
}
/// "sort"({list})" function
-void f_sort(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_sort(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
do_sort_uniq(argvars, rettv, true);
}
/// "uniq({list})" function
-void f_uniq(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_uniq(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
do_sort_uniq(argvars, rettv, false);
}
@@ -2533,7 +2533,7 @@ dict_T *tv_dict_copy(const vimconv_T *const conv, dict_T *const orig, const bool
new_di = tv_dict_item_alloc((const char *)di->di_key);
} else {
size_t len = STRLEN(di->di_key);
- char *const key = (char *)string_convert(conv, di->di_key, &len);
+ char *const key = (char *)string_convert(conv, (char *)di->di_key, &len);
if (key == NULL) {
new_di = tv_dict_item_alloc_len((const char *)di->di_key, len);
} else {
@@ -2806,25 +2806,25 @@ static void tv_dict_list(typval_T *const tv, typval_T *const rettv, const DictLi
}
/// "items(dict)" function
-void f_items(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_items(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_list(argvars, rettv, 2);
}
/// "keys()" function
-void f_keys(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_keys(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_list(argvars, rettv, 0);
}
/// "values(dict)" function
-void f_values(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_values(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_list(argvars, rettv, 1);
}
/// "has_key()" function
-void f_has_key(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_has_key(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type != VAR_DICT) {
emsg(_(e_dictreq));
diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h
index c4bc9f603b..8177d01f90 100644
--- a/src/nvim/eval/typval.h
+++ b/src/nvim/eval/typval.h
@@ -25,9 +25,6 @@
typedef int64_t varnumber_T;
typedef uint64_t uvarnumber_T;
-/// Type used for VimL VAR_FLOAT values
-typedef double float_T;
-
/// Refcount for dict or list that should not be freed
enum { DO_NOT_FREE_CNT = (INT_MAX / 2), };
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index c46cb6ba5d..4be922a055 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -409,7 +409,7 @@ void emsg_funcname(char *ermsg, const char_u *name)
char_u *p;
if (*name == K_SPECIAL) {
- p = concat_str((char_u *)"<SNR>", name + 3);
+ p = (char_u *)concat_str("<SNR>", (char *)name + 3);
} else {
p = (char_u *)name;
}
@@ -852,7 +852,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
saveRedobuff(&save_redo);
did_save_redo = true;
}
- ++fp->uf_calls;
+ fp->uf_calls++;
// check for CTRL-C hit
line_breakcheck();
// prepare the funccall_T structure
@@ -863,7 +863,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
fc->rettv = rettv;
fc->level = ex_nesting_level;
// Check if this function has a breakpoint.
- fc->breakpoint = dbg_find_breakpoint(false, fp->uf_name, (linenr_T)0);
+ fc->breakpoint = dbg_find_breakpoint(false, (char *)fp->uf_name, (linenr_T)0);
fc->dbg_tick = debug_tick;
// Set up fields for closure.
@@ -893,7 +893,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
v->di_tv.v_type = VAR_DICT;
v->di_tv.v_lock = VAR_UNLOCKED;
v->di_tv.vval.v_dict = selfdict;
- ++selfdict->dv_refcount;
+ selfdict->dv_refcount++;
}
// Init a: variables, unless none found (in lambda).
@@ -1058,7 +1058,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
bool func_not_yet_profiling_but_should =
do_profiling_yes
- && !fp->uf_profiling && has_profiling(false, fp->uf_name, NULL);
+ && !fp->uf_profiling && has_profiling(false, (char *)fp->uf_name, NULL);
if (func_not_yet_profiling_but_should) {
started_profiling = true;
@@ -1071,7 +1071,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
|| (fc->caller != NULL && fc->caller->func->uf_profiling));
if (func_or_func_caller_profiling) {
- ++fp->uf_tm_count;
+ fp->uf_tm_count++;
call_start = profile_start();
fp->uf_tm_children = profile_zero();
}
@@ -1083,7 +1083,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
const sctx_T save_current_sctx = current_sctx;
current_sctx = fp->uf_script_ctx;
save_did_emsg = did_emsg;
- did_emsg = FALSE;
+ did_emsg = false;
if (default_arg_err && (fp->uf_flags & FC_ABORT)) {
did_emsg = true;
@@ -1885,6 +1885,8 @@ theend:
return name;
}
+#define MAX_FUNC_NESTING 50
+
/// ":function"
void ex_function(exarg_T *eap)
{
@@ -1927,11 +1929,11 @@ void ex_function(exarg_T *eap)
if (ends_excmd(*eap->arg)) {
if (!eap->skip) {
todo = (int)func_hashtab.ht_used;
- for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi) {
+ for (hi = func_hashtab.ht_array; todo > 0 && !got_int; hi++) {
if (!HASHITEM_EMPTY(hi)) {
todo--;
fp = HI2UF(hi);
- if (message_filtered(fp->uf_name)) {
+ if (message_filtered((char *)fp->uf_name)) {
continue;
}
if (!func_name_refcount(fp->uf_name)) {
@@ -1948,7 +1950,7 @@ void ex_function(exarg_T *eap)
* ":function /pat": list functions matching pattern.
*/
if (*eap->arg == '/') {
- p = skip_regexp((char_u *)eap->arg + 1, '/', true, NULL);
+ p = (char_u *)skip_regexp(eap->arg + 1, '/', true, NULL);
if (!eap->skip) {
regmatch_T regmatch;
@@ -1960,7 +1962,7 @@ void ex_function(exarg_T *eap)
regmatch.rm_ic = p_ic;
todo = (int)func_hashtab.ht_used;
- for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi) {
+ for (hi = func_hashtab.ht_array; todo > 0 && !got_int; hi++) {
if (!HASHITEM_EMPTY(hi)) {
todo--;
fp = HI2UF(hi);
@@ -2010,14 +2012,14 @@ void ex_function(exarg_T *eap)
xfree(fudi.fd_newkey);
return;
} else {
- eap->skip = TRUE;
+ eap->skip = true;
}
}
// An error in a function call during evaluation of an expression in magic
// braces should not cause the function not to be defined.
saved_did_emsg = did_emsg;
- did_emsg = FALSE;
+ did_emsg = false;
//
// ":function func" with only function name: list function.
@@ -2304,8 +2306,12 @@ void ex_function(exarg_T *eap)
p += eval_fname_script((const char *)p);
xfree(trans_function_name((char **)&p, true, 0, NULL, NULL));
if (*skipwhite((char *)p) == '(') {
- nesting++;
- indent += 2;
+ if (nesting == MAX_FUNC_NESTING - 1) {
+ emsg(_("E1058: function nesting too deep"));
+ } else {
+ nesting++;
+ indent += 2;
+ }
}
}
@@ -2326,7 +2332,7 @@ void ex_function(exarg_T *eap)
}
// heredoc: Check for ":python <<EOF", ":lua <<EOF", etc.
- arg = (char_u *)skipwhite((char *)skiptowhite(p));
+ arg = (char_u *)skipwhite(skiptowhite((char *)p));
if (arg[0] == '<' && arg[1] == '<'
&& ((p[0] == 'p' && p[1] == 'y'
&& (!ASCII_ISALNUM(p[2]) || p[2] == 't'
@@ -2353,12 +2359,12 @@ void ex_function(exarg_T *eap)
// Check for ":let v =<< [trim] EOF"
// and ":let [a, b] =<< [trim] EOF"
- arg = (char_u *)skipwhite((char *)skiptowhite(p));
+ arg = (char_u *)skipwhite(skiptowhite((char *)p));
if (*arg == '[') {
arg = (char_u *)vim_strchr((char *)arg, ']');
}
if (arg != NULL) {
- arg = (char_u *)skipwhite((char *)skiptowhite(arg));
+ arg = (char_u *)skipwhite(skiptowhite((char *)arg));
if (arg[0] == '='
&& arg[1] == '<'
&& arg[2] == '<'
@@ -2373,7 +2379,7 @@ void ex_function(exarg_T *eap)
heredoc_trimmed =
vim_strnsave(theline, (size_t)((char_u *)skipwhite((char *)theline) - theline));
}
- skip_until = vim_strnsave(p, (size_t)(skiptowhite(p) - p));
+ skip_until = vim_strnsave(p, (size_t)((char_u *)skiptowhite((char *)p) - p));
do_concat = false;
is_heredoc = true;
}
@@ -2847,7 +2853,7 @@ void ex_return(exarg_T *eap)
{
char_u *arg = (char_u *)eap->arg;
typval_T rettv;
- int returning = FALSE;
+ int returning = false;
if (current_funccal == NULL) {
emsg(_("E133: :return not inside a function"));
@@ -3004,7 +3010,7 @@ void ex_call(exarg_T *eap)
// When inside :try we need to check for following "| catch" or "| endtry".
// Not when there was an error, but do check if an exception was thrown.
- if ((!aborting() || current_exception != NULL) && (!failed || eap->cstack->cs_trylevel > 0)) {
+ if ((!aborting() || did_throw) && (!failed || eap->cstack->cs_trylevel > 0)) {
// Check for trailing illegal characters and a following command.
if (!ends_excmd(*arg)) {
if (!failed && !aborting()) {
@@ -3029,8 +3035,8 @@ end:
/// @param is_cmd set when called due to a ":return" command.
/// @param rettv may point to a typval_T with the return rettv.
///
-/// @return TRUE when the return can be carried out,
-/// FALSE when the return gets pending.
+/// @return true when the return can be carried out,
+/// false when the return gets pending.
int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv)
{
int idx;
@@ -3080,7 +3086,7 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv)
}
report_make_pending(CSTP_RETURN, rettv);
} else {
- current_funccal->returned = TRUE;
+ current_funccal->returned = true;
// If the return is carried out now, store the return value. For
// a return immediately after reanimation, the value is already
@@ -3099,16 +3105,16 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv)
/// Generate a return command for producing the value of "rettv". The result
/// is an allocated string. Used by report_pending() for verbose messages.
-char_u *get_return_cmd(void *rettv)
+char *get_return_cmd(void *rettv)
{
- char_u *s = NULL;
- char_u *tofree = NULL;
+ char *s = NULL;
+ char *tofree = NULL;
if (rettv != NULL) {
- tofree = s = (char_u *)encode_tv2echo((typval_T *)rettv, NULL);
+ tofree = s = encode_tv2echo((typval_T *)rettv, NULL);
}
if (s == NULL) {
- s = (char_u *)"";
+ s = "";
}
STRCPY(IObuff, ":return ");
@@ -3117,7 +3123,7 @@ char_u *get_return_cmd(void *rettv)
STRCPY(IObuff + IOSIZE - 4, "...");
}
xfree(tofree);
- return vim_strsave(IObuff);
+ return (char *)vim_strsave(IObuff);
}
/// Get next function line.
@@ -3128,12 +3134,12 @@ char *get_func_line(int c, void *cookie, int indent, bool do_concat)
{
funccall_T *fcp = (funccall_T *)cookie;
ufunc_T *fp = fcp->func;
- char_u *retval;
+ char *retval;
garray_T *gap; // growarray with function lines
// If breakpoints have been added/deleted need to check for it.
if (fcp->dbg_tick != debug_tick) {
- fcp->breakpoint = dbg_find_breakpoint(false, fp->uf_name, SOURCING_LNUM);
+ fcp->breakpoint = dbg_find_breakpoint(false, (char *)fp->uf_name, SOURCING_LNUM);
fcp->dbg_tick = debug_tick;
}
if (do_profiling == PROF_YES) {
@@ -3153,7 +3159,7 @@ char *get_func_line(int c, void *cookie, int indent, bool do_concat)
if (fcp->linenr >= gap->ga_len) {
retval = NULL;
} else {
- retval = (char_u *)xstrdup(((char **)(gap->ga_data))[fcp->linenr++]);
+ retval = xstrdup(((char **)(gap->ga_data))[fcp->linenr++]);
SOURCING_LNUM = fcp->linenr;
if (do_profiling == PROF_YES) {
func_line_start(cookie);
@@ -3163,16 +3169,16 @@ char *get_func_line(int c, void *cookie, int indent, bool do_concat)
// Did we encounter a breakpoint?
if (fcp->breakpoint != 0 && fcp->breakpoint <= SOURCING_LNUM) {
- dbg_breakpoint(fp->uf_name, SOURCING_LNUM);
+ dbg_breakpoint((char *)fp->uf_name, SOURCING_LNUM);
// Find next breakpoint.
- fcp->breakpoint = dbg_find_breakpoint(false, fp->uf_name, SOURCING_LNUM);
+ fcp->breakpoint = dbg_find_breakpoint(false, (char *)fp->uf_name, SOURCING_LNUM);
fcp->dbg_tick = debug_tick;
}
- return (char *)retval;
+ return retval;
}
-/// @return TRUE if the currently active function should be ended, because a
+/// @return true if the currently active function should be ended, because a
/// return was encountered or an error occurred. Used inside a ":while".
int func_has_ended(void *cookie)
{
@@ -3184,7 +3190,7 @@ int func_has_ended(void *cookie)
|| fcp->returned;
}
-/// @return TRUE if cookie indicates a function which "abort"s on errors.
+/// @return true if cookie indicates a function which "abort"s on errors.
int func_has_abort(void *cookie)
{
return ((funccall_T *)cookie)->func->uf_flags & FC_ABORT;
@@ -3275,7 +3281,7 @@ int func_level(void *cookie)
return ((funccall_T *)cookie)->level;
}
-/// @return TRUE when a function was ended by a ":return" command.
+/// @return true when a function was ended by a ":return" command.
int current_func_returned(void)
{
return current_funccal->returned;
diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c
index 73e84a8c1e..2c4f06c037 100644
--- a/src/nvim/eval/vars.c
+++ b/src/nvim/eval/vars.c
@@ -81,7 +81,7 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd)
// The marker is the next word.
if (*cmd != NUL && *cmd != '"') {
marker = skipwhite(cmd);
- p = (char *)skiptowhite((char_u *)marker);
+ p = skiptowhite(marker);
if (*skipwhite(p) != NUL && *skipwhite(p) != '"') {
semsg(_(e_trailing_arg), p);
return NULL;
@@ -413,7 +413,7 @@ void list_hashtable_vars(hashtab_T *ht, const char *prefix, int empty, int *firs
// apply :filter /pat/ to variable name
xstrlcpy(buf, prefix, IOSIZE);
xstrlcat(buf, (char *)di->di_key, IOSIZE);
- if (message_filtered((char_u *)buf)) {
+ if (message_filtered(buf)) {
continue;
}
@@ -587,7 +587,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
char *s = vim_getenv(name);
if (s != NULL) {
- tofree = (char *)concat_str((const char_u *)s, (const char_u *)p);
+ tofree = concat_str(s, p);
p = (const char *)tofree;
xfree(s);
}
@@ -663,8 +663,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
} else if (opt_type == gov_string && stringval != NULL && s != NULL) {
// string
char *const oldstringval = stringval;
- stringval = (char *)concat_str((const char_u *)stringval,
- (const char_u *)s);
+ stringval = concat_str(stringval, s);
xfree(oldstringval);
s = stringval;
}
@@ -709,7 +708,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
if (p != NULL && op != NULL && *op == '.') {
s = get_reg_contents(*arg == '@' ? '"' : regname, kGRegExprSrc);
if (s != NULL) {
- ptofree = (char *)concat_str((char_u *)s, (const char_u *)p);
+ ptofree = concat_str(s, p);
p = (const char *)ptofree;
xfree(s);
}
@@ -795,6 +794,7 @@ static void ex_unletlock(exarg_T *eap, char *argstart, int deep, ex_unletlock_ca
semsg(_(e_invarg2), arg - 1);
return;
}
+ assert(*lv.ll_name == '$'); // suppress clang "Uninitialized argument value"
if (!error && !eap->skip && callback(&lv, arg, eap, deep) == FAIL) {
error = true;
}
@@ -1122,7 +1122,7 @@ void vars_clear(hashtab_T *ht)
vars_clear_ext(ht, true);
}
-/// Like vars_clear(), but only free the value if "free_val" is TRUE.
+/// Like vars_clear(), but only free the value if "free_val" is true.
void vars_clear_ext(hashtab_T *ht, int free_val)
{
int todo;
@@ -1304,7 +1304,7 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv,
set_search_direction(v->di_tv.vval.v_number ? '/' : '?');
} else if (strcmp(varname, "hlsearch") == 0) {
no_hlsearch = !v->di_tv.vval.v_number;
- redraw_all_later(SOME_VALID);
+ redraw_all_later(UPD_SOME_VALID);
}
return;
} else if (v->di_tv.v_type != tv->v_type) {
@@ -1631,7 +1631,7 @@ static void set_option_from_tv(const char *varname, typval_T *varp)
strval = tv_get_string_buf_chk(varp, nbuf);
}
if (!error && strval != NULL) {
- set_option_value(varname, numval, strval, OPT_LOCAL);
+ set_option_value_give_err(varname, numval, strval, OPT_LOCAL);
}
}
@@ -1706,7 +1706,7 @@ bool var_exists(const char *var)
}
/// "gettabvar()" function
-void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_gettabvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const varname = tv_get_string_chk(&argvars[1]);
tabpage_T *const tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
@@ -1720,19 +1720,19 @@ void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "gettabwinvar()" function
-void f_gettabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_gettabwinvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
getwinvar(argvars, rettv, 1);
}
/// "getwinvar()" function
-void f_getwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_getwinvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
getwinvar(argvars, rettv, 0);
}
/// "getbufvar()" function
-void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_getbufvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const varname = tv_get_string_chk(&argvars[1]);
buf_T *const buf = tv_get_buf_from_arg(&argvars[0]);
@@ -1741,7 +1741,7 @@ void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "settabvar()" function
-void f_settabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_settabvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = 0;
@@ -1772,19 +1772,19 @@ void f_settabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "settabwinvar()" function
-void f_settabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_settabwinvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
setwinvar(argvars, rettv, 1);
}
/// "setwinvar()" function
-void f_setwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_setwinvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
setwinvar(argvars, rettv, 0);
}
/// "setbufvar()" function
-void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_setbufvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (check_secure()
|| !tv_check_str_or_nr(&argvars[0])) {
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 06a372bb93..e672b80d69 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -120,7 +120,7 @@ void do_ascii(const exarg_T *const eap)
{
char *dig;
int cc[MAX_MCO];
- int c = utfc_ptr2char(get_cursor_pos_ptr(), cc);
+ int c = utfc_ptr2char((char *)get_cursor_pos_ptr(), cc);
if (c == NUL) {
msg("NUL");
return;
@@ -274,7 +274,7 @@ void ex_align(exarg_T *eap)
if (eap->cmdidx == CMD_left) { // left align
new_indent = indent;
} else {
- has_tab = FALSE; // avoid uninit warnings
+ has_tab = false; // avoid uninit warnings
len = linelen(eap->cmdidx == CMD_right ? &has_tab
: NULL) - get_indent();
@@ -404,7 +404,7 @@ static int sort_compare(const void *s1, const void *s2)
}
fast_breakcheck();
if (got_int) {
- sort_abort = TRUE;
+ sort_abort = true;
}
// When sorting numbers "start_col_nr" is the number, not the column
@@ -513,7 +513,7 @@ void ex_sort(exarg_T *eap)
eap->nextcmd = (char *)check_nextcmd((char_u *)p);
break;
} else if (!ASCII_ISALPHA(*p) && regmatch.regprog == NULL) {
- s = (char *)skip_regexp((char_u *)p + 1, *p, true, NULL);
+ s = skip_regexp(p + 1, *p, true, NULL);
if (*s != *p) {
emsg(_(e_invalpat));
goto sortend;
@@ -586,11 +586,11 @@ void ex_sort(exarg_T *eap)
p = s + start_col;
if (sort_nr) {
if (sort_what & STR2NR_HEX) {
- s = (char *)skiptohex((char_u *)p);
+ s = skiptohex(p);
} else if (sort_what & STR2NR_BIN) {
s = (char *)skiptobin(p);
} else {
- s = (char *)skiptodigit((char_u *)p);
+ s = skiptodigit(p);
}
if (s > p && s[-1] == '-') {
s--; // include preceding negative sign
@@ -678,7 +678,7 @@ void ex_sort(exarg_T *eap)
// delete the original lines if appending worked
if (i == count) {
- for (i = 0; i < count; ++i) {
+ for (i = 0; i < count; i++) {
ml_delete(eap->line1, false);
}
} else {
@@ -743,7 +743,7 @@ void ex_retab(exarg_T *eap)
curwin->w_p_list = 0; // don't want list mode here
new_ts_str = eap->arg;
- if (!tabstop_set((char_u *)eap->arg, &new_vts_array)) {
+ if (!tabstop_set(eap->arg, &new_vts_array)) {
return;
}
while (ascii_isdigit(*(eap->arg)) || *(eap->arg) == ',') {
@@ -841,7 +841,7 @@ void ex_retab(exarg_T *eap)
if (ptr[col] == NUL) {
break;
}
- vcol += win_chartabsize(curwin, (char_u *)ptr + col, (colnr_T)vcol);
+ vcol += win_chartabsize(curwin, ptr + col, (colnr_T)vcol);
if (vcol >= MAXCOL) {
emsg(_(e_resulting_text_too_long));
break;
@@ -867,7 +867,7 @@ void ex_retab(exarg_T *eap)
&& tabstop_eq(curbuf->b_p_vts_array, new_vts_array)) {
// not changed
} else {
- redraw_curbuf_later(NOT_VALID);
+ redraw_curbuf_later(UPD_NOT_VALID);
}
if (first_line != 0) {
changed_lines(first_line, 0, last_line + 1, 0L, true);
@@ -1103,7 +1103,7 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
if (curwin->w_cursor.lnum < line2) {
line2++;
}
- ++curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum++;
}
appended_lines_mark(n, count);
@@ -1150,7 +1150,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
}
if (addr_count == 0) { // :!
- msg_scroll = FALSE; // don't scroll here
+ msg_scroll = false; // don't scroll here
autowrite_all();
msg_scroll = scroll_save;
}
@@ -1347,7 +1347,8 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
msg_putchar('\n'); // Keep message from buf_write().
no_wait_return--;
if (!aborting()) {
- semsg(_("E482: Can't create file %s"), itmp); // Will call wait_return.
+ // will call wait_return()
+ semsg(_("E482: Can't create file %s"), itmp);
}
goto filterend;
}
@@ -1368,7 +1369,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
xfree(cmd_buf);
goto error;
}
- redraw_curbuf_later(VALID);
+ redraw_curbuf_later(UPD_VALID);
}
read_linecount = curbuf->b_ml.ml_line_count;
@@ -1376,14 +1377,14 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
call_shell((char_u *)cmd_buf, (ShellOpts)(kShellOptFilter | shell_flags), NULL);
xfree(cmd_buf);
- did_check_timestamps = FALSE;
- need_check_timestamps = TRUE;
+ did_check_timestamps = false;
+ need_check_timestamps = true;
// When interrupting the shell command, it may still have produced some
// useful output. Reset got_int here, so that readfile() won't cancel
// reading.
os_breakcheck();
- got_int = FALSE;
+ got_int = false;
if (do_out) {
if (otmp != NULL) {
@@ -1656,7 +1657,7 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
}
#endif
if (otmp != NULL) {
- append_redir(buf, len, (char *)p_srr, otmp);
+ append_redir(buf, len, p_srr, otmp);
}
return buf;
}
@@ -1709,12 +1710,12 @@ void print_line(linenr_T lnum, int use_number, int list)
int save_silent = silent_mode;
// apply :filter /pat/
- if (message_filtered(ml_get(lnum))) {
+ if (message_filtered((char *)ml_get(lnum))) {
return;
}
msg_start();
- silent_mode = FALSE;
+ silent_mode = false;
info_message = true; // use mch_msg(), not mch_errmsg()
print_line_no_prefix(lnum, use_number, list);
if (save_silent) {
@@ -1822,7 +1823,7 @@ void ex_write(exarg_T *eap)
}
/// write current buffer to file 'eap->arg'
-/// if 'eap->append' is TRUE, append to the file
+/// if 'eap->append' is true, append to the file
///
/// if *eap->arg == NUL write to current file
///
@@ -1847,7 +1848,7 @@ int do_write(exarg_T *eap)
emsg(_(e_argreq));
goto theend;
}
- other = FALSE;
+ other = false;
} else {
fname = ffname;
free_fname = fix_fname(ffname);
@@ -1880,8 +1881,7 @@ int do_write(exarg_T *eap)
// Writing to the current file is not allowed in readonly mode
// and a file name is required.
// "nofile" and "nowrite" buffers cannot be written implicitly either.
- if (!other && (bt_dontwrite_msg(curbuf)
- || check_fname() == FAIL
+ if (!other && (bt_dontwrite_msg(curbuf) || check_fname() == FAIL
|| check_readonly(&eap->forceit, curbuf))) {
goto theend;
}
@@ -1900,7 +1900,7 @@ int do_write(exarg_T *eap)
(char_u *)_("Write partial file?"), 2) != VIM_YES) {
goto theend;
}
- eap->forceit = TRUE;
+ eap->forceit = true;
} else {
emsg(_("E140: Use ! to write partial buffer"));
goto theend;
@@ -1937,8 +1937,8 @@ int do_write(exarg_T *eap)
apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, curbuf);
apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, alt_buf);
if (!alt_buf->b_p_bl) {
- alt_buf->b_p_bl = TRUE;
- apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, alt_buf);
+ alt_buf->b_p_bl = true;
+ apply_autocmds(EVENT_BUFADD, NULL, NULL, false, alt_buf);
}
if (curbuf != was_curbuf || aborting()) {
// buffer changed, don't write the file
@@ -1966,7 +1966,7 @@ int do_write(exarg_T *eap)
// After ":saveas fname" reset 'readonly'.
if (eap->cmdidx == CMD_saveas) {
if (retval == OK) {
- curbuf->b_p_ro = FALSE;
+ curbuf->b_p_ro = false;
redraw_tabline = true;
}
}
@@ -1996,17 +1996,22 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, int oth
{
// Write to another file or b_flags set or not writing the whole file:
// overwriting only allowed with '!'
+ // If "other" is false and bt_nofilename(buf) is true, this must be
+ // writing an "acwrite" buffer to the same file as its b_ffname, and
+ // buf_write() will only allow writing with BufWriteCmd autocommands,
+ // so there is no need for an overwrite check.
if ((other
- || (buf->b_flags & BF_NOTEDITED)
- || ((buf->b_flags & BF_NEW)
- && vim_strchr(p_cpo, CPO_OVERNEW) == NULL)
- || (buf->b_flags & BF_READERR))
+ || (!bt_nofilename(buf)
+ && ((buf->b_flags & BF_NOTEDITED)
+ || ((buf->b_flags & BF_NEW)
+ && vim_strchr(p_cpo, CPO_OVERNEW) == NULL)
+ || (buf->b_flags & BF_READERR))))
&& !p_wa
&& os_path_exists((char_u *)ffname)) {
if (!eap->forceit && !eap->append) {
#ifdef UNIX
// It is possible to open a directory on Unix.
- if (os_isdir((char_u *)ffname)) {
+ if (os_isdir(ffname)) {
semsg(_(e_isadir2), ffname);
return FAIL;
}
@@ -2018,7 +2023,7 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, int oth
if (vim_dialog_yesno(VIM_QUESTION, NULL, (char_u *)buff, 2) != VIM_YES) {
return FAIL;
}
- eap->forceit = TRUE;
+ eap->forceit = true;
} else {
emsg(_(e_exists));
return FAIL;
@@ -2041,7 +2046,7 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, int oth
STRCPY(dir, ".");
} else {
dir = xmalloc(MAXPATHL);
- p = (char *)p_dir;
+ p = p_dir;
copy_option_part(&p, dir, MAXPATHL, ",");
}
swapname = (char *)makeswapname((char_u *)fname, (char_u *)ffname, curbuf, (char_u *)dir);
@@ -2058,7 +2063,7 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, int oth
xfree(swapname);
return FAIL;
}
- eap->forceit = TRUE;
+ eap->forceit = true;
} else {
semsg(_("E768: Swap file exists: %s (:silent! overrides)"),
swapname);
@@ -2159,7 +2164,7 @@ bool not_writing(void)
}
/// Check if a buffer is read-only (either 'readonly' option is set or file is
-/// read-only). Ask for overruling in a dialog. Return TRUE and give an error
+/// read-only). Ask for overruling in a dialog. Return true and give an error
/// message when the buffer is readonly.
static int check_readonly(int *forceit, buf_T *buf)
{
@@ -2184,10 +2189,10 @@ static int check_readonly(int *forceit, buf_T *buf)
if (vim_dialog_yesno(VIM_QUESTION, NULL, (char_u *)buff, 2) == VIM_YES) {
// Set forceit, to force the writing of a readonly file
- *forceit = TRUE;
- return FALSE;
+ *forceit = true;
+ return false;
} else {
- return TRUE;
+ return true;
}
} else if (buf->b_p_ro) {
emsg(_(e_readonly));
@@ -2195,10 +2200,10 @@ static int check_readonly(int *forceit, buf_T *buf)
semsg(_("E505: \"%s\" is read-only (add ! to override)"),
buf->b_fname);
}
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
/// Try to abandon the current file and edit a new or existing file.
@@ -2292,7 +2297,7 @@ theend:
/// ECMD_LASTL: use last position in loaded file
/// ECMD_LAST: use last position in all files
/// ECMD_ONE: use first line
-/// @param flags ECMD_HIDE: if TRUE don't free the current buffer
+/// @param flags ECMD_HIDE: if true don't free the current buffer
/// ECMD_SET_HELP: set b_help flag of (new) buffer before
/// opening file
/// ECMD_OLDBUF: use existing buffer if it exists
@@ -2310,7 +2315,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
win_T *oldwin)
{
bool other_file; // true if editing another file
- int oldbuf; // TRUE if using existing buffer
+ int oldbuf; // true if using existing buffer
bool auto_buf = false; // true if autocommands brought us
// into the buffer unexpectedly
char *new_name = NULL;
@@ -2386,7 +2391,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// If the file was changed we may not be allowed to abandon it:
// - if we are going to re-edit the same file
- // - or if we are the only window on this file and if ECMD_HIDE is FALSE
+ // - or if we are the only window on this file and if ECMD_HIDE is false
if (((!other_file && !(flags & ECMD_OLDBUF))
|| (curbuf->b_nwindows == 1
&& !(flags & (ECMD_HIDE | ECMD_ADDBUF | ECMD_ALTBUF))))
@@ -2504,7 +2509,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
/*
* Make the (new) buffer the one used by the current window.
- * If the old buffer becomes unused, free it if ECMD_HIDE is FALSE.
+ * If the old buffer becomes unused, free it if ECMD_HIDE is false.
* If the current buffer was empty and has no file name, curbuf
* is returned by buflist_new(), nothing to do here.
*/
@@ -2601,11 +2606,11 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
curwin->w_buffer = buf;
curbuf = buf;
- ++curbuf->b_nwindows;
+ curbuf->b_nwindows++;
// Set 'fileformat', 'binary' and 'fenc' when forced.
if (!oldbuf && eap != NULL) {
- set_file_options(TRUE, eap);
+ set_file_options(true, eap);
set_forced_fenc(eap);
}
}
@@ -2641,7 +2646,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
} else if (!curbuf->b_help) {
// Don't make a buffer listed if it's a help buffer. Useful when using
// CTRL-O to go back to a help file.
- set_buflisted(TRUE);
+ set_buflisted(true);
}
// If autocommands change buffers under our fingers, forget about
@@ -2660,10 +2665,10 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
/*
* other_file oldbuf
- * FALSE FALSE re-edit same file, buffer is re-used
- * FALSE TRUE re-edit same file, nothing changes
- * TRUE FALSE start editing new file, new buffer
- * TRUE TRUE start editing in existing buffer (nothing to do)
+ * false false re-edit same file, buffer is re-used
+ * false true re-edit same file, nothing changes
+ * true false start editing new file, new buffer
+ * true true start editing in existing buffer (nothing to do)
*/
if (!other_file && !oldbuf) { // re-use the buffer
set_last_cursor(curwin); // may set b_last_cursor
@@ -2790,7 +2795,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// changed by the user.
do_modelines(OPT_WINONLY);
- apply_autocmds_retval(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf,
+ apply_autocmds_retval(EVENT_BUFENTER, NULL, NULL, false, curbuf,
&retval);
if ((flags & ECMD_NOWINENTER) == 0) {
apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, false, curbuf,
@@ -2848,7 +2853,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
curwin->w_cursor.col = solcol;
check_cursor_col();
curwin->w_cursor.coladd = 0;
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
} else {
beginline(BL_SOL | BL_FIX);
}
@@ -2874,7 +2879,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// Obey the 'O' flag in 'cpoptions': overwrite any previous file
// message.
if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0) {
- msg_scroll = FALSE;
+ msg_scroll = false;
}
if (!msg_scroll) { // wait a bit when overwriting an error msg
check_for_delay(false);
@@ -2910,7 +2915,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
update_topline(curwin);
curwin->w_scbind_pos = curwin->w_topline;
*so_ptr = n;
- redraw_curbuf_later(NOT_VALID); // redraw this buffer later
+ redraw_curbuf_later(UPD_NOT_VALID); // redraw this buffer later
}
// Change directories when the 'acd' option is set.
@@ -3018,7 +3023,7 @@ void ex_append(exarg_T *eap)
// Look for the "." after automatic indent.
vcol = 0;
- for (p = theline; indent > vcol; ++p) {
+ for (p = theline; indent > vcol; p++) {
if (*p == ' ') {
vcol++;
} else if (*p == TAB) {
@@ -3098,7 +3103,7 @@ void ex_change(exarg_T *eap)
append_indent = get_indent_lnum(eap->line1);
}
- for (lnum = eap->line2; lnum >= eap->line1; --lnum) {
+ for (lnum = eap->line2; lnum >= eap->line1; lnum--) {
if (curbuf->b_ml.ml_flags & ML_EMPTY) { // nothing to delete
break;
}
@@ -3547,7 +3552,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
which_pat = RE_LAST; // use last used regexp
delimiter = (char_u)(*cmd++); // remember delimiter character
pat = cmd; // remember start of search pat
- cmd = (char *)skip_regexp((char_u *)cmd, delimiter, p_magic, &eap->arg);
+ cmd = skip_regexp(cmd, delimiter, p_magic, &eap->arg);
if (cmd[0] == delimiter) { // end delimiter found
*cmd++ = NUL; // replace it with a NUL
has_second_delim = true;
@@ -3804,7 +3809,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
// Save the line number of the last change for the final
// cursor position (just like Vi).
curwin->w_cursor.lnum = lnum;
- do_again = FALSE;
+ do_again = false;
/*
* 1. Match empty string does not count, except for first
@@ -3940,8 +3945,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
// what matches. Temporarily replace the line
// and change it back afterwards.
orig_line = (char *)vim_strsave(ml_get(lnum));
- char *new_line = (char *)concat_str((char_u *)new_start,
- (char_u *)sub_firstline + copycol);
+ char *new_line = concat_str(new_start, sub_firstline + copycol);
// Position the cursor relative to the end of the line, the
// previous substitute may have inserted or deleted characters
@@ -3955,13 +3959,13 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
- regmatch.startpos[0].lnum;
search_match_endcol = regmatch.endpos[0].col
+ len_change;
- highlight_match = TRUE;
+ highlight_match = true;
update_topline(curwin);
validate_cursor();
- update_screen(SOME_VALID);
+ update_screen(UPD_SOME_VALID);
highlight_match = false;
- redraw_later(curwin, SOME_VALID);
+ redraw_later(curwin, UPD_SOME_VALID);
curwin->w_p_fen = save_p_fen;
if (msg_row == Rows - 1) {
@@ -4632,7 +4636,7 @@ void ex_global(exarg_T *eap)
delim = *cmd; // get the delimiter
cmd++; // skip delimiter if there is one
pat = cmd; // remember start of pattern
- cmd = (char *)skip_regexp((char_u *)cmd, delim, p_magic, &eap->arg);
+ cmd = skip_regexp(cmd, delim, p_magic, &eap->arg);
if (cmd[0] == delim) { // end delimiter found
*cmd++ = NUL; // replace it with a NUL
}
@@ -4768,10 +4772,9 @@ bool prepare_tagpreview(bool undo_sync)
== FAIL) {
return false;
}
- curwin->w_p_pvw = TRUE;
- curwin->w_p_wfh = TRUE;
- RESET_BINDING(curwin); /* don't take over 'scrollbind'
- and 'cursorbind' */
+ curwin->w_p_pvw = true;
+ curwin->w_p_wfh = true;
+ RESET_BINDING(curwin); // don't take over 'scrollbind' and 'cursorbind'
curwin->w_p_diff = false; // no 'diff'
set_string_option_direct("fdc", -1, // no 'foldcolumn'
"0", OPT_FREE, SID_NONE);
@@ -4789,7 +4792,7 @@ static int show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines, i
long cmdpreview_ns, handle_T cmdpreview_bufnr)
FUNC_ATTR_NONNULL_ALL
{
- char *save_shm_p = (char *)vim_strsave(p_shm);
+ char *save_shm_p = xstrdup(p_shm);
PreviewLines lines = *preview_lines;
buf_T *orig_buf = curbuf;
// We keep a special-purpose buffer around, but don't assume it exists.
@@ -4940,7 +4943,7 @@ char *skip_vimgrep_pat(char *p, char **s, int *flags)
if (s != NULL) {
*s = p;
}
- p = (char *)skiptowhite((char_u *)p);
+ p = skiptowhite(p);
if (s != NULL && *p != NUL) {
*p++ = NUL;
}
@@ -4950,7 +4953,7 @@ char *skip_vimgrep_pat(char *p, char **s, int *flags)
*s = p + 1;
}
c = (char_u)(*p);
- p = (char *)skip_regexp((char_u *)p + 1, c, true, NULL);
+ p = skip_regexp(p + 1, c, true, NULL);
if (*p != c) {
return NULL;
}
@@ -4995,7 +4998,7 @@ void ex_oldfiles(exarg_T *eap)
}
nr++;
const char *fname = tv_get_string(TV_LIST_ITEM_TV(li));
- if (!message_filtered((char_u *)fname)) {
+ if (!message_filtered((char *)fname)) {
msg_outnum(nr);
msg_puts(": ");
msg_outtrans((char *)tv_get_string(TV_LIST_ITEM_TV(li)));
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 54315a6417..11280eecbb 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -14,11 +14,6 @@
#include "nvim/arglist.h"
#include "nvim/ascii.h"
#include "nvim/autocmd.h"
-#include "nvim/globals.h"
-#include "nvim/vim.h"
-#ifdef HAVE_LOCALE_H
-# include <locale.h>
-#endif
#include "nvim/buffer.h"
#include "nvim/change.h"
#include "nvim/charset.h"
@@ -30,6 +25,7 @@
#include "nvim/ex_eval.h"
#include "nvim/ex_getln.h"
#include "nvim/fileio.h"
+#include "nvim/globals.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
@@ -39,13 +35,13 @@
#include "nvim/ops.h"
#include "nvim/option.h"
#include "nvim/os/fs_defs.h"
-#include "nvim/os/shell.h"
#include "nvim/os_unix.h"
#include "nvim/path.h"
#include "nvim/quickfix.h"
#include "nvim/runtime.h"
#include "nvim/strings.h"
#include "nvim/undo.h"
+#include "nvim/vim.h"
#include "nvim/window.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -368,7 +364,7 @@ bool check_changed_any(bool hidden, bool unload)
exiting = false;
// When ":confirm" used, don't give an error message.
if (!(p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM))) {
- // There must be a wait_return for this message, do_buffer()
+ // There must be a wait_return() for this message, do_buffer()
// may cause a redraw. But wait_return() is a no-op when vgetc()
// is busy (Quit used from window menu), then make sure we don't
// cause a scroll up.
@@ -543,10 +539,10 @@ void ex_listdo(exarg_T *eap)
if (curwin->w_arg_idx != i || !editing_arg_idx(curwin)) {
// Clear 'shm' to avoid that the file message overwrites
// any output from the command.
- p_shm_save = (char *)vim_strsave(p_shm);
- set_option_value("shm", 0L, "", 0);
+ p_shm_save = xstrdup(p_shm);
+ set_option_value_give_err("shm", 0L, "", 0);
do_argfile(eap, i);
- set_option_value("shm", 0L, p_shm_save, 0);
+ set_option_value_give_err("shm", 0L, p_shm_save, 0);
xfree(p_shm_save);
}
if (curwin->w_arg_idx != i) {
@@ -612,10 +608,10 @@ void ex_listdo(exarg_T *eap)
// Go to the next buffer. Clear 'shm' to avoid that the file
// message overwrites any output from the command.
- p_shm_save = (char *)vim_strsave(p_shm);
- set_option_value("shm", 0L, "", 0);
+ p_shm_save = xstrdup(p_shm);
+ set_option_value_give_err("shm", 0L, "", 0);
goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
- set_option_value("shm", 0L, p_shm_save, 0);
+ set_option_value_give_err("shm", 0L, p_shm_save, 0);
xfree(p_shm_save);
// If autocommands took us elsewhere, quit here.
@@ -635,10 +631,10 @@ void ex_listdo(exarg_T *eap)
// Clear 'shm' to avoid that the file message overwrites
// any output from the command.
- p_shm_save = (char *)vim_strsave(p_shm);
- set_option_value("shm", 0L, "", 0);
+ p_shm_save = xstrdup(p_shm);
+ set_option_value_give_err("shm", 0L, "", 0);
ex_cnext(eap);
- set_option_value("shm", 0L, p_shm_save, 0);
+ set_option_value_give_err("shm", 0L, p_shm_save, 0);
xfree(p_shm_save);
// If jumping to the next quickfix entry fails, quit here.
@@ -680,11 +676,11 @@ void ex_listdo(exarg_T *eap)
// buffer was opened while Syntax autocommands were disabled,
// need to trigger them now.
if (buf == curbuf) {
- apply_autocmds(EVENT_SYNTAX, (char *)curbuf->b_p_syn, curbuf->b_fname, true,
+ apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, curbuf->b_fname, true,
curbuf);
} else {
aucmd_prepbuf(&aco, buf);
- apply_autocmds(EVENT_SYNTAX, (char *)buf->b_p_syn, buf->b_fname, true, buf);
+ apply_autocmds(EVENT_SYNTAX, buf->b_p_syn, buf->b_fname, true, buf);
aucmd_restbuf(&aco);
}
@@ -776,324 +772,6 @@ void ex_checktime(exarg_T *eap)
no_check_timestamps = save_no_check_timestamps;
}
-#if defined(HAVE_LOCALE_H)
-# define HAVE_GET_LOCALE_VAL
-
-static char *get_locale_val(int what)
-{
- // Obtain the locale value from the libraries.
- char *loc = setlocale(what, NULL);
-
- return loc;
-}
-#endif
-
-/// @return true when "lang" starts with a valid language name.
-/// Rejects NULL, empty string, "C", "C.UTF-8" and others.
-static bool is_valid_mess_lang(char *lang)
-{
- return lang != NULL && ASCII_ISALPHA(lang[0]) && ASCII_ISALPHA(lang[1]);
-}
-
-/// Obtain the current messages language. Used to set the default for
-/// 'helplang'. May return NULL or an empty string.
-char *get_mess_lang(void)
-{
- char *p;
-
-#ifdef HAVE_GET_LOCALE_VAL
-# if defined(LC_MESSAGES)
- p = get_locale_val(LC_MESSAGES);
-# else
- // This is necessary for Win32, where LC_MESSAGES is not defined and $LANG
- // may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME
- // and LC_MONETARY may be set differently for a Japanese working in the
- // US.
- p = get_locale_val(LC_COLLATE);
-# endif
-#else
- p = os_getenv("LC_ALL");
- if (!is_valid_mess_lang(p)) {
- p = os_getenv("LC_MESSAGES");
- if (!is_valid_mess_lang(p)) {
- p = os_getenv("LANG");
- }
- }
-#endif
- return is_valid_mess_lang(p) ? p : NULL;
-}
-
-// Complicated #if; matches with where get_mess_env() is used below.
-#ifdef HAVE_WORKING_LIBINTL
-/// Get the language used for messages from the environment.
-static char *get_mess_env(void)
-{
- char *p;
-
- p = (char *)os_getenv("LC_ALL");
- if (p == NULL) {
- p = (char *)os_getenv("LC_MESSAGES");
- if (p == NULL) {
- p = (char *)os_getenv("LANG");
- if (p != NULL && ascii_isdigit(*p)) {
- p = NULL; // ignore something like "1043"
- }
-# ifdef HAVE_GET_LOCALE_VAL
- if (p == NULL) {
- p = get_locale_val(LC_CTYPE);
- }
-# endif
- }
- }
- return p;
-}
-
-#endif
-
-/// Set the "v:lang" variable according to the current locale setting.
-/// Also do "v:lc_time"and "v:ctype".
-void set_lang_var(void)
-{
- const char *loc;
-
-#ifdef HAVE_GET_LOCALE_VAL
- loc = get_locale_val(LC_CTYPE);
-#else
- // setlocale() not supported: use the default value
- loc = "C";
-#endif
- set_vim_var_string(VV_CTYPE, loc, -1);
-
- // When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall
- // back to LC_CTYPE if it's empty.
-#ifdef HAVE_WORKING_LIBINTL
- loc = get_mess_env();
-#elif defined(LC_MESSAGES)
- loc = get_locale_val(LC_MESSAGES);
-#else
- // In Windows LC_MESSAGES is not defined fallback to LC_CTYPE
- loc = get_locale_val(LC_CTYPE);
-#endif
- set_vim_var_string(VV_LANG, loc, -1);
-
-#ifdef HAVE_GET_LOCALE_VAL
- loc = get_locale_val(LC_TIME);
-#endif
- set_vim_var_string(VV_LC_TIME, loc, -1);
-
-#ifdef HAVE_GET_LOCALE_VAL
- loc = get_locale_val(LC_COLLATE);
-#else
- // setlocale() not supported: use the default value
- loc = "C";
-#endif
- set_vim_var_string(VV_COLLATE, loc, -1);
-}
-
-#ifdef HAVE_WORKING_LIBINTL
-
-/// ":language": Set the language (locale).
-///
-/// @param eap
-void ex_language(exarg_T *eap)
-{
- char *loc;
- char *p;
- char *name;
- int what = LC_ALL;
- char *whatstr = "";
-# ifdef LC_MESSAGES
-# define VIM_LC_MESSAGES LC_MESSAGES
-# else
-# define VIM_LC_MESSAGES 6789
-# endif
-
- name = eap->arg;
-
- // Check for "messages {name}", "ctype {name}" or "time {name}" argument.
- // Allow abbreviation, but require at least 3 characters to avoid
- // confusion with a two letter language name "me" or "ct".
- p = (char *)skiptowhite((char_u *)eap->arg);
- if ((*p == NUL || ascii_iswhite(*p)) && p - eap->arg >= 3) {
- if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0) {
- what = VIM_LC_MESSAGES;
- name = skipwhite(p);
- whatstr = "messages ";
- } else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0) {
- what = LC_CTYPE;
- name = skipwhite(p);
- whatstr = "ctype ";
- } else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0) {
- what = LC_TIME;
- name = skipwhite(p);
- whatstr = "time ";
- } else if (STRNICMP(eap->arg, "collate", p - eap->arg) == 0) {
- what = LC_COLLATE;
- name = skipwhite(p);
- whatstr = "collate ";
- }
- }
-
- if (*name == NUL) {
- if (what == VIM_LC_MESSAGES) {
- p = get_mess_env();
- } else {
- p = setlocale(what, NULL);
- }
- if (p == NULL || *p == NUL) {
- p = "Unknown";
- }
- smsg(_("Current %slanguage: \"%s\""), whatstr, p);
- } else {
-# ifndef LC_MESSAGES
- if (what == VIM_LC_MESSAGES) {
- loc = "";
- } else {
-# endif
- loc = setlocale(what, name);
-# ifdef LC_NUMERIC
- // Make sure strtod() uses a decimal point, not a comma.
- setlocale(LC_NUMERIC, "C");
-# endif
-# ifndef LC_MESSAGES
- }
-# endif
- if (loc == NULL) {
- semsg(_("E197: Cannot set language to \"%s\""), name);
- } else {
-# ifdef HAVE_NL_MSG_CAT_CNTR
- // Need to do this for GNU gettext, otherwise cached translations
- // will be used again.
- extern int _nl_msg_cat_cntr;
-
- _nl_msg_cat_cntr++;
-# endif
- // Reset $LC_ALL, otherwise it would overrule everything.
- os_setenv("LC_ALL", "", 1);
-
- if (what != LC_TIME && what != LC_COLLATE) {
- // Tell gettext() what to translate to. It apparently doesn't
- // use the currently effective locale.
- if (what == LC_ALL) {
- os_setenv("LANG", name, 1);
-
- // Clear $LANGUAGE because GNU gettext uses it.
- os_setenv("LANGUAGE", "", 1);
- }
- if (what != LC_CTYPE) {
- os_setenv("LC_MESSAGES", name, 1);
- set_helplang_default(name);
- }
- }
-
- // Set v:lang, v:lc_time, v:collate and v:ctype to the final result.
- set_lang_var();
- maketitle();
- }
- }
-}
-
-static char **locales = NULL; // Array of all available locales
-
-# ifndef WIN32
-static bool did_init_locales = false;
-
-/// @return an array of strings for all available locales + NULL for the
-/// last element or,
-/// NULL in case of error.
-static char **find_locales(void)
-{
- garray_T locales_ga;
- char *loc;
- char *saveptr = NULL;
-
- // Find all available locales by running command "locale -a". If this
- // doesn't work we won't have completion.
- char *locale_a = (char *)get_cmd_output((char_u *)"locale -a", NULL,
- kShellOptSilent, NULL);
- if (locale_a == NULL) {
- return NULL;
- }
- ga_init(&locales_ga, sizeof(char_u *), 20);
-
- // Transform locale_a string where each locale is separated by "\n"
- // into an array of locale strings.
- loc = os_strtok(locale_a, "\n", &saveptr);
-
- while (loc != NULL) {
- loc = xstrdup(loc);
- GA_APPEND(char *, &locales_ga, loc);
- loc = os_strtok(NULL, "\n", &saveptr);
- }
- xfree(locale_a);
- // Guarantee that .ga_data is NULL terminated
- ga_grow(&locales_ga, 1);
- ((char_u **)locales_ga.ga_data)[locales_ga.ga_len] = NULL;
- return locales_ga.ga_data;
-}
-# endif
-
-/// Lazy initialization of all available locales.
-static void init_locales(void)
-{
-# ifndef WIN32
- if (!did_init_locales) {
- did_init_locales = true;
- locales = find_locales();
- }
-# endif
-}
-
-# if defined(EXITFREE)
-void free_locales(void)
-{
- int i;
- if (locales != NULL) {
- for (i = 0; locales[i] != NULL; i++) {
- xfree(locales[i]);
- }
- XFREE_CLEAR(locales);
- }
-}
-
-# endif
-
-/// Function given to ExpandGeneric() to obtain the possible arguments of the
-/// ":language" command.
-char *get_lang_arg(expand_T *xp, int idx)
-{
- if (idx == 0) {
- return "messages";
- }
- if (idx == 1) {
- return "ctype";
- }
- if (idx == 2) {
- return "time";
- }
- if (idx == 3) {
- return "collate";
- }
-
- init_locales();
- if (locales == NULL) {
- return NULL;
- }
- return locales[idx - 4];
-}
-
-/// Function given to ExpandGeneric() to obtain the available locales.
-char *get_locales(expand_T *xp, int idx)
-{
- init_locales();
- if (locales == NULL) {
- return NULL;
- }
- return locales[idx];
-}
-
-#endif
-
static void script_host_execute(char *name, exarg_T *eap)
{
size_t len;
diff --git a/src/nvim/ex_cmds2.h b/src/nvim/ex_cmds2.h
index e454a30028..3a41e105f3 100644
--- a/src/nvim/ex_cmds2.h
+++ b/src/nvim/ex_cmds2.h
@@ -1,8 +1,6 @@
#ifndef NVIM_EX_CMDS2_H
#define NVIM_EX_CMDS2_H
-#include <stdbool.h>
-
#include "nvim/ex_cmds_defs.h"
//
diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h
index e80e47bcff..71956b2246 100644
--- a/src/nvim/ex_cmds_defs.h
+++ b/src/nvim/ex_cmds_defs.h
@@ -188,7 +188,7 @@ struct exarg {
cmdidx_T cmdidx; ///< the index for the command
uint32_t argt; ///< flags for the command
int skip; ///< don't execute the command, only parse it
- int forceit; ///< TRUE if ! present
+ int forceit; ///< true if ! present
int addr_count; ///< the number of addresses given
linenr_T line1; ///< the first line number
linenr_T line2; ///< the second line number or count
@@ -196,8 +196,8 @@ struct exarg {
int flags; ///< extra flags after count: EXFLAG_
char *do_ecmd_cmd; ///< +command arg to be used in edited file
linenr_T do_ecmd_lnum; ///< the line number in an edited file
- int append; ///< TRUE with ":w >>file" command
- int usefilter; ///< TRUE with ":w !command" and ":r!command"
+ int append; ///< true with ":w >>file" command
+ int usefilter; ///< true with ":w !command" and ":r!command"
int amount; ///< number of '>' or '<' for shift command
int regname; ///< register name (NUL if none)
int force_bin; ///< 0, FORCE_BIN or FORCE_NOBIN
@@ -230,13 +230,15 @@ struct expand {
sctx_T xp_script_ctx; // SCTX for completion function
int xp_backslash; // one of the XP_BS_ values
#ifndef BACKSLASH_IN_FILENAME
- int xp_shell; // TRUE for a shell command, more
+ int xp_shell; // true for a shell command, more
// characters need to be escaped
#endif
int xp_numfiles; // number of files found by file name completion
int xp_col; // cursor position in line
char **xp_files; // list of files
char *xp_line; // text being completed
+#define EXPAND_BUF_LEN 256
+ char xp_buf[EXPAND_BUF_LEN]; // buffer for returned match
};
// values for xp_backslash
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 7bf272fbba..bf518f3849 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -47,6 +47,7 @@
#include "nvim/if_cscope.h"
#include "nvim/input.h"
#include "nvim/keycodes.h"
+#include "nvim/locale.h"
#include "nvim/lua/executor.h"
#include "nvim/main.h"
#include "nvim/mapping.h"
@@ -94,6 +95,12 @@ static char e_ambiguous_use_of_user_defined_command[]
= N_("E464: Ambiguous use of user-defined command");
static char e_not_an_editor_command[]
= N_("E492: Not an editor command");
+static char e_no_source_file_name_to_substitute_for_sfile[]
+ = N_("E498: no :source file name to substitute for \"<sfile>\"");
+static char e_no_call_stack_to_substitute_for_stack[]
+ = N_("E489: no call stack to substitute for \"<stack>\"");
+static char e_no_script_file_name_to_substitute_for_script[]
+ = N_("E1274: No script file name to substitute for \"<script>\"");
static int quitmore = 0;
static bool ex_pressedreturn = false;
@@ -127,6 +134,7 @@ struct dbg_stuff {
char *vv_throwpoint;
int did_emsg;
int got_int;
+ bool did_throw;
int need_rethrow;
int check_cstack;
except_T *current_exception;
@@ -158,6 +166,7 @@ static void save_dbg_stuff(struct dbg_stuff *dsp)
// Necessary for debugging an inactive ":catch", ":finally", ":endtry".
dsp->did_emsg = did_emsg; did_emsg = false;
dsp->got_int = got_int; got_int = false;
+ dsp->did_throw = did_throw; did_throw = false;
dsp->need_rethrow = need_rethrow; need_rethrow = false;
dsp->check_cstack = check_cstack; check_cstack = false;
dsp->current_exception = current_exception; current_exception = NULL;
@@ -173,6 +182,7 @@ static void restore_dbg_stuff(struct dbg_stuff *dsp)
(void)v_throwpoint(dsp->vv_throwpoint);
did_emsg = dsp->did_emsg;
got_int = dsp->got_int;
+ did_throw = dsp->did_throw;
need_rethrow = dsp->need_rethrow;
check_cstack = dsp->check_cstack;
current_exception = dsp->current_exception;
@@ -243,8 +253,8 @@ void do_exmode(void)
RedrawingDisabled--;
no_wait_return--;
- redraw_all_later(NOT_VALID);
- update_screen(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
+ update_screen(UPD_NOT_VALID);
need_wait_return = false;
msg_scroll = save_msg_scroll;
}
@@ -390,7 +400,8 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
initial_trylevel = trylevel;
- current_exception = NULL;
+ // "did_throw" will be set to true when an exception is being thrown.
+ did_throw = false;
// "did_emsg" will be set to true when emsg() is used, in which case we
// cancel the whole command line, and any if/endif or loop.
// If force_abort is set, we cancel everything.
@@ -455,7 +466,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
if (breakpoint != NULL && dbg_tick != NULL
&& *dbg_tick != debug_tick) {
*breakpoint = dbg_find_breakpoint(getline_equal(fgetline, cookie, getsourceline),
- (char_u *)fname, SOURCING_LNUM);
+ fname, SOURCING_LNUM);
*dbg_tick = debug_tick;
}
@@ -464,10 +475,10 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
// Did we encounter a breakpoint?
if (breakpoint != NULL && *breakpoint != 0 && *breakpoint <= SOURCING_LNUM) {
- dbg_breakpoint((char_u *)fname, SOURCING_LNUM);
+ dbg_breakpoint(fname, SOURCING_LNUM);
// Find next breakpoint.
*breakpoint = dbg_find_breakpoint(getline_equal(fgetline, cookie, getsourceline),
- (char_u *)fname, SOURCING_LNUM);
+ fname, SOURCING_LNUM);
*dbg_tick = debug_tick;
}
if (do_profiling == PROF_YES) {
@@ -509,7 +520,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
cstack.cs_idx <
0 ? 0 : (cstack.cs_idx + 1) * 2,
true)) == NULL) {
- // Don't call wait_return for aborted command line. The NULL
+ // Don't call wait_return() for aborted command line. The NULL
// returned for the end of a sourced file or executed function
// doesn't do this.
if (KeyTyped && !(flags & DOCMD_REPEAT)) {
@@ -524,7 +535,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
if (flags & DOCMD_KEEPLINE) {
xfree(repeat_cmdline);
if (count == 0) {
- repeat_cmdline = vim_strsave((char_u *)next_cmdline);
+ repeat_cmdline = (char *)vim_strsave((char_u *)next_cmdline);
} else {
repeat_cmdline = NULL;
}
@@ -618,7 +629,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
// not to use a cs_line[] from an entry that isn't a ":while"
// or ":for": It would make "current_line" invalid and can
// cause a crash.
- if (!did_emsg && !got_int && !current_exception
+ if (!did_emsg && !got_int && !did_throw
&& cstack.cs_idx >= 0
&& (cstack.cs_flags[cstack.cs_idx]
& (CSF_WHILE | CSF_FOR))
@@ -632,8 +643,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
// Check for the next breakpoint at or after the ":while"
// or ":for".
if (breakpoint != NULL) {
- *breakpoint = dbg_find_breakpoint(getline_equal(fgetline, cookie, getsourceline),
- (char_u *)fname,
+ *breakpoint = dbg_find_breakpoint(getline_equal(fgetline, cookie, getsourceline), fname,
((wcmd_T *)lines_ga.ga_data)[current_line].lnum - 1);
*dbg_tick = debug_tick;
}
@@ -660,7 +670,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
current_line = 0;
}
- // A ":finally" makes did_emsg, got_int and current_exception pending for
+ // A ":finally" makes did_emsg, got_int and did_throw pending for
// being restored at the ":endtry". Reset them here and set the
// ACTIVE and FINALLY flags, so that the finally clause gets executed.
// This includes the case where a missing ":endif", ":endwhile" or
@@ -669,9 +679,8 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
cstack.cs_lflags &= ~CSL_HAD_FINA;
report_make_pending((cstack.cs_pending[cstack.cs_idx]
& (CSTP_ERROR | CSTP_INTERRUPT | CSTP_THROW)),
- current_exception);
- did_emsg = got_int = false;
- current_exception = NULL;
+ did_throw ? current_exception : NULL);
+ did_emsg = got_int = did_throw = false;
cstack.cs_flags[cstack.cs_idx] |= CSF_ACTIVE | CSF_FINALLY;
}
@@ -684,7 +693,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
// exception, cancel everything. If it is left normally, reset
// force_abort to get the non-EH compatible abortion behavior for
// the rest of the script.
- if (trylevel == 0 && !did_emsg && !got_int && !current_exception) {
+ if (trylevel == 0 && !did_emsg && !got_int && !did_throw) {
force_abort = false;
}
@@ -698,7 +707,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
// - didn't get an error message or lines are not typed
// - there is a command after '|', inside a :if, :while, :for or :try, or
// looping for ":source" command or function call.
- } while (!((got_int || (did_emsg && force_abort) || current_exception)
+ } while (!((got_int || (did_emsg && force_abort) || did_throw)
&& cstack.cs_trylevel == 0)
&& !(did_emsg
// Keep going when inside try/catch, so that the error can be
@@ -718,7 +727,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
if (cstack.cs_idx >= 0) {
// If a sourced file or executed function ran to its end, report the
// unclosed conditional.
- if (!got_int && !current_exception
+ if (!got_int && !did_throw
&& ((getline_equal(fgetline, cookie, getsourceline)
&& !source_finished(fgetline, cookie))
|| (getline_equal(fgetline, cookie, get_func_line)
@@ -761,7 +770,8 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
// conditional, discard the uncaught exception, disable the conversion
// of interrupts or errors to exceptions, and ensure that no more
// commands are executed.
- if (current_exception) {
+ if (did_throw) {
+ assert(current_exception != NULL);
char *p = NULL;
msglist_T *messages = NULL;
msglist_T *next;
@@ -823,14 +833,14 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
// cstack belongs to the same function or, respectively, script file, it
// will have to be checked for finally clauses to be executed due to the
// ":return" or ":finish". This is done in do_one_cmd().
- if (current_exception) {
+ if (did_throw) {
need_rethrow = true;
}
if ((getline_equal(fgetline, cookie, getsourceline)
&& ex_nesting_level > source_level(real_cookie))
|| (getline_equal(fgetline, cookie, get_func_line)
&& ex_nesting_level > func_level(real_cookie) + 1)) {
- if (!current_exception) {
+ if (!did_throw) {
check_cstack = true;
}
} else {
@@ -844,8 +854,8 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
|| getline_equal(fgetline, cookie, get_func_line))
&& ex_nesting_level + 1 <= debug_break_level) {
do_debug(getline_equal(fgetline, cookie, getsourceline)
- ? (char_u *)_("End of sourced file")
- : (char_u *)_("End of function"));
+ ? _("End of sourced file")
+ : _("End of function"));
}
}
@@ -881,7 +891,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
need_wait_return = false;
msg_didany = false; // don't wait when restarting edit
} else if (need_wait_return) {
- // The msg_start() above clears msg_didout. The wait_return we do
+ // The msg_start() above clears msg_didout. The wait_return() we do
// here should not overwrite the command that may be shown before
// doing that.
msg_didout |= msg_didout_before_start;
@@ -1361,6 +1371,13 @@ bool is_cmd_ni(cmdidx_T cmdidx)
bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **errormsg)
{
char *after_modifier = NULL;
+ bool retval = false;
+ // parsing the command modifiers may set ex_pressedreturn
+ const bool save_ex_pressedreturn = ex_pressedreturn;
+ // parsing the command range may require moving the cursor
+ const pos_T save_cursor = curwin->w_cursor;
+ // parsing the command range may set the last search pattern
+ save_last_search_pattern();
// Initialize cmdinfo
CLEAR_POINTER(cmdinfo);
@@ -1375,13 +1392,10 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
.cookie = NULL,
};
- const bool save_ex_pressedreturn = ex_pressedreturn;
// Parse command modifiers
if (parse_command_modifiers(eap, errormsg, &cmdinfo->cmdmod, false) == FAIL) {
- ex_pressedreturn = save_ex_pressedreturn;
- goto err;
+ goto end;
}
- ex_pressedreturn = save_ex_pressedreturn;
after_modifier = eap->cmd;
// Save location after command modifiers
@@ -1394,21 +1408,21 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
char *p = find_ex_command(eap, NULL);
if (p == NULL) {
*errormsg = _(e_ambiguous_use_of_user_defined_command);
- goto err;
+ goto end;
}
// Set command address type and parse command range
set_cmd_addr_type(eap, p);
eap->cmd = cmd;
- if (parse_cmd_address(eap, errormsg, false) == FAIL) {
- goto err;
+ if (parse_cmd_address(eap, errormsg, true) == FAIL) {
+ goto end;
}
// Skip colon and whitespace
eap->cmd = skip_colon_white(eap->cmd, true);
// Fail if command is a comment or if command doesn't exist
if (*eap->cmd == NUL || *eap->cmd == '"') {
- goto err;
+ goto end;
}
// Fail if command is invalid
if (eap->cmdidx == CMD_SIZE) {
@@ -1417,7 +1431,7 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
char *cmdname = after_modifier ? after_modifier : cmdline;
append_command(cmdname);
*errormsg = (char *)IObuff;
- goto err;
+ goto end;
}
// Correctly set 'forceit' for commands
@@ -1456,12 +1470,12 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
// Fail if command doesn't support bang but is used with a bang
if (!(eap->argt & EX_BANG) && eap->forceit) {
*errormsg = _(e_nobang);
- goto err;
+ goto end;
}
// Fail if command doesn't support a range but it is given a range
if (!(eap->argt & EX_RANGE) && eap->addr_count > 0) {
*errormsg = _(e_norange);
- goto err;
+ goto end;
}
// Set default range for command if required
if ((eap->argt & EX_DFLALL) && eap->addr_count == 0) {
@@ -1471,7 +1485,7 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
// Parse register and count
parse_register(eap);
if (parse_count(eap, errormsg, false) == FAIL) {
- goto err;
+ goto end;
}
// Remove leading whitespace and colon from next command
@@ -1487,10 +1501,15 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
cmdinfo->magic.bar = true;
}
- return true;
-err:
- undo_cmdmod(&cmdinfo->cmdmod);
- return false;
+ retval = true;
+end:
+ if (!retval) {
+ undo_cmdmod(&cmdinfo->cmdmod);
+ }
+ ex_pressedreturn = save_ex_pressedreturn;
+ curwin->w_cursor = save_cursor;
+ restore_last_search_pattern();
+ return retval;
}
static int execute_cmd0(int *retv, exarg_T *eap, char **errormsg, bool preview)
@@ -1660,7 +1679,7 @@ static void profile_cmd(const exarg_T *eap, cstack_T *cstack, LineGetter fgetlin
&& (!eap->skip || cstack->cs_idx == 0
|| (cstack->cs_idx > 0
&& (cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE)))) {
- int skip = did_emsg || got_int || current_exception;
+ bool skip = did_emsg || got_int || did_throw;
if (eap->cmdidx == CMD_catch) {
skip = !skip && !(cstack->cs_idx >= 0
@@ -1857,7 +1876,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
ea.skip = (did_emsg
|| got_int
- || current_exception
+ || did_throw
|| (cstack->cs_idx >= 0
&& !(cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE)));
@@ -2565,7 +2584,7 @@ static void apply_cmdmod(cmdmod_T *cmod)
if ((cmod->cmod_flags & CMOD_NOAUTOCMD) && cmod->cmod_save_ei == NULL) {
// Set 'eventignore' to "all".
// First save the existing option value for restoring it later.
- cmod->cmod_save_ei = (char *)vim_strsave(p_ei);
+ cmod->cmod_save_ei = xstrdup(p_ei);
set_string_option_direct("ei", -1, "all", OPT_FREE, SID_NONE);
}
}
@@ -2587,7 +2606,7 @@ void undo_cmdmod(cmdmod_T *cmod)
if (cmod->cmod_save_ei != NULL) {
// Restore 'eventignore' to the value before ":noautocmd".
set_string_option_direct("ei", -1, cmod->cmod_save_ei, OPT_FREE, SID_NONE);
- free_string_option((char_u *)cmod->cmod_save_ei);
+ free_string_option(cmod->cmod_save_ei);
cmod->cmod_save_ei = NULL;
}
@@ -3038,7 +3057,7 @@ int cmd_exists(const char *const name)
}
/// "fullcommand" function
-void f_fullcommand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_fullcommand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char *name = argvars[0].vval.v_string;
@@ -3072,7 +3091,7 @@ cmdidx_T excmd_get_cmdidx(const char *cmd, size_t len)
{
cmdidx_T idx;
- for (idx = (cmdidx_T)0; (int)idx < (int)CMD_SIZE; idx = (cmdidx_T)((int)idx + 1)) {
+ for (idx = (cmdidx_T)0; (int)idx < CMD_SIZE; idx = (cmdidx_T)((int)idx + 1)) {
if (strncmp(cmdnames[(int)idx].cmd_name, cmd, len) == 0) {
break;
}
@@ -3294,7 +3313,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
goto error;
}
if (skip) { // skip "/pat/"
- cmd = (char *)skip_regexp((char_u *)cmd, c, p_magic, NULL);
+ cmd = skip_regexp(cmd, c, p_magic, NULL);
if (*cmd == c) {
cmd++;
}
@@ -3570,6 +3589,9 @@ char *invalid_range(exarg_T *eap)
assert(eap->line2 >= 0);
// No error for value that is too big, will use the last entry.
if (eap->line2 <= 0) {
+ if (eap->addr_count == 0) {
+ return _(e_no_errors);
+ }
return _(e_invrange);
}
break;
@@ -3631,8 +3653,8 @@ char *replace_makeprg(exarg_T *eap, char *arg, char **cmdlinep)
// Don't do it when ":vimgrep" is used for ":grep".
if ((eap->cmdidx == CMD_make || eap->cmdidx == CMD_lmake || isgrep)
&& !grep_internal(eap->cmdidx)) {
- const char *program = isgrep ? (*curbuf->b_p_gp == NUL ? (char *)p_gp : (char *)curbuf->b_p_gp)
- : (*curbuf->b_p_mp == NUL ? (char *)p_mp : (char *)curbuf->b_p_mp);
+ const char *program = isgrep ? (*curbuf->b_p_gp == NUL ? (char *)p_gp : curbuf->b_p_gp)
+ : (*curbuf->b_p_mp == NUL ? (char *)p_mp : curbuf->b_p_mp);
arg = skipwhite(arg);
@@ -3646,7 +3668,7 @@ char *replace_makeprg(exarg_T *eap, char *arg, char **cmdlinep)
STRCAT(new_cmdline, arg);
}
- msg_make((char_u *)arg);
+ msg_make(arg);
// 'eap->cmd' is not set here, because it is not used at CMD_make
xfree(*cmdlinep);
@@ -3690,7 +3712,7 @@ int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp)
size_t srclen;
int escaped;
char *repl = (char *)eval_vars((char_u *)p, (char_u *)eap->arg, &srclen, &(eap->do_ecmd_lnum),
- errormsgp, &escaped);
+ errormsgp, &escaped, true);
if (*errormsgp != NULL) { // error detected
return FAIL;
}
@@ -3772,8 +3794,8 @@ int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp)
// if there are still wildcards present.
if (vim_strchr(eap->arg, '$') != NULL
|| vim_strchr(eap->arg, '~') != NULL) {
- expand_env_esc((char_u *)eap->arg, NameBuff, MAXPATHL, true, true, NULL);
- has_wildcards = path_has_wildcard(NameBuff);
+ expand_env_esc((char_u *)eap->arg, (char_u *)NameBuff, MAXPATHL, true, true, NULL);
+ has_wildcards = path_has_wildcard((char_u *)NameBuff);
p = (char *)NameBuff;
} else {
p = NULL;
@@ -3788,7 +3810,7 @@ int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp)
// done by ExpandOne() below.
#ifdef UNIX
if (!has_wildcards) {
- backslash_halve((char_u *)eap->arg);
+ backslash_halve(eap->arg);
}
#else
backslash_halve((char_u *)eap->arg);
@@ -4042,7 +4064,7 @@ static int getargopt(exarg_T *eap)
*arg = NUL;
if (pp == &eap->force_ff) {
- if (check_ff_value((char_u *)eap->cmd + eap->force_ff) == FAIL) {
+ if (check_ff_value(eap->cmd + eap->force_ff) == FAIL) {
return FAIL;
}
eap->force_ff = (char_u)eap->cmd[eap->force_ff];
@@ -4276,7 +4298,7 @@ int ends_excmd(int c) FUNC_ATTR_CONST
/// @return the next command, after the first '|' or '\n' or,
/// NULL if not found.
-char_u *find_nextcmd(const char_u *p)
+char *find_nextcmd(const char *p)
{
while (*p != '|' && *p != '\n') {
if (*p == NUL) {
@@ -4284,7 +4306,7 @@ char_u *find_nextcmd(const char_u *p)
}
p++;
}
- return (char_u *)p + 1;
+ return (char *)p + 1;
}
/// Check if *p is a separator between Ex commands, skipping over white space.
@@ -5013,7 +5035,7 @@ static void ex_tabs(exarg_T *eap)
msg_putchar('\n');
vim_snprintf((char *)IObuff, IOSIZE, _("Tab page %d"), tabcount++);
- msg_outtrans_attr(IObuff, HL_ATTR(HLF_T));
+ msg_outtrans_attr((char *)IObuff, HL_ATTR(HLF_T));
ui_flush(); // output one line at a time
os_breakcheck();
@@ -5044,7 +5066,7 @@ static void ex_tabs(exarg_T *eap)
static void ex_mode(exarg_T *eap)
{
if (*eap->arg == NUL) {
- must_redraw = CLEAR;
+ must_redraw = UPD_CLEAR;
ex_redraw(eap);
} else {
emsg(_(e_screenmode));
@@ -5136,7 +5158,7 @@ void do_exedit(exarg_T *eap, win_T *old_curwin)
no_wait_return = 0;
need_wait_return = false;
msg_scroll = 0;
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
pending_exmode_active = true;
normal_enter(false, true);
@@ -5298,7 +5320,7 @@ static void ex_syncbind(exarg_T *eap)
scrolldown(-y, true);
}
curwin->w_scbind_pos = topline;
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
cursor_correct();
curwin->w_redr_status = true;
}
@@ -5366,7 +5388,7 @@ static void ex_read(exarg_T *eap)
deleted_lines_mark(lnum, 1L);
}
}
- redraw_curbuf_later(VALID);
+ redraw_curbuf_later(UPD_VALID);
}
}
}
@@ -5466,8 +5488,8 @@ bool changedir_func(char *new_dir, CdScope scope)
new_dir = pdir;
}
- if (os_dirname(NameBuff, MAXPATHL) == OK) {
- pdir = (char *)vim_strsave(NameBuff);
+ if (os_dirname((char_u *)NameBuff, MAXPATHL) == OK) {
+ pdir = xstrdup(NameBuff);
} else {
pdir = NULL;
}
@@ -5480,7 +5502,7 @@ bool changedir_func(char *new_dir, CdScope scope)
if (*new_dir == NUL && p_cdh) {
#endif
// Use NameBuff for home directory name.
- expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
+ expand_env("$HOME", NameBuff, MAXPATHL);
new_dir = (char *)NameBuff;
}
@@ -5549,7 +5571,7 @@ void ex_cd(exarg_T *eap)
/// ":pwd".
static void ex_pwd(exarg_T *eap)
{
- if (os_dirname(NameBuff, MAXPATHL) == OK) {
+ if (os_dirname((char_u *)NameBuff, MAXPATHL) == OK) {
#ifdef BACKSLASH_IN_FILENAME
slash_adjust(NameBuff);
#endif
@@ -6037,11 +6059,11 @@ static void ex_redraw(exarg_T *eap)
validate_cursor();
update_topline(curwin);
if (eap->forceit) {
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
redraw_cmdline = true;
}
- update_screen(eap->forceit ? NOT_VALID
- : VIsual_active ? INVERTED : 0);
+ update_screen(eap->forceit ? UPD_NOT_VALID
+ : VIsual_active ? UPD_INVERTED : 0);
if (need_maketitle) {
maketitle();
}
@@ -6074,7 +6096,7 @@ static void ex_redrawstatus(exarg_T *eap)
} else {
status_redraw_curbuf();
}
- update_screen(VIsual_active ? INVERTED : 0);
+ update_screen(VIsual_active ? UPD_INVERTED : 0);
RedrawingDisabled = r;
p_lz = p;
ui_flush();
@@ -6135,7 +6157,7 @@ FILE *open_exfile(char_u *fname, int forceit, char *mode)
{
#ifdef UNIX
// with Unix it is possible to open a directory
- if (os_isdir(fname)) {
+ if (os_isdir((char *)fname)) {
semsg(_(e_isadir2), fname);
return NULL;
}
@@ -6435,7 +6457,7 @@ static void ex_findpat(exarg_T *eap)
if (*eap->arg == '/') { // Match regexp, not just whole words
whole = false;
eap->arg++;
- char *p = (char *)skip_regexp((char_u *)eap->arg, '/', p_magic, NULL);
+ char *p = skip_regexp(eap->arg, '/', p_magic, NULL);
if (*p) {
*p++ = NUL;
p = skipwhite(p);
@@ -6477,7 +6499,7 @@ static void ex_pedit(exarg_T *eap)
if (curwin != curwin_save && win_valid(curwin_save)) {
// Return cursor to where we were
validate_cursor();
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
win_enter(curwin_save, true);
}
g_do_tagpreview = 0;
@@ -6555,6 +6577,7 @@ enum {
SPEC_SFILE,
SPEC_SLNUM,
SPEC_STACK,
+ SPEC_SCRIPT,
SPEC_AFILE,
SPEC_ABUF,
SPEC_AMATCH,
@@ -6579,6 +6602,7 @@ ssize_t find_cmdline_var(const char_u *src, size_t *usedlen)
[SPEC_SFILE] = "<sfile>", // ":so" file name
[SPEC_SLNUM] = "<slnum>", // ":so" file line number
[SPEC_STACK] = "<stack>", // call stack
+ [SPEC_SCRIPT] = "<script>", // script file name
[SPEC_AFILE] = "<afile>", // autocommand file name
[SPEC_ABUF] = "<abuf>", // autocommand buffer number
[SPEC_AMATCH] = "<amatch>", // autocommand match name
@@ -6600,34 +6624,36 @@ ssize_t find_cmdline_var(const char_u *src, size_t *usedlen)
/// Evaluate cmdline variables.
///
-/// change '%' to curbuf->b_ffname
-/// '#' to curwin->w_alt_fnum
-/// '<cword>' to word under the cursor
-/// '<cWORD>' to WORD under the cursor
-/// '<cexpr>' to C-expression under the cursor
-/// '<cfile>' to path name under the cursor
-/// '<sfile>' to sourced file name
-/// '<stack>' to call stack
-/// '<slnum>' to sourced file line number
-/// '<afile>' to file name for autocommand
-/// '<abuf>' to buffer number for autocommand
-/// '<amatch>' to matching name for autocommand
+/// change "%" to curbuf->b_ffname
+/// "#" to curwin->w_alt_fnum
+/// "<cword>" to word under the cursor
+/// "<cWORD>" to WORD under the cursor
+/// "<cexpr>" to C-expression under the cursor
+/// "<cfile>" to path name under the cursor
+/// "<sfile>" to sourced file name
+/// "<stack>" to call stack
+/// "<script>" to current script name
+/// "<slnum>" to sourced file line number
+/// "<afile>" to file name for autocommand
+/// "<abuf>" to buffer number for autocommand
+/// "<amatch>" to matching name for autocommand
///
/// When an error is detected, "errormsg" is set to a non-NULL pointer (may be
/// "" for error without a message) and NULL is returned.
///
-/// @param src pointer into commandline
-/// @param srcstart beginning of valid memory for src
-/// @param usedlen characters after src that are used
-/// @param lnump line number for :e command, or NULL
-/// @param errormsg pointer to error message
-/// @param escaped return value has escaped white space (can be NULL)
+/// @param src pointer into commandline
+/// @param srcstart beginning of valid memory for src
+/// @param usedlen characters after src that are used
+/// @param lnump line number for :e command, or NULL
+/// @param errormsg pointer to error message
+/// @param escaped return value has escaped white space (can be NULL)
+/// @param empty_is_error empty result is considered an error
///
/// @return an allocated string if a valid match was found.
/// Returns NULL if no match was found. "usedlen" then still contains the
/// number of characters to skip.
char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnump, char **errormsg,
- int *escaped)
+ int *escaped, bool empty_is_error)
{
char *result;
char *resultbuf = NULL;
@@ -6792,12 +6818,25 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum
break;
case SPEC_SFILE: // file name for ":so" command
+ result = estack_sfile(ESTACK_SFILE);
+ if (result == NULL) {
+ *errormsg = _(e_no_source_file_name_to_substitute_for_sfile);
+ return NULL;
+ }
+ resultbuf = result; // remember allocated string
+ break;
case SPEC_STACK: // call stack
- result = estack_sfile(spec_idx == SPEC_SFILE ? ESTACK_SFILE : ESTACK_STACK);
+ result = estack_sfile(ESTACK_STACK);
if (result == NULL) {
- *errormsg = spec_idx == SPEC_SFILE
- ? _("E498: no :source file name to substitute for \"<sfile>\"")
- : _("E489: no call stack to substitute for \"<stack>\"");
+ *errormsg = _(e_no_call_stack_to_substitute_for_stack);
+ return NULL;
+ }
+ resultbuf = result; // remember allocated string
+ break;
+ case SPEC_SCRIPT: // script file name
+ result = estack_sfile(ESTACK_SCRIPT);
+ if (result == NULL) {
+ *errormsg = _(e_no_script_file_name_to_substitute_for_script);
return NULL;
}
resultbuf = result; // remember allocated string
@@ -6845,7 +6884,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum
if (src[*usedlen] == '<') {
(*usedlen)++;
char *s;
- if ((s = (char *)STRRCHR(result, '.')) != NULL
+ if ((s = strrchr(result, '.')) != NULL
&& s >= path_tail(result)) {
resultlen = (size_t)(s - result);
}
@@ -6860,11 +6899,13 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum
}
if (resultlen == 0 || valid != VALID_HEAD + VALID_PATH) {
- if (valid != VALID_HEAD + VALID_PATH) {
- // xgettext:no-c-format
- *errormsg = _("E499: Empty file name for '%' or '#', only works with \":p:h\"");
- } else {
- *errormsg = _("E500: Evaluates to an empty string");
+ if (empty_is_error) {
+ if (valid != VALID_HEAD + VALID_PATH) {
+ // xgettext:no-c-format
+ *errormsg = _("E499: Empty file name for '%' or '#', only works with \":p:h\"");
+ } else {
+ *errormsg = _("E500: Evaluates to an empty string");
+ }
}
result = NULL;
} else {
@@ -6888,7 +6929,8 @@ char *expand_sfile(char *arg)
// replace "<sfile>" with the sourced file name, and do ":" stuff
size_t srclen;
char *errormsg;
- char *repl = (char *)eval_vars((char_u *)p, (char_u *)result, &srclen, NULL, &errormsg, NULL);
+ char *repl = (char *)eval_vars((char_u *)p, (char_u *)result, &srclen, NULL, &errormsg, NULL,
+ true);
if (errormsg != NULL) {
if (*errormsg) {
emsg(errormsg);
@@ -6919,16 +6961,16 @@ char *expand_sfile(char *arg)
/// ":rshada" and ":wshada".
static void ex_shada(exarg_T *eap)
{
- char *save_shada = (char *)p_shada;
+ char *save_shada = p_shada;
if (*p_shada == NUL) {
- p_shada = (char_u *)"'100";
+ p_shada = "'100";
}
if (eap->cmdidx == CMD_rviminfo || eap->cmdidx == CMD_rshada) {
(void)shada_read_everything(eap->arg, eap->forceit, false);
} else {
shada_write_file(eap->arg, eap->forceit);
}
- p_shada = (char_u *)save_shada;
+ p_shada = save_shada;
}
/// Make a dialog message in "buff[DIALOG_MSG_SIZE]".
@@ -6945,15 +6987,15 @@ void dialog_msg(char *buff, char *format, char *fname)
static void ex_behave(exarg_T *eap)
{
if (STRCMP(eap->arg, "mswin") == 0) {
- set_option_value("selection", 0L, "exclusive", 0);
- set_option_value("selectmode", 0L, "mouse,key", 0);
- set_option_value("mousemodel", 0L, "popup", 0);
- set_option_value("keymodel", 0L, "startsel,stopsel", 0);
+ set_option_value_give_err("selection", 0L, "exclusive", 0);
+ set_option_value_give_err("selectmode", 0L, "mouse,key", 0);
+ set_option_value_give_err("mousemodel", 0L, "popup", 0);
+ set_option_value_give_err("keymodel", 0L, "startsel,stopsel", 0);
} else if (STRCMP(eap->arg, "xterm") == 0) {
- set_option_value("selection", 0L, "inclusive", 0);
- set_option_value("selectmode", 0L, "", 0);
- set_option_value("mousemodel", 0L, "extend", 0);
- set_option_value("keymodel", 0L, "", 0);
+ set_option_value_give_err("selection", 0L, "inclusive", 0);
+ set_option_value_give_err("selectmode", 0L, "", 0);
+ set_option_value_give_err("mousemodel", 0L, "extend", 0);
+ set_option_value_give_err("keymodel", 0L, "", 0);
} else {
semsg(_(e_invarg2), eap->arg);
}
@@ -7073,7 +7115,7 @@ static void ex_setfiletype(exarg_T *eap)
arg += 9;
}
- set_option_value("filetype", 0L, arg, OPT_LOCAL);
+ set_option_value_give_err("filetype", 0L, arg, OPT_LOCAL);
if (arg != eap->arg) {
did_filetype = false;
}
@@ -7099,7 +7141,7 @@ void set_no_hlsearch(bool flag)
static void ex_nohlsearch(exarg_T *eap)
{
set_no_hlsearch(true);
- redraw_all_later(SOME_VALID);
+ redraw_all_later(UPD_SOME_VALID);
}
static void ex_fold(exarg_T *eap)
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index 69d509abb7..6dddafcfcb 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -45,20 +45,19 @@
// there or even outside the try conditional. Try conditionals may be nested.
// Configuration whether an exception is thrown on error or interrupt. When
-// the preprocessor macros below evaluate to FALSE, an error (did_emsg) or
+// the preprocessor macros below evaluate to false, an error (did_emsg) or
// interrupt (got_int) under an active try conditional terminates the script
// after the non-active finally clauses of all active try conditionals have been
// executed. Otherwise, errors and/or interrupts are converted into catchable
-// exceptions, which terminate the script only if not caught. For user
-// exceptions, only current_exception is set. (Note: got_int can be set
-// asynchronously afterwards by a SIGINT, so current_exception && got_int is not
+// exceptions (did_throw additionally set), which terminate the script only if
+// not caught. For user exceptions, only did_throw is set. (Note: got_int can
+// be set asynchronously afterwards by a SIGINT, so did_throw && got_int is not
// a reliant test that the exception currently being thrown is an interrupt
// exception. Similarly, did_emsg can be set afterwards on an error in an
-// (unskipped) conditional command inside an inactive conditional, so
-// current_exception && did_emsg is not a reliant test that the exception
-// currently being thrown is an error exception.) - The macros can be defined
-// as expressions checking for a variable that is allowed to be changed during
-// execution of a script.
+// (unskipped) conditional command inside an inactive conditional, so did_throw
+// && did_emsg is not a reliant test that the exception currently being thrown
+// is an error exception.) - The macros can be defined as expressions checking
+// for a variable that is allowed to be changed during execution of a script.
// Values used for the Vim release.
#define THROW_ON_ERROR true
@@ -71,7 +70,7 @@
#define CHECK_SKIP \
(did_emsg \
|| got_int \
- || current_exception \
+ || did_throw \
|| (cstack->cs_idx > 0 \
&& !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE)))
@@ -82,14 +81,14 @@ static void discard_pending_return(typval_T *p)
/*
* When several errors appear in a row, setting "force_abort" is delayed until
- * the failing command returned. "cause_abort" is set to TRUE meanwhile, in
+ * the failing command returned. "cause_abort" is set to true meanwhile, in
* order to indicate that situation. This is useful when "force_abort" was set
* during execution of a function call from an expression: the aborting of the
* expression evaluation is done without producing any error messages, but all
* error messages on parsing errors during the expression evaluation are given
* (even if a try conditional is active).
*/
-static int cause_abort = FALSE;
+static int cause_abort = false;
/// @return true when immediately aborting on error, or when an interrupt
/// occurred or an exception was thrown but not caught.
@@ -104,7 +103,7 @@ static int cause_abort = FALSE;
/// value. "got_int" is also set by calling interrupt().
int aborting(void)
{
- return (did_emsg && force_abort) || got_int || current_exception;
+ return (did_emsg && force_abort) || got_int || did_throw;
}
/// The value of "force_abort" is temporarily reset by the first emsg() call
@@ -114,11 +113,11 @@ int aborting(void)
void update_force_abort(void)
{
if (cause_abort) {
- force_abort = TRUE;
+ force_abort = true;
}
}
-/// @return TRUE if a command with a subcommand resulting in "retcode" should
+/// @return true if a command with a subcommand resulting in "retcode" should
/// abort the script processing. Can be used to suppress an autocommand after
/// execution of a failing subcommand as long as the error message has not been
/// displayed and actually caused the abortion.
@@ -127,7 +126,7 @@ int should_abort(int retcode)
return (retcode == FAIL && trylevel != 0 && !emsg_silent) || aborting();
}
-/// @return TRUE if a function with the "abort" flag should not be considered
+/// @return true if a function with the "abort" flag should not be considered
/// ended on an error. This means that parsing commands is continued in order
/// to find finally clauses to be executed, and that some errors in skipped
/// commands are still reported.
@@ -175,7 +174,7 @@ bool cause_errthrow(const char *mesg, bool severe, bool *ignore)
*/
if (!did_emsg) {
cause_abort = force_abort;
- force_abort = FALSE;
+ force_abort = false;
}
/*
@@ -186,7 +185,7 @@ bool cause_errthrow(const char *mesg, bool severe, bool *ignore)
* currently throwing an exception, do nothing. The message text will
* then be stored to v:errmsg by emsg() without displaying it.
*/
- if (((trylevel == 0 && !cause_abort) || emsg_silent) && !current_exception) {
+ if (((trylevel == 0 && !cause_abort) || emsg_silent) && !did_throw) {
return false;
}
@@ -206,7 +205,7 @@ bool cause_errthrow(const char *mesg, bool severe, bool *ignore)
* Ensure that all commands in nested function calls and sourced files
* are aborted immediately.
*/
- cause_abort = TRUE;
+ cause_abort = true;
/*
* When an exception is being thrown, some commands (like conditionals) are
@@ -217,7 +216,7 @@ bool cause_errthrow(const char *mesg, bool severe, bool *ignore)
* exception currently being thrown to prevent it from being caught. Just
* execute finally clauses and terminate.
*/
- if (current_exception) {
+ if (did_throw) {
// When discarding an interrupt exception, reset got_int to prevent the
// same interrupt being converted to an exception again and discarding
// the error exception we are about to throw here.
@@ -318,8 +317,8 @@ void do_errthrow(cstack_T *cstack, char *cmdname)
* are aborted immediately.
*/
if (cause_abort) {
- cause_abort = FALSE;
- force_abort = TRUE;
+ cause_abort = false;
+ force_abort = true;
}
// If no exception is to be thrown or the conversion should be done after
@@ -334,7 +333,7 @@ void do_errthrow(cstack_T *cstack, char *cmdname)
if (cstack != NULL) {
do_throw(cstack);
} else {
- need_rethrow = TRUE;
+ need_rethrow = true;
}
}
*msg_list = NULL;
@@ -343,13 +342,13 @@ void do_errthrow(cstack_T *cstack, char *cmdname)
/// do_intthrow(): Replace the current exception by an interrupt or interrupt
/// exception if appropriate.
///
-/// @return TRUE if the current exception is discarded or,
-/// FALSE otherwise.
+/// @return true if the current exception is discarded or,
+/// false otherwise.
int do_intthrow(cstack_T *cstack)
{
// If no interrupt occurred or no try conditional is active and no exception
// is being thrown, do nothing (for compatibility of non-EH scripts).
- if (!got_int || (trylevel == 0 && !current_exception)) {
+ if (!got_int || (trylevel == 0 && !did_throw)) {
return false;
}
@@ -358,7 +357,7 @@ int do_intthrow(cstack_T *cstack)
// The interrupt aborts everything except for executing finally clauses.
// Discard any user or error or interrupt exception currently being
// thrown.
- if (current_exception) {
+ if (did_throw) {
discard_current_exception();
}
} else {
@@ -369,7 +368,7 @@ int do_intthrow(cstack_T *cstack)
// will be terminated then. - If an interrupt exception is already
// being thrown, do nothing.
- if (current_exception) {
+ if (did_throw) {
if (current_exception->type == ET_INTERRUPT) {
return false;
}
@@ -501,13 +500,13 @@ static int throw_exception(void *value, except_type_T type, char *cmdname)
int save_msg_silent = msg_silent;
if (debug_break_level > 0) {
- msg_silent = FALSE; // display messages
+ msg_silent = false; // display messages
} else {
verbose_enter();
}
no_wait_return++;
if (debug_break_level > 0 || *p_vfile == NUL) {
- msg_scroll = TRUE; // always scroll up, don't overwrite
+ msg_scroll = true; // always scroll up, don't overwrite
}
smsg(_("Exception thrown: %s"), excp->value);
msg_puts("\n"); // don't overwrite this either
@@ -554,13 +553,13 @@ static void discard_exception(except_T *excp, bool was_finished)
saved_IObuff = (char *)vim_strsave(IObuff);
if (debug_break_level > 0) {
- msg_silent = FALSE; // display messages
+ msg_silent = false; // display messages
} else {
verbose_enter();
}
no_wait_return++;
if (debug_break_level > 0 || *p_vfile == NUL) {
- msg_scroll = TRUE; // always scroll up, don't overwrite
+ msg_scroll = true; // always scroll up, don't overwrite
}
smsg(was_finished ? _("Exception finished: %s")
: _("Exception discarded: %s"),
@@ -596,6 +595,7 @@ void discard_current_exception(void)
}
// Note: all globals manipulated here should be saved/restored in
// try_enter/try_leave.
+ did_throw = false;
need_rethrow = false;
}
@@ -622,13 +622,13 @@ static void catch_exception(except_T *excp)
int save_msg_silent = msg_silent;
if (debug_break_level > 0) {
- msg_silent = FALSE; // display messages
+ msg_silent = false; // display messages
} else {
verbose_enter();
}
no_wait_return++;
if (debug_break_level > 0 || *p_vfile == NUL) {
- msg_scroll = TRUE; // always scroll up, don't overwrite
+ msg_scroll = true; // always scroll up, don't overwrite
}
smsg(_("Exception caught: %s"), excp->value);
msg_puts("\n"); // don't overwrite this either
@@ -726,14 +726,14 @@ static void report_pending(int action, int pending, void *value)
break;
case CSTP_RETURN:
// ":return" command producing value, allocated
- s = (char *)get_return_cmd(value);
+ s = get_return_cmd(value);
break;
default:
if (pending & CSTP_THROW) {
vim_snprintf((char *)IObuff, IOSIZE,
mesg, _("Exception"));
- mesg = (char *)concat_str(IObuff, (char_u *)": %s");
+ mesg = concat_str((char *)IObuff, ": %s");
s = ((except_T *)value)->value;
} else if ((pending & CSTP_ERROR) && (pending & CSTP_INTERRUPT)) {
s = _("Error and interrupt");
@@ -746,7 +746,7 @@ static void report_pending(int action, int pending, void *value)
save_msg_silent = msg_silent;
if (debug_break_level > 0) {
- msg_silent = FALSE; // display messages
+ msg_silent = false; // display messages
}
no_wait_return++;
msg_scroll = true; // always scroll up, don't overwrite
@@ -830,7 +830,7 @@ void ex_if(exarg_T *eap)
if (cstack->cs_idx == CSTACK_LEN - 1) {
eap->errmsg = _("E579: :if nesting too deep");
} else {
- ++cstack->cs_idx;
+ cstack->cs_idx++;
cstack->cs_flags[cstack->cs_idx] = 0;
skip = CHECK_SKIP;
@@ -870,7 +870,7 @@ void ex_endif(exarg_T *eap)
(void)do_intthrow(eap->cstack);
}
- --eap->cstack->cs_idx;
+ eap->cstack->cs_idx--;
}
}
@@ -964,8 +964,8 @@ void ex_while(exarg_T *eap)
* cstack entry.
*/
if ((cstack->cs_lflags & CSL_HAD_LOOP) == 0) {
- ++cstack->cs_idx;
- ++cstack->cs_looplevel;
+ cstack->cs_idx++;
+ cstack->cs_looplevel++;
cstack->cs_line[cstack->cs_idx] = -1;
}
cstack->cs_flags[cstack->cs_idx] =
@@ -987,7 +987,7 @@ void ex_while(exarg_T *eap)
// Jumping here from a ":continue" or ":endfor": use the
// previously evaluated list.
fi = cstack->cs_forinfo[cstack->cs_idx];
- error = FALSE;
+ error = false;
} else {
// Evaluate the argument and get the info in a structure.
fi = eval_for_line(eap->arg, &error, &eap->nextcmd, skip);
@@ -998,7 +998,7 @@ void ex_while(exarg_T *eap)
if (!error && fi != NULL && !skip) {
result = next_for_item(fi, eap->arg);
} else {
- result = FALSE;
+ result = false;
}
if (!result) {
@@ -1118,7 +1118,7 @@ void ex_endwhile(exarg_T *eap)
eap->errmsg = _(e_endtry);
}
// Try to find the matching ":while" and report what's missing.
- for (idx = cstack->cs_idx; idx > 0; --idx) {
+ for (idx = cstack->cs_idx; idx > 0; idx--) {
fl = cstack->cs_flags[idx];
if ((fl & CSF_TRY) && !(fl & CSF_FINALLY)) {
// Give up at a try conditional not in its finally clause.
@@ -1131,7 +1131,7 @@ void ex_endwhile(exarg_T *eap)
}
}
// Cleanup and rewind all contained (and unclosed) conditionals.
- (void)cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, FALSE);
+ (void)cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, false);
rewind_conditionals(cstack, idx, CSF_TRY, &cstack->cs_trylevel);
} else if (cstack->cs_flags[cstack->cs_idx] & CSF_TRUE
&& !(cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE)
@@ -1186,7 +1186,7 @@ void ex_throw(exarg_T *eap)
void do_throw(cstack_T *cstack)
{
int idx;
- int inactivate_try = FALSE;
+ int inactivate_try = false;
//
// Cleanup and deactivate up to the next surrounding try conditional that
@@ -1199,14 +1199,14 @@ void do_throw(cstack_T *cstack)
//
#ifndef THROW_ON_ERROR_TRUE
if (did_emsg && !THROW_ON_ERROR) {
- inactivate_try = TRUE;
- did_emsg = FALSE;
+ inactivate_try = true;
+ did_emsg = false;
}
#endif
#ifndef THROW_ON_INTERRUPT_TRUE
if (got_int && !THROW_ON_INTERRUPT) {
- inactivate_try = TRUE;
- got_int = FALSE;
+ inactivate_try = true;
+ got_int = false;
}
#endif
idx = cleanup_conditionals(cstack, 0, inactivate_try);
@@ -1237,6 +1237,8 @@ void do_throw(cstack_T *cstack)
cstack->cs_flags[idx] &= ~CSF_ACTIVE;
cstack->cs_exception[idx] = current_exception;
}
+
+ did_throw = true;
}
/// Handle ":try"
@@ -1248,8 +1250,8 @@ void ex_try(exarg_T *eap)
if (cstack->cs_idx == CSTACK_LEN - 1) {
eap->errmsg = _("E601: :try nesting too deep");
} else {
- ++cstack->cs_idx;
- ++cstack->cs_trylevel;
+ cstack->cs_idx++;
+ cstack->cs_trylevel++;
cstack->cs_flags[cstack->cs_idx] = CSF_TRY;
cstack->cs_pending[cstack->cs_idx] = CSTP_NONE;
@@ -1314,7 +1316,7 @@ void ex_catch(exarg_T *eap)
eap->errmsg = get_end_emsg(cstack);
skip = true;
}
- for (idx = cstack->cs_idx; idx > 0; --idx) {
+ for (idx = cstack->cs_idx; idx > 0; idx--) {
if (cstack->cs_flags[idx] & CSF_TRY) {
break;
}
@@ -1333,10 +1335,10 @@ void ex_catch(exarg_T *eap)
if (ends_excmd(*eap->arg)) { // no argument, catch all errors
pat = ".*";
end = NULL;
- eap->nextcmd = (char *)find_nextcmd((char_u *)eap->arg);
+ eap->nextcmd = find_nextcmd(eap->arg);
} else {
pat = eap->arg + 1;
- end = (char *)skip_regexp((char_u *)pat, *eap->arg, true, NULL);
+ end = skip_regexp(pat, *eap->arg, true, NULL);
}
if (!give_up) {
@@ -1345,7 +1347,7 @@ void ex_catch(exarg_T *eap)
* corresponding try block never got active (because of an inactive
* surrounding conditional or after an error or interrupt or throw).
*/
- if (!current_exception || !(cstack->cs_flags[idx] & CSF_TRUE)) {
+ if (!did_throw || !(cstack->cs_flags[idx] & CSF_TRUE)) {
skip = true;
}
@@ -1376,7 +1378,7 @@ void ex_catch(exarg_T *eap)
*end = NUL;
}
save_cpo = p_cpo;
- p_cpo = "";
+ p_cpo = empty_option;
// Disable error messages, it will make current exception
// invalid
emsg_off++;
@@ -1406,10 +1408,10 @@ void ex_catch(exarg_T *eap)
}
if (caught) {
- // Make this ":catch" clause active and reset did_emsg and got_int.
- // Put the exception on the caught stack.
+ // Make this ":catch" clause active and reset did_emsg, got_int,
+ // and did_throw. Put the exception on the caught stack.
cstack->cs_flags[idx] |= CSF_ACTIVE | CSF_CAUGHT;
- did_emsg = got_int = false;
+ did_emsg = got_int = did_throw = false;
catch_exception((except_T *)cstack->cs_exception[idx]);
// It's mandatory that the current exception is stored in the cstack
// so that it can be discarded at the next ":catch", ":finally", or
@@ -1419,10 +1421,6 @@ void ex_catch(exarg_T *eap)
if (cstack->cs_exception[cstack->cs_idx] != current_exception) {
internal_error("ex_catch()");
}
- // Discarding current_exceptions happens based on what is stored in
- // cstack->cs_exception, *all* calls to discard_current_exception() are
- // (and must be) guarded by current_exception check.
- current_exception = NULL;
} else {
/*
* If there is a preceding catch clause and it caught the exception,
@@ -1434,12 +1432,12 @@ void ex_catch(exarg_T *eap)
* a ":continue", ":break", ":return", or ":finish", discard the
* pending action.
*/
- cleanup_conditionals(cstack, CSF_TRY, TRUE);
+ cleanup_conditionals(cstack, CSF_TRY, true);
}
}
if (end != NULL) {
- eap->nextcmd = (char *)find_nextcmd((char_u *)end);
+ eap->nextcmd = find_nextcmd(end);
}
}
@@ -1447,7 +1445,7 @@ void ex_catch(exarg_T *eap)
void ex_finally(exarg_T *eap)
{
int idx;
- int skip = FALSE;
+ int skip = false;
int pending = CSTP_NONE;
cstack_T *const cstack = eap->cstack;
@@ -1456,7 +1454,7 @@ void ex_finally(exarg_T *eap)
} else {
if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) {
eap->errmsg = get_end_emsg(cstack);
- for (idx = cstack->cs_idx - 1; idx > 0; --idx) {
+ for (idx = cstack->cs_idx - 1; idx > 0; idx--) {
if (cstack->cs_flags[idx] & CSF_TRY) {
break;
}
@@ -1477,14 +1475,12 @@ void ex_finally(exarg_T *eap)
rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR,
&cstack->cs_looplevel);
- /*
- * Don't do something when the corresponding try block never got active
- * (because of an inactive surrounding conditional or after an error or
- * interrupt or throw) or for a ":finally" without ":try" or a multiple
- * ":finally". After every other error (did_emsg or the conditional
- * errors detected above) or after an interrupt (got_int) or an
- * exception (current_exception), the finally clause must be executed.
- */
+ // Don't do something when the corresponding try block never got active
+ // (because of an inactive surrounding conditional or after an error or
+ // interrupt or throw) or for a ":finally" without ":try" or a multiple
+ // ":finally". After every other error (did_emsg or the conditional
+ // errors detected above) or after an interrupt (got_int) or an
+ // exception (did_throw), the finally clause must be executed.
skip = !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE);
if (!skip) {
@@ -1507,24 +1503,22 @@ void ex_finally(exarg_T *eap)
* ":continue", ":break", ":finish", or ":return" from the preceding
* try block or catch clause.
*/
- cleanup_conditionals(cstack, CSF_TRY, FALSE);
-
- /*
- * Make did_emsg, got_int, current_exception pending. If set, they
- * overrule a pending ":continue", ":break", ":return", or ":finish".
- * Then we have particularly to discard a pending return value (as done
- * by the call to cleanup_conditionals() above when did_emsg or
- * got_int is set). The pending values are restored by the
- * ":endtry", except if there is a new error, interrupt, exception,
- * ":continue", ":break", ":return", or ":finish" in the following
- * finally clause. A missing ":endwhile", ":endfor" or ":endif"
- * detected here is treated as if did_emsg and current_exception had
- * already been set, respectively in case that the error is not
- * converted to an exception, current_exception had already been unset.
- * We must not set did_emsg here since that would suppress the
- * error message.
- */
- if (pending == CSTP_ERROR || did_emsg || got_int || current_exception) {
+ cleanup_conditionals(cstack, CSF_TRY, false);
+
+ // Make did_emsg, got_int, did_throw pending. If set, they overrule
+ // a pending ":continue", ":break", ":return", or ":finish". Then
+ // we have particularly to discard a pending return value (as done
+ // by the call to cleanup_conditionals() above when did_emsg or
+ // got_int is set). The pending values are restored by the
+ // ":endtry", except if there is a new error, interrupt, exception,
+ // ":continue", ":break", ":return", or ":finish" in the following
+ // finally clause. A missing ":endwhile", ":endfor" or ":endif"
+ // detected here is treated as if did_emsg and did_throw had
+ // already been set, respectively in case that the error is not
+ // converted to an exception, did_throw had already been unset.
+ // We must not set did_emsg here since that would suppress the
+ // error message.
+ if (pending == CSTP_ERROR || did_emsg || got_int || did_throw) {
if (cstack->cs_pending[cstack->cs_idx] == CSTP_RETURN) {
report_discard_pending(CSTP_RETURN,
cstack->cs_rettv[cstack->cs_idx]);
@@ -1533,7 +1527,7 @@ void ex_finally(exarg_T *eap)
if (pending == CSTP_ERROR && !did_emsg) {
pending |= (THROW_ON_ERROR ? CSTP_THROW : 0);
} else {
- pending |= (current_exception ? CSTP_THROW : 0);
+ pending |= (did_throw ? CSTP_THROW : 0);
}
pending |= did_emsg ? CSTP_ERROR : 0;
pending |= got_int ? CSTP_INTERRUPT : 0;
@@ -1547,19 +1541,16 @@ void ex_finally(exarg_T *eap)
// exception. When emsg() is called for a missing ":endif" or
// a missing ":endwhile"/":endfor" detected here, the
// exception will be discarded.
- if (current_exception
- && cstack->cs_exception[cstack->cs_idx] != current_exception) {
+ if (did_throw && cstack->cs_exception[cstack->cs_idx] != current_exception) {
internal_error("ex_finally()");
}
}
- /*
- * Set CSL_HAD_FINA, so do_cmdline() will reset did_emsg,
- * got_int, and current_exception and make the finally clause active.
- * This will happen after emsg() has been called for a missing
- * ":endif" or a missing ":endwhile"/":endfor" detected here, so
- * that the following finally clause will be executed even then.
- */
+ // Set CSL_HAD_FINA, so do_cmdline() will reset did_emsg,
+ // got_int, and did_throw and make the finally clause active.
+ // This will happen after emsg() has been called for a missing
+ // ":endif" or a missing ":endwhile"/":endfor" detected here, so
+ // that the following finally clause will be executed even then.
cstack->cs_lflags |= CSL_HAD_FINA;
}
}
@@ -1587,8 +1578,7 @@ void ex_endtry(exarg_T *eap)
// made inactive by a ":continue", ":break", ":return", or ":finish" in
// the finally clause. The latter case need not be tested since then
// anything pending has already been discarded.
- bool skip = did_emsg || got_int || current_exception
- || !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE);
+ bool skip = did_emsg || got_int || did_throw || !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE);
if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) {
eap->errmsg = get_end_emsg(cstack);
@@ -1602,14 +1592,12 @@ void ex_endtry(exarg_T *eap)
&cstack->cs_looplevel);
skip = true;
- /*
- * If an exception is being thrown, discard it to prevent it from
- * being rethrown at the end of this function. It would be
- * discarded by the error message, anyway. Resets current_exception.
- * This does not affect the script termination due to the error
- * since "trylevel" is decremented after emsg() has been called.
- */
- if (current_exception) {
+ // If an exception is being thrown, discard it to prevent it from
+ // being rethrown at the end of this function. It would be
+ // discarded by the error message, anyway. Resets did_throw.
+ // This does not affect the script termination due to the error
+ // since "trylevel" is decremented after emsg() has been called.
+ if (did_throw) {
discard_current_exception();
}
@@ -1624,7 +1612,7 @@ void ex_endtry(exarg_T *eap)
* a finally clause, we need to rethrow it after closing the try
* conditional.
*/
- if (current_exception
+ if (did_throw
&& (cstack->cs_flags[idx] & CSF_TRUE)
&& !(cstack->cs_flags[idx] & CSF_FINALLY)) {
rethrow = true;
@@ -1648,10 +1636,10 @@ void ex_endtry(exarg_T *eap)
if (got_int) {
skip = true;
(void)do_intthrow(cstack);
- // The do_intthrow() call may have reset current_exception or
+ // The do_intthrow() call may have reset did_throw or
// cstack->cs_pending[idx].
rethrow = false;
- if (current_exception && !(cstack->cs_flags[idx] & CSF_FINALLY)) {
+ if (did_throw && !(cstack->cs_flags[idx] & CSF_FINALLY)) {
rethrow = true;
}
}
@@ -1683,7 +1671,7 @@ void ex_endtry(exarg_T *eap)
* after errors except when this ":endtry" is not within a ":try".
* Restore "emsg_silent" if it has been reset by this try conditional.
*/
- (void)cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, TRUE);
+ (void)cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, true);
if (cstack->cs_idx >= 0 && (cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) {
cstack->cs_idx--;
@@ -1712,16 +1700,16 @@ void ex_endtry(exarg_T *eap)
ex_break(eap);
break;
case CSTP_RETURN:
- do_return(eap, FALSE, FALSE, rettv);
+ do_return(eap, false, false, rettv);
break;
case CSTP_FINISH:
- do_finish(eap, FALSE);
+ do_finish(eap, false);
break;
// When the finally clause was entered due to an error,
// interrupt or throw (as opposed to a ":continue", ":break",
// ":return", or ":finish"), restore the pending values of
- // did_emsg, got_int, and current_exception. This is skipped, if there
+ // did_emsg, got_int, and did_throw. This is skipped, if there
// was a new error, interrupt, throw, ":continue", ":break",
// ":return", or ":finish". in the finally clause.
default:
@@ -1768,35 +1756,32 @@ void enter_cleanup(cleanup_T *csp)
{
int pending = CSTP_NONE;
- /*
- * Postpone did_emsg, got_int, current_exception. The pending values will be
- * restored by leave_cleanup() except if there was an aborting error,
- * interrupt, or uncaught exception after this function ends.
- */
- if (did_emsg || got_int || current_exception || need_rethrow) {
+ // Postpone did_emsg, got_int, did_throw. The pending values will be
+ // restored by leave_cleanup() except if there was an aborting error,
+ // interrupt, or uncaught exception after this function ends.
+ if (did_emsg || got_int || did_throw || need_rethrow) {
csp->pending = (did_emsg ? CSTP_ERROR : 0)
| (got_int ? CSTP_INTERRUPT : 0)
- | (current_exception ? CSTP_THROW : 0)
+ | (did_throw ? CSTP_THROW : 0)
| (need_rethrow ? CSTP_THROW : 0);
- // If we are currently throwing an exception, save it as well. On an error
- // not yet converted to an exception, update "force_abort" and reset
- // "cause_abort" (as do_errthrow() would do). This is needed for the
- // do_cmdline() call that is going to be made for autocommand execution. We
- // need not save *msg_list because there is an extra instance for every call
- // of do_cmdline(), anyway.
- if (current_exception || need_rethrow) {
+ // If we are currently throwing an exception (did_throw), save it as
+ // well. On an error not yet converted to an exception, update
+ // "force_abort" and reset "cause_abort" (as do_errthrow() would do).
+ // This is needed for the do_cmdline() call that is going to be made
+ // for autocommand execution. We need not save *msg_list because
+ // there is an extra instance for every call of do_cmdline(), anyway.
+ if (did_throw || need_rethrow) {
csp->exception = current_exception;
current_exception = NULL;
} else {
csp->exception = NULL;
if (did_emsg) {
force_abort |= cause_abort;
- cause_abort = FALSE;
+ cause_abort = false;
}
}
- did_emsg = got_int = need_rethrow = false;
- current_exception = NULL;
+ did_emsg = got_int = did_throw = need_rethrow = false;
// Report if required by the 'verbose' option or when debugging.
report_make_pending(pending, csp->exception);
@@ -1863,10 +1848,10 @@ void leave_cleanup(cleanup_T *csp)
// enter_cleanup() was called, let "cause_abort" take the part of
// "force_abort" (as done by cause_errthrow()).
cause_abort = force_abort;
- force_abort = FALSE;
+ force_abort = false;
}
- // Restore the pending values of did_emsg, got_int, and current_exception.
+ // Restore the pending values of did_emsg, got_int, and did_throw.
if (pending & CSTP_ERROR) {
did_emsg = true;
}
@@ -1874,7 +1859,7 @@ void leave_cleanup(cleanup_T *csp)
got_int = true;
}
if (pending & CSTP_THROW) {
- need_rethrow = true; // current_exception will be set by do_one_cmd()
+ need_rethrow = true; // did_throw will be set by do_one_cmd()
}
// Report if required by the 'verbose' option or when debugging.
@@ -1895,7 +1880,7 @@ void leave_cleanup(cleanup_T *csp)
/// inactive itself (a try conditional not in its finally
/// clause possibly find before is always made inactive).
///
-/// If "inclusive" is TRUE and "searched_cond" is CSF_TRY|CSF_SILENT, the saved
+/// If "inclusive" is true and "searched_cond" is CSF_TRY|CSF_SILENT, the saved
/// former value of "emsg_silent", if reset when the try conditional finally
/// reached was entered, is restored (used by ex_endtry()). This is normally
/// done only when such a try conditional is left.
@@ -1904,9 +1889,9 @@ void leave_cleanup(cleanup_T *csp)
int cleanup_conditionals(cstack_T *cstack, int searched_cond, int inclusive)
{
int idx;
- int stop = FALSE;
+ int stop = false;
- for (idx = cstack->cs_idx; idx >= 0; --idx) {
+ for (idx = cstack->cs_idx; idx >= 0; idx--) {
if (cstack->cs_flags[idx] & CSF_TRY) {
/*
* Discard anything pending in a finally clause and continue the
@@ -1968,20 +1953,20 @@ int cleanup_conditionals(cstack_T *cstack, int searched_cond, int inclusive)
if (searched_cond == 0 && !inclusive) {
break;
}
- stop = TRUE;
+ stop = true;
}
}
}
// Stop on the searched conditional type (even when the surrounding
// conditional is not active or something has been made pending).
- // If "inclusive" is TRUE and "searched_cond" is CSF_TRY|CSF_SILENT,
+ // If "inclusive" is true and "searched_cond" is CSF_TRY|CSF_SILENT,
// check first whether "emsg_silent" needs to be restored.
if (cstack->cs_flags[idx] & searched_cond) {
if (!inclusive) {
break;
}
- stop = TRUE;
+ stop = true;
}
cstack->cs_flags[idx] &= ~CSF_ACTIVE;
if (stop && searched_cond != (CSF_TRY | CSF_SILENT)) {
@@ -2036,7 +2021,7 @@ void rewind_conditionals(cstack_T *cstack, int idx, int cond_type, int *cond_lev
if (cstack->cs_flags[cstack->cs_idx] & CSF_FOR) {
free_for_info(cstack->cs_forinfo[cstack->cs_idx]);
}
- --cstack->cs_idx;
+ cstack->cs_idx--;
}
}
@@ -2046,7 +2031,7 @@ void ex_endfunction(exarg_T *eap)
emsg(_("E193: :endfunction not inside a function"));
}
-/// @return TRUE if the string "p" looks like a ":while" or ":for" command.
+/// @return true if the string "p" looks like a ":while" or ":for" command.
int has_loop_cmd(char *p)
{
int len;
@@ -2064,7 +2049,7 @@ int has_loop_cmd(char *p)
}
if ((p[0] == 'w' && p[1] == 'h')
|| (p[0] == 'f' && p[1] == 'o' && p[2] == 'r')) {
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index a0bcccb5be..0998bdd867 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -105,8 +105,8 @@ typedef struct command_line_state {
long count;
int indent;
int c;
- int gotesc; // TRUE when <ESC> just typed
- int do_abbr; // when TRUE check for abbr.
+ int gotesc; // true when <ESC> just typed
+ int do_abbr; // when true check for abbr.
char_u *lookfor; // string to match
int hiscnt; // current history line in use
int save_hiscnt; // history line before attempting
@@ -170,6 +170,8 @@ static Array cmdline_block = ARRAY_DICT_INIT;
/// user interrupting highlight function to not interrupt command-line.
static bool getln_interrupted_highlight = false;
+static int cedit_key = -1; ///< key value of 'cedit' option
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ex_getln.c.generated.h"
#endif
@@ -313,7 +315,7 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s
p = skipwhite(p);
delim = (delim_optional && vim_isIDc(*p)) ? ' ' : *p++;
*search_delim = delim;
- end = (char *)skip_regexp((char_u *)p, delim, p_magic, NULL);
+ end = skip_regexp(p, delim, p_magic, NULL);
use_last_pat = end == p && *end == delim;
if (end == p && !use_last_pat) {
@@ -415,7 +417,7 @@ static void may_do_incsearch_highlighting(int firstc, long count, incsearch_stat
if (patlen == 0 && !use_last_pat) {
found = 0;
set_no_hlsearch(true); // turn off previous highlight
- redraw_all_later(SOME_VALID);
+ redraw_all_later(UPD_SOME_VALID);
} else {
int search_flags = SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK;
ui_busy_start();
@@ -488,7 +490,7 @@ static void may_do_incsearch_highlighting(int firstc, long count, incsearch_stat
next_char = ccline.cmdbuff[skiplen + patlen];
ccline.cmdbuff[skiplen + patlen] = NUL;
if (empty_pattern(ccline.cmdbuff) && !no_hlsearch) {
- redraw_all_later(SOME_VALID);
+ redraw_all_later(UPD_SOME_VALID);
set_no_hlsearch(true);
}
ccline.cmdbuff[skiplen + patlen] = next_char;
@@ -500,7 +502,7 @@ static void may_do_incsearch_highlighting(int firstc, long count, incsearch_stat
curwin->w_redr_status = true;
}
- update_screen(SOME_VALID);
+ update_screen(UPD_SOME_VALID);
highlight_match = false;
restore_last_search_pattern();
@@ -585,9 +587,9 @@ static void finish_incsearch_highlighting(int gotesc, incsearch_state_T *s, bool
p_magic = s->magic_save;
validate_cursor(); // needed for TAB
- redraw_all_later(SOME_VALID);
+ redraw_all_later(UPD_SOME_VALID);
if (call_update_screen) {
- update_screen(SOME_VALID);
+ update_screen(UPD_SOME_VALID);
}
}
}
@@ -611,7 +613,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool init
lastwin->w_p_so = 0;
set_option_value("ch", 1L, NULL, 0);
- update_screen(VALID); // redraw the screen NOW
+ update_screen(UPD_VALID); // redraw the screen NOW
made_cmdheight_nonzero = false;
lastwin->w_p_so = save_so;
@@ -632,7 +634,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool init
.ignore_drag_release = true,
};
CommandLineState *s = &state;
- s->save_p_icm = vim_strsave(p_icm);
+ s->save_p_icm = vim_strsave((char_u *)p_icm);
init_incsearch_state(&s->is_state);
CmdlineInfo save_ccline;
bool did_save_ccline = false;
@@ -852,7 +854,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool init
s->histype == HIST_SEARCH ? s->firstc : NUL);
if (s->firstc == ':') {
xfree(new_last_cmdline);
- new_last_cmdline = vim_strsave(ccline.cmdbuff);
+ new_last_cmdline = (char *)vim_strsave(ccline.cmdbuff);
}
}
@@ -883,7 +885,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool init
State = s->save_State;
if (cmdpreview != save_cmdpreview) {
cmdpreview = save_cmdpreview; // restore preview state
- redraw_all_later(SOME_VALID);
+ redraw_all_later(UPD_SOME_VALID);
}
may_trigger_modechanged();
setmouse();
@@ -916,7 +918,7 @@ theend:
// Restore cmdheight
set_option_value("ch", 0L, NULL, 0);
// Redraw is needed for command line completion
- redraw_all_later(CLEAR);
+ redraw_all_later(UPD_NOT_VALID);
made_cmdheight_nonzero = false;
}
@@ -1260,7 +1262,7 @@ static int command_line_execute(VimState *state, int key)
}
if (s->wim_index < 3) {
- ++s->wim_index;
+ s->wim_index++;
}
if (s->c == ESC) {
@@ -1277,8 +1279,11 @@ static int command_line_execute(VimState *state, int key)
// <S-Tab> goes to last match, in a clumsy way
if (s->c == K_S_TAB && KeyTyped) {
if (nextwild(&s->xpc, WILD_EXPAND_KEEP, 0, s->firstc != '@') == OK) {
- // Trigger the popup menu when wildoptions=pum
- showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0));
+ if (s->xpc.xp_numfiles > 1
+ && ((!s->did_wild_list && (wim_flags[s->wim_index] & WIM_LIST)) || p_wmnu)) {
+ // Trigger the popup menu when wildoptions=pum
+ showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0));
+ }
nextwild(&s->xpc, WILD_PREV, 0, s->firstc != '@');
nextwild(&s->xpc, WILD_PREV, 0, s->firstc != '@');
return command_line_changed(s);
@@ -1395,7 +1400,7 @@ static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_
validate_cursor();
highlight_match = true;
save_viewstate(curwin, &s->old_viewstate);
- update_screen(NOT_VALID);
+ update_screen(UPD_NOT_VALID);
highlight_match = false;
redrawcmdline();
curwin->w_cursor = s->match_end;
@@ -1474,7 +1479,7 @@ static int command_line_handle_key(CommandLineState *s)
// delete current character is the same as backspace on next
// character, except at end of line
if (s->c == K_DEL && ccline.cmdpos != ccline.cmdlen) {
- ++ccline.cmdpos;
+ ccline.cmdpos++;
}
if (s->c == K_DEL) {
@@ -1798,13 +1803,17 @@ static int command_line_handle_key(CommandLineState *s)
return command_line_not_changed(s);
case Ctrl_A: // all matches
- if (nextwild(&s->xpc, WILD_ALL, 0, s->firstc != '@') == FAIL) {
- break;
- }
if (cmdline_pum_active()) {
+ // As Ctrl-A completes all the matches, close the popup
+ // menu (if present)
cmdline_pum_cleanup(&ccline);
- s->xpc.xp_context = EXPAND_NOTHING;
}
+
+ if (nextwild(&s->xpc, WILD_ALL, 0, s->firstc != '@') == FAIL) {
+ break;
+ }
+ s->xpc.xp_context = EXPAND_NOTHING;
+ s->did_wild_list = false;
return command_line_changed(s);
case Ctrl_L:
@@ -2343,7 +2352,7 @@ static bool cmdpreview_may_show(CommandLineState *s)
if (cmdpreview_type != 0) {
int save_rd = RedrawingDisabled;
RedrawingDisabled = 0;
- update_screen(SOME_VALID);
+ update_screen(UPD_SOME_VALID);
RedrawingDisabled = save_rd;
}
@@ -2364,9 +2373,9 @@ end:
return cmdpreview_type != 0;
}
-static int command_line_changed(CommandLineState *s)
+/// Trigger CmdlineChanged autocommands.
+static void do_autocmd_cmdlinechanged(int firstc)
{
- // Trigger CmdlineChanged autocommands.
if (has_event(EVENT_CMDLINECHANGED)) {
TryState tstate;
Error err = ERROR_INIT;
@@ -2374,7 +2383,7 @@ static int command_line_changed(CommandLineState *s)
dict_T *dict = get_v_event(&save_v_event);
char firstcbuf[2];
- firstcbuf[0] = (char)(s->firstc > 0 ? s->firstc : '-');
+ firstcbuf[0] = (char)firstc;
firstcbuf[1] = 0;
// set v:event to a dictionary with information about the commandline
@@ -2394,6 +2403,12 @@ static int command_line_changed(CommandLineState *s)
redrawcmd();
}
}
+}
+
+static int command_line_changed(CommandLineState *s)
+{
+ // Trigger CmdlineChanged autocommands.
+ do_autocmd_cmdlinechanged(s->firstc > 0 ? s->firstc : '-');
if (s->firstc == ':'
&& current_sctx.sc_sid == 0 // only if interactive
@@ -2405,7 +2420,7 @@ static int command_line_changed(CommandLineState *s)
// 'inccommand' preview has been shown.
} else if (cmdpreview) {
cmdpreview = false;
- update_screen(SOME_VALID); // Clear 'inccommand' preview.
+ update_screen(UPD_SOME_VALID); // Clear 'inccommand' preview.
} else {
if (s->xpc.xp_context == EXPAND_NOTHING && (KeyTyped || vpeekc() == NUL)) {
may_do_incsearch_highlighting(s->firstc, s->count, &s->is_state);
@@ -2526,6 +2541,58 @@ char_u *get_cmdprompt(void)
return ccline.cmdprompt;
}
+/// Read the 'wildmode' option, fill wim_flags[].
+int check_opt_wim(void)
+{
+ char_u new_wim_flags[4];
+ int i;
+ int idx = 0;
+
+ for (i = 0; i < 4; i++) {
+ new_wim_flags[i] = 0;
+ }
+
+ for (char *p = p_wim; *p; p++) {
+ for (i = 0; ASCII_ISALPHA(p[i]); i++) {}
+ if (p[i] != NUL && p[i] != ',' && p[i] != ':') {
+ return FAIL;
+ }
+ if (i == 7 && STRNCMP(p, "longest", 7) == 0) {
+ new_wim_flags[idx] |= WIM_LONGEST;
+ } else if (i == 4 && STRNCMP(p, "full", 4) == 0) {
+ new_wim_flags[idx] |= WIM_FULL;
+ } else if (i == 4 && STRNCMP(p, "list", 4) == 0) {
+ new_wim_flags[idx] |= WIM_LIST;
+ } else if (i == 8 && STRNCMP(p, "lastused", 8) == 0) {
+ new_wim_flags[idx] |= WIM_BUFLASTUSED;
+ } else {
+ return FAIL;
+ }
+ p += i;
+ if (*p == NUL) {
+ break;
+ }
+ if (*p == ',') {
+ if (idx == 3) {
+ return FAIL;
+ }
+ idx++;
+ }
+ }
+
+ // fill remaining entries with last flag
+ while (idx < 3) {
+ new_wim_flags[idx + 1] = new_wim_flags[idx];
+ idx++;
+ }
+
+ // only when there are no errors, wim_flags[] is changed
+ for (i = 0; i < 4; i++) {
+ wim_flags[i] = new_wim_flags[i];
+ }
+ return OK;
+}
+
/// Return true when the text must not be changed and we can't switch to
/// another window or buffer. True when editing the command line etc.
bool text_locked(void)
@@ -3023,7 +3090,7 @@ color_cmdline_error:
/*
* Draw part of the cmdline at the current cursor position. But draw stars
- * when cmdline_star is TRUE.
+ * when cmdline_star is true.
*/
static void draw_cmdline(int start, int len)
{
@@ -3131,7 +3198,7 @@ static void draw_cmdline(int start, int len)
}
}
- msg_outtrans_len((char_u *)arshape_buf, newlen);
+ msg_outtrans_len(arshape_buf, newlen);
} else {
draw_cmdline_no_arabicshape:
if (kv_size(ccline.last_colors.colors)) {
@@ -3146,7 +3213,7 @@ draw_cmdline_no_arabicshape:
chunk.attr);
}
} else {
- msg_outtrans_len(ccline.cmdbuff + start, len);
+ msg_outtrans_len((char *)ccline.cmdbuff + start, len);
}
}
}
@@ -3154,7 +3221,6 @@ draw_cmdline_no_arabicshape:
static void ui_ext_cmdline_show(CmdlineInfo *line)
{
Arena arena = ARENA_EMPTY;
- arena_start(&arena, &ui_ext_fixblk);
Array content;
if (cmdline_star) {
content = arena_array(&arena, 1);
@@ -3199,7 +3265,7 @@ static void ui_ext_cmdline_show(CmdlineInfo *line)
line->special_shift,
line->level);
}
- arena_mem_free(arena_finish(&arena), &ui_ext_fixblk);
+ arena_mem_free(arena_finish(&arena));
}
void ui_ext_cmdline_block_append(size_t indent, const char *line)
@@ -3278,7 +3344,7 @@ void cmdline_ui_flush(void)
/*
* Put a character on the command line. Shifts the following text to the
- * right when "shift" is TRUE. Used for CTRL-V, CTRL-K, etc.
+ * right when "shift" is true. Used for CTRL-V, CTRL-K, etc.
* "c" must be printable (fit in one display cell)!
*/
void putcmdline(char c, int shift)
@@ -3304,7 +3370,7 @@ void putcmdline(char c, int shift)
ui_cursor_shape();
}
-/// Undo a putcmdline(c, FALSE).
+/// Undo a putcmdline(c, false).
void unputcmdline(void)
{
if (cmd_silent) {
@@ -3325,9 +3391,9 @@ void unputcmdline(void)
/*
* Put the given string, of the given length, onto the command line.
* If len is -1, then STRLEN() is used to calculate the length.
- * If 'redraw' is TRUE then the new part of the command line, and the remaining
+ * If 'redraw' is true then the new part of the command line, and the remaining
* part will be redrawn, otherwise it will not. If this function is called
- * twice in a row, then 'redraw' should be FALSE and redrawcmd() should be
+ * twice in a row, then 'redraw' should be false and redrawcmd() should be
* called afterwards.
*/
void put_on_cmdline(char_u *str, int len, int redraw)
@@ -3404,7 +3470,7 @@ void put_on_cmdline(char_u *str, int len, int redraw)
}
if (redraw && !cmd_silent) {
- msg_no_more = TRUE;
+ msg_no_more = true;
i = cmdline_row;
cursorcmd();
draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos);
@@ -3412,7 +3478,7 @@ void put_on_cmdline(char_u *str, int len, int redraw)
if (cmdline_row != i || ccline.overstrike) {
msg_clr_eos();
}
- msg_no_more = FALSE;
+ msg_no_more = false;
}
if (KeyTyped) {
m = Columns * Rows;
@@ -3539,8 +3605,8 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
/*
* Put a string on the command line.
- * When "literally" is TRUE, insert literally.
- * When "literally" is FALSE, insert as typed, but don't leave the command
+ * When "literally" is true, insert literally.
+ * When "literally" is false, insert as typed, but don't leave the command
* line.
*/
void cmdline_paste_str(char_u *s, int literally)
@@ -3548,7 +3614,7 @@ void cmdline_paste_str(char_u *s, int literally)
int c, cv;
if (literally) {
- put_on_cmdline(s, -1, TRUE);
+ put_on_cmdline(s, -1, true);
} else {
while (*s != NUL) {
cv = *s;
@@ -3637,7 +3703,7 @@ void redrawcmd(void)
redrawcmdprompt();
// Don't use more prompt, truncate the cmdline if it doesn't fit.
- msg_no_more = TRUE;
+ msg_no_more = true;
draw_cmdline(0, ccline.cmdlen);
msg_clr_eos();
msg_no_more = false;
@@ -3652,7 +3718,7 @@ void redrawcmd(void)
* An emsg() before may have set msg_scroll. This is used in normal mode,
* in cmdline mode we can reset them now.
*/
- msg_scroll = FALSE; // next message overwrites cmdline
+ msg_scroll = false; // next message overwrites cmdline
// Typing ':' at the more prompt may set skip_redraw. We don't want this
// in cmdline mode.
@@ -3867,8 +3933,41 @@ static CmdlineInfo *get_ccline_ptr(void)
}
}
+/// Get the current command-line type.
+/// Returns ':' or '/' or '?' or '@' or '>' or '-'
+/// Only works when the command line is being edited.
+/// Returns NUL when something is wrong.
+static int get_cmdline_type(void)
+{
+ CmdlineInfo *p = get_ccline_ptr();
+
+ if (p == NULL) {
+ return NUL;
+ }
+ if (p->cmdfirstc == NUL) {
+ return (p->input_fn) ? '@' : '-';
+ }
+ return p->cmdfirstc;
+}
+
+/// Get the current command line in allocated memory.
+/// Only works when the command line is being edited.
+/// Returns NULL when something is wrong.
+static char_u *get_cmdline_str(void)
+{
+ if (cmdline_star > 0) {
+ return NULL;
+ }
+ CmdlineInfo *p = get_ccline_ptr();
+
+ if (p == NULL) {
+ return NULL;
+ }
+ return vim_strnsave(p->cmdbuff, (size_t)p->cmdlen);
+}
+
/// Get the current command-line completion type.
-char_u *get_cmdline_completion(void)
+static char_u *get_cmdline_completion(void)
{
if (cmdline_star > 0) {
return NULL;
@@ -3886,57 +3985,72 @@ char_u *get_cmdline_completion(void)
return NULL;
}
-/*
- * Get the current command line in allocated memory.
- * Only works when the command line is being edited.
- * Returns NULL when something is wrong.
- */
-char_u *get_cmdline_str(void)
+/// "getcmdcompltype()" function
+void f_getcmdcompltype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- if (cmdline_star > 0) {
- return NULL;
- }
- CmdlineInfo *p = get_ccline_ptr();
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = (char *)get_cmdline_completion();
+}
- if (p == NULL) {
- return NULL;
- }
- return vim_strnsave(p->cmdbuff, (size_t)p->cmdlen);
+/// "getcmdline()" function
+void f_getcmdline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
+{
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = (char *)get_cmdline_str();
}
-/*
- * Get the current command line position, counted in bytes.
- * Zero is the first position.
- * Only works when the command line is being edited.
- * Returns -1 when something is wrong.
- */
-int get_cmdline_pos(void)
+/// "getcmdpos()" function
+void f_getcmdpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
CmdlineInfo *p = get_ccline_ptr();
+ rettv->vval.v_number = p != NULL ? p->cmdpos + 1 : 0;
+}
- if (p == NULL) {
- return -1;
- }
- return p->cmdpos;
+/// "getcmdscreenpos()" function
+void f_getcmdscreenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
+{
+ CmdlineInfo *p = get_ccline_ptr();
+ rettv->vval.v_number = p != NULL ? p->cmdspos + 1 : 0;
}
-/// Get the command line cursor screen position.
-int get_cmdline_screen_pos(void)
+/// "getcmdtype()" function
+void f_getcmdtype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
+{
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = xmallocz(1);
+ rettv->vval.v_string[0] = (char)get_cmdline_type();
+}
+
+/// Set the command line str to "str".
+/// @return 1 when failed, 0 when OK.
+static int set_cmdline_str(const char *str, int pos)
{
CmdlineInfo *p = get_ccline_ptr();
if (p == NULL) {
- return -1;
+ return 1;
}
- return p->cmdspos;
+
+ int len = (int)STRLEN(str);
+ realloc_cmdbuff(len + 1);
+ p->cmdlen = len;
+ STRCPY(p->cmdbuff, str);
+
+ p->cmdpos = pos < 0 || pos > p->cmdlen ? p->cmdlen : pos;
+ new_cmdpos = p->cmdpos;
+
+ redrawcmd();
+
+ // Trigger CmdlineChanged autocommands.
+ do_autocmd_cmdlinechanged(get_cmdline_type());
+
+ return 0;
}
-/*
- * Set the command line byte position to "pos". Zero is the first position.
- * Only works when the command line is being edited.
- * Returns 1 when failed, 0 when OK.
- */
-int set_cmdline_pos(int pos)
+/// Set the command line byte position to "pos". Zero is the first position.
+/// Only works when the command line is being edited.
+/// @return 1 when failed, 0 when OK.
+static int set_cmdline_pos(int pos)
{
CmdlineInfo *p = get_ccline_ptr();
@@ -3954,23 +4068,39 @@ int set_cmdline_pos(int pos)
return 0;
}
-/*
- * Get the current command-line type.
- * Returns ':' or '/' or '?' or '@' or '>' or '-'
- * Only works when the command line is being edited.
- * Returns NUL when something is wrong.
- */
-int get_cmdline_type(void)
+/// "setcmdline()" function
+void f_setcmdline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- CmdlineInfo *p = get_ccline_ptr();
+ if (argvars[0].v_type != VAR_STRING || argvars[0].vval.v_string == NULL) {
+ emsg(_(e_stringreq));
+ return;
+ }
- if (p == NULL) {
- return NUL;
+ int pos = -1;
+ if (argvars[1].v_type != VAR_UNKNOWN) {
+ bool error = false;
+
+ pos = (int)tv_get_number_chk(&argvars[1], &error) - 1;
+ if (error) {
+ return;
+ }
+ if (pos < 0) {
+ emsg(_(e_positive));
+ return;
+ }
}
- if (p->cmdfirstc == NUL) {
- return (p->input_fn) ? '@' : '-';
+
+ rettv->vval.v_number = set_cmdline_str(argvars[0].vval.v_string, pos);
+}
+
+/// "setcmdpos()" function
+void f_setcmdpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
+{
+ const int pos = (int)tv_get_number(&argvars[0]) - 1;
+
+ if (pos >= 0) {
+ rettv->vval.v_number = set_cmdline_pos(pos);
}
- return p->cmdfirstc;
}
/// Return the first character of the current command line.
@@ -4021,6 +4151,24 @@ void cmdline_init(void)
CLEAR_FIELD(ccline);
}
+/// Check value of 'cedit' and set cedit_key.
+/// Returns NULL if value is OK, error message otherwise.
+char *check_cedit(void)
+{
+ int n;
+
+ if (*p_cedit == NUL) {
+ cedit_key = -1;
+ } else {
+ n = string_to_key((char_u *)p_cedit);
+ if (vim_isprintc(n)) {
+ return e_invarg;
+ }
+ cedit_key = n;
+ }
+ return NULL;
+}
+
/// Open a window on the current command line and history. Allow editing in
/// the window. Returns when the window is closed.
/// Returns:
@@ -4068,17 +4216,27 @@ static int open_cmdwin(void)
ga_clear(&winsizes);
return K_IGNORE;
}
+ // Don't let quitting the More prompt make this fail.
+ got_int = false;
+
+ // Set "cmdwin_type" before any autocommands may mess things up.
cmdwin_type = get_cmdline_type();
cmdwin_level = ccline.level;
// Create empty command-line buffer.
- buf_open_scratch(0, _("[Command Line]"));
+ if (buf_open_scratch(0, _("[Command Line]")) == FAIL) {
+ // Some autocommand messed it up?
+ win_close(curwin, true, false);
+ ga_clear(&winsizes);
+ cmdwin_type = 0;
+ return Ctrl_C;
+ }
// Command-line buffer has bufhidden=wipe, unlike a true "scratch" buffer.
- set_option_value("bh", 0L, "wipe", OPT_LOCAL);
- curwin->w_p_rl = cmdmsg_rl;
- cmdmsg_rl = false;
+ set_option_value_give_err("bh", 0L, "wipe", OPT_LOCAL);
curbuf->b_p_ma = true;
curwin->w_p_fen = false;
+ curwin->w_p_rl = cmdmsg_rl;
+ cmdmsg_rl = false;
// Don't allow switching to another buffer.
curbuf->b_ro_locked++;
@@ -4092,7 +4250,7 @@ static int open_cmdwin(void)
add_map("<Tab>", "<C-X><C-V>", MODE_INSERT, true);
add_map("<Tab>", "a<C-X><C-V>", MODE_NORMAL, true);
}
- set_option_value("ft", 0L, "vim", OPT_LOCAL);
+ set_option_value_give_err("ft", 0L, "vim", OPT_LOCAL);
}
curbuf->b_ro_locked--;
@@ -4128,7 +4286,7 @@ static int open_cmdwin(void)
ccline.redraw_state = kCmdRedrawNone;
ui_call_cmdline_hide(ccline.level);
}
- redraw_later(curwin, SOME_VALID);
+ redraw_later(curwin, UPD_SOME_VALID);
// No Ex mode here!
exmode_active = false;
diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c
index 9495ae1c4b..e907c45e79 100644
--- a/src/nvim/ex_session.c
+++ b/src/nvim/ex_session.c
@@ -359,7 +359,7 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr
// Then ":help" will re-use both the buffer and the window and set
// the options, even when "options" is not in 'sessionoptions'.
if (0 < wp->w_tagstackidx && wp->w_tagstackidx <= wp->w_tagstacklen) {
- curtag = (char *)wp->w_tagstack[wp->w_tagstackidx - 1].tagname;
+ curtag = wp->w_tagstack[wp->w_tagstackidx - 1].tagname;
}
if (put_line(fd, "enew | setl bt=help") == FAIL
@@ -956,7 +956,7 @@ void ex_mkrc(exarg_T *eap)
}
// When using 'viewdir' may have to create the directory.
- if (using_vdir && !os_isdir(p_vdir)) {
+ if (using_vdir && !os_isdir((char *)p_vdir)) {
vim_mkdir_emsg((const char *)p_vdir, 0755);
}
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index 1639f72990..8e780f4aaa 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -510,11 +510,11 @@ void extmark_adjust(buf_T *buf, linenr_T line1, linenr_T line2, linenr_T amount,
bcount_t old_byte = 0, new_byte = 0;
int old_row, new_row;
if (amount == MAXLNUM) {
- old_row = (int)(line2 - line1 + 1);
+ old_row = line2 - line1 + 1;
// TODO(bfredl): ej kasta?
old_byte = (bcount_t)buf->deleted_bytes2;
- new_row = (int)(amount_after + old_row);
+ new_row = amount_after + old_row;
} else {
// A region is either deleted (amount == MAXLNUM) or
// added (line2 == MAXLNUM). The only other case is :move
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index 2d09e7aa71..bbc6e53aa8 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -110,16 +110,15 @@ typedef struct ff_stack {
typedef struct ff_visited {
struct ff_visited *ffv_next;
- /* Visited directories are different if the wildcard string are
- * different. So we have to save it.
- */
+ // Visited directories are different if the wildcard string are
+ // different. So we have to save it.
char_u *ffv_wc_path;
+
// use FileID for comparison (needed because of links), else use filename.
bool file_id_valid;
FileID file_id;
- /* The memory for this struct is allocated according to the length of
- * ffv_fname.
- */
+ // The memory for this struct is allocated according to the length of
+ // ffv_fname.
char_u ffv_fname[1]; // actually longer
} ff_visited_T;
@@ -221,8 +220,8 @@ static char_u e_pathtoolong[] = N_("E854: path too long for completion");
///
/// Upward search is only done on the starting dir.
///
-/// If 'free_visited' is TRUE the list of already visited files/directories is
-/// cleared. Set this to FALSE if you just want to search from another
+/// If 'free_visited' is true the list of already visited files/directories is
+/// cleared. Set this to false if you just want to search from another
/// directory, but want to be sure that no directory from a previous search is
/// searched again. This is useful if you search for a file at different places.
/// The list of visited files/dirs can also be cleared with the function
@@ -269,7 +268,7 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
ff_clear(search_ctx);
// clear visited list if wanted
- if (free_visited == TRUE) {
+ if (free_visited == true) {
vim_findfile_free_visited(search_ctx);
} else {
/* Reuse old visited lists. Get the visited list for the given
@@ -302,7 +301,7 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
if (!vim_isAbsName(rel_fname) && len + 1 < MAXPATHL) {
// Make the start dir an absolute path name.
STRLCPY(ff_expand_buffer, rel_fname, len + 1);
- search_ctx->ffsc_start_dir = (char_u *)FullName_save((char *)ff_expand_buffer, FALSE);
+ search_ctx->ffsc_start_dir = (char_u *)FullName_save((char *)ff_expand_buffer, false);
} else {
search_ctx->ffsc_start_dir = vim_strnsave(rel_fname, len);
}
@@ -472,7 +471,7 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
STRCPY(buf, ff_expand_buffer);
STRCPY(buf + eb_len, search_ctx->ffsc_fix_path);
- if (os_isdir(buf)) {
+ if (os_isdir((char *)buf)) {
STRCAT(ff_expand_buffer, search_ctx->ffsc_fix_path);
add_pathsep((char *)ff_expand_buffer);
} else {
@@ -510,9 +509,7 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
xfree(buf);
}
- sptr = ff_create_stack_element(ff_expand_buffer,
- search_ctx->ffsc_wc_path,
- level, 0);
+ sptr = ff_create_stack_element(ff_expand_buffer, search_ctx->ffsc_wc_path, level, 0);
ff_push(search_ctx, sptr);
search_ctx->ffsc_file_to_search = vim_strsave(filename);
@@ -641,11 +638,8 @@ char_u *vim_findfile(void *search_ctx_arg)
* first time (hence stackp->ff_filearray == NULL)
*/
if (stackp->ffs_filearray == NULL
- && ff_check_visited(&search_ctx->ffsc_dir_visited_list
- ->ffvl_visited_list,
- stackp->ffs_fix_path,
- stackp->ffs_wc_path
- ) == FAIL) {
+ && ff_check_visited(&search_ctx->ffsc_dir_visited_list->ffvl_visited_list,
+ stackp->ffs_fix_path, stackp->ffs_wc_path) == FAIL) {
#ifdef FF_VERBOSE
if (p_verbose >= 5) {
verbose_enter_scroll();
@@ -790,8 +784,7 @@ char_u *vim_findfile(void *search_ctx_arg)
stackp->ffs_filearray_cur = 0;
stackp->ffs_stage = 0;
} else {
- rest_of_wildcards = &stackp->ffs_wc_path[
- STRLEN(stackp->ffs_wc_path)];
+ rest_of_wildcards = &stackp->ffs_wc_path[STRLEN(stackp->ffs_wc_path)];
}
if (stackp->ffs_stage == 0) {
@@ -803,7 +796,7 @@ char_u *vim_findfile(void *search_ctx_arg)
*/
for (int i = stackp->ffs_filearray_cur; i < stackp->ffs_filearray_size; i++) {
if (!path_with_url(stackp->ffs_filearray[i])
- && !os_isdir((char_u *)stackp->ffs_filearray[i])) {
+ && !os_isdir(stackp->ffs_filearray[i])) {
continue; // not a directory
}
// prepare the filename to be checked for existence below
@@ -827,29 +820,23 @@ char_u *vim_findfile(void *search_ctx_arg)
if (search_ctx->ffsc_tagfile) {
suf = "";
} else {
- suf = (char *)curbuf->b_p_sua;
+ suf = curbuf->b_p_sua;
}
for (;;) {
// if file exists and we didn't already find it
if ((path_with_url((char *)file_path)
|| (os_path_exists(file_path)
- && (search_ctx->ffsc_find_what
- == FINDFILE_BOTH
- || ((search_ctx->ffsc_find_what
- == FINDFILE_DIR)
- == os_isdir(file_path)))))
+ && (search_ctx->ffsc_find_what == FINDFILE_BOTH
+ || ((search_ctx->ffsc_find_what == FINDFILE_DIR)
+ == os_isdir((char *)file_path)))))
#ifndef FF_VERBOSE
&& (ff_check_visited(&search_ctx->ffsc_visited_list->ffvl_visited_list,
- file_path,
- (char_u *)""
- ) == OK)
+ file_path, (char_u *)"") == OK)
#endif
) {
#ifdef FF_VERBOSE
if (ff_check_visited(&search_ctx->ffsc_visited_list->ffvl_visited_list,
- file_path,
- (char_u *)""
- ) == FAIL) {
+ file_path, (char_u *)"") == FAIL) {
if (p_verbose >= 5) {
verbose_enter_scroll();
smsg("Already: %s", file_path);
@@ -898,7 +885,7 @@ char_u *vim_findfile(void *search_ctx_arg)
} else {
// still wildcards left, push the directories for further search
for (int i = stackp->ffs_filearray_cur; i < stackp->ffs_filearray_size; i++) {
- if (!os_isdir((char_u *)stackp->ffs_filearray[i])) {
+ if (!os_isdir(stackp->ffs_filearray[i])) {
continue; // not a directory
}
ff_push(search_ctx,
@@ -922,7 +909,7 @@ char_u *vim_findfile(void *search_ctx_arg)
stackp->ffs_fix_path) == 0) {
continue; // don't repush same directory
}
- if (!os_isdir((char_u *)stackp->ffs_filearray[i])) {
+ if (!os_isdir(stackp->ffs_filearray[i])) {
continue; // not a directory
}
ff_push(search_ctx,
@@ -945,7 +932,7 @@ char_u *vim_findfile(void *search_ctx_arg)
// is the last starting directory in the stop list?
if (ff_path_in_stoplist(search_ctx->ffsc_start_dir,
(int)(path_end - search_ctx->ffsc_start_dir),
- search_ctx->ffsc_stopdirs_v) == TRUE) {
+ search_ctx->ffsc_stopdirs_v) == true) {
break;
}
@@ -1289,7 +1276,7 @@ static void ff_clear(ff_search_ctx_T *search_ctx)
/// check if the given path is in the stopdirs
///
-/// @return TRUE if yes else FALSE
+/// @return true if yes else false
static int ff_path_in_stoplist(char_u *path, int path_len, char_u **stopdirs_v)
{
int i = 0;
@@ -1301,7 +1288,7 @@ static int ff_path_in_stoplist(char_u *path, int path_len, char_u **stopdirs_v)
// if no path consider it as match
if (path_len == 0) {
- return TRUE;
+ return true;
}
for (i = 0; stopdirs_v[i] != NULL; i++) {
@@ -1312,7 +1299,7 @@ static int ff_path_in_stoplist(char_u *path, int path_len, char_u **stopdirs_v)
*/
if (FNAMENCMP(stopdirs_v[i], path, path_len) == 0
&& vim_ispathsep(stopdirs_v[i][path_len])) {
- return TRUE;
+ return true;
}
} else {
if (FNAMECMP(stopdirs_v[i], path) == 0) {
@@ -1320,13 +1307,13 @@ static int ff_path_in_stoplist(char_u *path, int path_len, char_u **stopdirs_v)
}
}
}
- return FALSE;
+ return false;
}
/// Find the file name "ptr[len]" in the path. Also finds directory names.
///
-/// On the first call set the parameter 'first' to TRUE to initialize
-/// the search. For repeating calls to FALSE.
+/// On the first call set the parameter 'first' to true to initialize
+/// the search. For repeating calls to false.
///
/// Repeating calls will return other files called 'ptr[len]' from the path.
///
@@ -1355,8 +1342,8 @@ char_u *find_file_in_path(char_u *ptr, size_t len, int options, int first, char_
return find_file_in_path_option(ptr, len, options, first,
(*curbuf->b_p_path == NUL
? p_path
- : curbuf->b_p_path),
- FINDFILE_BOTH, rel_fname, curbuf->b_p_sua);
+ : (char_u *)curbuf->b_p_path),
+ FINDFILE_BOTH, rel_fname, (char_u *)curbuf->b_p_sua);
}
static char_u *ff_file_to_find = NULL;
@@ -1387,7 +1374,7 @@ void free_findfile(void)
/// @return an allocated string for the file name. NULL for error.
char_u *find_directory_in_path(char_u *ptr, size_t len, int options, char_u *rel_fname)
{
- return find_file_in_path_option(ptr, len, options, TRUE, p_cdpath,
+ return find_file_in_path_option(ptr, len, options, true, p_cdpath,
FINDFILE_DIR, rel_fname, (char_u *)"");
}
@@ -1422,14 +1409,14 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
// copy file name into NameBuff, expanding environment variables
save_char = ptr[len];
ptr[len] = NUL;
- expand_env_esc(ptr, NameBuff, MAXPATHL, false, true, NULL);
+ expand_env_esc(ptr, (char_u *)NameBuff, MAXPATHL, false, true, NULL);
ptr[len] = save_char;
xfree(ff_file_to_find);
- ff_file_to_find = vim_strsave(NameBuff);
+ ff_file_to_find = vim_strsave((char_u *)NameBuff);
if (options & FNAME_UNESC) {
// Change all "\ " to " ".
- for (ptr = ff_file_to_find; *ptr != NUL; ++ptr) {
+ for (ptr = ff_file_to_find; *ptr != NUL; ptr++) {
if (ptr[0] == '\\' && ptr[1] == ' ') {
memmove(ptr, ptr + 1, STRLEN(ptr));
}
@@ -1458,7 +1445,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
* If this is not a first call, return NULL. We already returned a
* filename on the first call.
*/
- if (first == TRUE) {
+ if (first == true) {
if (path_with_url((char *)ff_file_to_find)) {
file_name = vim_strsave(ff_file_to_find);
goto theend;
@@ -1466,7 +1453,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
/* When FNAME_REL flag given first use the directory of the file.
* Otherwise or when this fails use the current directory. */
- for (int run = 1; run <= 2; ++run) {
+ for (int run = 1; run <= 2; run++) {
size_t l = STRLEN(ff_file_to_find);
if (run == 1
&& rel_to_curdir
@@ -1486,11 +1473,11 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
buf = (char *)suffixes;
for (;;) {
if (
- (os_path_exists(NameBuff)
+ (os_path_exists((char_u *)NameBuff)
&& (find_what == FINDFILE_BOTH
|| ((find_what == FINDFILE_DIR)
== os_isdir(NameBuff))))) {
- file_name = vim_strsave(NameBuff);
+ file_name = vim_strsave((char_u *)NameBuff);
goto theend;
}
if (*buf == NUL) {
@@ -1507,7 +1494,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
* When "first" is set, first setup to the start of the option.
* Otherwise continue to find the next match.
*/
- if (first == TRUE) {
+ if (first == true) {
// vim_findfile_free_visited can handle a possible NULL pointer
vim_findfile_free_visited(fdip_search_ctx);
dir = (char *)path_option;
@@ -1521,7 +1508,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
break;
}
- did_findfile_init = FALSE;
+ did_findfile_init = false;
} else {
char_u *r_ptr;
@@ -1545,14 +1532,14 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
r_ptr, 100, false, find_what,
fdip_search_ctx, false, rel_fname);
if (fdip_search_ctx != NULL) {
- did_findfile_init = TRUE;
+ did_findfile_init = true;
}
xfree(buf);
}
}
}
if (file_name == NULL && (options & FNAME_MESS)) {
- if (first == TRUE) {
+ if (first == true) {
if (find_what == FINDFILE_DIR) {
semsg(_("E344: Can't find directory \"%s\" in cdpath"),
ff_file_to_find);
@@ -1654,7 +1641,7 @@ int vim_chdirfile(char *fname, CdCause cause)
STRLCPY(dir, fname, MAXPATHL);
*path_tail_with_sep(dir) = NUL;
- if (os_dirname(NameBuff, sizeof(NameBuff)) != OK) {
+ if (os_dirname((char_u *)NameBuff, sizeof(NameBuff)) != OK) {
NameBuff[0] = NUL;
}
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 5dfcbb0668..d67cd36a85 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -134,7 +134,7 @@ void filemess(buf_T *buf, char_u *name, char_u *s, int attr)
// calling filemess().
msg_scroll_save = msg_scroll;
if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0) {
- msg_scroll = FALSE;
+ msg_scroll = false;
}
if (!msg_scroll) { // wait a bit when overwriting an error msg
check_for_delay(false);
@@ -143,7 +143,7 @@ void filemess(buf_T *buf, char_u *name, char_u *s, int attr)
msg_scroll = msg_scroll_save;
msg_scrolled_ign = true;
// may truncate the message to avoid a hit-return prompt
- msg_outtrans_attr(msg_may_trunc(FALSE, IObuff), attr);
+ msg_outtrans_attr((char *)msg_may_trunc(false, IObuff), attr);
msg_clr_eos();
ui_flush();
msg_scrolled_ign = false;
@@ -167,6 +167,7 @@ void filemess(buf_T *buf, char_u *name, char_u *s, int attr)
/// READ_STDIN read from stdin instead of a file
/// READ_BUFFER read from curbuf instead of a file (converting after reading
/// stdin)
+/// READ_NOFILE do not read a file, only trigger BufReadCmd
/// READ_DUMMY read into a dummy buffer (to check if file contents changed)
/// READ_KEEP_UNDO don't clear undo info or read it from a file
/// READ_FIFO read from fifo/socket instead of a file
@@ -334,12 +335,18 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
}
curbuf->b_op_start = orig_start;
+
+ if (flags & READ_NOFILE) {
+ // Return NOTDONE instead of FAIL so that BufEnter can be triggered
+ // and other operations don't fail.
+ return NOTDONE;
+ }
}
if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0) {
- msg_scroll = FALSE; // overwrite previous file message
+ msg_scroll = false; // overwrite previous file message
} else {
- msg_scroll = TRUE; // don't overwrite previous file message
+ msg_scroll = true; // don't overwrite previous file message
}
// If the name is too long we might crash further on, quit here.
if (fname != NULL && *fname != NUL) {
@@ -402,7 +409,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
*/
check_readonly = (newfile && (curbuf->b_flags & BF_CHECK_RO));
if (check_readonly && !readonlymode) {
- curbuf->b_p_ro = FALSE;
+ curbuf->b_p_ro = false;
}
if (newfile && !read_stdin && !read_buffer && !read_fifo) {
@@ -518,18 +525,18 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
* loaded. Help files always get readonly mode
*/
if ((check_readonly && file_readonly) || curbuf->b_help) {
- curbuf->b_p_ro = TRUE;
+ curbuf->b_p_ro = true;
}
if (set_options) {
// Don't change 'eol' if reading from buffer as it will already be
// correctly set when reading stdin.
if (!read_buffer) {
- curbuf->b_p_eol = TRUE;
- curbuf->b_start_eol = TRUE;
+ curbuf->b_p_eol = true;
+ curbuf->b_start_eol = true;
}
- curbuf->b_p_bomb = FALSE;
- curbuf->b_start_bomb = FALSE;
+ curbuf->b_p_bomb = false;
+ curbuf->b_start_bomb = false;
}
// Create a swap file now, so that other Vims are warned that we are
@@ -583,7 +590,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
return FAIL;
}
- ++no_wait_return; // don't wait for return yet
+ no_wait_return++; // don't wait for return yet
// Set '[ mark to the line above where the lines go (line 1 if zero).
orig_start = curbuf->b_op_start;
@@ -635,7 +642,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
if (aborting()) { // autocmds may abort script processing
no_wait_return--;
msg_scroll = msg_save;
- curbuf->b_p_ro = TRUE; // must use "w!" now
+ curbuf->b_p_ro = true; // must use "w!" now
return FAIL;
}
/*
@@ -656,7 +663,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
} else {
emsg(_("E201: *ReadPre autocommands must not change current buffer"));
}
- curbuf->b_p_ro = TRUE; // must use "w!" now
+ curbuf->b_p_ro = true; // must use "w!" now
return FAIL;
}
}
@@ -670,7 +677,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
}
}
- msg_scroll = FALSE; // overwrite the file message
+ msg_scroll = false; // overwrite the file message
/*
* Set linecnt now, before the "retry" caused by a wrong guess for
@@ -692,7 +699,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
* Decide which 'encoding' to use or use first.
*/
if (eap != NULL && eap->force_enc != 0) {
- fenc = (char *)enc_canonize((char_u *)eap->cmd + eap->force_enc);
+ fenc = enc_canonize(eap->cmd + eap->force_enc);
fenc_alloced = true;
keep_dest_enc = true;
} else if (curbuf->b_p_bin) {
@@ -708,10 +715,10 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
fenc_alloced = false;
} else if (*p_fencs == NUL) {
- fenc = (char *)curbuf->b_p_fenc; // use format from buffer
+ fenc = curbuf->b_p_fenc; // use format from buffer
fenc_alloced = false;
} else {
- fenc_next = (char *)p_fencs; // try items in 'fileencodings'
+ fenc_next = p_fencs; // try items in 'fileencodings'
fenc = (char *)next_fenc(&fenc_next, &fenc_alloced);
}
@@ -751,8 +758,8 @@ retry:
}
file_rewind = false;
if (set_options) {
- curbuf->b_p_bomb = FALSE;
- curbuf->b_start_bomb = FALSE;
+ curbuf->b_p_bomb = false;
+ curbuf->b_start_bomb = false;
}
conv_error = 0;
}
@@ -766,7 +773,7 @@ retry:
} else {
if (eap != NULL && eap->force_ff != 0) {
fileformat = get_fileformat_force(curbuf, eap);
- try_unix = try_dos = try_mac = FALSE;
+ try_unix = try_dos = try_mac = false;
} else if (curbuf->b_p_bin) {
fileformat = EOL_UNIX; // binary: use Unix format
} else if (*p_ffs ==
@@ -892,7 +899,7 @@ retry:
}
// Set "can_retry" when it's possible to rewind the file and try with
- // another "fenc" value. It's FALSE when no other "fenc" to try, reading
+ // another "fenc" value. It's false when no other "fenc" to try, reading
// stdin or fixed at a specific encoding.
can_retry = (*fenc != NUL && !read_stdin && !keep_dest_enc && !read_fifo);
@@ -1011,7 +1018,7 @@ retry:
// Change NL to NUL to reverse the effect done
// below.
n = (int)(size - tlen);
- for (ni = 0; ni < n; ++ni) {
+ for (ni = 0; ni < n; ni++) {
if (p[ni] == NL) {
ptr[tlen++] = NUL;
} else {
@@ -1138,8 +1145,8 @@ retry:
size -= blen;
memmove(ptr, ptr + blen, (size_t)size);
if (set_options) {
- curbuf->b_p_bomb = TRUE;
- curbuf->b_start_bomb = TRUE;
+ curbuf->b_p_bomb = true;
+ curbuf->b_start_bomb = true;
}
}
@@ -1672,7 +1679,7 @@ failed:
&& ptr == line_start + 1)) {
// remember for when writing
if (set_options) {
- curbuf->b_p_eol = FALSE;
+ curbuf->b_p_eol = false;
}
*ptr = NUL;
len = (colnr_T)(ptr - line_start + 1);
@@ -1729,7 +1736,7 @@ failed:
os_remove(tmpname); // delete converted file
xfree(tmpname);
}
- --no_wait_return; // may wait for return now
+ no_wait_return--; // may wait for return now
/*
* In recovery mode everything but autocommands is skipped.
@@ -1749,7 +1756,7 @@ failed:
linecnt = 0;
}
if (newfile || read_buffer) {
- redraw_curbuf_later(NOT_VALID);
+ redraw_curbuf_later(UPD_NOT_VALID);
// After reading the text into the buffer the diff info needs to
// be updated.
diff_invalidate(curbuf);
@@ -1773,7 +1780,7 @@ failed:
if (!(flags & READ_DUMMY)) {
filemess(curbuf, (char_u *)sfname, (char_u *)_(e_interr), 0);
if (newfile) {
- curbuf->b_p_ro = TRUE; // must use "w!" now
+ curbuf->b_p_ro = true; // must use "w!" now
}
}
msg_scroll = msg_save;
@@ -1788,30 +1795,30 @@ failed:
#ifdef UNIX
if (S_ISFIFO(perm)) { // fifo
STRCAT(IObuff, _("[fifo]"));
- c = TRUE;
+ c = true;
}
if (S_ISSOCK(perm)) { // or socket
STRCAT(IObuff, _("[socket]"));
- c = TRUE;
+ c = true;
}
# ifdef OPEN_CHR_FILES
if (S_ISCHR(perm)) { // or character special
STRCAT(IObuff, _("[character special]"));
- c = TRUE;
+ c = true;
}
# endif
#endif
if (curbuf->b_p_ro) {
STRCAT(IObuff, shortmess(SHM_RO) ? _("[RO]") : _("[readonly]"));
- c = TRUE;
+ c = true;
}
if (read_no_eol_lnum) {
msg_add_eol();
- c = TRUE;
+ c = true;
}
if (ff_error == EOL_DOS) {
STRCAT(IObuff, _("[CR missing]"));
- c = TRUE;
+ c = true;
}
if (split) {
STRCAT(IObuff, _("[long lines split]"));
@@ -1819,25 +1826,25 @@ failed:
}
if (notconverted) {
STRCAT(IObuff, _("[NOT converted]"));
- c = TRUE;
+ c = true;
} else if (converted) {
STRCAT(IObuff, _("[converted]"));
- c = TRUE;
+ c = true;
}
if (conv_error != 0) {
sprintf((char *)IObuff + STRLEN(IObuff),
_("[CONVERSION ERROR in line %" PRId64 "]"), (int64_t)conv_error);
- c = TRUE;
+ c = true;
} else if (illegal_byte > 0) {
sprintf((char *)IObuff + STRLEN(IObuff),
_("[ILLEGAL BYTE in line %" PRId64 "]"), (int64_t)illegal_byte);
- c = TRUE;
+ c = true;
} else if (error) {
STRCAT(IObuff, _("[READ ERRORS]"));
- c = TRUE;
+ c = true;
}
if (msg_add_fileformat(fileformat)) {
- c = TRUE;
+ c = true;
}
msg_add_lines(c, (long)linecnt, filesize);
@@ -1865,9 +1872,8 @@ failed:
// with errors writing the file requires ":w!"
if (newfile && (error
|| conv_error != 0
- || (illegal_byte > 0 && bad_char_behavior != BAD_KEEP)
- )) {
- curbuf->b_p_ro = TRUE;
+ || (illegal_byte > 0 && bad_char_behavior != BAD_KEEP))) {
+ curbuf->b_p_ro = true;
}
u_clearline(); // cannot use "U" command after adding lines
@@ -1948,7 +1954,7 @@ failed:
if (!au_did_filetype && *curbuf->b_p_ft != NUL) {
// EVENT_FILETYPE was not triggered but the buffer already has a
// filetype. Trigger EVENT_FILETYPE using the existing filetype.
- apply_autocmds(EVENT_FILETYPE, (char *)curbuf->b_p_ft, curbuf->b_fname, true, curbuf);
+ apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname, true, curbuf);
}
} else {
apply_autocmds_exarg(EVENT_FILEREADPOST, sfname, sfname,
@@ -1999,7 +2005,7 @@ static linenr_T readfile_linenr(linenr_T linecnt, char_u *p, char_u *endp)
linenr_T lnum;
lnum = curbuf->b_ml.ml_line_count - linecnt + 1;
- for (s = p; s < endp; ++s) {
+ for (s = p; s < endp; s++) {
if (*s == '\n') {
lnum++;
}
@@ -2018,11 +2024,11 @@ void prep_exarg(exarg_T *eap, const buf_T *buf)
snprintf(eap->cmd, cmd_len, "e ++enc=%s", buf->b_p_fenc);
eap->force_enc = 8;
eap->bad_char = buf->b_bad_char;
- eap->force_ff = *buf->b_p_ff;
+ eap->force_ff = (unsigned char)(*buf->b_p_ff);
eap->force_bin = buf->b_p_bin ? FORCE_BIN : FORCE_NOBIN;
- eap->read_edit = FALSE;
- eap->forceit = FALSE;
+ eap->read_edit = false;
+ eap->forceit = false;
}
/// Set default or forced 'fileformat' and 'binary'.
@@ -2050,8 +2056,8 @@ void set_file_options(int set_options, exarg_T *eap)
void set_forced_fenc(exarg_T *eap)
{
if (eap->force_enc != 0) {
- char_u *fenc = enc_canonize((char_u *)eap->cmd + eap->force_enc);
- set_string_option_direct("fenc", -1, (char *)fenc, OPT_FREE|OPT_LOCAL, 0);
+ char *fenc = enc_canonize(eap->cmd + eap->force_enc);
+ set_string_option_direct("fenc", -1, fenc, OPT_FREE|OPT_LOCAL, 0);
xfree(fenc);
}
}
@@ -2075,12 +2081,12 @@ static char_u *next_fenc(char **pp, bool *alloced)
}
p = (char_u *)vim_strchr((*pp), ',');
if (p == NULL) {
- r = enc_canonize((char_u *)(*pp));
+ r = (char_u *)enc_canonize(*pp);
*pp += STRLEN(*pp);
} else {
r = vim_strnsave((char_u *)(*pp), (size_t)(p - (char_u *)(*pp)));
*pp = (char *)p + 1;
- p = enc_canonize(r);
+ p = (char_u *)enc_canonize((char *)r);
xfree(r);
r = p;
}
@@ -2161,9 +2167,9 @@ char *new_file_message(void)
///
/// If "forceit" is true, we don't care for errors when attempting backups.
/// In case of an error everything possible is done to restore the original
-/// file. But when "forceit" is TRUE, we risk losing it.
+/// file. But when "forceit" is true, we risk losing it.
///
-/// When "reset_changed" is TRUE and "append" == FALSE and "start" == 1 and
+/// When "reset_changed" is true and "append" == false and "start" == 1 and
/// "end" == curbuf->b_ml.ml_line_count, reset curbuf->b_changed.
///
/// This function must NOT use NameBuff (because it's called by autowrite()).
@@ -2204,9 +2210,9 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
int bufsize;
long perm; // file permissions
int retval = OK;
- int newfile = false; // TRUE if file doesn't exist yet
+ int newfile = false; // true if file doesn't exist yet
int msg_save = msg_scroll;
- int overwriting; // TRUE if writing over original
+ int overwriting; // true if writing over original
int no_eol = false; // no end-of-line written
int device = false; // writing to a device
int prev_got_int = got_int;
@@ -2215,7 +2221,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
static char *err_readonly =
"is read-only (cannot override: \"W\" in 'cpoptions')";
#if defined(UNIX)
- int made_writable = FALSE; // 'w' bit has been set
+ int made_writable = false; // 'w' bit has been set
#endif
// writing everything
int whole = (start == 1 && end == buf->b_ml.ml_line_count);
@@ -2234,7 +2240,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
vim_acl_T acl = NULL; /* ACL copied from original file to
backup or new file */
#endif
- int write_undo_file = FALSE;
+ int write_undo_file = false;
context_sha256_T sha_ctx;
unsigned int bkc = get_bkc_value(buf);
const pos_T orig_start = buf->b_op_start;
@@ -2266,7 +2272,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
// must init bw_conv_buf and bw_iconv_fd before jumping to "fail"
write_info.bw_conv_buf = NULL;
- write_info.bw_conv_error = FALSE;
+ write_info.bw_conv_error = false;
write_info.bw_conv_error_lnum = 0;
write_info.bw_restlen = 0;
#ifdef HAVE_ICONV
@@ -2314,10 +2320,10 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
if (buf->b_ffname != NULL && FNAMECMP(ffname, buf->b_ffname) == 0) {
overwriting = true;
} else {
- overwriting = FALSE;
+ overwriting = false;
}
- ++no_wait_return; // don't wait for return yet
+ no_wait_return++; // don't wait for return yet
/*
* Set '[ and '] marks to the lines to be written.
@@ -2329,12 +2335,12 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
{
aco_save_T aco;
- int buf_ffname = FALSE;
- int buf_sfname = FALSE;
- int buf_fname_f = FALSE;
- int buf_fname_s = FALSE;
- int did_cmd = FALSE;
- int nofile_err = FALSE;
+ int buf_ffname = false;
+ int buf_sfname = false;
+ int buf_fname_f = false;
+ int buf_fname_s = false;
+ int did_cmd = false;
+ int nofile_err = false;
int empty_memline = (buf->b_ml.ml_mfp == NULL);
bufref_T bufref;
@@ -2512,9 +2518,9 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
if (shortmess(SHM_OVER) && !exiting) {
- msg_scroll = FALSE; // overwrite previous file message
+ msg_scroll = false; // overwrite previous file message
} else {
- msg_scroll = TRUE; // don't overwrite previous file message
+ msg_scroll = true; // don't overwrite previous file message
}
if (!filtering) {
filemess(buf,
@@ -2525,7 +2531,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
#endif
(char_u *)"", 0); // show that we are busy
}
- msg_scroll = FALSE; // always overwrite the file message now
+ msg_scroll = false; // always overwrite the file message now
buffer = verbose_try_malloc(BUFSIZE);
// can't allocate big buffer, use small one (to be able to write when out of
@@ -2558,8 +2564,8 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
/* It's a device of some kind (or a fifo) which we can write to
* but for which we can't make a backup. */
- device = TRUE;
- newfile = TRUE;
+ device = true;
+ newfile = true;
perm = -1;
}
}
@@ -2571,8 +2577,8 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
goto fail;
}
if (c == NODE_WRITABLE) {
- device = TRUE;
- newfile = TRUE;
+ device = true;
+ newfile = true;
perm = -1;
} else {
perm = os_getperm((const char *)fname);
@@ -2638,7 +2644,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
* abort it.
*/
prev_got_int = got_int;
- got_int = FALSE;
+ got_int = false;
// Mark the buffer as 'being saved' to prevent changed buffer warnings
buf->b_saving = true;
@@ -2656,7 +2662,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
const bool no_prepend_dot = false;
if ((bkc & BKC_YES) || append) { // "yes"
- backup_copy = TRUE;
+ backup_copy = true;
} else if ((bkc & BKC_AUTO)) { // "auto"
int i;
@@ -2669,7 +2675,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
if (os_fileinfo_hardlinks(&file_info_old) > 1
|| !os_fileinfo_link(fname, &file_info)
|| !os_fileinfo_id_equal(&file_info, &file_info_old)) {
- backup_copy = TRUE;
+ backup_copy = true;
} else {
/*
* Check if we can create a file and set the owner/group to
@@ -2689,7 +2695,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
fd = os_open((char *)IObuff,
O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, (int)perm);
if (fd < 0) { // can't write in directory
- backup_copy = TRUE;
+ backup_copy = true;
} else {
#ifdef UNIX
os_fchown(fd, (uv_uid_t)file_info_old.stat.st_uid, (uv_gid_t)file_info_old.stat.st_gid);
@@ -2697,7 +2703,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
|| file_info.stat.st_uid != file_info_old.stat.st_uid
|| file_info.stat.st_gid != file_info_old.stat.st_gid
|| (long)file_info.stat.st_mode != perm) {
- backup_copy = TRUE;
+ backup_copy = true;
}
#endif
/* Close the file before removing it, on MS-Windows we
@@ -2719,7 +2725,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
if ((bkc & BKC_BREAKSYMLINK)
&& file_info_link_ok
&& !os_fileinfo_id_equal(&file_info, &file_info_old)) {
- backup_copy = FALSE;
+ backup_copy = false;
}
// Hardlinks.
@@ -2727,7 +2733,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
&& os_fileinfo_hardlinks(&file_info_old) > 1
&& (!file_info_link_ok
|| os_fileinfo_id_equal(&file_info, &file_info_old))) {
- backup_copy = FALSE;
+ backup_copy = false;
}
#endif
}
@@ -2736,7 +2742,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
if (*p_bex == NUL) {
backup_ext = ".bak";
} else {
- backup_ext = (char *)p_bex;
+ backup_ext = p_bex;
}
if (backup_copy) {
@@ -2758,7 +2764,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
* For these reasons, the existing writable file must be truncated
* and reused. Creation of a backup COPY will be attempted.
*/
- dirp = (char *)p_bdir;
+ dirp = p_bdir;
while (*dirp) {
/*
* Isolate one directory name, using an entry in 'bdir'.
@@ -2769,7 +2775,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
if (trailing_pathseps) {
IObuff[dir_len - 2] = NUL;
}
- if (*dirp == NUL && !os_isdir(IObuff)) {
+ if (*dirp == NUL && !os_isdir((char *)IObuff)) {
int ret;
char *failed_dir;
if ((ret = os_mkdir_recurse((char *)IObuff, 0755, &failed_dir)) != 0) {
@@ -2789,7 +2795,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
rootname = (char *)get_file_in_dir((char_u *)fname, IObuff);
if (rootname == NULL) {
- some_error = TRUE; // out of memory
+ some_error = true; // out of memory
goto nobackup;
}
@@ -2804,7 +2810,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
if (backup == NULL) {
xfree(rootname);
- some_error = TRUE; // out of memory
+ some_error = true; // out of memory
goto nobackup;
}
@@ -2889,7 +2895,7 @@ nobackup:
if (backup == NULL && errmsg == NULL) {
SET_ERRMSG(_("E509: Cannot create backup file (add ! to override)"));
}
- // Ignore errors when forceit is TRUE.
+ // Ignore errors when forceit is true.
if ((some_error || errmsg != NULL) && !forceit) {
retval = FAIL;
goto fail;
@@ -2919,7 +2925,7 @@ nobackup:
* path/fo.o.h.bak Try all directories in 'backupdir', first one
* that works is used.
*/
- dirp = (char *)p_bdir;
+ dirp = p_bdir;
while (*dirp) {
/*
* Isolate one directory name and make the backup file name.
@@ -2930,7 +2936,7 @@ nobackup:
if (trailing_pathseps) {
IObuff[dir_len - 2] = NUL;
}
- if (*dirp == NUL && !os_isdir(IObuff)) {
+ if (*dirp == NUL && !os_isdir((char *)IObuff)) {
int ret;
char *failed_dir;
if ((ret = os_mkdir_recurse((char *)IObuff, 0755, &failed_dir)) != 0) {
@@ -3049,10 +3055,10 @@ nobackup:
// Check for forced 'fileencoding' from "++opt=val" argument.
if (eap != NULL && eap->force_enc != 0) {
fenc = eap->cmd + eap->force_enc;
- fenc = (char *)enc_canonize((char_u *)fenc);
+ fenc = enc_canonize(fenc);
fenc_tofree = fenc;
} else {
- fenc = (char *)buf->b_p_fenc;
+ fenc = buf->b_p_fenc;
}
// Check if the file needs to be converted.
@@ -3089,8 +3095,8 @@ nobackup:
if (!write_info.bw_conv_buf) {
end = 0;
}
- write_info.bw_first = TRUE;
- } else
+ write_info.bw_first = true;
+ } else {
#endif
/*
@@ -3106,6 +3112,11 @@ nobackup:
}
}
}
+
+#ifdef HAVE_ICONV
+}
+#endif
+
if (converted && wb_flags == 0
#ifdef HAVE_ICONV
&& write_info.bw_iconv_fd == (iconv_t)-1
@@ -3115,7 +3126,7 @@ nobackup:
SET_ERRMSG(_("E213: Cannot convert (add ! to write without conversion)"));
goto restore_backup;
}
- notconverted = TRUE;
+ notconverted = true;
}
// If conversion is taking place, we may first pretend to write and check
@@ -3137,12 +3148,12 @@ nobackup:
} else {
// Open the file "wfname" for writing.
// We may try to open the file twice: If we can't write to the file
- // and forceit is TRUE we delete the existing file and try to
+ // and forceit is true we delete the existing file and try to
// create a new one. If this still fails we may have lost the
// original file! (this may happen when the user reached his
// quotum for number of files).
// Appending will fail if the file does not exist and forceit is
- // FALSE.
+ // false.
while ((fd = os_open(wfname,
O_WRONLY |
(append ?
@@ -3366,7 +3377,7 @@ restore_backup:
// been written to disk and we don't lose it.
// For a device do try the fsync() but don't complain if it does not work
// (could be a pipe).
- // If the 'fsync' option is FALSE, don't fsync(). Useful for laptops.
+ // If the 'fsync' option is false, don't fsync(). Useful for laptops.
int error;
if (p_fs && (error = os_fsync(fd)) != 0 && !device
// fsync not supported on this storage.
@@ -3485,7 +3496,7 @@ restore_backup:
}
lnum -= start; // compute number of written lines
- --no_wait_return; // may wait for return now
+ no_wait_return--; // may wait for return now
#if !defined(UNIX)
fname = sfname; // use shortname now, for the messages
@@ -3495,32 +3506,32 @@ restore_backup:
c = false;
if (write_info.bw_conv_error) {
STRCAT(IObuff, _(" CONVERSION ERROR"));
- c = TRUE;
+ c = true;
if (write_info.bw_conv_error_lnum != 0) {
vim_snprintf_add((char *)IObuff, IOSIZE, _(" in line %" PRId64 ";"),
(int64_t)write_info.bw_conv_error_lnum);
}
} else if (notconverted) {
STRCAT(IObuff, _("[NOT converted]"));
- c = TRUE;
+ c = true;
} else if (converted) {
STRCAT(IObuff, _("[converted]"));
- c = TRUE;
+ c = true;
}
if (device) {
STRCAT(IObuff, _("[Device]"));
- c = TRUE;
+ c = true;
} else if (newfile) {
STRCAT(IObuff, new_file_message());
c = true;
}
if (no_eol) {
msg_add_eol();
- c = TRUE;
+ c = true;
}
// may add [unix/dos/mac]
if (msg_add_fileformat(fileformat)) {
- c = TRUE;
+ c = true;
}
msg_add_lines(c, (long)lnum, nchars); // add line/char count
if (!shortmess(SHM_WRITE)) {
@@ -3568,7 +3579,7 @@ restore_backup:
* the backup file our 'original' file.
*/
if (*p_pm && dobackup) {
- char *const org = modname(fname, (char *)p_pm, false);
+ char *const org = modname(fname, p_pm, false);
if (backup != NULL) {
/*
@@ -3624,7 +3635,7 @@ restore_backup:
* Finish up. We get here either after failure or success.
*/
fail:
- --no_wait_return; // may wait for return now
+ no_wait_return--; // may wait for return now
nofail:
// Done saving, we accept changed buffer warnings again
@@ -3711,23 +3722,23 @@ nofail:
if (append) {
apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
- FALSE, curbuf, eap);
+ false, curbuf, eap);
} else if (filtering) {
apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
- FALSE, curbuf, eap);
+ false, curbuf, eap);
} else if (reset_changed && whole) {
apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
- FALSE, curbuf, eap);
+ false, curbuf, eap);
} else {
apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
- FALSE, curbuf, eap);
+ false, curbuf, eap);
}
// restore curwin/curbuf and a few other things
aucmd_restbuf(&aco);
if (aborting()) { // autocmds may abort script processing
- retval = FALSE;
+ retval = false;
}
}
@@ -3994,11 +4005,11 @@ static int buf_write_bytes(struct bw_info *ip)
}
if (ucs2bytes(c, &p, flags) && !ip->bw_conv_error) {
- ip->bw_conv_error = TRUE;
+ ip->bw_conv_error = true;
ip->bw_conv_error_lnum = ip->bw_start_lnum;
}
if (c == NL) {
- ++ip->bw_start_lnum;
+ ip->bw_start_lnum++;
}
}
if (flags & FIO_LATIN1) {
@@ -4049,7 +4060,7 @@ static int buf_write_bytes(struct bw_info *ip)
to = (char *)ip->bw_conv_buf;
tolen = save_len;
}
- ip->bw_first = FALSE;
+ ip->bw_first = false;
}
/*
@@ -4058,7 +4069,7 @@ static int buf_write_bytes(struct bw_info *ip)
if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen)
== (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
|| fromlen > CONV_RESTLEN) {
- ip->bw_conv_error = TRUE;
+ ip->bw_conv_error = true;
return FAIL;
}
@@ -4163,12 +4174,12 @@ static bool need_conversion(const char_u *fenc)
int fenc_flags;
if (*fenc == NUL || STRCMP(p_enc, fenc) == 0) {
- same_encoding = TRUE;
+ same_encoding = true;
fenc_flags = 0;
} else {
// Ignore difference between "ansi" and "latin1", "ucs-4" and
// "ucs-4be", etc.
- enc_flags = get_fio_flags(p_enc);
+ enc_flags = get_fio_flags((char_u *)p_enc);
fenc_flags = get_fio_flags(fenc);
same_encoding = (enc_flags != 0 && fenc_flags == enc_flags);
}
@@ -4192,7 +4203,7 @@ static int get_fio_flags(const char_u *name)
int prop;
if (*name == NUL) {
- name = p_enc;
+ name = (char_u *)p_enc;
}
prop = enc_canon_props(name);
if (prop & ENC_UNICODE) {
@@ -4296,10 +4307,10 @@ static int make_bom(char_u *buf, char_u *name)
/// Shorten filename of a buffer.
///
-/// @param force when TRUE: Use full path from now on for files currently being
+/// @param force when true: Use full path from now on for files currently being
/// edited, both for file name and swap file name. Try to shorten the file
/// names a bit, if safe to do so.
-/// when FALSE: Only try to shorten absolute file names.
+/// when false: Only try to shorten absolute file names.
///
/// For buffers that have buftype "nofile" or "scratch": never change the file
/// name.
@@ -4386,7 +4397,7 @@ char *modname(const char *fname, const char *ext, bool prepend_dot)
}
add_pathsep(retval);
fnamelen = strlen(retval);
- prepend_dot = FALSE; // nothing to prepend a dot to
+ prepend_dot = false; // nothing to prepend a dot to
} else {
fnamelen = strlen(fname);
retval = xmalloc(fnamelen + extlen + 3);
@@ -4769,7 +4780,7 @@ int vim_rename(const char_u *from, const char_u *to)
return 0;
}
-static int already_warned = FALSE;
+static int already_warned = false;
/// Check if any not hidden buffer has been changed.
/// Postpone the check if there are characters in the stuff buffer, a global
@@ -4778,7 +4789,7 @@ static int already_warned = FALSE;
///
/// @param focus called for GUI focus event
///
-/// @return TRUE if some message was written (screen should be redrawn and cursor positioned).
+/// @return true if some message was written (screen should be redrawn and cursor positioned).
int check_timestamps(int focus)
{
int didit = 0;
@@ -4786,15 +4797,15 @@ int check_timestamps(int focus)
// Don't check timestamps while system() or another low-level function may
// cause us to lose and gain focus.
if (no_check_timestamps > 0) {
- return FALSE;
+ return false;
}
// Avoid doing a check twice. The OK/Reload dialog can cause a focus
// event and we would keep on checking if the file is steadily growing.
// Do check again after typing something.
if (focus && did_check_timestamps) {
- need_check_timestamps = TRUE;
- return FALSE;
+ need_check_timestamps = true;
+ return false;
}
if (!stuff_empty() || global_busy || !typebuf_typed()
@@ -4937,7 +4948,7 @@ int buf_check_timestamp(buf_T *buf)
buf_store_file_info(buf, &file_info);
}
- if (os_isdir((char_u *)buf->b_fname)) {
+ if (os_isdir(buf->b_fname)) {
// Don't do anything for a directory. Might contain the file explorer.
} else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
&& !bufIsChanged(buf) && file_info_ok) {
@@ -5075,7 +5086,7 @@ int buf_check_timestamp(buf_T *buf)
redraw_cmdline = false;
}
}
- already_warned = TRUE;
+ already_warned = true;
}
xfree(path);
@@ -5306,8 +5317,8 @@ static void vim_mktempdir(void)
mode_t umask_save = umask(0077);
for (size_t i = 0; i < ARRAY_SIZE(temp_dirs); i++) {
// Expand environment variables, leave room for "/tmp/nvim.<user>/XXXXXX/999999999".
- expand_env((char_u *)temp_dirs[i], (char_u *)tmp, TEMP_FILE_PATH_MAXLEN - 64);
- if (!os_isdir((char_u *)tmp)) {
+ expand_env((char *)temp_dirs[i], tmp, TEMP_FILE_PATH_MAXLEN - 64);
+ if (!os_isdir(tmp)) {
continue;
}
@@ -5317,7 +5328,7 @@ static void vim_mktempdir(void)
xstrlcat(tmp, user, sizeof(tmp));
(void)os_mkdir(tmp, 0700); // Always create, to avoid a race.
bool owned = os_file_owned(tmp);
- bool isdir = os_isdir((char_u *)tmp);
+ bool isdir = os_isdir(tmp);
#ifdef UNIX
int perm = os_getperm(tmp); // XDG_RUNTIME_DIR must be owned by the user, mode 0700.
bool valid = isdir && owned && 0700 == (perm & 0777);
@@ -5606,8 +5617,8 @@ bool match_file_list(char_u *list, char_u *sfname, char_u *ffname)
/// Convert the given pattern "pat" which has shell style wildcards in it, into
/// a regular expression, and return the result in allocated memory. If there
-/// is a directory path separator to be matched, then TRUE is put in
-/// allow_dirs, otherwise FALSE is put there -- webb.
+/// is a directory path separator to be matched, then true is put in
+/// allow_dirs, otherwise false is put there -- webb.
/// Handle backslashes before special characters, like "\*" and "\ ".
///
/// @param pat_end first char after pattern or NULL
@@ -5625,7 +5636,7 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs
bool add_dollar = true;
if (allow_dirs != NULL) {
- *allow_dirs = FALSE;
+ *allow_dirs = false;
}
if (pat_end == NULL) {
pat_end = pat + STRLEN(pat);
@@ -5711,7 +5722,7 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs
reg_pat[i++] = '/';
reg_pat[i++] = ']';
if (allow_dirs != NULL) {
- *allow_dirs = TRUE;
+ *allow_dirs = true;
}
break;
}
@@ -5745,7 +5756,7 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs
&& (!no_bslash || *p != '\\')
#endif
) {
- *allow_dirs = TRUE;
+ *allow_dirs = true;
}
reg_pat[i++] = '\\';
reg_pat[i++] = *p;
@@ -5758,7 +5769,7 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs
reg_pat[i++] = '/';
reg_pat[i++] = ']';
if (allow_dirs != NULL) {
- *allow_dirs = TRUE;
+ *allow_dirs = true;
}
break;
#endif
diff --git a/src/nvim/fileio.h b/src/nvim/fileio.h
index 650977deac..ae3c51f1bc 100644
--- a/src/nvim/fileio.h
+++ b/src/nvim/fileio.h
@@ -15,6 +15,7 @@
#define READ_KEEP_UNDO 0x20 // keep undo info
#define READ_FIFO 0x40 // read from fifo or socket
#define READ_NOWINENTER 0x80 // do not trigger BufWinEnter
+#define READ_NOFILE 0x100 // do not read a file, do trigger BufReadCmd
#define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 8ce24fd378..b4ddb3ec08 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -394,7 +394,7 @@ void opFoldRange(pos_T firstpos, pos_T lastpos, int opening, int recurse, int ha
}
// Force a redraw to remove the Visual highlighting.
if (had_visual) {
- redraw_curbuf_later(INVERTED);
+ redraw_curbuf_later(UPD_INVERTED);
}
}
@@ -721,7 +721,7 @@ void deleteFold(win_T *const wp, const linenr_T start, const linenr_T end, const
emsg(_(e_nofold));
// Force a redraw to remove the Visual highlighting.
if (had_visual) {
- redraw_buf_later(wp->w_buffer, INVERTED);
+ redraw_buf_later(wp->w_buffer, UPD_INVERTED);
}
} else {
// Deleting markers may make cursor column invalid
@@ -757,7 +757,7 @@ void clearFolding(win_T *win)
/// The changes in lines from top to bot (inclusive).
void foldUpdate(win_T *wp, linenr_T top, linenr_T bot)
{
- if (disable_fold_update || compl_busy || State & MODE_INSERT) {
+ if (disable_fold_update || State & MODE_INSERT) {
return;
}
@@ -819,7 +819,7 @@ void foldUpdateAfterInsert(void)
void foldUpdateAll(win_T *win)
{
win->w_foldinvalid = true;
- redraw_later(win, NOT_VALID);
+ redraw_later(win, UPD_NOT_VALID);
}
// foldMoveTo() {{{2
@@ -1556,7 +1556,7 @@ static void foldCreateMarkers(win_T *wp, pos_T start, pos_T end)
}
parseMarker(wp);
- foldAddMarker(buf, start, wp->w_p_fmr, foldstartmarkerlen);
+ foldAddMarker(buf, start, (char_u *)wp->w_p_fmr, foldstartmarkerlen);
foldAddMarker(buf, end, foldendmarker, foldendmarkerlen);
// Update both changes here, to avoid all folds after the start are
@@ -1575,9 +1575,9 @@ static void foldCreateMarkers(win_T *wp, pos_T start, pos_T end)
/// Add "marker[markerlen]" in 'commentstring' to position `pos`.
static void foldAddMarker(buf_T *buf, pos_T pos, const char_u *marker, size_t markerlen)
{
- char_u *cms = buf->b_p_cms;
+ char_u *cms = (char_u *)buf->b_p_cms;
char_u *newline;
- char_u *p = (char_u *)strstr((char *)buf->b_p_cms, "%s");
+ char_u *p = (char_u *)strstr(buf->b_p_cms, "%s");
bool line_is_comment = false;
linenr_T lnum = pos.lnum;
@@ -1621,7 +1621,7 @@ static void deleteFoldMarkers(win_T *wp, fold_T *fp, int recursive, linenr_T lnu
lnum_off + fp->fd_top);
}
}
- foldDelMarker(wp->w_buffer, fp->fd_top + lnum_off, wp->w_p_fmr,
+ foldDelMarker(wp->w_buffer, fp->fd_top + lnum_off, (char_u *)wp->w_p_fmr,
foldstartmarkerlen);
foldDelMarker(wp->w_buffer, fp->fd_top + lnum_off + fp->fd_len - 1,
foldendmarker, foldendmarkerlen);
@@ -1639,7 +1639,7 @@ static void foldDelMarker(buf_T *buf, linenr_T lnum, char_u *marker, size_t mark
return;
}
- char_u *cms = buf->b_p_cms;
+ char_u *cms = (char_u *)buf->b_p_cms;
char_u *line = ml_get_buf(buf, lnum, false);
for (char_u *p = line; *p != NUL; p++) {
if (STRNCMP(p, marker, markerlen) != 0) {
@@ -1729,7 +1729,7 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldin
emsg_silent++; // handle exceptions, but don't display errors
text =
- (char_u *)eval_to_string_safe((char *)wp->w_p_fdt, NULL,
+ (char_u *)eval_to_string_safe(wp->w_p_fdt, NULL,
was_set_insecurely(wp, "foldtext", OPT_LOCAL));
emsg_silent--;
@@ -1790,7 +1790,7 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldin
static void foldtext_cleanup(char_u *str)
{
// Ignore leading and trailing white space in 'commentstring'.
- char_u *cms_start = (char_u *)skipwhite((char *)curbuf->b_p_cms);
+ char_u *cms_start = (char_u *)skipwhite(curbuf->b_p_cms);
size_t cms_slen = STRLEN(cms_start);
while (cms_slen > 0 && ascii_iswhite(cms_start[cms_slen - 1])) {
cms_slen--;
@@ -2854,7 +2854,7 @@ static void foldlevelIndent(fline_T *flp)
// empty line or lines starting with a character in 'foldignore': level
// depends on surrounding lines
- if (*s == NUL || vim_strchr((char *)flp->wp->w_p_fdi, *s) != NULL) {
+ if (*s == NUL || vim_strchr(flp->wp->w_p_fdi, *s) != NULL) {
// first and last line can't be undefined, use level 0
if (lnum == 1 || lnum == buf->b_ml.ml_line_count) {
flp->lvl = 0;
@@ -2907,7 +2907,7 @@ static void foldlevelExpr(fline_T *flp)
const bool save_keytyped = KeyTyped;
int c;
- const int n = eval_foldexpr((char *)flp->wp->w_p_fde, &c);
+ const int n = eval_foldexpr(flp->wp->w_p_fde, &c);
KeyTyped = save_keytyped;
switch (c) {
@@ -2985,8 +2985,8 @@ static void foldlevelExpr(fline_T *flp)
/// Relies on the option value to have been checked for correctness already.
static void parseMarker(win_T *wp)
{
- foldendmarker = (char_u *)vim_strchr((char *)wp->w_p_fmr, ',');
- foldstartmarkerlen = (size_t)(foldendmarker++ - wp->w_p_fmr);
+ foldendmarker = (char_u *)vim_strchr(wp->w_p_fmr, ',');
+ foldstartmarkerlen = (size_t)(foldendmarker++ - (char_u *)wp->w_p_fmr);
foldendmarkerlen = STRLEN(foldendmarker);
}
@@ -3003,7 +3003,7 @@ static void foldlevelMarker(fline_T *flp)
int start_lvl = flp->lvl;
// cache a few values for speed
- char_u *startmarker = flp->wp->w_p_fmr;
+ char_u *startmarker = (char_u *)flp->wp->w_p_fmr;
int cstart = *startmarker;
startmarker++;
int cend = *foldendmarker;
@@ -3212,19 +3212,19 @@ static void foldclosed_both(typval_T *argvars, typval_T *rettv, int end)
}
/// "foldclosed()" function
-void f_foldclosed(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_foldclosed(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
foldclosed_both(argvars, rettv, false);
}
/// "foldclosedend()" function
-void f_foldclosedend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_foldclosedend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
foldclosed_both(argvars, rettv, true);
}
/// "foldlevel()" function
-void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_foldlevel(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const linenr_T lnum = tv_get_lnum(argvars);
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) {
@@ -3233,7 +3233,7 @@ void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "foldtext()" function
-void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_foldtext(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
@@ -3279,7 +3279,7 @@ void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "foldtextresult(lnum)" function
-void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_foldtextresult(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char_u buf[FOLD_TEXT_LEN];
static bool entered = false;
diff --git a/src/nvim/garray.c b/src/nvim/garray.c
index 7a3c14b1bb..1afabe4e10 100644
--- a/src/nvim/garray.c
+++ b/src/nvim/garray.c
@@ -131,7 +131,7 @@ void ga_remove_duplicate_strings(garray_T *gap)
fnames[j - 1] = fnames[j];
}
- --gap->ga_len;
+ gap->ga_len--;
}
}
}
diff --git a/src/nvim/garray.h b/src/nvim/garray.h
index 56bd5c9130..0281678925 100644
--- a/src/nvim/garray.h
+++ b/src/nvim/garray.h
@@ -4,7 +4,7 @@
#include <stddef.h> // for size_t
#include "nvim/log.h"
-#include "nvim/types.h" // for char_u
+#include "nvim/types.h"
/// Structure used for growing arrays.
/// This is used to store information that only grows, is deleted all at
diff --git a/src/nvim/generators/c_grammar.lua b/src/nvim/generators/c_grammar.lua
index 70a7be86b5..d872ffd6a9 100644
--- a/src/nvim/generators/c_grammar.lua
+++ b/src/nvim/generators/c_grammar.lua
@@ -26,6 +26,7 @@ local c_id = (
local c_void = P('void')
local c_param_type = (
((P('Error') * fill * P('*') * fill) * Cc('error')) +
+ ((P('Arena') * fill * P('*') * fill) * Cc('arena')) +
C((P('const ') ^ -1) * (c_id) * (ws ^ 1) * P('*')) +
(C(c_id) * (ws ^ 1))
)
diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua
index b167767f7a..67b8f5f0f5 100644
--- a/src/nvim/generators/gen_api_dispatch.lua
+++ b/src/nvim/generators/gen_api_dispatch.lua
@@ -17,6 +17,7 @@ local nvimdir = arg[1]
package.path = nvimdir .. '/?.lua;' .. package.path
_G.vim = loadfile(nvimdir..'/../../runtime/lua/vim/shared.lua')()
+_G.vim.inspect = loadfile(nvimdir..'/../../runtime/lua/vim/inspect.lua')()
local hashy = require'generators.hashy'
@@ -72,6 +73,11 @@ for i = 6, #arg do
-- for specifying errors
fn.parameters[#fn.parameters] = nil
end
+ if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'arena' then
+ -- return value is allocated in an arena
+ fn.arena_return = true
+ fn.parameters[#fn.parameters] = nil
+ end
end
end
input:close()
@@ -210,7 +216,7 @@ for i = 1, #functions do
if fn.impl_name == nil and fn.remote then
local args = {}
- output:write('Object handle_'..fn.name..'(uint64_t channel_id, Array args, Error *error)')
+ output:write('Object handle_'..fn.name..'(uint64_t channel_id, Array args, Arena* arena, Error *error)')
output:write('\n{')
output:write('\n#if MIN_LOG_LEVEL <= LOGLVL_DBG')
output:write('\n logmsg(LOGLVL_DBG, "RPC: ", NULL, -1, true, "ch %" PRIu64 ": invoke '
@@ -319,6 +325,10 @@ for i = 1, #functions do
output:write(call_args)
end
+ if fn.arena_return then
+ output:write(', arena')
+ end
+
if fn.can_fail then
-- if the function can fail, also pass a pointer to the local error object
if #args > 0 then
@@ -355,11 +365,12 @@ local hashorder, hashfun = hashy.hashy_hash("msgpack_rpc_get_handler_for", vim.t
return "method_handlers["..idx.."].name"
end)
-output:write("static const MsgpackRpcRequestHandler method_handlers[] = {\n")
-for _, name in ipairs(hashorder) do
+output:write("const MsgpackRpcRequestHandler method_handlers[] = {\n")
+for n, name in ipairs(hashorder) do
local fn = remote_fns[name]
+ fn.handler_id = n-1
output:write(' { .name = "'..name..'", .fn = handle_'.. (fn.impl_name or fn.name)..
- ', .fast = '..tostring(fn.fast)..'},\n')
+ ', .fast = '..tostring(fn.fast)..', .arena_return = '..tostring(not not fn.arena_return)..'},\n')
end
output:write("};\n\n")
output:write(hashfun)
@@ -400,6 +411,8 @@ output:write([[
#include "nvim/api/private/helpers.h"
#include "nvim/lua/converter.h"
#include "nvim/lua/executor.h"
+#include "nvim/memory.h"
+
]])
include_headers(output, headers)
output:write('\n')
@@ -477,6 +490,13 @@ local function process_function(fn)
if fn.receives_channel_id then
cparams = 'LUA_INTERNAL_CALL, ' .. cparams
end
+ if fn.arena_return then
+ cparams = cparams .. '&arena, '
+ write_shifted_output(output, [[
+ Arena arena = ARENA_EMPTY;
+ ]])
+ end
+
if fn.can_fail then
cparams = cparams .. '&err'
else
@@ -511,15 +531,21 @@ local function process_function(fn)
else
return_type = fn.return_type
end
+ local free_retval
+ if fn.arena_return then
+ free_retval = "arena_mem_free(arena_finish(&arena));"
+ else
+ free_retval = "api_free_"..return_type:lower().."(ret);"
+ end
write_shifted_output(output, string.format([[
const %s ret = %s(%s);
nlua_push_%s(lstate, ret, true);
- api_free_%s(ret);
+ %s
%s
%s
return 1;
- ]], fn.return_type, fn.name, cparams, return_type, return_type:lower(),
- free_at_exit_code, err_throw_code))
+ ]], fn.return_type, fn.name, cparams, return_type,
+ free_retval, free_at_exit_code, err_throw_code))
else
write_shifted_output(output, string.format([[
%s(%s);
diff --git a/src/nvim/generators/gen_api_ui_events.lua b/src/nvim/generators/gen_api_ui_events.lua
index 93bbaab74c..f9e888c20d 100755
--- a/src/nvim/generators/gen_api_ui_events.lua
+++ b/src/nvim/generators/gen_api_ui_events.lua
@@ -125,7 +125,7 @@ for i = 1, #events do
local param = ev.parameters[j]
local copy = 'copy_'..param[2]
if param[1] == 'String' then
- send = send..' String copy_'..param[2]..' = copy_string('..param[2]..');\n'
+ send = send..' String copy_'..param[2]..' = copy_string('..param[2]..', NULL);\n'
argv = argv..', '..copy..'.data, INT2PTR('..copy..'.size)'
recv = (recv..' String '..param[2]..
' = (String){.data = argv['..argc..'],'..
@@ -134,7 +134,7 @@ for i = 1, #events do
recv_cleanup = recv_cleanup..' api_free_string('..param[2]..');\n'
argc = argc+2
elseif param[1] == 'Array' then
- send = send..' Array '..copy..' = copy_array('..param[2]..');\n'
+ send = send..' Array '..copy..' = copy_array('..param[2]..', NULL);\n'
argv = argv..', '..copy..'.items, INT2PTR('..copy..'.size)'
recv = (recv..' Array '..param[2]..
' = (Array){.items = argv['..argc..'],'..
@@ -144,7 +144,7 @@ for i = 1, #events do
argc = argc+2
elseif param[1] == 'Object' then
send = send..' Object *'..copy..' = xmalloc(sizeof(Object));\n'
- send = send..' *'..copy..' = copy_object('..param[2]..');\n'
+ send = send..' *'..copy..' = copy_object('..param[2]..', NULL);\n'
argv = argv..', '..copy
recv = recv..' Object '..param[2]..' = *(Object *)argv['..argc..'];\n'
recv_argv = recv_argv..', '..param[2]
diff --git a/src/nvim/generators/gen_eval.lua b/src/nvim/generators/gen_eval.lua
index c72249161b..8e6d1f2634 100644
--- a/src/nvim/generators/gen_eval.lua
+++ b/src/nvim/generators/gen_eval.lua
@@ -28,13 +28,20 @@ local hashy = require'generators.hashy'
local hashpipe = io.open(funcsfname, 'wb')
local funcs = require('eval').funcs
+for _, func in pairs(funcs) do
+ if func.float_func then
+ func.func = "float_op_wrapper"
+ func.data = "{ .float_func = &"..func.float_func.." }"
+ end
+end
+
local metadata = mpack.unpack(io.open(metadata_file, 'rb'):read("*all"))
for _,fun in ipairs(metadata) do
if fun.eval then
funcs[fun.name] = {
args=#fun.parameters,
func='api_wrapper',
- data='&handle_'..fun.name,
+ data='{ .api_handler = &method_handlers['..fun.handler_id..'] }'
}
end
end
@@ -60,12 +67,12 @@ for _, name in ipairs(neworder) do
end
local base = def.base or "BASE_NONE"
local func = def.func or ('f_' .. name)
- local data = def.data or "NULL"
+ local data = def.data or "{ .nullptr = NULL }"
local fast = def.fast and 'true' or 'false'
- hashpipe:write((' { "%s", %s, %s, %s, %s, &%s, (FunPtr)%s },\n')
+ hashpipe:write((' { "%s", %s, %s, %s, %s, &%s, %s },\n')
:format(name, args[1], args[2], base, fast, func, data))
end
-hashpipe:write(' { NULL, 0, 0, BASE_NONE, false, NULL, NULL },\n')
+hashpipe:write(' { NULL, 0, 0, BASE_NONE, false, NULL, { .nullptr = NULL } },\n')
hashpipe:write("};\n\n")
hashpipe:write(hashfun)
hashpipe:close()
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 0f55158733..0a9457ef35 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -81,11 +81,9 @@ static buffheader_T readbuf2 = { { NULL, { NUL } }, NULL, 0, 0 };
static int typeahead_char = 0; // typeahead char that's not flushed
-/*
- * when block_redo is TRUE redo buffer will not be changed
- * used by edit() to repeat insertions and 'V' command for redoing
- */
-static int block_redo = FALSE;
+// when block_redo is true redo buffer will not be changed
+// used by edit() to repeat insertions and 'V' command for redoing
+static int block_redo = false;
static int KeyNoremap = 0; // remapping flags
@@ -162,7 +160,7 @@ static char_u *get_buffcont(buffheader_T *buffer, int dozero)
p2 = p;
for (const buffblock_T *bp = buffer->bh_first.b_next;
bp != NULL; bp = bp->b_next) {
- for (const char_u *str = bp->b_str; *str;) {
+ for (const char_u *str = (char_u *)bp->b_str; *str;) {
*p2++ = *str++;
}
}
@@ -179,7 +177,7 @@ char_u *get_recorded(void)
char_u *p;
size_t len;
- p = get_buffcont(&recordbuff, TRUE);
+ p = get_buffcont(&recordbuff, true);
free_buff(&recordbuff);
/*
@@ -207,7 +205,7 @@ char_u *get_recorded(void)
/// K_SPECIAL in the returned string is escaped.
char_u *get_inserted(void)
{
- return get_buffcont(&redobuff, FALSE);
+ return get_buffcont(&redobuff, false);
}
/// Add string after the current block of the given buffer
@@ -319,7 +317,7 @@ static void add_char_buff(buffheader_T *buf, int c)
/// Get one byte from the read buffers. Use readbuf1 one first, use readbuf2
/// if that one is empty.
-/// If advance == TRUE go to the next char.
+/// If advance == true go to the next char.
/// No translation is done K_SPECIAL is escaped.
static int read_readbuffers(int advance)
{
@@ -341,7 +339,7 @@ static int read_readbuf(buffheader_T *buf, int advance)
}
buffblock_T *const curr = buf->bh_first.b_next;
- c = curr->b_str[buf->bh_index];
+ c = (char_u)curr->b_str[buf->bh_index];
if (advance) {
if (curr->b_str[++buf->bh_index] == NUL) {
@@ -368,19 +366,15 @@ static void start_stuff(void)
}
}
-/*
- * Return TRUE if the stuff buffer is empty.
- */
+/// Return true if the stuff buffer is empty.
int stuff_empty(void)
FUNC_ATTR_PURE
{
return (readbuf1.bh_first.b_next == NULL && readbuf2.bh_first.b_next == NULL);
}
-/*
- * Return TRUE if readbuf1 is empty. There may still be redo characters in
- * redbuf2.
- */
+/// Return true if readbuf1 is empty. There may still be redo characters in
+/// redbuf2.
int readbuf1_empty(void)
FUNC_ATTR_PURE
{
@@ -629,6 +623,34 @@ void stuffnumReadbuff(long n)
add_num_buff(&readbuf1, n);
}
+/// Stuff a string into the typeahead buffer, such that edit() will insert it
+/// literally ("literally" true) or interpret is as typed characters.
+void stuffescaped(const char *arg, bool literally)
+{
+ while (*arg != NUL) {
+ // Stuff a sequence of normal ASCII characters, that's fast. Also
+ // stuff K_SPECIAL to get the effect of a special key when "literally"
+ // is true.
+ const char *const start = arg;
+ while ((*arg >= ' ' && *arg < DEL) || ((uint8_t)(*arg) == K_SPECIAL
+ && !literally)) {
+ arg++;
+ }
+ if (arg > start) {
+ stuffReadbuffLen(start, (arg - start));
+ }
+
+ // stuff a single special character
+ if (*arg != NUL) {
+ const int c = mb_cptr2char_adv((const char_u **)&arg);
+ if (literally && ((c < ' ' && c != TAB) || c == DEL)) {
+ stuffcharReadbuff(Ctrl_V);
+ }
+ stuffcharReadbuff(c);
+ }
+ }
+}
+
/// Read a character from the redo buffer. Translates K_SPECIAL and
/// multibyte characters.
/// The redo buffer is left as it is.
@@ -649,7 +671,7 @@ static int read_redo(bool init, bool old_redo)
if (bp == NULL) {
return FAIL;
}
- p = bp->b_str;
+ p = (char_u *)bp->b_str;
return OK;
}
if ((c = *p) == NUL) {
@@ -670,7 +692,7 @@ static int read_redo(bool init, bool old_redo)
}
if (*++p == NUL && bp->b_next != NULL) {
bp = bp->b_next;
- p = bp->b_str;
+ p = (char_u *)bp->b_str;
}
buf[i] = (char_u)c;
if (i == n - 1) { // last byte of a character
@@ -793,7 +815,7 @@ int start_redo_ins(void)
void stop_redo_ins(void)
{
- block_redo = FALSE;
+ block_redo = false;
}
/*
@@ -932,9 +954,9 @@ int ins_typebuf(char *str, int noremap, int offset, bool nottyped, bool silent)
} else {
nrm = noremap;
}
- for (i = 0; i < addlen; ++i) {
+ for (i = 0; i < addlen; i++) {
typebuf.tb_noremap[typebuf.tb_off + i + offset] =
- (char_u)((--nrm >= 0) ? val : RM_YES);
+ (uint8_t)((--nrm >= 0) ? val : RM_YES);
}
// tb_maplen and tb_silent only remember the length of mapped and/or
@@ -970,7 +992,7 @@ int ins_char_typebuf(int c, int modifiers)
return (int)len;
}
-/// Return TRUE if the typeahead buffer was changed (while waiting for a
+/// Return true if the typeahead buffer was changed (while waiting for a
/// character to arrive). Happens when a message was received from a client or
/// from feedkeys().
/// But check in a more generic way to avoid trouble: When "typebuf.tb_buf"
@@ -986,10 +1008,8 @@ bool typebuf_changed(int tb_change_cnt)
|| typebuf_was_filled);
}
-/*
- * Return TRUE if there are no characters in the typeahead buffer that have
- * not been typed (result from a mapping or come from ":normal").
- */
+/// Return true if there are no characters in the typeahead buffer that have
+/// not been typed (result from a mapping or come from ":normal").
int typebuf_typed(void)
FUNC_ATTR_PURE
{
@@ -1260,7 +1280,7 @@ void restore_typeahead(tasave_T *tp)
/// Open a new script file for the ":source!" command.
///
/// @param directly when true execute directly
-void openscript(char_u *name, bool directly)
+void openscript(char *name, bool directly)
{
if (curscript + 1 == NSCRIPT) {
emsg(_(e_nesting));
@@ -1353,9 +1373,7 @@ void close_all_scripts(void)
#endif
-/*
- * Return TRUE when reading keys from a script file.
- */
+/// Return true when reading keys from a script file.
int using_script(void)
FUNC_ATTR_PURE
{
@@ -1686,7 +1704,7 @@ int vpeekc_any(void)
/*
* Call vpeekc() without causing anything to be mapped.
- * Return TRUE if a character is available, FALSE otherwise.
+ * Return true if a character is available, false otherwise.
*/
int char_avail(void)
{
@@ -1750,7 +1768,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
if (!ui_has_messages()) {
// redraw the screen after getchar()
- update_screen(CLEAR);
+ update_screen(UPD_NOT_VALID);
}
set_vim_var_nr(VV_MOUSE_WIN, 0);
@@ -1810,13 +1828,13 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
}
/// "getchar()" function
-void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_getchar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
getchar_common(argvars, rettv);
}
/// "getcharstr()" function
-void f_getcharstr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_getcharstr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
getchar_common(argvars, rettv);
@@ -1836,7 +1854,7 @@ void f_getcharstr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getcharmod()" function
-void f_getcharmod(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_getcharmod(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = mod_mask;
}
@@ -1881,7 +1899,7 @@ static bool at_ins_compl_key(void)
c = p[3] & 0x1f;
}
return (ctrl_x_mode_not_default() && vim_is_ctrl_x_key(c))
- || ((compl_cont_status & CONT_LOCAL) && (c == Ctrl_N || c == Ctrl_P));
+ || (compl_status_local() && (c == Ctrl_N || c == Ctrl_P));
}
/// Check if typebuf.tb_buf[] contains a modifier plus key that can be changed
@@ -2047,12 +2065,11 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
// - Partly match: mlen == typebuf.tb_len
keylen = mp->m_keylen;
if (mlen == keylen || (mlen == typebuf.tb_len && typebuf.tb_len < keylen)) {
- char_u *s;
int n;
// If only script-local mappings are allowed, check if the
// mapping starts with K_SNR.
- s = typebuf.tb_noremap + typebuf.tb_off;
+ uint8_t *s = typebuf.tb_noremap + typebuf.tb_off;
if (*s == RM_SCRIPT
&& (mp->m_keys[0] != K_SPECIAL
|| mp->m_keys[1] != KS_EXTRA
@@ -2103,7 +2120,7 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
// Check for match with 'pastetoggle'
if (*p_pt != NUL && mp == NULL && (State & (MODE_INSERT | MODE_NORMAL))) {
- bool match = typebuf_match_len(p_pt, &mlen);
+ bool match = typebuf_match_len((char_u *)p_pt, &mlen);
if (match) {
// write chars to script file(s)
if (mlen > typebuf.tb_maplen) {
@@ -2112,7 +2129,7 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
}
del_typebuf(mlen, 0); // remove the chars
- set_option_value("paste", !p_paste, NULL, 0);
+ set_option_value_give_err("paste", !p_paste, NULL, 0);
if (!(State & MODE_INSERT)) {
msg_col = 0;
msg_row = Rows - 1;
@@ -2248,7 +2265,7 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
save_m_keys = vim_strsave(mp->m_keys);
if (save_m_luaref == LUA_NOREF) {
- save_m_str = vim_strsave(mp->m_str);
+ save_m_str = vim_strsave((char_u *)mp->m_str);
}
map_str = eval_map_expr(mp, NUL);
@@ -2280,7 +2297,7 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
vgetc_busy = save_vgetc_busy;
may_garbage_collect = save_may_garbage_collect;
} else {
- map_str = mp->m_str;
+ map_str = (char_u *)mp->m_str;
}
// Insert the 'to' part in the typebuf.tb_buf.
@@ -2364,8 +2381,8 @@ void check_end_reg_executing(bool advance)
///
/// if "advance" is true (vgetc()):
/// Really get the character.
-/// KeyTyped is set to TRUE in the case the user typed the key.
-/// KeyStuffed is TRUE if the character comes from the stuff buffer.
+/// KeyTyped is set to true in the case the user typed the key.
+/// KeyStuffed is true if the character comes from the stuff buffer.
/// if "advance" is false (vpeekc()):
/// Just look whether there is a character available.
/// Return NUL if not.
@@ -2452,7 +2469,7 @@ static int vgetorpeek(bool advance)
// flush all input
c = inchar(typebuf.tb_buf, typebuf.tb_buflen - 1, 0L);
- // If inchar() returns TRUE (script file was active) or we
+ // If inchar() returns true (script file was active) or we
// are inside a mapping, get out of Insert mode.
// Otherwise we behave like having gotten a CTRL-C.
// As a result typing CTRL-C in insert mode will
@@ -2501,7 +2518,7 @@ static int vgetorpeek(bool advance)
// write char to script file(s)
gotchars(typebuf.tb_buf + typebuf.tb_off, 1);
}
- KeyNoremap = typebuf.tb_noremap[typebuf.tb_off];
+ KeyNoremap = (unsigned char)typebuf.tb_noremap[typebuf.tb_off];
del_typebuf(1, 0);
}
break; // got character, break the for loop
@@ -2530,7 +2547,7 @@ static int vgetorpeek(bool advance)
&& (State & MODE_INSERT)
&& (p_timeout || (keylen == KEYLEN_PART_KEY && p_ttimeout))
&& (c = inchar(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_len, 3, 25L)) == 0) {
- colnr_T col = 0, vcol;
+ colnr_T col = 0;
char_u *ptr;
if (mode_displayed) {
@@ -2548,22 +2565,27 @@ static int vgetorpeek(bool advance)
// We are expecting to truncate the trailing
// white-space, so find the last non-white
// character -- webb
- col = vcol = curwin->w_wcol = 0;
+ curwin->w_wcol = 0;
ptr = get_cursor_line_ptr();
- while (col < curwin->w_cursor.col) {
- if (!ascii_iswhite(ptr[col])) {
- curwin->w_wcol = vcol;
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin,
+ curwin->w_cursor.lnum, 0, ptr, ptr);
+ while ((char_u *)cts.cts_ptr < ptr + curwin->w_cursor.col) {
+ if (!ascii_iswhite(*cts.cts_ptr)) {
+ curwin->w_wcol = cts.cts_vcol;
}
- vcol += lbr_chartabsize(ptr, ptr + col, vcol);
- col += utfc_ptr2len((char *)ptr + col);
+ cts.cts_vcol += lbr_chartabsize(&cts);
+ cts.cts_ptr += utfc_ptr2len(cts.cts_ptr);
}
+ clear_chartabsize_arg(&cts);
+
curwin->w_wrow = curwin->w_cline_row
+ curwin->w_wcol / curwin->w_width_inner;
curwin->w_wcol %= curwin->w_width_inner;
curwin->w_wcol += curwin_col_off();
col = 0; // no correction needed
} else {
- --curwin->w_wcol;
+ curwin->w_wcol--;
col = curwin->w_cursor.col - 1;
}
} else if (curwin->w_p_wrap && curwin->w_wrow) {
@@ -2866,7 +2888,7 @@ int inchar(char_u *buf, int maxlen, long wait_time)
if (read_size <= 0) { // Did not get a character from script.
// If we got an interrupt, skip all previously typed characters and
- // return TRUE if quit reading script file.
+ // return true if quit reading script file.
// Stop reading typeahead when a single CTRL-C was read,
// fill_input_buf() returns this when not able to read from stdin.
// Don't use buf[] here, closescript() may have freed typebuf.tb_buf[]
@@ -2929,7 +2951,7 @@ int fix_input_buffer(char_u *buf, int len)
// Two characters are special: NUL and K_SPECIAL.
// Replace NUL by K_SPECIAL KS_ZERO KE_FILLER
// Replace K_SPECIAL by K_SPECIAL KS_SPECIAL KE_FILLER
- for (i = len; --i >= 0; ++p) {
+ for (i = len; --i >= 0; p++) {
if (p[0] == NUL
|| (p[0] == K_SPECIAL
&& (i < 2 || p[1] != KS_EXTRA))) {
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 231220c319..060db3b3b1 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -159,31 +159,10 @@ EXTERN colnr_T dollar_vcol INIT(= -1);
// Variables for Insert mode completion.
-// Length in bytes of the text being completed (this is deleted to be replaced
-// by the match.)
-EXTERN int compl_length INIT(= 0);
-
-// Set when doing something for completion that may call edit() recursively,
-// which is not allowed. Also used to disable folding during completion
-EXTERN bool compl_busy INIT(= false);
-
-// List of flags for method of completion.
-EXTERN int compl_cont_status INIT(= 0);
-#define CONT_ADDING 1 // "normal" or "adding" expansion
-#define CONT_INTRPT (2 + 4) // a ^X interrupted the current expansion
- // it's set only iff N_ADDS is set
-#define CONT_N_ADDS 4 // next ^X<> will add-new or expand-current
-#define CONT_S_IPOS 8 // next ^X<> will set initial_pos?
- // if so, word-wise-expansion will set SOL
-#define CONT_SOL 16 // pattern includes start of line, just for
- // word-wise expansion, not set for ^X^L
-#define CONT_LOCAL 32 // for ctrl_x_mode 0, ^X^P/^X^N do a local
- // expansion, (eg use complete=.)
-
-EXTERN char_u *edit_submode INIT(= NULL); // msg for CTRL-X submode
-EXTERN char_u *edit_submode_pre INIT(= NULL); // prepended to edit_submode
-EXTERN char_u *edit_submode_extra INIT(= NULL); // appended to edit_submode
-EXTERN hlf_T edit_submode_highl; // highl. method for extra info
+EXTERN char *edit_submode INIT(= NULL); // msg for CTRL-X submode
+EXTERN char *edit_submode_pre INIT(= NULL); // prepended to edit_submode
+EXTERN char *edit_submode_extra INIT(= NULL); // appended to edit_submode
+EXTERN hlf_T edit_submode_highl; // highl. method for extra info
// state for putting characters in the message area
EXTERN int cmdmsg_rl INIT(= false); // cmdline is drawn right to left
@@ -198,7 +177,7 @@ EXTERN bool msg_scrolled_ign INIT(= false);
// is reset before the screen is redrawn, so we need to keep track of this.
EXTERN bool msg_did_scroll INIT(= false);
-EXTERN char_u *keep_msg INIT(= NULL); // msg to be shown after redraw
+EXTERN char *keep_msg INIT(= NULL); // msg to be shown after redraw
EXTERN int keep_msg_attr INIT(= 0); // highlight attr for keep_msg
EXTERN bool need_fileinfo INIT(= false); // do fileinfo() after redraw
EXTERN int msg_scroll INIT(= false); // msg_start() will scroll
@@ -262,9 +241,13 @@ EXTERN int do_profiling INIT(= PROF_NONE); ///< PROF_ values
/// Exception currently being thrown. Used to pass an exception to a different
/// cstack. Also used for discarding an exception before it is caught or made
-/// pending.
+/// pending. Only valid when did_throw is true.
EXTERN except_T *current_exception;
+/// An exception is being thrown. Reset when the exception is caught or as
+/// long as it is pending in a finally clause.
+EXTERN bool did_throw INIT(= false);
+
/// Set when a throw that cannot be handled in do_cmdline() must be propagated
/// to the cstack of the previously called do_cmdline().
EXTERN bool need_rethrow INIT(= false);
@@ -580,6 +563,8 @@ EXTERN bool can_si INIT(= false);
// one indent will be removed.
EXTERN bool can_si_back INIT(= false);
+EXTERN int old_indent INIT(= 0); ///< for ^^D command in insert mode
+
// w_cursor before formatting text.
EXTERN pos_T saved_cursor INIT(= { 0, 0, 0 });
@@ -686,7 +671,7 @@ EXTERN int swap_exists_action INIT(= SEA_NONE); ///< For dialog when swap file
EXTERN bool swap_exists_did_quit INIT(= false); ///< Selected "quit" at the dialog.
EXTERN char_u IObuff[IOSIZE]; ///< Buffer for sprintf, I/O, etc.
-EXTERN char_u NameBuff[MAXPATHL]; ///< Buffer for expanding file names
+EXTERN char NameBuff[MAXPATHL]; ///< Buffer for expanding file names
EXTERN char msg_buf[MSG_BUF_LEN]; ///< Small buffer for messages
EXTERN char os_buf[ ///< Buffer for the os/ layer
#if MAXPATHL > IOSIZE
@@ -750,9 +735,9 @@ EXTERN bool need_start_insertmode INIT(= false); ///< start insert mode soon
// including the terminating NUL
EXTERN char last_mode[MODE_MAX_LENGTH] INIT(= "n");
-EXTERN char_u *last_cmdline INIT(= NULL); // last command line (for ":)
-EXTERN char_u *repeat_cmdline INIT(= NULL); // command line for "."
-EXTERN char_u *new_last_cmdline INIT(= NULL); // new value for last_cmdline
+EXTERN char *last_cmdline INIT(= NULL); // last command line (for ":)
+EXTERN char *repeat_cmdline INIT(= NULL); // command line for "."
+EXTERN char *new_last_cmdline INIT(= NULL); // new value for last_cmdline
EXTERN char *autocmd_fname INIT(= NULL); // fname for <afile> on cmdline
EXTERN int autocmd_bufnr INIT(= 0); // fnum for <abuf> on cmdline
EXTERN char *autocmd_match INIT(= NULL); // name for <amatch> on cmdline
@@ -776,7 +761,7 @@ EXTERN int keep_help_flag INIT(= false); // doing :ta from help file
// When a string option is NULL (which only happens in out-of-memory
// situations), it is set to empty_option, to avoid having to check for NULL
// everywhere.
-EXTERN char_u *empty_option INIT(= (char_u *)"");
+EXTERN char *empty_option INIT(= "");
EXTERN bool redir_off INIT(= false); // no redirection for a moment
EXTERN FILE *redir_fd INIT(= NULL); // message redirection file
@@ -816,7 +801,6 @@ EXTERN char *last_chdir_reason INIT(= NULL);
EXTERN bool km_stopsel INIT(= false);
EXTERN bool km_startsel INIT(= false);
-EXTERN int cedit_key INIT(= -1); ///< key value of 'cedit' option
EXTERN int cmdwin_type INIT(= 0); ///< type of cmdline window or 0
EXTERN int cmdwin_result INIT(= 0); ///< result of cmdline window or 0
EXTERN int cmdwin_level INIT(= 0); ///< cmdline recursion level
@@ -940,7 +924,7 @@ EXTERN char e_patnotf2[] INIT(= N_("E486: Pattern not found: %s"));
EXTERN char e_positive[] INIT(= N_("E487: Argument must be positive"));
EXTERN char e_prev_dir[] INIT(= N_("E459: Cannot go back to previous directory"));
-EXTERN char e_quickfix[] INIT(= N_("E42: No Errors"));
+EXTERN char e_no_errors[] INIT(= N_("E42: No Errors"));
EXTERN char e_loclist[] INIT(= N_("E776: No location list"));
EXTERN char e_re_damg[] INIT(= N_("E43: Damaged match string"));
EXTERN char e_re_corr[] INIT(= N_("E44: Corrupted regexp program"));
@@ -1021,6 +1005,8 @@ EXTERN char e_resulting_text_too_long[] INIT(= N_("E1240: Resulting text too lon
EXTERN char e_line_number_out_of_range[] INIT(= N_("E1247: Line number out of range"));
+EXTERN char e_highlight_group_name_invalid_char[] INIT(= N_("E5248: Invalid character in group name"));
+
EXTERN char e_highlight_group_name_too_long[] INIT(= N_("E1249: Highlight group name too long"));
EXTERN char e_undobang_cannot_redo_or_move_branch[]
diff --git a/src/nvim/grid.c b/src/nvim/grid.c
index f95ef3e705..329adfda12 100644
--- a/src/nvim/grid.c
+++ b/src/nvim/grid.c
@@ -125,7 +125,7 @@ void grid_putchar(ScreenGrid *grid, int c, int row, int col, int attr)
char buf[MB_MAXBYTES + 1];
buf[utf_char2bytes(c, buf)] = NUL;
- grid_puts(grid, (char_u *)buf, row, col, attr);
+ grid_puts(grid, buf, row, col, attr);
}
/// get a single character directly from grid.chars into "bytes[]".
@@ -148,7 +148,7 @@ void grid_getbytes(ScreenGrid *grid, int row, int col, char_u *bytes, int *attrp
/// attributes 'attr', and update chars[] and attrs[].
/// Note: only outputs within one row, message is truncated at grid boundary!
/// Note: if grid, row and/or col is invalid, nothing is done.
-void grid_puts(ScreenGrid *grid, char_u *text, int row, int col, int attr)
+void grid_puts(ScreenGrid *grid, char *text, int row, int col, int attr)
{
grid_puts_len(grid, text, -1, row, col, attr);
}
@@ -187,10 +187,10 @@ void grid_put_schar(ScreenGrid *grid, int row, int col, char_u *schar, int attr)
/// like grid_puts(), but output "text[len]". When "len" is -1 output up to
/// a NUL.
-void grid_puts_len(ScreenGrid *grid, char_u *text, int textlen, int row, int col, int attr)
+void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col, int attr)
{
size_t off;
- char_u *ptr = text;
+ char *ptr = text;
int len = textlen;
int c;
size_t max_off;
@@ -237,13 +237,13 @@ void grid_puts_len(ScreenGrid *grid, char_u *text, int textlen, int row, int col
while (col < grid->cols
&& (len < 0 || (int)(ptr - text) < len)
&& *ptr != NUL) {
- c = *ptr;
+ c = (unsigned char)(*ptr);
// check if this is the first byte of a multibyte
mbyte_blen = len > 0
- ? utfc_ptr2len_len(ptr, (int)((text + len) - ptr))
- : utfc_ptr2len((char *)ptr);
+ ? utfc_ptr2len_len((char_u *)ptr, (int)((text + len) - ptr))
+ : utfc_ptr2len(ptr);
u8c = len >= 0
- ? utfc_ptr2char_len(ptr, u8cc, (int)((text + len) - ptr))
+ ? utfc_ptr2char_len((char_u *)ptr, u8cc, (int)((text + len) - ptr))
: utfc_ptr2char(ptr, u8cc);
mbyte_cells = utf_char2cells(u8c);
if (p_arshape && !p_tbidi && ARABIC_CHAR(u8c)) {
@@ -254,7 +254,8 @@ void grid_puts_len(ScreenGrid *grid, char_u *text, int textlen, int row, int col
nc1 = NUL;
} else {
nc = len >= 0
- ? utfc_ptr2char_len(ptr + mbyte_blen, pcc, (int)((text + len) - ptr - mbyte_blen))
+ ? utfc_ptr2char_len((char_u *)ptr + mbyte_blen, pcc,
+ (int)((text + len) - ptr - mbyte_blen))
: utfc_ptr2char(ptr + mbyte_blen, pcc);
nc1 = pcc[0];
}
@@ -320,7 +321,7 @@ void grid_puts_len(ScreenGrid *grid, char_u *text, int textlen, int row, int col
ptr += mbyte_blen;
if (clear_next_cell) {
// This only happens at the end, display one space next.
- ptr = (char_u *)" ";
+ ptr = " ";
len = -1;
}
}
@@ -393,11 +394,11 @@ void grid_fill(ScreenGrid *grid, int start_row, int end_row, int start_col, int
// double wide-char clear out the right half. Only needed in a
// terminal.
if (start_col > 0 && grid_fix_col(grid, start_col, row) != start_col) {
- grid_puts_len(grid, (char_u *)" ", 1, row, start_col - 1, 0);
+ grid_puts_len(grid, " ", 1, row, start_col - 1, 0);
}
if (end_col < grid->cols
&& grid_fix_col(grid, end_col, row) != end_col) {
- grid_puts_len(grid, (char_u *)" ", 1, row, end_col, 0);
+ grid_puts_len(grid, " ", 1, row, end_col, 0);
}
// if grid was resized (in ext_multigrid mode), the UI has no redraw updates
@@ -475,9 +476,9 @@ static int grid_char_needs_redraw(ScreenGrid *grid, size_t off_from, size_t off_
/// "endcol" gives the columns where valid characters are.
/// "clear_width" is the width of the window. It's > 0 if the rest of the line
/// needs to be cleared, negative otherwise.
-/// "rlflag" is TRUE in a rightleft window:
-/// When TRUE and "clear_width" > 0, clear columns 0 to "endcol"
-/// When FALSE and "clear_width" > 0, clear columns "endcol" to "clear_width"
+/// "rlflag" is true in a rightleft window:
+/// When true and "clear_width" > 0, clear columns 0 to "endcol"
+/// When false and "clear_width" > 0, clear columns "endcol" to "clear_width"
/// If "wrap" is true, then hint to the UI that "row" contains a line
/// which has wrapped into the next row.
void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int clear_width,
diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c
index e8410d1ee7..602fa8b71d 100644
--- a/src/nvim/hardcopy.c
+++ b/src/nvim/hardcopy.c
@@ -10,10 +10,6 @@
#include <string.h>
#include "nvim/ascii.h"
-#include "nvim/vim.h"
-#ifdef HAVE_LOCALE_H
-# include <locale.h>
-#endif
#include "nvim/buffer.h"
#include "nvim/charset.h"
#include "nvim/eval.h"
@@ -38,6 +34,7 @@
#include "nvim/syntax.h"
#include "nvim/ui.h"
#include "nvim/version.h"
+#include "nvim/vim.h"
/*
* To implement printing on a platform, the following functions must be
@@ -51,20 +48,20 @@
*
* int mch_print_begin(prt_settings_T *settings)
* Called to start the print job.
- * Return FALSE to abort.
+ * Return false to abort.
*
* int mch_print_begin_page(char_u *msg)
* Called at the start of each page.
* "msg" indicates the progress of the print job, can be NULL.
- * Return FALSE to abort.
+ * Return false to abort.
*
* int mch_print_end_page()
* Called at the end of each page.
- * Return FALSE to abort.
+ * Return false to abort.
*
* int mch_print_blank_page()
* Called to generate a blank page for collated, duplex, multiple copy
- * document. Return FALSE to abort.
+ * document. Return false to abort.
*
* void mch_print_end(prt_settings_T *psettings)
* Called at normal end of print job.
@@ -87,36 +84,33 @@
*
* mch_print_start_line(int margin, int page_line)
* Sets the current position at the start of line "page_line".
- * If margin is TRUE start in the left margin (for header and line number).
+ * If margin is true start in the left margin (for header and line number).
*
* int mch_print_text_out(char_u *p, size_t len);
* Output one character of text p[len] at the current position.
- * Return TRUE if there is no room for another character in the same line.
+ * Return true if there is no room for another character in the same line.
*
* Note that the generic code has no idea of margins. The machine code should
* simply make the page look smaller! The header and the line numbers are
* printed in the margin.
*/
-static option_table_T printer_opts[OPT_PRINT_NUM_OPTIONS]
- =
- {
- { "top", TRUE, 0, NULL, 0, FALSE },
- { "bottom", TRUE, 0, NULL, 0, FALSE },
- { "left", TRUE, 0, NULL, 0, FALSE },
- { "right", TRUE, 0, NULL, 0, FALSE },
- { "header", TRUE, 0, NULL, 0, FALSE },
- { "syntax", FALSE, 0, NULL, 0, FALSE },
- { "number", FALSE, 0, NULL, 0, FALSE },
- { "wrap", FALSE, 0, NULL, 0, FALSE },
- { "duplex", FALSE, 0, NULL, 0, FALSE },
- { "portrait", FALSE, 0, NULL, 0, FALSE },
- { "paper", FALSE, 0, NULL, 0, FALSE },
- { "collate", FALSE, 0, NULL, 0, FALSE },
- { "jobsplit", FALSE, 0, NULL, 0, FALSE },
- { "formfeed", FALSE, 0, NULL, 0, FALSE },
- }
-;
+static option_table_T printer_opts[OPT_PRINT_NUM_OPTIONS] = {
+ { "top", true, 0, NULL, 0, false },
+ { "bottom", true, 0, NULL, 0, false },
+ { "left", true, 0, NULL, 0, false },
+ { "right", true, 0, NULL, 0, false },
+ { "header", true, 0, NULL, 0, false },
+ { "syntax", false, 0, NULL, 0, false },
+ { "number", false, 0, NULL, 0, false },
+ { "wrap", false, 0, NULL, 0, false },
+ { "duplex", false, 0, NULL, 0, false },
+ { "portrait", false, 0, NULL, 0, false },
+ { "paper", false, 0, NULL, 0, false },
+ { "collate", false, 0, NULL, 0, false },
+ { "jobsplit", false, 0, NULL, 0, false },
+ { "formfeed", false, 0, NULL, 0, false },
+};
static const uint32_t cterm_color_8[8] = {
0x000000, 0xff0000, 0x00ff00, 0xffff00,
@@ -152,12 +146,12 @@ static int page_count;
static option_table_T mbfont_opts[OPT_MBFONT_NUM_OPTIONS] =
{
- { "c", FALSE, 0, NULL, 0, FALSE },
- { "a", FALSE, 0, NULL, 0, FALSE },
- { "r", FALSE, 0, NULL, 0, FALSE },
- { "b", FALSE, 0, NULL, 0, FALSE },
- { "i", FALSE, 0, NULL, 0, FALSE },
- { "o", FALSE, 0, NULL, 0, FALSE },
+ { "c", false, 0, NULL, 0, false },
+ { "a", false, 0, NULL, 0, false },
+ { "r", false, 0, NULL, 0, false },
+ { "b", false, 0, NULL, 0, false },
+ { "i", false, 0, NULL, 0, false },
+ { "o", false, 0, NULL, 0, false },
};
/*
@@ -267,7 +261,7 @@ struct prt_resfile_buffer_S {
*/
char *parse_printoptions(void)
{
- return parse_list_options(p_popt, printer_opts, OPT_PRINT_NUM_OPTIONS);
+ return parse_list_options((char_u *)p_popt, printer_opts, OPT_PRINT_NUM_OPTIONS);
}
/*
@@ -276,7 +270,7 @@ char *parse_printoptions(void)
*/
char *parse_printmbfont(void)
{
- return parse_list_options(p_pmfn, mbfont_opts, OPT_MBFONT_NUM_OPTIONS);
+ return parse_list_options((char_u *)p_pmfn, mbfont_opts, OPT_MBFONT_NUM_OPTIONS);
}
/*
@@ -324,7 +318,7 @@ static char *parse_list_options(char_u *option_str, option_table_T *table, size_
len = (int)(colonp - stringp);
- for (idx = 0; idx < table_size; ++idx) {
+ for (idx = 0; idx < table_size; idx++) {
if (STRNICMP(stringp, table[idx].name, len) == 0) {
break;
}
@@ -506,9 +500,7 @@ int prt_header_height(void)
return 2;
}
-/*
- * Return TRUE if using a line number for printing.
- */
+// Return true if using a line number for printing.
int prt_use_number(void)
{
return printer_opts[OPT_PRINT_NUMBER].present
@@ -526,7 +518,7 @@ int prt_get_unit(int idx)
static char *(units[4]) = PRT_UNIT_NAMES;
if (printer_opts[idx].present) {
- for (i = 0; i < 4; ++i) {
+ for (i = 0; i < 4; i++) {
if (STRNICMP(printer_opts[idx].string, units[i], 2) == 0) {
u = i;
break;
@@ -552,7 +544,7 @@ static void prt_header(prt_settings_T *const psettings, const int pagenum, const
if (*p_header != NUL) {
linenr_T tmp_lnum, tmp_topline, tmp_botline;
- int use_sandbox = FALSE;
+ int use_sandbox = false;
/*
* Need to (temporarily) set current line number and first/last line
@@ -621,7 +613,7 @@ static void prt_message(char_u *s)
{
// TODO(bfredl): delete this
grid_fill(&default_grid, Rows - 1, Rows, 0, Columns, ' ', ' ', 0);
- grid_puts(&default_grid, s, Rows - 1, 0, HL_ATTR(HLF_R));
+ grid_puts(&default_grid, (char *)s, Rows - 1, 0, HL_ATTR(HLF_R));
ui_flush();
}
@@ -669,7 +661,7 @@ void ex_hardcopy(exarg_T *eap)
settings.modec = 'c';
if (!syntax_present(curwin)) {
- settings.do_syntax = FALSE;
+ settings.do_syntax = false;
} else if (printer_opts[OPT_PRINT_SYNTAX].present
&& TOLOWER_ASC(printer_opts[OPT_PRINT_SYNTAX].string[0]) != 'a') {
settings.do_syntax =
@@ -751,11 +743,9 @@ void ex_hardcopy(exarg_T *eap)
/*
* Loop over all pages in the print job: 1 2 3 ...
*/
- for (page_count = 0; prtpos.file_line <= eap->line2; ++page_count) {
- /*
- * Loop over uncollated copies: 1 1 1, 2 2 2, 3 3 3, ...
- * For duplex: 12 12 12 34 34 34, ...
- */
+ for (page_count = 0; prtpos.file_line <= eap->line2; page_count++) {
+ // Loop over uncollated copies: 1 1 1, 2 2 2, 3 3 3, ...
+ // For duplex: 12 12 12 34 34 34, ...
for (uncollated_copies = 0;
uncollated_copies < settings.n_uncollated_copies;
uncollated_copies++) {
@@ -765,10 +755,8 @@ void ex_hardcopy(exarg_T *eap)
/*
* Do front and rear side of a page.
*/
- for (side = 0; side <= settings.duplex; ++side) {
- /*
- * Print one page.
- */
+ for (side = 0; side <= settings.duplex; side++) {
+ // Print one page.
// Check for interrupt character every page.
os_breakcheck();
@@ -870,7 +858,7 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T
{
colnr_T col;
char_u *line;
- int need_break = FALSE;
+ int need_break = false;
int outputlen;
int tab_spaces;
int print_pos;
@@ -883,7 +871,7 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T
if (!ppos->ff && prt_use_number()) {
prt_line_number(psettings, page_line, ppos->file_line);
}
- ppos->ff = FALSE;
+ ppos->ff = false;
} else {
// left over from wrap halfway through a tab
print_pos = ppos->print_pos;
@@ -946,7 +934,7 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T
&& printer_opts[OPT_PRINT_FORMFEED].present
&& TOLOWER_ASC(printer_opts[OPT_PRINT_FORMFEED].string[0])
== 'y') {
- ppos->ff = TRUE;
+ ppos->ff = true;
need_break = 1;
} else {
need_break = mch_print_text_out(line + col, (size_t)outputlen);
@@ -1988,7 +1976,7 @@ void mch_print_cleanup(void)
if (prt_do_conv) {
convert_setup(&prt_conv, NULL, NULL);
- prt_do_conv = FALSE;
+ prt_do_conv = false;
}
if (prt_ps_fd != NULL) {
fclose(prt_ps_fd);
@@ -2120,11 +2108,11 @@ static int prt_match_encoding(char *p_encoding, struct prt_ps_mbfont_S *p_cmap,
for (mbenc = 0; mbenc < p_cmap->num_encodings; mbenc++) {
if (STRNICMP(p_mbenc->encoding, p_encoding, enc_len) == 0) {
*pp_mbenc = p_mbenc;
- return TRUE;
+ return true;
}
p_mbenc++;
}
- return FALSE;
+ return false;
}
static int prt_match_charset(char *p_charset, struct prt_ps_mbfont_S *p_cmap,
@@ -2143,11 +2131,11 @@ static int prt_match_charset(char *p_charset, struct prt_ps_mbfont_S *p_cmap,
for (mbchar = 0; mbchar < p_cmap->num_charsets; mbchar++) {
if (STRNICMP(p_mbchar->charset, p_charset, char_len) == 0) {
*pp_mbchar = p_mbchar;
- return TRUE;
+ return true;
}
p_mbchar++;
}
- return FALSE;
+ return false;
}
int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
@@ -2159,17 +2147,14 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
char_u *p;
int props;
int cmap = 0;
- char_u *p_encoding;
struct prt_ps_encoding_S *p_mbenc;
struct prt_ps_encoding_S *p_mbenc_first;
struct prt_ps_charset_S *p_mbchar = NULL;
- /*
- * Set up font and encoding.
- */
- p_encoding = enc_skip(p_penc);
+ // Set up font and encoding.
+ char_u *p_encoding = (char_u *)enc_skip(p_penc);
if (*p_encoding == NUL) {
- p_encoding = enc_skip(p_enc);
+ p_encoding = (char_u *)enc_skip(p_enc);
}
// Look for a multi-byte font that matches the encoding and character set.
@@ -2188,7 +2173,7 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
p_mbenc_first = p_mbenc;
effective_cmap = cmap;
}
- if (prt_match_charset((char *)p_pmcs, &prt_ps_mbfonts[cmap], &p_mbchar)) {
+ if (prt_match_charset(p_pmcs, &prt_ps_mbfonts[cmap], &p_mbchar)) {
break;
}
}
@@ -2281,7 +2266,7 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
prt_ps_font = &prt_ps_mb_font;
} else {
- prt_use_courier = FALSE;
+ prt_use_courier = false;
prt_ps_font = &prt_ps_courier_font;
}
@@ -2298,7 +2283,7 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
paper_name = "A4";
paper_strlen = 2;
}
- for (i = 0; i < (int)PRT_MEDIASIZE_LEN; ++i) {
+ for (i = 0; i < (int)PRT_MEDIASIZE_LEN; i++) {
if (STRLEN(prt_mediasize[i].name) == (unsigned)paper_strlen
&& STRNICMP(prt_mediasize[i].name, paper_name,
paper_strlen) == 0) {
@@ -2339,7 +2324,7 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
* Set up the font size.
*/
fontsize = PRT_PS_DEFAULT_FONTSIZE;
- for (p = p_pfn; (p = (char_u *)vim_strchr((char *)p, ':')) != NULL; p++) {
+ for (p = (char_u *)p_pfn; (p = (char_u *)vim_strchr((char *)p, ':')) != NULL; p++) {
if (p[1] == 'h' && ascii_isdigit(p[2])) {
fontsize = atoi((char *)p + 2);
}
@@ -2383,16 +2368,16 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
* Set up printer duplex and tumble based on Duplex option setting - default
* is long sided duplex printing (i.e. no tumble).
*/
- prt_duplex = TRUE;
- prt_tumble = FALSE;
+ prt_duplex = true;
+ prt_tumble = false;
psettings->duplex = 1;
if (printer_opts[OPT_PRINT_DUPLEX].present) {
if (STRNICMP(printer_opts[OPT_PRINT_DUPLEX].string, "off", 3) == 0) {
- prt_duplex = FALSE;
+ prt_duplex = false;
psettings->duplex = 0;
} else if (STRNICMP(printer_opts[OPT_PRINT_DUPLEX].string, "short", 5)
== 0) {
- prt_tumble = TRUE;
+ prt_tumble = true;
}
}
@@ -2603,13 +2588,13 @@ bool mch_print_begin(prt_settings_T *psettings)
// that cannot be found then default to "latin1".
// Note: VIM specific encoding header is always skipped.
if (!prt_out_mbyte) {
- p_encoding = (char *)enc_skip(p_penc);
+ p_encoding = enc_skip(p_penc);
if (*p_encoding == NUL
|| !prt_find_resource(p_encoding, &res_encoding)) {
// 'printencoding' not set or not supported - find alternate
int props;
- p_encoding = (char *)enc_skip(p_enc);
+ p_encoding = enc_skip(p_enc);
props = enc_canon_props((char_u *)p_encoding);
if (!(props & ENC_8BIT)
|| !prt_find_resource(p_encoding, &res_encoding)) {
@@ -2629,9 +2614,9 @@ bool mch_print_begin(prt_settings_T *psettings)
// For the moment there are no checks on encoding resource files to
// perform
} else {
- p_encoding = (char *)enc_skip(p_penc);
+ p_encoding = enc_skip(p_penc);
if (*p_encoding == NUL) {
- p_encoding = (char *)enc_skip(p_enc);
+ p_encoding = enc_skip(p_enc);
}
if (prt_use_courier) {
// Include ASCII range encoding vector
@@ -2649,9 +2634,9 @@ bool mch_print_begin(prt_settings_T *psettings)
}
prt_conv.vc_type = CONV_NONE;
- if (!(enc_canon_props(p_enc) & enc_canon_props((char_u *)p_encoding) & ENC_8BIT)) {
+ if (!(enc_canon_props((char_u *)p_enc) & enc_canon_props((char_u *)p_encoding) & ENC_8BIT)) {
// Set up encoding conversion if required
- if (convert_setup(&prt_conv, p_enc, (char_u *)p_encoding) == FAIL) {
+ if (convert_setup(&prt_conv, p_enc, p_encoding) == FAIL) {
semsg(_("E620: Unable to convert to print encoding \"%s\""),
p_encoding);
return false;
@@ -2945,7 +2930,7 @@ int mch_print_begin_page(char_u *str)
int mch_print_blank_page(void)
{
- return mch_print_begin_page(NULL) ? (mch_print_end_page()) : FALSE;
+ return mch_print_begin_page(NULL) ? (mch_print_end_page()) : false;
}
static double prt_pos_x = 0;
@@ -3077,7 +3062,8 @@ int mch_print_text_out(char_u *const textp, size_t len)
if (prt_do_conv) {
// Convert from multi-byte to 8-bit encoding
- tofree = p = string_convert(&prt_conv, p, &len);
+ p = (char_u *)string_convert(&prt_conv, (char *)p, &len);
+ tofree = p;
if (p == NULL) {
p = (char_u *)"";
len = 0;
diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c
index 951e72ea52..308f64f011 100644
--- a/src/nvim/hashtab.c
+++ b/src/nvim/hashtab.c
@@ -67,7 +67,7 @@ void hash_clear(hashtab_T *ht)
void hash_clear_all(hashtab_T *ht, unsigned int off)
{
size_t todo = ht->ht_used;
- for (hashitem_T *hi = ht->ht_array; todo > 0; ++hi) {
+ for (hashitem_T *hi = ht->ht_array; todo > 0; hi++) {
if (!HASHITEM_EMPTY(hi)) {
xfree(hi->hi_key - off);
todo--;
@@ -356,7 +356,7 @@ static void hash_may_resize(hashtab_T *ht, size_t minitems)
hash_T newmask = newsize - 1;
size_t todo = ht->ht_used;
- for (hashitem_T *olditem = oldarray; todo > 0; ++olditem) {
+ for (hashitem_T *olditem = oldarray; todo > 0; olditem++) {
if (HASHITEM_EMPTY(olditem)) {
continue;
}
diff --git a/src/nvim/help.c b/src/nvim/help.c
index 442f2e0b7b..245d80489f 100644
--- a/src/nvim/help.c
+++ b/src/nvim/help.c
@@ -137,7 +137,7 @@ void ex_help(exarg_T *eap)
} else {
// There is no help window yet.
// Try to open the file specified by the "helpfile" option.
- if ((helpfd = os_fopen((char *)p_hf, READBIN)) == NULL) {
+ if ((helpfd = os_fopen(p_hf, READBIN)) == NULL) {
smsg(_("Sorry, help file \"%s\" not found"), p_hf);
goto erret;
}
@@ -537,7 +537,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
if (keep_lang) {
flags |= TAG_KEEP_LANG;
}
- if (find_tags(IObuff, num_matches, matches, flags, MAXCOL, NULL) == OK
+ if (find_tags((char *)IObuff, num_matches, matches, flags, MAXCOL, NULL) == OK
&& *num_matches > 0) {
// Sort the matches found on the heuristic number that is after the
// tag name.
@@ -652,7 +652,7 @@ void fix_help_buffer(void)
// Set filetype to "help".
if (STRCMP(curbuf->b_p_ft, "help") != 0) {
curbuf->b_ro_locked++;
- set_option_value("ft", 0L, "help", OPT_LOCAL);
+ set_option_value_give_err("ft", 0L, "help", OPT_LOCAL);
curbuf->b_ro_locked--;
}
@@ -701,7 +701,7 @@ void fix_help_buffer(void)
// Go through all directories in 'runtimepath', skipping
// $VIMRUNTIME.
- char *p = (char *)p_rtp;
+ char *p = p_rtp;
while (*p != NUL) {
copy_option_part(&p, (char *)NameBuff, MAXPATHL, ",");
char *const rt = vim_getenv("VIMRUNTIME");
@@ -741,8 +741,8 @@ void fix_help_buffer(void)
const char *const f2 = fnames[i2];
const char *const t1 = path_tail(f1);
const char *const t2 = path_tail(f2);
- const char *const e1 = (char *)STRRCHR(t1, '.');
- const char *const e2 = (char *)STRRCHR(t2, '.');
+ const char *const e1 = strrchr(t1, '.');
+ const char *const e2 = strrchr(t2, '.');
if (e1 == NULL || e2 == NULL) {
continue;
}
@@ -803,7 +803,7 @@ void fix_help_buffer(void)
// 'encoding' may be required.
vc.vc_type = CONV_NONE;
convert_setup(&vc,
- (char_u *)(this_utf == kTrue ? "utf-8" : "latin1"),
+ (this_utf == kTrue ? "utf-8" : "latin1"),
p_enc);
if (vc.vc_type == CONV_NONE) {
// No conversion needed.
@@ -811,7 +811,7 @@ void fix_help_buffer(void)
} else {
// Do the conversion. If it fails
// use the unconverted text.
- cp = (char *)string_convert(&vc, IObuff, NULL);
+ cp = string_convert(&vc, (char *)IObuff, NULL);
if (cp == NULL) {
cp = (char *)IObuff;
}
@@ -1169,7 +1169,7 @@ void ex_helptags(exarg_T *eap)
xpc.xp_context = EXPAND_DIRECTORIES;
dirname = (char *)ExpandOne(&xpc, (char_u *)eap->arg, NULL,
WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE);
- if (dirname == NULL || !os_isdir((char_u *)dirname)) {
+ if (dirname == NULL || !os_isdir(dirname)) {
semsg(_("E150: Not a directory: %s"), eap->arg);
} else {
do_helptags(dirname, add_help_tags, false);
diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c
index d6a18fcf8e..a78b933108 100644
--- a/src/nvim/highlight.c
+++ b/src/nvim/highlight.c
@@ -223,7 +223,7 @@ int ns_get_hl(NS *ns_hl, int hl_id, bool link, bool nodefault)
}
}
- it.attr_id = fallback ? -1 : hl_get_syn_attr((int)ns_id, hl_id, attrs);
+ it.attr_id = fallback ? -1 : hl_get_syn_attr(ns_id, hl_id, attrs);
it.version = p->hl_valid - tmp;
it.is_default = attrs.rgb_ae_attr & HL_DEFAULT;
it.link_global = attrs.rgb_ae_attr & HL_GLOBAL;
@@ -406,7 +406,7 @@ void update_ns_hl(int ns_id)
}
int *hl_attrs = **alloc;
- for (int hlf = 0; hlf < (int)HLF_COUNT; hlf++) {
+ for (int hlf = 0; hlf < HLF_COUNT; hlf++) {
int id = syn_check_group(hlf_names[hlf], STRLEN(hlf_names[hlf]));
bool optional = (hlf == HLF_INACTIVE || hlf == HLF_NFLOAT);
hl_attrs[hlf] = hl_get_ui_attr(ns_id, hlf, id, optional);
@@ -729,7 +729,7 @@ static int hl_cterm2rgb_color(int nr)
0x08, 0x12, 0x1C, 0x26, 0x30, 0x3A, 0x44, 0x4E, 0x58, 0x62, 0x6C, 0x76,
0x80, 0x8A, 0x94, 0x9E, 0xA8, 0xB2, 0xBC, 0xC6, 0xD0, 0xDA, 0xE4, 0xEE
};
- static char_u ansi_table[16][4] = {
+ static uint8_t ansi_table[16][4] = {
// R G B idx
{ 0, 0, 0, 1 }, // black
{ 224, 0, 0, 2 }, // dark red
@@ -903,7 +903,7 @@ Dictionary hlattrs2dict(Dictionary *hl_alloc, HlAttrs ae, bool use_rgb)
*hl_alloc = hl;
return hl;
} else {
- Dictionary allocated = copy_dictionary(hl);
+ Dictionary allocated = copy_dictionary(hl, NULL);
kv_destroy(hl);
return allocated;
}
diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c
index 77424de3b8..ed1f0185b7 100644
--- a/src/nvim/highlight_group.c
+++ b/src/nvim/highlight_group.c
@@ -79,6 +79,8 @@ typedef struct {
int sg_rgb_sp_idx; ///< RGB special color index
int sg_blend; ///< blend level (0-100 inclusive), -1 if unset
+
+ int sg_parent; ///< parent of @nested.group
} HlGroup;
enum {
@@ -183,6 +185,54 @@ static const char *highlight_init_both[] = {
"default link DiagnosticSignWarn DiagnosticWarn",
"default link DiagnosticSignInfo DiagnosticInfo",
"default link DiagnosticSignHint DiagnosticHint",
+
+ "default link @error Error",
+ "default link @text.underline Underlined",
+ "default link @todo Todo",
+ "default link @debug Debug",
+
+ // Miscs
+ "default link @comment Comment",
+ "default link @punctuation Delimiter",
+
+ // Constants
+ "default link @constant Constant",
+ "default link @constant.builtin Special",
+ "default link @constant.macro Define",
+ "default link @define Define",
+ "default link @macro Macro",
+ "default link @string String",
+ "default link @string.escape SpecialChar",
+ "default link @character Character",
+ "default link @character.special SpecialChar",
+ "default link @number Number",
+ "default link @boolean Boolean",
+ "default link @float Float",
+
+ // Functions
+ "default link @function Function",
+ "default link @function.builtin Special",
+ "default link @function.macro Macro",
+ "default link @parameter Identifier",
+ "default link @method Function",
+ "default link @field Identifier",
+ "default link @property Identifier",
+ "default link @constructor Special",
+
+ // Keywords
+ "default link @conditional Conditional",
+ "default link @repeat Repeat",
+ "default link @label Label",
+ "default link @operator Operator",
+ "default link @keyword Keyword",
+ "default link @exception Exception",
+
+ "default link @type Type",
+ "default link @type.definition Typedef",
+ "default link @storageclass StorageClass",
+ "default link @structure Structure",
+ "default link @include Include",
+ "default link @preproc PreProc",
NULL
};
@@ -640,7 +690,7 @@ static int color_numbers_8[28] = { 0, 4, 2, 6,
// Lookup the "cterm" value to be used for color with index "idx" in
// color_names[].
-// "boldp" will be set to TRUE or FALSE for a foreground color when using 8
+// "boldp" will be set to kTrue or kFalse for a foreground color when using 8
// colors, otherwise it will be unchanged.
int lookup_color(const int idx, const bool foreground, TriState *const boldp)
{
@@ -756,7 +806,7 @@ void set_hl_group(int id, HlAttrs attrs, Dict(highlight) *dict, int link_id)
update:
if (!updating_screen) {
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
}
need_highlight_changed = true;
}
@@ -802,14 +852,14 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
// Isolate the name.
- name_end = (const char *)skiptowhite((const char_u *)line);
+ name_end = (const char *)skiptowhite(line);
linep = (const char *)skipwhite(name_end);
// Check for "default" argument.
if (strncmp(line, "default", (size_t)(name_end - line)) == 0) {
dodefault = true;
line = linep;
- name_end = (const char *)skiptowhite((const char_u *)line);
+ name_end = (const char *)skiptowhite(line);
linep = (const char *)skipwhite(name_end);
}
@@ -841,9 +891,9 @@ void do_highlight(const char *line, const bool forceit, const bool init)
int to_id;
HlGroup *hlgroup = NULL;
- from_end = (const char *)skiptowhite((const char_u *)from_start);
+ from_end = (const char *)skiptowhite(from_start);
to_start = (const char *)skipwhite(from_end);
- to_end = (const char *)skiptowhite((const char_u *)to_start);
+ to_end = (const char *)skiptowhite(to_start);
if (ends_excmd((uint8_t)(*from_start))
|| ends_excmd((uint8_t)(*to_start))) {
@@ -893,7 +943,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
hlgroup->sg_script_ctx.sc_lnum += SOURCING_LNUM;
nlua_set_sctx(&hlgroup->sg_script_ctx);
hlgroup->sg_cleared = false;
- redraw_all_later(SOME_VALID);
+ redraw_all_later(UPD_SOME_VALID);
// Only call highlight changed() once after multiple changes
need_highlight_changed = true;
@@ -916,10 +966,10 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
init_highlight(true, true);
highlight_changed();
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
return;
}
- name_end = (const char *)skiptowhite((const char_u *)line);
+ name_end = (const char *)skiptowhite(line);
linep = (const char *)skipwhite(name_end);
}
@@ -1004,7 +1054,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
} else {
arg_start = linep;
- linep = (const char *)skiptowhite((const char_u *)linep);
+ linep = (const char *)skiptowhite(linep);
}
if (linep == arg_start) {
semsg(_("E417: missing argument: %s"), key_start);
@@ -1156,7 +1206,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
if (dark != -1
&& dark != (*p_bg == 'd')
&& !option_was_set("bg")) {
- set_option_value("bg", 0L, (dark ? "dark" : "light"), 0);
+ set_option_value_give_err("bg", 0L, (dark ? "dark" : "light"), 0);
reset_option_was_set("bg");
}
}
@@ -1270,12 +1320,12 @@ void do_highlight(const char *line, const bool forceit, const bool init)
// changed
ui_refresh();
} else {
- // TUI and newer UIs will repaint the screen themselves. NOT_VALID
+ // TUI and newer UIs will repaint the screen themselves. UPD_NOT_VALID
// redraw below will still handle usages of guibg=fg etc.
ui_default_colors_set();
}
did_highlight_changed = true;
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
} else {
set_hl_attr(idx);
}
@@ -1292,7 +1342,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
// redrawing. This may happen when evaluating 'statusline' changes the
// StatusLine group.
if (!updating_screen) {
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
}
need_highlight_changed = true;
}
@@ -1303,7 +1353,7 @@ void free_highlight(void)
{
ga_clear(&highlight_ga);
map_destroy(cstr_t, int)(&highlight_unames);
- arena_mem_free(arena_finish(&highlight_arena), NULL);
+ arena_mem_free(arena_finish(&highlight_arena));
}
#endif
@@ -1321,7 +1371,7 @@ void restore_cterm_colors(void)
/// @param check_link if true also check for an existing link.
///
-/// @return TRUE if highlight group "idx" has any settings.
+/// @return true if highlight group "idx" has any settings.
static int hl_has_settings(int idx, bool check_link)
{
return hl_table[idx].sg_cleared == 0
@@ -1371,7 +1421,12 @@ static void highlight_list_one(const int id)
const HlGroup *sgp = &hl_table[id - 1]; // index is ID minus one
bool didh = false;
- if (message_filtered(sgp->sg_name)) {
+ if (message_filtered((char *)sgp->sg_name)) {
+ return;
+ }
+
+ // don't list specialized groups if a parent is used instead
+ if (sgp->sg_parent && sgp->sg_cleared) {
return;
}
@@ -1661,7 +1716,12 @@ static void set_hl_attr(int idx)
int syn_name2id(const char *name)
FUNC_ATTR_NONNULL_ALL
{
- return syn_name2id_len(name, STRLEN(name));
+ if (name[0] == '@') {
+ // if we look up @aaa.bbb, we have to consider @aaa as well
+ return syn_check_group(name, strlen(name));
+ } else {
+ return syn_name2id_len(name, STRLEN(name));
+ }
}
/// Lookup a highlight group name and return its ID.
@@ -1701,7 +1761,7 @@ int syn_name2attr(const char_u *name)
return 0;
}
-/// Return TRUE if highlight group "name" exists.
+/// Return true if highlight group "name" exists.
int highlight_exists(const char *name)
{
return syn_name2id(name) > 0;
@@ -1750,11 +1810,19 @@ static int syn_add_group(const char *name, size_t len)
if (!vim_isprintc(c)) {
emsg(_("E669: Unprintable character in group name"));
return 0;
- } else if (!ASCII_ISALNUM(c) && c != '_') {
- // This is an error, but since there previously was no check only give a warning.
+ } else if (!ASCII_ISALNUM(c) && c != '_' && c != '.' && c != '@') {
+ // '.' and '@' are allowed characters for use with treesitter capture names.
msg_source(HL_ATTR(HLF_W));
- msg(_("W18: Invalid character in group name"));
- break;
+ emsg(_(e_highlight_group_name_invalid_char));
+ return 0;
+ }
+ }
+
+ int scoped_parent = 0;
+ if (len > 1 && name[0] == '@') {
+ char *delim = xmemrchr(name, '.', len);
+ if (delim) {
+ scoped_parent = syn_check_group(name, (size_t)(delim - name));
}
}
@@ -1783,6 +1851,9 @@ static int syn_add_group(const char *name, size_t len)
hlgp->sg_rgb_sp_idx = kColorIdxNone;
hlgp->sg_blend = -1;
hlgp->sg_name_u = arena_memdupz(&highlight_arena, name, len);
+ hlgp->sg_parent = scoped_parent;
+ // will get set to false by caller if settings are added
+ hlgp->sg_cleared = true;
vim_strup((char_u *)hlgp->sg_name_u);
int id = highlight_ga.ga_len; // ID is index plus one
@@ -1844,10 +1915,13 @@ int syn_ns_get_final_id(int *ns_id, int hl_id)
continue;
}
- if (sgp->sg_link == 0 || sgp->sg_link > highlight_ga.ga_len) {
+ if (sgp->sg_link > 0 && sgp->sg_link <= highlight_ga.ga_len) {
+ hl_id = sgp->sg_link;
+ } else if (sgp->sg_cleared && sgp->sg_parent > 0) {
+ hl_id = sgp->sg_parent;
+ } else {
break;
}
- hl_id = sgp->sg_link;
}
return hl_id;
@@ -2000,13 +2074,13 @@ void set_context_in_highlight_cmd(expand_T *xp, const char *arg)
// (part of) subcommand already typed
if (*arg != NUL) {
- const char *p = (const char *)skiptowhite((const char_u *)arg);
+ const char *p = (const char *)skiptowhite(arg);
if (*p != NUL) { // Past "default" or group name.
include_default = 0;
if (strncmp("default", arg, (unsigned)(p - arg)) == 0) {
arg = (const char *)skipwhite(p);
xp->xp_pattern = (char *)arg;
- p = (const char *)skiptowhite((const char_u *)arg);
+ p = (const char *)skiptowhite(arg);
}
if (*p != NUL) { // past group name
include_link = 0;
@@ -2016,10 +2090,10 @@ void set_context_in_highlight_cmd(expand_T *xp, const char *arg)
if (strncmp("link", arg, (unsigned)(p - arg)) == 0
|| strncmp("clear", arg, (unsigned)(p - arg)) == 0) {
xp->xp_pattern = skipwhite(p);
- p = (const char *)skiptowhite((char_u *)xp->xp_pattern);
+ p = (const char *)skiptowhite(xp->xp_pattern);
if (*p != NUL) { // Past first group name.
xp->xp_pattern = skipwhite(p);
- p = (const char *)skiptowhite((char_u *)xp->xp_pattern);
+ p = (const char *)skiptowhite(xp->xp_pattern);
}
}
if (*p != NUL) { // Past group name(s).
diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c
index 689d1fce0d..9413abb2e1 100644
--- a/src/nvim/if_cscope.c
+++ b/src/nvim/if_cscope.c
@@ -153,10 +153,10 @@ void set_context_in_cscope_cmd(expand_T *xp, const char *arg, cmdidx_T cmdidx)
// (part of) subcommand already typed
if (*arg != NUL) {
- const char *p = (const char *)skiptowhite((const char_u *)arg);
+ const char *p = (const char *)skiptowhite(arg);
if (*p != NUL) { // Past first word.
xp->xp_pattern = skipwhite(p);
- if (*skiptowhite((char_u *)xp->xp_pattern) != NUL) {
+ if (*skiptowhite(xp->xp_pattern) != NUL) {
xp->xp_context = EXPAND_NOTHING;
} else if (STRNICMP(arg, "add", p - arg) == 0) {
xp->xp_context = EXPAND_FILES;
@@ -203,19 +203,19 @@ static void do_cscope_general(exarg_T *eap, int make_split)
/// Implementation of ":cscope" and ":lcscope"
void ex_cscope(exarg_T *eap)
{
- do_cscope_general(eap, FALSE);
+ do_cscope_general(eap, false);
}
/// Implementation of ":scscope". Same as ex_cscope(), but splits window, too.
void ex_scscope(exarg_T *eap)
{
- do_cscope_general(eap, TRUE);
+ do_cscope_general(eap, true);
}
/// Implementation of ":cstag"
void ex_cstag(exarg_T *eap)
{
- int ret = FALSE;
+ int ret = false;
if (*eap->arg == NUL) {
(void)emsg(_("E562: Usage: cstag <ident>"));
@@ -278,7 +278,7 @@ void ex_cstag(exarg_T *eap)
/// This simulates a vim_fgets(), but for cscope, returns the next line
/// from the cscope output. should only be called from find_tags()
///
-/// @return true if eof, FALSE otherwise
+/// @return true if eof, false otherwise
bool cs_fgets(char_u *buf, int size)
FUNC_ATTR_NONNULL_ALL
{
@@ -423,7 +423,7 @@ static int cs_add_common(char *arg1, char *arg2, char *flags)
// get the filename (arg1), expand it, and try to stat it
fname = xmalloc(MAXPATHL + 1);
- expand_env((char_u *)arg1, (char_u *)fname, MAXPATHL);
+ expand_env(arg1, fname, MAXPATHL);
size_t len = STRLEN(fname);
fbuf = fname;
(void)modify_fname(":p", false, &usedlen, &fname, &fbuf, &len);
@@ -445,7 +445,7 @@ staterr:
// get the prepend path (arg2), expand it, and see if it exists
if (arg2 != NULL) {
ppath = xmalloc(MAXPATHL + 1);
- expand_env((char_u *)arg2, (char_u *)ppath, MAXPATHL);
+ expand_env(arg2, ppath, MAXPATHL);
if (!os_path_exists((char_u *)ppath)) {
goto staterr;
}
@@ -757,14 +757,14 @@ err_closing:
#endif
// expand the cscope exec for env var's
prog = xmalloc(MAXPATHL + 1);
- expand_env(p_csprg, (char_u *)prog, MAXPATHL);
+ expand_env(p_csprg, prog, MAXPATHL);
// alloc space to hold the cscope command
size_t len = strlen(prog) + strlen(csinfo[i].fname) + 32;
if (csinfo[i].ppath) {
// expand the prepend path for env var's
ppath = xmalloc(MAXPATHL + 1);
- expand_env((char_u *)csinfo[i].ppath, (char_u *)ppath, MAXPATHL);
+ expand_env(csinfo[i].ppath, ppath, MAXPATHL);
len += strlen(ppath);
}
@@ -839,7 +839,7 @@ err_closing:
si.hStdOutput = stdout_wr;
si.hStdError = stdout_wr;
si.hStdInput = stdin_rd;
- created = CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE,
+ created = CreateProcess(NULL, cmd, NULL, NULL, true, CREATE_NEW_CONSOLE,
NULL, NULL, &si, &pi);
xfree(prog);
xfree(cmd);
@@ -875,7 +875,7 @@ err_closing:
/// Query cscope using command line interface. Parse the output and use tselect
/// to allow choices. Like Nvi, creates a pipe to send to/from query/cscope.
///
-/// @return TRUE if we jump to a tag or abort, FALSE if not.
+/// @return true if we jump to a tag or abort, false if not.
static int cs_find(exarg_T *eap)
{
char *opt, *pat;
@@ -900,7 +900,7 @@ 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) {
+ for (int i = 0; i < eap_arg_len; i++) {
if (NUL == eap->arg[i]) {
eap->arg[i] = ' ';
}
@@ -953,7 +953,7 @@ static bool cs_find_common(char *opt, char *pat, int forceit, int verbose, bool
cmdletter = opt[0];
}
- qfpos = vim_strchr((char *)p_csqf, cmdletter);
+ qfpos = vim_strchr(p_csqf, cmdletter);
if (qfpos != NULL) {
qfpos++;
// next symbol must be + or -
@@ -1106,7 +1106,7 @@ static int cs_help(exarg_T *eap)
cmdp++;
}
- wait_return(TRUE);
+ wait_return(true);
return CSCOPE_SUCCESS;
}
@@ -1280,7 +1280,7 @@ static void cs_kill_execute(size_t i, char *cname)
(void)smsg_attr(HL_ATTR(HLF_R) | MSG_HIST,
_("cscope connection %s closed"), cname);
}
- cs_release_csp(i, TRUE);
+ cs_release_csp(i, true);
}
/// Convert the cscope output into a ctags style entry (as might be found
@@ -1838,7 +1838,7 @@ static void cs_release_csp(size_t i, bool freefnpp)
// Can't use sigaction(), loop for two seconds. First yield the CPU
// to give cscope a chance to exit quickly.
sleep(0);
- for (waited = 0; waited < 40; ++waited) {
+ for (waited = 0; waited < 40; waited++) {
pid = waitpid(csinfo[i].pid, &pstat, WNOHANG);
waitpid_errno = errno;
if (pid != 0) {
@@ -1932,7 +1932,7 @@ static int cs_reset(exarg_T *eap)
pplist[i] = csinfo[i].ppath;
fllist[i] = csinfo[i].flags;
if (csinfo[i].fname != NULL) {
- cs_release_csp(i, FALSE);
+ cs_release_csp(i, false);
}
}
@@ -2035,7 +2035,7 @@ static int cs_show(exarg_T *eap)
}
}
- wait_return(TRUE);
+ wait_return(false);
return CSCOPE_SUCCESS;
}
diff --git a/src/nvim/indent.c b/src/nvim/indent.c
index f18a6d7b32..792f4d93c4 100644
--- a/src/nvim/indent.c
+++ b/src/nvim/indent.c
@@ -25,6 +25,7 @@
#include "nvim/screen.h"
#include "nvim/search.h"
#include "nvim/strings.h"
+#include "nvim/textformat.h"
#include "nvim/undo.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -33,12 +34,13 @@
/// Set the integer values corresponding to the string setting of 'vartabstop'.
/// "array" will be set, caller must free it if needed.
-/// Return false for an error.
-bool tabstop_set(char_u *var, long **array)
+///
+/// @return false for an error.
+bool tabstop_set(char *var, long **array)
{
long valcount = 1;
int t;
- char_u *cp;
+ char *cp;
if (var[0] == NUL || (var[0] == '0' && var[1] == NUL)) {
*array = NULL;
@@ -49,8 +51,8 @@ bool tabstop_set(char_u *var, long **array)
if (cp == var || cp[-1] == ',') {
char *end;
- if (strtol((char *)cp, &end, 10) <= 0) {
- if (cp != (char_u *)end) {
+ if (strtol(cp, &end, 10) <= 0) {
+ if (cp != end) {
emsg(_(e_positive));
} else {
semsg(_(e_invarg2), cp);
@@ -75,7 +77,7 @@ bool tabstop_set(char_u *var, long **array)
t = 1;
for (cp = var; *cp != NUL;) {
- int n = atoi((char *)cp);
+ int n = atoi(cp);
// Catch negative values, overflow and ridiculous big values.
if (n <= 0 || n > TABSTOP_MAX) {
@@ -341,7 +343,7 @@ int get_sts_value(void)
// Count the size (in window cells) of the indent in the current line.
int get_indent(void)
{
- return get_indent_str_vtab(get_cursor_line_ptr(),
+ return get_indent_str_vtab((char *)get_cursor_line_ptr(),
curbuf->b_p_ts,
curbuf->b_p_vts_array,
false);
@@ -350,7 +352,7 @@ int get_indent(void)
// Count the size (in window cells) of the indent in line "lnum".
int get_indent_lnum(linenr_T lnum)
{
- return get_indent_str_vtab(ml_get(lnum),
+ return get_indent_str_vtab((char *)ml_get(lnum),
curbuf->b_p_ts,
curbuf->b_p_vts_array,
false);
@@ -360,7 +362,7 @@ int get_indent_lnum(linenr_T lnum)
// "buf".
int get_indent_buf(buf_T *buf, linenr_T lnum)
{
- return get_indent_str_vtab(ml_get_buf(buf, lnum, false),
+ return get_indent_str_vtab((char *)ml_get_buf(buf, lnum, false),
curbuf->b_p_ts,
buf->b_p_vts_array,
false);
@@ -398,7 +400,7 @@ int get_indent_str(const char_u *ptr, int ts, bool list)
/// Count the size (in window cells) of the indent in line "ptr", using
/// variable tabstops.
/// if "list" is true, count only screen size for tabs.
-int get_indent_str_vtab(const char_u *ptr, long ts, long *vts, bool list)
+int get_indent_str_vtab(const char *ptr, long ts, long *vts, bool list)
{
int count = 0;
@@ -710,7 +712,7 @@ int get_number_indent(linenr_T lnum)
if ((State & MODE_INSERT) || has_format_option(FO_Q_COMS)) {
lead_len = get_leader_len((char *)ml_get(lnum), NULL, false, true);
}
- regmatch.regprog = vim_regcomp((char *)curbuf->b_p_flp, RE_MAGIC);
+ regmatch.regprog = vim_regcomp(curbuf->b_p_flp, RE_MAGIC);
if (regmatch.regprog != NULL) {
regmatch.rm_ic = false;
@@ -732,6 +734,47 @@ int get_number_indent(linenr_T lnum)
return (int)col;
}
+/// This is called when 'breakindentopt' is changed and when a window is
+/// initialized
+bool briopt_check(win_T *wp)
+{
+ int bri_shift = 0;
+ int bri_min = 20;
+ bool bri_sbr = false;
+ int bri_list = 0;
+
+ char *p = wp->w_p_briopt;
+ while (*p != NUL) {
+ if (STRNCMP(p, "shift:", 6) == 0
+ && ((p[6] == '-' && ascii_isdigit(p[7])) || ascii_isdigit(p[6]))) {
+ p += 6;
+ bri_shift = getdigits_int(&p, true, 0);
+ } else if (STRNCMP(p, "min:", 4) == 0 && ascii_isdigit(p[4])) {
+ p += 4;
+ bri_min = getdigits_int(&p, true, 0);
+ } else if (STRNCMP(p, "sbr", 3) == 0) {
+ p += 3;
+ bri_sbr = true;
+ } else if (STRNCMP(p, "list:", 5) == 0) {
+ p += 5;
+ bri_list = (int)getdigits(&p, false, 0);
+ }
+ if (*p != ',' && *p != NUL) {
+ return false;
+ }
+ if (*p == ',') {
+ p++;
+ }
+ }
+
+ wp->w_briopt_shift = bri_shift;
+ wp->w_briopt_min = bri_min;
+ wp->w_briopt_sbr = bri_sbr;
+ wp->w_briopt_list = bri_list;
+
+ return true;
+}
+
// Return appropriate space number for breakindent, taking influencing
// parameters into account. Window must be specified, since it is not
// necessarily always the current one.
@@ -757,7 +800,7 @@ int get_breakindent_win(win_T *wp, char_u *line)
prev_ts = wp->w_buffer->b_p_ts;
prev_tick = buf_get_changedtick(wp->w_buffer);
prev_vts = wp->w_buffer->b_p_vts_array;
- prev_indent = get_indent_str_vtab(line,
+ prev_indent = get_indent_str_vtab((char *)line,
wp->w_buffer->b_p_ts,
wp->w_buffer->b_p_vts_array,
wp->w_p_list);
@@ -770,7 +813,7 @@ int get_breakindent_win(win_T *wp, char_u *line)
// add additional indent for numbered lists
if (wp->w_briopt_list != 0) {
regmatch_T regmatch = {
- .regprog = vim_regcomp((char *)curbuf->b_p_flp,
+ .regprog = vim_regcomp(curbuf->b_p_flp,
RE_MAGIC + RE_STRING + RE_AUTO + RE_STRICT),
};
@@ -855,7 +898,7 @@ int get_expr_indent(void)
// Need to make a copy, the 'indentexpr' option could be changed while
// evaluating it.
- char_u *inde_copy = vim_strsave(curbuf->b_p_inde);
+ char_u *inde_copy = vim_strsave((char_u *)curbuf->b_p_inde);
indent = (int)eval_to_number((char *)inde_copy);
xfree(inde_copy);
@@ -992,13 +1035,15 @@ int get_lisp_indent(void)
amount = 2;
} else {
char_u *line = that;
-
- amount = 0;
-
- while (*that && col) {
- amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount);
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, pos->lnum, 0, line, line);
+ while (*cts.cts_ptr != NUL && col > 0) {
+ cts.cts_vcol += lbr_chartabsize_adv(&cts);
col--;
}
+ amount = cts.cts_vcol;
+ that = (char_u *)cts.cts_ptr;
+ clear_chartabsize_arg(&cts);
// Some keywords require "body" indenting rules (the
// non-standard-lisp ones are Scheme special forms):
@@ -1014,10 +1059,15 @@ int get_lisp_indent(void)
}
firsttry = amount;
- while (ascii_iswhite(*that)) {
- amount += lbr_chartabsize(line, that, (colnr_T)amount);
- that++;
+ init_chartabsize_arg(&cts, curwin, (colnr_T)(that - line),
+ amount, line, that);
+ while (ascii_iswhite(*cts.cts_ptr)) {
+ cts.cts_vcol += lbr_chartabsize(&cts);
+ cts.cts_ptr++;
}
+ that = (char_u *)cts.cts_ptr;
+ amount = cts.cts_vcol;
+ clear_chartabsize_arg(&cts);
if (*that && (*that != ';')) {
// Not a comment line.
@@ -1030,33 +1080,38 @@ int get_lisp_indent(void)
parencount = 0;
quotecount = 0;
+ init_chartabsize_arg(&cts, curwin,
+ (colnr_T)(that - line), amount, line, that);
if (vi_lisp || ((*that != '"') && (*that != '\'')
&& (*that != '#') && ((*that < '0') || (*that > '9')))) {
- while (*that
- && (!ascii_iswhite(*that) || quotecount || parencount)
- && (!((*that == '(' || *that == '[')
+ while (*cts.cts_ptr
+ && (!ascii_iswhite(*cts.cts_ptr) || quotecount || parencount)
+ && (!((*cts.cts_ptr == '(' || *cts.cts_ptr == '[')
&& !quotecount && !parencount && vi_lisp))) {
- if (*that == '"') {
+ if (*cts.cts_ptr == '"') {
quotecount = !quotecount;
}
- if (((*that == '(') || (*that == '[')) && !quotecount) {
+ if (((*cts.cts_ptr == '(') || (*cts.cts_ptr == '[')) && !quotecount) {
parencount++;
}
- if (((*that == ')') || (*that == ']')) && !quotecount) {
+ if (((*cts.cts_ptr == ')') || (*cts.cts_ptr == ']')) && !quotecount) {
parencount--;
}
- if ((*that == '\\') && (*(that + 1) != NUL)) {
- amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount);
+ if ((*cts.cts_ptr == '\\') && (*(cts.cts_ptr + 1) != NUL)) {
+ cts.cts_vcol += lbr_chartabsize_adv(&cts);
}
- amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount);
+ cts.cts_vcol += lbr_chartabsize_adv(&cts);
}
}
- while (ascii_iswhite(*that)) {
- amount += lbr_chartabsize(line, that, (colnr_T)amount);
- that++;
+ while (ascii_iswhite(*cts.cts_ptr)) {
+ cts.cts_vcol += lbr_chartabsize(&cts);
+ cts.cts_ptr++;
}
+ that = (char_u *)cts.cts_ptr;
+ amount = cts.cts_vcol;
+ clear_chartabsize_arg(&cts);
if (!*that || (*that == ';')) {
amount = firsttry;
@@ -1077,7 +1132,7 @@ static int lisp_match(char_u *p)
{
char_u buf[LSIZE];
int len;
- char *word = (char *)(*curbuf->b_p_lw != NUL ? curbuf->b_p_lw : p_lispwords);
+ char *word = (char *)(*curbuf->b_p_lw != NUL ? (char_u *)curbuf->b_p_lw : p_lispwords);
while (*word != NUL) {
(void)copy_option_part(&word, (char *)buf, LSIZE, ",");
diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c
index 34a3de4f78..166695ef5b 100644
--- a/src/nvim/indent_c.c
+++ b/src/nvim/indent_c.c
@@ -212,18 +212,16 @@ int is_pos_in_string(const char_u *line, colnr_T col)
* Below "XXX" means that this function may unlock the current line.
*/
-/*
- * Return true if the string "line" starts with a word from 'cinwords'.
- */
-bool cin_is_cinword(const char_u *line)
+/// @return true if the string "line" starts with a word from 'cinwords'.
+bool cin_is_cinword(const char *line)
{
bool retval = false;
size_t cinw_len = STRLEN(curbuf->b_p_cinw) + 1;
char_u *cinw_buf = xmalloc(cinw_len);
- line = (char_u *)skipwhite((char *)line);
+ line = skipwhite((char *)line);
- for (char *cinw = (char *)curbuf->b_p_cinw; *cinw;) {
+ for (char *cinw = curbuf->b_p_cinw; *cinw;) {
size_t len = copy_option_part(&cinw, (char *)cinw_buf, cinw_len, ",");
if (STRNCMP(line, cinw_buf, len) == 0
&& (!vim_iswordc(line[len]) || !vim_iswordc(line[len - 1]))) {
@@ -275,10 +273,8 @@ static const char_u *cin_skipcomment(const char_u *s)
return s;
}
-/*
- * Return TRUE if there is no code at *s. White space and comments are
- * not considered code.
- */
+/// Return true if there is no code at *s. White space and comments are
+/// not considered code.
static int cin_nocode(const char_u *s)
{
return *cin_skipcomment(s) == NUL;
@@ -383,7 +379,7 @@ bool cin_islabel(void) // XXX
cursor_save = curwin->w_cursor;
while (curwin->w_cursor.lnum > 1) {
- --curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum--;
/*
* If we're in a comment or raw string now, skip to the start of
@@ -403,7 +399,7 @@ bool cin_islabel(void) // XXX
}
curwin->w_cursor = cursor_save;
- if (cin_isterminated(line, TRUE, FALSE)
+ if (cin_isterminated(line, true, false)
|| cin_isscopedecl(line)
|| cin_iscase(line, true)
|| (cin_islabel_skip(&line) && cin_nocode(line))) {
@@ -434,7 +430,7 @@ static int cin_isinit(void)
for (;;) {
int i, l;
- for (i = 0; i < (int)ARRAY_SIZE(skip); ++i) {
+ for (i = 0; i < (int)ARRAY_SIZE(skip); i++) {
l = (int)strlen(skip[i]);
if (cin_starts_with(s, skip[i])) {
s = cin_skipcomment(s + l);
@@ -455,7 +451,7 @@ static int cin_isinit(void)
return true;
}
- return FALSE;
+ return false;
}
/// Recognize a switch label: "case .*:" or "default:".
@@ -465,7 +461,7 @@ bool cin_iscase(const char_u *s, bool strict)
{
s = cin_skipcomment(s);
if (cin_starts_with(s, "case")) {
- for (s += 4; *s; ++s) {
+ for (s += 4; *s; s++) {
s = cin_skipcomment(s);
if (*s == NUL) {
break;
@@ -519,7 +515,7 @@ bool cin_isscopedecl(const char_u *p)
bool found = false;
- for (char *cinsd = (char *)curbuf->b_p_cinsd; *cinsd;) {
+ for (char *cinsd = curbuf->b_p_cinsd; *cinsd;) {
const size_t len = copy_option_part(&cinsd, (char *)cinsd_buf, cinsd_len, ",");
if (STRNCMP(s, cinsd_buf, len) == 0) {
const char_u *skip = cin_skipcomment(s + len);
@@ -588,7 +584,7 @@ static bool cin_is_cpp_namespace(const char_u *s)
*/
static const char_u *after_label(const char_u *l)
{
- for (; *l; ++l) {
+ for (; *l; l++) {
if (*l == ':') {
if (l[1] == ':') { // skip over "::" for C++
l++;
@@ -680,10 +676,10 @@ static int cin_first_id_amount(void)
line = get_cursor_line_ptr();
p = (char_u *)skipwhite((char *)line);
- len = (int)(skiptowhite(p) - p);
+ len = (int)((char_u *)skiptowhite((char *)p) - p);
if (len == 6 && STRNCMP(p, "static", 6) == 0) {
p = (char_u *)skipwhite((char *)p + 6);
- len = (int)(skiptowhite(p) - p);
+ len = (int)((char_u *)skiptowhite((char *)p) - p);
}
if (len == 6 && STRNCMP(p, "struct", 6) == 0) {
p = (char_u *)skipwhite((char *)p + 6);
@@ -769,10 +765,10 @@ static int cin_ispreproc(const char_u *s)
if (*skipwhite((char *)s) == '#') {
return true;
}
- return FALSE;
+ return false;
}
-/// Return TRUE if line "*pp" at "*lnump" is a preprocessor statement or a
+/// Return true if line "*pp" at "*lnump" is a preprocessor statement or a
/// continuation line of a preprocessor statement. Decrease "*lnump" to the
/// start and return the line in "*pp".
/// Put the amount of indent in "*amount".
@@ -789,7 +785,7 @@ static int cin_ispreproc_cont(const char_u **pp, linenr_T *lnump, int *amount)
for (;;) {
if (cin_ispreproc(line)) {
- retval = TRUE;
+ retval = true;
*lnump = lnum;
break;
}
@@ -842,7 +838,7 @@ static char_u cin_isterminated(const char_u *s, int incl_open, int incl_comma)
{
char_u found_start = 0;
unsigned n_open = 0;
- int is_else = FALSE;
+ int is_else = false;
s = cin_skipcomment(s);
@@ -1095,14 +1091,12 @@ probablyFound:
return 0;
}
-/*
- * Return TRUE if we are at the end of a do-while.
- * do
- * nothing;
- * while (foo
- * && bar); <-- here
- * Adjust the cursor to the line with "while".
- */
+/// Return true if we are at the end of a do-while.
+/// do
+/// nothing;
+/// while (foo
+/// && bar); <-- here
+/// Adjust the cursor to the line with "while".
static int cin_iswhileofdo_end(int terminated)
{
const char_u *line;
@@ -1133,7 +1127,7 @@ static int cin_iswhileofdo_end(int terminated)
}
if (cin_starts_with(s, "while")) {
curwin->w_cursor.lnum = trypos->lnum;
- return TRUE;
+ return true;
}
}
@@ -1146,7 +1140,7 @@ static int cin_iswhileofdo_end(int terminated)
p++;
}
}
- return FALSE;
+ return false;
}
static int cin_isbreak(const char_u *p)
@@ -1190,7 +1184,7 @@ static int cin_is_cpp_baseclass(cpp_baseclass_cache_T *cached)
return false;
}
- cpp_base_class = lookfor_ctor_init = class_or_struct = FALSE;
+ cpp_base_class = lookfor_ctor_init = class_or_struct = false;
/* Search for a line starting with '#', empty, ending in ';' or containing
* '{' or '}' and start below it. This handles the following situations:
@@ -1256,7 +1250,7 @@ static int cin_is_cpp_baseclass(cpp_baseclass_cache_T *cached)
if (s[1] == ':') {
/* skip double colon. It can't be a constructor
* initialization any more */
- lookfor_ctor_init = FALSE;
+ lookfor_ctor_init = false;
s = cin_skipcomment(s + 2);
} else if (lookfor_ctor_init || class_or_struct) {
/* we have something found, that looks like the start of
@@ -1270,8 +1264,8 @@ static int cin_is_cpp_baseclass(cpp_baseclass_cache_T *cached)
}
} else if ((STRNCMP(s, "class", 5) == 0 && !vim_isIDc(s[5]))
|| (STRNCMP(s, "struct", 6) == 0 && !vim_isIDc(s[6]))) {
- class_or_struct = TRUE;
- lookfor_ctor_init = FALSE;
+ class_or_struct = true;
+ lookfor_ctor_init = false;
if (*s == 'c') {
s = cin_skipcomment(s + 5);
@@ -1280,12 +1274,12 @@ static int cin_is_cpp_baseclass(cpp_baseclass_cache_T *cached)
}
} else {
if (s[0] == '{' || s[0] == '}' || s[0] == ';') {
- cpp_base_class = lookfor_ctor_init = class_or_struct = FALSE;
+ cpp_base_class = lookfor_ctor_init = class_or_struct = false;
} else if (s[0] == ')') {
/* Constructor-initialization is assumed if we come across
* something like "):" */
- class_or_struct = FALSE;
- lookfor_ctor_init = TRUE;
+ class_or_struct = false;
+ lookfor_ctor_init = true;
} else if (s[0] == '?') {
// Avoid seeing '() :' after '?' as constructor init.
return false;
@@ -1345,11 +1339,9 @@ static int get_baseclass_amount(int col)
return amount;
}
-/*
- * Return TRUE if string "s" ends with the string "find", possibly followed by
- * white space and comments. Skip strings and comments.
- * Ignore "ignore" after "find" if it's not NULL.
- */
+/// Return true if string "s" ends with the string "find", possibly followed by
+/// white space and comments. Skip strings and comments.
+/// Ignore "ignore" after "find" if it's not NULL.
static int cin_ends_in(const char_u *s, const char_u *find, const char_u *ignore)
{
const char_u *p = s;
@@ -1371,12 +1363,10 @@ static int cin_ends_in(const char_u *s, const char_u *find, const char_u *ignore
p++;
}
}
- return FALSE;
+ return false;
}
-/*
- * Return TRUE when "s" starts with "word" and then a non-ID character.
- */
+/// Return true when "s" starts with "word" and then a non-ID character.
static int cin_starts_with(const char_u *s, const char *word)
{
int l = (int)STRLEN(word);
@@ -1573,7 +1563,7 @@ static int corr_ind_maxparen(pos_T *startpos)
static int find_last_paren(const char_u *l, int start, int end)
{
int i;
- int retval = FALSE;
+ int retval = false;
int open_count = 0;
curwin->w_cursor.col = 0; // default is start of line
@@ -1588,7 +1578,7 @@ static int find_last_paren(const char_u *l, int start, int end)
open_count--;
} else {
curwin->w_cursor.col = i;
- retval = TRUE;
+ retval = true;
}
}
}
@@ -1740,7 +1730,7 @@ void parse_cino(buf_T *buf)
// Handle C #pragma directives
buf->b_ind_pragma = 0;
- for (p = (char *)buf->b_p_cino; *p;) {
+ for (p = buf->b_p_cino; *p;) {
l = p++;
if (*p == '-') {
p++;
@@ -2029,7 +2019,7 @@ int get_c_indent(void)
if (trypos == NULL && curwin->w_cursor.lnum > 1) {
// There may be a statement before the comment, search from the end
// of the line for a comment start.
- linecomment_pos.col = check_linecomment(ml_get(curwin->w_cursor.lnum - 1));
+ linecomment_pos.col = check_linecomment((char *)ml_get(curwin->w_cursor.lnum - 1));
if (linecomment_pos.col != MAXCOL) {
trypos = &linecomment_pos;
trypos->lnum = curwin->w_cursor.lnum - 1;
@@ -2055,7 +2045,7 @@ int get_c_indent(void)
char *p;
int start_align = 0;
int start_off = 0;
- int done = FALSE;
+ int done = false;
// find how indented the line beginning the comment is
getvcol(curwin, comment_pos, &col, NULL, NULL);
@@ -2063,7 +2053,7 @@ int get_c_indent(void)
*lead_start = NUL;
*lead_middle = NUL;
- p = (char *)curbuf->b_p_com;
+ p = curbuf->b_p_com;
while (*p != NUL) {
int align = 0;
int off = 0;
@@ -2098,7 +2088,7 @@ int get_c_indent(void)
* up with the comment opener per the 'comments' option. */
if (STRNCMP(theline, lead_middle, lead_middle_len) == 0
&& STRNCMP(theline, lead_end, STRLEN(lead_end)) != 0) {
- done = TRUE;
+ done = true;
if (curwin->w_cursor.lnum > 1) {
/* If the start comment string matches in the previous
* line, use the indent of that line plus offset. If
@@ -2330,7 +2320,7 @@ int get_c_indent(void)
/* look for opening unmatched paren, indent one level
* for each additional level */
n = 1;
- for (col = 0; col < our_paren_pos.col; ++col) {
+ for (col = 0; col < our_paren_pos.col; col++) {
switch (l[col]) {
case '(':
case '{':
@@ -2388,7 +2378,7 @@ int get_c_indent(void)
* but ignore (void) before the line (ignore_paren_col). */
col = our_paren_pos.col;
while ((int)our_paren_pos.col > ignore_paren_col) {
- --our_paren_pos.col;
+ our_paren_pos.col--;
switch (*ml_get_pos(&our_paren_pos)) {
case '(':
amount += curbuf->b_ind_unclosed2;
@@ -2562,7 +2552,7 @@ int get_c_indent(void)
}
}
- lookfor_break = FALSE;
+ lookfor_break = false;
if (cin_iscase(theline, false)) { // it's a switch() label
lookfor = LOOKFOR_CASE; // find a previous switch() label
@@ -2646,7 +2636,7 @@ int get_c_indent(void)
continue;
}
- terminated = cin_isterminated(l, FALSE, TRUE);
+ terminated = cin_isterminated(l, false, true);
/*
* If we are at top level and the line looks like a
@@ -2660,7 +2650,7 @@ int get_c_indent(void)
* don't add extra indent.
* TODO: does not work, if a function
* declaration is split over multiple lines:
- * cin_isfuncdecl returns FALSE then.
+ * cin_isfuncdecl returns false then.
*/
if (terminated == ',') {
break;
@@ -2862,7 +2852,7 @@ int get_c_indent(void)
if (n) {
amount = n;
l = after_label(get_cursor_line_ptr());
- if (l != NULL && cin_is_cinword(l)) {
+ if (l != NULL && cin_is_cinword((char *)l)) {
if (theline[0] == '{') {
amount += curbuf->b_ind_open_extra;
} else {
@@ -2971,7 +2961,7 @@ int get_c_indent(void)
* initialisation (not indented) or a variable declaration
* (indented).
*/
- terminated = cin_isterminated(l, FALSE, TRUE);
+ terminated = cin_isterminated(l, false, true);
if (js_cur_has_key) {
js_cur_has_key = false; // only check the first line
@@ -3116,7 +3106,7 @@ int get_c_indent(void)
* Check if we are after an "if", "while", etc.
* Also allow " } else".
*/
- if (cin_is_cinword(l) || cin_iselse((char_u *)skipwhite((char *)l))) {
+ if (cin_is_cinword((char *)l) || cin_iselse((char_u *)skipwhite((char *)l))) {
// Found an unterminated line after an if (), line up
// with the last one.
// if (cond)
diff --git a/src/nvim/input.c b/src/nvim/input.c
index 37c2903cfd..0aa9feaca3 100644
--- a/src/nvim/input.c
+++ b/src/nvim/input.c
@@ -46,7 +46,7 @@ int ask_yesno(const char *const str, const bool direct)
int r = ' ';
while (r != 'y' && r != 'n') {
- // Same highlighting as for wait_return.
+ // same highlighting as for wait_return()
smsg_attr(HL_ATTR(HLF_R), "%s (y/n)?", str);
if (direct) {
r = get_keystroke(NULL);
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c
index 938189f343..ba0a36cafe 100644
--- a/src/nvim/insexpand.c
+++ b/src/nvim/insexpand.c
@@ -43,6 +43,7 @@
#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/tag.h"
+#include "nvim/textformat.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/vim.h"
@@ -140,6 +141,21 @@ struct compl_S {
int cp_number; ///< sequence number
};
+/// state information used for getting the next set of insert completion
+/// matches.
+typedef struct {
+ char *e_cpt; ///< current entry in 'complete'
+ buf_T *ins_buf; ///< buffer being scanned
+ pos_T *cur_match_pos; ///< current match position
+ pos_T prev_match_pos; ///< previous match position
+ bool set_match_pos; ///< save first_match_pos/last_match_pos
+ pos_T first_match_pos; ///< first match position
+ pos_T last_match_pos; ///< last match position
+ bool found_all; ///< found all matches of a certain type.
+ char_u *dict; ///< dictionary file to search
+ int dict_f; ///< "dict" is an exact file name or not
+} ins_compl_next_state_T;
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "insexpand.c.generated.h"
#endif
@@ -162,6 +178,7 @@ static char e_compldel[] = N_("E840: Completion function deleted text");
// "compl_curr_match" points to the currently selected entry.
// "compl_shown_match" is different from compl_curr_match during
// ins_compl_get_exp().
+// "compl_old_match" points to previous "compl_curr_match".
static compl_T *compl_first_match = NULL;
static compl_T *compl_curr_match = NULL;
@@ -203,12 +220,15 @@ static bool compl_started = false;
///< Which Ctrl-X mode are we in?
static int ctrl_x_mode = CTRL_X_NORMAL;
-static int compl_matches = 0;
+static int compl_matches = 0; ///< number of completion matches
static char *compl_pattern = NULL;
static Direction compl_direction = FORWARD;
static Direction compl_shows_dir = FORWARD;
static int compl_pending = 0; ///< > 1 for postponed CTRL-N
static pos_T compl_startpos;
+/// Length in bytes of the text being completed (this is deleted to be replaced
+/// by the match.)
+static int compl_length = 0;
static colnr_T compl_col = 0; ///< column where the text starts
///< that is being completed
static char_u *compl_orig_text = NULL; ///< text as it was before
@@ -216,6 +236,20 @@ static char_u *compl_orig_text = NULL; ///< text as it was before
static int compl_cont_mode = 0;
static expand_T compl_xp;
+// List of flags for method of completion.
+static int compl_cont_status = 0;
+
+#define CONT_ADDING 1 ///< "normal" or "adding" expansion
+#define CONT_INTRPT (2 + 4) ///< a ^X interrupted the current expansion
+ ///< it's set only iff N_ADDS is set
+#define CONT_N_ADDS 4 ///< next ^X<> will add-new or expand-current
+#define CONT_S_IPOS 8 ///< next ^X<> will set initial_pos?
+ ///< if so, word-wise-expansion will set SOL
+#define CONT_SOL 16 ///< pattern includes start of line, just for
+ ///< word-wise expansion, not set for ^X^L
+#define CONT_LOCAL 32 ///< for ctrl_x_mode 0, ^X^P/^X^N do a local
+ ///< expansion, (eg use complete=.)
+
static bool compl_opt_refresh_always = false;
static size_t spell_bad_len = 0; // length of located bad word
@@ -234,7 +268,7 @@ void ins_ctrl_x(void)
}
// We're not sure which CTRL-X mode it will be yet
ctrl_x_mode = CTRL_X_NOT_DEFINED_YET;
- edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
+ edit_submode = _(CTRL_X_MSG(ctrl_x_mode));
edit_submode_pre = NULL;
showmode();
} else {
@@ -359,9 +393,52 @@ bool ctrl_x_mode_not_defined_yet(void)
return ctrl_x_mode == CTRL_X_NOT_DEFINED_YET;
}
-/// Check that the "dict" or "tsr" option can be used.
+/// @return true if currently in "normal" or "adding" insert completion matches state
+bool compl_status_adding(void)
+{
+ return compl_cont_status & CONT_ADDING;
+}
+
+/// @return true if the completion pattern includes start of line, just for
+/// word-wise expansion.
+bool compl_status_sol(void)
+{
+ return compl_cont_status & CONT_SOL;
+}
+
+/// @return true if ^X^P/^X^N will do a local completion (i.e. use complete=.)
+bool compl_status_local(void)
+{
+ return compl_cont_status & CONT_LOCAL;
+}
+
+/// Clear the completion status flags
+void compl_status_clear(void)
+{
+ compl_cont_status = 0;
+}
+
+// @return true if completion is using the forward direction matches
+static bool compl_dir_forward(void)
+{
+ return compl_direction == FORWARD;
+}
+
+/// @return true if currently showing forward completion matches
+static bool compl_shows_dir_forward(void)
+{
+ return compl_shows_dir == FORWARD;
+}
+
+/// @return true if currently showing backward completion matches
+static bool compl_shows_dir_backward(void)
+{
+ return compl_shows_dir == BACKWARD;
+}
+
+/// Check that the 'dictionary' or 'thesaurus' option can be used.
///
-/// @param dict_opt check "dict" when true, "tsr" when false.
+/// @param dict_opt check 'dictionary' when true, 'thesaurus' when false.
bool check_compl_option(bool dict_opt)
{
if (dict_opt
@@ -445,6 +522,18 @@ bool vim_is_ctrl_x_key(int c)
return false;
}
+/// @return true if "match" is the original text when the completion began.
+static bool match_at_original_text(const compl_T *const match)
+{
+ return match->cp_flags & CP_ORIGINAL_TEXT;
+}
+
+/// @return true if "match" is the first match in the completion list.
+static bool is_first_match(const compl_T *const match)
+{
+ return match == compl_first_match;
+}
+
/// Check that character "c" is part of the item currently being
/// completed. Used to decide whether to abandon complete mode when the menu
/// is visible.
@@ -479,6 +568,106 @@ bool ins_compl_accept_char(int c)
return vim_iswordc(c);
}
+/// Get the completed text by inferring the case of the originally typed text.
+/// If the result is in allocated memory "tofree" is set to it.
+static char_u *ins_compl_infercase_gettext(char_u *str, int char_len, int compl_char_len,
+ int min_len, char **tofree)
+{
+ bool has_lower = false;
+ bool was_letter = false;
+
+ // Allocate wide character array for the completion and fill it.
+ int *const wca = xmalloc((size_t)char_len * sizeof(*wca));
+ {
+ const char_u *p = str;
+ for (int i = 0; i < char_len; i++) {
+ wca[i] = mb_ptr2char_adv(&p);
+ }
+ }
+
+ // Rule 1: Were any chars converted to lower?
+ {
+ const char_u *p = compl_orig_text;
+ for (int i = 0; i < min_len; i++) {
+ const int c = mb_ptr2char_adv(&p);
+ if (mb_islower(c)) {
+ has_lower = true;
+ if (mb_isupper(wca[i])) {
+ // Rule 1 is satisfied.
+ for (i = compl_char_len; i < char_len; i++) {
+ wca[i] = mb_tolower(wca[i]);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // Rule 2: No lower case, 2nd consecutive letter converted to
+ // upper case.
+ if (!has_lower) {
+ const char_u *p = compl_orig_text;
+ for (int i = 0; i < min_len; i++) {
+ const int c = mb_ptr2char_adv(&p);
+ if (was_letter && mb_isupper(c) && mb_islower(wca[i])) {
+ // Rule 2 is satisfied.
+ for (i = compl_char_len; i < char_len; i++) {
+ wca[i] = mb_toupper(wca[i]);
+ }
+ break;
+ }
+ was_letter = mb_islower(c) || mb_isupper(c);
+ }
+ }
+
+ // Copy the original case of the part we typed.
+ {
+ const char_u *p = compl_orig_text;
+ for (int i = 0; i < min_len; i++) {
+ const int c = mb_ptr2char_adv(&p);
+ if (mb_islower(c)) {
+ wca[i] = mb_tolower(wca[i]);
+ } else if (mb_isupper(c)) {
+ wca[i] = mb_toupper(wca[i]);
+ }
+ }
+ }
+
+ // Generate encoding specific output from wide character array.
+ garray_T gap;
+ char *p = (char *)IObuff;
+ int i = 0;
+ ga_init(&gap, 1, 500);
+ while (i < char_len) {
+ if (gap.ga_data != NULL) {
+ ga_grow(&gap, 10);
+ assert(gap.ga_data != NULL); // suppress clang "Dereference of NULL pointer"
+ p = (char *)gap.ga_data + gap.ga_len;
+ gap.ga_len += utf_char2bytes(wca[i++], p);
+ } else if ((p - (char *)IObuff) + 6 >= IOSIZE) {
+ // Multi-byte characters can occupy up to five bytes more than
+ // ASCII characters, and we also need one byte for NUL, so when
+ // getting to six bytes from the edge of IObuff switch to using a
+ // growarray. Add the character in the next round.
+ ga_grow(&gap, IOSIZE);
+ *p = NUL;
+ STRCPY(gap.ga_data, IObuff);
+ gap.ga_len = (int)STRLEN(IObuff);
+ } else {
+ p += utf_char2bytes(wca[i++], p);
+ }
+ }
+ xfree(wca);
+
+ if (gap.ga_data != NULL) {
+ *tofree = gap.ga_data;
+ return gap.ga_data;
+ }
+
+ *p = NUL;
+ return IObuff;
+}
+
/// This is like ins_compl_add(), but if 'ic' and 'inf' are set, then the
/// case of the originally typed text is used, and the case of the completed
/// text is inferred, ie this tries to work out what case you probably wanted
@@ -490,13 +679,10 @@ int ins_compl_add_infercase(char_u *str_arg, int len, bool icase, char_u *fname,
FUNC_ATTR_NONNULL_ARG(1)
{
char_u *str = str_arg;
- int i, c;
- int actual_len; // Take multi-byte characters
- int actual_compl_length; // into account.
- int min_len;
- bool has_lower = false;
- bool was_letter = false;
+ int char_len; // count multi-byte characters
+ int compl_char_len;
int flags = 0;
+ char *tofree = NULL;
if (p_ic && curbuf->b_p_inf && len > 0) {
// Infer case of completed part.
@@ -504,101 +690,28 @@ int ins_compl_add_infercase(char_u *str_arg, int len, bool icase, char_u *fname,
// Find actual length of completion.
{
const char_u *p = str;
- actual_len = 0;
+ char_len = 0;
while (*p != NUL) {
MB_PTR_ADV(p);
- actual_len++;
+ char_len++;
}
}
// Find actual length of original text.
{
const char_u *p = compl_orig_text;
- actual_compl_length = 0;
+ compl_char_len = 0;
while (*p != NUL) {
MB_PTR_ADV(p);
- actual_compl_length++;
+ compl_char_len++;
}
}
- // "actual_len" may be smaller than "actual_compl_length" when using
+ // "char_len" may be smaller than "compl_char_len" when using
// thesaurus, only use the minimum when comparing.
- min_len = actual_len < actual_compl_length
- ? actual_len : actual_compl_length;
-
- // Allocate wide character array for the completion and fill it.
- int *const wca = xmalloc((size_t)actual_len * sizeof(*wca));
- {
- const char_u *p = str;
- for (i = 0; i < actual_len; i++) {
- wca[i] = mb_ptr2char_adv(&p);
- }
- }
-
- // Rule 1: Were any chars converted to lower?
- {
- const char_u *p = compl_orig_text;
- for (i = 0; i < min_len; i++) {
- c = mb_ptr2char_adv(&p);
- if (mb_islower(c)) {
- has_lower = true;
- if (mb_isupper(wca[i])) {
- // Rule 1 is satisfied.
- for (i = actual_compl_length; i < actual_len; i++) {
- wca[i] = mb_tolower(wca[i]);
- }
- break;
- }
- }
- }
- }
-
- // Rule 2: No lower case, 2nd consecutive letter converted to
- // upper case.
- if (!has_lower) {
- const char_u *p = compl_orig_text;
- for (i = 0; i < min_len; i++) {
- c = mb_ptr2char_adv(&p);
- if (was_letter && mb_isupper(c) && mb_islower(wca[i])) {
- // Rule 2 is satisfied.
- for (i = actual_compl_length; i < actual_len; i++) {
- wca[i] = mb_toupper(wca[i]);
- }
- break;
- }
- was_letter = mb_islower(c) || mb_isupper(c);
- }
- }
+ int min_len = char_len < compl_char_len ? char_len : compl_char_len;
- // Copy the original case of the part we typed.
- {
- const char_u *p = compl_orig_text;
- for (i = 0; i < min_len; i++) {
- c = mb_ptr2char_adv(&p);
- if (mb_islower(c)) {
- wca[i] = mb_tolower(wca[i]);
- } else if (mb_isupper(c)) {
- wca[i] = mb_toupper(wca[i]);
- }
- }
- }
-
- // Generate encoding specific output from wide character array.
- // Multi-byte characters can occupy up to five bytes more than
- // ASCII characters, and we also need one byte for NUL, so stay
- // six bytes away from the edge of IObuff.
- {
- char_u *p = IObuff;
- i = 0;
- while (i < actual_len && (p - IObuff + 6) < IOSIZE) {
- p += utf_char2bytes(wca[i++], (char *)p);
- }
- *p = NUL;
- }
-
- xfree(wca);
-
- str = IObuff;
+ str = ins_compl_infercase_gettext(str, char_len, compl_char_len, min_len, &tofree);
}
if (cont_s_ipos) {
flags |= CP_CONT_S_IPOS;
@@ -607,22 +720,30 @@ int ins_compl_add_infercase(char_u *str_arg, int len, bool icase, char_u *fname,
flags |= CP_ICASE;
}
- return ins_compl_add(str, len, fname, NULL, false, NULL, dir, flags, false);
+ int res = ins_compl_add(str, len, fname, NULL, false, NULL, dir, flags, false);
+ xfree(tofree);
+ return res;
}
/// Add a match to the list of matches
///
-/// @param[in] str Match to add.
-/// @param[in] len Match length, -1 to use #STRLEN.
-/// @param[in] fname File name match comes from. May be NULL.
-/// @param[in] cptext Extra text for popup menu. May be NULL. If not NULL,
-/// must have exactly #CPT_COUNT items.
+/// @param[in] str text of the match to add
+/// @param[in] len length of "str". If -1, then the length of "str" is computed.
+/// @param[in] fname file name to associate with this match. May be NULL.
+/// @param[in] cptext list of strings to use with this match (for abbr, menu, info
+/// and kind). May be NULL.
+/// If not NULL, must have exactly #CPT_COUNT items.
/// @param[in] cptext_allocated If true, will not copy cptext strings.
///
/// @note Will free strings in case of error.
/// cptext itself will not be freed.
-/// @param[in] cdir Completion direction.
-/// @param[in] adup True if duplicate matches are to be accepted.
+/// @param[in] user_data user supplied data (any vim type) for this match
+/// @param[in] cdir match direction. If 0, use "compl_direction".
+/// @param[in] flags_arg match flags (cp_flags)
+/// @param[in] adup accept this match even if it is already present.
+///
+/// If "cdir" is FORWARD, then the match is added after the current match.
+/// Otherwise, it is added before the current match.
///
/// @return NOTDONE if the given string is already in the list of completions,
/// otherwise it is added to the list and OK is returned. FAIL will be
@@ -661,14 +782,14 @@ static int ins_compl_add(char_u *const str, int len, char_u *const fname,
if (compl_first_match != NULL && !adup) {
match = compl_first_match;
do {
- if (!(match->cp_flags & CP_ORIGINAL_TEXT)
+ if (!match_at_original_text(match)
&& STRNCMP(match->cp_str, str, len) == 0
- && match->cp_str[len] == NUL) {
+ && ((int)STRLEN(match->cp_str) <= len || match->cp_str[len] == NUL)) {
FREE_CPTEXT(cptext, cptext_allocated);
return NOTDONE;
}
match = match->cp_next;
- } while (match != NULL && match != compl_first_match);
+ } while (match != NULL && !is_first_match(match));
}
// Remove any popup menu before changing the list of matches.
@@ -721,7 +842,8 @@ static int ins_compl_add(char_u *const str, int len, char_u *const fname,
match->cp_user_data = *user_data;
}
- // Link the new match structure in the list of matches.
+ // Link the new match structure after (FORWARD) or before (BACKWARD) the
+ // current match in the list of matches .
if (compl_first_match == NULL) {
match->cp_next = match->cp_prev = NULL;
} else if (dir == FORWARD) {
@@ -777,9 +899,10 @@ static void ins_compl_longest_match(compl_T *match)
if (compl_leader == NULL) {
// First match, use it as a whole.
compl_leader = vim_strsave(match->cp_str);
+
had_match = (curwin->w_cursor.col > compl_col);
ins_compl_delete();
- ins_bytes(compl_leader + get_compl_len());
+ ins_bytes((char *)compl_leader + get_compl_len());
ins_redraw(false);
// When the match isn't there (to avoid matching itself) remove it
@@ -788,40 +911,42 @@ static void ins_compl_longest_match(compl_T *match)
ins_compl_delete();
}
compl_used_match = false;
- } else {
- // Reduce the text if this match differs from compl_leader.
- p = compl_leader;
- s = match->cp_str;
- while (*p != NUL) {
- c1 = utf_ptr2char((char *)p);
- c2 = utf_ptr2char((char *)s);
-
- if ((match->cp_flags & CP_ICASE)
- ? (mb_tolower(c1) != mb_tolower(c2))
- : (c1 != c2)) {
- break;
- }
- MB_PTR_ADV(p);
- MB_PTR_ADV(s);
- }
- if (*p != NUL) {
- // Leader was shortened, need to change the inserted text.
- *p = NUL;
- had_match = (curwin->w_cursor.col > compl_col);
- ins_compl_delete();
- ins_bytes(compl_leader + get_compl_len());
- ins_redraw(false);
+ return;
+ }
- // When the match isn't there (to avoid matching itself) remove it
- // again after redrawing.
- if (!had_match) {
- ins_compl_delete();
- }
+ // Reduce the text if this match differs from compl_leader.
+ p = compl_leader;
+ s = match->cp_str;
+ while (*p != NUL) {
+ c1 = utf_ptr2char((char *)p);
+ c2 = utf_ptr2char((char *)s);
+
+ if ((match->cp_flags & CP_ICASE)
+ ? (mb_tolower(c1) != mb_tolower(c2))
+ : (c1 != c2)) {
+ break;
}
+ MB_PTR_ADV(p);
+ MB_PTR_ADV(s);
+ }
- compl_used_match = false;
+ if (*p != NUL) {
+ // Leader was shortened, need to change the inserted text.
+ *p = NUL;
+ had_match = (curwin->w_cursor.col > compl_col);
+ ins_compl_delete();
+ ins_bytes((char *)compl_leader + get_compl_len());
+ ins_redraw(false);
+
+ // When the match isn't there (to avoid matching itself) remove it
+ // again after redrawing.
+ if (!had_match) {
+ ins_compl_delete();
+ }
}
+
+ compl_used_match = false;
}
/// Add an array of matches to the list of matches.
@@ -846,20 +971,21 @@ static void ins_compl_add_matches(int num_matches, char **matches, int icase)
/// Return the number of matches (excluding the original).
static int ins_compl_make_cyclic(void)
{
- compl_T *match;
- int count = 0;
+ if (compl_first_match == NULL) {
+ return 0;
+ }
- if (compl_first_match != NULL) {
- // Find the end of the list.
- match = compl_first_match;
- // there's always an entry for the compl_orig_text, it doesn't count.
- while (match->cp_next != NULL && match->cp_next != compl_first_match) {
- match = match->cp_next;
- count++;
- }
- match->cp_next = compl_first_match;
- compl_first_match->cp_prev = match;
+ // Find the end of the list.
+ compl_T *match = compl_first_match;
+ int count = 0;
+ // there's always an entry for the compl_orig_text, it doesn't count.
+ while (match->cp_next != NULL && !is_first_match(match->cp_next)) {
+ match = match->cp_next;
+ count++;
}
+ match->cp_next = compl_first_match;
+ compl_first_match->cp_prev = match;
+
return count;
}
@@ -882,10 +1008,10 @@ void completeopt_was_set(void)
{
compl_no_insert = false;
compl_no_select = false;
- if (strstr((char *)p_cot, "noselect") != NULL) {
+ if (strstr(p_cot, "noselect") != NULL) {
compl_no_select = true;
}
- if (strstr((char *)p_cot, "noinsert") != NULL) {
+ if (strstr(p_cot, "noinsert") != NULL) {
compl_no_insert = true;
}
}
@@ -898,10 +1024,12 @@ static int compl_match_arraysize;
/// Remove any popup menu.
static void ins_compl_del_pum(void)
{
- if (compl_match_array != NULL) {
- pum_undisplay(false);
- XFREE_CLEAR(compl_match_array);
+ if (compl_match_array == NULL) {
+ return;
}
+
+ pum_undisplay(false);
+ XFREE_CLEAR(compl_match_array);
}
/// Check if the popup menu should be displayed.
@@ -909,7 +1037,7 @@ bool pum_wanted(void)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
// "completeopt" must contain "menu" or "menuone"
- return vim_strchr((char *)p_cot, 'm') != NULL;
+ return vim_strchr(p_cot, 'm') != NULL;
}
/// Check that there are two or more matches to be shown in the popup menu.
@@ -919,17 +1047,16 @@ static bool pum_enough_matches(void)
{
// Don't display the popup menu if there are no matches or there is only
// one (ignoring the original text).
- compl_T *comp = compl_first_match;
+ compl_T *compl = compl_first_match;
int i = 0;
do {
- if (comp == NULL
- || ((comp->cp_flags & CP_ORIGINAL_TEXT) == 0 && ++i == 2)) {
+ if (compl == NULL || (!match_at_original_text(compl) && ++i == 2)) {
break;
}
- comp = comp->cp_next;
- } while (comp != compl_first_match);
+ compl = compl->cp_next;
+ } while (!is_first_match(compl));
- if (strstr((char *)p_cot, "menuone") != NULL) {
+ if (strstr(p_cot, "menuone") != NULL) {
return i >= 1;
}
return i >= 2;
@@ -953,6 +1080,8 @@ static dict_T *ins_compl_dict_alloc(compl_T *match)
return dict;
}
+/// Trigger the CompleteChanged autocmd event. Invoked each time the Insert mode
+/// completion menu is changed.
static void trigger_complete_changed_event(int cur)
{
static bool recursive = false;
@@ -981,141 +1110,151 @@ static void trigger_complete_changed_event(int cur)
restore_v_event(v_event, &save_v_event);
}
-/// Show the popup menu for the list of matches.
-/// Also adjusts "compl_shown_match" to an entry that is actually displayed.
-void ins_compl_show_pum(void)
+/// Build a popup menu to show the completion matches.
+///
+/// @return the popup menu entry that should be selected,
+/// -1 if nothing should be selected.
+static int ins_compl_build_pum(void)
{
- compl_T *compl;
- compl_T *shown_compl = NULL;
- bool did_find_shown_match = false;
- bool shown_match_ok = false;
- int i;
- int cur = -1;
- colnr_T col;
- int lead_len = 0;
- bool array_changed = false;
+ // Need to build the popup menu list.
+ compl_match_arraysize = 0;
+ compl_T *compl = compl_first_match;
- if (!pum_wanted() || !pum_enough_matches()) {
- return;
+ // If it's user complete function and refresh_always,
+ // do not use "compl_leader" as prefix filter.
+ if (ins_compl_need_restart()) {
+ XFREE_CLEAR(compl_leader);
}
- // Dirty hard-coded hack: remove any matchparen highlighting.
- do_cmdline_cmd("if exists('g:loaded_matchparen')|3match none|endif");
+ const int lead_len = compl_leader != NULL ? (int)STRLEN(compl_leader) : 0;
- // Update the screen before drawing the popup menu over it.
- update_screen(0);
-
- if (compl_match_array == NULL) {
- array_changed = true;
- // Need to build the popup menu list.
- compl_match_arraysize = 0;
- compl = compl_first_match;
- // If it's user complete function and refresh_always,
- // do not use "compl_leader" as prefix filter.
- if (ins_compl_need_restart()) {
- XFREE_CLEAR(compl_leader);
- }
- if (compl_leader != NULL) {
- lead_len = (int)STRLEN(compl_leader);
- }
- do {
- if ((compl->cp_flags & CP_ORIGINAL_TEXT) == 0
- && (compl_leader == NULL
- || ins_compl_equal(compl, compl_leader, (size_t)lead_len))) {
- compl_match_arraysize++;
- }
- compl = compl->cp_next;
- } while (compl != NULL && compl != compl_first_match);
- if (compl_match_arraysize == 0) {
- return;
+ do {
+ if (!match_at_original_text(compl)
+ && (compl_leader == NULL
+ || ins_compl_equal(compl, compl_leader, (size_t)lead_len))) {
+ compl_match_arraysize++;
}
+ compl = compl->cp_next;
+ } while (compl != NULL && !is_first_match(compl));
- assert(compl_match_arraysize >= 0);
- compl_match_array = xcalloc((size_t)compl_match_arraysize, sizeof(pumitem_T));
- // If the current match is the original text don't find the first
- // match after it, don't highlight anything.
- if (compl_shown_match->cp_flags & CP_ORIGINAL_TEXT) {
- shown_match_ok = true;
- }
+ if (compl_match_arraysize == 0) {
+ return -1;
+ }
- i = 0;
- compl = compl_first_match;
- do {
- if ((compl->cp_flags & CP_ORIGINAL_TEXT) == 0
- && (compl_leader == NULL
- || ins_compl_equal(compl, compl_leader, (size_t)lead_len))) {
- if (!shown_match_ok) {
- if (compl == compl_shown_match || did_find_shown_match) {
- // This item is the shown match or this is the
- // first displayed item after the shown match.
- compl_shown_match = compl;
- did_find_shown_match = true;
- shown_match_ok = true;
- } else {
- // Remember this displayed match for when the
- // shown match is just below it.
- shown_compl = compl;
- }
- cur = i;
- }
+ assert(compl_match_arraysize >= 0);
+ compl_match_array = xcalloc((size_t)compl_match_arraysize, sizeof(pumitem_T));
- if (compl->cp_text[CPT_ABBR] != NULL) {
- compl_match_array[i].pum_text =
- compl->cp_text[CPT_ABBR];
- } else {
- compl_match_array[i].pum_text = compl->cp_str;
- }
- compl_match_array[i].pum_kind = compl->cp_text[CPT_KIND];
- compl_match_array[i].pum_info = compl->cp_text[CPT_INFO];
- if (compl->cp_text[CPT_MENU] != NULL) {
- compl_match_array[i++].pum_extra =
- compl->cp_text[CPT_MENU];
+ // If the current match is the original text don't find the first
+ // match after it, don't highlight anything.
+ bool shown_match_ok = match_at_original_text(compl_shown_match);
+
+ compl_T *shown_compl = NULL;
+ bool did_find_shown_match = false;
+ int cur = -1;
+ int i = 0;
+ compl = compl_first_match;
+ do {
+ if (!match_at_original_text(compl)
+ && (compl_leader == NULL
+ || ins_compl_equal(compl, compl_leader, (size_t)lead_len))) {
+ if (!shown_match_ok) {
+ if (compl == compl_shown_match || did_find_shown_match) {
+ // This item is the shown match or this is the
+ // first displayed item after the shown match.
+ compl_shown_match = compl;
+ did_find_shown_match = true;
+ shown_match_ok = true;
} else {
- compl_match_array[i++].pum_extra = compl->cp_fname;
+ // Remember this displayed match for when the
+ // shown match is just below it.
+ shown_compl = compl;
}
+ cur = i;
}
- if (compl == compl_shown_match) {
- did_find_shown_match = true;
+ if (compl->cp_text[CPT_ABBR] != NULL) {
+ compl_match_array[i].pum_text = compl->cp_text[CPT_ABBR];
+ } else {
+ compl_match_array[i].pum_text = compl->cp_str;
+ }
+ compl_match_array[i].pum_kind = compl->cp_text[CPT_KIND];
+ compl_match_array[i].pum_info = compl->cp_text[CPT_INFO];
+ if (compl->cp_text[CPT_MENU] != NULL) {
+ compl_match_array[i++].pum_extra = compl->cp_text[CPT_MENU];
+ } else {
+ compl_match_array[i++].pum_extra = compl->cp_fname;
+ }
+ }
- // When the original text is the shown match don't set
- // compl_shown_match.
- if (compl->cp_flags & CP_ORIGINAL_TEXT) {
- shown_match_ok = true;
- }
+ if (compl == compl_shown_match) {
+ did_find_shown_match = true;
- if (!shown_match_ok && shown_compl != NULL) {
- // The shown match isn't displayed, set it to the
- // previously displayed match.
- compl_shown_match = shown_compl;
- shown_match_ok = true;
- }
+ // When the original text is the shown match don't set
+ // compl_shown_match.
+ if (match_at_original_text(compl)) {
+ shown_match_ok = true;
}
- compl = compl->cp_next;
- } while (compl != NULL && compl != compl_first_match);
- if (!shown_match_ok) { // no displayed match at all
- cur = -1;
+ if (!shown_match_ok && shown_compl != NULL) {
+ // The shown match isn't displayed, set it to the
+ // previously displayed match.
+ compl_shown_match = shown_compl;
+ shown_match_ok = true;
+ }
}
+ compl = compl->cp_next;
+ } while (compl != NULL && !is_first_match(compl));
+
+ if (!shown_match_ok) { // no displayed match at all
+ cur = -1;
+ }
+
+ return cur;
+}
+
+/// Show the popup menu for the list of matches.
+/// Also adjusts "compl_shown_match" to an entry that is actually displayed.
+void ins_compl_show_pum(void)
+{
+ if (!pum_wanted() || !pum_enough_matches()) {
+ return;
+ }
+
+ // Dirty hard-coded hack: remove any matchparen highlighting.
+ do_cmdline_cmd("if exists('g:loaded_matchparen')|3match none|endif");
+
+ // Update the screen before drawing the popup menu over it.
+ update_screen(0);
+
+ int cur = -1;
+ bool array_changed = false;
+
+ if (compl_match_array == NULL) {
+ array_changed = true;
+ // Need to build the popup menu list.
+ cur = ins_compl_build_pum();
} else {
// popup menu already exists, only need to find the current item.
- for (i = 0; i < compl_match_arraysize; i++) {
+ for (int i = 0; i < compl_match_arraysize; i++) {
if (compl_match_array[i].pum_text == compl_shown_match->cp_str
- || compl_match_array[i].pum_text
- == compl_shown_match->cp_text[CPT_ABBR]) {
+ || compl_match_array[i].pum_text == compl_shown_match->cp_text[CPT_ABBR]) {
cur = i;
break;
}
}
}
+ if (compl_match_array == NULL) {
+ return;
+ }
+
// In Replace mode when a $ is displayed at the end of the line only
// part of the screen would be updated. We do need to redraw here.
dollar_vcol = -1;
// Compute the screen column of the start of the completed text.
// Use the cursor to get all wrapping and other settings right.
- col = curwin->w_cursor.col;
+ const colnr_T col = curwin->w_cursor.col;
curwin->w_cursor.col = compl_col;
pum_selected_item = cur;
pum_display(compl_match_array, compl_match_arraysize, cur, array_changed, 0);
@@ -1129,8 +1268,8 @@ void ins_compl_show_pum(void)
#define DICT_FIRST (1) ///< use just first element in "dict"
#define DICT_EXACT (2) ///< "dict" is the exact name of a file
-/// Add any identifiers that match the given pattern in the list of dictionary
-/// files "dict_start" to the list of completions.
+/// Add any identifiers that match the given pattern "pat" in the list of
+/// dictionary files "dict_start" to the list of completions.
///
/// @param flags DICT_FIRST and/or DICT_EXACT
/// @param thesaurus Thesaurus completion
@@ -1231,6 +1370,54 @@ theend:
xfree(buf);
}
+/// Add all the words in the line "*buf_arg" from the thesaurus file "fname"
+/// skipping the word at 'skip_word'.
+///
+/// @return OK on success.
+static int thesaurus_add_words_in_line(char *fname, char_u **buf_arg, int dir, char_u *skip_word)
+{
+ int status = OK;
+
+ // Add the other matches on the line
+ char_u *ptr = *buf_arg;
+ while (!got_int) {
+ // Find start of the next word. Skip white
+ // space and punctuation.
+ ptr = find_word_start(ptr);
+ if (*ptr == NUL || *ptr == NL) {
+ break;
+ }
+ char_u *wstart = ptr;
+
+ // Find end of the word.
+ // Japanese words may have characters in
+ // different classes, only separate words
+ // with single-byte non-word characters.
+ while (*ptr != NUL) {
+ const int l = utfc_ptr2len((const char *)ptr);
+
+ if (l < 2 && !vim_iswordc(*ptr)) {
+ break;
+ }
+ ptr += l;
+ }
+
+ // Add the word. Skip the regexp match.
+ if (wstart != skip_word) {
+ status = ins_compl_add_infercase(wstart, (int)(ptr - wstart), p_ic,
+ (char_u *)fname, dir, false);
+ if (status == FAIL) {
+ break;
+ }
+ }
+ }
+
+ *buf_arg = ptr;
+ return status;
+}
+
+/// Process "count" dictionary/thesaurus "files" and add the text matching
+/// "regmatch".
static void ins_compl_files(int count, char **files, int thesaurus, int flags, regmatch_T *regmatch,
char_u *buf, Direction *dir)
FUNC_ATTR_NONNULL_ARG(2, 7)
@@ -1255,8 +1442,7 @@ static void ins_compl_files(int count, char **files, int thesaurus, int flags, r
// Read dictionary file line by line.
// Check each line for a match.
- while (!got_int && !compl_interrupted
- && !vim_fgets(buf, LSIZE, fp)) {
+ while (!got_int && !compl_interrupted && !vim_fgets(buf, LSIZE, fp)) {
ptr = buf;
while (vim_regexec(regmatch, (char *)buf, (colnr_T)(ptr - buf))) {
ptr = regmatch->startp[0];
@@ -1269,38 +1455,10 @@ static void ins_compl_files(int count, char **files, int thesaurus, int flags, r
(int)(ptr - regmatch->startp[0]),
p_ic, (char_u *)files[i], *dir, false);
if (thesaurus) {
- char_u *wstart;
-
- // Add the other matches on the line
+ // For a thesaurus, add all the words in the line
ptr = buf;
- while (!got_int) {
- // Find start of the next word. Skip white
- // space and punctuation.
- ptr = find_word_start(ptr);
- if (*ptr == NUL || *ptr == NL) {
- break;
- }
- wstart = ptr;
-
- // Find end of the word.
- // Japanese words may have characters in
- // different classes, only separate words
- // with single-byte non-word characters.
- while (*ptr != NUL) {
- const int l = utfc_ptr2len((char *)ptr);
-
- if (l < 2 && !vim_iswordc(*ptr)) {
- break;
- }
- ptr += l;
- }
-
- // Add the word. Skip the regexp match.
- if (wstart != regmatch->startp[0]) {
- add_r = ins_compl_add_infercase(wstart, (int)(ptr - wstart),
- p_ic, (char_u *)files[i], *dir, false);
- }
- }
+ add_r = thesaurus_add_words_in_line(files[i], &ptr, *dir,
+ regmatch->startp[0]);
}
if (add_r == OK) {
// if dir was BACKWARD then honor it just once
@@ -1391,12 +1549,13 @@ static void ins_compl_free(void)
}
tv_clear(&match->cp_user_data);
xfree(match);
- } while (compl_curr_match != NULL && compl_curr_match != compl_first_match);
+ } while (compl_curr_match != NULL && !is_first_match(compl_curr_match));
compl_first_match = compl_curr_match = NULL;
compl_shown_match = NULL;
compl_old_match = NULL;
}
+/// Reset/clear the completion state.
void ins_compl_clear(void)
{
compl_cont_status = 0;
@@ -1450,6 +1609,12 @@ colnr_T ins_compl_col(void)
return compl_col;
}
+/// Return the length in bytes of the text being completed
+int ins_compl_len(void)
+{
+ return compl_length;
+}
+
/// Delete one character before the cursor and show the subset of the matches
/// that match the word that is now before the cursor.
/// Returns the character to be used, NUL if the work is done and another char
@@ -1485,12 +1650,12 @@ int ins_compl_bs(void)
xfree(compl_leader);
compl_leader = vim_strnsave(line + compl_col, (size_t)(p_off - (ptrdiff_t)compl_col));
+
ins_compl_new_leader();
if (compl_shown_match != NULL) {
// Make sure current match is not a hidden item.
compl_curr_match = compl_shown_match;
}
-
return NUL;
}
@@ -1513,7 +1678,7 @@ static void ins_compl_new_leader(void)
{
ins_compl_del_pum();
ins_compl_delete();
- ins_bytes(compl_leader + get_compl_len());
+ ins_bytes((char *)compl_leader + get_compl_len());
compl_used_match = false;
if (compl_started) {
@@ -1567,7 +1732,7 @@ void ins_compl_addleader(int c)
utf_char2bytes(c, (char *)buf);
buf[cc] = NUL;
- ins_char_bytes((char_u *)buf, (size_t)cc);
+ ins_char_bytes(buf, (size_t)cc);
} else {
ins_char(c);
}
@@ -1603,13 +1768,13 @@ static void ins_compl_set_original_text(char_u *str)
FUNC_ATTR_NONNULL_ALL
{
// Replace the original text entry.
- // The CP_ORIGINAL_TEXT flag is either at the first item or might possibly be
- // at the last item for backward completion
- if (compl_first_match->cp_flags & CP_ORIGINAL_TEXT) { // safety check
+ // The CP_ORIGINAL_TEXT flag is either at the first item or might possibly
+ // be at the last item for backward completion
+ if (match_at_original_text(compl_first_match)) { // safety check
xfree(compl_first_match->cp_str);
compl_first_match->cp_str = vim_strsave(str);
} else if (compl_first_match->cp_prev != NULL
- && (compl_first_match->cp_prev->cp_flags & CP_ORIGINAL_TEXT)) {
+ && match_at_original_text(compl_first_match->cp_prev)) {
xfree(compl_first_match->cp_prev->cp_str);
compl_first_match->cp_prev->cp_str = vim_strsave(str);
}
@@ -1628,20 +1793,20 @@ void ins_compl_addfrommatch(void)
if ((int)STRLEN(p) <= len) { // the match is too short
// When still at the original match use the first entry that matches
// the leader.
- if (compl_shown_match->cp_flags & CP_ORIGINAL_TEXT) {
- p = NULL;
- for (cp = compl_shown_match->cp_next; cp != NULL
- && cp != compl_first_match; cp = cp->cp_next) {
- if (compl_leader == NULL
- || ins_compl_equal(cp, compl_leader, STRLEN(compl_leader))) {
- p = cp->cp_str;
- break;
- }
- }
- if (p == NULL || (int)STRLEN(p) <= len) {
- return;
+ if (!match_at_original_text(compl_shown_match)) {
+ return;
+ }
+
+ p = NULL;
+ for (cp = compl_shown_match->cp_next; cp != NULL
+ && !is_first_match(cp); cp = cp->cp_next) {
+ if (compl_leader == NULL
+ || ins_compl_equal(cp, compl_leader, STRLEN(compl_leader))) {
+ p = cp->cp_str;
+ break;
}
- } else {
+ }
+ if (p == NULL || (int)STRLEN(p) <= len) {
return;
}
}
@@ -1650,6 +1815,249 @@ void ins_compl_addfrommatch(void)
ins_compl_addleader(c);
}
+/// Set the CTRL-X completion mode based on the key "c" typed after a CTRL-X.
+/// Uses the global variables: ctrl_x_mode, edit_submode, edit_submode_pre,
+/// compl_cont_mode and compl_cont_status.
+///
+/// @return true when the character is not to be inserted.
+static bool set_ctrl_x_mode(const int c)
+{
+ bool retval = false;
+
+ switch (c) {
+ case Ctrl_E:
+ case Ctrl_Y:
+ // scroll the window one line up or down
+ ctrl_x_mode = CTRL_X_SCROLL;
+ if (!(State & REPLACE_FLAG)) {
+ edit_submode = _(" (insert) Scroll (^E/^Y)");
+ } else {
+ edit_submode = _(" (replace) Scroll (^E/^Y)");
+ }
+ edit_submode_pre = NULL;
+ showmode();
+ break;
+ case Ctrl_L:
+ // complete whole line
+ ctrl_x_mode = CTRL_X_WHOLE_LINE;
+ break;
+ case Ctrl_F:
+ // complete filenames
+ ctrl_x_mode = CTRL_X_FILES;
+ break;
+ case Ctrl_K:
+ // complete words from a dictionary
+ ctrl_x_mode = CTRL_X_DICTIONARY;
+ break;
+ case Ctrl_R:
+ // Register insertion without exiting CTRL-X mode
+ // Simply allow ^R to happen without affecting ^X mode
+ break;
+ case Ctrl_T:
+ // complete words from a thesaurus
+ ctrl_x_mode = CTRL_X_THESAURUS;
+ break;
+ case Ctrl_U:
+ // user defined completion
+ ctrl_x_mode = CTRL_X_FUNCTION;
+ break;
+ case Ctrl_O:
+ // omni completion
+ ctrl_x_mode = CTRL_X_OMNI;
+ break;
+ case 's':
+ case Ctrl_S:
+ // complete spelling suggestions
+ ctrl_x_mode = CTRL_X_SPELL;
+ emsg_off++; // Avoid getting the E756 error twice.
+ spell_back_to_badword();
+ emsg_off--;
+ break;
+ case Ctrl_RSB:
+ // complete tag names
+ ctrl_x_mode = CTRL_X_TAGS;
+ break;
+ case Ctrl_I:
+ case K_S_TAB:
+ // complete keywords from included files
+ ctrl_x_mode = CTRL_X_PATH_PATTERNS;
+ break;
+ case Ctrl_D:
+ // complete definitions from included files
+ ctrl_x_mode = CTRL_X_PATH_DEFINES;
+ break;
+ case Ctrl_V:
+ case Ctrl_Q:
+ // complete vim commands
+ ctrl_x_mode = CTRL_X_CMDLINE;
+ break;
+ case Ctrl_Z:
+ // stop completion
+ ctrl_x_mode = CTRL_X_NORMAL;
+ edit_submode = NULL;
+ showmode();
+ retval = true;
+ break;
+ case Ctrl_P:
+ case Ctrl_N:
+ // ^X^P means LOCAL expansion if nothing interrupted (eg we
+ // just started ^X mode, or there were enough ^X's to cancel
+ // the previous mode, say ^X^F^X^X^P or ^P^X^X^X^P, see below)
+ // do normal expansion when interrupting a different mode (say
+ // ^X^F^X^P or ^P^X^X^P, see below)
+ // nothing changes if interrupting mode 0, (eg, the flag
+ // doesn't change when going to ADDING mode -- Acevedo
+ if (!(compl_cont_status & CONT_INTRPT)) {
+ compl_cont_status |= CONT_LOCAL;
+ } else if (compl_cont_mode != 0) {
+ compl_cont_status &= ~CONT_LOCAL;
+ }
+ FALLTHROUGH;
+ default:
+ // If we have typed at least 2 ^X's... for modes != 0, we set
+ // compl_cont_status = 0 (eg, as if we had just started ^X
+ // mode).
+ // For mode 0, we set "compl_cont_mode" to an impossible
+ // value, in both cases ^X^X can be used to restart the same
+ // mode (avoiding ADDING mode).
+ // Undocumented feature: In a mode != 0 ^X^P and ^X^X^P start
+ // 'complete' and local ^P expansions respectively.
+ // In mode 0 an extra ^X is needed since ^X^P goes to ADDING
+ // mode -- Acevedo
+ if (c == Ctrl_X) {
+ if (compl_cont_mode != 0) {
+ compl_cont_status = 0;
+ } else {
+ compl_cont_mode = CTRL_X_NOT_DEFINED_YET;
+ }
+ }
+ ctrl_x_mode = CTRL_X_NORMAL;
+ edit_submode = NULL;
+ showmode();
+ break;
+ }
+
+ return retval;
+}
+
+/// Stop insert completion mode
+static bool ins_compl_stop(const int c, const int prev_mode, bool retval)
+{
+ // Get here when we have finished typing a sequence of ^N and
+ // ^P or other completion characters in CTRL-X mode. Free up
+ // memory that was used, and make sure we can redo the insert.
+ if (compl_curr_match != NULL || compl_leader != NULL || c == Ctrl_E) {
+ // If any of the original typed text has been changed, eg when
+ // ignorecase is set, we must add back-spaces to the redo
+ // buffer. We add as few as necessary to delete just the part
+ // of the original text that has changed.
+ // When using the longest match, edited the match or used
+ // CTRL-E then don't use the current match.
+ char_u *ptr;
+ if (compl_curr_match != NULL && compl_used_match && c != Ctrl_E) {
+ ptr = compl_curr_match->cp_str;
+ } else {
+ ptr = NULL;
+ }
+ ins_compl_fixRedoBufForLeader(ptr);
+ }
+
+ bool want_cindent = (get_can_cindent() && cindent_on());
+
+ // When completing whole lines: fix indent for 'cindent'.
+ // Otherwise, break line if it's too long.
+ if (compl_cont_mode == CTRL_X_WHOLE_LINE) {
+ // re-indent the current line
+ if (want_cindent) {
+ do_c_expr_indent();
+ want_cindent = false; // don't do it again
+ }
+ } else {
+ const int prev_col = curwin->w_cursor.col;
+
+ // put the cursor on the last char, for 'tw' formatting
+ if (prev_col > 0) {
+ dec_cursor();
+ }
+
+ // only format when something was inserted
+ if (!arrow_used && !ins_need_undo_get() && c != Ctrl_E) {
+ insertchar(NUL, 0, -1);
+ }
+
+ if (prev_col > 0
+ && get_cursor_line_ptr()[curwin->w_cursor.col] != NUL) {
+ inc_cursor();
+ }
+ }
+
+ // If the popup menu is displayed pressing CTRL-Y means accepting
+ // the selection without inserting anything. When
+ // compl_enter_selects is set the Enter key does the same.
+ if ((c == Ctrl_Y || (compl_enter_selects
+ && (c == CAR || c == K_KENTER || c == NL)))
+ && pum_visible()) {
+ retval = true;
+ }
+
+ // CTRL-E means completion is Ended, go back to the typed text.
+ // but only do this, if the Popup is still visible
+ if (c == Ctrl_E) {
+ ins_compl_delete();
+ char_u *p = NULL;
+ if (compl_leader != NULL) {
+ p = compl_leader;
+ } else if (compl_first_match != NULL) {
+ p = compl_orig_text;
+ }
+ if (p != NULL) {
+ const int compl_len = get_compl_len();
+ const int len = (int)STRLEN(p);
+ if (len > compl_len) {
+ ins_bytes_len((char *)p + compl_len, (size_t)(len - compl_len));
+ }
+ }
+ retval = true;
+ }
+
+ auto_format(false, true);
+
+ // Trigger the CompleteDonePre event to give scripts a chance to
+ // act upon the completion before clearing the info, and restore
+ // ctrl_x_mode, so that complete_info() can be used.
+ ctrl_x_mode = prev_mode;
+ ins_apply_autocmds(EVENT_COMPLETEDONEPRE);
+
+ ins_compl_free();
+ compl_started = false;
+ compl_matches = 0;
+ if (!shortmess(SHM_COMPLETIONMENU)) {
+ msg_clr_cmdline(); // necessary for "noshowmode"
+ }
+ ctrl_x_mode = CTRL_X_NORMAL;
+ compl_enter_selects = false;
+ if (edit_submode != NULL) {
+ edit_submode = NULL;
+ showmode();
+ }
+
+ if (c == Ctrl_C && cmdwin_type != 0) {
+ // Avoid the popup menu remains displayed when leaving the
+ // command line window.
+ update_screen(0);
+ }
+
+ // Indent now if a key was typed that is in 'cinkeys'.
+ if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0))) {
+ do_c_expr_indent();
+ }
+ // Trigger the CompleteDone event to give scripts a chance to act
+ // upon the end of completion.
+ ins_apply_autocmds(EVENT_COMPLETEDONE);
+
+ return retval;
+}
+
/// Prepare for Insert mode completion, or stop it.
/// Called just after typing a character in Insert mode.
///
@@ -1658,7 +2066,6 @@ void ins_compl_addfrommatch(void)
/// @return true when the character is not to be inserted;
bool ins_compl_prep(int c)
{
- char_u *ptr;
bool retval = false;
const int prev_mode = ctrl_x_mode;
@@ -1698,111 +2105,14 @@ bool ins_compl_prep(int c)
// Set "compl_get_longest" when finding the first matches.
if (ctrl_x_mode_not_defined_yet()
|| (ctrl_x_mode_normal() && !compl_started)) {
- compl_get_longest = (strstr((char *)p_cot, "longest") != NULL);
+ compl_get_longest = (strstr(p_cot, "longest") != NULL);
compl_used_match = true;
}
if (ctrl_x_mode_not_defined_yet()) {
// We have just typed CTRL-X and aren't quite sure which CTRL-X mode
// it will be yet. Now we decide.
- switch (c) {
- case Ctrl_E:
- case Ctrl_Y:
- ctrl_x_mode = CTRL_X_SCROLL;
- if (!(State & REPLACE_FLAG)) {
- edit_submode = (char_u *)_(" (insert) Scroll (^E/^Y)");
- } else {
- edit_submode = (char_u *)_(" (replace) Scroll (^E/^Y)");
- }
- edit_submode_pre = NULL;
- showmode();
- break;
- case Ctrl_L:
- ctrl_x_mode = CTRL_X_WHOLE_LINE;
- break;
- case Ctrl_F:
- ctrl_x_mode = CTRL_X_FILES;
- break;
- case Ctrl_K:
- ctrl_x_mode = CTRL_X_DICTIONARY;
- break;
- case Ctrl_R:
- // Simply allow ^R to happen without affecting ^X mode
- break;
- case Ctrl_T:
- ctrl_x_mode = CTRL_X_THESAURUS;
- break;
- case Ctrl_U:
- ctrl_x_mode = CTRL_X_FUNCTION;
- break;
- case Ctrl_O:
- ctrl_x_mode = CTRL_X_OMNI;
- break;
- case 's':
- case Ctrl_S:
- ctrl_x_mode = CTRL_X_SPELL;
- emsg_off++; // Avoid getting the E756 error twice.
- spell_back_to_badword();
- emsg_off--;
- break;
- case Ctrl_RSB:
- ctrl_x_mode = CTRL_X_TAGS;
- break;
- case Ctrl_I:
- case K_S_TAB:
- ctrl_x_mode = CTRL_X_PATH_PATTERNS;
- break;
- case Ctrl_D:
- ctrl_x_mode = CTRL_X_PATH_DEFINES;
- break;
- case Ctrl_V:
- case Ctrl_Q:
- ctrl_x_mode = CTRL_X_CMDLINE;
- break;
- case Ctrl_Z:
- ctrl_x_mode = CTRL_X_NORMAL;
- edit_submode = NULL;
- showmode();
- retval = true;
- break;
- case Ctrl_P:
- case Ctrl_N:
- // ^X^P means LOCAL expansion if nothing interrupted (eg we
- // just started ^X mode, or there were enough ^X's to cancel
- // the previous mode, say ^X^F^X^X^P or ^P^X^X^X^P, see below)
- // do normal expansion when interrupting a different mode (say
- // ^X^F^X^P or ^P^X^X^P, see below)
- // nothing changes if interrupting mode 0, (eg, the flag
- // doesn't change when going to ADDING mode -- Acevedo
- if (!(compl_cont_status & CONT_INTRPT)) {
- compl_cont_status |= CONT_LOCAL;
- } else if (compl_cont_mode != 0) {
- compl_cont_status &= ~CONT_LOCAL;
- }
- FALLTHROUGH;
- default:
- // If we have typed at least 2 ^X's... for modes != 0, we set
- // compl_cont_status = 0 (eg, as if we had just started ^X
- // mode).
- // For mode 0, we set "compl_cont_mode" to an impossible
- // value, in both cases ^X^X can be used to restart the same
- // mode (avoiding ADDING mode).
- // Undocumented feature: In a mode != 0 ^X^P and ^X^X^P start
- // 'complete' and local ^P expansions respectively.
- // In mode 0 an extra ^X is needed since ^X^P goes to ADDING
- // mode -- Acevedo
- if (c == Ctrl_X) {
- if (compl_cont_mode != 0) {
- compl_cont_status = 0;
- } else {
- compl_cont_mode = CTRL_X_NOT_DEFINED_YET;
- }
- }
- ctrl_x_mode = CTRL_X_NORMAL;
- edit_submode = NULL;
- showmode();
- break;
- }
+ retval = set_ctrl_x_mode(c);
} else if (ctrl_x_mode_not_default()) {
// We're already in CTRL-X mode, do we stay in it?
if (!vim_is_ctrl_x_key(c)) {
@@ -1827,107 +2137,7 @@ bool ins_compl_prep(int c)
&& c != Ctrl_R
&& !ins_compl_pum_key(c))
|| ctrl_x_mode == CTRL_X_FINISHED) {
- // Get here when we have finished typing a sequence of ^N and
- // ^P or other completion characters in CTRL-X mode. Free up
- // memory that was used, and make sure we can redo the insert.
- if (compl_curr_match != NULL || compl_leader != NULL || c == Ctrl_E) {
- // If any of the original typed text has been changed, eg when
- // ignorecase is set, we must add back-spaces to the redo
- // buffer. We add as few as necessary to delete just the part
- // of the original text that has changed.
- // When using the longest match, edited the match or used
- // CTRL-E then don't use the current match.
- if (compl_curr_match != NULL && compl_used_match && c != Ctrl_E) {
- ptr = compl_curr_match->cp_str;
- } else {
- ptr = NULL;
- }
- ins_compl_fixRedoBufForLeader(ptr);
- }
-
- bool want_cindent = (can_cindent_get() && cindent_on());
-
- // When completing whole lines: fix indent for 'cindent'.
- // Otherwise, break line if it's too long.
- if (compl_cont_mode == CTRL_X_WHOLE_LINE) {
- // re-indent the current line
- if (want_cindent) {
- do_c_expr_indent();
- want_cindent = false; // don't do it again
- }
- } else {
- int prev_col = curwin->w_cursor.col;
-
- // put the cursor on the last char, for 'tw' formatting
- if (prev_col > 0) {
- dec_cursor();
- }
-
- if (!arrow_used && !ins_need_undo_get() && c != Ctrl_E) {
- insertchar(NUL, 0, -1);
- }
-
- if (prev_col > 0
- && get_cursor_line_ptr()[curwin->w_cursor.col] != NUL) {
- inc_cursor();
- }
- }
-
- // If the popup menu is displayed pressing CTRL-Y means accepting
- // the selection without inserting anything. When
- // compl_enter_selects is set the Enter key does the same.
- if ((c == Ctrl_Y || (compl_enter_selects
- && (c == CAR || c == K_KENTER || c == NL)))
- && pum_visible()) {
- retval = true;
- }
-
- // CTRL-E means completion is Ended, go back to the typed text.
- // but only do this, if the Popup is still visible
- if (c == Ctrl_E) {
- ins_compl_delete();
- if (compl_leader != NULL) {
- ins_bytes(compl_leader + get_compl_len());
- } else if (compl_first_match != NULL) {
- ins_bytes(compl_orig_text + get_compl_len());
- }
- retval = true;
- }
-
- auto_format(false, true);
-
- // Trigger the CompleteDonePre event to give scripts a chance to
- // act upon the completion before clearing the info, and restore
- // ctrl_x_mode, so that complete_info() can be used.
- ctrl_x_mode = prev_mode;
- ins_apply_autocmds(EVENT_COMPLETEDONEPRE);
-
- ins_compl_free();
- compl_started = false;
- compl_matches = 0;
- if (!shortmess(SHM_COMPLETIONMENU)) {
- msg_clr_cmdline(); // necessary for "noshowmode"
- }
- ctrl_x_mode = CTRL_X_NORMAL;
- compl_enter_selects = false;
- if (edit_submode != NULL) {
- edit_submode = NULL;
- showmode();
- }
-
- // Avoid the popup menu remains displayed when leaving the
- // command line window.
- if (c == Ctrl_C && cmdwin_type != 0) {
- update_screen(0);
- }
-
- // Indent now if a key was typed that is in 'cinkeys'.
- if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0))) {
- do_c_expr_indent();
- }
- // Trigger the CompleteDone event to give scripts a chance to act
- // upon the end of completion.
- ins_apply_autocmds(EVENT_COMPLETEDONE);
+ retval = ins_compl_stop(c, prev_mode, retval);
}
} else if (ctrl_x_mode == CTRL_X_LOCAL_MSG) {
// Trigger the CompleteDone event to give scripts a chance to act
@@ -2010,16 +2220,16 @@ static buf_T *ins_compl_next_buf(buf_T *buf, int flag)
return buf;
}
-/// Get the user-defined completion function name for completion 'type'
+/// Get the user-defined completion function name for completion "type"
static char_u *get_complete_funcname(int type)
{
switch (type) {
case CTRL_X_FUNCTION:
- return curbuf->b_p_cfu;
+ return (char_u *)curbuf->b_p_cfu;
case CTRL_X_OMNI:
- return curbuf->b_p_ofu;
+ return (char_u *)curbuf->b_p_ofu;
case CTRL_X_THESAURUS:
- return *curbuf->b_p_tsrfu == NUL ? p_tsrfu : curbuf->b_p_tsrfu;
+ return *curbuf->b_p_tsrfu == NUL ? (char_u *)p_tsrfu : (char_u *)curbuf->b_p_tsrfu;
default:
return (char_u *)"";
}
@@ -2147,10 +2357,15 @@ static int ins_compl_add_tv(typval_T *const tv, const Direction dir, bool fast)
for (size_t i = 0; i < CPT_COUNT; i++) {
xfree(cptext[i]);
}
+ tv_clear(&user_data);
return FAIL;
}
- return ins_compl_add((char_u *)word, -1, NULL,
- (char_u **)cptext, true, &user_data, dir, flags, dup);
+ int status = ins_compl_add((char_u *)word, -1, NULL, (char_u **)cptext, true,
+ &user_data, dir, flags, dup);
+ if (status != OK) {
+ tv_clear(&user_data);
+ }
+ return status;
}
/// Add completions from a list.
@@ -2256,7 +2471,7 @@ static void set_completion(colnr_T startcol, list_T *list)
}
/// "complete()" function
-void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_complete(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if ((State & MODE_INSERT) == 0) {
emsg(_("E785: complete() can only be used in Insert mode"));
@@ -2280,13 +2495,13 @@ void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "complete_add()" function
-void f_complete_add(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_complete_add(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = ins_compl_add_tv(&argvars[0], 0, false);
}
/// "complete_check()" function
-void f_complete_check(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_complete_check(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int saved = RedrawingDisabled;
@@ -2305,18 +2520,19 @@ static char_u *ins_compl_mode(void)
return (char_u *)"";
}
+/// Assign the sequence number to all the completion matches which don't have
+/// one assigned yet.
static void ins_compl_update_sequence_numbers(void)
{
int number = 0;
compl_T *match;
- if (compl_direction == FORWARD) {
+ if (compl_dir_forward()) {
// search backwards for the first valid (!= -1) number.
// This should normally succeed already at the first loop
// cycle, so it's fast!
for (match = compl_curr_match->cp_prev;
- match != NULL && match != compl_first_match;
- match = match->cp_prev) {
+ match != NULL && !is_first_match(match); match = match->cp_prev) {
if (match->cp_number != -1) {
number = match->cp_number;
break;
@@ -2336,8 +2552,7 @@ static void ins_compl_update_sequence_numbers(void)
// number. This should normally succeed already at the
// first loop cycle, so it's fast!
for (match = compl_curr_match->cp_next;
- match != NULL && match != compl_first_match;
- match = match->cp_next) {
+ match != NULL && !is_first_match(match); match = match->cp_next) {
if (match->cp_number != -1) {
number = match->cp_number;
break;
@@ -2406,7 +2621,7 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
if (ret == OK && compl_first_match != NULL) {
compl_T *match = compl_first_match;
do {
- if (!(match->cp_flags & CP_ORIGINAL_TEXT)) {
+ if (!match_at_original_text(match)) {
dict_T *di = tv_dict_alloc();
tv_list_append_dict(li, di);
@@ -2422,7 +2637,7 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
}
}
match = match->cp_next;
- } while (match != NULL && match != compl_first_match);
+ } while (match != NULL && !is_first_match(match));
}
}
@@ -2441,7 +2656,7 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
}
/// "complete_info()" function
-void f_complete_info(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_complete_info(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_alloc_ret(rettv);
@@ -2464,6 +2679,481 @@ static bool thesaurus_func_complete(int type)
&& (*curbuf->b_p_tsrfu != NUL || *p_tsrfu != NUL);
}
+/// Return value of process_next_cpt_value()
+enum {
+ INS_COMPL_CPT_OK = 1,
+ INS_COMPL_CPT_CONT,
+ INS_COMPL_CPT_END,
+};
+
+/// Process the next 'complete' option value in st->e_cpt.
+///
+/// If successful, the arguments are set as below:
+/// st->cpt - pointer to the next option value in "st->cpt"
+/// compl_type_arg - type of insert mode completion to use
+/// st->found_all - all matches of this type are found
+/// st->ins_buf - search for completions in this buffer
+/// st->first_match_pos - position of the first completion match
+/// st->last_match_pos - position of the last completion match
+/// st->set_match_pos - true if the first match position should be saved to
+/// avoid loops after the search wraps around.
+/// st->dict - name of the dictionary or thesaurus file to search
+/// st->dict_f - flag specifying whether "dict" is an exact file name or not
+///
+/// @return INS_COMPL_CPT_OK if the next value is processed successfully.
+/// INS_COMPL_CPT_CONT to skip the current completion source matching
+/// the "st->e_cpt" option value and process the next matching source.
+/// INS_COMPL_CPT_END if all the values in "st->e_cpt" are processed.
+static int process_next_cpt_value(ins_compl_next_state_T *st, int *compl_type_arg,
+ pos_T *start_match_pos)
+{
+ int compl_type = -1;
+ int status = INS_COMPL_CPT_OK;
+
+ st->found_all = false;
+
+ while (*st->e_cpt == ',' || *st->e_cpt == ' ') {
+ st->e_cpt++;
+ }
+
+ if (*st->e_cpt == '.' && !curbuf->b_scanned) {
+ st->ins_buf = curbuf;
+ st->first_match_pos = *start_match_pos;
+ // Move the cursor back one character so that ^N can match the
+ // word immediately after the cursor.
+ if (ctrl_x_mode_normal() && dec(&st->first_match_pos) < 0) {
+ // Move the cursor to after the last character in the
+ // buffer, so that word at start of buffer is found
+ // correctly.
+ st->first_match_pos.lnum = st->ins_buf->b_ml.ml_line_count;
+ st->first_match_pos.col = (colnr_T)STRLEN(ml_get(st->first_match_pos.lnum));
+ }
+ st->last_match_pos = st->first_match_pos;
+ compl_type = 0;
+
+ // Remember the first match so that the loop stops when we
+ // wrap and come back there a second time.
+ st->set_match_pos = true;
+ } else if (vim_strchr("buwU", *st->e_cpt) != NULL
+ && (st->ins_buf = ins_compl_next_buf(st->ins_buf, *st->e_cpt)) != curbuf) {
+ // Scan a buffer, but not the current one.
+ if (st->ins_buf->b_ml.ml_mfp != NULL) { // loaded buffer
+ compl_started = true;
+ st->first_match_pos.col = st->last_match_pos.col = 0;
+ st->first_match_pos.lnum = st->ins_buf->b_ml.ml_line_count + 1;
+ st->last_match_pos.lnum = 0;
+ compl_type = 0;
+ } else { // unloaded buffer, scan like dictionary
+ st->found_all = true;
+ if (st->ins_buf->b_fname == NULL) {
+ status = INS_COMPL_CPT_CONT;
+ goto done;
+ }
+ compl_type = CTRL_X_DICTIONARY;
+ st->dict = (char_u *)st->ins_buf->b_fname;
+ st->dict_f = DICT_EXACT;
+ }
+ msg_hist_off = true; // reset in msg_trunc_attr()
+ vim_snprintf((char *)IObuff, IOSIZE, _("Scanning: %s"),
+ st->ins_buf->b_fname == NULL
+ ? buf_spname(st->ins_buf)
+ : st->ins_buf->b_sfname == NULL
+ ? st->ins_buf->b_fname
+ : st->ins_buf->b_sfname);
+ (void)msg_trunc_attr((char *)IObuff, true, HL_ATTR(HLF_R));
+ } else if (*st->e_cpt == NUL) {
+ status = INS_COMPL_CPT_END;
+ } else {
+ if (ctrl_x_mode_line_or_eval()) {
+ compl_type = -1;
+ } else if (*st->e_cpt == 'k' || *st->e_cpt == 's') {
+ if (*st->e_cpt == 'k') {
+ compl_type = CTRL_X_DICTIONARY;
+ } else {
+ compl_type = CTRL_X_THESAURUS;
+ }
+ if (*++st->e_cpt != ',' && *st->e_cpt != NUL) {
+ st->dict = (char_u *)st->e_cpt;
+ st->dict_f = DICT_FIRST;
+ }
+ } else if (*st->e_cpt == 'i') {
+ compl_type = CTRL_X_PATH_PATTERNS;
+ } else if (*st->e_cpt == 'd') {
+ compl_type = CTRL_X_PATH_DEFINES;
+ } else if (*st->e_cpt == ']' || *st->e_cpt == 't') {
+ msg_hist_off = true; // reset in msg_trunc_attr()
+ compl_type = CTRL_X_TAGS;
+ vim_snprintf((char *)IObuff, IOSIZE, "%s", _("Scanning tags."));
+ (void)msg_trunc_attr((char *)IObuff, true, HL_ATTR(HLF_R));
+ } else {
+ compl_type = -1;
+ }
+
+ // in any case e_cpt is advanced to the next entry
+ (void)copy_option_part(&st->e_cpt, (char *)IObuff, IOSIZE, ",");
+
+ st->found_all = true;
+ if (compl_type == -1) {
+ status = INS_COMPL_CPT_CONT;
+ }
+ }
+
+done:
+ *compl_type_arg = compl_type;
+ return status;
+}
+
+/// Get the next set of identifiers or defines matching "compl_pattern" in
+/// included files.
+static void get_next_include_file_completion(int compl_type)
+{
+ find_pattern_in_path((char_u *)compl_pattern, compl_direction,
+ STRLEN(compl_pattern), false, false,
+ ((compl_type == CTRL_X_PATH_DEFINES
+ && !(compl_cont_status & CONT_SOL))
+ ? FIND_DEFINE : FIND_ANY),
+ 1L, ACTION_EXPAND, 1, MAXLNUM);
+}
+
+/// Get the next set of words matching "compl_pattern" in dictionary or
+/// thesaurus files.
+static void get_next_dict_tsr_completion(int compl_type, char_u *dict, int dict_f)
+{
+ if (thesaurus_func_complete(compl_type)) {
+ expand_by_function(compl_type, (char_u *)compl_pattern);
+ } else {
+ ins_compl_dictionaries(dict != NULL ? dict
+ : (compl_type == CTRL_X_THESAURUS
+ ? (*curbuf->b_p_tsr == NUL ? p_tsr : (char_u *)curbuf->b_p_tsr)
+ : (*curbuf->b_p_dict ==
+ NUL ? (char_u *)p_dict : (char_u *)curbuf->b_p_dict)),
+ (char_u *)compl_pattern,
+ dict != NULL ? dict_f : 0,
+ compl_type == CTRL_X_THESAURUS);
+ }
+}
+
+/// Get the next set of tag names matching "compl_pattern".
+static void get_next_tag_completion(void)
+{
+ // set p_ic according to p_ic, p_scs and pat for find_tags().
+ const int save_p_ic = p_ic;
+ p_ic = ignorecase((char_u *)compl_pattern);
+
+ // Find up to TAG_MANY matches. Avoids that an enormous number
+ // of matches is found when compl_pattern is empty
+ g_tag_at_cursor = true;
+ char **matches;
+ int num_matches;
+ if (find_tags(compl_pattern, &num_matches, &matches,
+ TAG_REGEXP | TAG_NAMES | TAG_NOIC | TAG_INS_COMP
+ | (ctrl_x_mode_not_default() ? TAG_VERBOSE : 0),
+ TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0) {
+ ins_compl_add_matches(num_matches, matches, p_ic);
+ }
+ g_tag_at_cursor = false;
+ p_ic = save_p_ic;
+}
+
+/// Get the next set of filename matching "compl_pattern".
+static void get_next_filename_completion(void)
+{
+ char **matches;
+ int num_matches;
+ if (expand_wildcards(1, &compl_pattern, &num_matches, &matches,
+ EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) != OK) {
+ return;
+ }
+
+ // May change home directory back to "~".
+ tilde_replace((char_u *)compl_pattern, num_matches, matches);
+#ifdef BACKSLASH_IN_FILENAME
+ if (curbuf->b_p_csl[0] != NUL) {
+ for (int i = 0; i < num_matches; i++) {
+ char_u *ptr = matches[i];
+ while (*ptr != NUL) {
+ if (curbuf->b_p_csl[0] == 's' && *ptr == '\\') {
+ *ptr = '/';
+ } else if (curbuf->b_p_csl[0] == 'b' && *ptr == '/') {
+ *ptr = '\\';
+ }
+ ptr += utfc_ptr2len(ptr);
+ }
+ }
+ }
+#endif
+ ins_compl_add_matches(num_matches, matches, p_fic || p_wic);
+}
+
+/// Get the next set of command-line completions matching "compl_pattern".
+static void get_next_cmdline_completion(void)
+{
+ char **matches;
+ int num_matches;
+ if (expand_cmdline(&compl_xp, (char_u *)compl_pattern,
+ (int)STRLEN(compl_pattern),
+ &num_matches, &matches) == EXPAND_OK) {
+ ins_compl_add_matches(num_matches, matches, false);
+ }
+}
+
+/// Get the next set of spell suggestions matching "compl_pattern".
+static void get_next_spell_completion(linenr_T lnum)
+{
+ char **matches;
+ int num_matches = expand_spelling(lnum, (char_u *)compl_pattern, &matches);
+ if (num_matches > 0) {
+ ins_compl_add_matches(num_matches, matches, p_ic);
+ } else {
+ xfree(matches);
+ }
+}
+
+/// Return the next word or line from buffer "ins_buf" at position
+/// "cur_match_pos" for completion. The length of the match is set in "len".
+/// @param ins_buf buffer being scanned
+/// @param cur_match_pos current match position
+/// @param match_len
+/// @param cont_s_ipos next ^X<> will set initial_pos
+static char_u *ins_comp_get_next_word_or_line(buf_T *ins_buf, pos_T *cur_match_pos, int *match_len,
+ bool *cont_s_ipos)
+{
+ *match_len = 0;
+ char_u *ptr = ml_get_buf(ins_buf, cur_match_pos->lnum, false) + cur_match_pos->col;
+ int len;
+ if (ctrl_x_mode_line_or_eval()) {
+ if (compl_status_adding()) {
+ if (cur_match_pos->lnum >= ins_buf->b_ml.ml_line_count) {
+ return NULL;
+ }
+ ptr = ml_get_buf(ins_buf, cur_match_pos->lnum + 1, false);
+ if (!p_paste) {
+ ptr = (char_u *)skipwhite((char *)ptr);
+ }
+ }
+ len = (int)STRLEN(ptr);
+ } else {
+ char_u *tmp_ptr = ptr;
+
+ if (compl_status_adding() && compl_length <= (int)STRLEN(tmp_ptr)) {
+ tmp_ptr += compl_length;
+ // Skip if already inside a word.
+ if (vim_iswordp(tmp_ptr)) {
+ return NULL;
+ }
+ // Find start of next word.
+ tmp_ptr = find_word_start(tmp_ptr);
+ }
+ // Find end of this word.
+ tmp_ptr = find_word_end(tmp_ptr);
+ len = (int)(tmp_ptr - ptr);
+
+ if (compl_status_adding() && len == compl_length) {
+ if (cur_match_pos->lnum < ins_buf->b_ml.ml_line_count) {
+ // Try next line, if any. the new word will be "join" as if the
+ // normal command "J" was used. IOSIZE is always greater than
+ // compl_length, so the next STRNCPY always works -- Acevedo
+ STRNCPY(IObuff, ptr, len); // NOLINT(runtime/printf)
+ ptr = ml_get_buf(ins_buf, cur_match_pos->lnum + 1, false);
+ tmp_ptr = ptr = (char_u *)skipwhite((char *)ptr);
+ // Find start of next word.
+ tmp_ptr = find_word_start(tmp_ptr);
+ // Find end of next word.
+ tmp_ptr = find_word_end(tmp_ptr);
+ if (tmp_ptr > ptr) {
+ if (*ptr != ')' && IObuff[len - 1] != TAB) {
+ if (IObuff[len - 1] != ' ') {
+ IObuff[len++] = ' ';
+ }
+ // IObuf =~ "\k.* ", thus len >= 2
+ if (p_js
+ && (IObuff[len - 2] == '.'
+ || IObuff[len - 2] == '?'
+ || IObuff[len - 2] == '!')) {
+ IObuff[len++] = ' ';
+ }
+ }
+ // copy as much as possible of the new word
+ if (tmp_ptr - ptr >= IOSIZE - len) {
+ tmp_ptr = ptr + IOSIZE - len - 1;
+ }
+ STRLCPY(IObuff + len, ptr, IOSIZE - len);
+ len += (int)(tmp_ptr - ptr);
+ *cont_s_ipos = true;
+ }
+ IObuff[len] = NUL;
+ ptr = IObuff;
+ }
+ if (len == compl_length) {
+ return NULL;
+ }
+ }
+ }
+
+ *match_len = len;
+ return ptr;
+}
+
+/// Get the next set of words matching "compl_pattern" for default completion(s)
+/// (normal ^P/^N and ^X^L).
+/// Search for "compl_pattern" in the buffer "st->ins_buf" starting from the
+/// position "st->start_pos" in the "compl_direction" direction. If
+/// "st->set_match_pos" is true, then set the "st->first_match_pos" and
+/// "st->last_match_pos".
+///
+/// @return OK if a new next match is found, otherwise FAIL.
+static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_pos)
+{
+ // If 'infercase' is set, don't use 'smartcase' here
+ const int save_p_scs = p_scs;
+ assert(st->ins_buf);
+ if (st->ins_buf->b_p_inf) {
+ p_scs = false;
+ }
+
+ // Buffers other than curbuf are scanned from the beginning or the
+ // end but never from the middle, thus setting nowrapscan in this
+ // buffers is a good idea, on the other hand, we always set
+ // wrapscan for curbuf to avoid missing matches -- Acevedo,Webb
+ const int save_p_ws = p_ws;
+ if (st->ins_buf != curbuf) {
+ p_ws = false;
+ } else if (*st->e_cpt == '.') {
+ p_ws = true;
+ }
+ bool looped_around = false;
+ int found_new_match = FAIL;
+ for (;;) {
+ bool cont_s_ipos = false;
+
+ msg_silent++; // Don't want messages for wrapscan.
+ // ctrl_x_mode_line_or_eval() || word-wise search that
+ // has added a word that was at the beginning of the line.
+ if (ctrl_x_mode_line_or_eval() || (compl_cont_status & CONT_SOL)) {
+ found_new_match = search_for_exact_line(st->ins_buf, st->cur_match_pos,
+ compl_direction, (char_u *)compl_pattern);
+ } else {
+ found_new_match = searchit(NULL, st->ins_buf, st->cur_match_pos,
+ NULL, compl_direction, (char_u *)compl_pattern, 1L,
+ SEARCH_KEEP + SEARCH_NFMSG, RE_LAST, NULL);
+ }
+ msg_silent--;
+ if (!compl_started || st->set_match_pos) {
+ // set "compl_started" even on fail
+ compl_started = true;
+ st->first_match_pos = *st->cur_match_pos;
+ st->last_match_pos = *st->cur_match_pos;
+ st->set_match_pos = false;
+ } else if (st->first_match_pos.lnum == st->last_match_pos.lnum
+ && st->first_match_pos.col == st->last_match_pos.col) {
+ found_new_match = FAIL;
+ } else if (compl_dir_forward()
+ && (st->prev_match_pos.lnum > st->cur_match_pos->lnum
+ || (st->prev_match_pos.lnum == st->cur_match_pos->lnum
+ && st->prev_match_pos.col >= st->cur_match_pos->col))) {
+ if (looped_around) {
+ found_new_match = FAIL;
+ } else {
+ looped_around = true;
+ }
+ } else if (!compl_dir_forward()
+ && (st->prev_match_pos.lnum < st->cur_match_pos->lnum
+ || (st->prev_match_pos.lnum == st->cur_match_pos->lnum
+ && st->prev_match_pos.col <= st->cur_match_pos->col))) {
+ if (looped_around) {
+ found_new_match = FAIL;
+ } else {
+ looped_around = true;
+ }
+ }
+ st->prev_match_pos = *st->cur_match_pos;
+ if (found_new_match == FAIL) {
+ break;
+ }
+
+ // when ADDING, the text before the cursor matches, skip it
+ if (compl_status_adding() && st->ins_buf == curbuf
+ && start_pos->lnum == st->cur_match_pos->lnum
+ && start_pos->col == st->cur_match_pos->col) {
+ continue;
+ }
+ int len;
+ char_u *ptr = ins_comp_get_next_word_or_line(st->ins_buf, st->cur_match_pos,
+ &len, &cont_s_ipos);
+ if (ptr == NULL) {
+ continue;
+ }
+ if (ins_compl_add_infercase(ptr, len, p_ic,
+ st->ins_buf == curbuf ? NULL : (char_u *)st->ins_buf->b_sfname,
+ 0, cont_s_ipos) != NOTDONE) {
+ found_new_match = OK;
+ break;
+ }
+ }
+ p_scs = save_p_scs;
+ p_ws = save_p_ws;
+
+ return found_new_match;
+}
+
+/// get the next set of completion matches for "type".
+/// @return true if a new match is found, otherwise false.
+static bool get_next_completion_match(int type, ins_compl_next_state_T *st, pos_T *ini)
+{
+ int found_new_match = FAIL;
+
+ switch (type) {
+ case -1:
+ break;
+ case CTRL_X_PATH_PATTERNS:
+ case CTRL_X_PATH_DEFINES:
+ get_next_include_file_completion(type);
+ break;
+
+ case CTRL_X_DICTIONARY:
+ case CTRL_X_THESAURUS:
+ get_next_dict_tsr_completion(type, st->dict, st->dict_f);
+ st->dict = NULL;
+ break;
+
+ case CTRL_X_TAGS:
+ get_next_tag_completion();
+ break;
+
+ case CTRL_X_FILES:
+ get_next_filename_completion();
+ break;
+
+ case CTRL_X_CMDLINE:
+ case CTRL_X_CMDLINE_CTRL_X:
+ get_next_cmdline_completion();
+ break;
+
+ case CTRL_X_FUNCTION:
+ case CTRL_X_OMNI:
+ expand_by_function(type, (char_u *)compl_pattern);
+ break;
+
+ case CTRL_X_SPELL:
+ get_next_spell_completion(st->first_match_pos.lnum);
+ break;
+
+ default: // normal ^P/^N and ^X^L
+ found_new_match = get_next_default_completion(st, ini);
+ if (found_new_match == FAIL && st->ins_buf == curbuf) {
+ st->found_all = true;
+ }
+ }
+
+ // check if compl_curr_match has changed, (e.g. other type of
+ // expansion added something)
+ if (type != 0 && compl_curr_match != compl_old_match) {
+ found_new_match = OK;
+ }
+
+ return found_new_match;
+}
+
/// Get the next expansion(s), using "compl_pattern".
/// The search starts at position "ini" in curbuf and in the direction
/// compl_direction.
@@ -2473,28 +3163,10 @@ static bool thesaurus_func_complete(int type)
/// Return the total number of matches or -1 if still unknown -- Acevedo
static int ins_compl_get_exp(pos_T *ini)
{
- static pos_T first_match_pos;
- static pos_T last_match_pos;
- static char *e_cpt = ""; // curr. entry in 'complete'
- static bool found_all = false; // Found all matches of a
- // certain type.
- static buf_T *ins_buf = NULL; // buffer being scanned
-
- pos_T *pos;
- char **matches;
- int save_p_scs;
- bool save_p_ws;
- int save_p_ic;
+ static ins_compl_next_state_T st;
int i;
- int num_matches;
- int len;
int found_new_match;
int type = ctrl_x_mode;
- char_u *ptr;
- char_u *dict = NULL;
- int dict_f = 0;
- bool set_match_pos;
- pos_T prev_pos = { 0, 0, 0 };
assert(curbuf != NULL);
@@ -2502,111 +3174,34 @@ static int ins_compl_get_exp(pos_T *ini)
FOR_ALL_BUFFERS(buf) {
buf->b_scanned = false;
}
- found_all = false;
- ins_buf = curbuf;
- e_cpt = (compl_cont_status & CONT_LOCAL) ? "." : (char *)curbuf->b_p_cpt;
- last_match_pos = first_match_pos = *ini;
- } else if (ins_buf != curbuf && !buf_valid(ins_buf)) {
- ins_buf = curbuf; // In case the buffer was wiped out.
+ st.found_all = false;
+ st.ins_buf = curbuf;
+ st.e_cpt = (compl_cont_status & CONT_LOCAL) ? "." : curbuf->b_p_cpt;
+ st.last_match_pos = st.first_match_pos = *ini;
+ } else if (st.ins_buf != curbuf && !buf_valid(st.ins_buf)) {
+ st.ins_buf = curbuf; // In case the buffer was wiped out.
}
- assert(ins_buf != NULL);
+ assert(st.ins_buf != NULL);
compl_old_match = compl_curr_match; // remember the last current match
- pos = (compl_direction == FORWARD) ? &last_match_pos : &first_match_pos;
+ st.cur_match_pos = (compl_dir_forward() ? &st.last_match_pos : &st.first_match_pos);
// For ^N/^P loop over all the flags/windows/buffers in 'complete'
for (;;) {
found_new_match = FAIL;
- set_match_pos = false;
+ st.set_match_pos = false;
// For ^N/^P pick a new entry from e_cpt if compl_started is off,
// or if found_all says this entry is done. For ^X^L only use the
// entries from 'complete' that look in loaded buffers.
if ((ctrl_x_mode_normal() || ctrl_x_mode_line_or_eval())
- && (!compl_started || found_all)) {
- found_all = false;
- while (*e_cpt == ',' || *e_cpt == ' ') {
- e_cpt++;
- }
- if (*e_cpt == '.' && !curbuf->b_scanned) {
- ins_buf = curbuf;
- first_match_pos = *ini;
- // Move the cursor back one character so that ^N can match the
- // word immediately after the cursor.
- if (ctrl_x_mode_normal() && dec(&first_match_pos) < 0) {
- // Move the cursor to after the last character in the
- // buffer, so that word at start of buffer is found
- // correctly.
- first_match_pos.lnum = ins_buf->b_ml.ml_line_count;
- first_match_pos.col = (colnr_T)STRLEN(ml_get(first_match_pos.lnum));
- }
- last_match_pos = first_match_pos;
- type = 0;
-
- // Remember the first match so that the loop stops when we
- // wrap and come back there a second time.
- set_match_pos = true;
- } else if (vim_strchr("buwU", *e_cpt) != NULL
- && (ins_buf = ins_compl_next_buf(ins_buf, *e_cpt)) != curbuf) {
- // Scan a buffer, but not the current one.
- if (ins_buf->b_ml.ml_mfp != NULL) { // loaded buffer
- compl_started = true;
- first_match_pos.col = last_match_pos.col = 0;
- first_match_pos.lnum = ins_buf->b_ml.ml_line_count + 1;
- last_match_pos.lnum = 0;
- type = 0;
- } else { // unloaded buffer, scan like dictionary
- found_all = true;
- if (ins_buf->b_fname == NULL) {
- continue;
- }
- type = CTRL_X_DICTIONARY;
- dict = (char_u *)ins_buf->b_fname;
- dict_f = DICT_EXACT;
- }
- msg_hist_off = true; // reset in msg_trunc_attr()
- vim_snprintf((char *)IObuff, IOSIZE, _("Scanning: %s"),
- ins_buf->b_fname == NULL
- ? buf_spname(ins_buf)
- : ins_buf->b_sfname == NULL
- ? ins_buf->b_fname
- : ins_buf->b_sfname);
- (void)msg_trunc_attr((char *)IObuff, true, HL_ATTR(HLF_R));
- } else if (*e_cpt == NUL) {
+ && (!compl_started || st.found_all)) {
+ int status = process_next_cpt_value(&st, &type, ini);
+ if (status == INS_COMPL_CPT_END) {
break;
- } else {
- if (ctrl_x_mode_line_or_eval()) {
- type = -1;
- } else if (*e_cpt == 'k' || *e_cpt == 's') {
- if (*e_cpt == 'k') {
- type = CTRL_X_DICTIONARY;
- } else {
- type = CTRL_X_THESAURUS;
- }
- if (*++e_cpt != ',' && *e_cpt != NUL) {
- dict = (char_u *)e_cpt;
- dict_f = DICT_FIRST;
- }
- } else if (*e_cpt == 'i') {
- type = CTRL_X_PATH_PATTERNS;
- } else if (*e_cpt == 'd') {
- type = CTRL_X_PATH_DEFINES;
- } else if (*e_cpt == ']' || *e_cpt == 't') {
- msg_hist_off = true; // reset in msg_trunc_attr()
- type = CTRL_X_TAGS;
- vim_snprintf((char *)IObuff, IOSIZE, "%s", _("Scanning tags."));
- (void)msg_trunc_attr((char *)IObuff, true, HL_ATTR(HLF_R));
- } else {
- type = -1;
- }
-
- // in any case e_cpt is advanced to the next entry
- (void)copy_option_part(&e_cpt, (char *)IObuff, IOSIZE, ",");
-
- found_all = true;
- if (type == -1) {
- continue;
- }
+ }
+ if (status == INS_COMPL_CPT_CONT) {
+ continue;
}
}
@@ -2616,271 +3211,12 @@ static int ins_compl_get_exp(pos_T *ini)
break;
}
- switch (type) {
- case -1:
- break;
- case CTRL_X_PATH_PATTERNS:
- case CTRL_X_PATH_DEFINES:
- find_pattern_in_path((char_u *)compl_pattern, compl_direction,
- STRLEN(compl_pattern), false, false,
- ((type == CTRL_X_PATH_DEFINES
- && !(compl_cont_status & CONT_SOL))
- ? FIND_DEFINE
- : FIND_ANY),
- 1L, ACTION_EXPAND, 1, MAXLNUM);
- break;
-
- case CTRL_X_DICTIONARY:
- case CTRL_X_THESAURUS:
- if (thesaurus_func_complete(type)) {
- expand_by_function(type, (char_u *)compl_pattern);
- } else {
- ins_compl_dictionaries(dict != NULL ? dict
- : (type == CTRL_X_THESAURUS
- ? (*curbuf->b_p_tsr == NUL ? p_tsr : curbuf->b_p_tsr)
- : (*curbuf->b_p_dict ==
- NUL ? p_dict : curbuf->b_p_dict)),
- (char_u *)compl_pattern,
- dict != NULL ? dict_f : 0, type == CTRL_X_THESAURUS);
- }
- dict = NULL;
- break;
-
- case CTRL_X_TAGS:
- // set p_ic according to p_ic, p_scs and pat for find_tags().
- save_p_ic = p_ic;
- p_ic = ignorecase((char_u *)compl_pattern);
-
- // Find up to TAG_MANY matches. Avoids that an enormous number
- // of matches is found when compl_pattern is empty
- g_tag_at_cursor = true;
- if (find_tags((char_u *)compl_pattern, &num_matches, &matches,
- TAG_REGEXP | TAG_NAMES | TAG_NOIC | TAG_INS_COMP
- | (ctrl_x_mode_not_default() ? TAG_VERBOSE : 0),
- TAG_MANY, (char_u *)curbuf->b_ffname) == OK && num_matches > 0) {
- ins_compl_add_matches(num_matches, matches, p_ic);
- }
- g_tag_at_cursor = false;
- p_ic = save_p_ic;
- break;
-
- case CTRL_X_FILES:
- if (expand_wildcards(1, &compl_pattern, &num_matches, &matches,
- EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) == OK) {
- // May change home directory back to "~".
- tilde_replace((char_u *)compl_pattern, num_matches, matches);
-#ifdef BACKSLASH_IN_FILENAME
- if (curbuf->b_p_csl[0] != NUL) {
- for (int i = 0; i < num_matches; i++) {
- char_u *ptr = matches[i];
- while (*ptr != NUL) {
- if (curbuf->b_p_csl[0] == 's' && *ptr == '\\') {
- *ptr = '/';
- } else if (curbuf->b_p_csl[0] == 'b' && *ptr == '/') {
- *ptr = '\\';
- }
- ptr += utfc_ptr2len(ptr);
- }
- }
- }
-#endif
- ins_compl_add_matches(num_matches, matches, p_fic || p_wic);
- }
- break;
-
- case CTRL_X_CMDLINE:
- case CTRL_X_CMDLINE_CTRL_X:
- if (expand_cmdline(&compl_xp, (char_u *)compl_pattern,
- (int)STRLEN(compl_pattern),
- &num_matches, &matches) == EXPAND_OK) {
- ins_compl_add_matches(num_matches, matches, false);
- }
- break;
-
- case CTRL_X_FUNCTION:
- case CTRL_X_OMNI:
- expand_by_function(type, (char_u *)compl_pattern);
- break;
-
- case CTRL_X_SPELL:
- num_matches = expand_spelling(first_match_pos.lnum,
- (char_u *)compl_pattern, &matches);
- if (num_matches > 0) {
- ins_compl_add_matches(num_matches, matches, p_ic);
- }
- break;
-
- default: // normal ^P/^N and ^X^L
- // If 'infercase' is set, don't use 'smartcase' here
- save_p_scs = p_scs;
- assert(ins_buf);
- if (ins_buf->b_p_inf) {
- p_scs = false;
- }
-
- // Buffers other than curbuf are scanned from the beginning or the
- // end but never from the middle, thus setting nowrapscan in this
- // buffers is a good idea, on the other hand, we always set
- // wrapscan for curbuf to avoid missing matches -- Acevedo,Webb
- save_p_ws = p_ws;
- if (ins_buf != curbuf) {
- p_ws = false;
- } else if (*e_cpt == '.') {
- p_ws = true;
- }
- bool looped_around = false;
- for (;;) {
- bool cont_s_ipos = false;
-
- msg_silent++; // Don't want messages for wrapscan.
- // ctrl_x_mode_line_or_eval() || word-wise search that
- // has added a word that was at the beginning of the line.
- if (ctrl_x_mode_line_or_eval()
- || (compl_cont_status & CONT_SOL)) {
- found_new_match = search_for_exact_line(ins_buf, pos,
- compl_direction,
- (char_u *)compl_pattern);
- } else {
- found_new_match = searchit(NULL, ins_buf, pos, NULL,
- compl_direction,
- (char_u *)compl_pattern, 1L,
- SEARCH_KEEP + SEARCH_NFMSG,
- RE_LAST, NULL);
- }
- msg_silent--;
- if (!compl_started || set_match_pos) {
- // set "compl_started" even on fail
- compl_started = true;
- first_match_pos = *pos;
- last_match_pos = *pos;
- set_match_pos = false;
- } else if (first_match_pos.lnum == last_match_pos.lnum
- && first_match_pos.col == last_match_pos.col) {
- found_new_match = FAIL;
- } else if ((compl_direction == FORWARD)
- && (prev_pos.lnum > pos->lnum
- || (prev_pos.lnum == pos->lnum
- && prev_pos.col >= pos->col))) {
- if (looped_around) {
- found_new_match = FAIL;
- } else {
- looped_around = true;
- }
- } else if ((compl_direction != FORWARD)
- && (prev_pos.lnum < pos->lnum
- || (prev_pos.lnum == pos->lnum
- && prev_pos.col <= pos->col))) {
- if (looped_around) {
- found_new_match = FAIL;
- } else {
- looped_around = true;
- }
- }
- prev_pos = *pos;
- if (found_new_match == FAIL) {
- if (ins_buf == curbuf) {
- found_all = true;
- }
- break;
- }
-
- // when ADDING, the text before the cursor matches, skip it
- if ((compl_cont_status & CONT_ADDING) && ins_buf == curbuf
- && ini->lnum == pos->lnum
- && ini->col == pos->col) {
- continue;
- }
- ptr = ml_get_buf(ins_buf, pos->lnum, false) + pos->col;
- if (ctrl_x_mode_line_or_eval()) {
- if (compl_cont_status & CONT_ADDING) {
- if (pos->lnum >= ins_buf->b_ml.ml_line_count) {
- continue;
- }
- ptr = ml_get_buf(ins_buf, pos->lnum + 1, false);
- if (!p_paste) {
- ptr = (char_u *)skipwhite((char *)ptr);
- }
- }
- len = (int)STRLEN(ptr);
- } else {
- char_u *tmp_ptr = ptr;
-
- if (compl_cont_status & CONT_ADDING) {
- tmp_ptr += compl_length;
- // Skip if already inside a word.
- if (vim_iswordp(tmp_ptr)) {
- continue;
- }
- // Find start of next word.
- tmp_ptr = find_word_start(tmp_ptr);
- }
- // Find end of this word.
- tmp_ptr = find_word_end(tmp_ptr);
- len = (int)(tmp_ptr - ptr);
-
- if ((compl_cont_status & CONT_ADDING)
- && len == compl_length) {
- if (pos->lnum < ins_buf->b_ml.ml_line_count) {
- // Try next line, if any. the new word will be "join" as if the
- // normal command "J" was used. IOSIZE is always greater than
- // compl_length, so the next STRNCPY always works -- Acevedo
- STRNCPY(IObuff, ptr, len); // NOLINT(runtime/printf)
- ptr = ml_get_buf(ins_buf, pos->lnum + 1, false);
- tmp_ptr = ptr = (char_u *)skipwhite((char *)ptr);
- // Find start of next word.
- tmp_ptr = find_word_start(tmp_ptr);
- // Find end of next word.
- tmp_ptr = find_word_end(tmp_ptr);
- if (tmp_ptr > ptr) {
- if (*ptr != ')' && IObuff[len - 1] != TAB) {
- if (IObuff[len - 1] != ' ') {
- IObuff[len++] = ' ';
- }
- // IObuf =~ "\k.* ", thus len >= 2
- if (p_js
- && (IObuff[len - 2] == '.'
- || IObuff[len - 2] == '?'
- || IObuff[len - 2] == '!')) {
- IObuff[len++] = ' ';
- }
- }
- // copy as much as possible of the new word
- if (tmp_ptr - ptr >= IOSIZE - len) {
- tmp_ptr = ptr + IOSIZE - len - 1;
- }
- STRLCPY(IObuff + len, ptr, IOSIZE - len);
- len += (int)(tmp_ptr - ptr);
- cont_s_ipos = true;
- }
- IObuff[len] = NUL;
- ptr = IObuff;
- }
- if (len == compl_length) {
- continue;
- }
- }
- }
- if (ins_compl_add_infercase(ptr, len, p_ic,
- ins_buf == curbuf ? NULL : (char_u *)ins_buf->b_sfname,
- 0, cont_s_ipos) != NOTDONE) {
- found_new_match = OK;
- break;
- }
- }
- p_scs = save_p_scs;
- p_ws = save_p_ws;
- }
-
- // check if compl_curr_match has changed, (e.g. other type of
- // expansion added something)
- if (type != 0 && compl_curr_match != compl_old_match) {
- found_new_match = OK;
- }
+ // get the next set of completion matches
+ found_new_match = get_next_completion_match(type, &st, ini);
// break the loop for specialized modes (use 'complete' just for the
// generic ctrl_x_mode == CTRL_X_NORMAL) or when we've found a new match
- if ((ctrl_x_mode_not_default()
- && !ctrl_x_mode_line_or_eval())
+ if ((ctrl_x_mode_not_default() && !ctrl_x_mode_line_or_eval())
|| found_new_match != FAIL) {
if (got_int) {
break;
@@ -2890,8 +3226,7 @@ static int ins_compl_get_exp(pos_T *ini)
ins_compl_check_keys(0, false);
}
- if ((ctrl_x_mode_not_default()
- && !ctrl_x_mode_line_or_eval())
+ if ((ctrl_x_mode_not_default() && !ctrl_x_mode_line_or_eval())
|| compl_interrupted) {
break;
}
@@ -2899,8 +3234,8 @@ static int ins_compl_get_exp(pos_T *ini)
} else {
// Mark a buffer scanned when it has been scanned completely
if (type == 0 || type == CTRL_X_PATH_PATTERNS) {
- assert(ins_buf);
- ins_buf->b_scanned = true;
+ assert(st.ins_buf);
+ st.ins_buf->b_scanned = true;
}
compl_started = false;
@@ -2908,16 +3243,14 @@ static int ins_compl_get_exp(pos_T *ini)
}
compl_started = true;
- if ((ctrl_x_mode_normal()
- || ctrl_x_mode_line_or_eval())
- && *e_cpt == NUL) { // Got to end of 'complete'
+ if ((ctrl_x_mode_normal() || ctrl_x_mode_line_or_eval())
+ && *st.e_cpt == NUL) { // Got to end of 'complete'
found_new_match = FAIL;
}
i = -1; // total of matches, unknown
if (found_new_match == FAIL
- || (ctrl_x_mode_not_default()
- && !ctrl_x_mode_line_or_eval())) {
+ || (ctrl_x_mode_not_default() && !ctrl_x_mode_line_or_eval())) {
i = ins_compl_make_cyclic();
}
@@ -2925,7 +3258,7 @@ static int ins_compl_get_exp(pos_T *ini)
// If several matches were added (FORWARD) or the search failed and has
// just been made cyclic then we have to move compl_curr_match to the
// next or previous entry (if any) -- Acevedo
- compl_curr_match = compl_direction == FORWARD
+ compl_curr_match = compl_dir_forward()
? compl_old_match->cp_next
: compl_old_match->cp_prev;
if (compl_curr_match == NULL) {
@@ -2937,6 +3270,31 @@ static int ins_compl_get_exp(pos_T *ini)
return i;
}
+/// Update "compl_shown_match" to the actually shown match, it may differ when
+/// "compl_leader" is used to omit some of the matches.
+static void ins_compl_update_shown_match(void)
+{
+ while (!ins_compl_equal(compl_shown_match,
+ compl_leader, STRLEN(compl_leader))
+ && compl_shown_match->cp_next != NULL
+ && !is_first_match(compl_shown_match->cp_next)) {
+ compl_shown_match = compl_shown_match->cp_next;
+ }
+
+ // If we didn't find it searching forward, and compl_shows_dir is
+ // backward, find the last match.
+ if (compl_shows_dir_backward()
+ && !ins_compl_equal(compl_shown_match, compl_leader, STRLEN(compl_leader))
+ && (compl_shown_match->cp_next == NULL
+ || is_first_match(compl_shown_match->cp_next))) {
+ while (!ins_compl_equal(compl_shown_match, compl_leader, STRLEN(compl_leader))
+ && compl_shown_match->cp_prev != NULL
+ && !is_first_match(compl_shown_match->cp_prev)) {
+ compl_shown_match = compl_shown_match->cp_prev;
+ }
+ }
+}
+
/// Delete the old text being completed.
void ins_compl_delete(void)
{
@@ -2944,7 +3302,7 @@ void ins_compl_delete(void)
// In insert mode: Delete the typed part.
// In replace mode: Put the old characters back, if any.
- col = compl_col + (compl_cont_status & CONT_ADDING ? compl_length : 0);
+ col = compl_col + (compl_status_adding() ? compl_length : 0);
if ((int)curwin->w_cursor.col > col) {
if (stop_arrow() == FAIL) {
return;
@@ -2963,8 +3321,8 @@ void ins_compl_delete(void)
/// "in_compl_func" is true when called from complete_check().
void ins_compl_insert(bool in_compl_func)
{
- ins_bytes(compl_shown_match->cp_str + get_compl_len());
- compl_used_match = !(compl_shown_match->cp_flags & CP_ORIGINAL_TEXT);
+ ins_bytes((char *)compl_shown_match->cp_str + get_compl_len());
+ compl_used_match = !match_at_original_text(compl_shown_match);
dict_T *dict = ins_compl_dict_alloc(compl_shown_match);
set_vim_var_dict(VV_COMPLETED_ITEM, dict);
@@ -2973,97 +3331,69 @@ void ins_compl_insert(bool in_compl_func)
}
}
-/// Fill in the next completion in the current direction.
-/// If "allow_get_expansion" is true, then we may call ins_compl_get_exp() to
-/// get more completions. If it is false, then we just do nothing when there
-/// are no more completions in a given direction. The latter case is used when
-/// we are still in the middle of finding completions, to allow browsing
-/// through the ones found so far.
-/// @return the total number of matches, or -1 if still unknown -- webb.
-///
-/// compl_curr_match is currently being used by ins_compl_get_exp(), so we use
-/// compl_shown_match here.
-///
-/// Note that this function may be called recursively once only. First with
-/// "allow_get_expansion" true, which calls ins_compl_get_exp(), which in turn
-/// calls this function with "allow_get_expansion" false.
-///
-/// @param count Repeat completion this many times; should be at least 1
-/// @param insert_match Insert the newly selected match
-/// @param in_compl_func Called from complete_check()
-static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match,
- bool in_compl_func)
+/// show the file name for the completion match (if any). Truncate the file
+/// name to avoid a wait for return.
+static void ins_compl_show_filename(void)
{
- int num_matches = -1;
- int todo = count;
- compl_T *found_compl = NULL;
- bool found_end = false;
- const bool started = compl_started;
-
- // When user complete function return -1 for findstart which is next
- // time of 'always', compl_shown_match become NULL.
- if (compl_shown_match == NULL) {
- return -1;
+ char *const lead = _("match in file");
+ int space = sc_col - vim_strsize(lead) - 2;
+ if (space <= 0) {
+ return;
}
- if (compl_leader != NULL
- && (compl_shown_match->cp_flags & CP_ORIGINAL_TEXT) == 0) {
- // Set "compl_shown_match" to the actually shown match, it may differ
- // when "compl_leader" is used to omit some of the matches.
- while (!ins_compl_equal(compl_shown_match,
- compl_leader, STRLEN(compl_leader))
- && compl_shown_match->cp_next != NULL
- && compl_shown_match->cp_next != compl_first_match) {
- compl_shown_match = compl_shown_match->cp_next;
- }
-
- // If we didn't find it searching forward, and compl_shows_dir is
- // backward, find the last match.
- if (compl_shows_dir == BACKWARD
- && !ins_compl_equal(compl_shown_match, compl_leader, STRLEN(compl_leader))
- && (compl_shown_match->cp_next == NULL
- || compl_shown_match->cp_next == compl_first_match)) {
- while (!ins_compl_equal(compl_shown_match, compl_leader, STRLEN(compl_leader))
- && compl_shown_match->cp_prev != NULL
- && compl_shown_match->cp_prev != compl_first_match) {
- compl_shown_match = compl_shown_match->cp_prev;
- }
+ // We need the tail that fits. With double-byte encoding going
+ // back from the end is very slow, thus go from the start and keep
+ // the text that fits in "space" between "s" and "e".
+ char *s;
+ char *e;
+ for (s = e = (char *)compl_shown_match->cp_fname; *e != NUL; MB_PTR_ADV(e)) {
+ space -= ptr2cells(e);
+ while (space < 0) {
+ space += ptr2cells(s);
+ MB_PTR_ADV(s);
}
}
+ msg_hist_off = true;
+ vim_snprintf((char *)IObuff, IOSIZE, "%s %s%s", lead,
+ (char_u *)s > compl_shown_match->cp_fname ? "<" : "", s);
+ msg((char *)IObuff);
+ msg_hist_off = false;
+ redraw_cmdline = false; // don't overwrite!
+}
- if (allow_get_expansion && insert_match
- && (!(compl_get_longest || compl_restarting) || compl_used_match)) {
- // Delete old text to be replaced
- ins_compl_delete();
- }
-
- // When finding the longest common text we stick at the original text,
- // don't let CTRL-N or CTRL-P move to the first match.
- bool advance = count != 1 || !allow_get_expansion || !compl_get_longest;
-
- // When restarting the search don't insert the first match either.
- if (compl_restarting) {
- advance = false;
- compl_restarting = false;
- }
+/// Find the next set of matches for completion. Repeat the completion "todo"
+/// times. The number of matches found is returned in 'num_matches'.
+///
+/// @param allow_get_expansion If true, then ins_compl_get_exp() may be called to
+/// get more completions.
+/// If false, then do nothing when there are no more
+/// completions in the given direction.
+/// @param todo repeat completion this many times
+/// @param advance If true, then completion will move to the first match.
+/// Otherwise, the original text will be shown.
+///
+/// @return OK on success and -1 if the number of matches are unknown.
+static int find_next_completion_match(bool allow_get_expansion, int todo, bool advance,
+ int *num_matches)
+{
+ bool found_end = false;
+ compl_T *found_compl = NULL;
- // Repeat this for when <PageUp> or <PageDown> is typed. But don't wrap
- // around.
while (--todo >= 0) {
- if (compl_shows_dir == FORWARD && compl_shown_match->cp_next != NULL) {
+ if (compl_shows_dir_forward() && compl_shown_match->cp_next != NULL) {
compl_shown_match = compl_shown_match->cp_next;
found_end = (compl_first_match != NULL
- && (compl_shown_match->cp_next == compl_first_match
- || compl_shown_match == compl_first_match));
- } else if (compl_shows_dir == BACKWARD
+ && (is_first_match(compl_shown_match->cp_next)
+ || is_first_match(compl_shown_match)));
+ } else if (compl_shows_dir_backward()
&& compl_shown_match->cp_prev != NULL) {
- found_end = (compl_shown_match == compl_first_match);
+ found_end = is_first_match(compl_shown_match);
compl_shown_match = compl_shown_match->cp_prev;
- found_end |= (compl_shown_match == compl_first_match);
+ found_end |= is_first_match(compl_shown_match);
} else {
if (!allow_get_expansion) {
if (advance) {
- if (compl_shows_dir == BACKWARD) {
+ if (compl_shows_dir_backward()) {
compl_pending -= todo + 1;
} else {
compl_pending += todo + 1;
@@ -3073,7 +3403,7 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match
}
if (!compl_no_select && advance) {
- if (compl_shows_dir == BACKWARD) {
+ if (compl_shows_dir_backward()) {
compl_pending--;
} else {
compl_pending++;
@@ -3081,7 +3411,7 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match
}
// Find matches.
- num_matches = ins_compl_get_exp(&compl_startpos);
+ *num_matches = ins_compl_get_exp(&compl_startpos);
// handle any pending completions
while (compl_pending != 0 && compl_direction == compl_shows_dir
@@ -3099,7 +3429,7 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match
}
found_end = false;
}
- if ((compl_shown_match->cp_flags & CP_ORIGINAL_TEXT) == 0
+ if (!match_at_original_text(compl_shown_match)
&& compl_leader != NULL
&& !ins_compl_equal(compl_shown_match,
compl_leader, STRLEN(compl_leader))) {
@@ -3119,15 +3449,77 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match
}
}
+ return OK;
+}
+
+/// Fill in the next completion in the current direction.
+/// If "allow_get_expansion" is true, then we may call ins_compl_get_exp() to
+/// get more completions. If it is false, then we just do nothing when there
+/// are no more completions in a given direction. The latter case is used when
+/// we are still in the middle of finding completions, to allow browsing
+/// through the ones found so far.
+/// @return the total number of matches, or -1 if still unknown -- webb.
+///
+/// compl_curr_match is currently being used by ins_compl_get_exp(), so we use
+/// compl_shown_match here.
+///
+/// Note that this function may be called recursively once only. First with
+/// "allow_get_expansion" true, which calls ins_compl_get_exp(), which in turn
+/// calls this function with "allow_get_expansion" false.
+///
+/// @param count Repeat completion this many times; should be at least 1
+/// @param insert_match Insert the newly selected match
+/// @param in_compl_func Called from complete_check()
+static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match,
+ bool in_compl_func)
+{
+ int num_matches = -1;
+ int todo = count;
+ const bool started = compl_started;
+
+ // When user complete function return -1 for findstart which is next
+ // time of 'always', compl_shown_match become NULL.
+ if (compl_shown_match == NULL) {
+ return -1;
+ }
+
+ if (compl_leader != NULL && !match_at_original_text(compl_shown_match)) {
+ // Update "compl_shown_match" to the actually shown match
+ ins_compl_update_shown_match();
+ }
+
+ if (allow_get_expansion && insert_match
+ && (!(compl_get_longest || compl_restarting) || compl_used_match)) {
+ // Delete old text to be replaced
+ ins_compl_delete();
+ }
+
+ // When finding the longest common text we stick at the original text,
+ // don't let CTRL-N or CTRL-P move to the first match.
+ bool advance = count != 1 || !allow_get_expansion || !compl_get_longest;
+
+ // When restarting the search don't insert the first match either.
+ if (compl_restarting) {
+ advance = false;
+ compl_restarting = false;
+ }
+
+ // Repeat this for when <PageUp> or <PageDown> is typed. But don't wrap
+ // around.
+ if (find_next_completion_match(allow_get_expansion, todo, advance,
+ &num_matches) == -1) {
+ return -1;
+ }
+
// Insert the text of the new completion, or the compl_leader.
if (compl_no_insert && !started) {
- ins_bytes(compl_orig_text + get_compl_len());
+ ins_bytes((char *)compl_orig_text + get_compl_len());
compl_used_match = false;
} else if (insert_match) {
if (!compl_get_longest || compl_used_match) {
ins_compl_insert(in_compl_func);
} else {
- ins_bytes(compl_leader + get_compl_len());
+ ins_bytes((char *)compl_leader + get_compl_len());
}
} else {
compl_used_match = false;
@@ -3154,31 +3546,8 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match
}
// Show the file name for the match (if any)
- // Truncate the file name to avoid a wait for return.
if (compl_shown_match->cp_fname != NULL) {
- char *lead = _("match in file");
- int space = sc_col - vim_strsize(lead) - 2;
- char *s;
- char *e;
-
- if (space > 0) {
- // We need the tail that fits. With double-byte encoding going
- // back from the end is very slow, thus go from the start and keep
- // the text that fits in "space" between "s" and "e".
- for (s = e = (char *)compl_shown_match->cp_fname; *e != NUL; MB_PTR_ADV(e)) {
- space -= ptr2cells(e);
- while (space < 0) {
- space += ptr2cells(s);
- MB_PTR_ADV(s);
- }
- }
- msg_hist_off = true;
- vim_snprintf((char *)IObuff, IOSIZE, "%s %s%s", lead,
- (char_u *)s > compl_shown_match->cp_fname ? "<" : "", s);
- msg((char *)IObuff);
- msg_hist_off = false;
- redraw_cmdline = false; // don't overwrite!
- }
+ ins_compl_show_filename();
}
return num_matches;
@@ -3331,7 +3700,7 @@ static bool ins_compl_use_match(int c)
static int get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col)
{
if ((compl_cont_status & CONT_SOL) || ctrl_x_mode_path_defines()) {
- if (!(compl_cont_status & CONT_ADDING)) {
+ if (!compl_status_adding()) {
while (--startcol >= 0 && vim_isIDc(line[startcol])) {}
compl_col += ++startcol;
compl_length = curs_col - startcol;
@@ -3341,7 +3710,7 @@ static int get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col)
} else {
compl_pattern = (char *)vim_strnsave(line + compl_col, (size_t)compl_length);
}
- } else if (compl_cont_status & CONT_ADDING) {
+ } else if (compl_status_adding()) {
char_u *prefix = (char_u *)"\\<";
// we need up to 2 extra chars for the prefix
@@ -3398,7 +3767,7 @@ static int get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col)
/// Sets the global variables: compl_col, compl_length and compl_pattern.
static int get_wholeline_compl_info(char_u *line, colnr_T curs_col)
{
- compl_col = (colnr_T)getwhitecols(line);
+ compl_col = (colnr_T)getwhitecols((char *)line);
compl_length = (int)curs_col - (int)compl_col;
if (compl_length < 0) { // cursor in indent: empty pattern
compl_length = 0;
@@ -3510,7 +3879,7 @@ static int get_userdefined_compl_info(colnr_T curs_col)
return FAIL;
}
- // Reset extended parameters of completion, when start new
+ // Reset extended parameters of completion, when starting new
// completion.
compl_opt_refresh_always = false;
@@ -3557,6 +3926,14 @@ static int get_spell_compl_info(int startcol, colnr_T curs_col)
}
/// Get the completion pattern, column and length.
+///
+/// @param startcol start column number of the completion pattern/text
+/// @param cur_col current cursor column
+///
+/// On return, "line_invalid" is set to true, if the current line may have
+/// become invalid and needs to be fetched again.
+///
+/// @return OK on success.
static int compl_get_info(char_u *line, int startcol, colnr_T curs_col, bool *line_invalid)
{
if (ctrl_x_mode_normal()
@@ -3574,12 +3951,12 @@ static int compl_get_info(char_u *line, int startcol, colnr_T curs_col, bool *li
if (get_userdefined_compl_info(curs_col) == FAIL) {
return FAIL;
}
- *line_invalid = true; // 'line' may have become invalid
+ *line_invalid = true; // "line" may have become invalid
} else if (ctrl_x_mode_spell()) {
if (get_spell_compl_info(startcol, curs_col) == FAIL) {
return FAIL;
}
- *line_invalid = true; // 'line' may have become invalid
+ *line_invalid = true; // "line" may have become invalid
} else {
internal_error("ins_complete()");
return FAIL;
@@ -3588,232 +3965,191 @@ static int compl_get_info(char_u *line, int startcol, colnr_T curs_col, bool *li
return OK;
}
-/// Do Insert mode completion.
-/// Called when character "c" was typed, which has a meaning for completion.
-/// Returns OK if completion was done, FAIL if something failed.
-int ins_complete(int c, bool enable_pum)
+/// Continue an interrupted completion mode search in "line".
+///
+/// If this same ctrl_x_mode has been interrupted use the text from
+/// "compl_startpos" to the cursor as a pattern to add a new word instead of
+/// expand the one before the cursor, in word-wise if "compl_startpos" is not in
+/// the same line as the cursor then fix it (the line has been split because it
+/// was longer than 'tw'). if SOL is set then skip the previous pattern, a word
+/// at the beginning of the line has been inserted, we'll look for that.
+static void ins_compl_continue_search(char_u *line)
{
- char_u *line;
- int startcol = 0; // column where searched text starts
- colnr_T curs_col; // cursor column
- int n;
- int save_w_wrow;
- int save_w_leftcol;
- int insert_match;
- const bool save_did_ai = did_ai;
- int flags = CP_ORIGINAL_TEXT;
- bool line_invalid = false;
-
- compl_direction = ins_compl_key2dir(c);
- insert_match = ins_compl_use_match(c);
-
- if (!compl_started) {
- // First time we hit ^N or ^P (in a row, I mean)
-
- did_ai = false;
- did_si = false;
- can_si = false;
- can_si_back = false;
- if (stop_arrow() == FAIL) {
- return FAIL;
- }
-
- line = ml_get(curwin->w_cursor.lnum);
- curs_col = curwin->w_cursor.col;
- compl_pending = 0;
-
- // If this same ctrl_x_mode has been interrupted use the text from
- // "compl_startpos" to the cursor as a pattern to add a new word
- // instead of expand the one before the cursor, in word-wise if
- // "compl_startpos" is not in the same line as the cursor then fix it
- // (the line has been split because it was longer than 'tw'). if SOL
- // is set then skip the previous pattern, a word at the beginning of
- // the line has been inserted, we'll look for that -- Acevedo.
- if ((compl_cont_status & CONT_INTRPT) == CONT_INTRPT
- && compl_cont_mode == ctrl_x_mode) {
- // it is a continued search
- compl_cont_status &= ~CONT_INTRPT; // remove INTRPT
- if (ctrl_x_mode_normal()
- || ctrl_x_mode_path_patterns()
- || ctrl_x_mode_path_defines()) {
- if (compl_startpos.lnum != curwin->w_cursor.lnum) {
- // line (probably) wrapped, set compl_startpos to the
- // first non_blank in the line, if it is not a wordchar
- // include it to get a better pattern, but then we don't
- // want the "\\<" prefix, check it below.
- compl_col = (colnr_T)getwhitecols(line);
- compl_startpos.col = compl_col;
- compl_startpos.lnum = curwin->w_cursor.lnum;
- compl_cont_status &= ~CONT_SOL; // clear SOL if present
- } else {
- // S_IPOS was set when we inserted a word that was at the
- // beginning of the line, which means that we'll go to SOL
- // mode but first we need to redefine compl_startpos
- if (compl_cont_status & CONT_S_IPOS) {
- compl_cont_status |= CONT_SOL;
- compl_startpos.col = (colnr_T)((char_u *)skipwhite((char *)line
- + compl_length
- + compl_startpos.col) - line);
- }
- compl_col = compl_startpos.col;
- }
- compl_length = curwin->w_cursor.col - (int)compl_col;
- // IObuff is used to add a "word from the next line" would we
- // have enough space? just being paranoid
-#define MIN_SPACE 75
- if (compl_length > (IOSIZE - MIN_SPACE)) {
- compl_cont_status &= ~CONT_SOL;
- compl_length = (IOSIZE - MIN_SPACE);
- compl_col = curwin->w_cursor.col - compl_length;
- }
- compl_cont_status |= CONT_ADDING | CONT_N_ADDS;
- if (compl_length < 1) {
- compl_cont_status &= CONT_LOCAL;
- }
- } else if (ctrl_x_mode_line_or_eval()) {
- compl_cont_status = CONT_ADDING | CONT_N_ADDS;
- } else {
- compl_cont_status = 0;
- }
+ // it is a continued search
+ compl_cont_status &= ~CONT_INTRPT; // remove INTRPT
+ if (ctrl_x_mode_normal()
+ || ctrl_x_mode_path_patterns()
+ || ctrl_x_mode_path_defines()) {
+ if (compl_startpos.lnum != curwin->w_cursor.lnum) {
+ // line (probably) wrapped, set compl_startpos to the
+ // first non_blank in the line, if it is not a wordchar
+ // include it to get a better pattern, but then we don't
+ // want the "\\<" prefix, check it below.
+ compl_col = (colnr_T)getwhitecols((char *)line);
+ compl_startpos.col = compl_col;
+ compl_startpos.lnum = curwin->w_cursor.lnum;
+ compl_cont_status &= ~CONT_SOL; // clear SOL if present
} else {
- compl_cont_status &= CONT_LOCAL;
- }
-
- if (!(compl_cont_status & CONT_ADDING)) { // normal expansion
- compl_cont_mode = ctrl_x_mode;
- if (ctrl_x_mode_not_default()) {
- // Remove LOCAL if ctrl_x_mode != CTRL_X_NORMAL
- compl_cont_status = 0;
+ // S_IPOS was set when we inserted a word that was at the
+ // beginning of the line, which means that we'll go to SOL
+ // mode but first we need to redefine compl_startpos
+ if (compl_cont_status & CONT_S_IPOS) {
+ compl_cont_status |= CONT_SOL;
+ compl_startpos.col = (colnr_T)((char_u *)skipwhite((char *)line
+ + compl_length
+ + compl_startpos.col) - line);
}
- compl_cont_status |= CONT_N_ADDS;
- compl_startpos = curwin->w_cursor;
- startcol = (int)curs_col;
- compl_col = 0;
- }
-
- // Work out completion pattern and original text -- webb
- if (compl_get_info(line, startcol, curs_col, &line_invalid) == FAIL) {
- if (ctrl_x_mode_function() || ctrl_x_mode_omni()
- || thesaurus_func_complete(ctrl_x_mode)) {
- // restore did_ai, so that adding comment leader works
- did_ai = save_did_ai;
- }
- return FAIL;
+ compl_col = compl_startpos.col;
}
- // If "line" was changed while getting completion info get it again.
- if (line_invalid) {
- line = ml_get(curwin->w_cursor.lnum);
+ compl_length = curwin->w_cursor.col - (int)compl_col;
+ // IObuff is used to add a "word from the next line" would we
+ // have enough space? just being paranoid
+#define MIN_SPACE 75
+ if (compl_length > (IOSIZE - MIN_SPACE)) {
+ compl_cont_status &= ~CONT_SOL;
+ compl_length = (IOSIZE - MIN_SPACE);
+ compl_col = curwin->w_cursor.col - compl_length;
+ }
+ compl_cont_status |= CONT_ADDING | CONT_N_ADDS;
+ if (compl_length < 1) {
+ compl_cont_status &= CONT_LOCAL;
}
+ } else if (ctrl_x_mode_line_or_eval()) {
+ compl_cont_status = CONT_ADDING | CONT_N_ADDS;
+ } else {
+ compl_cont_status = 0;
+ }
+}
- if (compl_cont_status & CONT_ADDING) {
- edit_submode_pre = (char_u *)_(" Adding");
- if (ctrl_x_mode_line_or_eval()) {
- // Insert a new line, keep indentation but ignore 'comments'.
- char_u *old = curbuf->b_p_com;
+/// start insert mode completion
+static int ins_compl_start(void)
+{
+ const bool save_did_ai = did_ai;
- curbuf->b_p_com = (char_u *)"";
- compl_startpos.lnum = curwin->w_cursor.lnum;
- compl_startpos.col = compl_col;
- ins_eol('\r');
- curbuf->b_p_com = old;
- compl_length = 0;
- compl_col = curwin->w_cursor.col;
- }
- } else {
- edit_submode_pre = NULL;
- compl_startpos.col = compl_col;
- }
+ // First time we hit ^N or ^P (in a row, I mean)
- if (compl_cont_status & CONT_LOCAL) {
- edit_submode = (char_u *)_(ctrl_x_msgs[CTRL_X_LOCAL_MSG]);
- } else {
- edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
- }
+ did_ai = false;
+ did_si = false;
+ can_si = false;
+ can_si_back = false;
+ if (stop_arrow() == FAIL) {
+ return FAIL;
+ }
- // If any of the original typed text has been changed we need to fix
- // the redo buffer.
- ins_compl_fixRedoBufForLeader(NULL);
+ char_u *line = ml_get(curwin->w_cursor.lnum);
+ colnr_T curs_col = curwin->w_cursor.col;
+ compl_pending = 0;
+
+ if ((compl_cont_status & CONT_INTRPT) == CONT_INTRPT
+ && compl_cont_mode == ctrl_x_mode) {
+ // this same ctrl-x_mode was interrupted previously. Continue the
+ // completion.
+ ins_compl_continue_search(line);
+ } else {
+ compl_cont_status &= CONT_LOCAL;
+ }
- // Always add completion for the original text.
- xfree(compl_orig_text);
- compl_orig_text = vim_strnsave(line + compl_col, (size_t)compl_length);
- if (p_ic) {
- flags |= CP_ICASE;
- }
- if (ins_compl_add(compl_orig_text, -1, NULL, NULL, false, NULL, 0,
- flags, false) != OK) {
- XFREE_CLEAR(compl_pattern);
- XFREE_CLEAR(compl_orig_text);
- return FAIL;
+ int startcol = 0; // column where searched text starts
+ if (!compl_status_adding()) { // normal expansion
+ compl_cont_mode = ctrl_x_mode;
+ if (ctrl_x_mode_not_default()) {
+ // Remove LOCAL if ctrl_x_mode != CTRL_X_NORMAL
+ compl_cont_status = 0;
}
+ compl_cont_status |= CONT_N_ADDS;
+ compl_startpos = curwin->w_cursor;
+ startcol = (int)curs_col;
+ compl_col = 0;
+ }
- // showmode might reset the internal line pointers, so it must
- // be called before line = ml_get(), or when this address is no
- // longer needed. -- Acevedo.
- edit_submode_extra = (char_u *)_("-- Searching...");
- edit_submode_highl = HLF_COUNT;
- showmode();
- edit_submode_extra = NULL;
- ui_flush();
- } else if (insert_match && stop_arrow() == FAIL) {
+ // Work out completion pattern and original text -- webb
+ bool line_invalid = false;
+ if (compl_get_info(line, startcol, curs_col, &line_invalid) == FAIL) {
+ if (ctrl_x_mode_function() || ctrl_x_mode_omni()
+ || thesaurus_func_complete(ctrl_x_mode)) {
+ // restore did_ai, so that adding comment leader works
+ did_ai = save_did_ai;
+ }
return FAIL;
}
+ // If "line" was changed while getting completion info get it again.
+ if (line_invalid) {
+ line = ml_get(curwin->w_cursor.lnum);
+ }
- compl_shown_match = compl_curr_match;
- compl_shows_dir = compl_direction;
+ if (compl_status_adding()) {
+ edit_submode_pre = _(" Adding");
+ if (ctrl_x_mode_line_or_eval()) {
+ // Insert a new line, keep indentation but ignore 'comments'.
+ char *old = curbuf->b_p_com;
- // Find next match (and following matches).
- save_w_wrow = curwin->w_wrow;
- save_w_leftcol = curwin->w_leftcol;
- n = ins_compl_next(true, ins_compl_key2count(c), insert_match, false);
+ curbuf->b_p_com = "";
+ compl_startpos.lnum = curwin->w_cursor.lnum;
+ compl_startpos.col = compl_col;
+ ins_eol('\r');
+ curbuf->b_p_com = old;
+ compl_length = 0;
+ compl_col = curwin->w_cursor.col;
+ }
+ } else {
+ edit_submode_pre = NULL;
+ compl_startpos.col = compl_col;
+ }
- if (n > 1) { // all matches have been found
- compl_matches = n;
+ if (compl_cont_status & CONT_LOCAL) {
+ edit_submode = _(ctrl_x_msgs[CTRL_X_LOCAL_MSG]);
+ } else {
+ edit_submode = _(CTRL_X_MSG(ctrl_x_mode));
}
- compl_curr_match = compl_shown_match;
- compl_direction = compl_shows_dir;
- // Eat the ESC that vgetc() returns after a CTRL-C to avoid leaving Insert
- // mode.
- if (got_int && !global_busy) {
- (void)vgetc();
- got_int = false;
+ // If any of the original typed text has been changed we need to fix
+ // the redo buffer.
+ ins_compl_fixRedoBufForLeader(NULL);
+
+ // Always add completion for the original text.
+ xfree(compl_orig_text);
+ compl_orig_text = vim_strnsave(line + compl_col, (size_t)compl_length);
+ int flags = CP_ORIGINAL_TEXT;
+ if (p_ic) {
+ flags |= CP_ICASE;
}
+ if (ins_compl_add(compl_orig_text, -1, NULL, NULL, false, NULL, 0,
+ flags, false) != OK) {
+ XFREE_CLEAR(compl_pattern);
+ XFREE_CLEAR(compl_orig_text);
+ return FAIL;
+ }
+
+ // showmode might reset the internal line pointers, so it must
+ // be called before line = ml_get(), or when this address is no
+ // longer needed. -- Acevedo.
+ edit_submode_extra = _("-- Searching...");
+ edit_submode_highl = HLF_COUNT;
+ showmode();
+ edit_submode_extra = NULL;
+ ui_flush();
+
+ return OK;
+}
+/// display the completion status message
+static void ins_compl_show_statusmsg(void)
+{
// we found no match if the list has only the "compl_orig_text"-entry
- if (compl_first_match == compl_first_match->cp_next) {
- edit_submode_extra = (compl_cont_status & CONT_ADDING)
- && compl_length > 1
- ? (char_u *)_(e_hitend) : (char_u *)_(e_patnotf);
+ if (is_first_match(compl_first_match->cp_next)) {
+ edit_submode_extra = compl_status_adding() && compl_length > 1 ? _(e_hitend) : _(e_patnotf);
edit_submode_highl = HLF_E;
- // remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode,
- // because we couldn't expand anything at first place, but if we used
- // ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word
- // (such as M in M'exico) if not tried already. -- Acevedo
- if (compl_length > 1
- || (compl_cont_status & CONT_ADDING)
- || (ctrl_x_mode_not_default()
- && !ctrl_x_mode_path_patterns()
- && !ctrl_x_mode_path_defines())) {
- compl_cont_status &= ~CONT_N_ADDS;
- }
- }
-
- if (compl_curr_match->cp_flags & CP_CONT_S_IPOS) {
- compl_cont_status |= CONT_S_IPOS;
- } else {
- compl_cont_status &= ~CONT_S_IPOS;
}
if (edit_submode_extra == NULL) {
- if (compl_curr_match->cp_flags & CP_ORIGINAL_TEXT) {
- edit_submode_extra = (char_u *)_("Back at original");
+ if (match_at_original_text(compl_curr_match)) {
+ edit_submode_extra = _("Back at original");
edit_submode_highl = HLF_W;
} else if (compl_cont_status & CONT_S_IPOS) {
- edit_submode_extra = (char_u *)_("Word from other line");
+ edit_submode_extra = _("Word from other line");
edit_submode_highl = HLF_COUNT;
} else if (compl_curr_match->cp_next == compl_curr_match->cp_prev) {
- edit_submode_extra = (char_u *)_("The only match");
+ edit_submode_extra = _("The only match");
edit_submode_highl = HLF_COUNT;
compl_curr_match->cp_number = 1;
} else {
@@ -3838,7 +4174,7 @@ int ins_complete(int c, bool enable_pum)
_("match %d"),
compl_curr_match->cp_number);
}
- edit_submode_extra = match_ref;
+ edit_submode_extra = (char *)match_ref;
edit_submode_highl = HLF_R;
if (dollar_vcol >= 0) {
curs_columns(curwin, false);
@@ -3862,6 +4198,72 @@ int ins_complete(int c, bool enable_pum)
msg_clr_cmdline(); // necessary for "noshowmode"
}
}
+}
+
+/// Do Insert mode completion.
+/// Called when character "c" was typed, which has a meaning for completion.
+/// Returns OK if completion was done, FAIL if something failed.
+int ins_complete(int c, bool enable_pum)
+{
+ int n;
+ int save_w_wrow;
+ int save_w_leftcol;
+ int insert_match;
+
+ compl_direction = ins_compl_key2dir(c);
+ insert_match = ins_compl_use_match(c);
+
+ if (!compl_started) {
+ if (ins_compl_start() == FAIL) {
+ return FAIL;
+ }
+ } else if (insert_match && stop_arrow() == FAIL) {
+ return FAIL;
+ }
+
+ compl_shown_match = compl_curr_match;
+ compl_shows_dir = compl_direction;
+
+ // Find next match (and following matches).
+ save_w_wrow = curwin->w_wrow;
+ save_w_leftcol = curwin->w_leftcol;
+ n = ins_compl_next(true, ins_compl_key2count(c), insert_match, false);
+
+ if (n > 1) { // all matches have been found
+ compl_matches = n;
+ }
+ compl_curr_match = compl_shown_match;
+ compl_direction = compl_shows_dir;
+
+ // Eat the ESC that vgetc() returns after a CTRL-C to avoid leaving Insert
+ // mode.
+ if (got_int && !global_busy) {
+ (void)vgetc();
+ got_int = false;
+ }
+
+ // we found no match if the list has only the "compl_orig_text"-entry
+ if (is_first_match(compl_first_match->cp_next)) {
+ // remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode,
+ // because we couldn't expand anything at first place, but if we used
+ // ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word
+ // (such as M in M'exico) if not tried already. -- Acevedo
+ if (compl_length > 1
+ || compl_status_adding()
+ || (ctrl_x_mode_not_default()
+ && !ctrl_x_mode_path_patterns()
+ && !ctrl_x_mode_path_defines())) {
+ compl_cont_status &= ~CONT_N_ADDS;
+ }
+ }
+
+ if (compl_curr_match->cp_flags & CP_CONT_S_IPOS) {
+ compl_cont_status |= CONT_S_IPOS;
+ } else {
+ compl_cont_status &= ~CONT_S_IPOS;
+ }
+
+ ins_compl_show_statusmsg();
// Show the popup menu, unless we got interrupted.
if (enable_pum && !compl_interrupted) {
@@ -3873,6 +4275,7 @@ int ins_complete(int c, bool enable_pum)
return OK;
}
+/// Remove (if needed) and show the popup menu
static void show_pum(int prev_w_wrow, int prev_w_leftcol)
{
// RedrawingDisabled may be set when invoked through complete().
diff --git a/src/nvim/keycodes.c b/src/nvim/keycodes.c
index 5a5257efb2..2b00d371f0 100644
--- a/src/nvim/keycodes.c
+++ b/src/nvim/keycodes.c
@@ -57,15 +57,15 @@ static char_u modifier_keys_table[] =
MOD_MASK_SHIFT, '*', '4', 'k', 'D', // delete char
MOD_MASK_SHIFT, '*', '5', 'k', 'L', // delete line
MOD_MASK_SHIFT, '*', '7', '@', '7', // end
- MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_END, '@', '7', // end
+ MOD_MASK_CTRL, KS_EXTRA, KE_C_END, '@', '7', // end
MOD_MASK_SHIFT, '*', '9', '@', '9', // exit
MOD_MASK_SHIFT, '*', '0', '@', '0', // find
MOD_MASK_SHIFT, '#', '1', '%', '1', // help
MOD_MASK_SHIFT, '#', '2', 'k', 'h', // home
- MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_HOME, 'k', 'h', // home
+ MOD_MASK_CTRL, KS_EXTRA, KE_C_HOME, 'k', 'h', // home
MOD_MASK_SHIFT, '#', '3', 'k', 'I', // insert
MOD_MASK_SHIFT, '#', '4', 'k', 'l', // left arrow
- MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_LEFT, 'k', 'l', // left arrow
+ MOD_MASK_CTRL, KS_EXTRA, KE_C_LEFT, 'k', 'l', // left arrow
MOD_MASK_SHIFT, '%', 'a', '%', '3', // message
MOD_MASK_SHIFT, '%', 'b', '%', '4', // move
MOD_MASK_SHIFT, '%', 'c', '%', '5', // next
@@ -75,63 +75,63 @@ static char_u modifier_keys_table[] =
MOD_MASK_SHIFT, '%', 'g', '%', '0', // redo
MOD_MASK_SHIFT, '%', 'h', '&', '3', // replace
MOD_MASK_SHIFT, '%', 'i', 'k', 'r', // right arr.
- MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_RIGHT, 'k', 'r', // right arr.
+ MOD_MASK_CTRL, KS_EXTRA, KE_C_RIGHT, 'k', 'r', // right arr.
MOD_MASK_SHIFT, '%', 'j', '&', '5', // resume
MOD_MASK_SHIFT, '!', '1', '&', '6', // save
MOD_MASK_SHIFT, '!', '2', '&', '7', // suspend
MOD_MASK_SHIFT, '!', '3', '&', '8', // undo
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_UP, 'k', 'u', // up arrow
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_DOWN, 'k', 'd', // down arrow
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_UP, 'k', 'u', // up arrow
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_DOWN, 'k', 'd', // down arrow
// vt100 F1
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF1, KS_EXTRA, (int)KE_XF1,
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF2, KS_EXTRA, (int)KE_XF2,
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF3, KS_EXTRA, (int)KE_XF3,
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF4, KS_EXTRA, (int)KE_XF4,
-
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F1, 'k', '1', // F1
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F2, 'k', '2',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F3, 'k', '3',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F4, 'k', '4',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F5, 'k', '5',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F6, 'k', '6',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F7, 'k', '7',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F8, 'k', '8',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F9, 'k', '9',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F10, 'k', ';', // F10
-
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F11, 'F', '1',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F12, 'F', '2',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F13, 'F', '3',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F14, 'F', '4',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F15, 'F', '5',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F16, 'F', '6',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F17, 'F', '7',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F18, 'F', '8',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F19, 'F', '9',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F20, 'F', 'A',
-
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F21, 'F', 'B',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F22, 'F', 'C',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F23, 'F', 'D',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F24, 'F', 'E',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F25, 'F', 'F',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F26, 'F', 'G',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F27, 'F', 'H',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F28, 'F', 'I',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F29, 'F', 'J',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F30, 'F', 'K',
-
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F31, 'F', 'L',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F32, 'F', 'M',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F33, 'F', 'N',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F34, 'F', 'O',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F35, 'F', 'P',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F36, 'F', 'Q',
- MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F37, 'F', 'R',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_XF1, KS_EXTRA, KE_XF1,
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_XF2, KS_EXTRA, KE_XF2,
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_XF3, KS_EXTRA, KE_XF3,
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_XF4, KS_EXTRA, KE_XF4,
+
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F1, 'k', '1', // F1
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F2, 'k', '2',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F3, 'k', '3',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F4, 'k', '4',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F5, 'k', '5',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F6, 'k', '6',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F7, 'k', '7',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F8, 'k', '8',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F9, 'k', '9',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F10, 'k', ';', // F10
+
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F11, 'F', '1',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F12, 'F', '2',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F13, 'F', '3',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F14, 'F', '4',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F15, 'F', '5',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F16, 'F', '6',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F17, 'F', '7',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F18, 'F', '8',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F19, 'F', '9',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F20, 'F', 'A',
+
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F21, 'F', 'B',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F22, 'F', 'C',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F23, 'F', 'D',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F24, 'F', 'E',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F25, 'F', 'F',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F26, 'F', 'G',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F27, 'F', 'H',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F28, 'F', 'I',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F29, 'F', 'J',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F30, 'F', 'K',
+
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F31, 'F', 'L',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F32, 'F', 'M',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F33, 'F', 'N',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F34, 'F', 'O',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F35, 'F', 'P',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F36, 'F', 'Q',
+ MOD_MASK_SHIFT, KS_EXTRA, KE_S_F37, 'F', 'R',
// TAB pseudo code
- MOD_MASK_SHIFT, 'k', 'B', KS_EXTRA, (int)KE_TAB,
+ MOD_MASK_SHIFT, 'k', 'B', KS_EXTRA, KE_TAB,
NUL
};
@@ -349,26 +349,26 @@ static struct mousetable {
bool is_drag; // Is it a mouse drag event?
} mouse_table[] =
{
- { (int)KE_LEFTMOUSE, MOUSE_LEFT, true, false },
- { (int)KE_LEFTDRAG, MOUSE_LEFT, false, true },
- { (int)KE_LEFTRELEASE, MOUSE_LEFT, false, false },
- { (int)KE_MIDDLEMOUSE, MOUSE_MIDDLE, true, false },
- { (int)KE_MIDDLEDRAG, MOUSE_MIDDLE, false, true },
- { (int)KE_MIDDLERELEASE, MOUSE_MIDDLE, false, false },
- { (int)KE_RIGHTMOUSE, MOUSE_RIGHT, true, false },
- { (int)KE_RIGHTDRAG, MOUSE_RIGHT, false, true },
- { (int)KE_RIGHTRELEASE, MOUSE_RIGHT, false, false },
- { (int)KE_X1MOUSE, MOUSE_X1, true, false },
- { (int)KE_X1DRAG, MOUSE_X1, false, true },
- { (int)KE_X1RELEASE, MOUSE_X1, false, false },
- { (int)KE_X2MOUSE, MOUSE_X2, true, false },
- { (int)KE_X2DRAG, MOUSE_X2, false, true },
- { (int)KE_X2RELEASE, MOUSE_X2, false, false },
+ { KE_LEFTMOUSE, MOUSE_LEFT, true, false },
+ { KE_LEFTDRAG, MOUSE_LEFT, false, true },
+ { KE_LEFTRELEASE, MOUSE_LEFT, false, false },
+ { KE_MIDDLEMOUSE, MOUSE_MIDDLE, true, false },
+ { KE_MIDDLEDRAG, MOUSE_MIDDLE, false, true },
+ { KE_MIDDLERELEASE, MOUSE_MIDDLE, false, false },
+ { KE_RIGHTMOUSE, MOUSE_RIGHT, true, false },
+ { KE_RIGHTDRAG, MOUSE_RIGHT, false, true },
+ { KE_RIGHTRELEASE, MOUSE_RIGHT, false, false },
+ { KE_X1MOUSE, MOUSE_X1, true, false },
+ { KE_X1DRAG, MOUSE_X1, false, true },
+ { KE_X1RELEASE, MOUSE_X1, false, false },
+ { KE_X2MOUSE, MOUSE_X2, true, false },
+ { KE_X2DRAG, MOUSE_X2, false, true },
+ { KE_X2RELEASE, MOUSE_X2, false, false },
// DRAG without CLICK
- { (int)KE_MOUSEMOVE, MOUSE_RELEASE, false, true },
+ { KE_MOUSEMOVE, MOUSE_RELEASE, false, true },
// RELEASE without CLICK
- { (int)KE_IGNORE, MOUSE_RELEASE, false, false },
- { 0, 0, 0, 0 },
+ { KE_IGNORE, MOUSE_RELEASE, false, false },
+ { 0, 0, 0, 0 },
};
/// Return the modifier mask bit (#MOD_MASK_*) corresponding to mod name
@@ -926,8 +926,8 @@ char *replace_termcodes(const char *const from, const size_t from_len, char **co
} else {
src += 5;
result[dlen++] = K_SPECIAL;
- result[dlen++] = (int)KS_EXTRA;
- result[dlen++] = (int)KE_SNR;
+ result[dlen++] = KS_EXTRA;
+ result[dlen++] = KE_SNR;
snprintf((char *)result + dlen, buf_len - dlen, "%" PRId64,
(int64_t)current_sctx.sc_sid);
dlen += STRLEN(result + dlen);
diff --git a/src/nvim/locale.c b/src/nvim/locale.c
new file mode 100644
index 0000000000..3e0774c096
--- /dev/null
+++ b/src/nvim/locale.c
@@ -0,0 +1,369 @@
+// 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
+
+// locale.c: functions for language/locale configuration
+
+#include "auto/config.h"
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#include "nvim/ascii.h"
+#include "nvim/buffer.h"
+#include "nvim/charset.h"
+#include "nvim/eval.h"
+#include "nvim/garray.h"
+#include "nvim/locale.h"
+#include "nvim/memory.h"
+#include "nvim/message.h"
+#include "nvim/option.h"
+#include "nvim/os/os.h"
+#include "nvim/os/shell.h"
+#include "nvim/path.h"
+#include "nvim/profile.h"
+#include "nvim/types.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "locale.c.generated.h"
+#endif
+
+#if defined(HAVE_LOCALE_H)
+# define HAVE_GET_LOCALE_VAL
+
+static char *get_locale_val(int what)
+{
+ // Obtain the locale value from the libraries.
+ char *loc = setlocale(what, NULL);
+
+ return loc;
+}
+#endif
+
+/// @return true when "lang" starts with a valid language name.
+/// Rejects NULL, empty string, "C", "C.UTF-8" and others.
+static bool is_valid_mess_lang(char *lang)
+{
+ return lang != NULL && ASCII_ISALPHA(lang[0]) && ASCII_ISALPHA(lang[1]);
+}
+
+/// Obtain the current messages language. Used to set the default for
+/// 'helplang'. May return NULL or an empty string.
+char *get_mess_lang(void)
+{
+ char *p;
+
+#ifdef HAVE_GET_LOCALE_VAL
+# if defined(LC_MESSAGES)
+ p = get_locale_val(LC_MESSAGES);
+# else
+ // This is necessary for Win32, where LC_MESSAGES is not defined and $LANG
+ // may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME
+ // and LC_MONETARY may be set differently for a Japanese working in the
+ // US.
+ p = get_locale_val(LC_COLLATE);
+# endif
+#else
+ p = os_getenv("LC_ALL");
+ if (!is_valid_mess_lang(p)) {
+ p = os_getenv("LC_MESSAGES");
+ if (!is_valid_mess_lang(p)) {
+ p = os_getenv("LANG");
+ }
+ }
+#endif
+ return is_valid_mess_lang(p) ? p : NULL;
+}
+
+// Complicated #if; matches with where get_mess_env() is used below.
+#ifdef HAVE_WORKING_LIBINTL
+/// Get the language used for messages from the environment.
+static char *get_mess_env(void)
+{
+ char *p;
+
+ p = (char *)os_getenv("LC_ALL");
+ if (p == NULL) {
+ p = (char *)os_getenv("LC_MESSAGES");
+ if (p == NULL) {
+ p = (char *)os_getenv("LANG");
+ if (p != NULL && ascii_isdigit(*p)) {
+ p = NULL; // ignore something like "1043"
+ }
+# ifdef HAVE_GET_LOCALE_VAL
+ if (p == NULL) {
+ p = get_locale_val(LC_CTYPE);
+ }
+# endif
+ }
+ }
+ return p;
+}
+#endif
+
+/// Set the "v:lang" variable according to the current locale setting.
+/// Also do "v:lc_time"and "v:ctype".
+void set_lang_var(void)
+{
+ const char *loc;
+
+#ifdef HAVE_GET_LOCALE_VAL
+ loc = get_locale_val(LC_CTYPE);
+#else
+ // setlocale() not supported: use the default value
+ loc = "C";
+#endif
+ set_vim_var_string(VV_CTYPE, loc, -1);
+
+ // When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall
+ // back to LC_CTYPE if it's empty.
+#ifdef HAVE_WORKING_LIBINTL
+ loc = get_mess_env();
+#elif defined(LC_MESSAGES)
+ loc = get_locale_val(LC_MESSAGES);
+#else
+ // In Windows LC_MESSAGES is not defined fallback to LC_CTYPE
+ loc = get_locale_val(LC_CTYPE);
+#endif
+ set_vim_var_string(VV_LANG, loc, -1);
+
+#ifdef HAVE_GET_LOCALE_VAL
+ loc = get_locale_val(LC_TIME);
+#endif
+ set_vim_var_string(VV_LC_TIME, loc, -1);
+
+#ifdef HAVE_GET_LOCALE_VAL
+ loc = get_locale_val(LC_COLLATE);
+#else
+ // setlocale() not supported: use the default value
+ loc = "C";
+#endif
+ set_vim_var_string(VV_COLLATE, loc, -1);
+}
+
+#if defined(HAVE_LOCALE_H)
+/// Setup to use the current locale (for ctype() and many other things).
+void init_locale(void)
+{
+ setlocale(LC_ALL, "");
+
+# ifdef LC_NUMERIC
+ // Make sure strtod() uses a decimal point, not a comma.
+ setlocale(LC_NUMERIC, "C");
+# endif
+
+ char localepath[MAXPATHL] = { 0 };
+ snprintf(localepath, sizeof(localepath), "%s", get_vim_var_str(VV_PROGPATH));
+ char *tail = path_tail_with_sep(localepath);
+ *tail = NUL;
+ tail = path_tail(localepath);
+ xstrlcpy(tail, "share/locale",
+ sizeof(localepath) - (size_t)(tail - localepath));
+ bindtextdomain(PROJECT_NAME, localepath);
+ textdomain(PROJECT_NAME);
+ TIME_MSG("locale set");
+}
+#endif
+
+#ifdef HAVE_WORKING_LIBINTL
+
+/// ":language": Set the language (locale).
+///
+/// @param eap
+void ex_language(exarg_T *eap)
+{
+ char *loc;
+ char *p;
+ char *name;
+ int what = LC_ALL;
+ char *whatstr = "";
+# ifdef LC_MESSAGES
+# define VIM_LC_MESSAGES LC_MESSAGES
+# else
+# define VIM_LC_MESSAGES 6789
+# endif
+
+ name = eap->arg;
+
+ // Check for "messages {name}", "ctype {name}" or "time {name}" argument.
+ // Allow abbreviation, but require at least 3 characters to avoid
+ // confusion with a two letter language name "me" or "ct".
+ p = skiptowhite(eap->arg);
+ if ((*p == NUL || ascii_iswhite(*p)) && p - eap->arg >= 3) {
+ if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0) {
+ what = VIM_LC_MESSAGES;
+ name = skipwhite(p);
+ whatstr = "messages ";
+ } else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0) {
+ what = LC_CTYPE;
+ name = skipwhite(p);
+ whatstr = "ctype ";
+ } else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0) {
+ what = LC_TIME;
+ name = skipwhite(p);
+ whatstr = "time ";
+ } else if (STRNICMP(eap->arg, "collate", p - eap->arg) == 0) {
+ what = LC_COLLATE;
+ name = skipwhite(p);
+ whatstr = "collate ";
+ }
+ }
+
+ if (*name == NUL) {
+ if (what == VIM_LC_MESSAGES) {
+ p = get_mess_env();
+ } else {
+ p = setlocale(what, NULL);
+ }
+ if (p == NULL || *p == NUL) {
+ p = "Unknown";
+ }
+ smsg(_("Current %slanguage: \"%s\""), whatstr, p);
+ } else {
+# ifndef LC_MESSAGES
+ if (what == VIM_LC_MESSAGES) {
+ loc = "";
+ } else {
+# endif
+ loc = setlocale(what, name);
+# ifdef LC_NUMERIC
+ // Make sure strtod() uses a decimal point, not a comma.
+ setlocale(LC_NUMERIC, "C");
+# endif
+# ifndef LC_MESSAGES
+ }
+# endif
+ if (loc == NULL) {
+ semsg(_("E197: Cannot set language to \"%s\""), name);
+ } else {
+# ifdef HAVE_NL_MSG_CAT_CNTR
+ // Need to do this for GNU gettext, otherwise cached translations
+ // will be used again.
+ extern int _nl_msg_cat_cntr;
+
+ _nl_msg_cat_cntr++;
+# endif
+ // Reset $LC_ALL, otherwise it would overrule everything.
+ os_setenv("LC_ALL", "", 1);
+
+ if (what != LC_TIME && what != LC_COLLATE) {
+ // Tell gettext() what to translate to. It apparently doesn't
+ // use the currently effective locale.
+ if (what == LC_ALL) {
+ os_setenv("LANG", name, 1);
+
+ // Clear $LANGUAGE because GNU gettext uses it.
+ os_setenv("LANGUAGE", "", 1);
+ }
+ if (what != LC_CTYPE) {
+ os_setenv("LC_MESSAGES", name, 1);
+ set_helplang_default(name);
+ }
+ }
+
+ // Set v:lang, v:lc_time, v:collate and v:ctype to the final result.
+ set_lang_var();
+ maketitle();
+ }
+ }
+}
+
+static char **locales = NULL; // Array of all available locales
+
+# ifndef WIN32
+static bool did_init_locales = false;
+
+/// @return an array of strings for all available locales + NULL for the
+/// last element or,
+/// NULL in case of error.
+static char **find_locales(void)
+{
+ garray_T locales_ga;
+ char *loc;
+ char *saveptr = NULL;
+
+ // Find all available locales by running command "locale -a". If this
+ // doesn't work we won't have completion.
+ char *locale_a = (char *)get_cmd_output((char_u *)"locale -a", NULL,
+ kShellOptSilent, NULL);
+ if (locale_a == NULL) {
+ return NULL;
+ }
+ ga_init(&locales_ga, sizeof(char_u *), 20);
+
+ // Transform locale_a string where each locale is separated by "\n"
+ // into an array of locale strings.
+ loc = os_strtok(locale_a, "\n", &saveptr);
+
+ while (loc != NULL) {
+ loc = xstrdup(loc);
+ GA_APPEND(char *, &locales_ga, loc);
+ loc = os_strtok(NULL, "\n", &saveptr);
+ }
+ xfree(locale_a);
+ // Guarantee that .ga_data is NULL terminated
+ ga_grow(&locales_ga, 1);
+ ((char_u **)locales_ga.ga_data)[locales_ga.ga_len] = NULL;
+ return locales_ga.ga_data;
+}
+# endif
+
+/// Lazy initialization of all available locales.
+static void init_locales(void)
+{
+# ifndef WIN32
+ if (!did_init_locales) {
+ did_init_locales = true;
+ locales = find_locales();
+ }
+# endif
+}
+
+# if defined(EXITFREE)
+void free_locales(void)
+{
+ int i;
+ if (locales != NULL) {
+ for (i = 0; locales[i] != NULL; i++) {
+ xfree(locales[i]);
+ }
+ XFREE_CLEAR(locales);
+ }
+}
+# endif
+
+/// Function given to ExpandGeneric() to obtain the possible arguments of the
+/// ":language" command.
+char *get_lang_arg(expand_T *xp, int idx)
+{
+ if (idx == 0) {
+ return "messages";
+ }
+ if (idx == 1) {
+ return "ctype";
+ }
+ if (idx == 2) {
+ return "time";
+ }
+ if (idx == 3) {
+ return "collate";
+ }
+
+ init_locales();
+ if (locales == NULL) {
+ return NULL;
+ }
+ return locales[idx - 4];
+}
+
+/// Function given to ExpandGeneric() to obtain the available locales.
+char *get_locales(expand_T *xp, int idx)
+{
+ init_locales();
+ if (locales == NULL) {
+ return NULL;
+ }
+ return locales[idx];
+}
+
+#endif
diff --git a/src/nvim/locale.h b/src/nvim/locale.h
new file mode 100644
index 0000000000..39735d371f
--- /dev/null
+++ b/src/nvim/locale.h
@@ -0,0 +1,10 @@
+#ifndef NVIM_LOCALE_H
+#define NVIM_LOCALE_H
+
+#include "nvim/ex_cmds_defs.h"
+#include "nvim/types.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "locale.h.generated.h"
+#endif
+#endif // NVIM_LOCALE_H
diff --git a/src/nvim/log.c b/src/nvim/log.c
index 99b17a612b..9bdf327430 100644
--- a/src/nvim/log.c
+++ b/src/nvim/log.c
@@ -60,16 +60,16 @@ static bool log_try_create(char *fname)
static void log_path_init(void)
{
size_t size = sizeof(log_file_path);
- expand_env((char_u *)"$" ENV_LOGFILE, (char_u *)log_file_path, (int)size - 1);
+ expand_env("$" ENV_LOGFILE, log_file_path, (int)size - 1);
if (strequal("$" ENV_LOGFILE, log_file_path)
|| log_file_path[0] == '\0'
- || os_isdir((char_u *)log_file_path)
+ || os_isdir(log_file_path)
|| !log_try_create(log_file_path)) {
// Make $XDG_STATE_HOME if it does not exist.
char *loghome = get_xdg_home(kXDGStateHome);
char *failed_dir = NULL;
bool log_dir_failure = false;
- if (!os_isdir((char_u *)loghome)) {
+ if (!os_isdir(loghome)) {
log_dir_failure = (os_mkdir_recurse(loghome, 0700, &failed_dir) != 0);
}
XFREE_CLEAR(loghome);
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index d1d1480696..42aa13cfc1 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -990,7 +990,7 @@ int nlua_in_fast_event(lua_State *lstate)
static bool viml_func_is_fast(const char *name)
{
- const EvalFuncDef *const fdef = find_internal_func((const char *)name);
+ const EvalFuncDef *const fdef = find_internal_func(name);
if (fdef) {
return fdef->fast;
}
@@ -1027,7 +1027,7 @@ int nlua_call(lua_State *lstate)
// TODO(bfredl): this should be simplified in error handling refactor
force_abort = false;
suppress_errthrow = false;
- current_exception = NULL;
+ did_throw = false;
did_emsg = false;
try_start();
@@ -1093,7 +1093,7 @@ static int nlua_rpc(lua_State *lstate, bool request)
Object result = rpc_send_call(chan_id, name, args, &res_mem, &err);
if (!ERROR_SET(&err)) {
nlua_push_Object(lstate, result, false);
- arena_mem_free(res_mem, NULL);
+ arena_mem_free(res_mem);
}
} else {
if (!rpc_send_event(chan_id, name, args)) {
@@ -1578,7 +1578,7 @@ void ex_luado(exarg_T *const eap)
}
lua_pop(lstate, 1);
check_cursor();
- update_screen(NOT_VALID);
+ update_screen(UPD_NOT_VALID);
}
/// Run lua file
@@ -1662,6 +1662,9 @@ static void nlua_add_treesitter(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
lua_pushcfunction(lstate, tslua_has_language);
lua_setfield(lstate, -2, "_ts_has_language");
+ lua_pushcfunction(lstate, tslua_remove_lang);
+ lua_setfield(lstate, -2, "_ts_remove_language");
+
lua_pushcfunction(lstate, tslua_inspect_lang);
lua_setfield(lstate, -2, "_ts_inspect_language");
diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c
index 5a82ae30b5..1b874e673a 100644
--- a/src/nvim/lua/stdlib.c
+++ b/src/nvim/lua/stdlib.c
@@ -474,6 +474,52 @@ static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
return 1;
}
+#if defined(HAVE_ICONV)
+
+/// Convert string from one encoding to another
+static int nlua_iconv(lua_State *lstate)
+{
+ int narg = lua_gettop(lstate);
+
+ if (narg < 3) {
+ return luaL_error(lstate, "Expected at least 3 arguments");
+ }
+
+ for (int i = 1; i <= 3; i++) {
+ if (lua_type(lstate, i) != LUA_TSTRING) {
+ return luaL_argerror(lstate, i, "expected string");
+ }
+ }
+
+ size_t str_len = 0;
+ const char *str = lua_tolstring(lstate, 1, &str_len);
+
+ char_u *from = (char_u *)enc_canonize(enc_skip((char *)lua_tolstring(lstate, 2, NULL)));
+ char_u *to = (char_u *)enc_canonize(enc_skip((char *)lua_tolstring(lstate, 3, NULL)));
+
+ vimconv_T vimconv;
+ vimconv.vc_type = CONV_NONE;
+ convert_setup_ext(&vimconv, from, false, to, false);
+
+ char_u *ret = (char_u *)string_convert(&vimconv, (char *)str, &str_len);
+
+ convert_setup(&vimconv, NULL, NULL);
+
+ xfree(from);
+ xfree(to);
+
+ if (ret == NULL) {
+ lua_pushnil(lstate);
+ } else {
+ lua_pushlstring(lstate, (char *)ret, str_len);
+ xfree(ret);
+ }
+
+ return 1;
+}
+
+#endif
+
void nlua_state_add_stdlib(lua_State *const lstate, bool is_thread)
{
if (!is_thread) {
@@ -519,6 +565,13 @@ void nlua_state_add_stdlib(lua_State *const lstate, bool is_thread)
// vim.spell
luaopen_spell(lstate);
lua_setfield(lstate, -2, "spell");
+
+#if defined(HAVE_ICONV)
+ // vim.iconv
+ // depends on p_ambw, p_emoji
+ lua_pushcfunction(lstate, &nlua_iconv);
+ lua_setfield(lstate, -2, "iconv");
+#endif
}
// vim.mpack
diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c
index f0d847e352..7ff4fbbff4 100644
--- a/src/nvim/lua/treesitter.c
+++ b/src/nvim/lua/treesitter.c
@@ -14,11 +14,14 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <uv.h>
#include "nvim/api/private/helpers.h"
#include "nvim/buffer.h"
#include "nvim/lib/kvec.h"
+#include "nvim/log.h"
#include "nvim/lua/treesitter.h"
+#include "nvim/map.h"
#include "nvim/memline.h"
#include "tree_sitter/api.h"
@@ -85,6 +88,10 @@ static struct luaL_Reg node_meta[] = {
{ "prev_sibling", node_prev_sibling },
{ "next_named_sibling", node_next_named_sibling },
{ "prev_named_sibling", node_prev_named_sibling },
+ { "named_children", node_named_children },
+ { "root", node_root },
+ { "byte_length", node_byte_length },
+
{ NULL, NULL }
};
@@ -145,18 +152,27 @@ int tslua_has_language(lua_State *L)
return 1;
}
+// Creates the language into the internal language map.
+//
+// Returns true if the language is correctly loaded in the language map
int tslua_add_language(lua_State *L)
{
const char *path = luaL_checkstring(L, 1);
const char *lang_name = luaL_checkstring(L, 2);
+ const char *symbol_name = lang_name;
+
+ if (lua_gettop(L) >= 3 && !lua_isnil(L, 3)) {
+ symbol_name = luaL_checkstring(L, 3);
+ }
if (pmap_has(cstr_t)(&langs, lang_name)) {
- return 0;
+ lua_pushboolean(L, true);
+ return 1;
}
#define BUFSIZE 128
char symbol_buf[BUFSIZE];
- snprintf(symbol_buf, BUFSIZE, "tree_sitter_%s", lang_name);
+ snprintf(symbol_buf, BUFSIZE, "tree_sitter_%s", symbol_name);
#undef BUFSIZE
uv_lib_t lib;
@@ -179,6 +195,7 @@ int tslua_add_language(lua_State *L)
TSLanguage *lang = lang_parser();
if (lang == NULL) {
+ uv_dlclose(&lib);
return luaL_error(L, "Failed to load parser %s: internal error", path);
}
@@ -198,6 +215,19 @@ int tslua_add_language(lua_State *L)
return 1;
}
+int tslua_remove_lang(lua_State *L)
+{
+ const char *lang_name = luaL_checkstring(L, 1);
+ bool present = pmap_has(cstr_t)(&langs, lang_name);
+ if (present) {
+ char *key = (char *)pmap_key(cstr_t)(&langs, lang_name);
+ pmap_del(cstr_t)(&langs, lang_name);
+ xfree(key);
+ }
+ lua_pushboolean(L, present);
+ return 1;
+}
+
int tslua_inspect_lang(lua_State *L)
{
const char *lang_name = luaL_checkstring(L, 1);
@@ -593,7 +623,7 @@ void push_tree(lua_State *L, TSTree *tree, bool do_copy)
lua_setfenv(L, -2); // [udata]
}
-static TSTree **tree_check(lua_State *L, uint16_t index)
+static TSTree **tree_check(lua_State *L, int index)
{
TSTree **ud = luaL_checkudata(L, index, TS_META_TREE);
return ud;
@@ -1036,6 +1066,57 @@ static int node_prev_named_sibling(lua_State *L)
return 1;
}
+static int node_named_children(lua_State *L)
+{
+ TSNode source;
+ if (!node_check(L, 1, &source)) {
+ return 0;
+ }
+ TSTreeCursor cursor = ts_tree_cursor_new(source);
+
+ lua_newtable(L);
+ int curr_index = 0;
+
+ if (ts_tree_cursor_goto_first_child(&cursor)) {
+ do {
+ TSNode node = ts_tree_cursor_current_node(&cursor);
+ if (ts_node_is_named(node)) {
+ push_node(L, node, 1);
+ lua_rawseti(L, -2, ++curr_index);
+ }
+ } while (ts_tree_cursor_goto_next_sibling(&cursor));
+ }
+
+ ts_tree_cursor_delete(&cursor);
+ return 1;
+}
+
+static int node_root(lua_State *L)
+{
+ TSNode node;
+ if (!node_check(L, 1, &node)) {
+ return 0;
+ }
+
+ TSNode root = ts_tree_root_node(node.tree);
+ push_node(L, root, 1);
+ return 1;
+}
+
+static int node_byte_length(lua_State *L)
+{
+ TSNode node;
+ if (!node_check(L, 1, &node)) {
+ return 0;
+ }
+
+ uint32_t start_byte = ts_node_start_byte(node);
+ uint32_t end_byte = ts_node_end_byte(node);
+
+ lua_pushnumber(L, end_byte - start_byte);
+ return 1;
+}
+
/// assumes the match table being on top of the stack
static void set_match(lua_State *L, TSQueryMatch *match, int nodeidx)
{
diff --git a/src/nvim/macros.h b/src/nvim/macros.h
index a896a406d1..5601db274b 100644
--- a/src/nvim/macros.h
+++ b/src/nvim/macros.h
@@ -31,7 +31,7 @@
/// @return `s, sizeof(s) - 1`
#define S_LEN(s) (s), (sizeof(s) - 1)
-/// LINEEMPTY() - return TRUE if the line is empty
+/// LINEEMPTY() - return true if the line is empty
#define LINEEMPTY(p) (*ml_get(p) == NUL)
// toupper() and tolower() that use the current locale.
diff --git a/src/nvim/main.c b/src/nvim/main.c
index d06b475934..883f946cad 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -25,23 +25,19 @@
#include "nvim/ex_getln.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
+#include "nvim/garray.h"
+#include "nvim/grid.h"
#include "nvim/hashtab.h"
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
#include "nvim/iconv.h"
#include "nvim/if_cscope.h"
#include "nvim/insexpand.h"
+#include "nvim/locale.h"
+#include "nvim/log.h"
#include "nvim/lua/executor.h"
#include "nvim/main.h"
#include "nvim/mapping.h"
-#include "nvim/ui_client.h"
-#include "nvim/vim.h"
-#ifdef HAVE_LOCALE_H
-# include <locale.h>
-#endif
-#include "nvim/garray.h"
-#include "nvim/grid.h"
-#include "nvim/log.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
@@ -70,8 +66,10 @@
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/ui.h"
+#include "nvim/ui_client.h"
#include "nvim/ui_compositor.h"
#include "nvim/version.h"
+#include "nvim/vim.h"
#include "nvim/window.h"
#ifdef WIN32
# include "nvim/os/os_win_console.h"
@@ -479,7 +477,7 @@ int main(int argc, char **argv)
if (exmode_active || use_remote_ui || use_builtin_ui) {
// Don't clear the screen when starting in Ex mode, or when a UI might have
// displayed messages.
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
} else {
screenclear(); // clear screen
TIME_MSG("clearing screen");
@@ -508,7 +506,7 @@ int main(int argc, char **argv)
// When started with "-q errorfile" jump to first error now.
if (params.edit_type == EDIT_QF) {
- qf_jump(NULL, 0, 0, FALSE);
+ qf_jump(NULL, 0, 0, false);
TIME_MSG("jump to first error");
}
@@ -520,7 +518,7 @@ int main(int argc, char **argv)
if (params.diff_mode) {
// set options in each window for "nvim -d".
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- diff_win_options(wp, TRUE);
+ diff_win_options(wp, true);
}
}
@@ -539,7 +537,7 @@ int main(int argc, char **argv)
starting = 0;
RedrawingDisabled = 0;
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
no_wait_return = false;
// 'autochdir' has been postponed.
@@ -713,8 +711,8 @@ void getout(int exitval)
if (did_emsg) {
// give the user a chance to read the (error) message
- no_wait_return = FALSE;
- wait_return(FALSE);
+ no_wait_return = false;
+ wait_return(false);
}
// Position the cursor again, the autocommands may have moved it
@@ -801,30 +799,6 @@ static int get_number_arg(const char *p, int *idx, int def)
return def;
}
-#if defined(HAVE_LOCALE_H)
-/// Setup to use the current locale (for ctype() and many other things).
-static void init_locale(void)
-{
- setlocale(LC_ALL, "");
-
-# ifdef LC_NUMERIC
- // Make sure strtod() uses a decimal point, not a comma.
- setlocale(LC_NUMERIC, "C");
-# endif
-
- char localepath[MAXPATHL] = { 0 };
- snprintf(localepath, sizeof(localepath), "%s", get_vim_var_str(VV_PROGPATH));
- char *tail = path_tail_with_sep(localepath);
- *tail = NUL;
- tail = path_tail(localepath);
- xstrlcpy(tail, "share/locale",
- sizeof(localepath) - (size_t)(tail - localepath));
- bindtextdomain(PROJECT_NAME, localepath);
- textdomain(PROJECT_NAME);
- TIME_MSG("locale set");
-}
-#endif
-
static uint64_t server_connect(char *server_addr, const char **errmsg)
{
if (server_addr == NULL) {
@@ -1052,7 +1026,7 @@ static void command_line_scan(mparm_T *parmp)
} else if (STRNICMP(argv[0] + argv_idx, "clean", 5) == 0) {
parmp->use_vimrc = "NONE";
parmp->clean = true;
- set_option_value("shadafile", 0L, "NONE", 0);
+ set_option_value_give_err("shadafile", 0L, "NONE", 0);
} else if (STRNICMP(argv[0] + argv_idx, "luamod-dev", 9) == 0) {
nlua_disable_preload = true;
} else {
@@ -1066,7 +1040,7 @@ static void command_line_scan(mparm_T *parmp)
}
break;
case 'A': // "-A" start in Arabic mode.
- set_option_value("arabic", 1L, NULL, 0);
+ set_option_value_give_err("arabic", 1L, NULL, 0);
break;
case 'b': // "-b" binary mode.
// Needs to be effective before expanding file names, because
@@ -1097,10 +1071,10 @@ static void command_line_scan(mparm_T *parmp)
os_exit(0);
case 'H': // "-H" start in Hebrew mode: rl + hkmap set.
p_hkmap = true;
- set_option_value("rl", 1L, NULL, 0);
+ set_option_value_give_err("rl", 1L, NULL, 0);
break;
case 'l': // "-l" lisp mode, 'lisp' and 'showmatch' on.
- set_option_value("lisp", 1L, NULL, 0);
+ set_option_value_give_err("lisp", 1L, NULL, 0);
p_sm = true;
break;
case 'M': // "-M" no changes or writing of files
@@ -1181,7 +1155,7 @@ static void command_line_scan(mparm_T *parmp)
// default is 10: a little bit verbose
p_verbose = get_number_arg(argv[0], &argv_idx, 10);
if (argv[0][argv_idx] != NUL) {
- set_option_value("verbosefile", 0L, argv[0] + argv_idx, 0);
+ set_option_value_give_err("verbosefile", 0L, argv[0] + argv_idx, 0);
argv_idx = (int)STRLEN(argv[0]);
}
break;
@@ -1189,7 +1163,7 @@ static void command_line_scan(mparm_T *parmp)
// "-w {scriptout}" write to script
if (ascii_isdigit(((char_u *)argv[0])[argv_idx])) {
n = get_number_arg(argv[0], &argv_idx, 10);
- set_option_value("window", n, NULL, 0);
+ set_option_value_give_err("window", n, NULL, 0);
break;
}
want_argument = true;
@@ -1284,7 +1258,7 @@ static void command_line_scan(mparm_T *parmp)
break;
case 'i': // "-i {shada}" use for shada
- set_option_value("shadafile", 0L, argv[0], 0);
+ set_option_value_give_err("shadafile", 0L, argv[0], 0);
break;
case 's': { // "-s {scriptin}" read from script file
@@ -1334,7 +1308,7 @@ scripterror:
if (ascii_isdigit(*((char_u *)argv[0]))) {
argv_idx = 0;
n = get_number_arg(argv[0], &argv_idx, 10);
- set_option_value("window", n, NULL, 0);
+ set_option_value_give_err("window", n, NULL, 0);
argv_idx = -1;
break;
}
@@ -1368,8 +1342,8 @@ scripterror:
ga_grow(&global_alist.al_ga, 1);
char *p = xstrdup(argv[0]);
- if (parmp->diff_mode && os_isdir((char_u *)p) && GARGCOUNT > 0
- && !os_isdir((char_u *)alist_name(&GARGLIST[0]))) {
+ if (parmp->diff_mode && os_isdir(p) && GARGCOUNT > 0
+ && !os_isdir(alist_name(&GARGLIST[0]))) {
char *r = concat_fnames(p, path_tail(alist_name(&GARGLIST[0])), true);
xfree(p);
p = r;
@@ -1516,7 +1490,7 @@ static void handle_quickfix(mparm_T *paramp)
set_string_option_direct("ef", -1, paramp->use_ef, OPT_FREE, SID_CARG);
}
vim_snprintf((char *)IObuff, IOSIZE, "cfile %s", p_ef);
- if (qf_init(NULL, (char *)p_ef, p_efm, true, (char *)IObuff, (char *)p_menc) < 0) {
+ if (qf_init(NULL, (char *)p_ef, p_efm, true, (char *)IObuff, p_menc) < 0) {
msg_putchar('\n');
os_exit(3);
}
@@ -1638,7 +1612,7 @@ static void create_windows(mparm_T *parmp)
}
curwin = curwin->w_next;
}
- dorewind = FALSE;
+ dorewind = false;
curbuf = curwin->w_buffer;
if (curbuf->b_ml.ml_mfp == NULL) {
// Set 'foldlevel' to 'foldlevelstart' if it's not negative..
@@ -1647,15 +1621,15 @@ static void create_windows(mparm_T *parmp)
}
// When getting the ATTENTION prompt here, use a dialog.
swap_exists_action = SEA_DIALOG;
- set_buflisted(TRUE);
+ set_buflisted(true);
// create memfile, read file
- (void)open_buffer(FALSE, NULL, 0);
+ (void)open_buffer(false, NULL, 0);
if (swap_exists_action == SEA_QUIT) {
if (got_int || only_one_window()) {
// abort selected or quit and only one window
- did_emsg = FALSE; // avoid hit-enter prompt
+ did_emsg = false; // avoid hit-enter prompt
getout(1);
}
// We can't close the window, it would disturb what
@@ -1667,7 +1641,7 @@ static void create_windows(mparm_T *parmp)
} else {
handle_swap_exists(NULL);
}
- dorewind = TRUE; // start again
+ dorewind = true; // start again
}
os_breakcheck();
if (got_int) {
@@ -1709,7 +1683,7 @@ static void edit_buffers(mparm_T *parmp, char_u *cwd)
}
arg_idx = 1;
- for (i = 1; i < parmp->window_count; ++i) {
+ for (i = 1; i < parmp->window_count; i++) {
if (cwd != NULL) {
os_chdir((char *)cwd);
}
@@ -1733,9 +1707,9 @@ static void edit_buffers(mparm_T *parmp, char_u *cwd)
if (i == 1) {
char buf[100];
- p_shm_save = xstrdup((char *)p_shm);
+ p_shm_save = xstrdup(p_shm);
snprintf(buf, sizeof(buf), "F%s", p_shm);
- set_option_value("shm", 0L, buf, 0);
+ set_option_value_give_err("shm", 0L, buf, 0);
}
} else {
if (curwin->w_next == NULL) { // just checking
@@ -1760,7 +1734,7 @@ static void edit_buffers(mparm_T *parmp, char_u *cwd)
// abort or quit selected
if (got_int || only_one_window()) {
// abort selected and only one window
- did_emsg = FALSE; // avoid hit-enter prompt
+ did_emsg = false; // avoid hit-enter prompt
getout(1);
}
win_close(curwin, true, false);
@@ -1779,7 +1753,7 @@ static void edit_buffers(mparm_T *parmp, char_u *cwd)
}
if (p_shm_save != NULL) {
- set_option_value("shm", 0L, p_shm_save, 0);
+ set_option_value_give_err("shm", 0L, p_shm_save, 0);
xfree(p_shm_save);
}
@@ -1841,7 +1815,7 @@ static void exe_commands(mparm_T *parmp)
* pattern on line 1. But don't move the cursor when an autocommand
* with g`" was used.
*/
- msg_scroll = TRUE;
+ msg_scroll = true;
if (parmp->tagname == NULL && curwin->w_cursor.lnum <= 1) {
curwin->w_cursor.lnum = 0;
}
@@ -1861,12 +1835,12 @@ static void exe_commands(mparm_T *parmp)
}
if (!exmode_active) {
- msg_scroll = FALSE;
+ msg_scroll = false;
}
// When started with "-q errorfile" jump to first error again.
if (parmp->edit_type == EDIT_QF) {
- qf_jump(NULL, 0, 0, FALSE);
+ qf_jump(NULL, 0, 0, false);
}
TIME_MSG("executing command arguments");
}
diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c
index 64a798a27b..333fb847f6 100644
--- a/src/nvim/mapping.c
+++ b/src/nvim/mapping.c
@@ -150,8 +150,8 @@ static void showmap(mapblock_T *mp, bool local)
{
size_t len = 1;
- if (message_filtered(mp->m_keys) && message_filtered(mp->m_str)
- && (mp->m_desc == NULL || message_filtered((char_u *)mp->m_desc))) {
+ if (message_filtered((char *)mp->m_keys) && message_filtered(mp->m_str)
+ && (mp->m_desc == NULL || message_filtered(mp->m_desc))) {
return;
}
@@ -203,7 +203,7 @@ static void showmap(mapblock_T *mp, bool local)
} else if (mp->m_str[0] == NUL) {
msg_puts_attr("<Nop>", HL_ATTR(HLF_8));
} else {
- msg_outtrans_special(mp->m_str, false, 0);
+ msg_outtrans_special((char_u *)mp->m_str, false, 0);
}
if (mp->m_desc != NULL) {
@@ -293,7 +293,7 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs
replaced = replace_termcodes(orig_rhs, orig_rhs_len, &rhs_buf, REPTERM_DO_LT, NULL,
cpo_flags);
mapargs->rhs_len = STRLEN(replaced);
- // XXX: replace_termcodes may produce an empty string even if orig_rhs is non-empty
+ // NB: replace_termcodes may produce an empty string even if orig_rhs is non-empty
// (e.g. a single ^V, see :h map-empty-rhs)
mapargs->rhs_is_noop = orig_rhs_len != 0 && mapargs->rhs_len == 0;
mapargs->rhs = (char_u *)replaced;
@@ -449,8 +449,8 @@ static void map_add(buf_T *buf, mapblock_T **map_table, mapblock_T **abbr_table,
}
mp->m_keys = vim_strsave(keys);
- mp->m_str = args->rhs;
- mp->m_orig_str = args->orig_rhs;
+ mp->m_str = (char *)args->rhs;
+ mp->m_orig_str = (char *)args->orig_rhs;
mp->m_luaref = args->rhs_lua;
if (!simplified) {
args->rhs = NULL;
@@ -704,7 +704,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
} else { // do we have a match?
if (round) { // second round: Try unmap "rhs" string
n = (int)STRLEN(mp->m_str);
- p = mp->m_str;
+ p = (char_u *)mp->m_str;
} else {
n = mp->m_keylen;
p = mp->m_keys;
@@ -761,8 +761,8 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
XFREE_CLEAR(mp->m_str);
XFREE_CLEAR(mp->m_orig_str);
}
- mp->m_str = args->rhs;
- mp->m_orig_str = args->orig_rhs;
+ mp->m_str = (char *)args->rhs;
+ mp->m_orig_str = (char *)args->orig_rhs;
mp->m_luaref = args->rhs_lua;
if (!keyround1_simplified) {
args->rhs = NULL;
@@ -1113,7 +1113,7 @@ int map_to_exists_mode(const char *const rhs, const int mode, const bool abbr)
mp = maphash[hash];
}
for (; mp; mp = mp->m_next) {
- if ((mp->m_mode & mode) && strstr((char *)mp->m_str, rhs) != NULL) {
+ if ((mp->m_mode & mode) && strstr(mp->m_str, rhs) != NULL) {
return true;
}
}
@@ -1506,7 +1506,7 @@ bool check_abbr(int c, char_u *ptr, int col, int mincol)
if (mp->m_expr) {
s = eval_map_expr(mp, c);
} else {
- s = mp->m_str;
+ s = (char_u *)mp->m_str;
}
if (s != NULL) {
// insert the to string
@@ -1542,7 +1542,7 @@ char_u *eval_map_expr(mapblock_T *mp, int c)
// Remove escaping of K_SPECIAL, because "str" is in a format to be used as
// typeahead.
if (mp->m_luaref == LUA_NOREF) {
- expr = vim_strsave(mp->m_str);
+ expr = vim_strsave((char_u *)mp->m_str);
vim_unescape_ks(expr);
}
@@ -1639,7 +1639,7 @@ int makemap(FILE *fd, buf_T *buf)
if (mp->m_luaref != LUA_NOREF) {
continue;
}
- for (p = mp->m_str; *p != NUL; p++) {
+ for (p = (char_u *)mp->m_str; *p != NUL; p++) {
if (p[0] == K_SPECIAL && p[1] == KS_EXTRA
&& p[2] == KE_SNR) {
break;
@@ -1785,7 +1785,7 @@ int makemap(FILE *fd, buf_T *buf)
if (putc(' ', fd) < 0
|| put_escstr(fd, mp->m_keys, 0) == FAIL
|| putc(' ', fd) < 0
- || put_escstr(fd, mp->m_str, 1) == FAIL
+ || put_escstr(fd, (char_u *)mp->m_str, 1) == FAIL
|| put_eol(fd) < 0) {
return FAIL;
}
@@ -1956,7 +1956,7 @@ char_u *check_map(char_u *keys, int mode, int exact, int ign_mod, int abbr, mapb
*local_ptr = local;
}
*rhs_lua = mp->m_luaref;
- return mp->m_luaref == LUA_NOREF ? mp->m_str : NULL;
+ return mp->m_luaref == LUA_NOREF ? (char_u *)mp->m_str : NULL;
}
}
}
@@ -1967,7 +1967,7 @@ char_u *check_map(char_u *keys, int mode, int exact, int ign_mod, int abbr, mapb
}
/// "hasmapto()" function
-void f_hasmapto(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_hasmapto(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *mode;
const char *const name = tv_get_string(&argvars[0]);
@@ -2127,7 +2127,7 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
}
/// "mapset()" function
-void f_mapset(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_mapset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char buf[NUMBUFLEN];
const char *which = tv_get_string_buf_chk(&argvars[0], buf);
@@ -2195,13 +2195,13 @@ void f_mapset(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "maparg()" function
-void f_maparg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_maparg(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
get_maparg(argvars, rettv, true);
}
/// "mapcheck()" function
-void f_mapcheck(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_mapcheck(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
get_maparg(argvars, rettv, false);
}
@@ -2322,7 +2322,7 @@ void langmap_set(void)
ga_clear(&langmap_mapga); // clear the previous map first
langmap_init(); // back to one-to-one map
- for (p = p_langmap; p[0] != NUL;) {
+ for (p = (char_u *)p_langmap; p[0] != NUL;) {
for (p2 = p; p2[0] != NUL && p2[0] != ',' && p2[0] != ';';
MB_PTR_ADV(p2)) {
if (p2[0] == '\\' && p2[1] != NUL) {
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 593275d489..9df4d416ff 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -33,9 +33,9 @@
#include "nvim/os/time.h"
#include "nvim/path.h"
#include "nvim/quickfix.h"
-#include "nvim/search.h"
#include "nvim/sign.h"
#include "nvim/strings.h"
+#include "nvim/textobject.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
@@ -674,7 +674,7 @@ static void fname2fnum(xfmark_T *fm)
)) {
int len;
- expand_env((char_u *)"~/", NameBuff, MAXPATHL);
+ expand_env("~/", NameBuff, MAXPATHL);
len = (int)STRLEN(NameBuff);
STRLCPY(NameBuff + len, fm->fname + 2, MAXPATHL - len);
} else {
@@ -683,7 +683,7 @@ static void fname2fnum(xfmark_T *fm)
// Try to shorten the file name.
os_dirname(IObuff, IOSIZE);
- p = path_shorten_fname(NameBuff, IObuff);
+ p = path_shorten_fname((char_u *)NameBuff, IObuff);
// buflist_new() will call fmarks_check_names()
(void)buflist_new((char *)NameBuff, (char *)p, (linenr_T)1, 0);
@@ -704,12 +704,12 @@ void fmarks_check_names(buf_T *buf)
return;
}
- for (i = 0; i < NGLOBALMARKS; ++i) {
+ for (i = 0; i < NGLOBALMARKS; i++) {
fmarks_check_one(&namedfm[i], name, buf);
}
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- for (i = 0; i < wp->w_jumplistlen; ++i) {
+ for (i = 0; i < wp->w_jumplistlen; i++) {
fmarks_check_one(&wp->w_jumplist[i], name, buf);
}
}
@@ -848,10 +848,10 @@ void ex_marks(exarg_T *eap)
}
show_one_mark('\'', arg, &curwin->w_pcmark, NULL, true);
- for (i = 0; i < NMARKS; ++i) {
+ for (i = 0; i < NMARKS; i++) {
show_one_mark(i + 'a', arg, &curbuf->b_namedm[i].mark, NULL, true);
}
- for (i = 0; i < NGLOBALMARKS; ++i) {
+ for (i = 0; i < NGLOBALMARKS; i++) {
if (namedfm[i].fmark.fnum != 0) {
name = fm_getname(&namedfm[i].fmark, 15);
} else {
@@ -911,7 +911,7 @@ static void show_one_mark(int c, char_u *arg, pos_T *p, char_u *name_arg, int cu
name = mark_line(p, 15);
mustfree = true;
}
- if (!message_filtered(name)) {
+ if (!message_filtered((char *)name)) {
if (!did_title) {
// Highlight title
msg_puts_title(_("\nmark line col file/text"));
@@ -922,7 +922,7 @@ static void show_one_mark(int c, char_u *arg, pos_T *p, char_u *name_arg, int cu
snprintf((char *)IObuff, IOSIZE, " %c %6" PRIdLINENR " %4d ", c, p->lnum, p->col);
msg_outtrans((char *)IObuff);
if (name != NULL) {
- msg_outtrans_attr(name, current ? HL_ATTR(HLF_D) : 0);
+ msg_outtrans_attr((char *)name, current ? HL_ATTR(HLF_D) : 0);
}
}
ui_flush(); // show one line at a time
@@ -975,7 +975,7 @@ void ex_delmarks(exarg_T *eap)
from = to = *p;
}
- for (i = from; i <= to; ++i) {
+ for (i = from; i <= to; i++) {
if (lower) {
curbuf->b_namedm[i - 'a'].mark.lnum = 0;
} else {
@@ -1027,7 +1027,7 @@ void ex_jumps(exarg_T *eap)
cleanup_jumplist(curwin, true);
// Highlight title
msg_puts_title(_("\n jump line col file/text"));
- for (i = 0; i < curwin->w_jumplistlen && !got_int; ++i) {
+ for (i = 0; i < curwin->w_jumplistlen && !got_int; i++) {
if (curwin->w_jumplist[i].fmark.mark.lnum != 0) {
name = fm_getname(&curwin->w_jumplist[i].fmark, 16);
@@ -1037,7 +1037,7 @@ void ex_jumps(exarg_T *eap)
name = vim_strsave((char_u *)"-invalid-");
}
// apply :filter /pat/ or file name not available
- if (name == NULL || message_filtered(name)) {
+ if (name == NULL || message_filtered((char *)name)) {
xfree(name);
continue;
}
@@ -1052,7 +1052,7 @@ void ex_jumps(exarg_T *eap)
i > curwin->w_jumplistidx ? i - curwin->w_jumplistidx : curwin->w_jumplistidx - i,
curwin->w_jumplist[i].fmark.mark.lnum, curwin->w_jumplist[i].fmark.mark.col);
msg_outtrans((char *)IObuff);
- msg_outtrans_attr(name,
+ msg_outtrans_attr((char *)name,
curwin->w_jumplist[i].fmark.fnum == curbuf->b_fnum
? HL_ATTR(HLF_D) : 0);
xfree(name);
@@ -1083,7 +1083,7 @@ void ex_changes(exarg_T *eap)
// Highlight title
msg_puts_title(_("\nchange line col text"));
- for (i = 0; i < curbuf->b_changelistlen && !got_int; ++i) {
+ for (i = 0; i < curbuf->b_changelistlen && !got_int; i++) {
if (curbuf->b_changelist[i].mark.lnum != 0) {
msg_putchar('\n');
if (got_int) {
@@ -1097,7 +1097,7 @@ void ex_changes(exarg_T *eap)
curbuf->b_changelist[i].mark.col);
msg_outtrans((char *)IObuff);
name = mark_line(&curbuf->b_changelist[i].mark, 17);
- msg_outtrans_attr(name, HL_ATTR(HLF_D));
+ msg_outtrans_attr((char *)name, HL_ATTR(HLF_D));
xfree(name);
os_breakcheck();
}
@@ -1391,7 +1391,7 @@ void mark_col_adjust(linenr_T lnum, colnr_T mincol, linenr_T lnum_amount, long c
*/
FOR_ALL_WINDOWS_IN_TAB(win, curtab) {
// marks in the jumplist
- for (i = 0; i < win->w_jumplistlen; ++i) {
+ for (i = 0; i < win->w_jumplistlen; i++) {
if (win->w_jumplist[i].fmark.fnum == fnum) {
COL_ADJUST(&(win->w_jumplist[i].fmark.mark));
}
@@ -1493,7 +1493,7 @@ void copy_jumplist(win_T *from, win_T *to)
{
int i;
- for (i = 0; i < from->w_jumplistlen; ++i) {
+ for (i = 0; i < from->w_jumplistlen; i++) {
to->w_jumplist[i] = from->w_jumplist[i];
if (from->w_jumplist[i].fname != NULL) {
to->w_jumplist[i].fname = xstrdup(from->w_jumplist[i].fname);
@@ -1717,7 +1717,7 @@ void free_jumplist(win_T *wp)
{
int i;
- for (i = 0; i < wp->w_jumplistlen; ++i) {
+ for (i = 0; i < wp->w_jumplistlen; i++) {
free_xfmark(wp->w_jumplist[i]);
}
wp->w_jumplistlen = 0;
diff --git a/src/nvim/match.c b/src/nvim/match.c
index 1c34c9f004..48f0d0fc05 100644
--- a/src/nvim/match.c
+++ b/src/nvim/match.c
@@ -47,7 +47,7 @@ static int match_add(win_T *wp, const char *const grp, const char *const pat, in
matchitem_T *m;
int hlg_id;
regprog_T *regprog = NULL;
- int rtype = SOME_VALID;
+ int rtype = UPD_SOME_VALID;
if (*grp == NUL || (pat != NULL && *pat == NUL)) {
return -1;
@@ -193,7 +193,7 @@ static int match_add(win_T *wp, const char *const grp, const char *const pat, in
}
m->pos.toplnum = toplnum;
m->pos.botlnum = botlnum;
- rtype = VALID;
+ rtype = UPD_VALID;
}
}
@@ -227,7 +227,7 @@ static int match_delete(win_T *wp, int id, bool perr)
{
matchitem_T *cur = wp->w_match_head;
matchitem_T *prev = cur;
- int rtype = SOME_VALID;
+ int rtype = UPD_SOME_VALID;
if (id < 1) {
if (perr) {
@@ -268,7 +268,7 @@ static int match_delete(win_T *wp, int id, bool perr)
wp->w_buffer->b_mod_bot = cur->pos.botlnum;
wp->w_buffer->b_mod_xlines = 0;
}
- rtype = VALID;
+ rtype = UPD_VALID;
}
xfree(cur);
redraw_later(wp, rtype);
@@ -287,7 +287,7 @@ void clear_matches(win_T *wp)
xfree(wp->w_match_head);
wp->w_match_head = m;
}
- redraw_later(wp, SOME_VALID);
+ redraw_later(wp, UPD_SOME_VALID);
}
/// Get match from ID 'id' in window 'wp'.
@@ -859,7 +859,7 @@ static int matchadd_dict_arg(typval_T *tv, const char **conceal_char, win_T **wi
}
/// "clearmatches()" function
-void f_clearmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_clearmatches(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
win_T *win = get_optional_window(argvars, 0);
@@ -869,7 +869,7 @@ void f_clearmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getmatches()" function
-void f_getmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_getmatches(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
matchitem_T *cur;
int i;
@@ -924,7 +924,7 @@ void f_getmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "setmatches()" function
-void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_setmatches(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
dict_T *d;
list_T *s = NULL;
@@ -1027,7 +1027,7 @@ void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "matchadd()" function
-void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_matchadd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char grpbuf[NUMBUFLEN];
char patbuf[NUMBUFLEN];
@@ -1069,7 +1069,7 @@ void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "matchaddpo()" function
-void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_matchaddpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = -1;
@@ -1120,7 +1120,7 @@ void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "matcharg()" function
-void f_matcharg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_matcharg(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const int id = (int)tv_get_number(&argvars[0]);
@@ -1143,7 +1143,7 @@ void f_matcharg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "matchdelete()" function
-void f_matchdelete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_matchdelete(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
win_T *win = get_optional_window(argvars, 1);
if (win == NULL) {
@@ -1183,7 +1183,7 @@ void ex_match(exarg_T *eap)
&& (ascii_iswhite(eap->arg[4]) || ends_excmd(eap->arg[4])))) {
end = (char_u *)eap->arg + 4;
} else {
- p = skiptowhite((char_u *)eap->arg);
+ p = (char_u *)skiptowhite(eap->arg);
if (!eap->skip) {
g = vim_strnsave((char_u *)eap->arg, (size_t)(p - (char_u *)eap->arg));
}
@@ -1194,7 +1194,7 @@ void ex_match(exarg_T *eap)
semsg(_(e_invarg2), eap->arg);
return;
}
- end = skip_regexp(p + 1, *p, true, NULL);
+ end = (char_u *)skip_regexp((char *)p + 1, *p, true, NULL);
if (!eap->skip) {
if (*end != NUL && !ends_excmd(*skipwhite((char *)end + 1))) {
xfree(g);
@@ -1215,5 +1215,5 @@ void ex_match(exarg_T *eap)
*end = (char_u)c;
}
}
- eap->nextcmd = (char *)find_nextcmd(end);
+ eap->nextcmd = find_nextcmd((char *)end);
}
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index af9e214d92..b874f0dc94 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -754,21 +754,19 @@ bool utf_composinglike(const char_u *p1, const char_u *p2)
/// space at least for #MAX_MCO + 1 elements.
///
/// @return leading character.
-int utfc_ptr2char(const char_u *p, int *pcc)
+int utfc_ptr2char(const char *p_in, int *pcc)
{
- int len;
- int c;
- int cc;
+ uint8_t *p = (uint8_t *)p_in;
int i = 0;
- c = utf_ptr2char((char *)p);
- len = utf_ptr2len((char *)p);
+ int c = utf_ptr2char((char *)p);
+ int len = utf_ptr2len((char *)p);
// Only accept a composing char when the first char isn't illegal.
if ((len > 1 || *p < 0x80)
&& p[len] >= 0x80
&& utf_composinglike(p, p + len)) {
- cc = utf_ptr2char((char *)p + len);
+ int cc = utf_ptr2char((char *)p + len);
for (;;) {
pcc[i++] = cc;
if (i == MAX_MCO) {
@@ -882,7 +880,7 @@ int utf_ptr2len_len(const char_u *p, int size)
} else {
m = len;
}
- for (i = 1; i < m; ++i) {
+ for (i = 1; i < m; i++) {
if ((p[i] & 0xc0) != 0x80) {
return 1;
}
@@ -1595,7 +1593,7 @@ void show_utf8(void)
}
clen = 0;
- for (i = 0; i < len; ++i) {
+ for (i = 0; i < len; i++) {
if (clen == 0) {
// start of (composing) character, get its length
if (i > 0) {
@@ -1632,10 +1630,10 @@ int utf_head_off(const char_u *base, const char_u *p)
// Skip backwards over trailing bytes: 10xx.xxxx
// Skip backwards again if on a composing char.
const char_u *q;
- for (q = p;; --q) {
+ for (q = p;; q--) {
// Move s to the last byte of this char.
const char_u *s;
- for (s = q; (s[1] & 0xc0) == 0x80; ++s) {}
+ for (s = q; (s[1] & 0xc0) == 0x80; s++) {}
// Move q to the first byte of this char.
while (q > base && (*q & 0xc0) == 0x80) {
@@ -1932,7 +1930,7 @@ void utf_find_illegal(void)
char_u *tofree = NULL;
vimconv.vc_type = CONV_NONE;
- if (enc_canon_props(curbuf->b_p_fenc) & ENC_8BIT) {
+ if (enc_canon_props((char_u *)curbuf->b_p_fenc) & ENC_8BIT) {
// 'encoding' is "utf-8" but we are editing a 8-bit encoded file,
// possibly a utf-8 file with illegal bytes. Setup for conversion
// from utf-8 to 'fileencoding'.
@@ -1944,7 +1942,7 @@ void utf_find_illegal(void)
p = get_cursor_pos_ptr();
if (vimconv.vc_type != CONV_NONE) {
xfree(tofree);
- tofree = string_convert(&vimconv, p, NULL);
+ tofree = (char_u *)string_convert(&vimconv, (char *)p, NULL);
if (tofree == NULL) {
break;
}
@@ -1975,7 +1973,7 @@ void utf_find_illegal(void)
if (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count) {
break;
}
- ++curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum++;
curwin->w_cursor.col = 0;
}
@@ -1989,8 +1987,7 @@ theend:
}
/// @return true if string "s" is a valid utf-8 string.
-/// When "end" is NULL stop at the first NUL.
-/// When "end" is positive stop there.
+/// When "end" is NULL stop at the first NUL. Otherwise stop at "end".
bool utf_valid_string(const char_u *s, const char_u *end)
{
const char_u *p = s;
@@ -2147,10 +2144,8 @@ const char *mb_unescape(const char **const pp)
return NULL;
}
-/*
- * Skip the Vim specific head of a 'encoding' name.
- */
-char_u *enc_skip(char_u *p)
+/// Skip the Vim specific head of a 'encoding' name.
+char *enc_skip(char *p)
{
if (STRNCMP(p, "2byte-", 6) == 0) {
return p + 6;
@@ -2161,27 +2156,25 @@ char_u *enc_skip(char_u *p)
return p;
}
-/*
- * Find the canonical name for encoding "enc".
- * When the name isn't recognized, returns "enc" itself, but with all lower
- * case characters and '_' replaced with '-'.
- * Returns an allocated string.
- */
-char_u *enc_canonize(char_u *enc) FUNC_ATTR_NONNULL_RET
+/// Find the canonical name for encoding "enc".
+/// When the name isn't recognized, returns "enc" itself, but with all lower
+/// case characters and '_' replaced with '-'.
+///
+/// @return an allocated string.
+char *enc_canonize(char *enc)
+ FUNC_ATTR_NONNULL_RET
{
char_u *p, *s;
- int i;
-
if (STRCMP(enc, "default") == 0) {
// Use the default encoding as found by set_init_1().
- return vim_strsave(fenc_default);
+ return (char *)vim_strsave(fenc_default);
}
// copy "enc" to allocated memory, with room for two '-'
char_u *r = xmalloc(STRLEN(enc) + 3);
// Make it all lower case and replace '_' with '-'.
p = r;
- for (s = enc; *s != NUL; ++s) {
+ for (s = (char_u *)enc; *s != NUL; s++) {
if (*s == '_') {
*p++ = '-';
} else {
@@ -2191,7 +2184,7 @@ char_u *enc_canonize(char_u *enc) FUNC_ATTR_NONNULL_RET
*p = NUL;
// Skip "2byte-" and "8bit-".
- p = enc_skip(r);
+ p = (char_u *)enc_skip((char *)r);
// Change "microsoft-cp" to "cp". Used in some spell files.
if (STRNCMP(p, "microsoft-cp", 12) == 0) {
@@ -2215,6 +2208,7 @@ char_u *enc_canonize(char_u *enc) FUNC_ATTR_NONNULL_RET
STRMOVE(p + 5, p + 6);
}
+ int i;
if (enc_canon_search(p) >= 0) {
// canonical name can be used unmodified
if (p != r) {
@@ -2225,7 +2219,7 @@ char_u *enc_canonize(char_u *enc) FUNC_ATTR_NONNULL_RET
xfree(r);
r = vim_strsave((char_u *)enc_canon_table[i].name);
}
- return r;
+ return (char *)r;
}
/// Search for an encoding alias of "name".
@@ -2234,7 +2228,7 @@ static int enc_alias_search(const char_u *name)
{
int i;
- for (i = 0; enc_alias_table[i].name != NULL; ++i) {
+ for (i = 0; enc_alias_table[i].name != NULL; i++) {
if (STRCMP(name, enc_alias_table[i].name) == 0) {
return enc_alias_table[i].canon;
}
@@ -2310,7 +2304,7 @@ enc_locale_copy_enc:
buf[i] = NUL;
}
- return enc_canonize((char_u *)buf);
+ return (char_u *)enc_canonize(buf);
}
#if defined(HAVE_ICONV)
@@ -2333,7 +2327,7 @@ void *my_iconv_open(char_u *to, char_u *from)
if (iconv_working == kBroken) {
return (void *)-1; // detected a broken iconv() previously
}
- fd = iconv_open((char *)enc_skip(to), (char *)enc_skip(from));
+ fd = iconv_open(enc_skip((char *)to), enc_skip((char *)from));
if (fd != (iconv_t)-1 && iconv_working == kUnknown) {
/*
@@ -2444,18 +2438,17 @@ static char_u *iconv_string(const vimconv_T *const vcp, char_u *str, size_t slen
#endif // HAVE_ICONV
-/*
- * Setup "vcp" for conversion from "from" to "to".
- * The names must have been made canonical with enc_canonize().
- * vcp->vc_type must have been initialized to CONV_NONE.
- * Note: cannot be used for conversion from/to ucs-2 and ucs-4 (will use utf-8
- * instead).
- * Afterwards invoke with "from" and "to" equal to NULL to cleanup.
- * Return FAIL when conversion is not supported, OK otherwise.
- */
-int convert_setup(vimconv_T *vcp, char_u *from, char_u *to)
+/// Setup "vcp" for conversion from "from" to "to".
+/// The names must have been made canonical with enc_canonize().
+/// vcp->vc_type must have been initialized to CONV_NONE.
+/// Note: cannot be used for conversion from/to ucs-2 and ucs-4 (will use utf-8
+/// instead).
+/// Afterwards invoke with "from" and "to" equal to NULL to cleanup.
+///
+/// @return FAIL when conversion is not supported, OK otherwise.
+int convert_setup(vimconv_T *vcp, char *from, char *to)
{
- return convert_setup_ext(vcp, from, true, to, true);
+ return convert_setup_ext(vcp, (char_u *)from, true, (char_u *)to, true);
}
/// As convert_setup(), but only when from_unicode_is_utf8 is true will all
@@ -2528,16 +2521,14 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8, c
return OK;
}
-/*
- * Convert text "ptr[*lenp]" according to "vcp".
- * Returns the result in allocated memory and sets "*lenp".
- * When "lenp" is NULL, use NUL terminated strings.
- * Illegal chars are often changed to "?", unless vcp->vc_fail is set.
- * When something goes wrong, NULL is returned and "*lenp" is unchanged.
- */
-char_u *string_convert(const vimconv_T *const vcp, char_u *ptr, size_t *lenp)
+/// Convert text "ptr[*lenp]" according to "vcp".
+/// Returns the result in allocated memory and sets "*lenp".
+/// When "lenp" is NULL, use NUL terminated strings.
+/// Illegal chars are often changed to "?", unless vcp->vc_fail is set.
+/// When something goes wrong, NULL is returned and "*lenp" is unchanged.
+char *string_convert(const vimconv_T *const vcp, char *ptr, size_t *lenp)
{
- return string_convert_ext(vcp, ptr, lenp, NULL);
+ return (char *)string_convert_ext(vcp, (char_u *)ptr, lenp, NULL);
}
/*
@@ -2567,7 +2558,7 @@ char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp
case CONV_TO_UTF8: // latin1 to utf-8 conversion
retval = xmalloc(len * 2 + 1);
d = retval;
- for (size_t i = 0; i < len; ++i) {
+ for (size_t i = 0; i < len; i++) {
c = ptr[i];
if (c < 0x80) {
*d++ = (char_u)c;
@@ -2585,7 +2576,7 @@ char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp
case CONV_9_TO_UTF8: // latin9 to utf-8 conversion
retval = xmalloc(len * 3 + 1);
d = retval;
- for (size_t i = 0; i < len; ++i) {
+ for (size_t i = 0; i < len; i++) {
c = ptr[i];
switch (c) {
case 0xa4:
@@ -2748,7 +2739,7 @@ static int tv_nr_compare(const void *a1, const void *a2)
}
/// "setcellwidths()" function
-void f_setcellwidths(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_setcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type != VAR_LIST || argvars[0].vval.v_list == NULL) {
emsg(_(e_listreq));
@@ -2857,10 +2848,10 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
xfree(cw_table_save);
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
}
-void f_charclass(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_charclass(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (tv_check_for_string(&argvars[0]) == FAIL
|| argvars[0].vval.v_string == NULL) {
diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c
index 216ee26620..9446aaee4f 100644
--- a/src/nvim/memfile.c
+++ b/src/nvim/memfile.c
@@ -77,7 +77,7 @@
///
/// @return - The open memory file, on success.
/// - NULL, on failure (e.g. file does not exist).
-memfile_T *mf_open(char_u *fname, int flags)
+memfile_T *mf_open(char *fname, int flags)
{
memfile_T *mfp = xmalloc(sizeof(memfile_T));
@@ -148,7 +148,7 @@ memfile_T *mf_open(char_u *fname, int flags)
///
/// @return OK On success.
/// FAIL If file could not be opened.
-int mf_open_file(memfile_T *mfp, char_u *fname)
+int mf_open_file(memfile_T *mfp, char *fname)
{
if (mf_do_open(mfp, fname, O_RDWR | O_CREAT | O_EXCL)) {
mfp->mf_dirty = true;
@@ -749,9 +749,9 @@ void mf_free_fnames(memfile_T *mfp)
///
/// Only called when creating or renaming the swapfile. Either way it's a new
/// name so we must work out the full path name.
-void mf_set_fnames(memfile_T *mfp, char_u *fname)
+void mf_set_fnames(memfile_T *mfp, char *fname)
{
- mfp->mf_fname = fname;
+ mfp->mf_fname = (char_u *)fname;
mfp->mf_ffname = (char_u *)FullName_save((char *)mfp->mf_fname, false);
}
@@ -779,7 +779,7 @@ bool mf_need_trans(memfile_T *mfp)
///
/// @param flags Flags for open().
/// @return A bool indicating success of the `open` call.
-static bool mf_do_open(memfile_T *mfp, char_u *fname, int flags)
+static bool mf_do_open(memfile_T *mfp, char *fname, int flags)
{
// fname cannot be NameBuff, because it must have been allocated.
mf_set_fnames(mfp, fname);
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 23bc5d59c8..b0b6b675cb 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -399,7 +399,7 @@ void ml_setname(buf_T *buf)
}
// Try all directories in the 'directory' option.
- dirp = (char *)p_dir;
+ dirp = p_dir;
bool found_existing_dir = false;
for (;;) {
if (*dirp == NUL) { // tried all directories, fail
@@ -430,7 +430,7 @@ void ml_setname(buf_T *buf)
if (vim_rename(mfp->mf_fname, fname) == 0) {
success = true;
mf_free_fnames(mfp);
- mf_set_fnames(mfp, fname);
+ mf_set_fnames(mfp, (char *)fname);
ml_upd_block0(buf, UB_SAME_DIR);
break;
}
@@ -483,14 +483,14 @@ void ml_open_file(buf_T *buf)
if (buf->b_spell) {
fname = vim_tempname();
if (fname != NULL) {
- (void)mf_open_file(mfp, fname); // consumes fname!
+ (void)mf_open_file(mfp, (char *)fname); // consumes fname!
}
buf->b_may_swap = false;
return;
}
// Try all directories in 'directory' option.
- dirp = (char *)p_dir;
+ dirp = p_dir;
bool found_existing_dir = false;
for (;;) {
if (*dirp == NUL) {
@@ -506,7 +506,7 @@ void ml_open_file(buf_T *buf)
if (fname == NULL) {
continue;
}
- if (mf_open_file(mfp, fname) == OK) { // consumes fname!
+ if (mf_open_file(mfp, (char *)fname) == OK) { // consumes fname!
ml_upd_block0(buf, UB_SAME_DIR);
// Flush block zero, so others can read it
@@ -523,7 +523,7 @@ void ml_open_file(buf_T *buf)
}
if (*p_dir != NUL && mfp->mf_fname == NULL) {
- need_wait_return = true; // call wait_return later
+ need_wait_return = true; // call wait_return() later
no_wait_return++;
(void)semsg(_("E303: Unable to open swap file for \"%s\", recovery impossible"),
buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname);
@@ -552,7 +552,7 @@ void check_need_swap(bool newfile)
/// Close memline for buffer 'buf'.
///
-/// @param del_file if TRUE, delete the swap file
+/// @param del_file if true, delete the swap file
void ml_close(buf_T *buf, int del_file)
{
if (buf->b_ml.ml_mfp == NULL) { // not open
@@ -590,7 +590,7 @@ void ml_close_notmod(void)
{
FOR_ALL_BUFFERS(buf) {
if (!bufIsChanged(buf)) {
- ml_close(buf, TRUE); // close all not-modified buffers
+ ml_close(buf, true); // close all not-modified buffers
}
}
}
@@ -721,7 +721,7 @@ static void add_b0_fenc(ZERO_BL *b0p, buf_T *buf)
b0p->b0_flags &= (uint8_t) ~B0_HAS_FENC;
} else {
memmove((char *)b0p->b0_fname + size - n,
- (char *)buf->b_p_fenc, (size_t)n);
+ buf->b_p_fenc, (size_t)n);
*(b0p->b0_fname + size - n - 1) = NUL;
b0p->b0_flags |= B0_HAS_FENC;
}
@@ -764,7 +764,7 @@ void ml_recover(bool checkext)
int attr;
int orig_file_status = NOTDONE;
- recoverymode = TRUE;
+ recoverymode = true;
called_from_main = (curbuf->b_ml.ml_mfp == NULL);
attr = HL_ATTR(HLF_E);
@@ -785,7 +785,7 @@ void ml_recover(bool checkext)
directly = false;
// count the number of matching swap files
- len = recover_names(fname, FALSE, 0, NULL);
+ len = recover_names(fname, false, 0, NULL);
if (len == 0) { // no swap files found
semsg(_("E305: No swap file found for %s"), fname);
goto theend;
@@ -794,16 +794,16 @@ void ml_recover(bool checkext)
i = 1;
} else { // several swap files found, choose
// list the names of the swap files
- (void)recover_names(fname, TRUE, 0, NULL);
+ (void)recover_names(fname, true, 0, NULL);
msg_putchar('\n');
msg_puts(_("Enter number of swap file to use (0 to quit): "));
- i = get_number(FALSE, NULL);
+ i = get_number(false, NULL);
if (i < 1 || i > len) {
goto theend;
}
}
// get the swap file name that will be used
- (void)recover_names(fname, FALSE, i, &fname_used);
+ (void)recover_names(fname, false, i, &fname_used);
}
if (fname_used == NULL) {
goto theend; // user chose invalid number.
@@ -835,7 +835,7 @@ void ml_recover(bool checkext)
*/
p = vim_strsave(fname_used); // save "fname_used" for the message:
// mf_open() will consume "fname_used"!
- mfp = mf_open(fname_used, O_RDONLY);
+ mfp = mf_open((char *)fname_used, O_RDONLY);
fname_used = p;
if (mfp == NULL || mfp->mf_fd < 0) {
semsg(_("E306: Cannot open %s"), fname_used);
@@ -857,7 +857,7 @@ void ml_recover(bool checkext)
if ((hp = mf_get(mfp, 0, 1)) == NULL) {
msg_start();
msg_puts_attr(_("Unable to read block 0 from "), attr | MSG_HIST);
- msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST);
+ msg_outtrans_attr((char *)mfp->mf_fname, attr | MSG_HIST);
msg_puts_attr(_("\nMaybe no changes were made or Vim did not update the swap file."),
attr | MSG_HIST);
msg_end();
@@ -866,7 +866,7 @@ void ml_recover(bool checkext)
b0p = hp->bh_data;
if (STRNCMP(b0p->b0_version, "VIM 3.0", 7) == 0) {
msg_start();
- msg_outtrans_attr(mfp->mf_fname, MSG_HIST);
+ msg_outtrans_attr((char *)mfp->mf_fname, MSG_HIST);
msg_puts_attr(_(" cannot be used with this version of Vim.\n"),
MSG_HIST);
msg_puts_attr(_("Use Vim version 3.0.\n"), MSG_HIST);
@@ -879,7 +879,7 @@ void ml_recover(bool checkext)
}
if (b0_magic_wrong(b0p)) {
msg_start();
- msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST);
+ msg_outtrans_attr((char *)mfp->mf_fname, attr | MSG_HIST);
msg_puts_attr(_(" cannot be used on this computer.\n"),
attr | MSG_HIST);
msg_puts_attr(_("The file was created on "), attr | MSG_HIST);
@@ -901,7 +901,7 @@ void ml_recover(bool checkext)
mf_new_page_size(mfp, (unsigned)char_to_long(b0p->b0_page_size));
if (mfp->mf_page_size < previous_page_size) {
msg_start();
- msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST);
+ msg_outtrans_attr((char *)mfp->mf_fname, attr | MSG_HIST);
msg_puts_attr(_(" has been damaged (page size is smaller than minimum value).\n"),
attr | MSG_HIST);
msg_end();
@@ -922,11 +922,9 @@ void ml_recover(bool checkext)
b0p = hp->bh_data;
}
- /*
- * If .swp file name given directly, use name from swap file for buffer.
- */
+ // If .swp file name given directly, use name from swap file for buffer.
if (directly) {
- expand_env(b0p->b0_fname, NameBuff, MAXPATHL);
+ expand_env((char *)b0p->b0_fname, NameBuff, MAXPATHL);
if (setfname(curbuf, (char *)NameBuff, NULL, true) == FAIL) {
goto theend;
}
@@ -993,7 +991,7 @@ void ml_recover(bool checkext)
set_fileformat(b0_ff - 1, OPT_LOCAL);
}
if (b0_fenc != NULL) {
- set_option_value("fenc", 0L, (char *)b0_fenc, OPT_LOCAL);
+ set_option_value_give_err("fenc", 0L, (char *)b0_fenc, OPT_LOCAL);
xfree(b0_fenc);
}
unchanged(curbuf, true, true);
@@ -1035,7 +1033,7 @@ void ml_recover(bool checkext)
if (pp->pb_id == PTR_ID) { // it is a pointer block
// check line count when using pointer block first time
if (idx == 0 && line_count != 0) {
- for (i = 0; i < (int)pp->pb_count; ++i) {
+ for (i = 0; i < (int)pp->pb_count; i++) {
line_count -= pp->pb_pointer[i].pe_line_count;
}
if (line_count != 0) {
@@ -1071,7 +1069,7 @@ void ml_recover(bool checkext)
ml_append(lnum++, _("???LINES MISSING"),
(colnr_T)0, true);
}
- ++idx; // get same block again for next index
+ idx++; // get same block again for next index
continue;
}
@@ -1131,7 +1129,7 @@ void ml_recover(bool checkext)
has_error = true;
}
- for (i = 0; i < dp->db_line_count; ++i) {
+ for (i = 0; i < dp->db_line_count; i++) {
txt_start = (dp->db_index[i] & DB_INDEX_MASK);
if (txt_start <= (int)HEADER_SIZE
|| txt_start >= (int)dp->db_txt_end) {
@@ -1177,7 +1175,7 @@ void ml_recover(bool checkext)
buf_inc_changedtick(curbuf);
}
} else {
- for (idx = 1; idx <= lnum; ++idx) {
+ for (idx = 1; idx <= lnum; idx++) {
// Need to copy one line, fetching the other one may flush it.
p = vim_strsave(ml_get(idx));
i = STRCMP(p, ml_get(idx + lnum));
@@ -1201,7 +1199,7 @@ void ml_recover(bool checkext)
curbuf->b_flags |= BF_RECOVERED;
check_cursor();
- recoverymode = FALSE;
+ recoverymode = false;
if (got_int) {
emsg(_("E311: Recovery Interrupted"));
} else if (error) {
@@ -1222,11 +1220,11 @@ void ml_recover(bool checkext)
msg_puts(_("\nYou may want to delete the .swp file now.\n\n"));
cmdline_row = msg_row;
}
- redraw_curbuf_later(NOT_VALID);
+ redraw_curbuf_later(UPD_NOT_VALID);
theend:
xfree(fname_used);
- recoverymode = FALSE;
+ recoverymode = false;
if (mfp != NULL) {
if (hp != NULL) {
mf_put(mfp, hp, false, false);
@@ -1238,7 +1236,7 @@ theend:
xfree(buf);
}
if (serious_error && called_from_main) {
- ml_close(curbuf, TRUE);
+ ml_close(curbuf, true);
} else {
apply_autocmds(EVENT_BUFREADPOST, NULL, curbuf->b_fname, false, curbuf);
apply_autocmds(EVENT_BUFWINENTER, NULL, curbuf->b_fname, false, curbuf);
@@ -1255,7 +1253,7 @@ theend:
/// - find the name of the n'th swap file when recovering
///
/// @param fname base for swap file name
-/// @param list when TRUE, list the swap file names
+/// @param list when true, list the swap file names
/// @param nr when non-zero, return nr'th swap file name
/// @param fname_out result when "nr" > 0
int recover_names(char_u *fname, int list, int nr, char_u **fname_out)
@@ -1294,7 +1292,7 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out)
// Do the loop for every directory in 'directory'.
// First allocate some memory to put the directory name in.
dir_name = xmalloc(STRLEN(p_dir) + 1);
- dirp = (char *)p_dir;
+ dirp = p_dir;
while (*dirp) {
// Isolate a directory name from *dirp and put it in dir_name (we know
// it is large enough, so use 31000 for length).
@@ -1310,7 +1308,7 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out)
names[2] = xstrdup(".sw?");
num_names = 3;
} else {
- num_names = recov_file_names(names, fname_res, TRUE);
+ num_names = recov_file_names(names, fname_res, true);
}
} else { // check directory dir_name
if (fname == NULL) {
@@ -1333,7 +1331,7 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out)
tail = (char_u *)path_tail((char *)fname_res);
tail = (char_u *)concat_fnames((char *)dir_name, (char *)tail, true);
}
- num_names = recov_file_names(names, tail, FALSE);
+ num_names = recov_file_names(names, tail, false);
xfree(tail);
}
}
@@ -1379,7 +1377,7 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out)
if (--num_files == 0) {
xfree(files);
} else {
- for (; i < num_files; ++i) {
+ for (; i < num_files; i++) {
files[i] = files[i + 1];
}
}
@@ -1406,7 +1404,7 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out)
}
if (num_files) {
- for (int i = 0; i < num_files; ++i) {
+ for (int i = 0; i < num_files; i++) {
// print the swap file name
msg_outnum((long)++file_count);
msg_puts(". ");
@@ -1422,7 +1420,7 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out)
file_count += num_files;
}
- for (int i = 0; i < num_names; ++i) {
+ for (int i = 0; i < num_names; i++) {
xfree(names[i]);
}
if (num_files > 0) {
@@ -1447,7 +1445,7 @@ char *make_percent_swname(const char *dir, const char *name)
*d = '%';
}
}
- d = concat_fnames(dir, s, TRUE);
+ d = concat_fnames(dir, s, true);
xfree(s);
xfree(f);
}
@@ -1668,8 +1666,8 @@ static int recov_file_names(char **names, char_u *path, int prepend_dot)
/// sync all memlines
///
-/// @param check_file if TRUE, check if original file exists and was not changed.
-/// @param check_char if TRUE, stop syncing when character becomes available, but
+/// @param check_file if true, check if original file exists and was not changed.
+/// @param check_char if true, stop syncing when character becomes available, but
///
/// always sync at least one block.
void ml_sync_all(int check_file, int check_char, bool do_fsync)
@@ -1714,7 +1712,7 @@ void ml_sync_all(int check_file, int check_char, bool do_fsync)
/// Used for the :preserve command and when the original file has been
/// changed or deleted.
///
-/// @param message if TRUE, the success of preserving is reported.
+/// @param message if true, the success of preserving is reported.
void ml_preserve(buf_T *buf, int message, bool do_fsync)
{
bhdr_T *hp;
@@ -1908,7 +1906,7 @@ int ml_line_alloced(void)
/// "line" does not need to be allocated, but can't be another line in a
/// buffer, unlocking may make it invalid.
///
-/// newfile: TRUE when starting to edit a new file, meaning that pe_old_lnum
+/// newfile: true when starting to edit a new file, meaning that pe_old_lnum
/// will be set for recovery
/// Check: The caller of this function should probably also call
/// appended_lines().
@@ -1922,7 +1920,7 @@ int ml_line_alloced(void)
int ml_append(linenr_T lnum, char *line, colnr_T len, bool newfile)
{
// When starting up, we might still need to create the memfile
- if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL, 0) == FAIL) {
+ if (curbuf->b_ml.ml_mfp == NULL && open_buffer(false, NULL, 0) == FAIL) {
return FAIL;
}
@@ -1949,7 +1947,7 @@ int ml_append_buf(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, bool new
if (buf->b_ml.ml_line_lnum != 0) {
ml_flush_line(buf);
}
- return ml_append_int(buf, lnum, line, len, newfile, FALSE);
+ return ml_append_int(buf, lnum, line, len, newfile, false);
}
/// @param lnum append after this line (can be 0)
@@ -2038,7 +2036,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
dp = hp->bh_data;
}
- ++buf->b_ml.ml_line_count;
+ buf->b_ml.ml_line_count++;
if ((int)dp->db_free >= space_needed) { // enough room in data block
/*
@@ -2286,7 +2284,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
&pp->pb_pointer[pb_idx + 1],
(size_t)(pp->pb_count - pb_idx - 1) * sizeof(PTR_EN));
}
- ++pp->pb_count;
+ pp->pb_count++;
pp->pb_pointer[pb_idx].pe_line_count = line_count_left;
pp->pb_pointer[pb_idx].pe_bnum = bnum_left;
pp->pb_pointer[pb_idx].pe_page_count = page_count_left;
@@ -2453,7 +2451,7 @@ int ml_replace(linenr_T lnum, char *line, bool copy)
/// Do not use it after calling ml_replace().
///
/// Check: The caller of this function should probably also call
-/// changed_lines(), unless update_screen(NOT_VALID) is used.
+/// changed_lines(), unless update_screen(UPD_NOT_VALID) is used.
///
/// @return FAIL for failure, OK otherwise
int ml_replace_buf(buf_T *buf, linenr_T lnum, char_u *line, bool copy)
@@ -2561,7 +2559,7 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message)
count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 2;
idx = lnum - buf->b_ml.ml_locked_low;
- --buf->b_ml.ml_line_count;
+ buf->b_ml.ml_line_count--;
line_start = ((dp->db_index[idx]) & DB_INDEX_MASK);
if (idx == 0) { // first line in block, text at the end
@@ -2705,7 +2703,7 @@ linenr_T ml_firstmarked(void)
dp = hp->bh_data;
for (i = lnum - curbuf->b_ml.ml_locked_low;
- lnum <= curbuf->b_ml.ml_locked_high; ++i, ++lnum) {
+ lnum <= curbuf->b_ml.ml_locked_high; i++, lnum++) {
if ((dp->db_index[i]) & DB_MARKED) {
(dp->db_index[i]) &= DB_INDEX_MASK;
curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
@@ -2745,7 +2743,7 @@ void ml_clearmarked(void)
dp = hp->bh_data;
for (i = lnum - curbuf->b_ml.ml_locked_low;
- lnum <= curbuf->b_ml.ml_locked_high; ++i, ++lnum) {
+ lnum <= curbuf->b_ml.ml_locked_high; i++, lnum++) {
if ((dp->db_index[i]) & DB_MARKED) {
(dp->db_index[i]) &= DB_INDEX_MASK;
curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
@@ -2965,7 +2963,7 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action)
high = buf->b_ml.ml_line_count;
if (action == ML_FIND) { // first try stack entries
- for (top = buf->b_ml.ml_stack_top - 1; top >= 0; --top) {
+ for (top = buf->b_ml.ml_stack_top - 1; top >= 0; top--) {
ip = &(buf->b_ml.ml_stack[top]);
if (ip->ip_low <= lnum && ip->ip_high >= lnum) {
bnum = ip->ip_bnum;
@@ -3021,8 +3019,8 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action)
ip->ip_high = high;
ip->ip_index = -1; // index not known yet
- dirty = FALSE;
- for (idx = 0; idx < (int)pp->pb_count; ++idx) {
+ dirty = false;
+ for (idx = 0; idx < (int)pp->pb_count; idx++) {
t = pp->pb_pointer[idx].pe_line_count;
CHECK(t == 0, _("pe_line_count is zero"));
if ((low += t) > lnum) {
@@ -3040,7 +3038,7 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action)
if (bnum != bnum2) {
bnum = bnum2;
pp->pb_pointer[idx].pe_bnum = bnum;
- dirty = TRUE;
+ dirty = true;
}
}
@@ -3058,10 +3056,10 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action)
}
if (action == ML_DELETE) {
pp->pb_pointer[idx].pe_line_count--;
- dirty = TRUE;
+ dirty = true;
} else if (action == ML_INSERT) {
pp->pb_pointer[idx].pe_line_count++;
- dirty = TRUE;
+ dirty = true;
}
mf_put(mfp, hp, dirty, false);
}
@@ -3119,7 +3117,7 @@ static void ml_lineadd(buf_T *buf, int count)
memfile_T *mfp = buf->b_ml.ml_mfp;
bhdr_T *hp;
- for (idx = buf->b_ml.ml_stack_top - 1; idx >= 0; --idx) {
+ for (idx = buf->b_ml.ml_stack_top - 1; idx >= 0; idx--) {
ip = &(buf->b_ml.ml_stack[idx]);
if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL) {
break;
@@ -3203,7 +3201,7 @@ int resolve_symlink(const char_u *fname, char_u *buf)
* be consistent even when opening a relative symlink from different
* working directories.
*/
- return vim_FullName((char *)tmp, (char *)buf, MAXPATHL, TRUE);
+ return vim_FullName((char *)tmp, (char *)buf, MAXPATHL, true);
}
#endif
@@ -3275,7 +3273,7 @@ char_u *get_file_in_dir(char_u *fname, char_u *dname)
retval = vim_strsave(fname);
} else if (dname[0] == '.' && vim_ispathsep(dname[1])) {
if (tail == fname) { // no path before file name
- retval = (char_u *)concat_fnames((char *)dname + 2, (char *)tail, TRUE);
+ retval = (char_u *)concat_fnames((char *)dname + 2, (char *)tail, true);
} else {
save_char = *tail;
*tail = NUL;
@@ -3285,7 +3283,7 @@ char_u *get_file_in_dir(char_u *fname, char_u *dname)
xfree(t);
}
} else {
- retval = (char_u *)concat_fnames((char *)dname, (char *)tail, TRUE);
+ retval = (char_u *)concat_fnames((char *)dname, (char *)tail, true);
}
return retval;
@@ -3455,7 +3453,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
&& !buf->b_help && !(buf->b_flags & BF_DUMMY)) {
int fd;
struct block0 b0;
- int differ = FALSE;
+ int differ = false;
// Try to read block 0 from the swap file to get the original
// file name (and inode number).
@@ -3472,19 +3470,19 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
// Symlinks may point to the same file even
// when the name differs, need to check the
// inode too.
- expand_env(b0.b0_fname, NameBuff, MAXPATHL);
- if (fnamecmp_ino((char_u *)buf->b_ffname, NameBuff,
+ expand_env((char *)b0.b0_fname, NameBuff, MAXPATHL);
+ if (fnamecmp_ino((char_u *)buf->b_ffname, (char_u *)NameBuff,
char_to_long(b0.b0_ino))) {
- differ = TRUE;
+ differ = true;
}
}
} else {
// The name in the swap file may be
// "~user/path/file". Expand it first.
- expand_env(b0.b0_fname, NameBuff, MAXPATHL);
- if (fnamecmp_ino((char_u *)buf->b_ffname, NameBuff,
+ expand_env((char *)b0.b0_fname, NameBuff, MAXPATHL);
+ if (fnamecmp_ino((char_u *)buf->b_ffname, (char_u *)NameBuff,
char_to_long(b0.b0_ino))) {
- differ = TRUE;
+ differ = true;
}
}
}
@@ -3494,7 +3492,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
// give the ATTENTION message when there is an old swap file
// for the current file, and the buffer was not recovered.
if (differ == false && !(curbuf->b_flags & BF_RECOVERED)
- && vim_strchr((char *)p_shm, SHM_ATTENTION) == NULL) {
+ && vim_strchr(p_shm, SHM_ATTENTION) == NULL) {
int choice = 0;
process_still_running = false;
@@ -3564,7 +3562,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
if (choice > 0) {
switch (choice) {
case 1:
- buf->b_p_ro = TRUE;
+ buf->b_p_ro = true;
break;
case 2:
break;
@@ -3579,7 +3577,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
break;
case 6:
swap_exists_action = SEA_QUIT;
- got_int = TRUE;
+ got_int = true;
break;
}
@@ -3610,13 +3608,13 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
XFREE_CLEAR(fname);
break;
}
- --fname[n - 2]; // ".svz", ".suz", etc.
+ fname[n - 2]--; // ".svz", ".suz", etc.
fname[n - 1] = 'z' + 1;
}
- --fname[n - 1]; // ".swo", ".swn", etc.
+ fname[n - 1]--; // ".swo", ".swn", etc.
}
- if (os_isdir((char_u *)dir_name)) {
+ if (os_isdir(dir_name)) {
*found_existing_dir = true;
} else if (!*found_existing_dir && **dirp == NUL) {
int ret;
@@ -3667,18 +3665,18 @@ static int b0_magic_wrong(ZERO_BL *b0p)
///
/// current file doesn't exist, file for swap file exist, file name(s) not
/// available -> probably different
-/// == 0 != 0 FAIL X TRUE
-/// == 0 != 0 X FAIL TRUE
+/// == 0 != 0 FAIL X true
+/// == 0 != 0 X FAIL true
///
/// current file exists, inode for swap unknown, file name(s) not
/// available -> probably different
-/// != 0 == 0 FAIL X TRUE
-/// != 0 == 0 X FAIL TRUE
+/// != 0 == 0 FAIL X true
+/// != 0 == 0 X FAIL true
///
/// current file doesn't exist, inode for swap unknown, one file name not
/// available -> probably different
-/// == 0 == 0 FAIL OK TRUE
-/// == 0 == 0 OK FAIL TRUE
+/// == 0 == 0 FAIL OK true
+/// == 0 == 0 OK FAIL true
///
/// current file doesn't exist, inode for swap unknown, both file names not
/// available -> compare file names
@@ -3722,8 +3720,8 @@ static bool fnamecmp_ino(char_u *fname_c, char_u *fname_s, long ino_block0)
* One of the inode numbers is unknown, try a forced vim_FullName() and
* compare the file names.
*/
- retval_c = vim_FullName((char *)fname_c, (char *)buf_c, MAXPATHL, TRUE);
- retval_s = vim_FullName((char *)fname_s, (char *)buf_s, MAXPATHL, TRUE);
+ retval_c = vim_FullName((char *)fname_c, (char *)buf_c, MAXPATHL, true);
+ retval_s = vim_FullName((char *)fname_s, (char *)buf_s, MAXPATHL, true);
if (retval_c == OK && retval_s == OK) {
return STRCMP(buf_c, buf_s) != 0;
}
@@ -4163,7 +4161,7 @@ void goto_byte(long cnt)
curwin->w_cursor.lnum = lnum;
curwin->w_cursor.col = (colnr_T)boff;
curwin->w_cursor.coladd = 0;
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
}
check_cursor();
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index fb36d4ccf4..a9785fcb7c 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -60,6 +60,8 @@ void try_to_free_memory(void)
// Try to save all buffers and release as many blocks as possible
mf_release_all();
+ arena_free_reuse_blks();
+
trying_to_free = false;
}
@@ -528,21 +530,19 @@ void time_to_bytes(time_t time_, uint8_t buf[8])
}
#define ARENA_BLOCK_SIZE 4096
+#define REUSE_MAX 4
+
+static struct consumed_blk *arena_reuse_blk;
+static size_t arena_reuse_blk_count = 0;
-void arena_start(Arena *arena, ArenaMem *reuse_blk)
+static void arena_free_reuse_blks(void)
{
- if (reuse_blk && *reuse_blk) {
- arena->cur_blk = (char *)(*reuse_blk);
- *reuse_blk = NULL;
- } else {
- arena->cur_blk = xmalloc(ARENA_BLOCK_SIZE);
+ while (arena_reuse_blk_count > 0) {
+ struct consumed_blk *blk = arena_reuse_blk;
+ arena_reuse_blk = arena_reuse_blk->prev;
+ xfree(blk);
+ arena_reuse_blk_count--;
}
- arena->pos = 0;
- arena->size = ARENA_BLOCK_SIZE;
- // address is the same as as (struct consumed_blk *)arena->cur_blk
- struct consumed_blk *blk = arena_alloc(arena, sizeof(struct consumed_blk), true);
- assert((char *)blk == (char *)arena->cur_blk);
- blk->prev = NULL;
}
/// Finnish the allocations in an arena.
@@ -558,17 +558,45 @@ ArenaMem arena_finish(Arena *arena)
return res;
}
+void alloc_block(Arena *arena)
+{
+ struct consumed_blk *prev_blk = (struct consumed_blk *)arena->cur_blk;
+ if (arena_reuse_blk_count > 0) {
+ arena->cur_blk = (char *)arena_reuse_blk;
+ arena_reuse_blk = arena_reuse_blk->prev;
+ arena_reuse_blk_count--;
+ } else {
+ arena_alloc_count++;
+ arena->cur_blk = xmalloc(ARENA_BLOCK_SIZE);
+ }
+ arena->pos = 0;
+ arena->size = ARENA_BLOCK_SIZE;
+ struct consumed_blk *blk = arena_alloc(arena, sizeof(struct consumed_blk), true);
+ blk->prev = prev_blk;
+}
+
+/// @param arena if NULL, do a global allocation. caller must then free the value!
+/// @param size if zero, will still return a non-null pointer, but not a unique one
void *arena_alloc(Arena *arena, size_t size, bool align)
{
+ if (!arena) {
+ return xmalloc(size);
+ }
if (align) {
arena->pos = (arena->pos + (ARENA_ALIGN - 1)) & ~(ARENA_ALIGN - 1);
}
- if (arena->pos + size > arena->size) {
- if (size > (arena->size - sizeof(struct consumed_blk)) >> 1) {
+ if (arena->pos + size > arena->size || !arena->cur_blk) {
+ if (size > (ARENA_BLOCK_SIZE - sizeof(struct consumed_blk)) >> 1) {
// if allocation is too big, allocate a large block with the requested
// size, but still with block pointer head. We do this even for
// arena->size / 2, as there likely is space left for the next
// small allocation in the current block.
+ if (!arena->cur_blk) {
+ // to simplify free-list management, arena->cur_blk must
+ // always be a normal, ARENA_BLOCK_SIZE sized, block
+ alloc_block(arena);
+ }
+ arena_alloc_count++;
char *alloc = xmalloc(size + sizeof(struct consumed_blk));
struct consumed_blk *cur_blk = (struct consumed_blk *)arena->cur_blk;
struct consumed_blk *fix_blk = (struct consumed_blk *)alloc;
@@ -576,12 +604,7 @@ void *arena_alloc(Arena *arena, size_t size, bool align)
cur_blk->prev = fix_blk;
return (alloc + sizeof(struct consumed_blk));
} else {
- struct consumed_blk *prev_blk = (struct consumed_blk *)arena->cur_blk;
- arena->cur_blk = xmalloc(ARENA_BLOCK_SIZE);
- arena->pos = 0;
- arena->size = ARENA_BLOCK_SIZE;
- struct consumed_blk *blk = arena_alloc(arena, sizeof(struct consumed_blk), true);
- blk->prev = prev_blk;
+ alloc_block(arena);
}
}
@@ -590,15 +613,17 @@ void *arena_alloc(Arena *arena, size_t size, bool align)
return mem;
}
-void arena_mem_free(ArenaMem mem, ArenaMem *reuse_blk)
+void arena_mem_free(ArenaMem mem)
{
struct consumed_blk *b = mem;
// peel of the first block, as it is guaranteed to be ARENA_BLOCK_SIZE,
// not a custom fix_blk
- if (reuse_blk && *reuse_blk == NULL && b != NULL) {
- *reuse_blk = b;
+ if (arena_reuse_blk_count < REUSE_MAX && b != NULL) {
+ struct consumed_blk *reuse_blk = b;
b = b->prev;
- (*reuse_blk)->prev = NULL;
+ reuse_blk->prev = arena_reuse_blk;
+ arena_reuse_blk = reuse_blk;
+ arena_reuse_blk_count++;
}
while (b) {
@@ -799,6 +824,9 @@ void free_all_mem(void)
nlua_free_all_mem();
ui_free_all_mem();
+
+ // should be last, in case earlier free functions deallocates arenas
+ arena_free_reuse_blks();
}
#endif
diff --git a/src/nvim/memory.h b/src/nvim/memory.h
index 63d607c2ce..f407192331 100644
--- a/src/nvim/memory.h
+++ b/src/nvim/memory.h
@@ -6,6 +6,8 @@
#include <stdint.h> // for uint8_t
#include <time.h> // for time_t
+#include "nvim/macros.h"
+
/// `malloc()` function signature
typedef void *(*MemMalloc)(size_t);
@@ -37,6 +39,8 @@ extern MemRealloc mem_realloc;
extern bool entered_free_all_mem;
#endif
+EXTERN size_t arena_alloc_count INIT(=0);
+
typedef struct consumed_blk {
struct consumed_blk *prev;
} *ArenaMem;
@@ -48,7 +52,7 @@ typedef struct {
size_t pos, size;
} Arena;
-// inits an empty arena. use arena_start() to actually allocate space!
+// inits an empty arena.
#define ARENA_EMPTY { .cur_blk = NULL, .pos = 0, .size = 0 }
#define kv_fixsize_arena(a, v, s) \
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index c3cf4457fc..cb6918cd27 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -419,7 +419,7 @@ static int add_menu_path(const char *const menu_path, vimmenu_T *menuarg, const
p = (call_data == NULL) ? NULL : xstrdup(call_data);
// loop over all modes, may add more than one
- for (i = 0; i < MENU_MODES; ++i) {
+ for (i = 0; i < MENU_MODES; i++) {
if (modes & (1 << i)) {
// free any old menu
free_menu_string(menu, i);
@@ -853,7 +853,7 @@ static void show_menus_recursive(vimmenu_T *menu, int modes, int depth)
msg_puts(" ");
}
// Same highlighting as for directories!?
- msg_outtrans_attr((char_u *)menu->name, HL_ATTR(HLF_D));
+ msg_outtrans_attr(menu->name, HL_ATTR(HLF_D));
}
if (menu != NULL && menu->children == NULL) {
@@ -914,7 +914,7 @@ static void show_menus_recursive(vimmenu_T *menu, int modes, int depth)
*/
static vimmenu_T *expand_menu = NULL;
static int expand_modes = 0x0;
-static int expand_emenu; // TRUE for ":emenu" command
+static int expand_emenu; // true for ":emenu" command
/*
* Work out what to complete when doing command line completion of menu names.
@@ -933,7 +933,7 @@ char *set_context_in_menu_cmd(expand_T *xp, const char *cmd, char *arg, bool for
xp->xp_context = EXPAND_UNSUCCESSFUL;
// Check for priority numbers, enable and disable
- for (p = arg; *p; ++p) {
+ for (p = arg; *p; p++) {
if (!ascii_isdigit(*p) && *p != '.') {
break;
}
@@ -957,7 +957,7 @@ char *set_context_in_menu_cmd(expand_T *xp, const char *cmd, char *arg, bool for
arg = after_dot = p;
- for (; *p && !ascii_iswhite(*p); ++p) {
+ for (; *p && !ascii_iswhite(*p); p++) {
if ((*p == '\\' || *p == Ctrl_V) && p[1] != NUL) {
p++;
} else if (*p == '.') {
@@ -1056,7 +1056,7 @@ char *get_menu_name(expand_T *xp, int idx)
} else {
str = menu->dname;
if (menu->en_dname == NULL) {
- should_advance = TRUE;
+ should_advance = true;
}
}
} else {
@@ -1163,10 +1163,8 @@ char *menu_name_skip(char *const name)
return p;
}
-/*
- * Return TRUE when "name" matches with menu "menu". The name is compared in
- * two ways: raw menu name and menu name without '&'. ignore part after a TAB.
- */
+/// Return true when "name" matches with menu "menu". The name is compared in
+/// two ways: raw menu name and menu name without '&'. ignore part after a TAB.
static bool menu_name_equal(const char *const name, const vimmenu_T *const menu)
{
if (menu->en_name != NULL
@@ -1181,7 +1179,7 @@ static bool menu_namecmp(const char *const name, const char *const mname)
{
int i;
- for (i = 0; name[i] != NUL && name[i] != TAB; ++i) {
+ for (i = 0; name[i] != NUL && name[i] != TAB; i++) {
if (name[i] != mname[i]) {
break;
}
@@ -1405,10 +1403,8 @@ bool menu_is_toolbar(const char *const name)
return STRNCMP(name, "ToolBar", 7) == 0;
}
-/*
- * Return TRUE if the name is a menu separator identifier: Starts and ends
- * with '-'
- */
+/// Return true if the name is a menu separator identifier: Starts and ends
+/// with '-'
int menu_is_separator(char *name)
{
return name[0] == '-' && name[STRLEN(name) - 1] == '-';
@@ -1945,7 +1941,7 @@ static void menuitem_getinfo(const char *menu_name, const vimmenu_T *menu, int m
/// "menu_info()" function
/// Return information about a menu (including all the child menus)
-void f_menu_info(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_menu_info(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_alloc_ret(rettv);
dict_T *const retdict = rettv->vval.v_dict;
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 684cf7207c..80b5f53f4e 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -56,7 +56,7 @@ typedef struct msgchunk_S msgchunk_T;
struct msgchunk_S {
msgchunk_T *sb_next;
msgchunk_T *sb_prev;
- char sb_eol; // TRUE when line ends after this text
+ char sb_eol; // true when line ends after this text
int sb_msg_col; // column in which text starts
int sb_attr; // text attributes
char_u sb_text[1]; // text to be displayed, actually longer
@@ -66,7 +66,7 @@ struct msgchunk_S {
#define DLG_BUTTON_SEP '\n'
#define DLG_HOTKEY_CHAR '&'
-static int confirm_msg_used = FALSE; // displaying confirm_msg
+static int confirm_msg_used = false; // displaying confirm_msg
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "message.c.generated.h"
#endif
@@ -78,7 +78,7 @@ MessageHistoryEntry *last_msg_hist = NULL;
static int msg_hist_len = 0;
static FILE *verbose_fd = NULL;
-static int verbose_did_open = FALSE;
+static int verbose_did_open = false;
bool keep_msg_more = false; // keep_msg was set by msgmore()
@@ -102,7 +102,7 @@ bool keep_msg_more = false; // keep_msg was set by msgmore()
* msg_scrolled How many lines the screen has been scrolled (because of
* messages). Used in update_screen() to scroll the screen
* back. Incremented each time the screen scrolls a line.
- * msg_scrolled_ign TRUE when msg_scrolled is non-zero and msg_puts_attr()
+ * msg_scrolled_ign true when msg_scrolled is non-zero and msg_puts_attr()
* writes something without scrolling should not make
* need_wait_return to be set. This is a hack to make ":ts"
* work without an extra prompt.
@@ -215,7 +215,7 @@ void msg_grid_validate(void)
/// Displays the string 's' on the status line
/// When terminal not initialized (yet) mch_errmsg(..) is used.
///
-/// @return TRUE if wait_return not called
+/// @return true if wait_return() not called
int msg(char *s)
{
return msg_attr_keep(s, 0, false, false);
@@ -265,7 +265,7 @@ void msg_multiline_attr(const char *s, int attr, bool check_int, bool *need_clea
// Print the rest of the message. We know there is no special
// character because strpbrk returned NULL
if (*s != NUL) {
- msg_outtrans_attr((char_u *)s, attr);
+ msg_outtrans_attr(s, attr);
}
}
@@ -305,7 +305,7 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline)
// Skip messages not match ":filter pattern".
// Don't filter when there is an error.
- if (!emsg_on_display && message_filtered((char_u *)s)) {
+ if (!emsg_on_display && message_filtered((char *)s)) {
return true;
}
@@ -319,13 +319,13 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline)
* break this loop, limit the recursiveness to 3 levels.
*/
if (entered >= 3) {
- return TRUE;
+ return true;
}
entered++;
// Add message to history (unless it's a repeated kept message or a
// truncated message)
- if ((const char_u *)s != keep_msg
+ if (s != keep_msg
|| (*s != '<'
&& last_msg_hist != NULL
&& last_msg_hist->msg != NULL
@@ -335,7 +335,7 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline)
// Truncate the message if needed.
msg_start();
- buf = msg_strtrunc((char_u *)s, FALSE);
+ buf = msg_strtrunc((char_u *)s, false);
if (buf != NULL) {
s = (const char *)buf;
}
@@ -344,7 +344,7 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline)
if (multiline) {
msg_multiline_attr(s, attr, false, &need_clear);
} else {
- msg_outtrans_attr((char_u *)s, attr);
+ msg_outtrans_attr(s, attr);
}
if (need_clear) {
msg_clr_eos();
@@ -420,7 +420,7 @@ void trunc_string(char *s, char *buf, int room_in, int buflen)
half = room / 2;
// First part: Start of the string.
- for (e = 0; len < half && e < buflen; ++e) {
+ for (e = 0; len < half && e < buflen; e++) {
if (s[e] == NUL) {
// text fits without truncating!
buf[e] = NUL;
@@ -634,18 +634,18 @@ void msg_source(int attr)
recursive = false;
}
-/// @return TRUE if not giving error messages right now:
+/// @return true if not giving error messages right now:
/// If "emsg_off" is set: no error messages at the moment.
/// If "msg" is in 'debug': do error message but without side effects.
/// If "emsg_skip" is set: never do error messages.
int emsg_not_now(void)
{
- if ((emsg_off > 0 && vim_strchr((char *)p_debug, 'm') == NULL
- && vim_strchr((char *)p_debug, 't') == NULL)
+ if ((emsg_off > 0 && vim_strchr(p_debug, 'm') == NULL
+ && vim_strchr(p_debug, 't') == NULL)
|| emsg_skip > 0) {
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
static bool emsg_multiline(const char *s, bool multiline)
@@ -665,7 +665,7 @@ static bool emsg_multiline(const char *s, bool multiline)
bool severe = emsg_severe;
emsg_severe = false;
- if (!emsg_off || vim_strchr((char *)p_debug, 't') != NULL) {
+ if (!emsg_off || vim_strchr(p_debug, 't') != NULL) {
// Cause a throw of an error exception if appropriate. Don't display
// the error message in this case. (If no matching catch clause will
// be found, the message will be displayed later on.) "ignore" is set
@@ -745,7 +745,7 @@ static bool emsg_multiline(const char *s, bool multiline)
attr = HL_ATTR(HLF_E); // set highlight mode for error messages
if (msg_scrolled != 0) {
need_wait_return = true; // needed in case emsg() is called after
- } // wait_return has reset need_wait_return
+ } // wait_return() has reset need_wait_return
// and a redraw is expected because
// msg_scrolled is non-zero
if (msg_ext_kind == NULL) {
@@ -766,7 +766,7 @@ static bool emsg_multiline(const char *s, bool multiline)
/// Rings the bell, if appropriate, and calls message() to do the real work
/// When terminal not initialized (yet) mch_errmsg(..) is used.
///
-/// @return true if wait_return not called
+/// @return true if wait_return() not called
bool emsg(const char *s)
{
return emsg_multiline(s, false);
@@ -1086,7 +1086,7 @@ void ex_messages(void *const eap_p)
HlMessageChunk chunk = kv_A(p->multiattr, i);
Array content_entry = ARRAY_DICT_INIT;
ADD(content_entry, INTEGER_OBJ(chunk.attr));
- ADD(content_entry, STRING_OBJ(copy_string(chunk.text)));
+ ADD(content_entry, STRING_OBJ(copy_string(chunk.text, NULL)));
ADD(content, ARRAY_OBJ(content_entry));
}
} else if (p->msg && p->msg[0]) {
@@ -1131,7 +1131,7 @@ void msg_end_prompt(void)
/// Wait for the user to hit a key (normally Enter)
///
-/// @param redraw if true, redraw the entire screen NOT_VALID
+/// @param redraw if true, redraw the entire screen UPD_NOT_VALID
/// if false, do a normal redraw
/// if -1, don't redraw at all
void wait_return(int redraw)
@@ -1143,7 +1143,7 @@ void wait_return(int redraw)
FILE *save_scriptout;
if (redraw == true) {
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
}
// If using ":silent cmd", don't wait for a return. Also don't set
@@ -1177,12 +1177,12 @@ void wait_return(int redraw)
oldState = State;
if (quit_more) {
c = CAR; // just pretend CR was hit
- quit_more = FALSE;
- got_int = FALSE;
+ quit_more = false;
+ got_int = false;
} else if (exmode_active) {
msg_puts(" "); // make sure the cursor is on the right line
c = CAR; // no need for a return in ex mode
- got_int = FALSE;
+ got_int = false;
} else {
// Make sure the hit-return prompt is on screen when 'guioptions' was
// just changed.
@@ -1247,8 +1247,8 @@ void wait_return(int redraw)
}
if (quit_more) {
c = CAR; // just pretend CR was hit
- quit_more = FALSE;
- got_int = FALSE;
+ quit_more = false;
+ got_int = false;
} else if (c != K_IGNORE) {
c = K_IGNORE;
hit_return_msg();
@@ -1307,7 +1307,7 @@ void wait_return(int redraw)
emsg_on_display = false; // can delete error message now
lines_left = -1; // reset lines_left at next msg_start()
reset_last_sourcing();
- if (keep_msg != NULL && vim_strsize((char *)keep_msg) >=
+ if (keep_msg != NULL && vim_strsize(keep_msg) >=
(Rows - cmdline_row - 1) * Columns + sc_col) {
XFREE_CLEAR(keep_msg); // don't redisplay message, it's too long
}
@@ -1316,7 +1316,7 @@ void wait_return(int redraw)
ui_refresh();
} else if (!skip_redraw) {
if (redraw == true || (msg_scrolled != 0 && redraw != -1)) {
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
}
if (ui_has(kUIMessages)) {
msg_ext_clear(true);
@@ -1350,7 +1350,7 @@ void set_keep_msg(char *s, int attr)
{
xfree(keep_msg);
if (s != NULL && msg_silent == 0) {
- keep_msg = vim_strsave((char_u *)s);
+ keep_msg = xstrdup(s);
} else {
keep_msg = NULL;
}
@@ -1510,7 +1510,7 @@ void msg_home_replace_hl(char_u *fname)
static void msg_home_replace_attr(char_u *fname, int attr)
{
char *name = home_replace_save(NULL, (char *)fname);
- msg_outtrans_attr((char_u *)name, attr);
+ msg_outtrans_attr(name, attr);
xfree(name);
}
@@ -1521,29 +1521,29 @@ static void msg_home_replace_attr(char_u *fname, int attr)
/// @return the number of characters it takes on the screen.
int msg_outtrans(char *str)
{
- return msg_outtrans_attr((char_u *)str, 0);
+ return msg_outtrans_attr(str, 0);
}
-int msg_outtrans_attr(const char_u *str, int attr)
+int msg_outtrans_attr(const char *str, int attr)
{
- return msg_outtrans_len_attr(str, (int)STRLEN(str), attr);
+ return msg_outtrans_len_attr((char_u *)str, (int)STRLEN(str), attr);
}
-int msg_outtrans_len(const char_u *str, int len)
+int msg_outtrans_len(const char *str, int len)
{
- return msg_outtrans_len_attr(str, len, 0);
+ return msg_outtrans_len_attr((char_u *)str, len, 0);
}
/// Output one character at "p".
/// Handles multi-byte characters.
///
/// @return pointer to the next character.
-char_u *msg_outtrans_one(char_u *p, int attr)
+char *msg_outtrans_one(char *p, int attr)
{
int l;
- if ((l = utfc_ptr2len((char *)p)) > 1) {
- msg_outtrans_len_attr(p, l, attr);
+ if ((l = utfc_ptr2len(p)) > 1) {
+ msg_outtrans_len_attr((char_u *)p, l, attr);
return p + l;
}
msg_puts_attr((const char *)transchar_byte(*p), attr);
@@ -1628,12 +1628,13 @@ int msg_outtrans_len_attr(const char_u *msgstr, int len, int attr)
return retval;
}
-void msg_make(char_u *arg)
+void msg_make(char *arg)
{
int i;
- static char_u *str = (char_u *)"eeffoc", *rs = (char_u *)"Plon#dqg#vxjduB";
+ static char *str = "eeffoc";
+ static char *rs = "Plon#dqg#vxjduB";
- arg = (char_u *)skipwhite((char *)arg);
+ arg = skipwhite(arg);
for (i = 5; *arg && i >= 0; i--) {
if (*arg++ != str[i]) {
break;
@@ -1641,7 +1642,7 @@ void msg_make(char_u *arg)
}
if (i < 0) {
msg_putchar('\n');
- for (i = 0; rs[i]; ++i) {
+ for (i = 0; rs[i]; i++) {
msg_putchar(rs[i] - 3);
}
}
@@ -1653,7 +1654,7 @@ void msg_make(char_u *arg)
/// If K_SPECIAL is encountered, then it is taken in conjunction with the
/// following character and shown as <F1>, <S-Up> etc. Any other character
/// which is not printable shown in <> form.
-/// If 'from' is TRUE (lhs of a mapping), a space is shown as <Space>.
+/// If 'from' is true (lhs of a mapping), a space is shown as <Space>.
/// If a character is displayed in one of these special ways, is also
/// highlighted (its highlight name is '8' in the p_hl variable).
/// Otherwise characters are not highlighted.
@@ -1976,13 +1977,13 @@ void msg_prt_line(char_u *s, int list)
/// Use grid_puts() to output one multi-byte character.
///
/// @return the pointer "s" advanced to the next character.
-static char_u *screen_puts_mbyte(char_u *s, int l, int attr)
+static char *screen_puts_mbyte(char *s, int l, int attr)
{
int cw;
attr = hl_combine_attr(HL_ATTR(HLF_MSG), attr);
msg_didout = true; // remember that line is not empty
- cw = utf_ptr2cells((char *)s);
+ cw = utf_ptr2cells(s);
if (cw > 1
&& (cmdmsg_rl ? msg_col <= 1 : msg_col == Columns - 1)) {
// Doesn't fit, print a highlighted '>' to fill it up.
@@ -2197,7 +2198,7 @@ static void msg_puts_display(const char_u *str, int maxlen, int attr, int recurs
// ourselves).
if (t_col > 0) {
// output postponed text
- t_puts(&t_col, t_s, s, attr);
+ t_puts(&t_col, (char *)t_s, (char *)s, attr);
}
// When no more prompt and no more room, truncate here
@@ -2222,7 +2223,7 @@ static void msg_puts_display(const char_u *str, int maxlen, int attr, int recurs
} else {
l = utfc_ptr2len((char *)s);
}
- s = screen_puts_mbyte((char_u *)s, l, attr);
+ s = (char_u *)screen_puts_mbyte((char *)s, l, attr);
did_last_char = true;
} else {
did_last_char = false;
@@ -2243,7 +2244,7 @@ static void msg_puts_display(const char_u *str, int maxlen, int attr, int recurs
}
inc_msg_scrolled();
- need_wait_return = true; // may need wait_return in main()
+ need_wait_return = true; // may need wait_return() in main()
redraw_cmdline = true;
if (cmdline_row > 0 && !exmode_active) {
cmdline_row--;
@@ -2281,7 +2282,7 @@ static void msg_puts_display(const char_u *str, int maxlen, int attr, int recurs
if (t_col > 0 && (wrap || *s == '\r' || *s == '\b'
|| *s == '\t' || *s == BELL)) {
// Output any postponed text.
- t_puts(&t_col, t_s, s, attr);
+ t_puts(&t_col, (char *)t_s, (char *)s, attr);
}
if (wrap && p_more && !recurse) {
@@ -2324,7 +2325,7 @@ static void msg_puts_display(const char_u *str, int maxlen, int attr, int recurs
// characters and draw them all at once later.
if (cmdmsg_rl || (cw > 1 && msg_col + t_col >= Columns - 1)) {
if (l > 1) {
- s = screen_puts_mbyte((char_u *)s, l, attr) - 1;
+ s = (char_u *)screen_puts_mbyte((char *)s, l, attr) - 1;
} else {
msg_screen_putchar(*s, attr);
}
@@ -2342,7 +2343,7 @@ static void msg_puts_display(const char_u *str, int maxlen, int attr, int recurs
// Output any postponed text.
if (t_col > 0) {
- t_puts(&t_col, t_s, s, attr);
+ t_puts(&t_col, (char *)t_s, (char *)s, attr);
}
if (p_more && !recurse) {
store_sb_text((char **)&sb_str, (char *)s, attr, &sb_col, false);
@@ -2353,13 +2354,13 @@ static void msg_puts_display(const char_u *str, int maxlen, int attr, int recurs
/// @return true when ":filter pattern" was used and "msg" does not match
/// "pattern".
-bool message_filtered(char_u *msg)
+bool message_filtered(char *msg)
{
if (cmdmod.cmod_filter_regmatch.regprog == NULL) {
return false;
}
- bool match = vim_regexec(&cmdmod.cmod_filter_regmatch, (char *)msg, (colnr_T)0);
+ bool match = vim_regexec(&cmdmod.cmod_filter_regmatch, msg, (colnr_T)0);
return cmdmod.cmod_filter_force ? match : !match;
}
@@ -2478,7 +2479,7 @@ void msg_reset_scroll(void)
}
}
} else {
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
}
msg_scrolled = 0;
msg_scrolled_at_flush = 0;
@@ -2506,8 +2507,8 @@ static void inc_msg_scrolled(void)
xfree(tofree);
}
msg_scrolled++;
- if (must_redraw < VALID) {
- must_redraw = VALID;
+ if (must_redraw < UPD_VALID) {
+ must_redraw = UPD_VALID;
}
}
@@ -2557,7 +2558,7 @@ static void store_sb_text(char **sb_str, char *s, int attr, int *sb_col, int fin
}
mp->sb_next = NULL;
} else if (finish && last_msgchunk != NULL) {
- last_msgchunk->sb_eol = TRUE;
+ last_msgchunk->sb_eol = true;
}
*sb_str = s;
@@ -2614,7 +2615,7 @@ void sb_text_end_cmdline(void)
}
/// Clear any text remembered for scrolling back.
-/// When "all" is FALSE keep the last line.
+/// When "all" is false keep the last line.
/// Called when redrawing the screen.
void clear_sb_text(int all)
{
@@ -2649,7 +2650,7 @@ void show_sb_text(void)
vim_beep(BO_MESS);
} else {
do_more_prompt('G');
- wait_return(FALSE);
+ wait_return(false);
}
}
@@ -2668,7 +2669,7 @@ static msgchunk_T *msg_sb_start(msgchunk_T *mps)
void msg_sb_eol(void)
{
if (last_msgchunk != NULL) {
- last_msgchunk->sb_eol = TRUE;
+ last_msgchunk->sb_eol = true;
}
}
@@ -2687,7 +2688,7 @@ static msgchunk_T *disp_sb_line(int row, msgchunk_T *smp)
if (*p == '\n') { // don't display the line break
p++;
}
- msg_puts_display(p, -1, mp->sb_attr, TRUE);
+ msg_puts_display(p, -1, mp->sb_attr, true);
if (mp->sb_eol || mp->sb_next == NULL) {
break;
}
@@ -2698,18 +2699,17 @@ static msgchunk_T *disp_sb_line(int row, msgchunk_T *smp)
}
/// Output any postponed text for msg_puts_attr_len().
-static void t_puts(int *t_col, const char_u *t_s, const char_u *s, int attr)
+static void t_puts(int *t_col, const char *t_s, const char *s, int attr)
{
attr = hl_combine_attr(HL_ATTR(HLF_MSG), attr);
// Output postponed text.
msg_didout = true; // Remember that line is not empty.
- grid_puts_len(&msg_grid_adj, (char_u *)t_s, (int)(s - t_s), msg_row, msg_col,
- attr);
+ grid_puts_len(&msg_grid_adj, (char *)t_s, (int)(s - t_s), msg_row, msg_col, attr);
msg_col += *t_col;
*t_col = 0;
// If the string starts with a composing character don't increment the
// column position for it.
- if (utf_iscomposing(utf_ptr2char((char *)t_s))) {
+ if (utf_iscomposing(utf_ptr2char(t_s))) {
msg_col--;
}
if (msg_col >= Columns) {
@@ -2718,7 +2718,7 @@ static void t_puts(int *t_col, const char_u *t_s, const char_u *s, int attr)
}
}
-/// @return TRUE when messages should be printed to stdout/stderr:
+/// @return true when messages should be printed to stdout/stderr:
/// - "batch mode" ("silent mode", -es/-Es)
/// - no UI and not embedded
int msg_use_printf(void)
@@ -2786,14 +2786,14 @@ static void msg_puts_printf(const char *str, const ptrdiff_t maxlen)
/// When at hit-enter prompt "typed_char" is the already typed character,
/// otherwise it's NUL.
///
-/// @return TRUE when jumping ahead to "confirm_msg_tail".
+/// @return true when jumping ahead to "confirm_msg_tail".
static int do_more_prompt(int typed_char)
{
static bool entered = false;
int used_typed_char = typed_char;
int oldState = State;
int c;
- int retval = FALSE;
+ int retval = false;
int toscroll;
bool to_redraw = false;
msgchunk_T *mp_last = NULL;
@@ -2817,7 +2817,7 @@ static int do_more_prompt(int typed_char)
// "g<": Find first line on the last page.
mp_last = msg_sb_start(last_msgchunk);
for (i = 0; i < Rows - 2 && mp_last != NULL
- && mp_last->sb_prev != NULL; ++i) {
+ && mp_last->sb_prev != NULL; i++) {
mp_last = msg_sb_start(mp_last->sb_prev);
}
}
@@ -2825,7 +2825,7 @@ static int do_more_prompt(int typed_char)
State = MODE_ASKMORE;
setmouse();
if (typed_char == NUL) {
- msg_moremsg(FALSE);
+ msg_moremsg(false);
}
for (;;) {
/*
@@ -2898,10 +2898,10 @@ static int do_more_prompt(int typed_char)
case ESC:
if (confirm_msg_used) {
// Jump to the choices of the dialog.
- retval = TRUE;
+ retval = true;
} else {
- got_int = TRUE;
- quit_more = TRUE;
+ got_int = true;
+ quit_more = true;
}
// When there is some more output (wrapping line) display that
// without another prompt.
@@ -2917,7 +2917,7 @@ static int do_more_prompt(int typed_char)
break;
default: // no valid response
- msg_moremsg(TRUE);
+ msg_moremsg(true);
continue;
}
@@ -2936,8 +2936,7 @@ static int do_more_prompt(int typed_char)
}
// go to start of line at top of the screen
- for (i = 0; i < Rows - 2 && mp != NULL && mp->sb_prev != NULL;
- ++i) {
+ for (i = 0; i < Rows - 2 && mp != NULL && mp->sb_prev != NULL; i++) {
mp = msg_sb_start(mp->sb_prev);
}
@@ -3084,10 +3083,9 @@ void msg_moremsg(int full)
char_u *s = (char_u *)_("-- More --");
attr = hl_combine_attr(HL_ATTR(HLF_MSG), HL_ATTR(HLF_M));
- grid_puts(&msg_grid_adj, s, Rows - 1, 0, attr);
+ grid_puts(&msg_grid_adj, (char *)s, Rows - 1, 0, attr);
if (full) {
- grid_puts(&msg_grid_adj, (char_u *)
- _(" SPACE/d/j: screen/page/line down, b/u/k: up, q: quit "),
+ grid_puts(&msg_grid_adj, _(" SPACE/d/j: screen/page/line down, b/u/k: up, q: quit "),
Rows - 1, vim_strsize((char *)s), attr);
}
}
@@ -3167,9 +3165,9 @@ void msg_clr_cmdline(void)
}
/// end putting a message on the screen
-/// call wait_return if the message does not fit in the available space
+/// call wait_return() if the message does not fit in the available space
///
-/// @return TRUE if wait_return not called.
+/// @return true if wait_return() not called.
int msg_end(void)
{
/*
@@ -3245,8 +3243,8 @@ void msg_ext_clear_later(void)
{
if (msg_ext_is_visible()) {
msg_ext_need_clear = true;
- if (must_redraw < VALID) {
- must_redraw = VALID;
+ if (must_redraw < UPD_VALID) {
+ must_redraw = UPD_VALID;
}
}
}
@@ -3392,7 +3390,7 @@ void verbose_enter_scroll(void)
msg_silent++;
} else {
// always scroll up, don't overwrite
- msg_scroll = TRUE;
+ msg_scroll = true;
}
}
@@ -3415,7 +3413,7 @@ void verbose_stop(void)
fclose(verbose_fd);
verbose_fd = NULL;
}
- verbose_did_open = FALSE;
+ verbose_did_open = false;
}
/// Open the file 'verbosefile'.
@@ -3425,9 +3423,9 @@ int verbose_open(void)
{
if (verbose_fd == NULL && !verbose_did_open) {
// Only give the error message once.
- verbose_did_open = TRUE;
+ verbose_did_open = true;
- verbose_fd = os_fopen((char *)p_vfile, "a");
+ verbose_fd = os_fopen(p_vfile, "a");
if (verbose_fd == NULL) {
semsg(_(e_notopen), p_vfile);
return FAIL;
@@ -3524,7 +3522,7 @@ void msg_advance(int col)
/// different letter.
///
/// @param textfiel IObuff for inputdialog(), NULL otherwise
-/// @param ex_cmd when TRUE pressing : accepts default and starts Ex command
+/// @param ex_cmd when true pressing : accepts default and starts Ex command
/// @returns 0 if cancelled, otherwise the nth button (1-indexed).
int do_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton,
char_u *textfield, int ex_cmd)
@@ -3800,7 +3798,7 @@ int vim_dialog_yesno(int type, char_u *title, char_u *message, int dflt)
if (do_dialog(type,
title == NULL ? (char_u *)_("Question") : title,
message,
- (char_u *)_("&Yes\n&No"), dflt, NULL, FALSE) == 1) {
+ (char_u *)_("&Yes\n&No"), dflt, NULL, false) == 1) {
return VIM_YES;
}
return VIM_NO;
@@ -3811,7 +3809,7 @@ int vim_dialog_yesnocancel(int type, char_u *title, char_u *message, int dflt)
switch (do_dialog(type,
title == NULL ? (char_u *)_("Question") : title,
message,
- (char_u *)_("&Yes\n&No\n&Cancel"), dflt, NULL, FALSE)) {
+ (char_u *)_("&Yes\n&No\n&Cancel"), dflt, NULL, false)) {
case 1:
return VIM_YES;
case 2:
@@ -3826,7 +3824,7 @@ int vim_dialog_yesnoallcancel(int type, char_u *title, char_u *message, int dflt
title == NULL ? (char_u *)"Question" : title,
message,
(char_u *)_("&Yes\n&No\nSave &All\n&Discard All\n&Cancel"),
- dflt, NULL, FALSE)) {
+ dflt, NULL, false)) {
case 1:
return VIM_YES;
case 2:
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index a8d0b3b584..73147204a1 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -179,7 +179,7 @@ retnomove:
}
if (flags & MOUSE_MAY_STOP_VIS) {
end_visual_mode();
- redraw_curbuf_later(INVERTED); // delete the inversion
+ redraw_curbuf_later(UPD_INVERTED); // delete the inversion
}
return IN_BUFFER;
}
@@ -279,7 +279,7 @@ retnomove:
: col >= fdc + (cmdwin_type == 0 && wp == curwin ? 0 : 1))
&& (flags & MOUSE_MAY_STOP_VIS)))) {
end_visual_mode();
- redraw_curbuf_later(INVERTED); // delete the inversion
+ redraw_curbuf_later(UPD_INVERTED); // delete the inversion
}
if (cmdwin_type != 0 && wp != curwin) {
// A click outside the command-line window: Use modeless
@@ -345,7 +345,7 @@ retnomove:
// before moving the cursor for a left click, stop Visual mode
if (flags & MOUSE_MAY_STOP_VIS) {
end_visual_mode();
- redraw_curbuf_later(INVERTED); // delete the inversion
+ redraw_curbuf_later(UPD_INVERTED); // delete the inversion
}
if (grid == 0) {
@@ -374,14 +374,14 @@ retnomove:
if (curwin->w_topfill < win_get_fill(curwin, curwin->w_topline)) {
curwin->w_topfill++;
} else {
- --curwin->w_topline;
+ curwin->w_topline--;
curwin->w_topfill = 0;
}
}
check_topfill(curwin, false);
curwin->w_valid &=
~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
row = 0;
} else if (row >= curwin->w_height_inner) {
count = 0;
@@ -410,7 +410,7 @@ retnomove:
}
}
check_topfill(curwin, false);
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
curwin->w_valid &=
~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
row = curwin->w_height_inner - 1;
@@ -631,14 +631,16 @@ colnr_T vcol2col(win_T *const wp, const linenr_T lnum, const colnr_T vcol)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
// try to advance to the specified column
- char_u *ptr = ml_get_buf(wp->w_buffer, lnum, false);
- char_u *const line = ptr;
- colnr_T count = 0;
- while (count < vcol && *ptr != NUL) {
- count += win_lbr_chartabsize(wp, line, ptr, count, NULL);
- MB_PTR_ADV(ptr);
- }
- return (colnr_T)(ptr - line);
+ char_u *line = ml_get_buf(wp->w_buffer, lnum, false);
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
+ while (cts.cts_vcol < vcol && *cts.cts_ptr != NUL) {
+ cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
+ MB_PTR_ADV(cts.cts_ptr);
+ }
+ clear_chartabsize_arg(&cts);
+
+ return (colnr_T)((char_u *)cts.cts_ptr - line);
}
/// Set UI mouse depending on current mode and 'mouse'.
@@ -667,7 +669,7 @@ static colnr_T scroll_line_len(linenr_T lnum)
char_u *line = ml_get(lnum);
if (*line != NUL) {
for (;;) {
- int numchar = win_chartabsize(curwin, line, col);
+ int numchar = win_chartabsize(curwin, (char *)line, col);
MB_PTR_ADV(line);
if (*line == NUL) { // don't count the last character
break;
@@ -702,8 +704,8 @@ static linenr_T find_longest_lnum(void)
max = len;
ret = lnum;
} else if (len == (colnr_T)max
- && abs((int)(lnum - curwin->w_cursor.lnum))
- < abs((int)(ret - curwin->w_cursor.lnum))) {
+ && abs(lnum - curwin->w_cursor.lnum)
+ < abs(ret - curwin->w_cursor.lnum)) {
ret = lnum;
}
}
@@ -790,7 +792,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
// checked for concealed characters.
vcol = 0;
while (vcol < offset && *ptr != NUL) {
- vcol += win_chartabsize(curwin, ptr, vcol);
+ vcol += win_chartabsize(curwin, (char *)ptr, vcol);
ptr += utfc_ptr2len((char *)ptr);
}
@@ -801,7 +803,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
vcol = offset;
ptr_end = ptr_row_offset;
while (vcol < col && *ptr_end != NUL) {
- vcol += win_chartabsize(curwin, ptr_end, vcol);
+ vcol += win_chartabsize(curwin, (char *)ptr_end, vcol);
ptr_end += utfc_ptr2len((char *)ptr_end);
}
@@ -816,7 +818,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
#define DECR() nudge--; ptr_end -= utfc_ptr2len((char *)ptr_end)
while (ptr < ptr_end && *ptr != NUL) {
- cwidth = win_chartabsize(curwin, ptr, vcol);
+ cwidth = win_chartabsize(curwin, (char *)ptr, vcol);
vcol += cwidth;
if (cwidth > 1 && *ptr == '\t' && nudge > 0) {
// A tab will "absorb" any previous adjustments.
diff --git a/src/nvim/mouse.h b/src/nvim/mouse.h
index 08261e4a30..21ff56bbbc 100644
--- a/src/nvim/mouse.h
+++ b/src/nvim/mouse.h
@@ -36,7 +36,7 @@
#define MOUSE_X2 0x400 // Mouse-button X2
// Direction for nv_mousescroll() and ins_mousescroll()
-#define MSCR_DOWN 0 // DOWN must be FALSE
+#define MSCR_DOWN 0 // DOWN must be false
#define MSCR_UP 1
#define MSCR_LEFT (-1)
#define MSCR_RIGHT (-2)
diff --git a/src/nvim/move.c b/src/nvim/move.c
index 1ed7acd012..b3ec3a8e7a 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -105,7 +105,7 @@ void redraw_for_cursorline(win_T *wp)
if ((wp->w_valid & VALID_CROW) == 0 && !pum_visible()
&& (wp->w_p_rnu || win_cursorline_standout(wp))) {
// win_line() will redraw the number column and cursorline only.
- redraw_later(wp, VALID);
+ redraw_later(wp, UPD_VALID);
}
}
@@ -118,11 +118,11 @@ static void redraw_for_cursorcolumn(win_T *wp)
if ((wp->w_valid & VALID_VIRTCOL) == 0 && !pum_visible()) {
if (wp->w_p_cuc || ((HL_ATTR(HLF_LC) || win_hl_attr(wp, HLF_LC)) && using_hlsearch())) {
// When 'cursorcolumn' is set or "CurSearch" is in use
- // need to redraw with SOME_VALID.
- redraw_later(wp, SOME_VALID);
+ // need to redraw with UPD_SOME_VALID.
+ redraw_later(wp, UPD_SOME_VALID);
} else if (wp->w_p_cul && (wp->w_p_culopt_flags & CULOPT_SCRLINE)) {
- // When 'cursorlineopt' contains "screenline" need to redraw with VALID.
- redraw_later(wp, VALID);
+ // When 'cursorlineopt' contains "screenline" need to redraw with UPD_VALID.
+ redraw_later(wp, UPD_VALID);
}
}
// If the cursor moves horizontally when 'concealcursor' is active, then the
@@ -184,7 +184,7 @@ void update_topline(win_T *wp)
// If the buffer is empty, always set topline to 1.
if (buf_is_empty(curbuf)) { // special case - file is empty
if (wp->w_topline != 1) {
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
}
wp->w_topline = 1;
wp->w_botline = 2;
@@ -336,9 +336,9 @@ void update_topline(win_T *wp)
dollar_vcol = -1;
if (wp->w_skipcol != 0) {
wp->w_skipcol = 0;
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
} else {
- redraw_later(wp, VALID);
+ redraw_later(wp, UPD_VALID);
}
// May need to set w_skipcol when cursor in w_topline.
if (wp->w_cursor.lnum == wp->w_topline) {
@@ -450,7 +450,7 @@ void changed_window_setting_win(win_T *wp)
wp->w_lines_valid = 0;
changed_line_abv_curs_win(wp);
wp->w_valid &= ~(VALID_BOTLINE|VALID_BOTLINE_AP|VALID_TOPLINE);
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
}
/*
@@ -472,7 +472,7 @@ void set_topline(win_T *wp, linenr_T lnum)
}
wp->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_TOPLINE);
// Don't set VALID_TOPLINE here, 'scrolloff' needs to be checked.
- redraw_later(wp, VALID);
+ redraw_later(wp, UPD_VALID);
}
/*
@@ -571,7 +571,7 @@ static void curs_rows(win_T *wp)
|| wp->w_lines[0].wl_lnum > wp->w_topline);
int i = 0;
wp->w_cline_row = 0;
- for (linenr_T lnum = wp->w_topline; lnum < wp->w_cursor.lnum; ++i) {
+ for (linenr_T lnum = wp->w_topline; lnum < wp->w_cursor.lnum; i++) {
bool valid = false;
if (!all_invalid && i < wp->w_lines_valid) {
if (wp->w_lines[i].wl_lnum < lnum || !wp->w_lines[i].wl_valid) {
@@ -587,7 +587,7 @@ static void curs_rows(win_T *wp)
valid = true;
}
} else if (wp->w_lines[i].wl_lnum > lnum) {
- --i; // hold at inserted lines
+ i--; // hold at inserted lines
}
}
if (valid && (lnum != wp->w_topline || !win_may_fill(wp))) {
@@ -847,7 +847,7 @@ void curs_columns(win_T *wp, int may_scroll)
wp->w_leftcol = new_leftcol;
win_check_anchored_floats(wp);
// screen has to be redrawn with new wp->w_leftcol
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
}
}
wp->w_wcol -= wp->w_leftcol;
@@ -954,7 +954,7 @@ void curs_columns(win_T *wp, int may_scroll)
wp->w_skipcol = 0;
}
if (prev_skipcol != wp->w_skipcol) {
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
}
redraw_for_cursorcolumn(curwin);
@@ -1053,7 +1053,7 @@ bool scrolldown(long line_count, int byfold)
if (curwin->w_topline == 1) {
break;
}
- --curwin->w_topline;
+ curwin->w_topline--;
curwin->w_topfill = 0;
// A sequence of folded lines only counts for one logical line
linenr_T first;
@@ -1068,7 +1068,7 @@ bool scrolldown(long line_count, int byfold)
done += plines_win_nofill(curwin, curwin->w_topline, true);
}
}
- --curwin->w_botline; // approximate w_botline
+ curwin->w_botline--; // approximate w_botline
invalidate_botline();
}
curwin->w_wrow += done; // keep w_wrow updated
@@ -1130,7 +1130,7 @@ bool scrollup(long line_count, int byfold)
linenr_T lnum = curwin->w_topline;
while (line_count--) {
if (curwin->w_topfill > 0) {
- --curwin->w_topfill;
+ curwin->w_topfill--;
} else {
if (byfold) {
(void)hasFolding(lnum, NULL, &lnum);
@@ -1187,7 +1187,7 @@ void check_topfill(win_T *wp, bool down)
int n = plines_win_nofill(wp, wp->w_topline, true);
if (wp->w_topfill + n > wp->w_height_inner) {
if (down && wp->w_topline > 1) {
- --wp->w_topline;
+ wp->w_topline--;
wp->w_topfill = 0;
} else {
wp->w_topfill = wp->w_height_inner - n;
@@ -1249,14 +1249,14 @@ void scrolldown_clamp(void)
}
if (end_row < curwin->w_height_inner - get_scrolloff_value(curwin)) {
if (can_fill) {
- ++curwin->w_topfill;
+ curwin->w_topfill++;
check_topfill(curwin, true);
} else {
- --curwin->w_topline;
+ curwin->w_topline--;
curwin->w_topfill = 0;
}
(void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
- --curwin->w_botline; // approximate w_botline
+ curwin->w_botline--; // approximate w_botline
curwin->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE);
}
}
@@ -1309,7 +1309,7 @@ static void topline_back(win_T *wp, lineoff_T *lp)
lp->fill++;
lp->height = 1;
} else {
- --lp->lnum;
+ lp->lnum--;
lp->fill = 0;
if (lp->lnum < 1) {
lp->height = MAXCOL;
@@ -1335,7 +1335,7 @@ static void botline_forw(win_T *wp, lineoff_T *lp)
lp->fill++;
lp->height = 1;
} else {
- ++lp->lnum;
+ lp->lnum++;
lp->fill = 0;
assert(wp->w_buffer != 0);
if (lp->lnum > wp->w_buffer->b_ml.ml_line_count) {
@@ -1726,7 +1726,7 @@ void scroll_cursor_halfway(int atend)
}
below += boff.height;
} else {
- ++below; // count a "~" line
+ below++; // count a "~" line
if (atend) {
used++;
}
@@ -1899,7 +1899,7 @@ int onepage(Direction dir, long count)
if (ONE_WINDOW && p_window > 0 && p_window < Rows - 1) {
// Vi compatible scrolling
if (p_window <= 2) {
- ++curwin->w_topline;
+ curwin->w_topline++;
} else {
curwin->w_topline += (linenr_T)p_window - 2;
}
@@ -1935,7 +1935,7 @@ int onepage(Direction dir, long count)
if (ONE_WINDOW && p_window > 0 && p_window < Rows - 1) {
// Vi compatible scrolling (sort of)
if (p_window <= 2) {
- --curwin->w_topline;
+ curwin->w_topline--;
} else {
curwin->w_topline -= (linenr_T)p_window - 2;
}
@@ -2000,7 +2000,7 @@ int onepage(Direction dir, long count)
max_topfill();
}
if (curwin->w_topfill == loff.fill) {
- --curwin->w_topline;
+ curwin->w_topline--;
curwin->w_topfill = 0;
}
comp_botline(curwin);
@@ -2040,7 +2040,7 @@ int onepage(Direction dir, long count)
}
}
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
return retval;
}
@@ -2144,7 +2144,7 @@ void halfpage(bool flag, linenr_T Prenum)
curwin->w_topfill = win_get_fill(curwin, curwin->w_topline);
if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
- ++curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum++;
curwin->w_valid &=
~(VALID_VIRTCOL|VALID_CHEIGHT|VALID_WCOL);
}
@@ -2177,7 +2177,7 @@ void halfpage(bool flag, linenr_T Prenum)
&& curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
(void)hasFolding(curwin->w_cursor.lnum, NULL,
&curwin->w_cursor.lnum);
- ++curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum++;
}
} else {
curwin->w_cursor.lnum += n;
@@ -2199,7 +2199,7 @@ void halfpage(bool flag, linenr_T Prenum)
if (n < 0 && scrolled > 0) {
break;
}
- --curwin->w_topline;
+ curwin->w_topline--;
(void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
curwin->w_topfill = 0;
}
@@ -2207,7 +2207,7 @@ void halfpage(bool flag, linenr_T Prenum)
VALID_BOTLINE|VALID_BOTLINE_AP);
scrolled += i;
if (curwin->w_cursor.lnum > 1) {
- --curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum--;
curwin->w_valid &= ~(VALID_VIRTCOL|VALID_CHEIGHT|VALID_WCOL);
}
}
@@ -2218,7 +2218,7 @@ void halfpage(bool flag, linenr_T Prenum)
curwin->w_cursor.lnum = 1;
} else if (hasAnyFolding(curwin)) {
while (--n >= 0 && curwin->w_cursor.lnum > 1) {
- --curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum--;
(void)hasFolding(curwin->w_cursor.lnum,
&curwin->w_cursor.lnum, NULL);
}
@@ -2232,7 +2232,7 @@ void halfpage(bool flag, linenr_T Prenum)
check_topfill(curwin, !flag);
cursor_correct();
beginline(BL_SOL | BL_FIX);
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
}
void do_check_cursorbind(void)
@@ -2284,7 +2284,7 @@ void do_check_cursorbind(void)
}
// Correct cursor for multi-byte character.
mb_adjust_cursor();
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
// Only scroll when 'scrollbind' hasn't done this.
if (!curwin->w_p_scb) {
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 1ca68979f4..d22bcb29d5 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -158,7 +158,7 @@ Object rpc_send_call(uint64_t id, const char *method_name, Array args, ArenaMem
}
// frame.result was allocated in an arena
- arena_mem_free(frame.result_mem, &rpc->unpacker->reuse_blk);
+ arena_mem_free(frame.result_mem);
frame.result_mem = NULL;
}
@@ -244,7 +244,7 @@ static void parse_msgpack(Channel *channel)
ui_client_event_raw_line(p->grid_line_event);
} else if (p->ui_handler.fn != NULL && p->result.type == kObjectTypeArray) {
p->ui_handler.fn(p->result.data.array);
- arena_mem_free(arena_finish(&p->arena), &p->reuse_blk);
+ arena_mem_free(arena_finish(&p->arena));
}
} else if (p->type == kMessageTypeResponse) {
ChannelCallFrame *frame = kv_last(channel->rpc.call_stack);
@@ -295,7 +295,7 @@ static void handle_request(Channel *channel, Unpacker *p, Array args)
if (!p->handler.fn) {
send_error(channel, p->type, p->request_id, p->unpack_error.msg);
api_clear_error(&p->unpack_error);
- arena_mem_free(arena_finish(&p->arena), &p->reuse_blk);
+ arena_mem_free(arena_finish(&p->arena));
return;
}
@@ -304,7 +304,8 @@ static void handle_request(Channel *channel, Unpacker *p, Array args)
evdata->channel = channel;
evdata->handler = p->handler;
evdata->args = args;
- evdata->used_mem = arena_finish(&p->arena);
+ evdata->used_mem = p->arena;
+ p->arena = (Arena)ARENA_EMPTY;
evdata->request_id = p->request_id;
channel_incref(channel);
if (p->handler.fast) {
@@ -344,7 +345,8 @@ static void request_event(void **argv)
// channel was closed, abort any pending requests
goto free_ret;
}
- Object result = handler.fn(channel->id, e->args, &error);
+
+ Object result = handler.fn(channel->id, e->args, &e->used_mem, &error);
if (e->type == kMessageTypeRequest || ERROR_SET(&error)) {
// Send the response.
msgpack_packer response;
@@ -355,13 +357,14 @@ static void request_event(void **argv)
&error,
result,
&out_buffer));
- } else {
+ }
+ if (!handler.arena_return) {
api_free_object(result);
}
free_ret:
- // e->args is allocated in an arena
- arena_mem_free(e->used_mem, &channel->rpc.unpacker->reuse_blk);
+ // e->args (and possibly result) are allocated in an arena
+ arena_mem_free(arena_finish(&e->used_mem));
channel_decref(channel);
xfree(e);
api_clear_error(&error);
@@ -624,7 +627,6 @@ static WBuffer *serialize_response(uint64_t channel_id, MessageType type, uint32
1, // responses only go though 1 channel
xfree);
msgpack_sbuffer_clear(sbuffer);
- api_free_object(arg);
return rv;
}
@@ -642,7 +644,7 @@ void rpc_set_client_info(uint64_t id, Dictionary info)
Dictionary rpc_client_info(Channel *chan)
{
- return copy_dictionary(chan->rpc.info);
+ return copy_dictionary(chan->rpc.info, NULL);
}
const char *rpc_client_name(Channel *chan)
diff --git a/src/nvim/msgpack_rpc/channel_defs.h b/src/nvim/msgpack_rpc/channel_defs.h
index e622ebddf5..404e68329a 100644
--- a/src/nvim/msgpack_rpc/channel_defs.h
+++ b/src/nvim/msgpack_rpc/channel_defs.h
@@ -27,7 +27,7 @@ typedef struct {
MsgpackRpcRequestHandler handler;
Array args;
uint32_t request_id;
- ArenaMem used_mem;
+ Arena used_mem;
} RequestEvent;
typedef struct {
diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c
index b252f0998e..532e684f93 100644
--- a/src/nvim/msgpack_rpc/server.c
+++ b/src/nvim/msgpack_rpc/server.c
@@ -216,7 +216,7 @@ bool server_stop(char *endpoint)
watchers.ga_len--;
// Bump v:servername to the next available server, if any.
- if (strequal(addr, (char *)get_vim_var_str(VV_SEND_SERVER))) {
+ if (strequal(addr, get_vim_var_str(VV_SEND_SERVER))) {
set_vservername(&watchers);
}
diff --git a/src/nvim/msgpack_rpc/unpacker.c b/src/nvim/msgpack_rpc/unpacker.c
index c8e9fdd4c3..24480835a1 100644
--- a/src/nvim/msgpack_rpc/unpacker.c
+++ b/src/nvim/msgpack_rpc/unpacker.c
@@ -181,13 +181,11 @@ void unpacker_init(Unpacker *p)
p->unpack_error = (Error)ERROR_INIT;
p->arena = (Arena)ARENA_EMPTY;
- p->reuse_blk = NULL;
}
void unpacker_teardown(Unpacker *p)
{
- arena_mem_free(p->reuse_blk, NULL);
- arena_mem_free(arena_finish(&p->arena), NULL);
+ arena_mem_free(arena_finish(&p->arena));
}
bool unpacker_parse_header(Unpacker *p)
@@ -308,7 +306,7 @@ bool unpacker_advance(Unpacker *p)
p->state = 10;
} else {
p->state = p->type == kMessageTypeResponse ? 1 : 2;
- arena_start(&p->arena, &p->reuse_blk);
+ p->arena = (Arena)ARENA_EMPTY;
}
}
@@ -322,7 +320,7 @@ bool unpacker_advance(Unpacker *p)
goto done;
} else {
// unpack other ui events using mpack_parse()
- arena_start(&p->arena, &p->reuse_blk);
+ p->arena = (Arena)ARENA_EMPTY;
}
}
@@ -416,13 +414,13 @@ redo:
if (p->ui_handler.fn != ui_client_event_grid_line) {
p->state = 12;
if (p->grid_line_event) {
- arena_mem_free(arena_finish(&p->arena), &p->reuse_blk);
+ arena_mem_free(arena_finish(&p->arena));
p->grid_line_event = NULL;
}
return true;
} else {
p->state = 13;
- arena_start(&p->arena, &p->reuse_blk);
+ p->arena = (Arena)ARENA_EMPTY;
p->grid_line_event = arena_alloc(&p->arena, sizeof *p->grid_line_event, true);
g = p->grid_line_event;
}
diff --git a/src/nvim/msgpack_rpc/unpacker.h b/src/nvim/msgpack_rpc/unpacker.h
index f39439be63..35048fb877 100644
--- a/src/nvim/msgpack_rpc/unpacker.h
+++ b/src/nvim/msgpack_rpc/unpacker.h
@@ -32,8 +32,6 @@ struct Unpacker {
Error unpack_error;
Arena arena;
- // one length free-list of reusable blocks
- ArenaMem reuse_blk;
int nevents;
int ncalls;
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 2c7dadad0b..47ad000385 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -65,6 +65,8 @@
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/tag.h"
+#include "nvim/textformat.h"
+#include "nvim/textobject.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/vim.h"
@@ -523,7 +525,7 @@ static bool normal_handle_special_visual_command(NormalState *s)
&& (nv_cmds[s->idx].cmd_flags & NV_STS)
&& !(mod_mask & MOD_MASK_SHIFT)) {
end_visual_mode();
- redraw_curbuf_later(INVERTED);
+ redraw_curbuf_later(UPD_INVERTED);
}
// Keys that work different when 'keymodel' contains "startsel"
@@ -629,16 +631,16 @@ static void normal_redraw_mode_message(NormalState *s)
if (must_redraw && keep_msg != NULL && !emsg_on_display) {
char_u *kmsg;
- kmsg = keep_msg;
+ kmsg = (char_u *)keep_msg;
keep_msg = NULL;
// Showmode() will clear keep_msg, but we want to use it anyway.
// First update w_topline.
setcursor();
update_screen(0);
// now reset it, otherwise it's put in the history again
- keep_msg = kmsg;
+ keep_msg = (char *)kmsg;
- kmsg = vim_strsave(keep_msg);
+ kmsg = vim_strsave((char_u *)keep_msg);
msg_attr((const char *)kmsg, keep_msg_attr);
xfree(kmsg);
}
@@ -1281,7 +1283,7 @@ static void normal_redraw(NormalState *s)
validate_cursor();
if (VIsual_active) {
- redraw_curbuf_later(INVERTED); // update inverted part
+ redraw_curbuf_later(UPD_INVERTED); // update inverted part
update_screen(0);
} else if (must_redraw) {
update_screen(0);
@@ -1300,7 +1302,7 @@ static void normal_redraw(NormalState *s)
// Display message after redraw. If an external message is still visible,
// it contains the kept message already.
if (keep_msg != NULL && !msg_ext_is_visible()) {
- char_u *const p = vim_strsave(keep_msg);
+ char *const p = xstrdup(keep_msg);
// msg_start() will set keep_msg to NULL, make a copy
// first. Don't reset keep_msg, msg_attr_keep() uses it to
@@ -1838,7 +1840,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
}
if (jump_flags) {
jump_flags = jump_to_mouse(jump_flags, NULL, which_button);
- redraw_curbuf_later(VIsual_active ? INVERTED : VALID);
+ redraw_curbuf_later(VIsual_active ? UPD_INVERTED : UPD_VALID);
update_screen(0);
setcursor();
ui_flush(); // Update before showing popup menu
@@ -2186,7 +2188,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
curwin->w_set_curswant = true;
}
if (is_click) {
- redraw_curbuf_later(INVERTED); // update the inversion
+ redraw_curbuf_later(UPD_INVERTED); // update the inversion
}
} else if (VIsual_active && !old_active) {
if (mod_mask & MOD_MASK_ALT) {
@@ -2311,7 +2313,7 @@ void reset_VIsual_and_resel(void)
{
if (VIsual_active) {
end_visual_mode();
- redraw_curbuf_later(INVERTED); // delete the inversion later
+ redraw_curbuf_later(UPD_INVERTED); // delete the inversion later
}
VIsual_reselect = false;
}
@@ -2321,7 +2323,7 @@ void reset_VIsual(void)
{
if (VIsual_active) {
end_visual_mode();
- redraw_curbuf_later(INVERTED); // delete the inversion later
+ redraw_curbuf_later(UPD_INVERTED); // delete the inversion later
VIsual_reselect = false;
}
}
@@ -2652,8 +2654,8 @@ void clear_showcmd(void)
lines = bot - top + 1;
if (VIsual_mode == Ctrl_V) {
- char_u *const saved_sbr = p_sbr;
- char_u *const saved_w_sbr = curwin->w_p_sbr;
+ char *const saved_sbr = p_sbr;
+ char *const saved_w_sbr = curwin->w_p_sbr;
// Make 'sbr' empty for a moment to get the correct size.
p_sbr = empty_option;
@@ -2716,8 +2718,6 @@ void clear_showcmd(void)
/// @return true if output has been written (and setcursor() has been called).
bool add_to_showcmd(int c)
{
- char_u *p;
- int i;
static int ignore[] = {
K_IGNORE,
K_LEFTMOUSE, K_LEFTDRAG, K_LEFTRELEASE, K_MOUSEMOVE,
@@ -2740,14 +2740,14 @@ bool add_to_showcmd(int c)
// Ignore keys that are scrollbar updates and mouse clicks
if (IS_SPECIAL(c)) {
- for (i = 0; ignore[i] != 0; i++) {
+ for (int i = 0; ignore[i] != 0; i++) {
if (ignore[i] == c) {
return false;
}
}
}
- p = transchar(c);
+ char *p = (char *)transchar(c);
if (*p == ' ') {
STRCPY(p, "<20>");
}
@@ -2843,12 +2843,12 @@ static void display_showcmd(void)
grid_puts_line_start(&msg_grid_adj, showcmd_row);
if (!showcmd_is_clear) {
- grid_puts(&msg_grid_adj, showcmd_buf, showcmd_row, sc_col,
+ grid_puts(&msg_grid_adj, (char *)showcmd_buf, showcmd_row, sc_col,
HL_ATTR(HLF_MSG));
}
// clear the rest of an old message by outputting up to SHOWCMD_COLS spaces
- grid_puts(&msg_grid_adj, (char_u *)" " + len, showcmd_row,
+ grid_puts(&msg_grid_adj, (char *)" " + len, showcmd_row,
sc_col + len, HL_ATTR(HLF_MSG));
grid_puts_line_flush(false);
@@ -2956,7 +2956,7 @@ void check_scrollbind(linenr_T topline_diff, long leftcol_diff)
}
}
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
cursor_correct();
curwin->w_redr_status = true;
}
@@ -3490,7 +3490,7 @@ void scroll_redraw(int up, long count)
if (moved) {
curwin->w_viewport_invalid = true;
}
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
}
/// Get the count specified after a 'z' command. Only the 'z<CR>', 'zl', 'zh',
@@ -3656,7 +3656,7 @@ static void nv_zet(cmdarg_T *cap)
case 't':
scroll_cursor_top(0, true);
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
set_fraction(curwin);
break;
@@ -3667,7 +3667,7 @@ static void nv_zet(cmdarg_T *cap)
case 'z':
scroll_cursor_halfway(true);
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
set_fraction(curwin);
break;
@@ -3690,7 +3690,7 @@ static void nv_zet(cmdarg_T *cap)
case 'b':
scroll_cursor_bot(0, true);
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
set_fraction(curwin);
break;
@@ -3742,7 +3742,7 @@ static void nv_zet(cmdarg_T *cap)
}
if (curwin->w_leftcol != col) {
curwin->w_leftcol = col;
- redraw_later(curwin, NOT_VALID);
+ redraw_later(curwin, UPD_NOT_VALID);
}
}
break;
@@ -3763,7 +3763,7 @@ static void nv_zet(cmdarg_T *cap)
}
if (curwin->w_leftcol != col) {
curwin->w_leftcol = col;
- redraw_later(curwin, NOT_VALID);
+ redraw_later(curwin, UPD_NOT_VALID);
}
}
break;
@@ -4098,7 +4098,7 @@ static void nv_clear(cmdarg_T *cap)
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
wp->w_s->b_syn_slow = false;
}
- redraw_later(curwin, CLEAR);
+ redraw_later(curwin, UPD_CLEAR);
}
}
@@ -4275,14 +4275,13 @@ static void nv_ident(cmdarg_T *cap)
// Allocate buffer to put the command in. Inserting backslashes can
// double the length of the word. p_kp / curbuf->b_p_kp could be added
// and some numbers.
- char_u *kp = *curbuf->b_p_kp == NUL ? p_kp : curbuf->b_p_kp; // 'keywordprg'
- assert(*kp != NUL); // option.c:do_set() should default to ":help" if empty.
- bool kp_ex = (*kp == ':'); // 'keywordprg' is an ex command
- bool kp_help = (STRCMP(kp, ":he") == 0 || STRCMP(kp, ":help") == 0);
+ char_u *kp = *curbuf->b_p_kp == NUL ? p_kp : (char_u *)curbuf->b_p_kp; // 'keywordprg'
+ bool kp_help = (*kp == NUL || STRCMP(kp, ":he") == 0 || STRCMP(kp, ":help") == 0);
if (kp_help && *skipwhite(ptr) == NUL) {
emsg(_(e_noident)); // found white space only
return;
}
+ bool kp_ex = (*kp == ':'); // 'keywordprg' is an ex command
size_t buf_size = n * 2 + 30 + STRLEN(kp);
char *buf = xmalloc(buf_size);
buf[0] = NUL;
@@ -4391,8 +4390,7 @@ static void nv_ident(cmdarg_T *cap)
init_history();
add_to_history(HIST_SEARCH, (char_u *)buf, true, NUL);
- (void)normal_search(cap, cmdchar == '*' ? '/' : '?', (char_u *)buf, 0,
- NULL);
+ (void)normal_search(cap, cmdchar == '*' ? '/' : '?', buf, 0, NULL);
} else {
g_tag_at_cursor = true;
do_cmdline_cmd(buf);
@@ -4566,9 +4564,9 @@ static void nv_right(cmdarg_T *cap)
// <Space> wraps to next line if 'whichwrap' has 's'.
// 'l' wraps to next line if 'whichwrap' has 'l'.
// CURS_RIGHT wraps to next line if 'whichwrap' has '>'.
- if (((cap->cmdchar == ' ' && vim_strchr((char *)p_ww, 's') != NULL)
- || (cap->cmdchar == 'l' && vim_strchr((char *)p_ww, 'l') != NULL)
- || (cap->cmdchar == K_RIGHT && vim_strchr((char *)p_ww, '>') != NULL))
+ if (((cap->cmdchar == ' ' && vim_strchr(p_ww, 's') != NULL)
+ || (cap->cmdchar == 'l' && vim_strchr(p_ww, 'l') != NULL)
+ || (cap->cmdchar == K_RIGHT && vim_strchr(p_ww, '>') != NULL))
&& curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
// When deleting we also count the NL as a character.
// Set cap->oap->inclusive when last char in the line is
@@ -4636,9 +4634,9 @@ static void nv_left(cmdarg_T *cap)
// 'h' wraps to previous line if 'whichwrap' has 'h'.
// CURS_LEFT wraps to previous line if 'whichwrap' has '<'.
if ((((cap->cmdchar == K_BS || cap->cmdchar == Ctrl_H)
- && vim_strchr((char *)p_ww, 'b') != NULL)
- || (cap->cmdchar == 'h' && vim_strchr((char *)p_ww, 'h') != NULL)
- || (cap->cmdchar == K_LEFT && vim_strchr((char *)p_ww, '<') != NULL))
+ && vim_strchr(p_ww, 'b') != NULL)
+ || (cap->cmdchar == 'h' && vim_strchr(p_ww, 'h') != NULL)
+ || (cap->cmdchar == K_LEFT && vim_strchr(p_ww, '<') != NULL))
&& curwin->w_cursor.lnum > 1) {
curwin->w_cursor.lnum--;
coladvance(MAXCOL);
@@ -4805,7 +4803,7 @@ static void nv_search(cmdarg_T *cap)
// When using 'incsearch' the cursor may be moved to set a different search
// start position.
- cap->searchbuf = getcmdline(cap->cmdchar, cap->count1, 0, true);
+ cap->searchbuf = (char *)getcmdline(cap->cmdchar, cap->count1, 0, true);
if (cap->searchbuf == NULL) {
clearop(oap);
@@ -4841,9 +4839,8 @@ static void nv_next(cmdarg_T *cap)
/// @param opt extra flags for do_search()
///
/// @return 0 for failure, 1 for found, 2 for found and line offset added.
-static int normal_search(cmdarg_T *cap, int dir, char_u *pat, int opt, int *wrapped)
+static int normal_search(cmdarg_T *cap, int dir, char *pat, int opt, int *wrapped)
{
- int i;
searchit_arg_T sia;
cap->oap->motion_type = kMTCharWise;
@@ -4852,8 +4849,8 @@ static int normal_search(cmdarg_T *cap, int dir, char_u *pat, int opt, int *wrap
curwin->w_set_curswant = true;
CLEAR_FIELD(sia);
- i = do_search(cap->oap, dir, dir, pat, cap->count1,
- opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, &sia);
+ int i = do_search(cap->oap, dir, dir, (char_u *)pat, cap->count1,
+ opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, &sia);
if (wrapped != NULL) {
*wrapped = sia.sa_wrapped;
}
@@ -5552,7 +5549,7 @@ static void n_swapchar(cmdarg_T *cap)
return;
}
- if (LINEEMPTY(curwin->w_cursor.lnum) && vim_strchr((char *)p_ww, '~') == NULL) {
+ if (LINEEMPTY(curwin->w_cursor.lnum) && vim_strchr(p_ww, '~') == NULL) {
clearopbeep(cap->oap);
return;
}
@@ -5568,7 +5565,7 @@ static void n_swapchar(cmdarg_T *cap)
did_change |= swapchar(cap->oap->op_type, &curwin->w_cursor);
inc_cursor();
if (gchar_cursor() == NUL) {
- if (vim_strchr((char *)p_ww, '~') != NULL
+ if (vim_strchr(p_ww, '~') != NULL
&& curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
curwin->w_cursor.lnum++;
curwin->w_cursor.col = 0;
@@ -5624,7 +5621,7 @@ static MarkMoveRes nv_mark_move_to(cmdarg_T *cap, MarkMove flags, fmark_T *fm)
/// Handle commands that are operators in Visual mode.
static void v_visop(cmdarg_T *cap)
{
- static char_u trans[] = "YyDdCcxdXdAAIIrr";
+ static char trans[] = "YyDdCcxdXdAAIIrr";
// Uppercase means linewise, except in block mode, then "D" deletes till
// the end of the line, and "C" replaces till EOL
@@ -5636,7 +5633,7 @@ static void v_visop(cmdarg_T *cap)
curwin->w_curswant = MAXCOL;
}
}
- cap->cmdchar = (uint8_t)(*(vim_strchr((char *)trans, cap->cmdchar) + 1));
+ cap->cmdchar = (uint8_t)(*(vim_strchr(trans, cap->cmdchar) + 1));
nv_operator(cap);
}
@@ -5819,7 +5816,7 @@ static void nv_visual(cmdarg_T *cap)
showmode();
may_trigger_modechanged();
}
- redraw_curbuf_later(INVERTED); // update the inversion
+ redraw_curbuf_later(UPD_INVERTED); // update the inversion
} else { // start Visual mode
if (cap->count0 > 0 && resel_VIsual_mode != NUL) {
// use previously selected part
@@ -5865,7 +5862,7 @@ static void nv_visual(cmdarg_T *cap)
} else {
curwin->w_set_curswant = true;
}
- redraw_curbuf_later(INVERTED); // show the inversion
+ redraw_curbuf_later(UPD_INVERTED); // show the inversion
} else {
if (!cap->arg) {
// start Select mode when 'selectmode' contains "cmd"
@@ -5900,7 +5897,7 @@ void start_selection(void)
void may_start_select(int c)
{
VIsual_select = (c == 'o' || (stuff_empty() && typebuf_typed()))
- && vim_strchr((char *)p_slm, c) != NULL;
+ && vim_strchr(p_slm, c) != NULL;
}
/// Start Visual mode "c".
@@ -5931,7 +5928,7 @@ static void n_start_visual_mode(int c)
}
// Only need to redraw this line, unless still need to redraw an old
// Visual area (when 'lazyredraw' is set).
- if (curwin->w_redr_type < INVERTED) {
+ if (curwin->w_redr_type < UPD_INVERTED) {
curwin->w_old_cursor_lnum = curwin->w_cursor.lnum;
curwin->w_old_visual_lnum = curwin->w_cursor.lnum;
}
@@ -6018,7 +6015,7 @@ static void nv_gv_cmd(cmdarg_T *cap)
may_start_select('c');
}
setmouse();
- redraw_curbuf_later(INVERTED);
+ redraw_curbuf_later(UPD_INVERTED);
showmode();
}
@@ -6901,7 +6898,7 @@ static void nv_normal(cmdarg_T *cap)
}
if (VIsual_active) {
end_visual_mode(); // stop Visual
- redraw_curbuf_later(INVERTED);
+ redraw_curbuf_later(UPD_INVERTED);
}
} else {
clearopbeep(cap->oap);
@@ -6955,7 +6952,7 @@ static void nv_esc(cmdarg_T *cap)
end_visual_mode(); // stop Visual
check_cursor_col(); // make sure cursor is not beyond EOL
curwin->w_set_curswant = true;
- redraw_curbuf_later(INVERTED);
+ redraw_curbuf_later(UPD_INVERTED);
} else if (no_reason) {
vim_beep(BO_ESC);
}
@@ -7075,8 +7072,8 @@ static void nv_object(cmdarg_T *cap)
include = true; // "ax" = an object: include white space
}
// Make sure (), [], {} and <> are in 'matchpairs'
- mps_save = curbuf->b_p_mps;
- curbuf->b_p_mps = (char_u *)"(:),{:},[:],<:>";
+ mps_save = (char_u *)curbuf->b_p_mps;
+ curbuf->b_p_mps = "(:),{:},[:],<:>";
switch (cap->nchar) {
case 'w': // "aw" = a word
@@ -7130,7 +7127,7 @@ static void nv_object(cmdarg_T *cap)
break;
}
- curbuf->b_p_mps = mps_save;
+ curbuf->b_p_mps = (char *)mps_save;
if (!flag) {
clearopbeep(cap->oap);
}
diff --git a/src/nvim/normal.h b/src/nvim/normal.h
index 9bda70eacd..13ea233658 100644
--- a/src/nvim/normal.h
+++ b/src/nvim/normal.h
@@ -57,7 +57,7 @@ typedef struct oparg_S {
* Arguments for Normal mode commands.
*/
typedef struct cmdarg_S {
- oparg_T *oap; // Operator arguments
+ oparg_T *oap; // Operator arguments
int prechar; // prefix character (optional, always 'g')
int cmdchar; // command character
int nchar; // next command character (optional)
@@ -69,7 +69,7 @@ typedef struct cmdarg_S {
long count1; // count before command, default 1
int arg; // extra argument from nv_cmds[]
int retval; // return: CA_* values
- char_u *searchbuf; // return: pointer to search pattern or NULL
+ char *searchbuf; // return: pointer to search pattern or NULL
} cmdarg_T;
// values for retval:
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 889cc4f5bc..10a25a9b18 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -52,6 +52,7 @@
#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/terminal.h"
+#include "nvim/textformat.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/vim.h"
@@ -95,9 +96,9 @@ struct block_def {
colnr_T textcol; // index of chars (partially) in block
colnr_T start_vcol; // start col of 1st char wholly inside block
colnr_T end_vcol; // start col of 1st char wholly after block
- int is_short; // TRUE if line is too short to fit in block
- int is_MAX; // TRUE if curswant==MAXCOL when starting
- int is_oneChar; // TRUE if block within one character
+ int is_short; // true if line is too short to fit in block
+ int is_MAX; // true if curswant==MAXCOL when starting
+ int is_oneChar; // true if block within one character
int pre_whitesp; // screen cols of ws before block
int pre_whitesp_c; // chars of ws before block
colnr_T end_char_vcols; // number of vcols of post-block char
@@ -198,13 +199,13 @@ int get_op_type(int char1, int char2)
return i;
}
-/// @return TRUE if operator "op" always works on whole lines.
+/// @return true if operator "op" always works on whole lines.
int op_on_lines(int op)
{
return opchars[op][2] & OPF_LINES;
}
-/// @return TRUE if operator "op" changes text.
+/// @return true if operator "op" changes text.
int op_is_change(int op)
{
return opchars[op][2] & OPF_CHANGE;
@@ -251,7 +252,7 @@ void op_shift(oparg_T *oap, int curs_top, int amount)
// isn't set or 'cindent' isn't set or '#' isn't in 'cino'.
shift_line(oap->op_type == OP_LSHIFT, p_sr, amount, false);
}
- ++curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum++;
}
if (oap->motion_type == kMTBlockWise) {
@@ -261,7 +262,7 @@ void op_shift(oparg_T *oap, int curs_top, int amount)
curwin->w_cursor.lnum = oap->start.lnum;
beginline(BL_SOL | BL_FIX); // shift_line() may have set cursor.col
} else {
- --curwin->w_cursor.lnum; // put cursor on last line, for ":>"
+ curwin->w_cursor.lnum--; // put cursor on last line, for ":>"
}
// The cursor line is not in a closed fold
foldOpenCursor();
@@ -394,12 +395,20 @@ static void shift_block(oparg_T *oap, int amount)
bd.startspaces = 0;
}
}
- for (; ascii_iswhite(*bd.textstart);) {
- // TODO(fmoralesc): is passing bd.textstart for start of the line OK?
- incr = lbr_chartabsize_adv(bd.textstart, &bd.textstart, bd.start_vcol);
+
+ // TODO(vim): is passing bd.textstart for start of the line OK?
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum,
+ bd.start_vcol, bd.textstart, bd.textstart);
+ while (ascii_iswhite(*cts.cts_ptr)) {
+ incr = lbr_chartabsize_adv(&cts);
total += incr;
- bd.start_vcol += incr;
+ cts.cts_vcol += incr;
}
+ bd.textstart = (char_u *)cts.cts_ptr;
+ bd.start_vcol = cts.cts_vcol;
+ clear_chartabsize_arg(&cts);
+
// OK, now total=all the VWS reqd, and textstart points at the 1st
// non-ws char in the block.
if (!curbuf->b_p_et) {
@@ -454,10 +463,16 @@ static void shift_block(oparg_T *oap, int amount)
// The character's column is in "bd.start_vcol".
colnr_T non_white_col = bd.start_vcol;
- while (ascii_iswhite(*non_white)) {
- incr = lbr_chartabsize_adv(bd.textstart, &non_white, non_white_col);
- non_white_col += incr;
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum,
+ non_white_col, bd.textstart, non_white);
+ while (ascii_iswhite(*cts.cts_ptr)) {
+ incr = lbr_chartabsize_adv(&cts);
+ cts.cts_vcol += incr;
}
+ non_white_col = cts.cts_vcol;
+ non_white = (char_u *)cts.cts_ptr;
+ clear_chartabsize_arg(&cts);
const colnr_T block_space_width = non_white_col - oap->start_vcol;
// We will shift by "total" or "block_space_width", whichever is less.
@@ -478,17 +493,19 @@ static void shift_block(oparg_T *oap, int amount)
if (bd.startspaces) {
verbatim_copy_width -= bd.start_char_vcols;
}
- while (verbatim_copy_width < destination_col) {
- char_u *line = verbatim_copy_end;
-
- // TODO: is passing verbatim_copy_end for start of the line OK?
- incr = lbr_chartabsize(line, verbatim_copy_end, verbatim_copy_width);
- if (verbatim_copy_width + incr > destination_col) {
+ init_chartabsize_arg(&cts, curwin, 0, verbatim_copy_width,
+ bd.textstart, verbatim_copy_end);
+ while (cts.cts_vcol < destination_col) {
+ incr = lbr_chartabsize(&cts);
+ if (cts.cts_vcol + incr > destination_col) {
break;
}
- verbatim_copy_width += incr;
- MB_PTR_ADV(verbatim_copy_end);
+ cts.cts_vcol += incr;
+ MB_PTR_ADV(cts.cts_ptr);
}
+ verbatim_copy_width = cts.cts_vcol;
+ verbatim_copy_end = (char_u *)cts.cts_ptr;
+ clear_chartabsize_arg(&cts);
// If "destination_col" is different from the width of the initial
// part of the line that will be copied, it means we encountered a tab
@@ -699,7 +716,7 @@ void op_reindent(oparg_T *oap, Indenter how)
oap->is_VIsual ? start_lnum + (linenr_T)oap->line_count :
last_changed + 1, 0L, true);
} else if (oap->is_VIsual) {
- redraw_curbuf_later(INVERTED);
+ redraw_curbuf_later(UPD_INVERTED);
}
if (oap->line_count > p_report) {
@@ -1087,7 +1104,7 @@ int do_record(int c)
if (!ui_has_messages()) {
// Enable macro indicator temporarily
set_option_value("ch", 1L, NULL, 0);
- update_screen(VALID);
+ update_screen(UPD_VALID);
changed_cmdheight = true;
}
@@ -1142,7 +1159,7 @@ int do_record(int c)
if (changed_cmdheight) {
// Restore cmdheight
set_option_value("ch", 0L, NULL, 0);
- redraw_all_later(CLEAR);
+ redraw_all_later(UPD_CLEAR);
}
}
return retval;
@@ -1292,7 +1309,7 @@ int do_execreg(int regname, int colon, int addcr, int silent)
// don't keep the cmdline containing @:
XFREE_CLEAR(new_last_cmdline);
// Escape all control characters with a CTRL-V
- p = vim_strsave_escaped_ext(last_cmdline,
+ p = vim_strsave_escaped_ext((char_u *)last_cmdline,
(char_u *)"\001\002\003\004\005\006\007"
"\010\011\012\013\014\015\016\017"
"\020\021\022\023\024\025\026\027"
@@ -1493,34 +1510,6 @@ int insert_reg(int regname, bool literally_arg)
return retval;
}
-/// Stuff a string into the typeahead buffer, such that edit() will insert it
-/// literally ("literally" true) or interpret is as typed characters.
-static void stuffescaped(const char *arg, bool literally)
-{
- while (*arg != NUL) {
- // Stuff a sequence of normal ASCII characters, that's fast. Also
- // stuff K_SPECIAL to get the effect of a special key when "literally"
- // is true.
- const char *const start = arg;
- while ((*arg >= ' ' && *arg < DEL) || ((uint8_t)(*arg) == K_SPECIAL
- && !literally)) {
- arg++;
- }
- if (arg > start) {
- stuffReadbuffLen(start, (arg - start));
- }
-
- // stuff a single special character
- if (*arg != NUL) {
- const int c = mb_cptr2char_adv((const char_u **)&arg);
- if (literally && ((c < ' ' && c != TAB) || c == DEL)) {
- stuffcharReadbuff(Ctrl_V);
- }
- stuffcharReadbuff(c);
- }
- }
-}
-
/// Converts a yankreg to a dict which can be used as an argument to the
// userregfunc.
static dict_T* yankreg_to_dict(yankreg_T* yankreg) {
@@ -1628,7 +1617,7 @@ bool get_spec_reg(int regname, char **argp, bool *allocated, bool errmsg)
if (last_cmdline == NULL && errmsg) {
emsg(_(e_nolastcmd));
}
- *argp = (char *)last_cmdline;
+ *argp = last_cmdline;
return true;
case '/': // last search-pattern
@@ -1835,6 +1824,7 @@ int op_delete(oparg_T *oap)
// Put deleted text into register 1 and shift number registers if the
// delete contains a line break, or when using a specific operator (Vi
// compatible)
+
if (oap->motion_type == kMTLineWise || oap->line_count > 1 || oap->use_reg_one) {
shift_delete_registers(is_append_register(oap->regname));
reg = get_global_reg(1);
@@ -2260,7 +2250,7 @@ static int op_replace(oparg_T *oap, int c)
curwin->w_cursor.col = 0;
oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
if (oap->end.col) {
- --oap->end.col;
+ oap->end.col--;
}
} else if (!oap->inclusive) {
dec(&(oap->end));
@@ -2348,7 +2338,7 @@ void op_tilde(oparg_T *oap)
{
pos_T pos;
struct block_def bd;
- int did_change = FALSE;
+ int did_change = false;
if (u_save((linenr_T)(oap->start.lnum - 1),
(linenr_T)(oap->end.lnum + 1)) == FAIL) {
@@ -2374,7 +2364,7 @@ void op_tilde(oparg_T *oap)
pos.col = 0;
oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
if (oap->end.col) {
- --oap->end.col;
+ oap->end.col--;
}
} else if (!oap->inclusive) {
dec(&(oap->end));
@@ -2401,7 +2391,7 @@ void op_tilde(oparg_T *oap)
if (!did_change && oap->is_VIsual) {
// No change: need to remove the Visual selection
- redraw_curbuf_later(INVERTED);
+ redraw_curbuf_later(UPD_INVERTED);
}
if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
@@ -2423,7 +2413,7 @@ void op_tilde(oparg_T *oap)
/// @param length is rounded up to include the whole last multi-byte character.
/// Also works correctly when the number of bytes changes.
///
-/// @return TRUE if some character was changed.
+/// @return true if some character was changed.
static int swapchars(int op_type, pos_T *pos, int length)
FUNC_ATTR_NONNULL_ALL
{
@@ -2520,7 +2510,7 @@ void op_insert(oparg_T *oap, long count1)
// vis block is still marked. Get rid of it now.
curwin->w_cursor.lnum = oap->start.lnum;
- update_screen(INVERTED);
+ update_screen(UPD_INVERTED);
if (oap->motion_type == kMTBlockWise) {
// When 'virtualedit' is used, need to insert the extra spaces before
@@ -2540,7 +2530,7 @@ void op_insert(oparg_T *oap, long count1)
coladvance_force(oap->op_type == OP_APPEND
? oap->end_vcol + 1 : getviscol());
if (oap->op_type == OP_APPEND) {
- --curwin->w_cursor.col;
+ curwin->w_cursor.col--;
}
curwin->w_ve_flags = old_ve_flags;
}
@@ -2561,10 +2551,10 @@ void op_insert(oparg_T *oap, long count1)
if (oap->motion_type == kMTBlockWise
&& curwin->w_cursor.coladd == 0) {
// Move the cursor to the character right of the block.
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
while (*get_cursor_pos_ptr() != NUL
&& (curwin->w_cursor.col < bd.textcol + bd.textlen)) {
- ++curwin->w_cursor.col;
+ curwin->w_cursor.col++;
}
if (bd.is_short && !bd.is_MAX) {
// First line was too short, make it longer and adjust the
@@ -2670,7 +2660,7 @@ void op_insert(oparg_T *oap, long count1)
if (oap->op_type == OP_APPEND) {
pre_textlen += bd2.textlen - bd.textlen;
if (bd2.endspaces) {
- --bd2.textlen;
+ bd2.textlen--;
}
}
bd.textcol = bd2.textcol;
@@ -2721,7 +2711,7 @@ void op_insert(oparg_T *oap, long count1)
/// handle a change operation
///
-/// @return TRUE if edit() returns because of a CTRL-O command
+/// @return true if edit() returns because of a CTRL-O command
int op_change(oparg_T *oap)
{
colnr_T l;
@@ -2747,10 +2737,10 @@ int op_change(oparg_T *oap)
// save for undo
if (curbuf->b_ml.ml_flags & ML_EMPTY) {
if (u_save_cursor() == FAIL) {
- return FALSE;
+ return false;
}
} else if (op_delete(oap) == FAIL) {
- return FALSE;
+ return false;
}
if ((l > curwin->w_cursor.col) && !LINEEMPTY(curwin->w_cursor.lnum)
@@ -2768,7 +2758,7 @@ int op_change(oparg_T *oap)
}
firstline = ml_get(oap->start.lnum);
pre_textlen = (long)STRLEN(firstline);
- pre_indent = (long)getwhitecols(firstline);
+ pre_indent = (long)getwhitecols((char *)firstline);
bd.textcol = curwin->w_cursor.col;
}
@@ -2776,7 +2766,7 @@ int op_change(oparg_T *oap)
fix_indent();
}
- retval = edit(NUL, FALSE, (linenr_T)1);
+ retval = edit(NUL, false, (linenr_T)1);
/*
* In Visual block mode, handle copying the new text to all lines of the
@@ -2789,7 +2779,7 @@ int op_change(oparg_T *oap)
// the indent, exclude that indent change from the inserted text.
firstline = ml_get(oap->start.lnum);
if (bd.textcol > (colnr_T)pre_indent) {
- long new_indent = (long)getwhitecols(firstline);
+ long new_indent = (long)getwhitecols((char *)firstline);
pre_textlen += new_indent - pre_indent;
bd.textcol += (colnr_T)(new_indent - pre_indent);
@@ -3593,12 +3583,19 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
// get the old line and advance to the position to insert at
oldp = get_cursor_line_ptr();
oldlen = STRLEN(oldp);
- for (ptr = oldp; vcol < col && *ptr;) {
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum, 0,
+ oldp, oldp);
+
+ while (cts.cts_vcol < col && *cts.cts_ptr != NUL) {
// Count a tab for what it's worth (if list mode not on)
- incr = lbr_chartabsize_adv(oldp, &ptr, vcol);
- vcol += incr;
+ incr = lbr_chartabsize_adv(&cts);
+ cts.cts_vcol += incr;
}
+ vcol = cts.cts_vcol;
+ ptr = (char_u *)cts.cts_ptr;
bd.textcol = (colnr_T)(ptr - oldp);
+ clear_chartabsize_arg(&cts);
shortline = (vcol < col) || (vcol == col && !*ptr);
@@ -3607,7 +3604,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
} else if (vcol > col) {
bd.endspaces = vcol - col;
bd.startspaces = incr - bd.endspaces;
- --bd.textcol;
+ bd.textcol--;
delcount = 1;
bd.textcol -= utf_head_off(oldp, oldp + bd.textcol);
if (oldp[bd.textcol] != TAB) {
@@ -3625,9 +3622,14 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
// calculate number of spaces required to fill right side of
// block
spaces = y_width + 1;
+ init_chartabsize_arg(&cts, curwin, 0, 0,
+ (char_u *)y_array[i], (char_u *)y_array[i]);
for (int j = 0; j < yanklen; j++) {
- spaces -= lbr_chartabsize(NULL, (char_u *)(&y_array[i][j]), 0);
+ spaces -= lbr_chartabsize(&cts);
+ cts.cts_ptr++;
+ cts.cts_vcol = 0;
}
+ clear_chartabsize_arg(&cts);
if (spaces < 0) {
spaces = 0;
}
@@ -3680,7 +3682,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
extmark_splice_cols(curbuf, (int)curwin->w_cursor.lnum - 1, bd.textcol,
delcount, (int)totlen + lines_appended, kExtmarkUndo);
- ++curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum++;
if (i == 0) {
curwin->w_cursor.col += bd.startspaces;
}
@@ -3984,7 +3986,7 @@ error:
// put cursor on first non-blank in first inserted line
curwin->w_cursor.col = 0;
if (dir == FORWARD) {
- ++curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum++;
}
beginline(BL_WHITE | BL_FIX);
} else { // put cursor on first inserted character
@@ -3994,7 +3996,7 @@ error:
}
msgmore(nr_lines);
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
end:
if (cmdmod.cmod_flags & CMOD_LOCKMARKS) {
@@ -4008,7 +4010,7 @@ end:
xfree(y_array);
}
- VIsual_active = FALSE;
+ VIsual_active = false;
// If the cursor is past the end of the line put it at the end.
adjust_cursor_eol();
@@ -4037,7 +4039,7 @@ void adjust_cursor_eol(void)
}
}
-/// @return TRUE if lines starting with '#' should be left aligned.
+/// @return true if lines starting with '#' should be left aligned.
int preprocs_left(void)
{
return ((curbuf->b_p_si && !curbuf->b_p_cin)
@@ -4123,7 +4125,7 @@ void ex_display(exarg_T *eap)
bool do_show = false;
for (size_t j = 0; !do_show && j < yb->y_size; j++) {
- do_show = !message_filtered((char_u *)yb->y_array[j]);
+ do_show = !message_filtered(yb->y_array[j]);
}
if (do_show || yb->y_size == 0) {
@@ -4144,7 +4146,7 @@ void ex_display(exarg_T *eap)
for (p = (char_u *)yb->y_array[j];
*p != NUL && (n -= ptr2cells((char *)p)) >= 0; p++) { // -V1019
clen = utfc_ptr2len((char *)p);
- msg_outtrans_len(p, clen);
+ msg_outtrans_len((char *)p, clen);
p += clen - 1;
}
}
@@ -4160,7 +4162,7 @@ void ex_display(exarg_T *eap)
// display last inserted text
if ((p = get_last_insert()) != NULL
&& (arg == NULL || vim_strchr((char *)arg, '.') != NULL) && !got_int
- && !message_filtered(p)) {
+ && !message_filtered((char *)p)) {
msg_puts("\n c \". ");
dis_msg(p, true);
}
@@ -4169,13 +4171,13 @@ void ex_display(exarg_T *eap)
if (last_cmdline != NULL && (arg == NULL || vim_strchr((char *)arg, ':') != NULL)
&& !got_int && !message_filtered(last_cmdline)) {
msg_puts("\n c \": ");
- dis_msg(last_cmdline, false);
+ dis_msg((char_u *)last_cmdline, false);
}
// display current file name
if (curbuf->b_fname != NULL
&& (arg == NULL || vim_strchr((char *)arg, '%') != NULL) && !got_int
- && !message_filtered((char_u *)curbuf->b_fname)) {
+ && !message_filtered(curbuf->b_fname)) {
msg_puts("\n c \"% ");
dis_msg((char_u *)curbuf->b_fname, false);
}
@@ -4185,7 +4187,7 @@ void ex_display(exarg_T *eap)
char *fname;
linenr_T dummy;
- if (buflist_name_nr(0, &fname, &dummy) != FAIL && !message_filtered((char_u *)fname)) {
+ if (buflist_name_nr(0, &fname, &dummy) != FAIL && !message_filtered(fname)) {
msg_puts("\n c \"# ");
dis_msg((char_u *)fname, false);
}
@@ -4194,14 +4196,14 @@ void ex_display(exarg_T *eap)
// display last search pattern
if (last_search_pat() != NULL
&& (arg == NULL || vim_strchr((char *)arg, '/') != NULL) && !got_int
- && !message_filtered(last_search_pat())) {
+ && !message_filtered((char *)last_search_pat())) {
msg_puts("\n c \"/ ");
dis_msg(last_search_pat(), false);
}
// display last used expression
if (expr_line != NULL && (arg == NULL || vim_strchr((char *)arg, '=') != NULL)
- && !got_int && !message_filtered(expr_line)) {
+ && !got_int && !message_filtered((char *)expr_line)) {
msg_puts("\n c \"= ");
dis_msg(expr_line, false);
}
@@ -4222,10 +4224,10 @@ static void dis_msg(const char_u *p, bool skip_esc)
&& !(*p == ESC && skip_esc && *(p + 1) == NUL)
&& (n -= ptr2cells((char *)p)) >= 0) {
if ((l = utfc_ptr2len((char *)p)) > 1) {
- msg_outtrans_len(p, l);
+ msg_outtrans_len((char *)p, l);
p += l;
} else {
- msg_outtrans_len(p++, 1);
+ msg_outtrans_len((char *)p++, 1);
}
}
os_breakcheck();
@@ -4297,8 +4299,8 @@ char_u *skip_comment(char_u *line, bool process, bool include_space, bool *is_co
}
/// @param count number of lines (minimal 2) to join at cursor position.
-/// @param save_undo when TRUE, save lines for undo first.
-/// @param use_formatoptions set to FALSE when e.g. processing backspace and comment
+/// @param save_undo when true, save lines for undo first.
+/// @param use_formatoptions set to false when e.g. processing backspace and comment
/// leaders should not be removed.
/// @param setmark when true, sets the '[ and '] mark, else, the caller is expected
/// to set those marks.
@@ -4319,7 +4321,7 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
colnr_T col = 0;
int ret = OK;
int *comments = NULL;
- int remove_comments = (use_formatoptions == TRUE)
+ int remove_comments = (use_formatoptions == true)
&& has_format_option(FO_REMOVE_COMS);
bool prev_was_comment = false;
assert(count >= 1);
@@ -4374,11 +4376,11 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
if (endcurr1 == ' ') {
endcurr1 = endcurr2;
} else {
- ++spaces[t];
+ spaces[t]++;
}
// Extra space when 'joinspaces' set and line ends in '.', '?', or '!'.
if (p_js && (endcurr1 == '.' || endcurr1 == '?' || endcurr1 == '!')) {
- ++spaces[t];
+ spaces[t]++;
}
}
}
@@ -4494,7 +4496,7 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
check_cursor_col();
curwin->w_cursor.coladd = 0;
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
theend:
xfree(spaces);
@@ -4504,532 +4506,6 @@ theend:
return ret;
}
-/// @return TRUE if the two comment leaders given are the same.
-///
-/// @param lnum The first line. White-space is ignored.
-///
-/// @note the whole of 'leader1' must match 'leader2_len' characters from 'leader2'.
-static int same_leader(linenr_T lnum, int leader1_len, char_u *leader1_flags, int leader2_len,
- char_u *leader2_flags)
-{
- int idx1 = 0, idx2 = 0;
- char_u *p;
- char_u *line1;
- char_u *line2;
-
- if (leader1_len == 0) {
- return leader2_len == 0;
- }
-
- /*
- * If first leader has 'f' flag, the lines can be joined only if the
- * second line does not have a leader.
- * If first leader has 'e' flag, the lines can never be joined.
- * If first leader has 's' flag, the lines can only be joined if there is
- * some text after it and the second line has the 'm' flag.
- */
- if (leader1_flags != NULL) {
- for (p = leader1_flags; *p && *p != ':'; ++p) {
- if (*p == COM_FIRST) {
- return leader2_len == 0;
- }
- if (*p == COM_END) {
- return FALSE;
- }
- if (*p == COM_START) {
- if (*(ml_get(lnum) + leader1_len) == NUL) {
- return FALSE;
- }
- if (leader2_flags == NULL || leader2_len == 0) {
- return FALSE;
- }
- for (p = leader2_flags; *p && *p != ':'; ++p) {
- if (*p == COM_MIDDLE) {
- return TRUE;
- }
- }
- return FALSE;
- }
- }
- }
-
- /*
- * Get current line and next line, compare the leaders.
- * The first line has to be saved, only one line can be locked at a time.
- */
- line1 = vim_strsave(ml_get(lnum));
- for (idx1 = 0; ascii_iswhite(line1[idx1]); idx1++) {}
- line2 = ml_get(lnum + 1);
- for (idx2 = 0; idx2 < leader2_len; ++idx2) {
- if (!ascii_iswhite(line2[idx2])) {
- if (line1[idx1++] != line2[idx2]) {
- break;
- }
- } else {
- while (ascii_iswhite(line1[idx1])) {
- idx1++;
- }
- }
- }
- xfree(line1);
-
- return idx2 == leader2_len && idx1 == leader1_len;
-}
-
-/// Implementation of the format operator 'gq'.
-///
-/// @param keep_cursor keep cursor on same text char
-static void op_format(oparg_T *oap, int keep_cursor)
-{
- linenr_T old_line_count = curbuf->b_ml.ml_line_count;
-
- // Place the cursor where the "gq" or "gw" command was given, so that "u"
- // can put it back there.
- curwin->w_cursor = oap->cursor_start;
-
- if (u_save((linenr_T)(oap->start.lnum - 1),
- (linenr_T)(oap->end.lnum + 1)) == FAIL) {
- return;
- }
- curwin->w_cursor = oap->start;
-
- if (oap->is_VIsual) {
- // When there is no change: need to remove the Visual selection
- redraw_curbuf_later(INVERTED);
- }
-
- if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
- // Set '[ mark at the start of the formatted area
- curbuf->b_op_start = oap->start;
- }
-
- // For "gw" remember the cursor position and put it back below (adjusted
- // for joined and split lines).
- if (keep_cursor) {
- saved_cursor = oap->cursor_start;
- }
-
- format_lines((linenr_T)oap->line_count, keep_cursor);
-
- /*
- * Leave the cursor at the first non-blank of the last formatted line.
- * If the cursor was moved one line back (e.g. with "Q}") go to the next
- * line, so "." will do the next lines.
- */
- if (oap->end_adjusted && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
- ++curwin->w_cursor.lnum;
- }
- beginline(BL_WHITE | BL_FIX);
- old_line_count = curbuf->b_ml.ml_line_count - old_line_count;
- msgmore(old_line_count);
-
- if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
- // put '] mark on the end of the formatted area
- curbuf->b_op_end = curwin->w_cursor;
- }
-
- if (keep_cursor) {
- curwin->w_cursor = saved_cursor;
- saved_cursor.lnum = 0;
-
- // formatting may have made the cursor position invalid
- check_cursor();
- }
-
- if (oap->is_VIsual) {
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_old_cursor_lnum != 0) {
- // When lines have been inserted or deleted, adjust the end of
- // the Visual area to be redrawn.
- if (wp->w_old_cursor_lnum > wp->w_old_visual_lnum) {
- wp->w_old_cursor_lnum += old_line_count;
- } else {
- wp->w_old_visual_lnum += old_line_count;
- }
- }
- }
- }
-}
-
-/// Implementation of the format operator 'gq' for when using 'formatexpr'.
-static void op_formatexpr(oparg_T *oap)
-{
- if (oap->is_VIsual) {
- // When there is no change: need to remove the Visual selection
- redraw_curbuf_later(INVERTED);
- }
-
- if (fex_format(oap->start.lnum, oap->line_count, NUL) != 0) {
- // As documented: when 'formatexpr' returns non-zero fall back to
- // internal formatting.
- op_format(oap, false);
- }
-}
-
-/// @param c character to be inserted
-int fex_format(linenr_T lnum, long count, int c)
-{
- int use_sandbox = was_set_insecurely(curwin, "formatexpr", OPT_LOCAL);
- int r;
- char_u *fex;
-
- /*
- * Set v:lnum to the first line number and v:count to the number of lines.
- * Set v:char to the character to be inserted (can be NUL).
- */
- set_vim_var_nr(VV_LNUM, (varnumber_T)lnum);
- set_vim_var_nr(VV_COUNT, (varnumber_T)count);
- set_vim_var_char(c);
-
- // Make a copy, the option could be changed while calling it.
- fex = vim_strsave(curbuf->b_p_fex);
- // Evaluate the function.
- if (use_sandbox) {
- sandbox++;
- }
- r = (int)eval_to_number((char *)fex);
- if (use_sandbox) {
- sandbox--;
- }
-
- set_vim_var_string(VV_CHAR, NULL, -1);
- xfree(fex);
-
- return r;
-}
-
-/// @param line_count number of lines to format, starting at the cursor position.
-/// when negative, format until the end of the paragraph.
-///
-/// Lines after the cursor line are saved for undo, caller must have saved the
-/// first line.
-///
-/// @param avoid_fex don't use 'formatexpr'
-void format_lines(linenr_T line_count, int avoid_fex)
-{
- bool is_not_par; // current line not part of parag.
- bool next_is_not_par; // next line not part of paragraph
- bool is_end_par; // at end of paragraph
- bool prev_is_end_par = false; // prev. line not part of parag.
- bool next_is_start_par = false;
- int leader_len = 0; // leader len of current line
- int next_leader_len; // leader len of next line
- char_u *leader_flags = NULL; // flags for leader of current line
- char_u *next_leader_flags = NULL; // flags for leader of next line
- bool advance = true;
- int second_indent = -1; // indent for second line (comment aware)
- bool first_par_line = true;
- int smd_save;
- long count;
- bool need_set_indent = true; // set indent of next paragraph
- linenr_T first_line = curwin->w_cursor.lnum;
- bool force_format = false;
- const int old_State = State;
-
- // length of a line to force formatting: 3 * 'tw'
- const int max_len = comp_textwidth(true) * 3;
-
- // check for 'q', '2' and '1' in 'formatoptions'
- const bool do_comments = has_format_option(FO_Q_COMS); // format comments
- int do_comments_list = 0; // format comments with 'n' or '2'
- const bool do_second_indent = has_format_option(FO_Q_SECOND);
- const bool do_number_indent = has_format_option(FO_Q_NUMBER);
- const bool do_trail_white = has_format_option(FO_WHITE_PAR);
-
- // Get info about the previous and current line.
- if (curwin->w_cursor.lnum > 1) {
- is_not_par = fmt_check_par(curwin->w_cursor.lnum - 1,
- &leader_len, &leader_flags, do_comments);
- } else {
- is_not_par = true;
- }
- next_is_not_par = fmt_check_par(curwin->w_cursor.lnum,
- &next_leader_len, &next_leader_flags, do_comments
- );
- is_end_par = (is_not_par || next_is_not_par);
- if (!is_end_par && do_trail_white) {
- is_end_par = !ends_in_white(curwin->w_cursor.lnum - 1);
- }
-
- curwin->w_cursor.lnum--;
- for (count = line_count; count != 0 && !got_int; --count) {
- /*
- * Advance to next paragraph.
- */
- if (advance) {
- curwin->w_cursor.lnum++;
- prev_is_end_par = is_end_par;
- is_not_par = next_is_not_par;
- leader_len = next_leader_len;
- leader_flags = next_leader_flags;
- }
-
- /*
- * The last line to be formatted.
- */
- if (count == 1 || curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count) {
- next_is_not_par = true;
- next_leader_len = 0;
- next_leader_flags = NULL;
- } else {
- next_is_not_par = fmt_check_par(curwin->w_cursor.lnum + 1,
- &next_leader_len, &next_leader_flags, do_comments
- );
- if (do_number_indent) {
- next_is_start_par =
- (get_number_indent(curwin->w_cursor.lnum + 1) > 0);
- }
- }
- advance = true;
- is_end_par = (is_not_par || next_is_not_par || next_is_start_par);
- if (!is_end_par && do_trail_white) {
- is_end_par = !ends_in_white(curwin->w_cursor.lnum);
- }
-
- /*
- * Skip lines that are not in a paragraph.
- */
- if (is_not_par) {
- if (line_count < 0) {
- break;
- }
- } else {
- /*
- * For the first line of a paragraph, check indent of second line.
- * Don't do this for comments and empty lines.
- */
- if (first_par_line
- && (do_second_indent || do_number_indent)
- && prev_is_end_par
- && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
- if (do_second_indent && !LINEEMPTY(curwin->w_cursor.lnum + 1)) {
- if (leader_len == 0 && next_leader_len == 0) {
- // no comment found
- second_indent =
- get_indent_lnum(curwin->w_cursor.lnum + 1);
- } else {
- second_indent = next_leader_len;
- do_comments_list = 1;
- }
- } else if (do_number_indent) {
- if (leader_len == 0 && next_leader_len == 0) {
- // no comment found
- second_indent =
- get_number_indent(curwin->w_cursor.lnum);
- } else {
- // get_number_indent() is now "comment aware"...
- second_indent =
- get_number_indent(curwin->w_cursor.lnum);
- do_comments_list = 1;
- }
- }
- }
-
- /*
- * When the comment leader changes, it's the end of the paragraph.
- */
- if (curwin->w_cursor.lnum >= curbuf->b_ml.ml_line_count
- || !same_leader(curwin->w_cursor.lnum,
- leader_len, leader_flags,
- next_leader_len,
- next_leader_flags)) {
- // Special case: If the next line starts with a line comment
- // and this line has a line comment after some text, the
- // paragraph doesn't really end.
- if (next_leader_flags == NULL
- || STRNCMP(next_leader_flags, "://", 3) != 0
- || check_linecomment(get_cursor_line_ptr()) == MAXCOL) {
- is_end_par = true;
- }
- }
-
- /*
- * If we have got to the end of a paragraph, or the line is
- * getting long, format it.
- */
- if (is_end_par || force_format) {
- if (need_set_indent) {
- int indent = 0; // amount of indent needed
-
- // Replace indent in first line of a paragraph with minimal
- // number of tabs and spaces, according to current options.
- // For the very first formatted line keep the current
- // indent.
- if (curwin->w_cursor.lnum == first_line) {
- indent = get_indent();
- } else if (curbuf->b_p_lisp) {
- indent = get_lisp_indent();
- } else {
- if (cindent_on()) {
- indent = *curbuf->b_p_inde != NUL ? get_expr_indent() : get_c_indent();
- } else {
- indent = get_indent();
- }
- }
- (void)set_indent(indent, SIN_CHANGED);
- }
-
- // put cursor on last non-space
- State = MODE_NORMAL; // don't go past end-of-line
- coladvance(MAXCOL);
- while (curwin->w_cursor.col && ascii_isspace(gchar_cursor())) {
- dec_cursor();
- }
-
- // do the formatting, without 'showmode'
- State = MODE_INSERT; // for open_line()
- smd_save = p_smd;
- p_smd = FALSE;
- insertchar(NUL, INSCHAR_FORMAT
- + (do_comments ? INSCHAR_DO_COM : 0)
- + (do_comments && do_comments_list
- ? INSCHAR_COM_LIST : 0)
- + (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent);
- State = old_State;
- p_smd = smd_save;
- second_indent = -1;
- // at end of par.: need to set indent of next par.
- need_set_indent = is_end_par;
- if (is_end_par) {
- // When called with a negative line count, break at the
- // end of the paragraph.
- if (line_count < 0) {
- break;
- }
- first_par_line = true;
- }
- force_format = false;
- }
-
- /*
- * When still in same paragraph, join the lines together. But
- * first delete the leader from the second line.
- */
- if (!is_end_par) {
- advance = false;
- curwin->w_cursor.lnum++;
- curwin->w_cursor.col = 0;
- if (line_count < 0 && u_save_cursor() == FAIL) {
- break;
- }
- if (next_leader_len > 0) {
- (void)del_bytes(next_leader_len, false, false);
- mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L,
- (long)-next_leader_len, 0);
- } else if (second_indent > 0) { // the "leader" for FO_Q_SECOND
- int indent = (int)getwhitecols_curline();
-
- if (indent > 0) {
- (void)del_bytes(indent, false, false);
- mark_col_adjust(curwin->w_cursor.lnum,
- (colnr_T)0, 0L, (long)-indent, 0);
- }
- }
- curwin->w_cursor.lnum--;
- if (do_join(2, TRUE, FALSE, FALSE, false) == FAIL) {
- beep_flush();
- break;
- }
- first_par_line = false;
- // If the line is getting long, format it next time
- if (STRLEN(get_cursor_line_ptr()) > (size_t)max_len) {
- force_format = true;
- } else {
- force_format = false;
- }
- }
- }
- line_breakcheck();
- }
-}
-
-/// @return TRUE if line "lnum" ends in a white character.
-static int ends_in_white(linenr_T lnum)
-{
- char_u *s = ml_get(lnum);
- size_t l;
-
- if (*s == NUL) {
- return FALSE;
- }
- l = STRLEN(s) - 1;
- return ascii_iswhite(s[l]);
-}
-
-/// Blank lines, and lines containing only the comment leader, are left
-/// untouched by the formatting. The function returns TRUE in this
-/// case. It also returns TRUE when a line starts with the end of a comment
-/// ('e' in comment flags), so that this line is skipped, and not joined to the
-/// previous line. A new paragraph starts after a blank line, or when the
-/// comment leader changes.
-static int fmt_check_par(linenr_T lnum, int *leader_len, char_u **leader_flags, int do_comments)
-{
- char_u *flags = NULL; // init for GCC
- char_u *ptr;
-
- ptr = ml_get(lnum);
- if (do_comments) {
- *leader_len = get_leader_len((char *)ptr, (char **)leader_flags, false, true);
- } else {
- *leader_len = 0;
- }
-
- if (*leader_len > 0) {
- /*
- * Search for 'e' flag in comment leader flags.
- */
- flags = *leader_flags;
- while (*flags && *flags != ':' && *flags != COM_END) {
- flags++;
- }
- }
-
- return *skipwhite((char *)ptr + *leader_len) == NUL
- || (*leader_len > 0 && *flags == COM_END)
- || startPS(lnum, NUL, FALSE);
-}
-
-/// Used for auto-formatting.
-///
-/// @return TRUE when a paragraph starts in line "lnum".
-/// FALSE when the previous line is in the same paragraph.
-int paragraph_start(linenr_T lnum)
-{
- char_u *p;
- int leader_len = 0; // leader len of current line
- char_u *leader_flags = NULL; // flags for leader of current line
- int next_leader_len = 0; // leader len of next line
- char_u *next_leader_flags = NULL; // flags for leader of next line
-
- if (lnum <= 1) {
- return TRUE; // start of the file
- }
- p = ml_get(lnum - 1);
- if (*p == NUL) {
- return TRUE; // after empty line
- }
- const bool do_comments = has_format_option(FO_Q_COMS); // format comments
- if (fmt_check_par(lnum - 1, &leader_len, &leader_flags, do_comments)) {
- return true; // after non-paragraph line
- }
-
- if (fmt_check_par(lnum, &next_leader_len, &next_leader_flags, do_comments)) {
- return true; // "lnum" is not a paragraph line
- }
-
- if (has_format_option(FO_WHITE_PAR) && !ends_in_white(lnum - 1)) {
- return TRUE; // missing trailing space in previous line.
- }
- if (has_format_option(FO_Q_NUMBER) && (get_number_indent(lnum) > 0)) {
- return TRUE; // numbered item starts in "lnum".
- }
- if (!same_leader(lnum - 1, leader_len, leader_flags,
- next_leader_len, next_leader_flags)) {
- return TRUE; // change of comment leader.
- }
- return FALSE;
-}
-
/// prepare a few things for block mode yank/delete/tilde
///
/// for delete:
@@ -5066,22 +4542,28 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool
bdp->start_char_vcols = 0;
line = ml_get(lnum);
- pstart = line;
prev_pstart = line;
- while (bdp->start_vcol < oap->start_vcol && *pstart) {
+
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, lnum, bdp->start_vcol, line, line);
+ while (cts.cts_vcol < oap->start_vcol && *cts.cts_ptr != NUL) {
// Count a tab for what it's worth (if list mode not on)
- incr = lbr_chartabsize(line, pstart, bdp->start_vcol);
- bdp->start_vcol += incr;
- if (ascii_iswhite(*pstart)) {
+ incr = lbr_chartabsize(&cts);
+ cts.cts_vcol += incr;
+ if (ascii_iswhite(*cts.cts_ptr)) {
bdp->pre_whitesp += incr;
bdp->pre_whitesp_c++;
} else {
bdp->pre_whitesp = 0;
bdp->pre_whitesp_c = 0;
}
- prev_pstart = pstart;
- MB_PTR_ADV(pstart);
+ prev_pstart = (char_u *)cts.cts_ptr;
+ MB_PTR_ADV(cts.cts_ptr);
}
+ bdp->start_vcol = cts.cts_vcol;
+ pstart = (char_u *)cts.cts_ptr;
+ clear_chartabsize_arg(&cts);
+
bdp->start_char_vcols = incr;
if (bdp->start_vcol < oap->start_vcol) { // line too short
bdp->end_vcol = bdp->start_vcol;
@@ -5117,13 +4599,19 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool
}
}
} else {
+ init_chartabsize_arg(&cts, curwin, lnum, bdp->end_vcol,
+ line, pend);
prev_pend = pend;
- while (bdp->end_vcol <= oap->end_vcol && *pend != NUL) {
+ while (cts.cts_vcol <= oap->end_vcol && *cts.cts_ptr != NUL) {
// Count a tab for what it's worth (if list mode not on)
- prev_pend = pend;
- incr = lbr_chartabsize_adv(line, &pend, bdp->end_vcol);
- bdp->end_vcol += incr;
+ prev_pend = (char_u *)cts.cts_ptr;
+ incr = lbr_chartabsize_adv(&cts);
+ cts.cts_vcol += incr;
}
+ bdp->end_vcol = cts.cts_vcol;
+ pend = (char_u *)cts.cts_ptr;
+ clear_chartabsize_arg(&cts);
+
if (bdp->end_vcol <= oap->end_vcol
&& (!is_del
|| oap->op_type == OP_APPEND
@@ -5248,7 +4736,7 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd)
if (!change_cnt && oap->is_VIsual) {
// No change: need to remove the Visual selection
- redraw_curbuf_later(INVERTED);
+ redraw_curbuf_later(UPD_INVERTED);
}
// Set '[ mark if something changed. Keep the last end
@@ -5296,12 +4784,12 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
pos_T endpos;
colnr_T save_coladd = 0;
- const bool do_hex = vim_strchr((char *)curbuf->b_p_nf, 'x') != NULL; // "heX"
- const bool do_oct = vim_strchr((char *)curbuf->b_p_nf, 'o') != NULL; // "Octal"
- const bool do_bin = vim_strchr((char *)curbuf->b_p_nf, 'b') != NULL; // "Bin"
- const bool do_alpha = vim_strchr((char *)curbuf->b_p_nf, 'p') != NULL; // "alPha"
+ const bool do_hex = vim_strchr(curbuf->b_p_nf, 'x') != NULL; // "heX"
+ const bool do_oct = vim_strchr(curbuf->b_p_nf, 'o') != NULL; // "Octal"
+ const bool do_bin = vim_strchr(curbuf->b_p_nf, 'b') != NULL; // "Bin"
+ const bool do_alpha = vim_strchr(curbuf->b_p_nf, 'p') != NULL; // "alPha"
// "Unsigned"
- const bool do_unsigned = vim_strchr((char *)curbuf->b_p_nf, 'u') != NULL;
+ const bool do_unsigned = vim_strchr(curbuf->b_p_nf, 'u') != NULL;
if (virtual_active()) {
save_coladd = pos->coladd;
@@ -5600,7 +5088,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
}
*ptr = NUL;
STRCAT(buf1, buf2);
- ins_str(buf1); // insert the new number
+ ins_str((char *)buf1); // insert the new number
endpos = curwin->w_cursor;
if (curwin->w_cursor.col) {
curwin->w_cursor.col--;
@@ -5901,7 +5389,7 @@ void write_reg_contents_ex(int name, const char_u *str, ssize_t len, bool must_a
// Special case: '/' search pattern
if (name == '/') {
- set_last_search_pat(str, RE_SEARCH, TRUE, TRUE);
+ set_last_search_pat(str, RE_SEARCH, true, true);
return;
}
@@ -5991,18 +5479,18 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str,
// Count the number of lines within the string
if (str_list) {
- for (char_u **ss = (char_u **)str; *ss != NULL; ++ss) {
+ for (char_u **ss = (char_u **)str; *ss != NULL; ss++) {
newlines++;
}
} else {
newlines = memcnt(str, '\n', len);
if (yank_type == kMTCharWise || len == 0 || str[len - 1] != '\n') {
extraline = 1;
- ++newlines; // count extra newline at the end
+ newlines++; // count extra newline at the end
}
if (y_ptr->y_size > 0 && y_ptr->y_type == kMTCharWise) {
append = true;
- --newlines; // uncount newline when appending first line
+ newlines--; // uncount newline when appending first line
}
}
@@ -6023,7 +5511,7 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str,
// Find the end of each line and save it into the array.
if (str_list) {
- for (char_u **ss = (char_u **)str; *ss != NULL; ++ss, ++lnum) {
+ for (char_u **ss = (char_u **)str; *ss != NULL; ss++, lnum++) {
size_t ss_len = STRLEN(*ss);
pp[lnum] = xmemdupz(*ss, ss_len);
if (ss_len > maxlen) {
@@ -6173,12 +5661,12 @@ void cursor_pos_info(dict_T *dict)
max_pos = VIsual;
}
if (*p_sel == 'e' && max_pos.col > 0) {
- --max_pos.col;
+ max_pos.col--;
}
if (l_VIsual_mode == Ctrl_V) {
- char_u *const saved_sbr = p_sbr;
- char_u *const saved_w_sbr = curwin->w_p_sbr;
+ char *const saved_sbr = p_sbr;
+ char *const saved_w_sbr = curwin->w_p_sbr;
// Make 'sbr' empty for a moment to get the correct size.
p_sbr = empty_option;
@@ -6186,8 +5674,7 @@ void cursor_pos_info(dict_T *dict)
oparg.is_VIsual = true;
oparg.motion_type = kMTBlockWise;
oparg.op_type = OP_NOP;
- getvcols(curwin, &min_pos, &max_pos,
- &oparg.start_vcol, &oparg.end_vcol);
+ getvcols(curwin, &min_pos, &max_pos, &oparg.start_vcol, &oparg.end_vcol);
p_sbr = saved_sbr;
curwin->w_p_sbr = saved_w_sbr;
if (curwin->w_curswant == MAXCOL) {
@@ -6203,7 +5690,7 @@ void cursor_pos_info(dict_T *dict)
line_count_selected = max_pos.lnum - min_pos.lnum + 1;
}
- for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) {
+ for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; lnum++) {
// Check for a CTRL-C every 100000 characters.
if (byte_count > last_check) {
os_breakcheck();
@@ -6350,14 +5837,14 @@ void cursor_pos_info(dict_T *dict)
}
if (dict == NULL) {
// Don't shorten this message, the user asked for it.
- p = p_shm;
- p_shm = (char_u *)"";
+ p = (char_u *)p_shm;
+ p_shm = "";
if (p_ch < 1) {
msg_start();
msg_scroll = true;
}
msg((char *)IObuff);
- p_shm = p;
+ p_shm = (char *)p;
}
}
@@ -6432,7 +5919,7 @@ static Callback opfunc_cb;
/// @return OK or FAIL
int set_operatorfunc_option(void)
{
- return option_set_callback_func(p_opfunc, &opfunc_cb);
+ return option_set_callback_func((char_u *)p_opfunc, &opfunc_cb);
}
#if defined(EXITFREE)
@@ -6643,7 +6130,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
// If 'cpoptions' does not contain 'r', insert the search
// pattern to really repeat the same command.
if (vim_strchr(p_cpo, CPO_REDO) == NULL) {
- AppendToRedobuffLit((char *)cap->searchbuf, -1);
+ AppendToRedobuffLit(cap->searchbuf, -1);
}
AppendToRedobuff(NL_STR);
} else if (cap->cmdchar == ':' || cap->cmdchar == K_COMMAND) {
@@ -6653,7 +6140,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
if (repeat_cmdline == NULL) {
ResetRedobuff();
} else {
- AppendToRedobuffLit((char *)repeat_cmdline, -1);
+ AppendToRedobuffLit(repeat_cmdline, -1);
AppendToRedobuff(NL_STR);
XFREE_CLEAR(repeat_cmdline);
}
@@ -6886,7 +6373,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
&& oap->motion_force == NUL) {
// Make sure redrawing is correct.
curwin->w_p_lbr = lbr_saved;
- redraw_curbuf_later(INVERTED);
+ redraw_curbuf_later(UPD_INVERTED);
}
}
}
@@ -6918,7 +6405,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
if (oap->is_VIsual && (oap->empty || !MODIFIABLE(curbuf)
|| oap->op_type == OP_FOLD)) {
curwin->w_p_lbr = lbr_saved;
- redraw_curbuf_later(INVERTED);
+ redraw_curbuf_later(UPD_INVERTED);
}
// If the end of an operator is in column one while oap->motion_type
diff --git a/src/nvim/option.c b/src/nvim/option.c
index cb2da3c57d..596bc72cd3 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -30,6 +30,7 @@
#include "nvim/arglist.h"
#include "nvim/ascii.h"
#include "nvim/buffer.h"
+#include "nvim/change.h"
#include "nvim/charset.h"
#include "nvim/cursor_shape.h"
#include "nvim/decoration_provider.h"
@@ -38,7 +39,6 @@
#include "nvim/edit.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
-#include "nvim/ex_cmds2.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
#include "nvim/ex_session.h"
@@ -52,6 +52,7 @@
#include "nvim/indent.h"
#include "nvim/indent_c.h"
#include "nvim/keycodes.h"
+#include "nvim/locale.h"
#include "nvim/macros.h"
#include "nvim/mapping.h"
#include "nvim/mbyte.h"
@@ -71,6 +72,7 @@
#include "nvim/popupmenu.h"
#include "nvim/regexp.h"
#include "nvim/screen.h"
+#include "nvim/search.h"
#include "nvim/spell.h"
#include "nvim/spellfile.h"
#include "nvim/spellsuggest.h"
@@ -91,6 +93,19 @@
#include "nvim/os/input.h"
#include "nvim/os/lang.h"
+static char e_unknown_option[]
+ = N_("E518: Unknown option");
+static char e_not_allowed_in_modeline[]
+ = N_("E520: Not allowed in a modeline");
+static char e_not_allowed_in_modeline_when_modelineexpr_is_off[]
+ = N_("E992: Not allowed in a modeline when 'modelineexpr' is off");
+static char e_key_code_not_set[]
+ = N_("E846: Key code not set");
+static char e_number_required_after_equal[]
+ = N_("E521: Number required after =");
+static char e_preview_window_already_exists[]
+ = N_("E590: A preview window already exists");
+
/*
* The options that are local to a window or buffer have "indir" set to one of
* these values. Special values:
@@ -134,7 +149,7 @@ static int p_et_nopaste;
static long p_sts_nopaste;
static long p_tw_nopaste;
static long p_wm_nopaste;
-static char_u *p_vsts_nopaste;
+static char *p_vsts_nopaste;
typedef struct vimoption {
char *fullname; // full option name
@@ -404,7 +419,7 @@ void set_init_1(bool clean_arg)
// NOTE: mlterm's author is being asked to 'set' a variable
// instead of an environment variable due to inheritance.
if (os_env_exists("MLTERM")) {
- set_option_value("tbidi", 1L, NULL, 0);
+ set_option_value_give_err("tbidi", 1L, NULL, 0);
}
didset_options2();
@@ -424,7 +439,7 @@ void set_init_1(bool clean_arg)
#ifdef HAVE_WORKING_LIBINTL
// GNU gettext 0.10.37 supports this feature: set the codeset used for
// translated messages independently from the current locale.
- (void)bind_textdomain_codeset(PROJECT_NAME, (char *)p_enc);
+ (void)bind_textdomain_codeset(PROJECT_NAME, p_enc);
#endif
// Set the default for 'helplang'.
@@ -440,7 +455,7 @@ static void set_option_default(int opt_idx, int opt_flags)
char_u *varp; // pointer to variable for current option
int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
- varp = get_varp_scope(&(options[opt_idx]), both ? OPT_LOCAL : opt_flags);
+ varp = (char_u *)get_varp_scope(&(options[opt_idx]), both ? OPT_LOCAL : opt_flags);
uint32_t flags = options[opt_idx].flags;
if (varp != NULL) { // skip hidden option, nothing to do for it
if (flags & P_STRING) {
@@ -451,7 +466,7 @@ static void set_option_default(int opt_idx, int opt_flags)
(char *)options[opt_idx].def_val, opt_flags, 0);
} else {
if ((opt_flags & OPT_FREE) && (flags & P_ALLOCED)) {
- free_string_option(*(char_u **)(varp));
+ free_string_option(*(char **)(varp));
}
*(char_u **)varp = options[opt_idx].def_val;
options[opt_idx].flags &= ~P_ALLOCED;
@@ -590,14 +605,14 @@ void free_all_options(void)
if (options[i].indir == PV_NONE) {
// global option: free value and default value.
if ((options[i].flags & P_ALLOCED) && options[i].var != NULL) {
- free_string_option(*(char_u **)options[i].var);
+ free_string_option(*(char **)options[i].var);
}
if (options[i].flags & P_DEF_ALLOCED) {
- free_string_option(options[i].def_val);
+ free_string_option((char *)options[i].def_val);
}
} else if (options[i].var != VAR_WIN && (options[i].flags & P_STRING)) {
// buffer-local option: free global value
- clear_string_option((char_u **)options[i].var);
+ clear_string_option((char **)options[i].var);
}
}
free_operatorfunc_option();
@@ -660,12 +675,12 @@ void set_init_3(void)
if (FNAMECMP(p, "csh") == 0
|| FNAMECMP(p, "tcsh") == 0) {
if (do_sp) {
- p_sp = (char_u *)"|& tee";
- options[idx_sp].def_val = p_sp;
+ p_sp = "|& tee";
+ options[idx_sp].def_val = (char_u *)p_sp;
}
if (do_srr) {
- p_srr = (char_u *)">&";
- options[idx_srr].def_val = p_srr;
+ p_srr = ">&";
+ options[idx_srr].def_val = (char_u *)p_srr;
}
} else if (FNAMECMP(p, "sh") == 0
|| FNAMECMP(p, "ksh") == 0
@@ -679,12 +694,12 @@ void set_init_3(void)
|| FNAMECMP(p, "dash") == 0) {
// Always use POSIX shell style redirection if we reach this
if (do_sp) {
- p_sp = (char_u *)"2>&1| tee";
- options[idx_sp].def_val = p_sp;
+ p_sp = "2>&1| tee";
+ options[idx_sp].def_val = (char_u *)p_sp;
}
if (do_srr) {
- p_srr = (char_u *)">%s 2>&1";
- options[idx_srr].def_val = p_srr;
+ p_srr = ">%s 2>&1";
+ options[idx_srr].def_val = (char_u *)p_srr;
}
}
xfree(p);
@@ -717,7 +732,7 @@ void set_helplang_default(const char *lang)
int idx = findoption("hlg");
if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) {
if (options[idx].flags & P_ALLOCED) {
- free_string_option(p_hlg);
+ free_string_option((char *)p_hlg);
}
p_hlg = (char_u *)xmemdupz(lang, lang_len);
// zh_CN becomes "cn", zh_TW becomes "tw".
@@ -795,7 +810,7 @@ int do_set(char *arg, int opt_flags)
int opt_idx;
char *errmsg;
char errbuf[80];
- char_u *startarg;
+ char *startarg;
int prefix; // 1: nothing, 0: "no", 2: "inv" in front of name
char_u nextchar; // next non-white char after option name
int afterchar; // character just after option name
@@ -818,7 +833,7 @@ int do_set(char *arg, int opt_flags)
while (*arg != NUL) { // loop to process all options
errmsg = NULL;
- startarg = (char_u *)arg; // remember for error message
+ startarg = arg; // remember for error message
if (STRNCMP(arg, "all", 3) == 0 && !isalpha(arg[3])
&& !(opt_flags & OPT_MODELINE)) {
@@ -834,7 +849,7 @@ int do_set(char *arg, int opt_flags)
didset_options();
didset_options2();
ui_refresh_options();
- redraw_all_later(CLEAR);
+ redraw_all_later(UPD_CLEAR);
} else {
showoptions(1, opt_flags);
did_show = true;
@@ -915,7 +930,7 @@ int do_set(char *arg, int opt_flags)
nextchar = (uint8_t)arg[len];
if (opt_idx == -1 && key == 0) { // found a mismatch: skip
- errmsg = N_("E518: Unknown option");
+ errmsg = e_unknown_option;
goto skip;
}
@@ -926,13 +941,13 @@ int do_set(char *arg, int opt_flags)
if (vim_strchr("=:!&<", nextchar) == NULL
&& (!(options[opt_idx].flags & P_BOOL)
|| nextchar == '?')) {
- errmsg = _(e_unsupportedoption);
+ errmsg = e_unsupportedoption;
}
goto skip;
}
flags = options[opt_idx].flags;
- varp = (char *)get_varp_scope(&(options[opt_idx]), opt_flags);
+ varp = get_varp_scope(&(options[opt_idx]), opt_flags);
} else {
flags = P_STRING;
}
@@ -953,11 +968,11 @@ int do_set(char *arg, int opt_flags)
// Disallow changing some options from modelines.
if (opt_flags & OPT_MODELINE) {
if (flags & (P_SECURE | P_NO_ML)) {
- errmsg = N_("E520: Not allowed in a modeline");
+ errmsg = e_not_allowed_in_modeline;
goto skip;
}
if ((flags & P_MLE) && !p_mle) {
- errmsg = N_("E992: Not allowed in a modeline when 'modelineexpr' is off");
+ errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off;
goto skip;
}
// In diff mode some options are overruled. This avoids that
@@ -1025,7 +1040,7 @@ int do_set(char *arg, int opt_flags)
}
}
} else {
- errmsg = N_("E846: Key code not set");
+ errmsg = e_key_code_not_set;
goto skip;
}
if (nextchar != '?'
@@ -1118,11 +1133,11 @@ int do_set(char *arg, int opt_flags)
// Allow negative, octal and hex numbers.
vim_str2nr((char_u *)arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true);
if (i == 0 || (arg[i] != NUL && !ascii_iswhite(arg[i]))) {
- errmsg = N_("E521: Number required after =");
+ errmsg = e_number_required_after_equal;
goto skip;
}
} else {
- errmsg = N_("E521: Number required after =");
+ errmsg = e_number_required_after_equal;
goto skip;
}
@@ -1172,7 +1187,7 @@ int do_set(char *arg, int opt_flags)
// A global-local string option might have an empty
// option as value to indicate that the global
// value should be used.
- if (((int)options[opt_idx].indir & PV_BOTH) && origval_l == empty_option) {
+ if (((int)options[opt_idx].indir & PV_BOTH) && origval_l == (char_u *)empty_option) {
origval_l = origval_g;
}
}
@@ -1192,7 +1207,7 @@ int do_set(char *arg, int opt_flags)
// required when an environment variable was set
// later
if (newval == NULL) {
- newval = empty_option;
+ newval = (char_u *)empty_option;
} else if (!(options[opt_idx].flags & P_NO_DEF_EXP)) {
s = option_expand(opt_idx, newval);
if (s == NULL) {
@@ -1220,7 +1235,7 @@ int do_set(char *arg, int opt_flags)
i = getdigits_int((char **)varp, true, 0);
switch (i) {
case 0:
- *(char_u **)varp = empty_option;
+ *(char **)varp = empty_option;
break;
case 1:
*(char_u **)varp = vim_strsave((char_u *)"indent,eol");
@@ -1468,7 +1483,7 @@ int do_set(char *arg, int opt_flags)
// for ":set" on local options. Note: when setting
// 'syntax' or 'filetype' autocommands may be
// triggered that can cause havoc.
- errmsg = did_set_string_option(opt_idx, (char_u **)varp, oldval,
+ errmsg = did_set_string_option(opt_idx, (char **)varp, (char *)oldval,
errbuf, sizeof(errbuf),
opt_flags, &value_checked);
@@ -1528,17 +1543,17 @@ skip:
if (errmsg != NULL) {
STRLCPY(IObuff, _(errmsg), IOSIZE);
i = (int)STRLEN(IObuff) + 2;
- if (i + ((char_u *)arg - startarg) < IOSIZE) {
+ if (i + (arg - startarg) < IOSIZE) {
// append the argument with the error
STRCAT(IObuff, ": ");
- assert((char_u *)arg >= startarg);
- memmove(IObuff + i, startarg, (size_t)((char_u *)arg - startarg));
- IObuff[i + ((char_u *)arg - startarg)] = NUL;
+ assert(arg >= startarg);
+ memmove(IObuff + i, startarg, (size_t)(arg - startarg));
+ IObuff[i + (arg - startarg)] = NUL;
}
// make sure all characters are printable
trans_characters((char *)IObuff, IOSIZE);
- no_wait_return++; // wait_return done later
+ no_wait_return++; // wait_return() done later
emsg((char *)IObuff); // show error highlighted
no_wait_return--;
@@ -1587,7 +1602,7 @@ void did_set_option(int opt_idx, int opt_flags, int new_value, int value_checked
/// Convert a key name or string into a key value.
/// Used for 'wildchar' and 'cedit' options.
-static int string_to_key(char_u *arg)
+int string_to_key(char_u *arg)
{
if (*arg == '<') {
return find_key_option(arg + 1, true);
@@ -1598,24 +1613,6 @@ static int string_to_key(char_u *arg)
return *arg;
}
-/// Check value of 'cedit' and set cedit_key.
-/// Returns NULL if value is OK, error message otherwise.
-char *check_cedit(void)
-{
- int n;
-
- if (*p_cedit == NUL) {
- cedit_key = -1;
- } else {
- n = string_to_key(p_cedit);
- if (vim_isprintc(n)) {
- return e_invarg;
- }
- cedit_key = n;
- }
- return NULL;
-}
-
// When changing 'title', 'titlestring', 'icon' or 'iconstring', call
// maketitle() to create and display it.
// When switching the title or icon off, call ui_set_{icon,title}(NULL) to get
@@ -1702,16 +1699,14 @@ int get_shada_parameter(int type)
/// Return NULL if the parameter is not specified in the string.
char_u *find_shada_parameter(int type)
{
- char_u *p;
-
- for (p = p_shada; *p; p++) {
+ for (char *p = p_shada; *p; p++) {
if (*p == type) {
- return p + 1;
+ return (char_u *)p + 1;
}
if (*p == 'n') { // 'n' is always the last one
break;
}
- p = (char_u *)vim_strchr((char *)p, ','); // skip until next ','
+ p = vim_strchr(p, ','); // skip until next ','
if (p == NULL) { // hit the end without finding parameter
break;
}
@@ -1746,15 +1741,15 @@ static char_u *option_expand(int opt_idx, char_u *val)
* names.
* For 'spellsuggest' expand after "file:".
*/
- expand_env_esc(val, NameBuff, MAXPATHL,
+ expand_env_esc(val, (char_u *)NameBuff, MAXPATHL,
(char_u **)options[opt_idx].var == &p_tags, false,
- (char_u **)options[opt_idx].var == &p_sps ? (char_u *)"file:" :
+ (char_u **)options[opt_idx].var == (char_u **)&p_sps ? (char_u *)"file:" :
NULL);
if (STRCMP(NameBuff, val) == 0) { // they are the same
return NULL;
}
- return NameBuff;
+ return (char_u *)NameBuff;
}
/// After setting various option values: recompute variables that depend on
@@ -1804,7 +1799,7 @@ void check_options(void)
for (opt_idx = 0; options[opt_idx].fullname != NULL; opt_idx++) {
if ((options[opt_idx].flags & P_STRING) && options[opt_idx].var != NULL) {
- check_string_option((char_u **)get_varp(&(options[opt_idx])));
+ check_string_option((char **)get_varp(&(options[opt_idx])));
}
}
}
@@ -1863,10 +1858,10 @@ void redraw_titles(void)
/// Return true if "val" is a valid name: only consists of alphanumeric ASCII
/// characters or characters in "allowed".
-bool valid_name(const char_u *val, const char *allowed)
+bool valid_name(const char *val, const char *allowed)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- for (const char_u *s = val; *s != NUL; s++) {
+ for (const char_u *s = (char_u *)val; *s != NUL; s++) {
if (!ASCII_ISALNUM(*s)
&& vim_strchr(allowed, *s) == NULL) {
return false;
@@ -1971,6 +1966,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
{
int old_value = *(int *)varp;
int old_global_value = 0;
+ char *errmsg = NULL;
// Disallow changing some options from secure mode
if ((secure || sandbox != 0)
@@ -2075,7 +2071,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
paste_option_changed();
} else if ((int *)varp == &p_ic && p_hls) {
// when 'ignorecase' is set or reset and 'hlsearch' is set, redraw
- redraw_all_later(SOME_VALID);
+ redraw_all_later(UPD_SOME_VALID);
} else if ((int *)varp == &p_hls) {
// when 'hlsearch' is set or reset: reset no_hlsearch
set_no_hlsearch(false);
@@ -2092,7 +2088,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
FOR_ALL_WINDOWS_IN_TAB(win, curtab) {
if (win->w_p_pvw && win != curwin) {
curwin->w_p_pvw = false;
- return N_("E590: A preview window already exists");
+ return e_preview_window_already_exists;
}
}
}
@@ -2151,10 +2147,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
}
} else if ((int *)varp == &curwin->w_p_spell) { // 'spell'
if (curwin->w_p_spell) {
- char *errmsg = did_set_spelllang(curwin);
- if (errmsg != NULL) {
- emsg(_(errmsg));
- }
+ errmsg = did_set_spelllang(curwin);
}
}
@@ -2173,7 +2166,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
// Enable Arabic shaping (major part of what Arabic requires)
if (!p_arshape) {
p_arshape = true;
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
}
}
@@ -2191,7 +2184,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
p_deco = true;
// Force-set the necessary keymap for arabic.
- set_option_value("keymap", 0L, "arabic", OPT_LOCAL);
+ errmsg = set_option_value("keymap", 0L, "arabic", OPT_LOCAL);
} else {
/*
* 'arabic' is reset, handle various sub-settings.
@@ -2271,7 +2264,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
}
check_redraw(options[opt_idx].flags);
- return NULL;
+ return errmsg;
}
/// Set the value of a number option, taking care of side effects
@@ -2730,15 +2723,15 @@ void check_redraw(uint32_t flags)
changed_window_setting();
}
if (flags & P_RBUF) {
- redraw_curbuf_later(NOT_VALID);
+ redraw_curbuf_later(UPD_NOT_VALID);
}
if (flags & P_RWINONLY) {
- redraw_later(curwin, NOT_VALID);
+ redraw_later(curwin, UPD_NOT_VALID);
}
if (doclear) {
- redraw_all_later(CLEAR);
+ redraw_all_later(UPD_CLEAR);
} else if (all) {
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
}
}
@@ -2888,7 +2881,7 @@ bool set_tty_option(const char *name, char *value)
void set_tty_background(const char *value)
{
- if (option_was_set("bg") || strequal((char *)p_bg, value)) {
+ if (option_was_set("bg") || strequal(p_bg, value)) {
// background is already set... ignore
return;
}
@@ -2898,7 +2891,7 @@ void set_tty_background(const char *value)
? "autocmd VimEnter * ++once ++nested set bg=light"
: "autocmd VimEnter * ++once ++nested set bg=dark");
} else {
- set_option_value("bg", 0L, value, 0);
+ set_option_value_give_err("bg", 0L, value, 0);
reset_option_was_set("bg");
}
}
@@ -2937,14 +2930,14 @@ getoption_T get_option_value(const char *name, long *numval, char **stringval, i
return gov_unknown;
}
- char_u *varp = get_varp_scope(&(options[opt_idx]), opt_flags);
+ char_u *varp = (char_u *)get_varp_scope(&(options[opt_idx]), opt_flags);
if (options[opt_idx].flags & P_STRING) {
if (varp == NULL) { // hidden option
return gov_hidden_string;
}
if (stringval != NULL) {
- if ((char_u **)varp == &p_pt) { // 'pastetoggle'
+ if ((char **)varp == &p_pt) { // 'pastetoggle'
*stringval = str2special_save(*(char **)(varp), false, false);
} else {
*stringval = xstrdup(*(char **)(varp));
@@ -3063,7 +3056,7 @@ int get_option_value_strict(char *name, int64_t *numval, char **stringval, int o
// only getting a pointer, no need to use aucmd_prepbuf()
curbuf = (buf_T *)from;
curwin->w_buffer = curbuf;
- varp = get_varp_scope(p, OPT_LOCAL);
+ varp = (char_u *)get_varp_scope(p, OPT_LOCAL);
curbuf = save_curbuf;
curwin->w_buffer = curbuf;
}
@@ -3071,7 +3064,7 @@ int get_option_value_strict(char *name, int64_t *numval, char **stringval, int o
win_T *save_curwin = curwin;
curwin = (win_T *)from;
curbuf = curwin->w_buffer;
- varp = get_varp_scope(p, OPT_LOCAL);
+ varp = (char_u *)get_varp_scope(p, OPT_LOCAL);
curwin = save_curwin;
curbuf = curwin->w_buffer;
}
@@ -3147,7 +3140,7 @@ bool is_hidden_option(int opt_idx)
/// is cleared (the exact semantics of this depend
/// on the option).
///
-/// @return NULL on success, error message on error.
+/// @return NULL on success, an untranslated error message on error.
char *set_option_value(const char *const name, const long number, const char *const string,
const int opt_flags)
FUNC_ATTR_NONNULL_ARG(1)
@@ -3177,7 +3170,7 @@ char *set_option_value(const char *const name, const long number, const char *co
return set_string_option(opt_idx, s, opt_flags);
}
- varp = get_varp_scope(&(options[opt_idx]), opt_flags);
+ varp = (char_u *)get_varp_scope(&(options[opt_idx]), opt_flags);
if (varp != NULL) { // hidden option is not changed
if (number == 0 && string != NULL) {
int idx;
@@ -3217,6 +3210,18 @@ char *set_option_value(const char *const name, const long number, const char *co
return NULL;
}
+/// Call set_option_value() and when an error is returned report it.
+///
+/// @param opt_flags OPT_LOCAL or 0 (both)
+void set_option_value_give_err(const char *name, long number, const char *string, int opt_flags)
+{
+ char *errmsg = set_option_value(name, number, string, opt_flags);
+
+ if (errmsg != NULL) {
+ emsg(_(errmsg));
+ }
+}
+
/// Return true if "name" is a string option.
/// Returns false if option "name" does not exist.
bool is_string_option(const char *name)
@@ -3294,14 +3299,14 @@ static void showoptions(int all, int opt_flags)
item_count = 0;
for (p = &options[0]; p->fullname != NULL; p++) {
// apply :filter /pat/
- if (message_filtered((char_u *)p->fullname)) {
+ if (message_filtered(p->fullname)) {
continue;
}
varp = NULL;
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) != 0) {
if (p->indir != PV_NONE) {
- varp = get_varp_scope(p, opt_flags);
+ varp = (char_u *)get_varp_scope(p, opt_flags);
}
} else {
varp = get_varp(p);
@@ -3405,13 +3410,12 @@ void ui_refresh_options(void)
/// @param opt_flags OPT_LOCAL or OPT_GLOBAL
static void showoneopt(vimoption_T *p, int opt_flags)
{
- char_u *varp;
int save_silent = silent_mode;
silent_mode = false;
info_message = true; // use mch_msg(), not mch_errmsg()
- varp = get_varp_scope(p, opt_flags);
+ char_u *varp = (char_u *)get_varp_scope(p, opt_flags);
// for 'modified' we also need to check if 'ff' or 'fenc' changed.
if ((p->flags & P_BOOL) && ((int *)varp == &curbuf->b_changed
@@ -3457,7 +3461,7 @@ static void showoneopt(vimoption_T *p, int opt_flags)
int makeset(FILE *fd, int opt_flags, int local_only)
{
vimoption_T *p;
- char_u *varp; // currently used value
+ char *varp; // currently used value
char_u *varp_fresh; // local value
char_u *varp_local = NULL; // fresh value
char *cmd;
@@ -3494,7 +3498,7 @@ int makeset(FILE *fd, int opt_flags, int local_only)
continue;
}
// Global values are only written when not at the default value.
- if ((opt_flags & OPT_GLOBAL) && optval_default(p, varp)) {
+ if ((opt_flags & OPT_GLOBAL) && optval_default(p, (char_u *)varp)) {
continue;
}
@@ -3513,11 +3517,11 @@ int makeset(FILE *fd, int opt_flags, int local_only)
// When fresh value of window-local option is not at the
// default, need to write it too.
if (!(opt_flags & OPT_GLOBAL) && !local_only) {
- varp_fresh = get_varp_scope(p, OPT_GLOBAL);
+ varp_fresh = (char_u *)get_varp_scope(p, OPT_GLOBAL);
if (!optval_default(p, varp_fresh)) {
round = 1;
- varp_local = varp;
- varp = varp_fresh;
+ varp_local = (char_u *)varp;
+ varp = (char *)varp_fresh;
}
}
}
@@ -3525,7 +3529,7 @@ int makeset(FILE *fd, int opt_flags, int local_only)
// Round 1: fresh value for window-local options.
// Round 2: other values
- for (; round <= 2; varp = varp_local, round++) {
+ for (; round <= 2; varp = (char *)varp_local, round++) {
if (round == 1 || (opt_flags & OPT_GLOBAL)) {
cmd = "set";
} else {
@@ -3553,8 +3557,7 @@ int makeset(FILE *fd, int opt_flags, int local_only)
}
do_endif = true;
}
- if (put_setstring(fd, cmd, p->fullname, (char_u **)varp,
- p->flags) == FAIL) {
+ if (put_setstring(fd, cmd, p->fullname, (char **)varp, p->flags) == FAIL) {
return FAIL;
}
if (do_endif) {
@@ -3575,24 +3578,20 @@ int makeset(FILE *fd, int opt_flags, int local_only)
int makefoldset(FILE *fd)
{
if (put_setstring(fd, "setlocal", "fdm", &curwin->w_p_fdm, 0) == FAIL
- || put_setstring(fd, "setlocal", "fde", &curwin->w_p_fde, 0)
- == FAIL
- || put_setstring(fd, "setlocal", "fmr", &curwin->w_p_fmr, 0)
- == FAIL
- || put_setstring(fd, "setlocal", "fdi", &curwin->w_p_fdi, 0)
- == FAIL
+ || put_setstring(fd, "setlocal", "fde", &curwin->w_p_fde, 0) == FAIL
+ || put_setstring(fd, "setlocal", "fmr", &curwin->w_p_fmr, 0) == FAIL
+ || put_setstring(fd, "setlocal", "fdi", &curwin->w_p_fdi, 0) == FAIL
|| put_setnum(fd, "setlocal", "fdl", &curwin->w_p_fdl) == FAIL
|| put_setnum(fd, "setlocal", "fml", &curwin->w_p_fml) == FAIL
|| put_setnum(fd, "setlocal", "fdn", &curwin->w_p_fdn) == FAIL
- || put_setbool(fd, "setlocal", "fen",
- curwin->w_p_fen) == FAIL) {
+ || put_setbool(fd, "setlocal", "fen", curwin->w_p_fen) == FAIL) {
return FAIL;
}
return OK;
}
-static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, uint64_t flags)
+static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_t flags)
{
char_u *s;
char_u *buf = NULL;
@@ -3607,7 +3606,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, uint6
// options some characters have to be escaped with
// CTRL-V or backslash
if (valuep == &p_pt) {
- s = *valuep;
+ s = (char_u *)(*valuep);
while (*s != NUL) {
if (put_escstr(fd, (char_u *)str2special((const char **)&s, false,
false), 2)
@@ -3620,13 +3619,13 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, uint6
// replace home directory in the whole option value into "buf"
buf = xmalloc(size);
- home_replace(NULL, (char *)(*valuep), (char *)buf, size, false);
+ home_replace(NULL, *valuep, (char *)buf, size, false);
// If the option value is longer than MAXPATHL, we need to append
// each comma separated part of the option separately, so that it
// can be expanded when read back.
if (size >= MAXPATHL && (flags & P_COMMA) != 0
- && vim_strchr((char *)(*valuep), ',') != NULL) {
+ && vim_strchr(*valuep, ',') != NULL) {
part = xmalloc(size);
// write line break to clear the option, e.g. ':set rtp='
@@ -3654,7 +3653,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, uint6
return FAIL;
}
xfree(buf);
- } else if (put_escstr(fd, *valuep, 2) == FAIL) {
+ } else if (put_escstr(fd, (char_u *)(*valuep), 2) == FAIL) {
return FAIL;
}
}
@@ -3780,7 +3779,7 @@ void unset_global_local_option(char *name, void *from)
clear_string_option(&((win_T *)from)->w_p_stl);
break;
case PV_WBR:
- clear_string_option((char_u **)&((win_T *)from)->w_p_wbr);
+ clear_string_option(&((win_T *)from)->w_p_wbr);
break;
case PV_UL:
buf->b_p_ul = NO_LOCAL_UNDOLEVEL;
@@ -3794,12 +3793,12 @@ void unset_global_local_option(char *name, void *from)
case PV_LCS:
clear_string_option(&((win_T *)from)->w_p_lcs);
set_chars_option((win_T *)from, &((win_T *)from)->w_p_lcs, true);
- redraw_later((win_T *)from, NOT_VALID);
+ redraw_later((win_T *)from, UPD_NOT_VALID);
break;
case PV_FCS:
clear_string_option(&((win_T *)from)->w_p_fcs);
set_chars_option((win_T *)from, &((win_T *)from)->w_p_fcs, true);
- redraw_later((win_T *)from, NOT_VALID);
+ redraw_later((win_T *)from, UPD_NOT_VALID);
break;
case PV_VE:
clear_string_option(&((win_T *)from)->w_p_ve);
@@ -3809,81 +3808,81 @@ void unset_global_local_option(char *name, void *from)
}
/// Get pointer to option variable, depending on local or global scope.
-static char_u *get_varp_scope(vimoption_T *p, int opt_flags)
+static char *get_varp_scope(vimoption_T *p, int opt_flags)
{
if ((opt_flags & OPT_GLOBAL) && p->indir != PV_NONE) {
if (p->var == VAR_WIN) {
- return (char_u *)GLOBAL_WO(get_varp(p));
+ return GLOBAL_WO(get_varp(p));
}
- return p->var;
+ return (char *)p->var;
}
if ((opt_flags & OPT_LOCAL) && ((int)p->indir & PV_BOTH)) {
switch ((int)p->indir) {
case PV_FP:
- return (char_u *)&(curbuf->b_p_fp);
+ return (char *)&(curbuf->b_p_fp);
case PV_EFM:
- return (char_u *)&(curbuf->b_p_efm);
+ return (char *)&(curbuf->b_p_efm);
case PV_GP:
- return (char_u *)&(curbuf->b_p_gp);
+ return (char *)&(curbuf->b_p_gp);
case PV_MP:
- return (char_u *)&(curbuf->b_p_mp);
+ return (char *)&(curbuf->b_p_mp);
case PV_EP:
- return (char_u *)&(curbuf->b_p_ep);
+ return (char *)&(curbuf->b_p_ep);
case PV_KP:
- return (char_u *)&(curbuf->b_p_kp);
+ return (char *)&(curbuf->b_p_kp);
case PV_PATH:
- return (char_u *)&(curbuf->b_p_path);
+ return (char *)&(curbuf->b_p_path);
case PV_AR:
- return (char_u *)&(curbuf->b_p_ar);
+ return (char *)&(curbuf->b_p_ar);
case PV_TAGS:
- return (char_u *)&(curbuf->b_p_tags);
+ return (char *)&(curbuf->b_p_tags);
case PV_TC:
- return (char_u *)&(curbuf->b_p_tc);
+ return (char *)&(curbuf->b_p_tc);
case PV_SISO:
- return (char_u *)&(curwin->w_p_siso);
+ return (char *)&(curwin->w_p_siso);
case PV_SO:
- return (char_u *)&(curwin->w_p_so);
+ return (char *)&(curwin->w_p_so);
case PV_DEF:
- return (char_u *)&(curbuf->b_p_def);
+ return (char *)&(curbuf->b_p_def);
case PV_INC:
- return (char_u *)&(curbuf->b_p_inc);
+ return (char *)&(curbuf->b_p_inc);
case PV_DICT:
- return (char_u *)&(curbuf->b_p_dict);
+ return (char *)&(curbuf->b_p_dict);
case PV_TSR:
- return (char_u *)&(curbuf->b_p_tsr);
+ return (char *)&(curbuf->b_p_tsr);
case PV_TSRFU:
- return (char_u *)&(curbuf->b_p_tsrfu);
+ return (char *)&(curbuf->b_p_tsrfu);
case PV_TFU:
- return (char_u *)&(curbuf->b_p_tfu);
+ return (char *)&(curbuf->b_p_tfu);
case PV_SBR:
- return (char_u *)&(curwin->w_p_sbr);
+ return (char *)&(curwin->w_p_sbr);
case PV_STL:
- return (char_u *)&(curwin->w_p_stl);
+ return (char *)&(curwin->w_p_stl);
case PV_WBR:
- return (char_u *)&(curwin->w_p_wbr);
+ return (char *)&(curwin->w_p_wbr);
case PV_UL:
- return (char_u *)&(curbuf->b_p_ul);
+ return (char *)&(curbuf->b_p_ul);
case PV_LW:
- return (char_u *)&(curbuf->b_p_lw);
+ return (char *)&(curbuf->b_p_lw);
case PV_BKC:
- return (char_u *)&(curbuf->b_p_bkc);
+ return (char *)&(curbuf->b_p_bkc);
case PV_MENC:
- return (char_u *)&(curbuf->b_p_menc);
+ return (char *)&(curbuf->b_p_menc);
case PV_FCS:
- return (char_u *)&(curwin->w_p_fcs);
+ return (char *)&(curwin->w_p_fcs);
case PV_LCS:
- return (char_u *)&(curwin->w_p_lcs);
+ return (char *)&(curwin->w_p_lcs);
case PV_VE:
- return (char_u *)&(curwin->w_p_ve);
+ return (char *)&(curwin->w_p_ve);
}
return NULL; // "cannot happen"
}
- return get_varp(p);
+ return (char *)get_varp(p);
}
/// Get pointer to option variable at 'opt_idx', depending on local or global
/// scope.
-char_u *get_option_varp_scope(int opt_idx, int opt_flags)
+char *get_option_varp_scope(int opt_idx, int opt_flags)
{
return get_varp_scope(&(options[opt_idx]), opt_flags);
}
@@ -4217,7 +4216,7 @@ char_u *get_equalprg(void)
if (*curbuf->b_p_ep == NUL) {
return p_ep;
}
- return curbuf->b_p_ep;
+ return (char_u *)curbuf->b_p_ep;
}
/// Copy options from one window to another.
@@ -4229,6 +4228,14 @@ void win_copy_options(win_T *wp_from, win_T *wp_to)
didset_window_options(wp_to, true);
}
+static char *copy_option_val(const char *val)
+{
+ if (val == empty_option) {
+ return empty_option; // no need to allocate memory
+ }
+ return xstrdup(val);
+}
+
/// Copy the options from one winopt_T to another.
/// Doesn't free the old option values in "to", use clear_winopt() for that.
/// The 'scroll' option is not copied, because it depends on the window height.
@@ -4237,21 +4244,23 @@ void copy_winopt(winopt_T *from, winopt_T *to)
{
to->wo_arab = from->wo_arab;
to->wo_list = from->wo_list;
+ to->wo_lcs = copy_option_val(from->wo_lcs);
+ to->wo_fcs = copy_option_val(from->wo_fcs);
to->wo_nu = from->wo_nu;
to->wo_rnu = from->wo_rnu;
- to->wo_ve = vim_strsave(from->wo_ve);
+ to->wo_ve = copy_option_val(from->wo_ve);
to->wo_ve_flags = from->wo_ve_flags;
to->wo_nuw = from->wo_nuw;
to->wo_rl = from->wo_rl;
- to->wo_rlc = vim_strsave(from->wo_rlc);
- to->wo_sbr = vim_strsave(from->wo_sbr);
- to->wo_stl = vim_strsave(from->wo_stl);
- to->wo_wbr = xstrdup(from->wo_wbr);
+ to->wo_rlc = copy_option_val(from->wo_rlc);
+ to->wo_sbr = copy_option_val(from->wo_sbr);
+ to->wo_stl = copy_option_val(from->wo_stl);
+ to->wo_wbr = copy_option_val(from->wo_wbr);
to->wo_wrap = from->wo_wrap;
to->wo_wrap_save = from->wo_wrap_save;
to->wo_lbr = from->wo_lbr;
to->wo_bri = from->wo_bri;
- to->wo_briopt = vim_strsave(from->wo_briopt);
+ to->wo_briopt = copy_option_val(from->wo_briopt);
to->wo_scb = from->wo_scb;
to->wo_scb_save = from->wo_scb_save;
to->wo_crb = from->wo_crb;
@@ -4259,32 +4268,28 @@ void copy_winopt(winopt_T *from, winopt_T *to)
to->wo_spell = from->wo_spell;
to->wo_cuc = from->wo_cuc;
to->wo_cul = from->wo_cul;
- to->wo_culopt = vim_strsave(from->wo_culopt);
- to->wo_cc = vim_strsave(from->wo_cc);
+ to->wo_culopt = copy_option_val(from->wo_culopt);
+ to->wo_cc = copy_option_val(from->wo_cc);
to->wo_diff = from->wo_diff;
to->wo_diff_saved = from->wo_diff_saved;
- to->wo_cocu = vim_strsave(from->wo_cocu);
+ to->wo_cocu = copy_option_val(from->wo_cocu);
to->wo_cole = from->wo_cole;
- to->wo_fdc = vim_strsave(from->wo_fdc);
- to->wo_fdc_save = from->wo_diff_saved
- ? vim_strsave(from->wo_fdc_save) : empty_option;
+ to->wo_fdc = copy_option_val(from->wo_fdc);
+ to->wo_fdc_save = from->wo_diff_saved ? xstrdup(from->wo_fdc_save) : empty_option;
to->wo_fen = from->wo_fen;
to->wo_fen_save = from->wo_fen_save;
- to->wo_fdi = vim_strsave(from->wo_fdi);
+ to->wo_fdi = copy_option_val(from->wo_fdi);
to->wo_fml = from->wo_fml;
to->wo_fdl = from->wo_fdl;
to->wo_fdl_save = from->wo_fdl_save;
- to->wo_fdm = vim_strsave(from->wo_fdm);
- to->wo_fdm_save = from->wo_diff_saved
- ? vim_strsave(from->wo_fdm_save) : empty_option;
+ to->wo_fdm = copy_option_val(from->wo_fdm);
+ to->wo_fdm_save = from->wo_diff_saved ? xstrdup(from->wo_fdm_save) : empty_option;
to->wo_fdn = from->wo_fdn;
- to->wo_fde = vim_strsave(from->wo_fde);
- to->wo_fdt = vim_strsave(from->wo_fdt);
- to->wo_fmr = vim_strsave(from->wo_fmr);
- to->wo_scl = vim_strsave(from->wo_scl);
- to->wo_winhl = vim_strsave(from->wo_winhl);
- to->wo_fcs = vim_strsave(from->wo_fcs);
- to->wo_lcs = vim_strsave(from->wo_lcs);
+ to->wo_fde = copy_option_val(from->wo_fde);
+ to->wo_fdt = copy_option_val(from->wo_fdt);
+ to->wo_fmr = copy_option_val(from->wo_fmr);
+ to->wo_scl = copy_option_val(from->wo_scl);
+ to->wo_winhl = copy_option_val(from->wo_winhl);
to->wo_winbl = from->wo_winbl;
// Copy the script context so that we know were the value was last set.
@@ -4319,10 +4324,10 @@ static void check_winopt(winopt_T *wop)
check_string_option(&wop->wo_cocu);
check_string_option(&wop->wo_briopt);
check_string_option(&wop->wo_winhl);
- check_string_option(&wop->wo_fcs);
check_string_option(&wop->wo_lcs);
+ check_string_option(&wop->wo_fcs);
check_string_option(&wop->wo_ve);
- check_string_option((char_u **)&wop->wo_wbr);
+ check_string_option(&wop->wo_wbr);
}
/// Free the allocated memory inside a winopt_T.
@@ -4345,10 +4350,10 @@ void clear_winopt(winopt_T *wop)
clear_string_option(&wop->wo_cocu);
clear_string_option(&wop->wo_briopt);
clear_string_option(&wop->wo_winhl);
- clear_string_option(&wop->wo_fcs);
clear_string_option(&wop->wo_lcs);
+ clear_string_option(&wop->wo_fcs);
clear_string_option(&wop->wo_ve);
- clear_string_option((char_u **)&wop->wo_wbr);
+ clear_string_option(&wop->wo_wbr);
}
void didset_window_options(win_T *wp, bool valid_cursor)
@@ -4430,7 +4435,7 @@ void buf_copy_options(buf_T *buf, int flags)
// (jumping back to a help file with CTRL-T or CTRL-O)
dont_do_help = ((flags & BCO_NOHELP) && buf->b_help) || buf->b_p_initialized;
if (dont_do_help) { // don't free b_p_isk
- save_p_isk = buf->b_p_isk;
+ save_p_isk = (char_u *)buf->b_p_isk;
buf->b_p_isk = NULL;
}
// Always free the allocated strings. If not already initialized,
@@ -4438,19 +4443,19 @@ void buf_copy_options(buf_T *buf, int flags)
if (!buf->b_p_initialized) {
free_buf_options(buf, true);
buf->b_p_ro = false; // don't copy readonly
- buf->b_p_fenc = vim_strsave(p_fenc);
+ buf->b_p_fenc = xstrdup(p_fenc);
switch (*p_ffs) {
case 'm':
- buf->b_p_ff = vim_strsave((char_u *)FF_MAC);
+ buf->b_p_ff = xstrdup(FF_MAC);
break;
case 'd':
- buf->b_p_ff = vim_strsave((char_u *)FF_DOS);
+ buf->b_p_ff = xstrdup(FF_DOS);
break;
case 'u':
- buf->b_p_ff = vim_strsave((char_u *)FF_UNIX);
+ buf->b_p_ff = xstrdup(FF_UNIX);
break;
default:
- buf->b_p_ff = vim_strsave(p_ff);
+ buf->b_p_ff = xstrdup(p_ff);
break;
}
buf->b_p_bh = empty_option;
@@ -4495,44 +4500,42 @@ void buf_copy_options(buf_T *buf, int flags)
buf->b_p_swf = p_swf;
COPY_OPT_SCTX(buf, BV_SWF);
}
- buf->b_p_cpt = vim_strsave(p_cpt);
+ buf->b_p_cpt = xstrdup(p_cpt);
COPY_OPT_SCTX(buf, BV_CPT);
#ifdef BACKSLASH_IN_FILENAME
buf->b_p_csl = vim_strsave(p_csl);
COPY_OPT_SCTX(buf, BV_CSL);
#endif
- buf->b_p_cfu = vim_strsave(p_cfu);
+ buf->b_p_cfu = xstrdup(p_cfu);
COPY_OPT_SCTX(buf, BV_CFU);
- buf->b_p_ofu = vim_strsave(p_ofu);
+ buf->b_p_ofu = xstrdup(p_ofu);
COPY_OPT_SCTX(buf, BV_OFU);
- buf->b_p_urf = vim_strsave(p_urf);
+ buf->b_p_urf = xstrdup(p_urf);
COPY_OPT_SCTX(buf, BV_URF);
- buf->b_p_tfu = vim_strsave(p_tfu);
+ buf->b_p_tfu = xstrdup(p_tfu);
COPY_OPT_SCTX(buf, BV_TFU);
buf->b_p_sts = p_sts;
COPY_OPT_SCTX(buf, BV_STS);
buf->b_p_sts_nopaste = p_sts_nopaste;
- buf->b_p_vsts = vim_strsave(p_vsts);
+ buf->b_p_vsts = xstrdup(p_vsts);
COPY_OPT_SCTX(buf, BV_VSTS);
if (p_vsts && p_vsts != empty_option) {
(void)tabstop_set(p_vsts, &buf->b_p_vsts_array);
} else {
buf->b_p_vsts_array = NULL;
}
- buf->b_p_vsts_nopaste = p_vsts_nopaste
- ? vim_strsave(p_vsts_nopaste)
- : NULL;
- buf->b_p_com = vim_strsave(p_com);
+ buf->b_p_vsts_nopaste = p_vsts_nopaste ? xstrdup(p_vsts_nopaste) : NULL;
+ buf->b_p_com = xstrdup(p_com);
COPY_OPT_SCTX(buf, BV_COM);
- buf->b_p_cms = vim_strsave(p_cms);
+ buf->b_p_cms = xstrdup(p_cms);
COPY_OPT_SCTX(buf, BV_CMS);
- buf->b_p_fo = vim_strsave(p_fo);
+ buf->b_p_fo = xstrdup(p_fo);
COPY_OPT_SCTX(buf, BV_FO);
- buf->b_p_flp = vim_strsave(p_flp);
+ buf->b_p_flp = xstrdup(p_flp);
COPY_OPT_SCTX(buf, BV_FLP);
- buf->b_p_nf = vim_strsave(p_nf);
+ buf->b_p_nf = xstrdup(p_nf);
COPY_OPT_SCTX(buf, BV_NF);
- buf->b_p_mps = vim_strsave(p_mps);
+ buf->b_p_mps = xstrdup(p_mps);
COPY_OPT_SCTX(buf, BV_MPS);
buf->b_p_si = p_si;
COPY_OPT_SCTX(buf, BV_SI);
@@ -4542,18 +4545,18 @@ void buf_copy_options(buf_T *buf, int flags)
COPY_OPT_SCTX(buf, BV_CI);
buf->b_p_cin = p_cin;
COPY_OPT_SCTX(buf, BV_CIN);
- buf->b_p_cink = vim_strsave(p_cink);
+ buf->b_p_cink = xstrdup(p_cink);
COPY_OPT_SCTX(buf, BV_CINK);
- buf->b_p_cino = vim_strsave(p_cino);
+ buf->b_p_cino = xstrdup(p_cino);
COPY_OPT_SCTX(buf, BV_CINO);
- buf->b_p_cinsd = vim_strsave(p_cinsd);
+ buf->b_p_cinsd = xstrdup(p_cinsd);
COPY_OPT_SCTX(buf, BV_CINSD);
// Don't copy 'filetype', it must be detected
buf->b_p_ft = empty_option;
buf->b_p_pi = p_pi;
COPY_OPT_SCTX(buf, BV_PI);
- buf->b_p_cinw = vim_strsave(p_cinw);
+ buf->b_p_cinw = xstrdup(p_cinw);
COPY_OPT_SCTX(buf, BV_CINW);
buf->b_p_lisp = p_lisp;
COPY_OPT_SCTX(buf, BV_LISP);
@@ -4562,25 +4565,25 @@ void buf_copy_options(buf_T *buf, int flags)
buf->b_p_smc = p_smc;
COPY_OPT_SCTX(buf, BV_SMC);
buf->b_s.b_syn_isk = empty_option;
- buf->b_s.b_p_spc = vim_strsave(p_spc);
+ buf->b_s.b_p_spc = xstrdup(p_spc);
COPY_OPT_SCTX(buf, BV_SPC);
(void)compile_cap_prog(&buf->b_s);
- buf->b_s.b_p_spf = vim_strsave(p_spf);
+ buf->b_s.b_p_spf = xstrdup(p_spf);
COPY_OPT_SCTX(buf, BV_SPF);
- buf->b_s.b_p_spl = vim_strsave(p_spl);
+ buf->b_s.b_p_spl = xstrdup(p_spl);
COPY_OPT_SCTX(buf, BV_SPL);
- buf->b_s.b_p_spo = vim_strsave(p_spo);
+ buf->b_s.b_p_spo = xstrdup(p_spo);
COPY_OPT_SCTX(buf, BV_SPO);
- buf->b_p_inde = vim_strsave(p_inde);
+ buf->b_p_inde = xstrdup(p_inde);
COPY_OPT_SCTX(buf, BV_INDE);
- buf->b_p_indk = vim_strsave(p_indk);
+ buf->b_p_indk = xstrdup(p_indk);
COPY_OPT_SCTX(buf, BV_INDK);
buf->b_p_fp = empty_option;
- buf->b_p_fex = vim_strsave(p_fex);
+ buf->b_p_fex = xstrdup(p_fex);
COPY_OPT_SCTX(buf, BV_FEX);
- buf->b_p_sua = vim_strsave(p_sua);
+ buf->b_p_sua = xstrdup(p_sua);
COPY_OPT_SCTX(buf, BV_SUA);
- buf->b_p_keymap = vim_strsave(p_keymap);
+ buf->b_p_keymap = xstrdup(p_keymap);
COPY_OPT_SCTX(buf, BV_KMAP);
buf->b_kmap_state |= KEYMAP_INIT;
// This isn't really an option, but copying the langmap and IME
@@ -4607,12 +4610,12 @@ void buf_copy_options(buf_T *buf, int flags)
buf->b_tc_flags = 0;
buf->b_p_def = empty_option;
buf->b_p_inc = empty_option;
- buf->b_p_inex = vim_strsave(p_inex);
+ buf->b_p_inex = xstrdup(p_inex);
COPY_OPT_SCTX(buf, BV_INEX);
buf->b_p_dict = empty_option;
buf->b_p_tsr = empty_option;
buf->b_p_tsrfu = empty_option;
- buf->b_p_qe = vim_strsave(p_qe);
+ buf->b_p_qe = xstrdup(p_qe);
COPY_OPT_SCTX(buf, BV_QE);
buf->b_p_udf = p_udf;
COPY_OPT_SCTX(buf, BV_UDF);
@@ -4626,19 +4629,19 @@ void buf_copy_options(buf_T *buf, int flags)
* or to a help buffer.
*/
if (dont_do_help) {
- buf->b_p_isk = save_p_isk;
+ buf->b_p_isk = (char *)save_p_isk;
if (p_vts && p_vts != empty_option && !buf->b_p_vts_array) {
(void)tabstop_set(p_vts, &buf->b_p_vts_array);
} else {
buf->b_p_vts_array = NULL;
}
} else {
- buf->b_p_isk = vim_strsave(p_isk);
+ buf->b_p_isk = xstrdup(p_isk);
COPY_OPT_SCTX(buf, BV_ISK);
did_isk = true;
buf->b_p_ts = p_ts;
COPY_OPT_SCTX(buf, BV_TS);
- buf->b_p_vts = vim_strsave(p_vts);
+ buf->b_p_vts = xstrdup(p_vts);
COPY_OPT_SCTX(buf, BV_VTS);
if (p_vts && p_vts != empty_option && !buf->b_p_vts_array) {
(void)tabstop_set(p_vts, &buf->b_p_vts_array);
@@ -4959,7 +4962,7 @@ void ExpandOldSetting(int *num_file, char ***file)
if (expand_option_idx >= 0) {
// Put string of option value in NameBuff.
option_value2string(&options[expand_option_idx], expand_option_flags);
- var = NameBuff;
+ var = (char_u *)NameBuff;
} else {
var = (char_u *)"";
}
@@ -4992,9 +4995,7 @@ void ExpandOldSetting(int *num_file, char ***file)
/// @param opt_flags OPT_GLOBAL and/or OPT_LOCAL
static void option_value2string(vimoption_T *opp, int opt_flags)
{
- char_u *varp;
-
- varp = get_varp_scope(opp, opt_flags);
+ char_u *varp = (char_u *)get_varp_scope(opp, opt_flags);
if (opp->flags & P_NUM) {
long wc = 0;
@@ -5016,7 +5017,7 @@ static void option_value2string(vimoption_T *opp, int opt_flags)
} else if (opp->flags & P_EXPAND) {
home_replace(NULL, (char *)varp, (char *)NameBuff, MAXPATHL, false);
// Translate 'pastetoggle' into special key names.
- } else if ((char_u **)opp->var == &p_pt) {
+ } else if ((char **)opp->var == &p_pt) {
str2specialbuf((const char *)p_pt, (char *)NameBuff, MAXPATHL);
} else {
STRLCPY(NameBuff, varp, MAXPATHL);
@@ -5038,25 +5039,14 @@ static int wc_use_keyname(char_u *varp, long *wcp)
return false;
}
-/// Return true if format option 'x' is in effect.
-/// Take care of no formatting when 'paste' is set.
-bool has_format_option(int x)
- FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
-{
- if (p_paste) {
- return false;
- }
- return vim_strchr((char *)curbuf->b_p_fo, x) != NULL;
-}
-
/// @returns true if "x" is present in 'shortmess' option, or
/// 'shortmess' contains 'a' and "x" is present in SHM_ALL_ABBREVIATIONS.
bool shortmess(int x)
{
return (p_shm != NULL
- && (vim_strchr((char *)p_shm, x) != NULL
- || (vim_strchr((char *)p_shm, 'a') != NULL
- && vim_strchr((char *)SHM_ALL_ABBREVIATIONS, x) != NULL)));
+ && (vim_strchr(p_shm, x) != NULL
+ || (vim_strchr(p_shm, 'a') != NULL
+ && vim_strchr(SHM_ALL_ABBREVIATIONS, x) != NULL)));
}
/// paste_option_changed() - Called after p_paste was set or reset.
@@ -5086,7 +5076,7 @@ static void paste_option_changed(void)
xfree(buf->b_p_vsts_nopaste);
}
buf->b_p_vsts_nopaste = buf->b_p_vsts && buf->b_p_vsts != empty_option
- ? vim_strsave(buf->b_p_vsts)
+ ? xstrdup(buf->b_p_vsts)
: NULL;
}
@@ -5105,9 +5095,7 @@ static void paste_option_changed(void)
if (p_vsts_nopaste) {
xfree(p_vsts_nopaste);
}
- p_vsts_nopaste = p_vsts && p_vsts != empty_option
- ? vim_strsave(p_vsts)
- : NULL;
+ p_vsts_nopaste = p_vsts && p_vsts != empty_option ? xstrdup(p_vsts) : NULL;
}
// Always set the option values, also when 'paste' is set when it is
@@ -5157,9 +5145,7 @@ static void paste_option_changed(void)
if (buf->b_p_vsts) {
free_string_option(buf->b_p_vsts);
}
- buf->b_p_vsts = buf->b_p_vsts_nopaste
- ? vim_strsave(buf->b_p_vsts_nopaste)
- : empty_option;
+ buf->b_p_vsts = buf->b_p_vsts_nopaste ? xstrdup(buf->b_p_vsts_nopaste) : empty_option;
xfree(buf->b_p_vsts_array);
if (buf->b_p_vsts && buf->b_p_vsts != empty_option) {
(void)tabstop_set(buf->b_p_vsts, &buf->b_p_vsts_array);
@@ -5186,7 +5172,7 @@ static void paste_option_changed(void)
if (p_vsts) {
free_string_option(p_vsts);
}
- p_vsts = p_vsts_nopaste ? vim_strsave(p_vsts_nopaste) : empty_option;
+ p_vsts = p_vsts_nopaste ? xstrdup(p_vsts_nopaste) : empty_option;
}
old_p_paste = p_paste;
@@ -5254,16 +5240,16 @@ void fill_breakat_flags(void)
}
if (p_breakat != NULL) {
- for (p = p_breakat; *p; p++) {
+ for (p = (char_u *)p_breakat; *p; p++) {
breakat_flags[*p] = true;
}
}
}
/// fill_culopt_flags() -- called when 'culopt' changes value
-int fill_culopt_flags(char_u *val, win_T *wp)
+int fill_culopt_flags(char *val, win_T *wp)
{
- char_u *p;
+ char *p;
char_u culopt_flags_new = 0;
if (val == NULL) {
@@ -5341,59 +5327,6 @@ int option_set_callback_func(char_u *optval, Callback *optcb)
return OK;
}
-/// Read the 'wildmode' option, fill wim_flags[].
-int check_opt_wim(void)
-{
- char_u new_wim_flags[4];
- char_u *p;
- int i;
- int idx = 0;
-
- for (i = 0; i < 4; i++) {
- new_wim_flags[i] = 0;
- }
-
- for (p = p_wim; *p; p++) {
- for (i = 0; ASCII_ISALPHA(p[i]); i++) {}
- if (p[i] != NUL && p[i] != ',' && p[i] != ':') {
- return FAIL;
- }
- if (i == 7 && STRNCMP(p, "longest", 7) == 0) {
- new_wim_flags[idx] |= WIM_LONGEST;
- } else if (i == 4 && STRNCMP(p, "full", 4) == 0) {
- new_wim_flags[idx] |= WIM_FULL;
- } else if (i == 4 && STRNCMP(p, "list", 4) == 0) {
- new_wim_flags[idx] |= WIM_LIST;
- } else if (i == 8 && STRNCMP(p, "lastused", 8) == 0) {
- new_wim_flags[idx] |= WIM_BUFLASTUSED;
- } else {
- return FAIL;
- }
- p += i;
- if (*p == NUL) {
- break;
- }
- if (*p == ',') {
- if (idx == 3) {
- return FAIL;
- }
- idx++;
- }
- }
-
- // fill remaining entries with last flag
- while (idx < 3) {
- new_wim_flags[idx + 1] = new_wim_flags[idx];
- idx++;
- }
-
- // only when there are no errors, wim_flags[] is changed
- for (i = 0; i < 4; i++) {
- wim_flags[i] = new_wim_flags[i];
- }
- return OK;
-}
-
/// Check if backspacing over something is allowed.
/// @param what BS_INDENT, BS_EOL, BS_START, or BS_NOSTOP
bool can_bs(int what)
@@ -5411,99 +5344,7 @@ bool can_bs(int what)
case '0':
return false;
}
- return vim_strchr((char *)p_bs, what) != NULL;
-}
-
-/// Save the current values of 'fileformat' and 'fileencoding', so that we know
-/// the file must be considered changed when the value is different.
-void save_file_ff(buf_T *buf)
-{
- buf->b_start_ffc = *buf->b_p_ff;
- buf->b_start_eol = buf->b_p_eol;
- buf->b_start_bomb = buf->b_p_bomb;
-
- // Only use free/alloc when necessary, they take time.
- if (buf->b_start_fenc == NULL
- || STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0) {
- xfree(buf->b_start_fenc);
- buf->b_start_fenc = (char *)vim_strsave(buf->b_p_fenc);
- }
-}
-
-/// Return true if 'fileformat' and/or 'fileencoding' has a different value
-/// from when editing started (save_file_ff() called).
-/// Also when 'endofline' was changed and 'binary' is set, or when 'bomb' was
-/// changed and 'binary' is not set.
-/// Also when 'endofline' was changed and 'fixeol' is not set.
-/// When "ignore_empty" is true don't consider a new, empty buffer to be
-/// changed.
-bool file_ff_differs(buf_T *buf, bool ignore_empty)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
-{
- // In a buffer that was never loaded the options are not valid.
- if (buf->b_flags & BF_NEVERLOADED) {
- return false;
- }
- if (ignore_empty
- && (buf->b_flags & BF_NEW)
- && buf->b_ml.ml_line_count == 1
- && *ml_get_buf(buf, (linenr_T)1, false) == NUL) {
- return false;
- }
- if (buf->b_start_ffc != *buf->b_p_ff) {
- return true;
- }
- if ((buf->b_p_bin || !buf->b_p_fixeol) && buf->b_start_eol != buf->b_p_eol) {
- return true;
- }
- if (!buf->b_p_bin && buf->b_start_bomb != buf->b_p_bomb) {
- return true;
- }
- if (buf->b_start_fenc == NULL) {
- return *buf->b_p_fenc != NUL;
- }
- return STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0;
-}
-
-/// This is called when 'breakindentopt' is changed and when a window is
-/// initialized
-bool briopt_check(win_T *wp)
-{
- int bri_shift = 0;
- int bri_min = 20;
- bool bri_sbr = false;
- int bri_list = 0;
-
- char *p = (char *)wp->w_p_briopt;
- while (*p != NUL) {
- if (STRNCMP(p, "shift:", 6) == 0
- && ((p[6] == '-' && ascii_isdigit(p[7])) || ascii_isdigit(p[6]))) {
- p += 6;
- bri_shift = getdigits_int(&p, true, 0);
- } else if (STRNCMP(p, "min:", 4) == 0 && ascii_isdigit(p[4])) {
- p += 4;
- bri_min = getdigits_int(&p, true, 0);
- } else if (STRNCMP(p, "sbr", 3) == 0) {
- p += 3;
- bri_sbr = true;
- } else if (STRNCMP(p, "list:", 5) == 0) {
- p += 5;
- bri_list = (int)getdigits(&p, false, 0);
- }
- if (*p != ',' && *p != NUL) {
- return false;
- }
- if (*p == ',') {
- p++;
- }
- }
-
- wp->w_briopt_shift = bri_shift;
- wp->w_briopt_min = bri_min;
- wp->w_briopt_sbr = bri_sbr;
- wp->w_briopt_list = bri_list;
-
- return true;
+ return vim_strchr(p_bs, what) != NULL;
}
/// Get the local or global value of 'backupcopy'.
@@ -5528,19 +5369,19 @@ char_u *get_showbreak_value(win_T *const win)
FUNC_ATTR_WARN_UNUSED_RESULT
{
if (win->w_p_sbr == NULL || *win->w_p_sbr == NUL) {
- return p_sbr;
+ return (char_u *)p_sbr;
}
if (STRCMP(win->w_p_sbr, "NONE") == 0) {
- return empty_option;
+ return (char_u *)empty_option;
}
- return win->w_p_sbr;
+ return (char_u *)win->w_p_sbr;
}
/// Return the current end-of-line type: EOL_DOS, EOL_UNIX or EOL_MAC.
int get_fileformat(const buf_T *buf)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- int c = *buf->b_p_ff;
+ int c = (unsigned char)(*buf->b_p_ff);
if (buf->b_p_bin || c == 'u') {
return EOL_UNIX;
@@ -5567,7 +5408,7 @@ int get_fileformat_force(const buf_T *buf, const exarg_T *eap)
? (eap->force_bin == FORCE_BIN) : buf->b_p_bin) {
return EOL_UNIX;
}
- c = *buf->b_p_ff;
+ c = (unsigned char)(*buf->b_p_ff);
}
if (c == 'u') {
return EOL_UNIX;
@@ -5624,7 +5465,7 @@ void set_fileformat(int eol_style, int opt_flags)
}
/// Skip to next part of an option argument: skip space and comma
-char_u *skip_to_option_part(const char_u *p)
+char *skip_to_option_part(const char *p)
{
if (*p == ',') {
p++;
@@ -5632,7 +5473,7 @@ char_u *skip_to_option_part(const char_u *p)
while (*p == ' ') {
p++;
}
- return (char_u *)p;
+ return (char *)p;
}
/// Isolate one part of a string option separated by `sep_chars`.
@@ -5667,7 +5508,7 @@ size_t copy_option_part(char **option, char *buf, size_t maxlen, char *sep_chars
if (*p != NUL && *p != ',') { // skip non-standard separator
p++;
}
- p = (char *)skip_to_option_part((char_u *)p); // p points to next file name
+ p = skip_to_option_part(p); // p points to next file name
*option = p;
return len;
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index af2383d91d..c2c2dfaa45 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -258,7 +258,7 @@ enum {
SHM_SEARCHCOUNT = 'S', ///< Search sats: '[1/10]'
};
/// Represented by 'a' flag.
-#define SHM_ALL_ABBREVIATIONS ((char_u[]) { \
+#define SHM_ALL_ABBREVIATIONS ((char[]) { \
SHM_RO, SHM_MOD, SHM_FILE, SHM_LAST, SHM_TEXT, SHM_LINES, SHM_NEW, SHM_WRI, \
0, \
})
@@ -384,7 +384,7 @@ enum {
*/
EXTERN long p_aleph; // 'aleph'
-EXTERN char_u *p_ambw; ///< 'ambiwidth'
+EXTERN char *p_ambw; ///< 'ambiwidth'
EXTERN int p_acd; ///< 'autochdir'
EXTERN int p_ai; ///< 'autoindent'
EXTERN int p_bin; ///< 'binary'
@@ -392,29 +392,29 @@ EXTERN int p_bomb; ///< 'bomb'
EXTERN int p_bl; ///< 'buflisted'
EXTERN int p_cin; ///< 'cindent'
EXTERN long p_channel; ///< 'channel'
-EXTERN char_u *p_cink; ///< 'cinkeys'
-EXTERN char_u *p_cinsd; ///< 'cinscopedecls'
-EXTERN char_u *p_cinw; ///< 'cinwords'
-EXTERN char_u *p_cfu; ///< 'completefunc'
-EXTERN char_u *p_ofu; ///< 'omnifunc'
-EXTERN char_u *p_tsrfu; ///< 'thesaurusfunc'
+EXTERN char *p_cink; ///< 'cinkeys'
+EXTERN char *p_cinsd; ///< 'cinscopedecls'
+EXTERN char *p_cinw; ///< 'cinwords'
+EXTERN char *p_cfu; ///< 'completefunc'
+EXTERN char *p_ofu; ///< 'omnifunc'
+EXTERN char *p_tsrfu; ///< 'thesaurusfunc'
EXTERN int p_ci; ///< 'copyindent'
EXTERN int p_ar; // 'autoread'
EXTERN int p_aw; // 'autowrite'
EXTERN int p_awa; // 'autowriteall'
-EXTERN char_u *p_bs; // 'backspace'
-EXTERN char_u *p_bg; // 'background'
+EXTERN char *p_bs; // 'backspace'
+EXTERN char *p_bg; // 'background'
EXTERN int p_bk; // 'backup'
-EXTERN char_u *p_bkc; // 'backupcopy'
+EXTERN char *p_bkc; // 'backupcopy'
EXTERN unsigned int bkc_flags; ///< flags from 'backupcopy'
#define BKC_YES 0x001
#define BKC_AUTO 0x002
#define BKC_NO 0x004
#define BKC_BREAKSYMLINK 0x008
#define BKC_BREAKHARDLINK 0x010
-EXTERN char_u *p_bdir; // 'backupdir'
-EXTERN char_u *p_bex; // 'backupext'
-EXTERN char_u *p_bo; // 'belloff'
+EXTERN char *p_bdir; // 'backupdir'
+EXTERN char *p_bex; // 'backupext'
+EXTERN char *p_bo; // 'belloff'
EXTERN char breakat_flags[256]; // which characters are in 'breakat'
EXTERN unsigned bo_flags;
@@ -440,56 +440,56 @@ EXTERN unsigned bo_flags;
#define BO_WILD 0x40000
EXTERN char_u *p_bsk; // 'backupskip'
-EXTERN char_u *p_breakat; // 'breakat'
-EXTERN char_u *p_bh; ///< 'bufhidden'
-EXTERN char_u *p_bt; ///< 'buftype'
-EXTERN char_u *p_cmp; // 'casemap'
+EXTERN char *p_breakat; // 'breakat'
+EXTERN char *p_bh; ///< 'bufhidden'
+EXTERN char *p_bt; ///< 'buftype'
+EXTERN char *p_cmp; // 'casemap'
EXTERN unsigned cmp_flags;
#define CMP_INTERNAL 0x001
#define CMP_KEEPASCII 0x002
-EXTERN char_u *p_enc; // 'encoding'
-EXTERN int p_deco; // 'delcombine'
-EXTERN char_u *p_ccv; // 'charconvert'
-EXTERN char_u *p_cino; ///< 'cinoptions'
-EXTERN char_u *p_cedit; // 'cedit'
-EXTERN char_u *p_cb; // 'clipboard'
+EXTERN char *p_enc; // 'encoding'
+EXTERN int p_deco; // 'delcombine'
+EXTERN char *p_ccv; // 'charconvert'
+EXTERN char *p_cino; ///< 'cinoptions'
+EXTERN char *p_cedit; // 'cedit'
+EXTERN char *p_cb; // 'clipboard'
EXTERN unsigned cb_flags;
#define CB_UNNAMED 0x001
#define CB_UNNAMEDPLUS 0x002
#define CB_UNNAMEDMASK (CB_UNNAMED | CB_UNNAMEDPLUS)
EXTERN long p_cwh; // 'cmdwinheight'
EXTERN long p_ch; // 'cmdheight'
-EXTERN char_u *p_cms; ///< 'commentstring'
-EXTERN char_u *p_cpt; ///< 'complete'
+EXTERN char *p_cms; ///< 'commentstring'
+EXTERN char *p_cpt; ///< 'complete'
EXTERN long p_columns; // 'columns'
EXTERN int p_confirm; // 'confirm'
-EXTERN char_u *p_cot; // 'completeopt'
+EXTERN char *p_cot; // 'completeopt'
#ifdef BACKSLASH_IN_FILENAME
EXTERN char_u *p_csl; // 'completeslash'
#endif
EXTERN long p_pb; // 'pumblend'
EXTERN long p_ph; // 'pumheight'
EXTERN long p_pw; // 'pumwidth'
-EXTERN char_u *p_com; ///< 'comments'
+EXTERN char *p_com; ///< 'comments'
EXTERN char *p_cpo; // 'cpoptions'
-EXTERN char_u *p_csprg; // 'cscopeprg'
+EXTERN char *p_csprg; // 'cscopeprg'
EXTERN int p_csre; // 'cscoperelative'
-EXTERN char_u *p_csqf; // 'cscopequickfix'
+EXTERN char *p_csqf; // 'cscopequickfix'
#define CSQF_CMDS "sgdctefia"
#define CSQF_FLAGS "+-0"
EXTERN int p_cst; // 'cscopetag'
EXTERN long p_csto; // 'cscopetagorder'
EXTERN long p_cspc; // 'cscopepathcomp'
EXTERN int p_csverbose; // 'cscopeverbose'
-EXTERN char_u *p_debug; // 'debug'
-EXTERN char_u *p_def; // 'define'
-EXTERN char_u *p_inc;
-EXTERN char_u *p_dip; // 'diffopt'
-EXTERN char_u *p_dex; // 'diffexpr'
-EXTERN char_u *p_dict; // 'dictionary'
+EXTERN char *p_debug; // 'debug'
+EXTERN char *p_def; // 'define'
+EXTERN char *p_inc;
+EXTERN char *p_dip; // 'diffopt'
+EXTERN char *p_dex; // 'diffexpr'
+EXTERN char *p_dict; // 'dictionary'
EXTERN int p_dg; // 'digraph'
-EXTERN char_u *p_dir; // 'directory'
-EXTERN char_u *p_dy; // 'display'
+EXTERN char *p_dir; // 'directory'
+EXTERN char *p_dy; // 'display'
EXTERN unsigned dy_flags;
#define DY_LASTLINE 0x001
#define DY_TRUNCATE 0x002
@@ -497,30 +497,30 @@ EXTERN unsigned dy_flags;
// code should use msg_use_msgsep() to check if msgsep is active
#define DY_MSGSEP 0x008
EXTERN int p_ed; // 'edcompatible'
-EXTERN char_u *p_ead; // 'eadirection'
+EXTERN char *p_ead; // 'eadirection'
EXTERN int p_emoji; // 'emoji'
EXTERN int p_ea; // 'equalalways'
-EXTERN char_u *p_ep; // 'equalprg'
+EXTERN char_u *p_ep; // 'equalprg'
EXTERN int p_eb; // 'errorbells'
-EXTERN char_u *p_ef; // 'errorfile'
-EXTERN char *p_efm; // 'errorformat'
-EXTERN char *p_gefm; // 'grepformat'
-EXTERN char_u *p_gp; // 'grepprg'
+EXTERN char_u *p_ef; // 'errorfile'
+EXTERN char *p_efm; // 'errorformat'
+EXTERN char *p_gefm; // 'grepformat'
+EXTERN char_u *p_gp; // 'grepprg'
EXTERN int p_eol; ///< 'endofline'
-EXTERN char_u *p_ei; // 'eventignore'
+EXTERN char *p_ei; // 'eventignore'
EXTERN int p_et; ///< 'expandtab'
EXTERN int p_exrc; // 'exrc'
-EXTERN char_u *p_fenc; ///< 'fileencoding'
-EXTERN char_u *p_fencs; // 'fileencodings'
-EXTERN char_u *p_ff; ///< 'fileformat'
-EXTERN char *p_ffs; // 'fileformats'
+EXTERN char *p_fenc; ///< 'fileencoding'
+EXTERN char *p_fencs; // 'fileencodings'
+EXTERN char *p_ff; ///< 'fileformat'
+EXTERN char *p_ffs; // 'fileformats'
EXTERN int p_fic; // 'fileignorecase'
-EXTERN char_u *p_ft; ///< 'filetype'
-EXTERN char_u *p_fcs; ///< 'fillchar'
+EXTERN char *p_ft; ///< 'filetype'
+EXTERN char *p_fcs; ///< 'fillchar'
EXTERN int p_fixeol; ///< 'fixendofline'
-EXTERN char_u *p_fcl; // 'foldclose'
+EXTERN char *p_fcl; // 'foldclose'
EXTERN long p_fdls; // 'foldlevelstart'
-EXTERN char_u *p_fdo; // 'foldopen'
+EXTERN char *p_fdo; // 'foldopen'
EXTERN unsigned fdo_flags;
#define FDO_ALL 0x001
#define FDO_BLOCK 0x002
@@ -533,76 +533,76 @@ EXTERN unsigned fdo_flags;
#define FDO_INSERT 0x100
#define FDO_UNDO 0x200
#define FDO_JUMP 0x400
-EXTERN char_u *p_fex; ///< 'formatexpr'
-EXTERN char_u *p_flp; ///< 'formatlistpat'
-EXTERN char_u *p_fo; ///< 'formatoptions'
-EXTERN char_u *p_fp; // 'formatprg'
+EXTERN char *p_fex; ///< 'formatexpr'
+EXTERN char *p_flp; ///< 'formatlistpat'
+EXTERN char *p_fo; ///< 'formatoptions'
+EXTERN char_u *p_fp; // 'formatprg'
EXTERN int p_fs; // 'fsync'
EXTERN int p_gd; // 'gdefault'
-EXTERN char_u *p_pdev; // 'printdevice'
-EXTERN char_u *p_penc; // 'printencoding'
-EXTERN char_u *p_pexpr; // 'printexpr'
-EXTERN char_u *p_pmfn; // 'printmbfont'
-EXTERN char_u *p_pmcs; // 'printmbcharset'
-EXTERN char_u *p_pfn; // 'printfont'
-EXTERN char_u *p_popt; // 'printoptions'
-EXTERN char_u *p_header; // 'printheader'
-EXTERN char_u *p_guicursor; // 'guicursor'
-EXTERN char_u *p_guifont; // 'guifont'
-EXTERN char_u *p_guifontwide; // 'guifontwide'
-EXTERN char_u *p_hf; // 'helpfile'
+EXTERN char_u *p_pdev; // 'printdevice'
+EXTERN char *p_penc; // 'printencoding'
+EXTERN char *p_pexpr; // 'printexpr'
+EXTERN char *p_pmfn; // 'printmbfont'
+EXTERN char *p_pmcs; // 'printmbcharset'
+EXTERN char *p_pfn; // 'printfont'
+EXTERN char *p_popt; // 'printoptions'
+EXTERN char_u *p_header; // 'printheader'
+EXTERN char *p_guicursor; // 'guicursor'
+EXTERN char_u *p_guifont; // 'guifont'
+EXTERN char_u *p_guifontwide; // 'guifontwide'
+EXTERN char *p_hf; // 'helpfile'
EXTERN long p_hh; // 'helpheight'
-EXTERN char_u *p_hlg; // 'helplang'
+EXTERN char_u *p_hlg; // 'helplang'
EXTERN int p_hid; // 'hidden'
-EXTERN char_u *p_hl; // 'highlight'
+EXTERN char *p_hl; // 'highlight'
EXTERN int p_hls; // 'hlsearch'
EXTERN long p_hi; // 'history'
EXTERN int p_hkmap; // 'hkmap'
EXTERN int p_hkmapp; // 'hkmapp'
EXTERN int p_arshape; // 'arabicshape'
EXTERN int p_icon; // 'icon'
-EXTERN char_u *p_iconstring; // 'iconstring'
+EXTERN char *p_iconstring; // 'iconstring'
EXTERN int p_ic; // 'ignorecase'
EXTERN long p_iminsert; ///< 'iminsert'
EXTERN long p_imsearch; ///< 'imsearch'
EXTERN int p_inf; ///< 'infercase'
-EXTERN char_u *p_inex; ///< 'includeexpr'
+EXTERN char *p_inex; ///< 'includeexpr'
EXTERN int p_is; // 'incsearch'
-EXTERN char_u *p_inde; ///< 'indentexpr'
-EXTERN char_u *p_indk; ///< 'indentkeys'
-EXTERN char_u *p_icm; // 'inccommand'
-EXTERN char_u *p_isf; // 'isfname'
-EXTERN char_u *p_isi; // 'isident'
-EXTERN char_u *p_isk; ///< 'iskeyword'
-EXTERN char_u *p_isp; // 'isprint'
+EXTERN char *p_inde; ///< 'indentexpr'
+EXTERN char *p_indk; ///< 'indentkeys'
+EXTERN char *p_icm; // 'inccommand'
+EXTERN char *p_isf; // 'isfname'
+EXTERN char *p_isi; // 'isident'
+EXTERN char *p_isk; ///< 'iskeyword'
+EXTERN char *p_isp; // 'isprint'
EXTERN int p_js; // 'joinspaces'
-EXTERN char_u *p_jop; // 'jumpooptions'
+EXTERN char *p_jop; // 'jumpooptions'
EXTERN unsigned jop_flags;
#define JOP_STACK 0x01
#define JOP_VIEW 0x02
-EXTERN char_u *p_keymap; ///< 'keymap'
-EXTERN char_u *p_kp; // 'keywordprg'
-EXTERN char_u *p_km; // 'keymodel'
-EXTERN char_u *p_langmap; // 'langmap'
+EXTERN char *p_keymap; ///< 'keymap'
+EXTERN char_u *p_kp; // 'keywordprg'
+EXTERN char *p_km; // 'keymodel'
+EXTERN char *p_langmap; // 'langmap'
EXTERN int p_lnr; // 'langnoremap'
EXTERN int p_lrm; // 'langremap'
-EXTERN char_u *p_lm; // 'langmenu'
-EXTERN long p_lines; // 'lines'
-EXTERN long p_linespace; // 'linespace'
+EXTERN char_u *p_lm; // 'langmenu'
+EXTERN long p_lines; // 'lines'
+EXTERN long p_linespace; // 'linespace'
EXTERN int p_lisp; ///< 'lisp'
-EXTERN char_u *p_lispwords; // 'lispwords'
+EXTERN char_u *p_lispwords; // 'lispwords'
EXTERN long p_ls; // 'laststatus'
EXTERN long p_stal; // 'showtabline'
-EXTERN char_u *p_lcs; // 'listchars'
+EXTERN char *p_lcs; // 'listchars'
EXTERN int p_lz; // 'lazyredraw'
EXTERN int p_lpl; // 'loadplugins'
EXTERN int p_magic; // 'magic'
-EXTERN char_u *p_menc; // 'makeencoding'
-EXTERN char *p_mef; // 'makeef'
-EXTERN char_u *p_mp; // 'makeprg'
-EXTERN char_u *p_mps; ///< 'matchpairs'
-EXTERN char_u *p_cc; // 'colorcolumn'
+EXTERN char *p_menc; // 'makeencoding'
+EXTERN char *p_mef; // 'makeef'
+EXTERN char_u *p_mp; // 'makeprg'
+EXTERN char *p_mps; ///< 'matchpairs'
+EXTERN char_u *p_cc; // 'colorcolumn'
EXTERN int p_cc_cols[256]; // array for 'colorcolumn' columns
EXTERN long p_mat; // 'matchtime'
EXTERN long p_mco; // 'maxcombine'
@@ -610,60 +610,60 @@ EXTERN long p_mfd; // 'maxfuncdepth'
EXTERN long p_mmd; // 'maxmapdepth'
EXTERN long p_mmp; // 'maxmempattern'
EXTERN long p_mis; // 'menuitems'
-EXTERN char_u *p_msm; // 'mkspellmem'
+EXTERN char *p_msm; // 'mkspellmem'
EXTERN int p_ml; ///< 'modeline'
-EXTERN int p_mle; // 'modelineexpr'
+EXTERN int p_mle; // 'modelineexpr'
EXTERN long p_mls; // 'modelines'
EXTERN int p_ma; ///< 'modifiable'
EXTERN int p_mod; ///< 'modified'
-EXTERN char_u *p_mouse; // 'mouse'
-EXTERN char_u *p_mousem; // 'mousemodel'
-EXTERN int p_mousef; // 'mousefocus'
-EXTERN char_u *p_mousescroll; // 'mousescroll'
+EXTERN char *p_mouse; // 'mouse'
+EXTERN char *p_mousem; // 'mousemodel'
+EXTERN int p_mousef; // 'mousefocus'
+EXTERN char *p_mousescroll; // 'mousescroll'
EXTERN long p_mousescroll_vert INIT(= MOUSESCROLL_VERT_DFLT);
EXTERN long p_mousescroll_hor INIT(= MOUSESCROLL_HOR_DFLT);
EXTERN long p_mouset; // 'mousetime'
EXTERN int p_more; // 'more'
-EXTERN char_u *p_nf; ///< 'nrformats'
-EXTERN char_u *p_opfunc; // 'operatorfunc'
-EXTERN char_u *p_para; // 'paragraphs'
+EXTERN char *p_nf; ///< 'nrformats'
+EXTERN char *p_opfunc; // 'operatorfunc'
+EXTERN char_u *p_para; // 'paragraphs'
EXTERN int p_paste; // 'paste'
-EXTERN char_u *p_pt; // 'pastetoggle'
-EXTERN char_u *p_pex; // 'patchexpr'
-EXTERN char_u *p_pm; // 'patchmode'
-EXTERN char_u *p_path; // 'path'
-EXTERN char_u *p_cdpath; // 'cdpath'
+EXTERN char *p_pt; // 'pastetoggle'
+EXTERN char_u *p_pex; // 'patchexpr'
+EXTERN char *p_pm; // 'patchmode'
+EXTERN char_u *p_path; // 'path'
+EXTERN char_u *p_cdpath; // 'cdpath'
EXTERN int p_pi; ///< 'preserveindent'
EXTERN long p_pyx; // 'pyxversion'
-EXTERN char_u *p_qe; ///< 'quoteescape'
+EXTERN char *p_qe; ///< 'quoteescape'
EXTERN int p_ro; ///< 'readonly'
-EXTERN char_u *p_rdb; // 'redrawdebug'
+EXTERN char *p_rdb; // 'redrawdebug'
EXTERN unsigned rdb_flags;
#define RDB_COMPOSITOR 0x001
#define RDB_NOTHROTTLE 0x002
#define RDB_INVALID 0x004
#define RDB_NODELTA 0x008
-EXTERN long p_rdt; // 'redrawtime'
-EXTERN long p_re; // 'regexpengine'
-EXTERN long p_report; // 'report'
-EXTERN long p_pvh; // 'previewheight'
-EXTERN int p_ari; // 'allowrevins'
-EXTERN int p_ri; // 'revins'
-EXTERN int p_ru; // 'ruler'
-EXTERN char_u *p_ruf; // 'rulerformat'
-EXTERN char_u *p_pp; // 'packpath'
-EXTERN char_u *p_qftf; // 'quickfixtextfunc'
-EXTERN char_u *p_rtp; // 'runtimepath'
-EXTERN long p_scbk; // 'scrollback'
-EXTERN long p_sj; // 'scrolljump'
-EXTERN long p_so; // 'scrolloff'
-EXTERN char *p_sbo; // 'scrollopt'
-EXTERN char_u *p_sections; // 'sections'
-EXTERN int p_secure; // 'secure'
-EXTERN char_u *p_sel; // 'selection'
-EXTERN char_u *p_slm; // 'selectmode'
-EXTERN char_u *p_ssop; // 'sessionoptions'
+EXTERN long p_rdt; // 'redrawtime'
+EXTERN long p_re; // 'regexpengine'
+EXTERN long p_report; // 'report'
+EXTERN long p_pvh; // 'previewheight'
+EXTERN int p_ari; // 'allowrevins'
+EXTERN int p_ri; // 'revins'
+EXTERN int p_ru; // 'ruler'
+EXTERN char *p_ruf; // 'rulerformat'
+EXTERN char *p_pp; // 'packpath'
+EXTERN char *p_qftf; // 'quickfixtextfunc'
+EXTERN char *p_rtp; // 'runtimepath'
+EXTERN long p_scbk; // 'scrollback'
+EXTERN long p_sj; // 'scrolljump'
+EXTERN long p_so; // 'scrolloff'
+EXTERN char *p_sbo; // 'scrollopt'
+EXTERN char *p_sections; // 'sections'
+EXTERN int p_secure; // 'secure'
+EXTERN char *p_sel; // 'selection'
+EXTERN char *p_slm; // 'selectmode'
+EXTERN char *p_ssop; // 'sessionoptions'
EXTERN unsigned ssop_flags;
#define SSOP_BUFFERS 0x001
@@ -685,23 +685,23 @@ EXTERN unsigned ssop_flags;
#define SSOP_TERMINAL 0x10000
#define SSOP_SKIP_RTP 0x20000
-EXTERN char_u *p_sh; // 'shell'
-EXTERN char_u *p_shcf; // 'shellcmdflag'
-EXTERN char_u *p_sp; // 'shellpipe'
-EXTERN char_u *p_shq; // 'shellquote'
-EXTERN char_u *p_sxq; // 'shellxquote'
-EXTERN char_u *p_sxe; // 'shellxescape'
-EXTERN char_u *p_srr; // 'shellredir'
+EXTERN char_u *p_sh; // 'shell'
+EXTERN char_u *p_shcf; // 'shellcmdflag'
+EXTERN char *p_sp; // 'shellpipe'
+EXTERN char_u *p_shq; // 'shellquote'
+EXTERN char_u *p_sxq; // 'shellxquote'
+EXTERN char_u *p_sxe; // 'shellxescape'
+EXTERN char *p_srr; // 'shellredir'
EXTERN int p_stmp; // 'shelltemp'
#ifdef BACKSLASH_IN_FILENAME
EXTERN int p_ssl; // 'shellslash'
#endif
-EXTERN char_u *p_stl; // 'statusline'
-EXTERN char *p_wbr; // 'winbar'
+EXTERN char *p_stl; // 'statusline'
+EXTERN char *p_wbr; // 'winbar'
EXTERN int p_sr; // 'shiftround'
EXTERN long p_sw; ///< 'shiftwidth'
-EXTERN char_u *p_shm; // 'shortmess'
-EXTERN char_u *p_sbr; // 'showbreak'
+EXTERN char *p_shm; // 'shortmess'
+EXTERN char *p_sbr; // 'showbreak'
EXTERN int p_sc; // 'showcmd'
EXTERN int p_sft; // 'showfulltag'
EXTERN int p_sm; // 'showmatch'
@@ -713,12 +713,12 @@ EXTERN int p_si; ///< 'smartindent'
EXTERN int p_sta; // 'smarttab'
EXTERN long p_sts; ///< 'softtabstop'
EXTERN int p_sb; // 'splitbelow'
-EXTERN char_u *p_sua; ///< 'suffixesadd'
+EXTERN char *p_sua; ///< 'suffixesadd'
EXTERN int p_swf; ///< 'swapfile'
EXTERN long p_smc; ///< 'synmaxcol'
EXTERN long p_tpm; // 'tabpagemax'
-EXTERN char_u *p_tal; // 'tabline'
-EXTERN char_u *p_tpf; // 'termpastefilter'
+EXTERN char *p_tal; // 'tabline'
+EXTERN char *p_tpf; // 'termpastefilter'
EXTERN unsigned int tpf_flags; ///< flags from 'termpastefilter'
#define TPF_BS 0x001
#define TPF_HT 0x002
@@ -727,16 +727,16 @@ EXTERN unsigned int tpf_flags; ///< flags from 'termpastefilter'
#define TPF_DEL 0x010
#define TPF_C0 0x020
#define TPF_C1 0x040
-EXTERN char_u *p_tfu; ///< 'tagfunc'
-EXTERN char_u *p_spc; ///< 'spellcapcheck'
-EXTERN char_u *p_spf; ///< 'spellfile'
-EXTERN char_u *p_spl; ///< 'spelllang'
-EXTERN char_u *p_spo; // 'spelloptions'
-EXTERN char_u *p_sps; // 'spellsuggest'
+EXTERN char *p_tfu; ///< 'tagfunc'
+EXTERN char *p_spc; ///< 'spellcapcheck'
+EXTERN char *p_spf; ///< 'spellfile'
+EXTERN char *p_spl; ///< 'spelllang'
+EXTERN char *p_spo; // 'spelloptions'
+EXTERN char *p_sps; // 'spellsuggest'
EXTERN int p_spr; // 'splitright'
EXTERN int p_sol; // 'startofline'
-EXTERN char_u *p_su; // 'suffixes'
-EXTERN char_u *p_swb; // 'switchbuf'
+EXTERN char_u *p_su; // 'suffixes'
+EXTERN char *p_swb; // 'switchbuf'
EXTERN unsigned swb_flags;
// Keep in sync with p_swb_values in optionstr.c
#define SWB_USEOPEN 0x001
@@ -745,10 +745,10 @@ EXTERN unsigned swb_flags;
#define SWB_NEWTAB 0x008
#define SWB_VSPLIT 0x010
#define SWB_USELAST 0x020
-EXTERN char_u *p_syn; ///< 'syntax'
+EXTERN char *p_syn; ///< 'syntax'
EXTERN long p_ts; ///< 'tabstop'
EXTERN int p_tbs; ///< 'tagbsearch'
-EXTERN char_u *p_tc; ///< 'tagcase'
+EXTERN char *p_tc; ///< 'tagcase'
EXTERN unsigned tc_flags; ///< flags from 'tagcase'
#define TC_FOLLOWIC 0x01
#define TC_IGNORE 0x02
@@ -767,7 +767,7 @@ EXTERN long p_tm; ///< 'timeoutlen'
EXTERN int p_title; ///< 'title'
EXTERN long p_titlelen; ///< 'titlelen'
EXTERN char_u *p_titleold; ///< 'titleold'
-EXTERN char_u *p_titlestring; ///< 'titlestring'
+EXTERN char *p_titlestring; ///< 'titlestring'
EXTERN char_u *p_tsr; ///< 'thesaurus'
EXTERN int p_tgc; ///< 'termguicolors'
EXTERN int p_ttimeout; ///< 'ttimeout'
@@ -778,15 +778,15 @@ EXTERN long p_ul; ///< 'undolevels'
EXTERN long p_ur; ///< 'undoreload'
EXTERN long p_uc; ///< 'updatecount'
EXTERN long p_ut; ///< 'updatetime'
-EXTERN char_u *p_shada; ///< 'shada'
+EXTERN char *p_shada; ///< 'shada'
EXTERN char *p_shadafile; ///< 'shadafile'
-EXTERN char_u *p_vsts; ///< 'varsofttabstop'
-EXTERN char_u *p_vts; ///< 'vartabstop'
+EXTERN char *p_vsts; ///< 'varsofttabstop'
+EXTERN char *p_vts; ///< 'vartabstop'
EXTERN char_u *p_vdir; ///< 'viewdir'
-EXTERN char_u *p_vop; ///< 'viewoptions'
+EXTERN char *p_vop; ///< 'viewoptions'
EXTERN unsigned vop_flags; ///< uses SSOP_ flags
EXTERN int p_vb; ///< 'visualbell'
-EXTERN char_u *p_ve; ///< 'virtualedit'
+EXTERN char *p_ve; ///< 'virtualedit'
EXTERN unsigned ve_flags;
#define VE_BLOCK 5U // includes "all"
#define VE_INSERT 6U // includes "all"
@@ -798,21 +798,21 @@ EXTERN long p_verbose; // 'verbose'
#ifdef IN_OPTION_C
char_u *p_vfile = (char_u *)""; // used before options are initialized
#else
-extern char_u *p_vfile; // 'verbosefile'
+extern char *p_vfile; // 'verbosefile'
#endif
EXTERN int p_warn; // 'warn'
-EXTERN char_u *p_wop; // 'wildoptions'
+EXTERN char *p_wop; // 'wildoptions'
EXTERN unsigned wop_flags;
#define WOP_TAGFILE 0x01
#define WOP_PUM 0x02
EXTERN long p_window; // 'window'
-EXTERN char_u *p_wak; // 'winaltkeys'
-EXTERN char_u *p_wig; // 'wildignore'
-EXTERN char_u *p_ww; // 'whichwrap'
+EXTERN char *p_wak; // 'winaltkeys'
+EXTERN char *p_wig; // 'wildignore'
+EXTERN char *p_ww; // 'whichwrap'
EXTERN long p_wc; // 'wildchar'
EXTERN long p_wcm; // 'wildcharm'
EXTERN int p_wic; // 'wildignorecase'
-EXTERN char_u *p_wim; // 'wildmode'
+EXTERN char *p_wim; // 'wildmode'
EXTERN int p_wmnu; // 'wildmenu'
EXTERN long p_wh; // 'winheight'
EXTERN long p_wmh; // 'winminheight'
@@ -825,7 +825,7 @@ EXTERN int p_wa; // 'writeany'
EXTERN int p_wb; // 'writebackup'
EXTERN long p_wd; // 'writedelay'
EXTERN int p_cdh; // 'cdhome'
-EXTERN char_u *p_urf; // 'userregister'
+EXTERN char *p_urf; // 'userregfunc'
EXTERN int p_force_on; ///< options that cannot be turned off.
EXTERN int p_force_off; ///< options that cannot be turned on.
@@ -974,8 +974,8 @@ enum {
WV_WRAP,
WV_SCL,
WV_WINHL,
- WV_FCS,
WV_LCS,
+ WV_FCS,
WV_WINBL,
WV_WBR,
WV_COUNT, // must be the last one
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index c50225dfdf..1bdfcbecb9 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -18,6 +18,7 @@
#include "nvim/drawscreen.h"
#include "nvim/eval.h"
#include "nvim/eval/vars.h"
+#include "nvim/ex_getln.h"
#include "nvim/hardcopy.h"
#include "nvim/highlight_group.h"
#include "nvim/indent.h"
@@ -45,8 +46,14 @@
# include "optionstr.c.generated.h"
#endif
-static char e_unclosed_expression_sequence[] = N_("E540: Unclosed expression sequence");
-static char e_unbalanced_groups[] = N_("E542: unbalanced groups");
+static char e_unclosed_expression_sequence[]
+ = N_("E540: Unclosed expression sequence");
+static char e_unbalanced_groups[]
+ = N_("E542: unbalanced groups");
+static char e_backupext_and_patchmode_are_equal[]
+ = N_("E589: 'backupext' and 'patchmode' are equal");
+static char e_showbreak_contains_unprintable_or_wide_character[]
+ = N_("E595: 'showbreak' contains unprintable or wide character");
static char *(p_ambw_values[]) = { "single", "double", NULL };
static char *(p_bg_values[]) = { "light", "dark", NULL };
@@ -106,10 +113,10 @@ static char *(p_tpf_values[]) = { "BS", "HT", "FF", "ESC", "DEL", "C0", "C1", NU
static char *(p_rdb_values[]) = { "compositor", "nothrottle", "invalid", "nodelta", NULL };
/// All possible flags for 'shm'.
-static char_u SHM_ALL[] = { SHM_RO, SHM_MOD, SHM_FILE, SHM_LAST, SHM_TEXT, SHM_LINES, SHM_NEW,
- SHM_WRI, SHM_ABBREVIATIONS, SHM_WRITE, SHM_TRUNC, SHM_TRUNCALL,
- SHM_OVER, SHM_OVERALL, SHM_SEARCH, SHM_ATTENTION, SHM_INTRO,
- SHM_COMPLETIONMENU, SHM_RECORDING, SHM_FILEINFO, SHM_SEARCHCOUNT, 0, };
+static char SHM_ALL[] = { SHM_RO, SHM_MOD, SHM_FILE, SHM_LAST, SHM_TEXT, SHM_LINES, SHM_NEW,
+ SHM_WRI, SHM_ABBREVIATIONS, SHM_WRITE, SHM_TRUNC, SHM_TRUNCALL,
+ SHM_OVER, SHM_OVERALL, SHM_SEARCH, SHM_ATTENTION, SHM_INTRO,
+ SHM_COMPLETIONMENU, SHM_RECORDING, SHM_FILEINFO, SHM_SEARCHCOUNT, 0, };
/// After setting various option values: recompute variables that depend on
/// option values.
@@ -248,14 +255,14 @@ void check_buf_options(buf_T *buf)
/// memory, vim_strsave() returned NULL, which was replaced by empty_option by
/// check_options().
/// Does NOT check for P_ALLOCED flag!
-void free_string_option(char_u *p)
+void free_string_option(char *p)
{
if (p != empty_option) {
xfree(p);
}
}
-void clear_string_option(char_u **pp)
+void clear_string_option(char **pp)
{
if (*pp != empty_option) {
xfree(*pp);
@@ -263,7 +270,7 @@ void clear_string_option(char_u **pp)
*pp = empty_option;
}
-void check_string_option(char_u **pp)
+void check_string_option(char **pp)
{
if (*pp == NULL) {
*pp = empty_option;
@@ -274,18 +281,18 @@ void check_string_option(char_u **pp)
///
/// @param opt_idx option index
/// @param varp pointer to option variable
-static void set_string_option_global(int opt_idx, char_u **varp)
+static void set_string_option_global(int opt_idx, char **varp)
{
- char_u **p, *s;
+ char **p;
// the global value is always allocated
if (is_window_local_option(opt_idx)) {
- p = (char_u **)GLOBAL_WO(varp);
+ p = (char **)GLOBAL_WO(varp);
} else {
- p = (char_u **)get_option_var(opt_idx);
+ p = (char **)get_option_var(opt_idx);
}
if (!is_global_option(opt_idx) && p != varp) {
- s = vim_strsave(*varp);
+ char *s = xstrdup(*varp);
free_string_option(*p);
*p = s;
}
@@ -326,13 +333,13 @@ void set_string_option_direct(const char *name, int opt_idx, const char *val, in
{
varp = (char **)get_option_varp_scope(idx, both ? OPT_LOCAL : opt_flags);
if ((opt_flags & OPT_FREE) && (get_option_flags(idx) & P_ALLOCED)) {
- free_string_option((char_u *)(*varp));
+ free_string_option(*varp);
}
*varp = s;
// For buffer/window local option may also set the global value.
if (both) {
- set_string_option_global(idx, (char_u **)varp);
+ set_string_option_global(idx, varp);
}
set_option_flag(idx, P_ALLOCED);
@@ -340,8 +347,8 @@ void set_string_option_direct(const char *name, int opt_idx, const char *val, in
// When setting both values of a global option with a local value,
// make the local value empty, so that the global value is used.
if (is_global_local_option(idx) && both) {
- free_string_option((char_u *)(*varp));
- *varp = (char *)empty_option;
+ free_string_option(*varp);
+ *varp = empty_option;
}
if (set_sid != SID_NONE) {
sctx_T script_ctx;
@@ -381,7 +388,7 @@ void set_string_option_direct_in_win(win_T *wp, const char *name, int opt_idx, c
/// @param[in] opt_flags Option flags: expected to contain #OPT_LOCAL and/or
/// #OPT_GLOBAL.
///
-/// @return NULL on success, error message on error.
+/// @return NULL on success, an untranslated error message on error.
char *set_string_option(const int opt_idx, const char *const value, const int opt_flags)
FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -413,15 +420,15 @@ char *set_string_option(const int opt_idx, const char *const value, const int op
char *const saved_newval = xstrdup(s);
int value_checked = false;
- char *const r = did_set_string_option(opt_idx, (char_u **)varp, (char_u *)oldval,
- NULL, 0,
- opt_flags, &value_checked);
- if (r == NULL) {
+ char *const errmsg = did_set_string_option(opt_idx, varp, oldval,
+ NULL, 0,
+ opt_flags, &value_checked);
+ if (errmsg == NULL) {
did_set_option(opt_idx, opt_flags, true, value_checked);
}
// call autocommand after handling side effects
- if (r == NULL) {
+ if (errmsg == NULL) {
if (!starting) {
trigger_optionsset_string(opt_idx, opt_flags, saved_oldval, saved_oldval_l, saved_oldval_g,
saved_newval);
@@ -436,12 +443,12 @@ char *set_string_option(const int opt_idx, const char *const value, const int op
xfree(saved_oldval_g);
xfree(saved_newval);
- return r;
+ return errmsg;
}
/// Return true if "val" is a valid 'filetype' name.
/// Also used for 'syntax' and 'keymap'.
-static bool valid_filetype(const char_u *val)
+static bool valid_filetype(const char *val)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return valid_name(val, ".-_");
@@ -513,7 +520,7 @@ static char *check_mousescroll(char *string)
/// Handle setting 'signcolumn' for value 'val'
///
/// @return OK when the value is valid, FAIL otherwise
-static int check_signcolumn(char_u *val)
+static int check_signcolumn(char *val)
{
if (*val == NUL) {
return FAIL;
@@ -624,39 +631,37 @@ static int shada_idx = -1;
/// @param value_checked value was checked to be safe, no need to set P_INSECURE
///
/// @return NULL for success, or an untranslated error message for an error
-char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *errbuf,
- size_t errbuflen, int opt_flags, int *value_checked)
+char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf, size_t errbuflen,
+ int opt_flags, int *value_checked)
{
char *errmsg = NULL;
char *s, *p;
int did_chartab = false;
- char_u **gvarp;
bool free_oldval = (get_option_flags(opt_idx) & P_ALLOCED);
bool value_changed = false;
// Get the global option to compare with, otherwise we would have to check
// two values for all local options.
- gvarp = (char_u **)get_option_varp_scope(opt_idx, OPT_GLOBAL);
+ char **gvarp = (char **)get_option_varp_scope(opt_idx, OPT_GLOBAL);
// Disallow changing some options from secure mode
if ((secure || sandbox != 0)
&& (get_option_flags(opt_idx) & P_SECURE)) {
errmsg = e_secure;
} else if (((get_option_flags(opt_idx) & P_NFNAME)
- && strpbrk((char *)(*varp),
- (secure ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL)
+ && strpbrk(*varp, (secure ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL)
|| ((get_option_flags(opt_idx) & P_NDNAME)
- && strpbrk((char *)(*varp), "*?[|;&<>\r\n") != NULL)) {
+ && strpbrk(*varp, "*?[|;&<>\r\n") != NULL)) {
// Check for a "normal" directory or file name in some options. Disallow a
// path separator (slash and/or backslash), wildcards and characters that
// are often illegal in a file name. Be more permissive if "secure" is off.
errmsg = e_invarg;
} else if (gvarp == &p_bkc) { // 'backupcopy'
- char_u *bkc = p_bkc;
+ char *bkc = p_bkc;
unsigned int *flags = &bkc_flags;
if (opt_flags & OPT_LOCAL) {
- bkc = curbuf->b_p_bkc;
+ bkc = curbuf->b_p_bkc;
flags = &curbuf->b_bkc_flags;
}
@@ -679,7 +684,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
} else if (varp == &p_bex || varp == &p_pm) { // 'backupext' and 'patchmode'
if (STRCMP(*p_bex == '.' ? p_bex + 1 : p_bex,
*p_pm == '.' ? p_pm + 1 : p_pm) == 0) {
- errmsg = N_("E589: 'backupext' and 'patchmode' are equal");
+ errmsg = e_backupext_and_patchmode_are_equal;
}
} else if (varp == &curwin->w_p_briopt) { // 'breakindentopt'
if (briopt_check(curwin) == FAIL) {
@@ -713,7 +718,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
}
} else if (varp == &curwin->w_p_cc) { // 'colorcolumn'
errmsg = check_colorcolumn(curwin);
- } else if (varp == &p_hlg) { // 'helplang'
+ } else if (varp == (char **)&p_hlg) { // 'helplang'
// Check for "", "ab", "ab,cd", etc.
for (s = (char *)p_hlg; *s != NUL; s += 3) {
if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL)) {
@@ -753,8 +758,8 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
if (opt_strings_flags(p_rdb, p_rdb_values, &rdb_flags, true) != OK) {
errmsg = e_invarg;
}
- } else if (varp == (char_u **)&p_sbo) { // 'scrollopt'
- if (check_opt_strings((char_u *)p_sbo, p_scbopt_values, true) != OK) {
+ } else if (varp == &p_sbo) { // 'scrollopt'
+ if (check_opt_strings(p_sbo, p_scbopt_values, true) != OK) {
errmsg = e_invarg;
}
} else if (varp == &p_ambw || (int *)varp == &p_emoji) { // 'ambiwidth'
@@ -775,7 +780,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
// scheme and set the colors again.
do_unlet(S_LEN("g:colors_name"), true);
free_string_option(p_bg);
- p_bg = vim_strsave((char_u *)(dark ? "dark" : "light"));
+ p_bg = xstrdup((dark ? "dark" : "light"));
check_string_option(&p_bg);
init_highlight(false, false);
}
@@ -804,7 +809,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
if (gvarp == &p_fenc) {
if (!MODIFIABLE(curbuf) && opt_flags != OPT_GLOBAL) {
errmsg = e_modifiable;
- } else if (vim_strchr((char *)(*varp), ',') != NULL) {
+ } else if (vim_strchr(*varp, ',') != NULL) {
// No comma allowed in 'fileencoding'; catches confusing it
// with 'fileencodings'.
errmsg = e_invarg;
@@ -818,9 +823,9 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
if (errmsg == NULL) {
// canonize the value, so that STRCMP() can be used on it
- p = (char *)enc_canonize(*varp);
+ p = enc_canonize(*varp);
xfree(*varp);
- *varp = (char_u *)p;
+ *varp = p;
if (varp == &p_enc) {
// only encoding=utf-8 allowed
if (STRCMP(p_enc, "utf-8") != 0) {
@@ -832,9 +837,9 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
}
} else if (varp == &p_penc) {
// Canonize printencoding if VIM standard one
- p = (char *)enc_canonize(p_penc);
+ p = enc_canonize(p_penc);
xfree(p_penc);
- p_penc = (char_u *)p;
+ p_penc = p;
} else if (varp == &curbuf->b_p_keymap) {
if (!valid_filetype(*varp)) {
errmsg = e_invarg;
@@ -889,15 +894,15 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
// Redraw needed when switching to/from "mac": a CR in the text
// will be displayed differently.
if (get_fileformat(curbuf) == EOL_MAC || *oldval == 'm') {
- redraw_curbuf_later(NOT_VALID);
+ redraw_curbuf_later(UPD_NOT_VALID);
}
}
- } else if (varp == (char_u **)&p_ffs) { // 'fileformats'
- if (check_opt_strings((char_u *)p_ffs, p_ff_values, true) != OK) {
+ } else if (varp == &p_ffs) { // 'fileformats'
+ if (check_opt_strings(p_ffs, p_ff_values, true) != OK) {
errmsg = e_invarg;
}
} else if (gvarp == &p_mps) { // 'matchpairs'
- for (p = (char *)(*varp); *p != NUL; p++) {
+ for (p = *varp; *p != NUL; p++) {
int x2 = -1;
int x3 = -1;
@@ -918,7 +923,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
}
}
} else if (gvarp == &p_com) { // 'comments'
- for (s = (char *)(*varp); *s;) {
+ for (s = *varp; *s;) {
while (*s && *s != ':') {
if (vim_strchr(COM_ALL, *s) == NULL
&& !ascii_isdigit(*s) && *s != '-') {
@@ -941,40 +946,33 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
}
s++;
}
- s = (char *)skip_to_option_part((char_u *)s);
+ s = skip_to_option_part(s);
}
- } else if (varp == &p_lcs) { // global 'listchars'
- errmsg = set_chars_option(curwin, varp, false);
+ } else if (varp == &p_lcs || varp == &p_fcs) { // global 'listchars' or 'fillchars'
+ char **local_ptr = varp == &p_lcs ? &curwin->w_p_lcs : &curwin->w_p_fcs;
+ // only apply the global value to "curwin" when it does not have a local value
+ errmsg =
+ set_chars_option(curwin, varp, **local_ptr == NUL || !(opt_flags & OPT_GLOBAL));
if (errmsg == NULL) {
- // The current window is set to use the global 'listchars' value.
- // So clear the window-local value.
+ // If the current window is set to use the global
+ // 'listchars'/'fillchars' value, clear the window-local value.
if (!(opt_flags & OPT_GLOBAL)) {
- clear_string_option(&curwin->w_p_lcs);
+ clear_string_option(local_ptr);
}
FOR_ALL_TAB_WINDOWS(tp, wp) {
+ // If the current window has a local value need to apply it
+ // again, it was changed when setting the global value.
// If no error was returned above, we don't expect an error
// here, so ignore the return value.
- (void)set_chars_option(wp, &wp->w_p_lcs, true);
+ local_ptr = varp == &p_lcs ? &wp->w_p_lcs : &wp->w_p_fcs;
+ if (**local_ptr == NUL) {
+ (void)set_chars_option(wp, local_ptr, true);
+ }
}
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
}
} else if (varp == &curwin->w_p_lcs) { // local 'listchars'
errmsg = set_chars_option(curwin, varp, true);
- } else if (varp == &p_fcs) { // global 'fillchars'
- errmsg = set_chars_option(curwin, varp, false);
- if (errmsg == NULL) {
- // The current window is set to use the global 'fillchars' value.
- // So clear the window-local value.
- if (!(opt_flags & OPT_GLOBAL)) {
- clear_string_option(&curwin->w_p_fcs);
- }
- FOR_ALL_TAB_WINDOWS(tp, wp) {
- // If no error was returned above, we don't expect an error
- // here, so ignore the return value.
- (void)set_chars_option(wp, &wp->w_p_fcs, true);
- }
- redraw_all_later(NOT_VALID);
- }
} else if (varp == &curwin->w_p_fcs) { // local 'fillchars'
errmsg = set_chars_option(curwin, varp, true);
} else if (varp == &p_cedit) { // 'cedit'
@@ -994,7 +992,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
// there would be a disconnect between the check for P_ALLOCED at the start
// of the function and the set of P_ALLOCED at the end of the function.
free_oldval = (get_option_flags(opt_idx) & P_ALLOCED);
- for (s = (char *)p_shada; *s;) {
+ for (s = p_shada; *s;) {
// Check it's a valid character
if (vim_strchr("!\"%'/:<@cfhnrs", *s) == NULL) {
errmsg = illegal_char(errbuf, errbuflen, *s);
@@ -1039,9 +1037,9 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
errmsg = N_("E528: Must specify a ' value");
}
} else if (gvarp == &p_sbr) { // 'showbreak'
- for (s = (char *)(*varp); *s;) {
+ for (s = *varp; *s;) {
if (ptr2cells(s) != 1) {
- errmsg = N_("E595: 'showbreak' contains unprintable or wide character");
+ errmsg = e_showbreak_contains_unprintable_or_wide_character;
}
MB_PTR_ADV(s);
}
@@ -1060,7 +1058,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
int flagval = (varp == &p_titlestring) ? STL_IN_TITLE : STL_IN_ICON;
// NULL => statusline syntax
- if (vim_strchr((char *)(*varp), '%') && check_stl_option((char *)(*varp)) == NULL) {
+ if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL) {
stl_syntax |= flagval;
} else {
stl_syntax &= ~flagval;
@@ -1079,15 +1077,15 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
if (check_opt_strings(p_km, p_km_values, true) != OK) {
errmsg = e_invarg;
} else {
- km_stopsel = (vim_strchr((char *)p_km, 'o') != NULL);
- km_startsel = (vim_strchr((char *)p_km, 'a') != NULL);
+ km_stopsel = (vim_strchr(p_km, 'o') != NULL);
+ km_startsel = (vim_strchr(p_km, 'a') != NULL);
}
} else if (varp == &p_mousem) { // 'mousemodel'
if (check_opt_strings(p_mousem, p_mousem_values, false) != OK) {
errmsg = e_invarg;
}
} else if (varp == &p_mousescroll) { // 'mousescroll'
- errmsg = check_mousescroll((char *)p_mousescroll);
+ errmsg = check_mousescroll(p_mousescroll);
} else if (varp == &p_swb) { // 'switchbuf'
if (opt_strings_flags(p_swb, p_swb_values, &swb_flags, true) != OK) {
errmsg = e_invarg;
@@ -1152,29 +1150,30 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
} else {
if (curwin->w_status_height || global_stl_height()) {
curwin->w_redr_status = true;
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
}
curbuf->b_help = (curbuf->b_p_bt[0] == 'h');
redraw_titles();
}
- } else if (gvarp == &p_stl || gvarp == (char_u **)&p_wbr || varp == &p_tal || varp == &p_ruf) {
+ } else if (gvarp == &p_stl || gvarp == &p_wbr || varp == &p_tal
+ || varp == &p_ruf) {
// 'statusline', 'winbar', 'tabline' or 'rulerformat'
int wid;
if (varp == &p_ruf) { // reset ru_wid first
ru_wid = 0;
}
- s = (char *)(*varp);
+ s = *varp;
if (varp == &p_ruf && *s == '%') {
// set ru_wid if 'ruf' starts with "%99("
if (*++s == '-') { // ignore a '-'
s++;
}
wid = getdigits_int(&s, true, 0);
- if (wid && *s == '(' && (errmsg = check_stl_option((char *)p_ruf)) == NULL) {
+ if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL) {
ru_wid = wid;
} else {
- errmsg = check_stl_option((char *)p_ruf);
+ errmsg = check_stl_option(p_ruf);
}
} else if (varp == &p_ruf || s[0] != '%' || s[1] != '!') {
// check 'statusline', 'winbar' or 'tabline' only if it doesn't start with "%!"
@@ -1184,12 +1183,12 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
comp_col();
}
// add / remove window bars for 'winbar'
- if (gvarp == (char_u **)&p_wbr) {
+ if (gvarp == &p_wbr) {
set_winbar(true);
}
} else if (gvarp == &p_cpt) {
// check if it is a valid value for 'complete' -- Acevedo
- for (s = (char *)(*varp); *s;) {
+ for (s = *varp; *s;) {
while (*s == ',' || *s == ' ') {
s++;
}
@@ -1246,7 +1245,8 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
&& (curwin->w_p_nu || curwin->w_p_rnu)) {
curwin->w_nrwidth_line_count = 0;
}
- } else if (varp == &curwin->w_p_fdc || varp == &curwin->w_allbuf_opt.wo_fdc) {
+ } else if (varp == &curwin->w_p_fdc
+ || varp == &curwin->w_allbuf_opt.wo_fdc) {
// 'foldcolumn'
if (**varp == NUL || check_opt_strings(*varp, p_fdc_values, false) != OK) {
errmsg = e_invarg;
@@ -1255,13 +1255,13 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
// 'pastetoggle': translate key codes like in a mapping
if (*p_pt) {
p = NULL;
- (void)replace_termcodes((char *)p_pt,
+ (void)replace_termcodes(p_pt,
STRLEN(p_pt),
&p, REPTERM_FROM_PART | REPTERM_DO_LT, NULL,
CPO_TO_CPO_FLAGS);
if (p != NULL) {
free_string_option(p_pt);
- p_pt = (char_u *)p;
+ p_pt = p;
}
}
} else if (varp == &p_bs) { // 'backspace'
@@ -1280,10 +1280,10 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
unsigned int *flags;
if (opt_flags & OPT_LOCAL) {
- p = (char *)curbuf->b_p_tc;
+ p = curbuf->b_p_tc;
flags = &curbuf->b_tc_flags;
} else {
- p = (char *)p_tc;
+ p = p_tc;
flags = &tc_flags;
}
@@ -1291,7 +1291,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
// make the local value empty: use the global value
*flags = 0;
} else if (*p == NUL
- || opt_strings_flags((char_u *)p, p_tc_values, flags, false) != OK) {
+ || opt_strings_flags(p, p_tc_values, flags, false) != OK) {
errmsg = e_invarg;
}
} else if (varp == &p_cmp) { // 'casemap'
@@ -1317,16 +1317,16 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
foldUpdateAll(curwin);
}
} else if (gvarp == &curwin->w_allbuf_opt.wo_fmr) { // 'foldmarker'
- p = vim_strchr((char *)(*varp), ',');
+ p = vim_strchr(*varp, ',');
if (p == NULL) {
errmsg = N_("E536: comma required");
- } else if ((char_u *)p == *varp || p[1] == NUL) {
+ } else if (p == *varp || p[1] == NUL) {
errmsg = e_invarg;
} else if (foldmethodIsMarker(curwin)) {
foldUpdateAll(curwin);
}
} else if (gvarp == &p_cms) { // 'commentstring'
- if (**varp != NUL && strstr((char *)(*varp), "%s") == NULL) {
+ if (**varp != NUL && strstr(*varp, "%s") == NULL) {
errmsg = N_("E537: 'commentstring' must be empty or contain %s");
}
} else if (varp == &p_fdo) { // 'foldopen'
@@ -1342,7 +1342,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
foldUpdateAll(curwin);
}
} else if (gvarp == &p_ve) { // 'virtualedit'
- char_u *ve = p_ve;
+ char *ve = p_ve;
unsigned int *flags = &ve_flags;
if (opt_flags & OPT_LOCAL) {
@@ -1365,7 +1365,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
}
} else if (varp == &p_csqf) {
if (p_csqf != NULL) {
- p = (char *)p_csqf;
+ p = p_csqf;
while (*p != NUL) {
if (vim_strchr(CSQF_CMDS, *p) == NULL
|| p[1] == NUL
@@ -1416,7 +1416,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
errmsg = e_invarg;
}
} else if (varp == &(curbuf->b_p_vsts)) { // 'varsofttabstop'
- char_u *cp;
+ char *cp;
if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) {
XFREE_CLEAR(curbuf->b_p_vsts_array);
@@ -1441,7 +1441,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
}
}
} else if (varp == &(curbuf->b_p_vts)) { // 'vartabstop'
- char_u *cp;
+ char *cp;
if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) {
XFREE_CLEAR(curbuf->b_p_vts_array);
@@ -1483,8 +1483,8 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
p = WW_ALL;
}
if (varp == &p_shm) { // 'shortmess'
- p = (char *)SHM_ALL;
- } else if (varp == (char_u **)&(p_cpo)) { // 'cpoptions'
+ p = SHM_ALL;
+ } else if (varp == &(p_cpo)) { // 'cpoptions'
p = CPO_VI;
} else if (varp == &(curbuf->b_p_fo)) { // 'formatoptions'
p = FO_ALL;
@@ -1494,7 +1494,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
p = MOUSE_ALL;
}
if (p != NULL) {
- for (s = (char *)(*varp); *s; s++) {
+ for (s = *varp; *s; s++) {
if (vim_strchr(p, *s) == NULL) {
errmsg = illegal_char(errbuf, errbuflen, *s);
break;
@@ -1526,9 +1526,9 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
&& is_global_local_option(opt_idx)) {
// global option with local value set to use global value; free
// the local value and make it empty
- p = (char *)get_option_varp_scope(opt_idx, OPT_LOCAL);
- free_string_option(*(char_u **)p);
- *(char_u **)p = empty_option;
+ p = get_option_varp_scope(opt_idx, OPT_LOCAL);
+ free_string_option(*(char **)p);
+ *(char **)p = empty_option;
} else if (!(opt_flags & OPT_LOCAL) && opt_flags != OPT_GLOBAL) {
// May set global value for local option.
set_string_option_global(opt_idx, varp);
@@ -1542,7 +1542,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
syn_recursive++;
// Only pass true for "force" when the value changed or not used
// recursively, to avoid endless recurrence.
- apply_autocmds(EVENT_SYNTAX, (char *)curbuf->b_p_syn, curbuf->b_fname,
+ apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, curbuf->b_fname,
value_changed || syn_recursive == 1, curbuf);
curbuf->b_flags |= BF_SYN_SET;
syn_recursive--;
@@ -1562,7 +1562,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
did_filetype = true;
// Only pass true for "force" when the value changed or not
// used recursively, to avoid endless recurrence.
- apply_autocmds(EVENT_FILETYPE, (char *)curbuf->b_p_ft, curbuf->b_fname,
+ apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname,
value_changed || ft_recursive == 1, curbuf);
ft_recursive--;
// Just in case the old "curbuf" is now invalid
@@ -1573,8 +1573,8 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
}
}
if (varp == &(curwin->w_s->b_p_spl)) {
- char_u fname[200];
- char_u *q = curwin->w_s->b_p_spl;
+ char fname[200];
+ char *q = curwin->w_s->b_p_spl;
// Skip the first name if it is "cjk".
if (STRNCMP(q, "cjk,", 4) == 0) {
@@ -1585,15 +1585,14 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
// They could set 'spellcapcheck' depending on the language.
// Use the first name in 'spelllang' up to '_region' or
// '.encoding'.
- for (p = (char *)q; *p != NUL; p++) {
+ for (p = q; *p != NUL; p++) {
if (!ASCII_ISALNUM(*p) && *p != '-') {
break;
}
}
- if (p > (char *)q) {
- vim_snprintf((char *)fname, sizeof(fname), "spell/%.*s.vim",
- (int)(p - (char *)q), q);
- source_runtime((char *)fname, DIP_ALL);
+ if (p > q) {
+ vim_snprintf(fname, sizeof(fname), "spell/%.*s.vim", (int)(p - q), q);
+ source_runtime(fname, DIP_ALL);
}
}
}
@@ -1617,7 +1616,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
/// @param list when true: accept a list of values
///
/// @return OK for correct value, FAIL otherwise. Empty is always OK.
-static int check_opt_strings(char_u *val, char **values, int list)
+static int check_opt_strings(char *val, char **values, int list)
{
return opt_strings_flags(val, values, NULL, list);
}
@@ -1630,7 +1629,7 @@ static int check_opt_strings(char_u *val, char **values, int list)
/// @param list when true: accept a list of values
///
/// @return OK for correct value, FAIL otherwise. Empty is always OK.
-static int opt_strings_flags(char_u *val, char **values, unsigned *flagp, bool list)
+static int opt_strings_flags(char *val, char **values, unsigned *flagp, bool list)
{
unsigned int new_flags = 0;
@@ -1658,7 +1657,7 @@ static int opt_strings_flags(char_u *val, char **values, unsigned *flagp, bool l
}
/// @return OK if "p" is a valid fileformat name, FAIL otherwise.
-int check_ff_value(char_u *p)
+int check_ff_value(char *p)
{
return check_opt_strings(p, p_ff_values, false);
}
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index 795bff66cb..c940c86675 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -553,9 +553,9 @@ char_u *expand_env_save_opt(char_u *src, bool one)
/// @param src Input string e.g. "$HOME/vim.hlp"
/// @param dst[out] Where to put the result
/// @param dstlen Maximum length of the result
-void expand_env(char_u *src, char_u *dst, int dstlen)
+void expand_env(char *src, char *dst, int dstlen)
{
- expand_env_esc(src, dst, dstlen, false, false, NULL);
+ expand_env_esc((char_u *)src, (char_u *)dst, dstlen, false, false, NULL);
}
/// Expand environment variable with path name and escaping.
@@ -765,12 +765,12 @@ static char *vim_version_dir(const char *vimdir)
return NULL;
}
char *p = concat_fnames(vimdir, VIM_VERSION_NODOT, true);
- if (os_isdir((char_u *)p)) {
+ if (os_isdir(p)) {
return p;
}
xfree(p);
p = concat_fnames(vimdir, RUNTIME_DIRNAME, true);
- if (os_isdir((char_u *)p)) {
+ if (os_isdir(p)) {
return p;
}
xfree(p);
@@ -937,8 +937,8 @@ char *vim_getenv(const char *name)
// - the directory name from 'helpfile' (unless it contains '$')
// - the executable name from argv[0]
if (vim_path == NULL) {
- if (p_hf != NULL && vim_strchr((char *)p_hf, '$') == NULL) {
- vim_path = (char *)p_hf;
+ if (p_hf != NULL && vim_strchr(p_hf, '$') == NULL) {
+ vim_path = p_hf;
}
char exe_name[MAXPATHL];
@@ -957,7 +957,7 @@ char *vim_getenv(const char *name)
char *vim_path_end = path_tail(vim_path);
// remove "doc/" from 'helpfile', if present
- if (vim_path == (char *)p_hf) {
+ if (vim_path == p_hf) {
vim_path_end = remove_tail(vim_path, vim_path_end, "doc");
}
@@ -976,7 +976,7 @@ char *vim_getenv(const char *name)
assert(vim_path_end >= vim_path);
vim_path = xstrndup(vim_path, (size_t)(vim_path_end - vim_path));
- if (!os_isdir((char_u *)vim_path)) {
+ if (!os_isdir(vim_path)) {
xfree(vim_path);
vim_path = NULL;
}
@@ -1156,15 +1156,12 @@ char *home_replace_save(buf_T *buf, const char *src)
/// Function given to ExpandGeneric() to obtain an environment variable name.
char *get_env_name(expand_T *xp, int idx)
{
-#define ENVNAMELEN 100
- // this static buffer is needed to avoid a memory leak in ExpandGeneric
- static char_u name[ENVNAMELEN];
assert(idx >= 0);
char *envname = os_getenvname_at_index((size_t)idx);
if (envname) {
- STRLCPY(name, envname, ENVNAMELEN);
+ STRLCPY(xp->xp_buf, envname, EXPAND_BUF_LEN);
xfree(envname);
- return (char *)name;
+ return xp->xp_buf;
}
return NULL;
}
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 0d62a5f5f9..c0d5616666 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -129,10 +129,10 @@ bool os_isrealdir(const char *name)
/// Check if the given path exists and is a directory.
///
/// @return `true` if `name` is a directory.
-bool os_isdir(const char_u *name)
+bool os_isdir(const char *name)
FUNC_ATTR_NONNULL_ALL
{
- int32_t mode = os_getperm((const char *)name);
+ int32_t mode = os_getperm(name);
if (mode < 0) {
return false;
}
@@ -865,7 +865,7 @@ int os_file_is_writable(const char *name)
int r;
RUN_UV_FS_FUNC(r, uv_fs_access, name, W_OK, NULL);
if (r == 0) {
- return os_isdir((char_u *)name) ? 2 : 1;
+ return os_isdir(name) ? 2 : 1;
}
return 0;
}
@@ -911,11 +911,11 @@ int os_mkdir_recurse(const char *const dir, int32_t mode, char **const failed_di
// We're done when it's "/" or "c:/".
const size_t dirlen = strlen(dir);
char *const curdir = xmemdupz(dir, dirlen);
- char *const past_head = (char *)get_past_head((char_u *)curdir);
+ char *const past_head = get_past_head(curdir);
char *e = curdir + dirlen;
const char *const real_end = e;
const char past_head_save = *past_head;
- while (!os_isdir((char_u *)curdir)) {
+ while (!os_isdir(curdir)) {
e = path_tail_with_sep(curdir);
if (e <= past_head) {
*past_head = NUL;
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index b793b8f9c6..461a79c37b 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -55,7 +55,7 @@ static void save_patterns(int num_pat, char **pat, int *num_file, char ***file)
char_u *s = vim_strsave((char_u *)pat[i]);
// Be compatible with expand_filename(): halve the number of
// backslashes.
- backslash_halve(s);
+ backslash_halve((char *)s);
(*file)[i] = (char *)s;
}
*num_file = num_pat;
@@ -74,7 +74,7 @@ static bool have_wildcard(int num, char **file)
static bool have_dollars(int num, char **file)
{
for (int i = 0; i < num; i++) {
- if (vim_strchr((char *)file[i], '$') != NULL) {
+ if (vim_strchr(file[i], '$') != NULL) {
return true;
}
}
@@ -508,7 +508,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
}
// check if this entry should be included
- dir = (os_isdir((char_u *)(*file)[i]));
+ dir = (os_isdir((*file)[i]));
if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE))) {
continue;
}
@@ -911,7 +911,7 @@ static int do_os_system(char **argv, const char *input, size_t len, char **outpu
out_data_ring(NULL, SIZE_MAX);
}
if (forward_output) {
- // caller should decide if wait_return is invoked
+ // caller should decide if wait_return() is invoked
no_wait_return++;
msg_end();
no_wait_return--;
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 1500254de5..a5cec6772f 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -33,7 +33,7 @@
#include "nvim/vim.h"
#include "nvim/window.h"
-#define URL_SLASH 1 // path_is_url() has found "://"
+#define URL_SLASH 1 // path_is_url() has found ":/"
#define URL_BACKSLASH 2 // path_is_url() has found ":\\"
#ifdef gen_expand_wildcards
@@ -62,7 +62,7 @@ FileComparison path_full_compare(char *const s1, char *const s2, const bool chec
FileID file_id_1, file_id_2;
if (expandenv) {
- expand_env((char_u *)s1, (char_u *)exp1, MAXPATHL);
+ expand_env(s1, exp1, MAXPATHL);
} else {
STRLCPY(exp1, s1, MAXPATHL);
}
@@ -104,7 +104,7 @@ char *path_tail(const char *fname)
return "";
}
- const char *tail = (char *)get_past_head((char_u *)fname);
+ const char *tail = get_past_head(fname);
const char *p = tail;
// Find last part of path.
while (*p != NUL) {
@@ -130,7 +130,7 @@ char *path_tail_with_sep(char *fname)
assert(fname != NULL);
// Don't remove the '/' from "c:/file".
- char *past_head = (char *)get_past_head((char_u *)fname);
+ char *past_head = get_past_head(fname);
char *tail = path_tail(fname);
while (tail > past_head && after_pathsep(fname, tail)) {
tail--;
@@ -150,7 +150,7 @@ char *path_tail_with_sep(char *fname)
const char_u *invocation_path_tail(const char_u *invocation, size_t *len)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ARG(1)
{
- const char_u *tail = get_past_head((char_u *)invocation);
+ const char_u *tail = (char_u *)get_past_head((char *)invocation);
const char_u *p = tail;
while (*p != NUL && *p != ' ') {
bool was_sep = vim_ispathsep_nocolon(*p);
@@ -215,13 +215,13 @@ bool is_path_head(const char_u *path)
/// Get a pointer to one character past the head of a path name.
/// Unix: after "/"; Win: after "c:\"
/// If there is no head, path is returned.
-char_u *get_past_head(const char_u *path)
+char *get_past_head(const char *path)
{
- const char_u *retval = path;
+ const char *retval = path;
#ifdef WIN32
// May skip "c:"
- if (is_path_head(path)) {
+ if (is_path_head((char_u *)path)) {
retval = path + 2;
}
#endif
@@ -230,13 +230,11 @@ char_u *get_past_head(const char_u *path)
retval++;
}
- return (char_u *)retval;
+ return (char *)retval;
}
-/*
- * Return TRUE if 'c' is a path separator.
- * Note that for MS-Windows this includes the colon.
- */
+/// Return true if 'c' is a path separator.
+/// Note that for MS-Windows this includes the colon.
int vim_ispathsep(int c)
{
#ifdef UNIX
@@ -262,9 +260,7 @@ int vim_ispathsep_nocolon(int c)
;
}
-/*
- * return TRUE if 'c' is a path list separator.
- */
+/// return true if 'c' is a path list separator.
int vim_ispathlistsep(int c)
{
#ifdef UNIX
@@ -314,16 +310,14 @@ void shorten_dir_len(char_u *str, int trim_len)
/// Shorten the path of a file from "~/foo/../.bar/fname" to "~/f/../.b/fname"
/// It's done in-place.
-void shorten_dir(char_u *str)
+void shorten_dir(char *str)
{
- shorten_dir_len(str, 1);
+ shorten_dir_len((char_u *)str, 1);
}
-/*
- * Return TRUE if the directory of "fname" exists, FALSE otherwise.
- * Also returns TRUE if there is no directory name.
- * "fname" must be writable!.
- */
+/// Return true if the directory of "fname" exists, false otherwise.
+/// Also returns true if there is no directory name.
+/// "fname" must be writable!.
bool dir_of_file_exists(char_u *fname)
{
char *p = path_tail_with_sep((char *)fname);
@@ -332,7 +326,7 @@ bool dir_of_file_exists(char_u *fname)
}
char c = *p;
*p = NUL;
- bool retval = os_isdir(fname);
+ bool retval = os_isdir((char *)fname);
*p = c;
return retval;
}
@@ -376,16 +370,16 @@ int path_fnamencmp(const char *const fname1, const char *const fname2, size_t le
const char *p1 = fname1;
const char *p2 = fname2;
while (len > 0) {
- c1 = utf_ptr2char((const char_u *)p1);
- c2 = utf_ptr2char((const char_u *)p2);
+ c1 = utf_ptr2char(p1);
+ c2 = utf_ptr2char(p2);
if ((c1 == NUL || c2 == NUL
|| (!((c1 == '/' || c1 == '\\') && (c2 == '\\' || c2 == '/'))))
&& (p_fic ? (c1 != c2 && CH_FOLD(c1) != CH_FOLD(c2)) : c1 != c2)) {
break;
}
- len -= (size_t)utfc_ptr2len((const char_u *)p1);
- p1 += utfc_ptr2len((const char_u *)p1);
- p2 += utfc_ptr2len((const char_u *)p2);
+ len -= (size_t)utfc_ptr2len(p1);
+ p1 += utfc_ptr2len(p1);
+ p2 += utfc_ptr2len(p2);
}
return p_fic ? CH_FOLD(c1) - CH_FOLD(c2) : c1 - c2;
#else
@@ -637,7 +631,7 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
while (*path_end != NUL) {
/* May ignore a wildcard that has a backslash before it; it will
* be removed by rem_backslash() or file_pat_to_reg_pat() below. */
- if (path_end >= path + wildoff && rem_backslash(path_end)) {
+ if (path_end >= path + wildoff && rem_backslash((char *)path_end)) {
*p++ = *path_end++;
} else if (vim_ispathsep_nocolon(*path_end)) {
if (e != NULL) {
@@ -663,8 +657,8 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
// Now we have one wildcard component between "s" and "e".
/* Remove backslashes between "wildoff" and the start of the wildcard
* component. */
- for (p = buf + wildoff; p < s; ++p) {
- if (rem_backslash(p)) {
+ for (p = buf + wildoff; p < s; p++) {
+ if (rem_backslash((char *)p)) {
STRMOVE(p, p + 1);
e--;
s--;
@@ -672,7 +666,7 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
}
// Check for "**" between "s" and "e".
- for (p = s; p < e; ++p) {
+ for (p = s; p < e; p++) {
if (p[0] == '*' && p[1] == '*') {
starstar = true;
}
@@ -758,7 +752,7 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
// no more wildcards, check if there is a match
// remove backslashes for the remaining components only
if (*path_end != NUL) {
- backslash_halve(buf + len + 1);
+ backslash_halve((char *)buf + len + 1);
}
// add existing file or symbolic link
if ((flags & EW_ALLLINKS) ? os_fileinfo_link((char *)buf, &file_info)
@@ -806,10 +800,8 @@ static int find_previous_pathsep(char_u *path, char_u **psep)
return FAIL;
}
-/*
- * Returns TRUE if "maybe_unique" is unique wrt other_paths in "gap".
- * "maybe_unique" is the end portion of "((char_u **)gap->ga_data)[i]".
- */
+/// Returns true if "maybe_unique" is unique wrt other_paths in "gap".
+/// "maybe_unique" is the end portion of "((char_u **)gap->ga_data)[i]".
static bool is_unique(char_u *maybe_unique, garray_T *gap, int i)
{
char_u **other_paths = (char_u **)gap->ga_data;
@@ -843,7 +835,7 @@ static bool is_unique(char_u *maybe_unique, garray_T *gap, int i)
*/
static void expand_path_option(char_u *curdir, garray_T *gap)
{
- char_u *path_option = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
+ char_u *path_option = *curbuf->b_p_path == NUL ? p_path : (char_u *)curbuf->b_p_path;
char_u *buf = xmalloc(MAXPATHL);
while (*path_option != NUL) {
@@ -1143,16 +1135,14 @@ static int expand_in_path(garray_T *const gap, char_u *const pattern, const int
if (flags & EW_ADDSLASH) {
glob_flags |= WILD_ADD_SLASH;
}
- globpath((char *)paths, pattern, gap, glob_flags);
+ globpath((char *)paths, (char *)pattern, gap, glob_flags);
xfree(paths);
return gap->ga_len;
}
-/*
- * Return TRUE if "p" contains what looks like an environment variable.
- * Allowing for escaping.
- */
+/// Return true if "p" contains what looks like an environment variable.
+/// Allowing for escaping.
static bool has_env_var(char_u *p)
{
for (; *p; MB_PTR_ADV(p)) {
@@ -1167,7 +1157,7 @@ static bool has_env_var(char_u *p)
#ifdef SPECIAL_WILDCHAR
-// Return TRUE if "p" contains a special wildcard character, one that Vim
+// Return true if "p" contains a special wildcard character, one that Vim
// cannot expand, requires using a shell.
static bool has_special_wildchar(char_u *p)
{
@@ -1322,7 +1312,7 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
}
if (add_pat == -1 || (add_pat == 0 && (flags & EW_NOTFOUND))) {
- char_u *t = backslash_halve_save(p);
+ char_u *t = (char_u *)backslash_halve_save((char *)p);
/* When EW_NOTFOUND is used, always add files and dirs. Makes
* "vim c:/" work. */
@@ -1365,9 +1355,7 @@ void FreeWild(int count, char **files)
xfree(files);
}
-/*
- * Return TRUE if we can expand this backtick thing here.
- */
+/// Return true if we can expand this backtick thing here.
static int vim_backtick(char_u *p)
{
return *p == '`' && *(p + 1) != NUL && *(p + STRLEN(p) - 1) == '`';
@@ -1484,7 +1472,7 @@ void addfile(garray_T *gap, char_u *f, int flags)
}
#endif
- isdir = os_isdir(f);
+ isdir = os_isdir((char *)f);
if ((isdir && !(flags & EW_DIR)) || (!isdir && !(flags & EW_FILE))) {
return;
}
@@ -1684,7 +1672,7 @@ void simplify_filename(char_u *filename)
static char *eval_includeexpr(const char *const ptr, const size_t len)
{
set_vim_var_string(VV_FNAME, ptr, (ptrdiff_t)len);
- char *res = eval_to_string_safe((char *)curbuf->b_p_inex, NULL,
+ char *res = eval_to_string_safe(curbuf->b_p_inex, NULL,
was_set_insecurely(curwin, "includeexpr", OPT_LOCAL));
set_vim_var_string(VV_FNAME, NULL, 0);
return res;
@@ -1726,7 +1714,7 @@ char_u *find_file_name_in_path(char_u *ptr, size_t len, int options, long count,
ptr = tofree;
len = STRLEN(ptr);
file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
- TRUE, rel_fname);
+ true, rel_fname);
}
}
if (file_name == NULL && (options & FNAME_MESS)) {
@@ -1740,7 +1728,7 @@ char_u *find_file_name_in_path(char_u *ptr, size_t len, int options, long count,
* appears several times in the path. */
while (file_name != NULL && --count > 0) {
xfree(file_name);
- file_name = find_file_in_path(ptr, len, options, FALSE, rel_fname);
+ file_name = find_file_in_path(ptr, len, options, false, rel_fname);
}
} else {
file_name = vim_strnsave(ptr, len);
@@ -1751,12 +1739,26 @@ char_u *find_file_name_in_path(char_u *ptr, size_t len, int options, long count,
return file_name;
}
-// Check if the "://" of a URL is at the pointer, return URL_SLASH.
+/// Checks for a Windows drive letter ("C:/") at the start of the path.
+///
+/// @see https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
+bool path_has_drive_letter(const char *p)
+ FUNC_ATTR_NONNULL_ALL
+{
+ return strlen(p) >= 2
+ && ASCII_ISALPHA(p[0])
+ && (p[1] == ':' || p[1] == '|')
+ && (strlen(p) == 2 || ((p[2] == '/') | (p[2] == '\\') | (p[2] == '?') | (p[2] == '#')));
+}
+
+// Check if the ":/" of a URL is at the pointer, return URL_SLASH.
// Also check for ":\\", which MS Internet Explorer accepts, return
// URL_BACKSLASH.
int path_is_url(const char *p)
{
- if (strncmp(p, "://", 3) == 0) {
+ // In the spec ':' is enough to recognize a scheme
+ // https://url.spec.whatwg.org/#scheme-state
+ if (strncmp(p, ":/", 2) == 0) {
return URL_SLASH;
} else if (strncmp(p, ":\\\\", 3) == 0) {
return URL_BACKSLASH;
@@ -1781,6 +1783,10 @@ int path_with_url(const char *fname)
return 0;
}
+ if (path_has_drive_letter(fname)) {
+ return 0;
+ }
+
// check body: alpha or dash
for (p = fname + 1; (isalpha(*p) || (*p == '-')); p++) {}
@@ -1789,7 +1795,7 @@ int path_with_url(const char *fname)
return 0;
}
- // "://" or ":\\" must follow
+ // ":/" or ":\\" must follow
return path_is_url(p);
}
@@ -1802,9 +1808,7 @@ bool path_with_extension(const char *path, const char *extension)
return strcmp(last_dot + 1, extension) == 0;
}
-/*
- * Return TRUE if "name" is a full (absolute) path name or URL.
- */
+/// Return true if "name" is a full (absolute) path name or URL.
bool vim_isAbsName(char_u *name)
{
return path_with_url((char *)name) != 0 || path_is_absolute(name);
@@ -1841,7 +1845,7 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force)
return OK;
}
- int rv = path_to_absolute((char_u *)fname, (char_u *)buf, len, force);
+ int rv = path_to_absolute(fname, buf, len, force);
if (rv == FAIL) {
xstrlcpy(buf, fname, len); // something failed; use the filename
}
@@ -1900,7 +1904,7 @@ void path_fix_case(char *name)
}
// Open the directory where the file is located.
- char *slash = (char *)STRRCHR(name, '/');
+ char *slash = strrchr(name, '/');
char *tail;
Directory dir;
bool ok;
@@ -1941,21 +1945,17 @@ void path_fix_case(char *name)
os_closedir(&dir);
}
-/*
- * Return TRUE if "p" points to just after a path separator.
- * Takes care of multi-byte characters.
- * "b" must point to the start of the file name
- */
+/// Return true if "p" points to just after a path separator.
+/// Takes care of multi-byte characters.
+/// "b" must point to the start of the file name
int after_pathsep(const char *b, const char *p)
{
return p > b && vim_ispathsep(p[-1])
&& utf_head_off((char_u *)b, (char_u *)p - 1) == 0;
}
-/*
- * Return TRUE if file names "f1" and "f2" are in the same directory.
- * "f1" may be a short name, "f2" must be a full path.
- */
+/// Return true if file names "f1" and "f2" are in the same directory.
+/// "f1" may be a short name, "f2" must be a full path.
bool same_directory(char_u *f1, char_u *f2)
{
char ffname[MAXPATHL];
@@ -1967,7 +1967,7 @@ bool same_directory(char_u *f1, char_u *f2)
return false;
}
- (void)vim_FullName((char *)f1, (char *)ffname, MAXPATHL, FALSE);
+ (void)vim_FullName((char *)f1, (char *)ffname, MAXPATHL, false);
t1 = path_tail_with_sep(ffname);
t2 = path_tail_with_sep((char *)f2);
return t1 - ffname == (char_u *)t2 - f2
@@ -2135,10 +2135,11 @@ int expand_wildcards_eval(char_u **pat, int *num_file, char ***file, int flags)
if (*exp_pat == '%' || *exp_pat == '#' || *exp_pat == '<') {
emsg_off++;
- eval_pat = eval_vars((char_u *)exp_pat, (char_u *)exp_pat, &usedlen, NULL, &ignored_msg, NULL);
+ eval_pat = eval_vars((char_u *)exp_pat, (char_u *)exp_pat, &usedlen, NULL, &ignored_msg, NULL,
+ true);
emsg_off--;
if (eval_pat != NULL) {
- exp_pat = (char *)concat_str(eval_pat, (char_u *)exp_pat + usedlen);
+ exp_pat = concat_str((char *)eval_pat, exp_pat + usedlen);
}
}
@@ -2194,7 +2195,7 @@ int expand_wildcards(int num_pat, char **pat, int *num_files, char ***files, int
ffname = (char_u *)FullName_save((*files)[i], false);
assert((*files)[i] != NULL);
assert(ffname != NULL);
- if (match_file_list(p_wig, (char_u *)(*files)[i], ffname)) {
+ if (match_file_list((char_u *)p_wig, (char_u *)(*files)[i], ffname)) {
// remove this matching file from the list
xfree((*files)[i]);
for (j = i; j + 1 < *num_files; j++) {
@@ -2233,9 +2234,7 @@ int expand_wildcards(int num_pat, char **pat, int *num_files, char ***files, int
return retval;
}
-/*
- * Return TRUE if "fname" matches with an entry in 'suffixes'.
- */
+/// Return true if "fname" matches with an entry in 'suffixes'.
int match_suffix(char_u *fname)
{
#define MAXSUFLEN 30 // maximum length of a file suffix
@@ -2354,20 +2353,20 @@ int append_path(char *path, const char *to_append, size_t max_len)
/// @param force also expand when "fname" is already absolute.
///
/// @return FAIL for failure, OK for success.
-static int path_to_absolute(const char_u *fname, char_u *buf, size_t len, int force)
+static int path_to_absolute(const char *fname, char *buf, size_t len, int force)
{
- char_u *p;
+ char *p;
*buf = NUL;
char *relative_directory = xmalloc(len);
char *end_of_path = (char *)fname;
// expand it if forced or not an absolute path
- if (force || !path_is_absolute(fname)) {
- p = STRRCHR(fname, '/');
+ if (force || !path_is_absolute((char_u *)fname)) {
+ p = strrchr(fname, '/');
#ifdef WIN32
if (p == NULL) {
- p = STRRCHR(fname, '\\');
+ p = strrchr(fname, '\\');
}
#endif
if (p != NULL) {
@@ -2381,24 +2380,24 @@ static int path_to_absolute(const char_u *fname, char_u *buf, size_t len, int fo
memcpy(relative_directory, fname, (size_t)(p - fname));
relative_directory[p - fname] = NUL;
}
- end_of_path = (char *)(p + 1);
+ end_of_path = p + 1;
} else {
relative_directory[0] = NUL;
end_of_path = (char *)fname;
}
- if (FAIL == path_full_dir_name(relative_directory, (char *)buf, len)) {
+ if (FAIL == path_full_dir_name(relative_directory, buf, len)) {
xfree(relative_directory);
return FAIL;
}
}
xfree(relative_directory);
- return append_path((char *)buf, end_of_path, len);
+ return append_path(buf, end_of_path, len);
}
/// Check if file `fname` is a full (absolute) path.
///
-/// @return `TRUE` if "fname" is absolute.
+/// @return `true` if "fname" is absolute.
int path_is_absolute(const char_u *fname)
{
#ifdef WIN32
diff --git a/src/nvim/plines.c b/src/nvim/plines.c
index 70bdbd8b1d..cc730ba307 100644
--- a/src/nvim/plines.c
+++ b/src/nvim/plines.c
@@ -98,15 +98,15 @@ int plines_win_nofill(win_T *wp, linenr_T lnum, bool winheight)
/// "wp". Does not care about folding, 'wrap' or 'diff'.
int plines_win_nofold(win_T *wp, linenr_T lnum)
{
- char_u *s;
+ char *s;
unsigned int col;
int width;
- s = ml_get_buf(wp->w_buffer, lnum, false);
+ s = (char *)ml_get_buf(wp->w_buffer, lnum, false);
if (*s == NUL) { // empty line
return 1;
}
- col = win_linetabsize(wp, s, MAXCOL);
+ col = win_linetabsize(wp, lnum, (char_u *)s, MAXCOL);
// If list mode is on, then the '$' at the end of the line may take up one
// extra column.
@@ -145,23 +145,27 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column)
}
char_u *line = ml_get_buf(wp->w_buffer, lnum, false);
- char_u *s = line;
colnr_T col = 0;
- while (*s != NUL && --column >= 0) {
- col += win_lbr_chartabsize(wp, line, s, col, NULL);
- MB_PTR_ADV(s);
+ chartabsize_T cts;
+
+ init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
+ while (*cts.cts_ptr != NUL && --column >= 0) {
+ cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
+ MB_PTR_ADV(cts.cts_ptr);
}
- // If *s is a TAB, and the TAB is not displayed as ^I, and we're not in
- // MODE_INSERT state, then col must be adjusted so that it represents the
+ // If *cts.cts_ptr is a TAB, and the TAB is not displayed as ^I, and we're not
+ // in MODE_INSERT state, then col must be adjusted so that it represents the
// last screen position of the TAB. This only fixes an error when the TAB
// wraps from one screen line to the next (when 'columns' is not a multiple
// of 'ts') -- webb.
- if (*s == TAB && (State & MODE_NORMAL)
+ col = cts.cts_vcol;
+ if (*cts.cts_ptr == TAB && (State & MODE_NORMAL)
&& (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
- col += win_lbr_chartabsize(wp, line, s, col, NULL) - 1;
+ col += win_lbr_chartabsize(&cts, NULL) - 1;
}
+ clear_chartabsize_arg(&cts);
// Add column offset for 'number', 'relativenumber', 'foldcolumn', etc.
int width = wp->w_width_inner - win_col_off(wp);
@@ -223,13 +227,13 @@ int plines_m_win(win_T *wp, linenr_T first, linenr_T last)
/// @param col
///
/// @return Number of characters.
-int win_chartabsize(win_T *wp, char_u *p, colnr_T col)
+int win_chartabsize(win_T *wp, char *p, colnr_T col)
{
buf_T *buf = wp->w_buffer;
if (*p == TAB && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
return tabstop_padding(col, buf->b_p_ts, buf->b_p_vts_array);
} else {
- return ptr2cells((char *)p);
+ return ptr2cells(p);
}
}
@@ -241,24 +245,24 @@ int win_chartabsize(win_T *wp, char_u *p, colnr_T col)
/// @return Number of characters the string will take on the screen.
int linetabsize(char_u *s)
{
- return linetabsize_col(0, s);
+ return linetabsize_col(0, (char *)s);
}
-/// Like linetabsize(), but starting at column "startcol".
+/// Like linetabsize(), but "s" starts at column "startcol".
///
/// @param startcol
/// @param s
///
/// @return Number of characters the string will take on the screen.
-int linetabsize_col(int startcol, char_u *s)
+int linetabsize_col(int startcol, char *s)
{
- colnr_T col = startcol;
- char_u *line = s; // pointer to start of line, for breakindent
-
- while (*s != NUL) {
- col += lbr_chartabsize_adv(line, &s, col);
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, 0, startcol, (char_u *)s, (char_u *)s);
+ while (*cts.cts_ptr != NUL) {
+ cts.cts_vcol += lbr_chartabsize_adv(&cts);
}
- return (int)col;
+ clear_chartabsize_arg(&cts);
+ return cts.cts_vcol;
}
/// Like linetabsize(), but for a given window instead of the current one.
@@ -268,19 +272,39 @@ int linetabsize_col(int startcol, char_u *s)
/// @param len
///
/// @return Number of characters the string will take on the screen.
-unsigned int win_linetabsize(win_T *wp, char_u *line, colnr_T len)
+unsigned int win_linetabsize(win_T *wp, linenr_T lnum, char_u *line, colnr_T len)
{
- colnr_T col = 0;
-
- for (char_u *s = line;
- *s != NUL && (len == MAXCOL || s < line + len);
- MB_PTR_ADV(s)) {
- col += win_lbr_chartabsize(wp, line, s, col, NULL);
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
+ for (; *cts.cts_ptr != NUL && (len == MAXCOL || cts.cts_ptr < (char *)line + len);
+ MB_PTR_ADV(cts.cts_ptr)) {
+ cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
}
+ clear_chartabsize_arg(&cts);
+ return (unsigned int)cts.cts_vcol;
+}
- return (unsigned int)col;
+/// Prepare the structure passed to chartabsize functions.
+///
+/// "line" is the start of the line, "ptr" is the first relevant character.
+/// When "lnum" is zero do not use text properties that insert text.
+void init_chartabsize_arg(chartabsize_T *cts, win_T *wp, linenr_T lnum, colnr_T col, char_u *line,
+ char_u *ptr)
+{
+ cts->cts_win = wp;
+ cts->cts_lnum = lnum;
+ cts->cts_vcol = col;
+ cts->cts_line = (char *)line;
+ cts->cts_ptr = (char *)ptr;
+ cts->cts_cur_text_width = 0;
+ // TODO(bfredl): actually lookup inline virtual text here
+ cts->cts_has_virt_text = false;
}
+/// Free any allocated item in "cts".
+void clear_chartabsize_arg(chartabsize_T *cts)
+{}
+
/// like win_chartabsize(), but also check for line breaks on the screen
///
/// @param line
@@ -288,16 +312,16 @@ unsigned int win_linetabsize(win_T *wp, char_u *line, colnr_T len)
/// @param col
///
/// @return The number of characters taken up on the screen.
-int lbr_chartabsize(char_u *line, unsigned char *s, colnr_T col)
+int lbr_chartabsize(chartabsize_T *cts)
{
if (!curwin->w_p_lbr && *get_showbreak_value(curwin) == NUL
- && !curwin->w_p_bri) {
+ && !curwin->w_p_bri && !cts->cts_has_virt_text) {
if (curwin->w_p_wrap) {
- return win_nolbr_chartabsize(curwin, s, col, NULL);
+ return win_nolbr_chartabsize(cts, NULL);
}
- return win_chartabsize(curwin, s, col);
+ return win_chartabsize(curwin, cts->cts_ptr, cts->cts_vcol);
}
- return win_lbr_chartabsize(curwin, line == NULL ? s: line, s, col, NULL);
+ return win_lbr_chartabsize(cts, NULL);
}
/// Call lbr_chartabsize() and advance the pointer.
@@ -307,12 +331,12 @@ int lbr_chartabsize(char_u *line, unsigned char *s, colnr_T col)
/// @param col
///
/// @return The number of characters take up on the screen.
-int lbr_chartabsize_adv(char_u *line, char_u **s, colnr_T col)
+int lbr_chartabsize_adv(chartabsize_T *cts)
{
int retval;
- retval = lbr_chartabsize(line, *s, col);
- MB_PTR_ADV(*s);
+ retval = lbr_chartabsize(cts);
+ MB_PTR_ADV(cts->cts_ptr);
return retval;
}
@@ -322,17 +346,19 @@ int lbr_chartabsize_adv(char_u *line, char_u **s, colnr_T col)
/// string at start of line. Warning: *headp is only set if it's a non-zero
/// value, init to 0 before calling.
///
-/// @param wp
-/// @param line
-/// @param s
-/// @param col
+/// @param cts
/// @param headp
///
/// @return The number of characters taken up on the screen.
-int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *headp)
+int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
{
+ win_T *wp = cts->cts_win;
+ char *line = cts->cts_line; // start of the line
+ char_u *s = (char_u *)cts->cts_ptr;
+ colnr_T vcol = cts->cts_vcol;
+
colnr_T col2;
- colnr_T col_adj = 0; // col + screen size of tab
+ colnr_T col_adj = 0; // vcol + screen size of tab
colnr_T colmax;
int added;
int mb_added = 0;
@@ -340,16 +366,23 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
char_u *ps;
int n;
+ cts->cts_cur_text_width = 0;
+
// No 'linebreak', 'showbreak' and 'breakindent': return quickly.
- if (!wp->w_p_lbr && !wp->w_p_bri && *get_showbreak_value(wp) == NUL) {
+ if (!wp->w_p_lbr && !wp->w_p_bri && *get_showbreak_value(wp) == NUL
+ && !cts->cts_has_virt_text) {
if (wp->w_p_wrap) {
- return win_nolbr_chartabsize(wp, s, col, headp);
+ return win_nolbr_chartabsize(cts, headp);
}
- return win_chartabsize(wp, s, col);
+ return win_chartabsize(wp, (char *)s, vcol);
+ }
+
+ // First get normal size, without 'linebreak' or virtual text
+ int size = win_chartabsize(wp, (char *)s, vcol);
+ if (cts->cts_has_virt_text) {
+ // TODO(bfredl): inline virtual text
}
- // First get normal size, without 'linebreak'
- int size = win_chartabsize(wp, s, col);
int c = *s;
if (*s == TAB) {
col_adj = size - 1;
@@ -365,15 +398,15 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
// Count all characters from first non-blank after a blank up to next
// non-blank after a blank.
numberextra = win_col_off(wp);
- col2 = col;
+ col2 = vcol;
colmax = (colnr_T)(wp->w_width_inner - numberextra - col_adj);
- if (col >= colmax) {
+ if (vcol >= colmax) {
colmax += col_adj;
n = colmax + win_col_off2(wp);
if (n > 0) {
- colmax += (((col - colmax) / n) + 1) * n - col_adj;
+ colmax += (((vcol - colmax) / n) + 1) * n - col_adj;
}
}
@@ -383,21 +416,21 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
c = *s;
if (!(c != NUL
- && (vim_isbreak(c) || col2 == col || !vim_isbreak((int)(*ps))))) {
+ && (vim_isbreak(c) || col2 == vcol || !vim_isbreak((int)(*ps))))) {
break;
}
- col2 += win_chartabsize(wp, s, col2);
+ col2 += win_chartabsize(wp, (char *)s, col2);
if (col2 >= colmax) { // doesn't fit
- size = colmax - col + col_adj;
+ size = colmax - vcol + col_adj;
break;
}
}
} else if ((size == 2)
&& (MB_BYTE2LEN(*s) > 1)
&& wp->w_p_wrap
- && in_win_border(wp, col)) {
+ && in_win_border(wp, vcol)) {
// Count the ">" in the last column.
size++;
mb_added = 1;
@@ -409,40 +442,40 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
added = 0;
char *const sbr = (char *)get_showbreak_value(wp);
- if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && col != 0) {
+ if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && vcol != 0) {
colnr_T sbrlen = 0;
int numberwidth = win_col_off(wp);
numberextra = numberwidth;
- col += numberextra + mb_added;
+ vcol += numberextra + mb_added;
- if (col >= (colnr_T)wp->w_width_inner) {
- col -= wp->w_width_inner;
+ if (vcol >= (colnr_T)wp->w_width_inner) {
+ vcol -= wp->w_width_inner;
numberextra = wp->w_width_inner - (numberextra - win_col_off2(wp));
- if (col >= numberextra && numberextra > 0) {
- col %= numberextra;
+ if (vcol >= numberextra && numberextra > 0) {
+ vcol %= numberextra;
}
if (*sbr != NUL) {
sbrlen = (colnr_T)mb_charlen((char_u *)sbr);
- if (col >= sbrlen) {
- col -= sbrlen;
+ if (vcol >= sbrlen) {
+ vcol -= sbrlen;
}
}
- if (col >= numberextra && numberextra > 0) {
- col %= numberextra;
- } else if (col > 0 && numberextra > 0) {
- col += numberwidth - win_col_off2(wp);
+ if (vcol >= numberextra && numberextra > 0) {
+ vcol %= numberextra;
+ } else if (vcol > 0 && numberextra > 0) {
+ vcol += numberwidth - win_col_off2(wp);
}
numberwidth -= win_col_off2(wp);
}
- if (col == 0 || (col + size + sbrlen > (colnr_T)wp->w_width_inner)) {
+ if (vcol == 0 || (vcol + size + sbrlen > (colnr_T)wp->w_width_inner)) {
if (*sbr != NUL) {
if (size + sbrlen + numberwidth > (colnr_T)wp->w_width_inner) {
// Calculate effective window width.
int width = (colnr_T)wp->w_width_inner - sbrlen - numberwidth;
- int prev_width = col ? ((colnr_T)wp->w_width_inner - (sbrlen + col))
+ int prev_width = vcol ? ((colnr_T)wp->w_width_inner - (sbrlen + vcol))
: 0;
if (width <= 0) {
@@ -459,11 +492,11 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
}
if (wp->w_p_bri) {
- added += get_breakindent_win(wp, line);
+ added += get_breakindent_win(wp, (char_u *)line);
}
size += added;
- if (col != 0) {
+ if (vcol != 0) {
added = 0;
}
}
@@ -485,8 +518,11 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
/// @param headp
///
/// @return The number of characters take up on the screen.
-static int win_nolbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp)
+static int win_nolbr_chartabsize(chartabsize_T *cts, int *headp)
{
+ win_T *wp = cts->cts_win;
+ char *s = cts->cts_ptr;
+ colnr_T col = cts->cts_vcol;
int n;
if ((*s == TAB) && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
@@ -494,11 +530,11 @@ static int win_nolbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp)
wp->w_buffer->b_p_ts,
wp->w_buffer->b_p_vts_array);
}
- n = ptr2cells((char *)s);
+ n = ptr2cells(s);
// Add one cell for a double-width character in the last column of the
// window, displayed with a ">".
- if ((n == 2) && (MB_BYTE2LEN(*s) > 1) && in_win_border(wp, col)) {
+ if ((n == 2) && (MB_BYTE2LEN((uint8_t)(*s)) > 1) && in_win_border(wp, col)) {
if (headp != NULL) {
*headp = 1;
}
diff --git a/src/nvim/plines.h b/src/nvim/plines.h
index 32778b69f1..7b228f3e91 100644
--- a/src/nvim/plines.h
+++ b/src/nvim/plines.h
@@ -3,6 +3,20 @@
#include "nvim/vim.h"
+// Argument for lbr_chartabsize().
+typedef struct {
+ win_T *cts_win;
+ linenr_T cts_lnum; // zero when not using text properties
+ char *cts_line; // start of the line
+ char *cts_ptr; // current position in line
+
+ bool cts_has_virt_text; // true if if a property inserts text
+ int cts_cur_text_width; // width of current inserted text
+ // TODO(bfredl): iterator in to the marktree for scanning virt text
+
+ int cts_vcol; // virtual column at current position
+} chartabsize_T;
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "plines.h.generated.h"
#endif
diff --git a/src/nvim/po/af.po b/src/nvim/po/af.po
index 82345f8a46..d64789660e 100644
--- a/src/nvim/po/af.po
+++ b/src/nvim/po/af.po
@@ -5320,8 +5320,8 @@ msgstr "E424: Te veel verskillende uitlig-eienskappe in gebruik"
msgid "E669: Unprintable character in group name"
msgstr "E669: Onvertoonbare karakter in groepnaam"
-msgid "W18: Invalid character in group name"
-msgstr "W18: Ongeldige karakter groepnaam"
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Ongeldige karakter groepnaam"
#~ msgid "E849: Too many highlight and syntax groups"
#~ msgstr ""
diff --git a/src/nvim/po/ca.po b/src/nvim/po/ca.po
index 6c4d6ddd22..5869e6567c 100644
--- a/src/nvim/po/ca.po
+++ b/src/nvim/po/ca.po
@@ -5983,9 +5983,9 @@ msgstr "E424: Hi ha massa atributs de ressalt diferents en s"
msgid "E669: Unprintable character in group name"
msgstr "E669: Carcter no imprimible en el nom del grup"
-#: ../syntax.c:7434
-msgid "W18: Invalid character in group name"
-msgstr "W18: Hi ha un carcter no vlid en el nom del grup"
+#: ../highlight_group.c:1756
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Hi ha un carcter no vlid en el nom del grup"
#: ../syntax.c:7448
msgid "E849: Too many highlight and syntax groups"
diff --git a/src/nvim/po/cs.cp1250.po b/src/nvim/po/cs.cp1250.po
index 859039eb87..bce5c0fa76 100644
--- a/src/nvim/po/cs.cp1250.po
+++ b/src/nvim/po/cs.cp1250.po
@@ -6072,10 +6072,10 @@ msgstr ""
msgid "E669: Unprintable character in group name"
msgstr ""
-#: ../syntax.c:7434
+#: ../highlight_group.c:1756
#, fuzzy
-msgid "W18: Invalid character in group name"
-msgstr "E182: Chybn jmno pkazu"
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Chybn jmno pkazu"
#: ../syntax.c:7448
msgid "E849: Too many highlight and syntax groups"
diff --git a/src/nvim/po/cs.po b/src/nvim/po/cs.po
index 4d9ad58836..f4eab3f0d4 100644
--- a/src/nvim/po/cs.po
+++ b/src/nvim/po/cs.po
@@ -6072,10 +6072,10 @@ msgstr ""
msgid "E669: Unprintable character in group name"
msgstr ""
-#: ../syntax.c:7434
+#: ../highlight_group.c:1756
#, fuzzy
-msgid "W18: Invalid character in group name"
-msgstr "E182: Chybn jmno pkazu"
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Chybn jmno pkazu"
#: ../syntax.c:7448
msgid "E849: Too many highlight and syntax groups"
diff --git a/src/nvim/po/da.po b/src/nvim/po/da.po
index f2b28ccc90..f4d39327b3 100644
--- a/src/nvim/po/da.po
+++ b/src/nvim/po/da.po
@@ -5599,8 +5599,8 @@ msgstr "E424: For mange forskellige fremhævningsattributter i brug"
msgid "E669: Unprintable character in group name"
msgstr "E669: Tegn som ikke kan udskrives i gruppenavn"
-msgid "W18: Invalid character in group name"
-msgstr "W18: Ugyldige tegn i gruppenavn"
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Ugyldige tegn i gruppenavn"
msgid "E849: Too many highlight and syntax groups"
msgstr "E849: For mange fremhævnings- og syntaksgrupper"
diff --git a/src/nvim/po/de.po b/src/nvim/po/de.po
index 2dde77e9f7..ce3fd77ede 100644
--- a/src/nvim/po/de.po
+++ b/src/nvim/po/de.po
@@ -5408,8 +5408,8 @@ msgid "E669: Unprintable character in group name"
msgstr "E669: Nicht druckbare Zeichen im Namen der Gruppe"
#: ../syntax.c:7304
-msgid "W18: Invalid character in group name"
-msgstr "W18: Ungltiges Zeichen im Namen der Gruppe"
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Ungltiges Zeichen im Namen der Gruppe"
#: ../syntax.c:7318
msgid "E849: Too many highlight and syntax groups"
diff --git a/src/nvim/po/en_GB.po b/src/nvim/po/en_GB.po
index 66cdba6f92..81ee9ed6a0 100644
--- a/src/nvim/po/en_GB.po
+++ b/src/nvim/po/en_GB.po
@@ -5730,8 +5730,8 @@ msgstr ""
msgid "E669: Unprintable character in group name"
msgstr ""
-#: ../syntax.c:7434
-msgid "W18: Invalid character in group name"
+#: ../highlight_group.c:1756
+msgid "E5248: Invalid character in group name"
msgstr ""
#: ../syntax.c:7448
diff --git a/src/nvim/po/eo.po b/src/nvim/po/eo.po
index 1c503d0a84..263fb61b18 100644
--- a/src/nvim/po/eo.po
+++ b/src/nvim/po/eo.po
@@ -5378,8 +5378,8 @@ msgstr "E424: Tro da malsamaj atributoj de emfazo uzataj"
msgid "E669: Unprintable character in group name"
msgstr "E669: Nepresebla signo en nomo de grupo"
-msgid "W18: Invalid character in group name"
-msgstr "W18: Nevalida signo en nomo de grupo"
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Nevalida signo en nomo de grupo"
msgid "E849: Too many highlight and syntax groups"
msgstr "E849: Tro da emfazaj kaj sintaksaj grupoj"
diff --git a/src/nvim/po/es.po b/src/nvim/po/es.po
index adea651b7c..8a44f6a534 100644
--- a/src/nvim/po/es.po
+++ b/src/nvim/po/es.po
@@ -6053,9 +6053,9 @@ msgstr "E669: Carácter no imprimible en el nombre del grupo"
# This is an error, but since there previously was no check only
# * give a warning.
-#: ../syntax.c:7434
-msgid "W18: Invalid character in group name"
-msgstr "W18: Hay un carácter no válido en el nombre del grupo"
+#: ../highlight_group.c:1756
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Hay un carácter no válido en el nombre del grupo"
#: ../syntax.c:7448
msgid "E849: Too many highlight and syntax groups"
diff --git a/src/nvim/po/fi.po b/src/nvim/po/fi.po
index f10d4ce977..1c0da244ba 100644
--- a/src/nvim/po/fi.po
+++ b/src/nvim/po/fi.po
@@ -5369,8 +5369,8 @@ msgstr "E424: Liikaa eri korostusattribuutteja"
msgid "E669: Unprintable character in group name"
msgstr "E669: Tulostuskelvoton merkki ryhmän nimessä"
-msgid "W18: Invalid character in group name"
-msgstr "W18: Virheellinen merkki ryhmän nimessä"
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Virheellinen merkki ryhmän nimessä"
msgid "E849: Too many highlight and syntax groups"
msgstr "E849: Liikaa korostuksia ja syntaksiryhmiä"
diff --git a/src/nvim/po/fr.po b/src/nvim/po/fr.po
index 239d6da211..cc3e9d6a0c 100644
--- a/src/nvim/po/fr.po
+++ b/src/nvim/po/fr.po
@@ -2040,8 +2040,8 @@ msgstr ""
msgid "E669: Unprintable character in group name"
msgstr "E669: Caractre non imprimable dans un nom de groupe"
-msgid "W18: Invalid character in group name"
-msgstr "W18: Caractre invalide dans un nom de groupe"
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Caractre invalide dans un nom de groupe"
msgid "E849: Too many highlight and syntax groups"
msgstr "E849: Trop de groupes de surbrillance et de syntaxe"
diff --git a/src/nvim/po/ga.po b/src/nvim/po/ga.po
index 1c25ee481c..346f0faa84 100644
--- a/src/nvim/po/ga.po
+++ b/src/nvim/po/ga.po
@@ -5668,8 +5668,8 @@ msgstr "E424: An iomarca trithe aibhsithe in sid"
msgid "E669: Unprintable character in group name"
msgstr "E669: Carachtar neamhghrafach in ainm grpa"
-msgid "W18: Invalid character in group name"
-msgstr "W18: Carachtar neamhbhail in ainm grpa"
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Carachtar neamhbhail in ainm grpa"
msgid "E849: Too many highlight and syntax groups"
msgstr "E849: An iomarca grpa aibhsithe agus comhrire"
diff --git a/src/nvim/po/it.po b/src/nvim/po/it.po
index 313280c807..152ed2cbe3 100644
--- a/src/nvim/po/it.po
+++ b/src/nvim/po/it.po
@@ -6046,9 +6046,9 @@ msgstr "E424: Troppi gruppi evidenziazione differenti in uso"
msgid "E669: Unprintable character in group name"
msgstr "E669: Carattere non stampabile in un nome di gruppo"
-#: ../syntax.c:7434
-msgid "W18: Invalid character in group name"
-msgstr "W18: Carattere non ammesso in un nome di gruppo"
+#: ../highlight_group.c:1756
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Carattere non ammesso in un nome di gruppo"
#: ../syntax.c:7448
msgid "E849: Too many highlight and syntax groups"
diff --git a/src/nvim/po/ko.UTF-8.po b/src/nvim/po/ko.UTF-8.po
index b99c22caeb..09be710374 100644
--- a/src/nvim/po/ko.UTF-8.po
+++ b/src/nvim/po/ko.UTF-8.po
@@ -5913,9 +5913,9 @@ msgstr "E424: 너무 많은 다른 하이라이트 속성이 사용되고 있습
msgid "E669: Unprintable character in group name"
msgstr "E669: 그룹 이름에 출력할 수 없는 문자가 있습니다"
-#: ../syntax.c:7434
-msgid "W18: Invalid character in group name"
-msgstr "W18: 그룹 이름에 이상한 문자"
+#: ../highlight_group.c:1756
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: 그룹 이름에 이상한 문자"
#: ../syntax.c:7448
msgid "E849: Too many highlight and syntax groups"
diff --git a/src/nvim/po/nb.po b/src/nvim/po/nb.po
index 2285d755cf..9bc730ae71 100644
--- a/src/nvim/po/nb.po
+++ b/src/nvim/po/nb.po
@@ -5930,9 +5930,9 @@ msgstr "E424: For mange forskjellige uthevingsattributter i bruk"
msgid "E669: Unprintable character in group name"
msgstr "E669: Ikke-skrivbart tegn i gruppenavn"
-#: ../syntax.c:7434
-msgid "W18: Invalid character in group name"
-msgstr "W18: Ugyldig tegn i gruppenavn"
+#: ../highlight_group.c:1756
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Ugyldig tegn i gruppenavn"
#: ../syntax.c:7448
msgid "E849: Too many highlight and syntax groups"
diff --git a/src/nvim/po/nl.po b/src/nvim/po/nl.po
index 00d113c83c..4d2e55adc6 100644
--- a/src/nvim/po/nl.po
+++ b/src/nvim/po/nl.po
@@ -5913,8 +5913,8 @@ msgstr ""
msgid "E669: Unprintable character in group name"
msgstr ""
-#: ../syntax.c:7434
-msgid "W18: Invalid character in group name"
+#: ../highlight_group.c:1756
+msgid "E5248: Invalid character in group name"
msgstr ""
#: ../syntax.c:7448
diff --git a/src/nvim/po/no.po b/src/nvim/po/no.po
index 2285d755cf..9bc730ae71 100644
--- a/src/nvim/po/no.po
+++ b/src/nvim/po/no.po
@@ -5930,9 +5930,9 @@ msgstr "E424: For mange forskjellige uthevingsattributter i bruk"
msgid "E669: Unprintable character in group name"
msgstr "E669: Ikke-skrivbart tegn i gruppenavn"
-#: ../syntax.c:7434
-msgid "W18: Invalid character in group name"
-msgstr "W18: Ugyldig tegn i gruppenavn"
+#: ../highlight_group.c:1756
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Ugyldig tegn i gruppenavn"
#: ../syntax.c:7448
msgid "E849: Too many highlight and syntax groups"
diff --git a/src/nvim/po/pl.UTF-8.po b/src/nvim/po/pl.UTF-8.po
index 5f1779d1bd..7e978113f6 100644
--- a/src/nvim/po/pl.UTF-8.po
+++ b/src/nvim/po/pl.UTF-8.po
@@ -5908,9 +5908,9 @@ msgstr "E424: Zbyt wiele różnych atrybutów podkreślania w użyciu"
msgid "E669: Unprintable character in group name"
msgstr "E669: Niedrukowalny znak w nazwie grupy"
-#: ../syntax.c:7434
-msgid "W18: Invalid character in group name"
-msgstr "W18: nieprawidłowy znak w nazwie grupy"
+#: ../highlight_group.c:1756
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: nieprawidłowy znak w nazwie grupy"
#: ../syntax.c:7448
msgid "E849: Too many highlight and syntax groups"
diff --git a/src/nvim/po/pt_BR.po b/src/nvim/po/pt_BR.po
index 533d916de1..bfd64b4d28 100644
--- a/src/nvim/po/pt_BR.po
+++ b/src/nvim/po/pt_BR.po
@@ -6070,8 +6070,8 @@ msgid "E669: Unprintable character in group name"
msgstr "E669: Caractere no-imprimvel no nome do grupo"
#: ../syntax.c:7320
-msgid "W18: Invalid character in group name"
-msgstr "W18: Caractere invlido no nome do grupo"
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Caractere invlido no nome do grupo"
#: ../syntax.c:7334
msgid "E849: Too many highlight and syntax groups"
diff --git a/src/nvim/po/ru.po b/src/nvim/po/ru.po
index 7566036d3e..da356770d7 100644
--- a/src/nvim/po/ru.po
+++ b/src/nvim/po/ru.po
@@ -5977,9 +5977,9 @@ msgstr "E424: Используется слишком много разных а
msgid "E669: Unprintable character in group name"
msgstr "E669: Непечатный символ в имени группы"
-#: ../syntax.c:7434
-msgid "W18: Invalid character in group name"
-msgstr "W18: Недопустимый символ в имени группы"
+#: ../highlight_group.c:1756
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Недопустимый символ в имени группы"
#: ../syntax.c:7448
msgid "E849: Too many highlight and syntax groups"
diff --git a/src/nvim/po/sk.cp1250.po b/src/nvim/po/sk.cp1250.po
index ff95c68a12..cb8b8c6abb 100644
--- a/src/nvim/po/sk.cp1250.po
+++ b/src/nvim/po/sk.cp1250.po
@@ -5940,9 +5940,9 @@ msgstr "E424: Pouvanch prli vea odlinch zvrazovacch vlastnost"
msgid "E669: Unprintable character in group name"
msgstr "E669: Netlaiteln znak v mene skupiny"
-#: ../syntax.c:7434
-msgid "W18: Invalid character in group name"
-msgstr "W18: Chybn znak v mene skupiny"
+#: ../highlight_group.c:1756
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Chybn znak v mene skupiny"
#: ../syntax.c:7448
msgid "E849: Too many highlight and syntax groups"
diff --git a/src/nvim/po/sk.po b/src/nvim/po/sk.po
index d35622726f..4f9e1fe185 100644
--- a/src/nvim/po/sk.po
+++ b/src/nvim/po/sk.po
@@ -5940,9 +5940,9 @@ msgstr "E424: Pouvanch prli vea odlinch zvrazovacch vlastnost"
msgid "E669: Unprintable character in group name"
msgstr "E669: Netlaiteln znak v mene skupiny"
-#: ../syntax.c:7434
-msgid "W18: Invalid character in group name"
-msgstr "W18: Chybn znak v mene skupiny"
+#: ../highlight_group.c:1756
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Chybn znak v mene skupiny"
#: ../syntax.c:7448
msgid "E849: Too many highlight and syntax groups"
diff --git a/src/nvim/po/sr.po b/src/nvim/po/sr.po
index 3c45e1bf80..cbdf736d0f 100644
--- a/src/nvim/po/sr.po
+++ b/src/nvim/po/sr.po
@@ -6050,8 +6050,8 @@ msgstr "E424: У употреби је превише различитих ат
msgid "E669: Unprintable character in group name"
msgstr "E669: У имену групе је карактер који не може да се штампа"
-msgid "W18: Invalid character in group name"
-msgstr "W18: Неважећи карактер у имену групе"
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Неважећи карактер у имену групе"
msgid "E849: Too many highlight and syntax groups"
msgstr "E849: Превише синтаксних и група истицања"
diff --git a/src/nvim/po/sv.po b/src/nvim/po/sv.po
index d50c9d695d..406900f7b2 100644
--- a/src/nvim/po/sv.po
+++ b/src/nvim/po/sv.po
@@ -2056,8 +2056,8 @@ msgid "E669: Unprintable character in group name"
msgstr "E669: Outskrivbart tecken i gruppnamn"
#: ../syntax.c:7292
-msgid "W18: Invalid character in group name"
-msgstr "W18: Ogiltigt tecken i gruppnamn"
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Ogiltigt tecken i gruppnamn"
#: ../syntax.c:7306
msgid "E849: Too many highlight and syntax groups"
diff --git a/src/nvim/po/tr.po b/src/nvim/po/tr.po
index d534666bbb..1ecdcd2f65 100644
--- a/src/nvim/po/tr.po
+++ b/src/nvim/po/tr.po
@@ -3054,8 +3054,8 @@ msgstr "E423: İzin verilmeyen argüman: %s"
msgid "E669: Unprintable character in group name"
msgstr "E669: Grup adında yazdırılamayan karakter"
-msgid "W18: Invalid character in group name"
-msgstr "W18: Grup adında geçersiz karakter"
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Grup adında geçersiz karakter"
msgid "E849: Too many highlight and syntax groups"
msgstr "E849: Çok fazla vurgulama ve sözdizim grupları"
diff --git a/src/nvim/po/uk.po b/src/nvim/po/uk.po
index 1b514ad7c3..d3dfc4c612 100644
--- a/src/nvim/po/uk.po
+++ b/src/nvim/po/uk.po
@@ -3058,8 +3058,8 @@ msgstr "E423: Неправильний аргумент: %s"
msgid "E669: Unprintable character in group name"
msgstr "E669: Недруковний символ у назві групи"
-msgid "W18: Invalid character in group name"
-msgstr "W18: Некоректний символ у назві групи"
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Некоректний символ у назві групи"
msgid "E849: Too many highlight and syntax groups"
msgstr "E849: Забагато груп підсвічування і синтаксису"
diff --git a/src/nvim/po/vi.po b/src/nvim/po/vi.po
index c693f910d8..ad59718a30 100644
--- a/src/nvim/po/vi.po
+++ b/src/nvim/po/vi.po
@@ -5975,9 +5975,9 @@ msgstr "E424: Sử dụng quá nhiều thuộc tính chiếu sáng cú pháp"
msgid "E669: Unprintable character in group name"
msgstr "E669: Ký tự không thể tin ra trong tên nhóm"
-#: ../syntax.c:7434
-msgid "W18: Invalid character in group name"
-msgstr "W18: Ký tự không cho phép trong tên nhóm"
+#: ../highlight_group.c:1756
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: Ký tự không cho phép trong tên nhóm"
#: ../syntax.c:7448
msgid "E849: Too many highlight and syntax groups"
diff --git a/src/nvim/po/zh_CN.UTF-8.po b/src/nvim/po/zh_CN.UTF-8.po
index 70c1389d7f..afa2f29029 100644
--- a/src/nvim/po/zh_CN.UTF-8.po
+++ b/src/nvim/po/zh_CN.UTF-8.po
@@ -734,9 +734,9 @@ msgid "E120: Using <SID> not in a script context: %s"
msgstr "E120: <SID> 不能在 script 上下文外使用: %s"
#: ../eval.c:7391
-#, fuzzy, c-format
+#, c-format
msgid "E725: Calling dict function without Dictionary: %s"
-msgstr "E720: Dictionary 中缺少冒号: %s"
+msgstr "E725: 调用字典函数但是没有字典:%s"
#: ../eval.c:7453
#, fuzzy
@@ -766,19 +766,16 @@ msgid "E737: Key already exists: %s"
msgstr "E737: 键已存在: %s"
#: ../eval.c:8692
-#, fuzzy
msgid "extend() argument"
-msgstr "--cmd 参数"
+msgstr "extend() 参数"
#: ../eval.c:8915
-#, fuzzy
msgid "map() argument"
-msgstr "-c 参数"
+msgstr "map() 参数"
#: ../eval.c:8916
-#, fuzzy
msgid "filter() argument"
-msgstr "-c 参数"
+msgstr "filter() 参数"
#: ../eval.c:9229
#, c-format
@@ -849,9 +846,8 @@ msgid "E702: Sort compare function failed"
msgstr "E702: Sort 比较函数失败"
#: ../eval.c:13806
-#, fuzzy
msgid "E882: Uniq compare function failed"
-msgstr "E702: Sort 比较函数失败"
+msgstr "E882: Uniq 比较函数失败"
#: ../eval.c:14085
msgid "(Invalid)"
@@ -864,31 +860,31 @@ msgstr "E677: 写临时文件出错"
#: ../eval.c:16159
#, fuzzy
msgid "E805: Using a Float as a Number"
-msgstr "E745: 将 List 作数字使用"
+msgstr "E805: 将浮点数当做数字使用"
#: ../eval.c:16162
msgid "E703: Using a Funcref as a Number"
-msgstr "E703: 将 Funcref 作数字使用"
+msgstr "E703: 将函数当做数字使用"
#: ../eval.c:16170
msgid "E745: Using a List as a Number"
-msgstr "E745: 将 List 作数字使用"
+msgstr "E745: 将列表当做数字使用"
#: ../eval.c:16173
msgid "E728: Using a Dictionary as a Number"
-msgstr "E728: 将 Dictionary 作数字使用"
+msgstr "E728: 将字典当做数字使用"
#: ../eval.c:16259
msgid "E729: using Funcref as a String"
-msgstr "E729: 将 Funcref 作 String 使用"
+msgstr "E729: 将函数当做字符串使用"
#: ../eval.c:16262
msgid "E730: using List as a String"
-msgstr "E730: 将 List 作 String 使用"
+msgstr "E730: 将列表当做字符串使用"
#: ../eval.c:16265
msgid "E731: using Dictionary as a String"
-msgstr "E731: 将 Dictionary 作 String 使用"
+msgstr "E731: 将字典当做字符串使用"
#: ../eval.c:16619
#, c-format
@@ -3053,11 +3049,11 @@ msgstr "E673: 不兼容的多字节编码和字符集。"
#: ../hardcopy.c:2238
msgid "E674: printmbcharset cannot be empty with multi-byte encoding."
-msgstr "E674: printmbcharset 在多字节编码下不能为空。"
+msgstr "E674: printmbcharset 在多字节编码下不能为空"
#: ../hardcopy.c:2254
msgid "E675: No default font specified for multi-byte printing."
-msgstr "E675: 没有指定多字节打印的默认字体。"
+msgstr "E675: 没有指定多字节打印的默认字体"
#: ../hardcopy.c:2426
msgid "E324: Can't open PostScript output file"
@@ -4204,9 +4200,8 @@ msgstr "E329: 没有菜单 \"%s\""
#. Only a mnemonic or accelerator is not valid.
#: ../menu.c:329
-#, fuzzy
msgid "E792: Empty menu name"
-msgstr "E749: 空的缓冲区"
+msgstr "E792: 空的菜单名称"
#: ../menu.c:340
msgid "E330: Menu path must not lead to a sub-menu"
@@ -4329,9 +4324,8 @@ msgid "E766: Insufficient arguments for printf()"
msgstr "E766: printf() 的参数不足"
#: ../message.c:3119
-#, fuzzy
msgid "E807: Expected Float argument for printf()"
-msgstr "E766: printf() 的参数不足"
+msgstr "E807: 期盼浮点数作为printf()参数"
#: ../message.c:3873
msgid "E767: Too many arguments to printf()"
@@ -5675,9 +5669,9 @@ msgid "E781: .sug file doesn't match .spl file: %s"
msgstr "E781: .sug 文件不能匹配 .spl 文件: %s"
#: ../spell.c:9305
-#, fuzzy, c-format
+#, c-format
msgid "E782: error while reading .sug file: %s"
-msgstr "E47: 读取错误文件失败"
+msgstr "E782: 当读取.sug 文件时错误"
#. This should have been checked when generating the .spl
#. file.
@@ -5867,6 +5861,7 @@ msgstr "E410: 不正确的 :syntax 子命令: %s"
msgid ""
" TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN"
msgstr ""
+" 总 计 计 数 匹 配 最 慢 的 平 均 名 字 模 式"
#: ../syntax.c:6146
msgid "E679: recursive loop loading syncolor.vim"
@@ -5942,9 +5937,9 @@ msgstr "E424: 使用了太多不同的高亮度属性"
msgid "E669: Unprintable character in group name"
msgstr "E669: 组名中存在不可显示字符"
-#: ../syntax.c:7434
-msgid "W18: Invalid character in group name"
-msgstr "W18: 组名中含有无效字符"
+#: ../highlight_group.c:1756
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: 组名中含有无效字符"
#: ../syntax.c:7448
msgid "E849: Too many highlight and syntax groups"
@@ -6103,14 +6098,13 @@ msgstr "Vim: 读错误,退出中...\n"
#. This happens when the FileChangedRO autocommand changes the
#. * file in a way it becomes shorter.
#: ../undo.c:379
-#, fuzzy
msgid "E881: Line count changed unexpectedly"
-msgstr "E787: 意外地改变了缓冲区"
+msgstr "E881: 行数意外地改变了"
#: ../undo.c:627
-#, fuzzy, c-format
+#, c-format
msgid "E828: Cannot open undo file for writing: %s"
-msgstr "E212: 无法打开并写入文件"
+msgstr "E828: 无法打开撤销文件去写入"
#: ../undo.c:717
#, c-format
diff --git a/src/nvim/po/zh_TW.UTF-8.po b/src/nvim/po/zh_TW.UTF-8.po
index e2fb2d39d4..e95b1e2cad 100644
--- a/src/nvim/po/zh_TW.UTF-8.po
+++ b/src/nvim/po/zh_TW.UTF-8.po
@@ -59,19 +59,19 @@ msgstr "無法傳送回應訊息"
#: ../api/private/helpers.c:204
msgid "internal error: unknown option type"
-msgstr ""
+msgstr "內部錯誤: 未知的選項類型"
#: ../buffer.c:92
msgid "[Location List]"
-msgstr ""
+msgstr "[Location 列表]"
#: ../buffer.c:93
msgid "[Quickfix List]"
-msgstr ""
+msgstr "[Quickfix 列表]"
#: ../buffer.c:94
msgid "E855: Autocommands caused command to abort"
-msgstr ""
+msgstr "E855: 自動命令導致命令被停止"
#: ../buffer.c:135
msgid "E82: Cannot allocate any buffer, exiting..."
@@ -349,7 +349,7 @@ msgstr "E103: 緩衝區 \"%s\" 不是在 diff 模式"
#: ../diff.c:2193
msgid "E787: Buffer changed unexpectedly"
-msgstr ""
+msgstr "E787: 意外地改變了緩衝區"
#: ../digraph.c:1598
msgid "E104: Escape not allowed in digraph"
@@ -365,7 +365,7 @@ msgstr "E105: 使用 :loadkeymap "
#: ../digraph.c:1821
msgid "E791: Empty keymap entry"
-msgstr ""
+msgstr "E791: 空的鍵位映射項"
#: ../edit.c:82
msgid " Keyword completion (^N^P)"
@@ -434,11 +434,11 @@ msgstr "已到段落結尾"
#: ../edit.c:101
msgid "E839: Completion function changed window"
-msgstr ""
+msgstr "E839: 補全函式更改了窗口"
#: ../edit.c:102
msgid "E840: Completion function deleted text"
-msgstr ""
+msgstr "E840: 補全函式刪除了文本"
#: ../edit.c:1847
msgid "'dictionary' option is empty"
@@ -556,7 +556,7 @@ msgstr "E118: 函式 %s 的引數過多"
#: ../eval.c:148
#, c-format
msgid "E716: Key not present in Dictionary: %s"
-msgstr ""
+msgstr "E716: 鍵在字典中不存在: %s"
#: ../eval.c:150
#, c-format
@@ -581,7 +581,7 @@ msgstr "E360: 不能用 -f 選項執行 shell"
#: ../eval.c:154
#, c-format
msgid "E734: Wrong variable type for %s="
-msgstr ""
+msgstr "E734: 錯誤的變數類型: %s="
#: ../eval.c:155
#, fuzzy, c-format
@@ -595,19 +595,19 @@ msgstr "E461: 不合法的變數名稱: %s"
#: ../eval.c:157
msgid "E806: using Float as a String"
-msgstr ""
+msgstr "E806: 使用浮點數作為字串"
#: ../eval.c:1830
msgid "E687: Less targets than List items"
-msgstr ""
+msgstr "E687: 目標比列表項數少"
#: ../eval.c:1834
msgid "E688: More targets than List items"
-msgstr ""
+msgstr "E688: 目標比列表項數多"
#: ../eval.c:1906
msgid "Double ; in list of variables"
-msgstr ""
+msgstr "變數列表出現兩個 ;"
#: ../eval.c:2078
#, fuzzy, c-format
@@ -616,23 +616,23 @@ msgstr "E138: 無法寫入 viminfo 檔案 %s !"
#: ../eval.c:2391
msgid "E689: Can only index a List or Dictionary"
-msgstr ""
+msgstr "E689: 只能索引一個列表或者字典"
#: ../eval.c:2396
msgid "E708: [:] must come last"
-msgstr ""
+msgstr "E708: [:] 必須在最後"
#: ../eval.c:2439
msgid "E709: [:] requires a List value"
-msgstr ""
+msgstr "E709: [:] 需要一個列表值"
#: ../eval.c:2674
msgid "E710: List value has more items than target"
-msgstr ""
+msgstr "E710: 列表值的項比目標多"
#: ../eval.c:2678
msgid "E711: List value has not enough items"
-msgstr ""
+msgstr "E711: 列表值沒有足夠多的項"
#: ../eval.c:2867
#, fuzzy
@@ -651,7 +651,7 @@ msgstr "E108: 無此變數: \"%s\""
#: ../eval.c:3333
msgid "E743: variable nested too deep for (un)lock"
-msgstr ""
+msgstr "E743: (un)lock 的變數嵌套過深"
#: ../eval.c:3630
msgid "E109: Missing ':' after '?'"
@@ -659,7 +659,7 @@ msgstr "E109: '?' 後缺少 ':'"
#: ../eval.c:3893
msgid "E691: Can only compare List with List"
-msgstr ""
+msgstr "E691: 只能比較列表和列表"
#: ../eval.c:3895
#, fuzzy
@@ -668,7 +668,7 @@ msgstr "E449: 收到不正確的運算式"
#: ../eval.c:3915
msgid "E735: Can only compare Dictionary with Dictionary"
-msgstr ""
+msgstr "E735: 只能比較字典和字典"
#: ../eval.c:3917
#, fuzzy
@@ -677,7 +677,7 @@ msgstr "E116: 函式 %s 的引數不正確"
#: ../eval.c:3932
msgid "E693: Can only compare Funcref with Funcref"
-msgstr ""
+msgstr "E693: 只能比較Funcref 和 Funcref"
#: ../eval.c:3934
#, fuzzy
@@ -736,7 +736,7 @@ msgstr "E242: 找不到顏色: %s"
#: ../eval.c:6499
#, c-format
msgid "E721: Duplicate key in Dictionary: \"%s\""
-msgstr ""
+msgstr "E721: Dictionary 中出現重複的鍵: \"%s\""
#: ../eval.c:6517
#, fuzzy, c-format
@@ -781,7 +781,7 @@ msgstr "E120: <SID> 不能在 script 本文外使用: %s"
#: ../eval.c:7391
#, c-format
msgid "E725: Calling dict function without Dictionary: %s"
-msgstr ""
+msgstr "E725: 調用字典函式但是沒有字典: %s"
#: ../eval.c:7453
#, fuzzy
@@ -814,16 +814,15 @@ msgstr "E227: %s 的 mapping 已經存在"
#: ../eval.c:8692
msgid "extend() argument"
-msgstr ""
+msgstr "extend() 參數"
#: ../eval.c:8915
-#, fuzzy
msgid "map() argument"
-msgstr "vim [參數] "
+msgstr "map() 參數"
#: ../eval.c:8916
msgid "filter() argument"
-msgstr ""
+msgstr "filter() 參數"
#: ../eval.c:9229
#, c-format
@@ -857,19 +856,19 @@ msgstr "E596: 不正確的字型"
#: ../eval.c:11980
msgid "E726: Stride is zero"
-msgstr ""
+msgstr "E726: 步長為零"
#: ../eval.c:11982
msgid "E727: Start past end"
-msgstr ""
+msgstr "E727: 起始值在終止值後"
#: ../eval.c:12024 ../eval.c:15297
msgid "<empty>"
-msgstr ""
+msgstr "<空>"
#: ../eval.c:12282
msgid "remove() argument"
-msgstr ""
+msgstr "remove() 參數"
#: ../eval.c:12466
msgid "E655: Too many symbolic links (cycle?)"
@@ -877,11 +876,11 @@ msgstr "E655: 太多層的符號鏈結(symlink) (循環?)"
#: ../eval.c:12593
msgid "reverse() argument"
-msgstr ""
+msgstr "reverse() 參數"
#: ../eval.c:13721
msgid "sort() argument"
-msgstr ""
+msgstr "sort() 參數"
#: ../eval.c:13721
#, fuzzy
@@ -895,7 +894,7 @@ msgstr "E237: 無法選擇此印表機"
#: ../eval.c:13806
msgid "E882: Uniq compare function failed"
-msgstr ""
+msgstr "E882: Uniq 比較函式失敗"
#: ../eval.c:14085
msgid "(Invalid)"
@@ -908,32 +907,31 @@ msgstr "E208: 寫入檔案 \"%s\" 錯誤"
#: ../eval.c:16159
msgid "E805: Using a Float as a Number"
-msgstr ""
+msgstr "E805: 將浮點數當做數字使用"
#: ../eval.c:16162
msgid "E703: Using a Funcref as a Number"
-msgstr ""
+msgstr "E703: 將函式當做數字使用"
#: ../eval.c:16170
msgid "E745: Using a List as a Number"
-msgstr ""
+msgstr "E745: 將列表當做數字使用"
#: ../eval.c:16173
msgid "E728: Using a Dictionary as a Number"
-msgstr ""
+msgstr "E728: 將字典當做數字使用"
#: ../eval.c:16259
msgid "E729: using Funcref as a String"
-msgstr ""
+msgstr "E729: 將函式當做字串使用"
#: ../eval.c:16262
-#, fuzzy
msgid "E730: using List as a String"
-msgstr "E374: 格式化字串裡少了 ]"
+msgstr "E730: 將列表當做字串使用"
#: ../eval.c:16265
msgid "E731: using Dictionary as a String"
-msgstr ""
+msgstr "E731: 將字典當做字串使用"
#: ../eval.c:16619
#, fuzzy, c-format
@@ -953,12 +951,12 @@ msgstr "E128: 函式名稱第一個字母必須大寫: %s"
#: ../eval.c:16732
#, c-format
msgid "E705: Variable name conflicts with existing function: %s"
-msgstr ""
+msgstr "E705: 變數名與已有函式名衝突: %s"
#: ../eval.c:16763
#, c-format
msgid "E741: Value is locked: %s"
-msgstr ""
+msgstr "E741: 值已鎖定: %s"
#: ../eval.c:16764 ../eval.c:16769 ../message.c:1839
msgid "Unknown"
@@ -971,7 +969,7 @@ msgstr "E284: 不能設定 IC 數值"
#: ../eval.c:16838
msgid "E698: variable nested too deep for making a copy"
-msgstr ""
+msgstr "E698: 變數嵌套過深無法複製"
#: ../eval.c:17249
#, c-format
@@ -1216,7 +1214,7 @@ msgstr "要覆寫已存在的檔案 \"%.*s\"?"
#: ../ex_cmds.c:2317
#, c-format
msgid "Swap file \"%s\" exists, overwrite anyway?"
-msgstr ""
+msgstr "交換文件 \"%s\" 已存在,確實需要覆蓋嗎?"
#: ../ex_cmds.c:2326
#, fuzzy, c-format
@@ -1456,7 +1454,7 @@ msgstr "%3d %s %s 第 %<PRId64> 行 "
#: ../ex_cmds2.c:942
msgid "E750: First use \":profile start {fname}\""
-msgstr ""
+msgstr "E750: 請先使用 :profile start <fname>"
#: ../ex_cmds2.c:1269
#, fuzzy, c-format
@@ -1555,7 +1553,7 @@ msgstr "vim [參數] "
#: ../ex_cmds2.c:2771
msgid "environment variable"
-msgstr ""
+msgstr "環境變數"
#: ../ex_cmds2.c:2773
#, fuzzy
@@ -2047,7 +2045,7 @@ msgstr "E199: 已刪除掉作用中的視窗或暫存區"
#: ../file_search.c:203
msgid "E854: path too long for completion"
-msgstr ""
+msgstr "E854: 補全用的路徑太長了"
#: ../file_search.c:446
#, c-format
@@ -2099,11 +2097,11 @@ msgstr "[未命名]"
#: ../fileio.c:511
msgid "[New DIRECTORY]"
-msgstr ""
+msgstr "[新目錄]"
#: ../fileio.c:529 ../fileio.c:532
msgid "[File too big]"
-msgstr ""
+msgstr "[文件太大]"
#: ../fileio.c:534
msgid "[Permission Denied]"
@@ -2265,7 +2263,7 @@ msgstr "E513: 無法寫入 -- 轉換失敗"
msgid ""
"E513: write error, conversion failed in line %<PRId64> (make 'fenc' empty to "
"override)"
-msgstr ""
+msgstr "E513: 寫入錯誤,轉換失敗 (請將 'fenc' 置空以強制執行)"
#: ../fileio.c:3448
msgid "E514: write error (file system full?)"
@@ -2720,7 +2718,7 @@ msgstr "E49: 錯誤的捲動大小"
#: ../globals.h:1021
msgid "E901: Job table is full"
-msgstr ""
+msgstr "E901: 任務表已經滿"
#: ../globals.h:1024
#, c-format
@@ -2877,7 +2875,7 @@ msgstr "E42: 沒有錯誤"
#: ../globals.h:1067
msgid "E776: No location list"
-msgstr ""
+msgstr "E776: 沒有位置列表"
#: ../globals.h:1068
msgid "E43: Damaged match string"
@@ -2992,7 +2990,7 @@ msgstr "E473: 內部錯誤"
#: ../globals.h:1104
msgid "E363: pattern uses more memory than 'maxmempattern'"
-msgstr ""
+msgstr "E363: 表達式的內存超出 'maxmempattern'"
#: ../globals.h:1105
#, fuzzy
@@ -3097,15 +3095,15 @@ msgstr "E621: \"%s\" 資源檔版本錯誤"
#: ../hardcopy.c:2225
msgid "E673: Incompatible multi-byte encoding and character set."
-msgstr ""
+msgstr "E673: 不兼容的多字節編碼和字元集"
#: ../hardcopy.c:2238
msgid "E674: printmbcharset cannot be empty with multi-byte encoding."
-msgstr ""
+msgstr "E674: printmbcharset 在多字節編碼下不能為空"
#: ../hardcopy.c:2254
msgid "E675: No default font specified for multi-byte printing."
-msgstr ""
+msgstr "E675: 沒有指定多字節打印的默認字型"
#: ../hardcopy.c:2426
msgid "E324: Can't open PostScript output file"
@@ -3267,6 +3265,7 @@ msgstr "%-5s: %-30s (用法: %s)"
#: ../if_cscope.c:1155
msgid ""
"\n"
+" a: Find assignments to this symbol\n"
" c: Find functions calling this function\n"
" d: Find functions called by this function\n"
" e: Find this egrep pattern\n"
@@ -3276,6 +3275,16 @@ msgid ""
" s: Find this C symbol\n"
" t: Find this text string\n"
msgstr ""
+"\n"
+" a: 搜索對此符號的賦值\n"
+" c: 搜索調用此函式的函式\n"
+" d: 搜索此函式調用的函式\n"
+" e: 搜索此 egrep 模式\n"
+" f: 搜索此文件\n"
+" g: 搜索此定義\n"
+" i: 搜索包含此文件的文件\n"
+" s: 搜索此 C 符号\n"
+" t: 搜索此文本字串\n"
#: ../if_cscope.c:1226
msgid "E568: duplicate cscope database not added"
@@ -3509,7 +3518,7 @@ msgstr "-N\t\t\t'nocompatible' 不完全與傳統 Vi 相容,可使用 Vim 加
#: ../main.c:2215
msgid "-V[N][fname]\t\tBe verbose [level N] [log messages to fname]"
-msgstr ""
+msgstr "-V[N][fname]\t\t詳細 [level N] [log messages to fname]"
#: ../main.c:2216
msgid "-D\t\t\tDebugging mode"
@@ -3602,7 +3611,7 @@ msgstr "-W <scriptout>\t對檔案 <scriptout> 寫入所有輸入的命令"
#: ../main.c:2240
msgid "--startuptime <file>\tWrite startup timing messages to <file>"
-msgstr ""
+msgstr "--startuptime <file>\t將啟動時間寫入到文件 <file>"
#: ../main.c:2242
msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
@@ -3794,7 +3803,7 @@ msgstr ""
#: ../memline.c:945
msgid " has been damaged (page size is smaller than minimum value).\n"
-msgstr ""
+msgstr "已损坏(頁面大小小於最小值)。\n"
#: ../memline.c:974
#, c-format
@@ -4082,7 +4091,7 @@ msgstr "E317: 指標區塊 id 錯 2"
#: ../memline.c:3070
#, c-format
msgid "E773: Symlink loop for \"%s\""
-msgstr ""
+msgstr "E773: \"%s\" 符號鏈接出現循環"
#: ../memline.c:3221
msgid "E325: ATTENTION"
@@ -4231,7 +4240,7 @@ msgstr "E329: 沒有那樣的選單"
#. Only a mnemonic or accelerator is not valid.
#: ../menu.c:329
msgid "E792: Empty menu name"
-msgstr ""
+msgstr "E792: 空的菜單名稱"
#: ../menu.c:340
msgid "E330: Menu path must not lead to a sub-menu"
@@ -4312,7 +4321,7 @@ msgstr "-- 尚有 --"
#: ../message.c:2398
msgid " SPACE/d/j: screen/page/line down, b/u/k: up, q: quit "
-msgstr ""
+msgstr " 空格/d/j: 屏幕/頁/行 下翻,b/u/k: 上翻,q: 退出 "
#: ../message.c:3021 ../message.c:3031
msgid "Question"
@@ -4357,7 +4366,7 @@ msgstr "E116: 函式 %s 的引數不正確"
#: ../message.c:3119
msgid "E807: Expected Float argument for printf()"
-msgstr ""
+msgstr "E807: 期盼浮點數作為printf()參數"
#: ../message.c:3873
#, fuzzy
@@ -4370,11 +4379,11 @@ msgstr "W10: 注意: 你正在修改一個唯讀檔"
#: ../misc1.c:2537
msgid "Type number and <Enter> or click with mouse (empty cancels): "
-msgstr ""
+msgstr "請輸入數字並<Enter>或點擊鼠標(空白取消): "
#: ../misc1.c:2539
msgid "Type number and <Enter> (empty cancels): "
-msgstr ""
+msgstr "請選擇數字並(<Enter> 取消): "
#: ../misc1.c:2585
msgid "1 more line"
@@ -4400,7 +4409,7 @@ msgstr " (已中斷)"
#: ../misc1.c:2635
msgid "Beep!"
-msgstr ""
+msgstr "Beep!"
#: ../misc2.c:738
#, c-format
@@ -4617,7 +4626,7 @@ msgstr "E520: 不能在 Modeline 裡出現"
#: ../option.c:2815
msgid "E846: Key code not set"
-msgstr ""
+msgstr "E846: 未設置鍵位代碼"
#: ../option.c:2924
msgid "E521: Number required after ="
@@ -4642,11 +4651,11 @@ msgstr "E589: 'backupext' 跟 'patchmode' 是一樣的"
#: ../option.c:3964
msgid "E834: Conflicts with value of 'listchars'"
-msgstr ""
+msgstr "E834: 與'listchars'中的值發生衝突"
#: ../option.c:3966
msgid "E835: Conflicts with value of 'fillchars'"
-msgstr ""
+msgstr "E835: 與'fillchars'中的值發生衝突"
#: ../option.c:4163
msgid "E524: Missing colon"
@@ -4884,7 +4893,7 @@ msgstr "E382: 無法寫入,'buftype' 選項已設定"
#: ../quickfix.c:2812
msgid "E683: File name missing or invalid pattern"
-msgstr ""
+msgstr "E683: 缺少文件名或模式無效"
#: ../quickfix.c:2911
#, fuzzy, c-format
@@ -5022,25 +5031,26 @@ msgid ""
"E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be "
"used "
msgstr ""
+"E864: \\%#= 後面只能是0,1,或者2。自動引擎將會被使用"
#: ../regexp_nfa.c:239
msgid "E865: (NFA) Regexp end encountered prematurely"
-msgstr ""
+msgstr "E865: (NFA) 過早的遇到了正則表達式的結尾"
#: ../regexp_nfa.c:240
#, c-format
msgid "E866: (NFA regexp) Misplaced %c"
-msgstr ""
+msgstr "E866: (NFA regexp) %c 放錯了位置"
#: ../regexp_nfa.c:242
#, c-format
msgid "E877: (NFA regexp) Invalid character class: %<PRId64>"
-msgstr ""
+msgstr "E877: (NFA regexp) 不可用的字元類: %<PRId64>"
#: ../regexp_nfa.c:1261
#, c-format
msgid "E867: (NFA) Unknown operator '\\z%c'"
-msgstr ""
+msgstr "E867: (NFA) 未知的操作符 '\\z%c'"
#: ../regexp_nfa.c:1387
#, c-format
@@ -5050,21 +5060,21 @@ msgstr ""
#: ../regexp_nfa.c:1802
#, c-format
msgid "E869: (NFA) Unknown operator '\\@%c'"
-msgstr ""
+msgstr "E869: (NFA) 未知的操作符 '\\%%%c'"
#: ../regexp_nfa.c:1831
msgid "E870: (NFA regexp) Error reading repetition limits"
-msgstr ""
+msgstr "E870: (NFA regexp) 读取重复限制时出错"
#. Can't have a multi follow a multi.
#: ../regexp_nfa.c:1895
msgid "E871: (NFA regexp) Can't have a multi follow a multi !"
-msgstr ""
+msgstr "E871: (NFA regexp) 不能多个跟多个!"
#. Too many `('
#: ../regexp_nfa.c:2037
msgid "E872: (NFA regexp) Too many '('"
-msgstr ""
+msgstr "E872: (NFA regexp) 太多 '('"
#: ../regexp_nfa.c:2042
#, fuzzy
@@ -5073,31 +5083,32 @@ msgstr "E50: 太多 \\z("
#: ../regexp_nfa.c:2066
msgid "E873: (NFA regexp) proper termination error"
-msgstr ""
+msgstr "E873: (NFA regexp) 未適當終止"
#: ../regexp_nfa.c:2599
msgid "E874: (NFA) Could not pop the stack !"
-msgstr ""
+msgstr "E874: (NFA) 無法出棧!"
#: ../regexp_nfa.c:3298
msgid ""
"E875: (NFA regexp) (While converting from postfix to NFA), too many states "
"left on stack"
-msgstr ""
+msgstr "E875: (NFA regexp) (從後綴轉到 NFA 时),棧上遺留了太多狀態"
#: ../regexp_nfa.c:3302
msgid "E876: (NFA regexp) Not enough space to store the whole NFA "
-msgstr ""
+msgstr "E876: (NFA regexp) 沒有足夠的空間存儲NFA "
#: ../regexp_nfa.c:4571 ../regexp_nfa.c:4869
msgid ""
"Could not open temporary log file for writing, displaying on stderr ... "
msgstr ""
+"無法打開臨時日志文件進行寫入,顯示在stderr中..."
#: ../regexp_nfa.c:4840
#, c-format
msgid "(NFA) COULD NOT OPEN %s !"
-msgstr ""
+msgstr "(NFA) 不能打开 %s !"
#: ../regexp_nfa.c:6049
#, fuzzy
@@ -5270,17 +5281,17 @@ msgstr "E297: 暫存檔寫入錯誤"
#: ../spell.c:952
msgid "E758: Truncated spell file"
-msgstr ""
+msgstr "E758: 已截斷的拼寫文件"
#: ../spell.c:953
#, c-format
msgid "Trailing text in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,多餘的後續文本: %s"
#: ../spell.c:954
#, c-format
msgid "Affix name too long in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,附加項名字太長: %s"
#: ../spell.c:955
#, fuzzy
@@ -5289,20 +5300,20 @@ msgstr "E431: Tag 檔 \"%s\" 格式錯誤"
#: ../spell.c:957
msgid "E762: Character in FOL, LOW or UPP is out of range"
-msgstr ""
+msgstr "E762: FOL、LOW 或 UPP 中字元超出範圍"
#: ../spell.c:958
msgid "Compressing word tree..."
-msgstr ""
+msgstr "壓縮單詞樹……"
#: ../spell.c:1951
msgid "E756: Spell checking is not enabled"
-msgstr ""
+msgstr "E756: 拼寫檢查未啟用"
#: ../spell.c:2249
#, c-format
msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\""
-msgstr ""
+msgstr "警告: 找不到單詞列表 \"%s.%s.spl\" or \"%s.ascii.spl\""
#: ../spell.c:2473
#, fuzzy, c-format
@@ -5316,11 +5327,11 @@ msgstr "E307: %s 看起來不像是 Vim 暫存檔"
#: ../spell.c:2501
msgid "E771: Old spell file, needs to be updated"
-msgstr ""
+msgstr "E771: 舊的拼寫文件,需要更新"
#: ../spell.c:2504
msgid "E772: Spell file is for newer version of Vim"
-msgstr ""
+msgstr "E772: 為更高版本的 Vim 所使用的拼寫文件"
#: ../spell.c:2602
#, fuzzy
@@ -5340,66 +5351,68 @@ msgstr "搜尋 tag 檔案 \"%s\""
#: ../spell.c:4589 ../spell.c:5635 ../spell.c:6140
#, c-format
msgid "Conversion failure for word in %s line %d: %s"
-msgstr ""
+msgstr "單詞 %s 轉換失敗,第 %d 行: %s"
#: ../spell.c:4630 ../spell.c:6170
#, c-format
msgid "Conversion in %s not supported: from %s to %s"
-msgstr ""
+msgstr "不支持 %s 中的轉換: 从 %s 到 %s"
#: ../spell.c:4642
#, c-format
msgid "Invalid value for FLAG in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,FLAG 的值无效: %s"
#: ../spell.c:4655
#, c-format
msgid "FLAG after using flags in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,在使用標志後出現 FLAG: %s"
#: ../spell.c:4723
#, c-format
msgid ""
"Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line "
"%d"
-msgstr ""
+msgstr "在 PFX 項之後定義 COMPOUNDFORBIDFLAG (%s 第%d行)可能會給出的錯誤結果"
+"%d"
#: ../spell.c:4731
#, c-format
msgid ""
"Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line "
"%d"
-msgstr ""
+msgstr "在 PFX 項之後定義 COMPOUNDFORBIDFLAG (%s 第%d行)可能會給出的錯誤結果"
+"%d"
#: ../spell.c:4747
#, c-format
msgid "Wrong COMPOUNDRULES value in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,错误的 COMPOUNDMIN 值: %s"
#: ../spell.c:4771
#, c-format
msgid "Wrong COMPOUNDWORDMAX value in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,错误的 COMPOUNDWORDMAX 值: %s"
#: ../spell.c:4777
#, c-format
msgid "Wrong COMPOUNDMIN value in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,错误的 COMPOUNDMIN 值: %s"
#: ../spell.c:4783
#, c-format
msgid "Wrong COMPOUNDSYLMAX value in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,错误的 COMPOUNDSYLMAX 值: %s"
#: ../spell.c:4795
#, c-format
msgid "Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,错误的 CHECKCOMPOUNDPATTERN 值: %s"
#: ../spell.c:4847
#, c-format
msgid "Different combining flag in continued affix block in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,在連續的附加塊種出現不同的組合標誌: %s"
#: ../spell.c:4850
#, fuzzy, c-format
@@ -5412,45 +5425,47 @@ msgid ""
"Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in %s "
"line %d: %s"
msgstr ""
+"%s 第 %d 行,附加項被 BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST 使"
+"用: %s"
#: ../spell.c:4893
#, c-format
msgid "Expected Y or N in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,此處需要 Y 或 N: %s"
#: ../spell.c:4968
#, c-format
msgid "Broken condition in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,錯誤的條件: %s"
#: ../spell.c:5091
#, c-format
msgid "Expected REP(SAL) count in %s line %d"
-msgstr ""
+msgstr "%s 第 %d 行,此處需要 REP(SAL) 計數"
#: ../spell.c:5120
#, c-format
msgid "Expected MAP count in %s line %d"
-msgstr ""
+msgstr "%s 第 %d 行,此處需要 MAP 計數"
#: ../spell.c:5132
#, c-format
msgid "Duplicate character in MAP in %s line %d"
-msgstr ""
+msgstr "%s 第 %d 行,MAP 中存在重複的字元"
#: ../spell.c:5176
#, c-format
msgid "Unrecognized or duplicate item in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,無法識別或重複的項: %s"
#: ../spell.c:5197
#, c-format
msgid "Missing FOL/LOW/UPP line in %s"
-msgstr ""
+msgstr "%s 中缺少 FOL/LOW/UPP 行"
#: ../spell.c:5220
msgid "COMPOUNDSYLMAX used without SYLLABLE"
-msgstr ""
+msgstr "在没有 SYLLABLE 的情況下使用了 COMPOUNDSYLMAX"
#: ../spell.c:5236
#, fuzzy
@@ -5464,32 +5479,32 @@ msgstr "太多編輯參數"
#: ../spell.c:5240
msgid "Too many postponed prefixes and/or compound flags"
-msgstr ""
+msgstr "太多延遲前綴和/或組合標誌"
#: ../spell.c:5250
#, c-format
msgid "Missing SOFO%s line in %s"
-msgstr ""
+msgstr "%s 中缺少 SOFO%s 行"
#: ../spell.c:5253
#, c-format
msgid "Both SAL and SOFO lines in %s"
-msgstr ""
+msgstr "%s 同時出現 SAL 和 SOFO 行"
#: ../spell.c:5331
#, c-format
msgid "Flag is not a number in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,標誌不是數字: %s"
#: ../spell.c:5334
#, c-format
msgid "Illegal flag in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,無效的標誌: %s"
#: ../spell.c:5493 ../spell.c:5501
#, c-format
msgid "%s value differs from what is used in another .aff file"
-msgstr ""
+msgstr "%s 的值與另一個 .aff 文件中使用的值不相同"
#: ../spell.c:5602
#, fuzzy, c-format
@@ -5499,12 +5514,12 @@ msgstr "掃瞄字典: %s"
#: ../spell.c:5611
#, c-format
msgid "E760: No word count in %s"
-msgstr ""
+msgstr "E760: %s 中没有單詞計數"
#: ../spell.c:5669
#, c-format
msgid "line %6d, word %6d - %s"
-msgstr ""
+msgstr "第 %6d 行,第 %6d 个單詞 - %s"
#: ../spell.c:5691
#, fuzzy, c-format
@@ -5514,17 +5529,17 @@ msgstr "每一行都找不到: %s"
#: ../spell.c:5694
#, c-format
msgid "First duplicate word in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,首次出現重複的單詞: %s"
#: ../spell.c:5746
#, c-format
msgid "%d duplicate word(s) in %s"
-msgstr ""
+msgstr "存在 %d 个重複的單詞,在 %s 中"
#: ../spell.c:5748
#, c-format
msgid "Ignored %d word(s) with non-ASCII characters in %s"
-msgstr ""
+msgstr "忽略了含有非 ASCII 字元的 %d 个單詞,在 %s 中"
#: ../spell.c:6115
#, fuzzy, c-format
@@ -5534,42 +5549,42 @@ msgstr "從標準輸入讀取..."
#: ../spell.c:6155
#, c-format
msgid "Duplicate /encoding= line ignored in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %ld 行,重复的 /encoding= 行已被忽略: %s"
#: ../spell.c:6159
#, c-format
msgid "/encoding= line after word ignored in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,单词后的 /encoding= 行已被忽略: %s"
#: ../spell.c:6180
#, c-format
msgid "Duplicate /regions= line ignored in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,重复的 /regions= 行已被忽略: %s"
#: ../spell.c:6185
#, c-format
msgid "Too many regions in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,太多區域: %s"
#: ../spell.c:6198
#, c-format
msgid "/ line ignored in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,/ 行已被忽略: %s"
#: ../spell.c:6224
#, fuzzy, c-format
msgid "Invalid region nr in %s line %d: %s"
-msgstr "E573: 不正確的伺服器 id : %s"
+msgstr "%s 第 %d 行,無效的區域號: %s"
#: ../spell.c:6230
#, c-format
msgid "Unrecognized flags in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,不可識別的標誌: %s"
#: ../spell.c:6257
#, c-format
msgid "Ignored %d words with non-ASCII characters"
-msgstr ""
+msgstr "忽略了含有非 ASCII 字元的 %d 个單詞"
#: ../spell.c:6656
#, c-format
@@ -5578,23 +5593,23 @@ msgstr ""
#: ../spell.c:7340
msgid "Reading back spell file..."
-msgstr ""
+msgstr "读取拼寫文件……"
#. Go through the trie of good words, soundfold each word and add it to
#. the soundfold trie.
#: ../spell.c:7357
msgid "Performing soundfolding..."
-msgstr ""
+msgstr "正在 soundfolding……"
#: ../spell.c:7368
#, c-format
msgid "Number of words after soundfolding: %<PRId64>"
-msgstr ""
+msgstr "soundfolding 后的單詞数: %<PRId64>"
#: ../spell.c:7476
#, c-format
msgid "Total number of words: %d"
-msgstr ""
+msgstr "單詞总数: %d"
#: ../spell.c:7655
#, fuzzy, c-format
@@ -5604,11 +5619,11 @@ msgstr "寫入 viminfo 檔案 \"%s\" 中"
#: ../spell.c:7707 ../spell.c:7927
#, c-format
msgid "Estimated runtime memory use: %d bytes"
-msgstr ""
+msgstr "估計運行時的內存用量: %d 位元"
#: ../spell.c:7820
msgid "E751: Output file name must not have region name"
-msgstr ""
+msgstr "E751: 輸出文件不能含有區域名"
#: ../spell.c:7822
#, fuzzy
@@ -5622,7 +5637,7 @@ msgstr "E15: 不正確的運算式: %s"
#: ../spell.c:7907
msgid "Warning: both compounding and NOBREAK specified"
-msgstr ""
+msgstr "警告: 同時指定了 compounding 和 NOBREAK"
#: ../spell.c:7920
#, fuzzy, c-format
@@ -5631,30 +5646,30 @@ msgstr "寫入 viminfo 檔案 \"%s\" 中"
#: ../spell.c:7925
msgid "Done!"
-msgstr ""
+msgstr "完成!"
#: ../spell.c:8034
#, c-format
msgid "E765: 'spellfile' does not have %<PRId64> entries"
-msgstr ""
+msgstr "E765: 'spellfile' 没有 %<PRId64> 項"
#: ../spell.c:8074
#, c-format
msgid "Word '%.*s' removed from %s"
-msgstr ""
+msgstr "从 %s 中删除了單詞"
#: ../spell.c:8117
#, c-format
msgid "Word '%.*s' added to %s"
-msgstr ""
+msgstr "向 %s 中添加了單詞"
#: ../spell.c:8381
msgid "E763: Word characters differ between spell files"
-msgstr ""
+msgstr "E763: 拼寫文件之間的字元不相同"
#: ../spell.c:8684
msgid "Sorry, no suggestions"
-msgstr ""
+msgstr "抱歉,没有建议"
#: ../spell.c:8687
#, fuzzy, c-format
@@ -5671,7 +5686,7 @@ msgstr "將變動存儲至 \"%.*s\"?"
#: ../spell.c:8737
#, c-format
msgid " < \"%.*s\""
-msgstr ""
+msgstr " < \"%.*s\""
#: ../spell.c:8882
#, fuzzy
@@ -5691,28 +5706,28 @@ msgstr "E307: %s 看起來不像是 Vim 暫存檔"
#: ../spell.c:9282
#, c-format
msgid "E779: Old .sug file, needs to be updated: %s"
-msgstr ""
+msgstr "E779: 舊的.sug 文件,需要更新: %s"
#: ../spell.c:9286
#, c-format
msgid "E780: .sug file is for newer version of Vim: %s"
-msgstr ""
+msgstr "E780: .sug 文件適用於較新的 Vim 版本: %s"
#: ../spell.c:9295
#, c-format
msgid "E781: .sug file doesn't match .spl file: %s"
-msgstr ""
+msgstr "E781: .sug 文件不能匹配 .spl 文件: %s"
#: ../spell.c:9305
#, fuzzy, c-format
msgid "E782: error while reading .sug file: %s"
-msgstr "E47: 讀取錯誤檔案失敗"
+msgstr "E782: 當讀取.sug 文件時錯誤"
#. This should have been checked when generating the .spl
#. file.
#: ../spell.c:11575
msgid "E783: duplicate char in MAP entry"
-msgstr ""
+msgstr "E783: MAP 條目中有重複的字元"
#: ../syntax.c:266
msgid "No Syntax items defined for this buffer"
@@ -5894,10 +5909,11 @@ msgstr "E410: 不正確的 :syntax 子命令: %s"
msgid ""
" TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN"
msgstr ""
+" 總 計 計 數 匹 配 最 慢 的 平 均 名 字 模 式"
#: ../syntax.c:6146
msgid "E679: recursive loop loading syncolor.vim"
-msgstr ""
+msgstr "E679: 加載 syncolor.vim 时出現嵌套循環"
#: ../syntax.c:6256
#, c-format
@@ -5969,13 +5985,13 @@ msgstr "E424: 使用了過多相異的高亮度屬性"
msgid "E669: Unprintable character in group name"
msgstr "E669: 群組名稱中有無法列印的字元"
-#: ../syntax.c:7434
-msgid "W18: Invalid character in group name"
-msgstr "W18: 群組名稱中有不正確的字元"
+#: ../highlight_group.c:1756
+msgid "E5248: Invalid character in group name"
+msgstr "E5248: 群組名稱中有不正確的字元"
#: ../syntax.c:7448
msgid "E849: Too many highlight and syntax groups"
-msgstr ""
+msgstr "E849: 高亮和語法組過多"
#: ../tag.c:104
msgid "E555: at bottom of tag stack"
@@ -6083,7 +6099,7 @@ msgstr "E435: 找不到 tag, 用猜的!"
#: ../tag.c:2797
#, c-format
msgid "Duplicate field name: %s"
-msgstr ""
+msgstr "重複的字段名: %s"
#: ../term.c:1442
msgid "' not known. Available builtin terminals are:"
@@ -6131,35 +6147,35 @@ msgstr "Vim: 讀取輸入錯誤,離開中...\n"
#. * file in a way it becomes shorter.
#: ../undo.c:379
msgid "E881: Line count changed unexpectedly"
-msgstr ""
+msgstr "E881: 行數意外地改變了"
#: ../undo.c:627
-#, fuzzy, c-format
+#, c-format
msgid "E828: Cannot open undo file for writing: %s"
-msgstr "E212: 無法以寫入模式開啟"
+msgstr "E828: 無法打開撤銷文件去寫入"
#: ../undo.c:717
#, c-format
msgid "E825: Corrupted undo file (%s): %s"
-msgstr ""
+msgstr "E825: 已損壞的撤銷文件 (%s): %s"
#: ../undo.c:1039
msgid "Cannot write undo file in any directory in 'undodir'"
-msgstr ""
+msgstr "不能寫入撤銷文件到 'undodir' 中的任何文件夾"
#: ../undo.c:1074
#, c-format
msgid "Will not overwrite with undo file, cannot read: %s"
-msgstr ""
+msgstr "不能寫入撤銷文件,不可讀取: %s"
#: ../undo.c:1092
#, c-format
msgid "Will not overwrite, this is not an undo file: %s"
-msgstr ""
+msgstr "不會覆蓋,這不是撤銷文件: %s"
#: ../undo.c:1108
msgid "Skipping undo file write, nothing to undo"
-msgstr ""
+msgstr "跳過撤消文件寫入,沒有可撤消的內容"
#: ../undo.c:1121
#, fuzzy, c-format
@@ -6174,7 +6190,7 @@ msgstr "E297: 暫存檔寫入錯誤"
#: ../undo.c:1280
#, c-format
msgid "Not reading undo file, owner differs: %s"
-msgstr ""
+msgstr "不能讀取撤銷文件,擁有者不同: %s"
#: ../undo.c:1292
#, fuzzy, c-format
@@ -6198,7 +6214,7 @@ msgstr "E484: 無法開啟檔案 %s"
#: ../undo.c:1328
msgid "File contents changed, cannot use undo info"
-msgstr ""
+msgstr "文件內容已經改變,不能使用撤銷信息"
#: ../undo.c:1497
#, fuzzy, c-format
@@ -6207,11 +6223,11 @@ msgstr "結束執行 %s"
#: ../undo.c:1586 ../undo.c:1812
msgid "Already at oldest change"
-msgstr ""
+msgstr "已經在最早的改變"
#: ../undo.c:1597 ../undo.c:1814
msgid "Already at newest change"
-msgstr ""
+msgstr "已經在最新的改變"
#: ../undo.c:1806
#, fuzzy, c-format
@@ -6259,11 +6275,11 @@ msgstr "%<PRId64> 行 %s 過 %d 次"
#: ../undo.c:2228
msgid "before"
-msgstr ""
+msgstr "之前"
#: ../undo.c:2228
msgid "after"
-msgstr ""
+msgstr "之後"
#: ../undo.c:2325
#, fuzzy
@@ -6272,7 +6288,7 @@ msgstr "沒有這個 mapping 對應"
#: ../undo.c:2330
msgid "number changes when saved"
-msgstr ""
+msgstr " 編號 改變 時間 保存"
#: ../undo.c:2360
#, fuzzy, c-format
diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c
index a4afe97ac8..0d9080ceb7 100644
--- a/src/nvim/popupmenu.c
+++ b/src/nvim/popupmenu.c
@@ -156,7 +156,6 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i
if (pum_external) {
if (array_changed) {
Arena arena = ARENA_EMPTY;
- arena_start(&arena, &ui_ext_fixblk);
Array arr = arena_array(&arena, (size_t)size);
for (int i = 0; i < size; i++) {
Array item = arena_array(&arena, 4);
@@ -168,7 +167,7 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i
}
ui_call_popupmenu_show(arr, selected, pum_win_row, cursor_col,
pum_anchor_grid);
- arena_mem_free(arena_finish(&arena), &ui_ext_fixblk);
+ arena_mem_free(arena_finish(&arena));
} else {
ui_call_popupmenu_select(selected);
return;
@@ -525,7 +524,7 @@ void pum_redraw(void)
}
if (pum_rl) {
- char *rt = (char *)reverse_text(st);
+ char *rt = reverse_text((char *)st);
char *rt_start = rt;
int size = vim_strsize(rt);
@@ -543,14 +542,13 @@ void pum_redraw(void)
size++;
}
}
- grid_puts_len(&pum_grid, (char_u *)rt, (int)STRLEN(rt), row,
- grid_col - size + 1, attr);
+ grid_puts_len(&pum_grid, rt, (int)STRLEN(rt), row, grid_col - size + 1, attr);
xfree(rt_start);
xfree(st);
grid_col -= width;
} else {
// use grid_puts_len() to truncate the text
- grid_puts(&pum_grid, st, row, grid_col, attr);
+ grid_puts(&pum_grid, (char *)st, row, grid_col, attr);
xfree(st);
grid_col += width;
}
@@ -561,11 +559,11 @@ void pum_redraw(void)
// Display two spaces for a Tab.
if (pum_rl) {
- grid_puts_len(&pum_grid, (char_u *)" ", 2, row, grid_col - 1,
+ grid_puts_len(&pum_grid, " ", 2, row, grid_col - 1,
attr);
grid_col -= 2;
} else {
- grid_puts_len(&pum_grid, (char_u *)" ", 2, row, grid_col, attr);
+ grid_puts_len(&pum_grid, " ", 2, row, grid_col, attr);
grid_col += 2;
}
totwidth += 2;
@@ -704,7 +702,7 @@ static bool pum_set_selected(int n, int repeat)
if ((pum_array[pum_selected].pum_info != NULL)
&& (Rows > 10)
&& (repeat <= 1)
- && (vim_strchr((char *)p_cot, 'p') != NULL)) {
+ && (vim_strchr(p_cot, 'p') != NULL)) {
win_T *curwin_save = curwin;
tabpage_T *curtab_save = curtab;
int res = OK;
@@ -744,11 +742,11 @@ static bool pum_set_selected(int n, int repeat)
if (res == OK) {
// Edit a new, empty buffer. Set options for a "wipeout"
// buffer.
- set_option_value("swf", 0L, NULL, OPT_LOCAL);
- set_option_value("bl", 0L, NULL, OPT_LOCAL);
- set_option_value("bt", 0L, "nofile", OPT_LOCAL);
- set_option_value("bh", 0L, "wipe", OPT_LOCAL);
- set_option_value("diff", 0L, NULL, OPT_LOCAL);
+ set_option_value_give_err("swf", 0L, NULL, OPT_LOCAL);
+ set_option_value_give_err("bl", 0L, NULL, OPT_LOCAL);
+ set_option_value_give_err("bt", 0L, "nofile", OPT_LOCAL);
+ set_option_value_give_err("bh", 0L, "wipe", OPT_LOCAL);
+ set_option_value_give_err("diff", 0L, NULL, OPT_LOCAL);
}
}
@@ -802,7 +800,7 @@ static bool pum_set_selected(int n, int repeat)
// Return cursor to where we were
validate_cursor();
- redraw_later(curwin, SOME_VALID);
+ redraw_later(curwin, UPD_SOME_VALID);
// When the preview window was resized we need to
// update the view on the buffer. Only go back to
diff --git a/src/nvim/profile.c b/src/nvim/profile.c
index d4f3756f4d..cded231c85 100644
--- a/src/nvim/profile.c
+++ b/src/nvim/profile.c
@@ -279,7 +279,7 @@ void ex_profile(exarg_T *eap)
char *e;
int len;
- e = (char *)skiptowhite((char_u *)eap->arg);
+ e = skiptowhite(eap->arg);
len = (int)(e - eap->arg);
e = skipwhite(e);
@@ -354,7 +354,7 @@ void set_context_in_profile_cmd(expand_T *xp, const char *arg)
pexpand_what = PEXP_SUBCMD;
xp->xp_pattern = (char *)arg;
- char_u *const end_subcmd = skiptowhite((const char_u *)arg);
+ char_u *const end_subcmd = (char_u *)skiptowhite(arg);
if (*end_subcmd == NUL) {
return;
}
@@ -612,7 +612,7 @@ static void func_dump_profile(FILE *fd)
.script_ctx = fp->uf_script_ctx,
.channel_id = 0,
};
- char *p = (char *)get_scriptname(last_set, &should_free);
+ char *p = get_scriptname(last_set, &should_free);
fprintf(fd, " Defined: %s:%" PRIdLINENR "\n",
p, fp->uf_script_ctx.sc_lnum);
if (should_free) {
@@ -721,7 +721,7 @@ static void script_dump_profile(FILE *fd)
fprintf(fd, "\n");
fprintf(fd, "count total (s) self (s)\n");
- sfd = os_fopen((char *)si->sn_name, "r");
+ sfd = os_fopen(si->sn_name, "r");
if (sfd == NULL) {
fprintf(fd, "Cannot open file!\n");
} else {
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 17fbbe17b8..f9c4892b91 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -67,9 +67,9 @@ struct qfline_S {
char *qf_module; ///< module name for this error
char *qf_pattern; ///< search pattern for the error
char *qf_text; ///< description of the error
- char qf_viscol; ///< set to TRUE if qf_col and qf_end_col is
+ char qf_viscol; ///< set to true if qf_col and qf_end_col is
// screen column
- char qf_cleared; ///< set to TRUE if line has been deleted
+ char qf_cleared; ///< set to true if line has been deleted
char qf_type; ///< type of the error (mostly 'E'); 1 for :helpgrep
char qf_valid; ///< valid error message detected
};
@@ -100,7 +100,7 @@ typedef struct qf_list_S {
qfline_T *qf_ptr; ///< pointer to the current error
int qf_count; ///< number of errors (0 means empty list)
int qf_index; ///< current index in the error list
- int qf_nonevalid; ///< TRUE if not a single valid entry found
+ int qf_nonevalid; ///< true if not a single valid entry found
char *qf_title; ///< title derived from the command that created
///< the error list or set by setqflist
typval_T *qf_ctx; ///< context set by setqflist/setloclist
@@ -607,7 +607,7 @@ static efm_T *parse_efm_option(char *efm)
goto parse_efm_error;
}
// Advance to next part
- efm = (char *)skip_to_option_part((char_u *)efm + len); // skip comma and spaces
+ efm = skip_to_option_part(efm + len); // skip comma and spaces
}
if (fmt_first == NULL) { // nothing found
@@ -799,7 +799,7 @@ retry:
// Convert a line if it contains a non-ASCII character
if (state->vc.vc_type != CONV_NONE && has_non_ascii((char_u *)state->linebuf)) {
- char *line = (char *)string_convert(&state->vc, (char_u *)state->linebuf, &state->linelen);
+ char *line = string_convert(&state->vc, state->linebuf, &state->linelen);
if (line != NULL) {
if (state->linelen < IOSIZE) {
STRLCPY(state->linebuf, line, state->linelen + 1);
@@ -1000,7 +1000,7 @@ static int qf_setup_state(qfstate_T *pstate, char *restrict enc, const char *res
{
pstate->vc.vc_type = CONV_NONE;
if (enc != NULL && *enc != NUL) {
- convert_setup(&pstate->vc, (char_u *)enc, p_enc);
+ convert_setup(&pstate->vc, enc, p_enc);
}
if (efile != NULL
@@ -1091,7 +1091,7 @@ static int qf_init_ext(qf_info_T *qi, int qf_idx, const char *restrict efile, bu
// Use the local value of 'errorformat' if it's set.
if (errorformat == p_efm && tv == NULL && buf && *buf->b_p_efm != NUL) {
- efm = (char *)buf->b_p_efm;
+ efm = buf->b_p_efm;
} else {
efm = errorformat;
}
@@ -1244,7 +1244,7 @@ static int qf_parse_fmt_f(regmatch_T *rmp, int midx, qffields_T *fields, int pre
// Expand ~/file and $HOME/file to full path.
char c = (char)(*rmp->endp[midx]);
*rmp->endp[midx] = NUL;
- expand_env(rmp->startp[midx], (char_u *)fields->namebuf, CMDBUFFSIZE);
+ expand_env((char *)rmp->startp[midx], fields->namebuf, CMDBUFFSIZE);
*rmp->endp[midx] = (char_u)c;
// For separate filename patterns (%O, %P and %Q), the specified file
@@ -1891,7 +1891,7 @@ static qf_info_T *ll_get_or_alloc_list(win_T *wp)
/// Get the quickfix/location list stack to use for the specified Ex command.
/// For a location list command, returns the stack for the current window. If
/// the location list is not found, then returns NULL and prints an error
-/// message if 'print_emsg' is TRUE.
+/// message if 'print_emsg' is true.
static qf_info_T *qf_cmd_get_stack(exarg_T *eap, int print_emsg)
{
qf_info_T *qi = &ql_info;
@@ -2129,7 +2129,7 @@ static char *qf_push_dir(char *dirbuf, struct dir_stack_T **stackptr, bool is_fi
while (ds_new) {
xfree((*stackptr)->dirname);
(*stackptr)->dirname = concat_fnames(ds_new->dirname, dirbuf, true);
- if (os_isdir((char_u *)(*stackptr)->dirname)) {
+ if (os_isdir((*stackptr)->dirname)) {
break;
}
@@ -2511,7 +2511,7 @@ static win_T *qf_find_win_with_normal_buf(void)
}
// Go to a window in any tabpage containing the specified file. Returns true
-// if successfully jumped to the window. Otherwise returns FALSE.
+// if successfully jumped to the window. Otherwise returns false.
static bool qf_goto_tabwin_with_file(int fnum)
{
FOR_ALL_TAB_WINDOWS(tp, wp) {
@@ -2923,7 +2923,7 @@ void qf_jump(qf_info_T *qi, int dir, int errornr, int forceit)
// If 'newwin' is true, then open the file in a new window.
static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, bool newwin)
{
- char *old_swb = (char *)p_swb;
+ char *old_swb = p_swb;
unsigned old_swb_flags = swb_flags;
const bool old_KeyTyped = KeyTyped; // getting file may reset it
@@ -2932,7 +2932,7 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, boo
}
if (qf_stack_empty(qi) || qf_list_empty(qf_get_curlist(qi))) {
- emsg(_(e_quickfix));
+ emsg(_(e_no_errors));
return;
}
@@ -2994,10 +2994,10 @@ theend:
qfl->qf_ptr = qf_ptr;
qfl->qf_index = qf_index;
}
- if (p_swb != (char_u *)old_swb && p_swb == empty_option) {
+ if (p_swb != old_swb && p_swb == empty_option) {
// Restore old 'switchbuf' value, but not when an autocommand or
// modeline has changed the value.
- p_swb = (char_u *)old_swb;
+ p_swb = old_swb;
swb_flags = old_swb_flags;
}
decr_quickfix_busy();
@@ -3038,23 +3038,23 @@ static void qf_list_entry(qfline_T *qfp, int qf_idx, bool cursel)
// text of the entry.
bool filter_entry = true;
if (qfp->qf_module != NULL && *qfp->qf_module != NUL) {
- filter_entry &= message_filtered((char_u *)qfp->qf_module);
+ filter_entry &= message_filtered(qfp->qf_module);
}
if (filter_entry && fname != NULL) {
- filter_entry &= message_filtered((char_u *)fname);
+ filter_entry &= message_filtered(fname);
}
if (filter_entry && qfp->qf_pattern != NULL) {
- filter_entry &= message_filtered((char_u *)qfp->qf_pattern);
+ filter_entry &= message_filtered(qfp->qf_pattern);
}
if (filter_entry) {
- filter_entry &= message_filtered((char_u *)qfp->qf_text);
+ filter_entry &= message_filtered(qfp->qf_text);
}
if (filter_entry) {
return;
}
msg_putchar('\n');
- msg_outtrans_attr(IObuff, cursel ? HL_ATTR(HLF_QFL) : qfFileAttr);
+ msg_outtrans_attr((char *)IObuff, cursel ? HL_ATTR(HLF_QFL) : qfFileAttr);
if (qfp->qf_lnum != 0) {
msg_puts_attr(":", qfSepAttr);
@@ -3111,7 +3111,7 @@ void qf_list(exarg_T *eap)
}
if (qf_stack_empty(qi) || qf_list_empty(qf_get_curlist(qi))) {
- emsg(_(e_quickfix));
+ emsg(_(e_no_errors));
return;
}
@@ -3180,7 +3180,7 @@ static void qf_fmt_text(const char *restrict text, char *restrict buf, int bufsi
int i;
const char *p = (char *)text;
- for (i = 0; *p != NUL && i < bufsize - 1; ++i) {
+ for (i = 0; *p != NUL && i < bufsize - 1; i++) {
if (*p == '\n') {
buf[i] = ' ';
while (*++p != NUL) {
@@ -3263,13 +3263,13 @@ void qf_age(exarg_T *eap)
emsg(_("E380: At bottom of quickfix stack"));
break;
}
- --qi->qf_curlist;
+ qi->qf_curlist--;
} else {
if (qi->qf_curlist >= qi->qf_listcount - 1) {
emsg(_("E381: At top of quickfix stack"));
break;
}
- ++qi->qf_curlist;
+ qi->qf_curlist++;
}
}
qf_msg(qi, qi->qf_curlist, "");
@@ -3393,7 +3393,7 @@ bool qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, linenr_T amount,
found_one = true;
if (qfp->qf_lnum >= line1 && qfp->qf_lnum <= line2) {
if (amount == MAXLNUM) {
- qfp->qf_cleared = TRUE;
+ qfp->qf_cleared = true;
} else {
qfp->qf_lnum += amount;
}
@@ -3467,7 +3467,7 @@ void qf_view_result(bool split)
qi = GET_LOC_LIST(curwin);
}
if (qf_list_empty(qf_get_curlist(qi))) {
- emsg(_(e_quickfix));
+ emsg(_(e_no_errors));
return;
}
@@ -3558,12 +3558,12 @@ static int qf_goto_cwindow(const qf_info_T *qi, bool resize, int sz, bool vertsp
static void qf_set_cwindow_options(void)
{
// switch off 'swapfile'
- set_option_value("swf", 0L, NULL, OPT_LOCAL);
- set_option_value("bt", 0L, "quickfix", OPT_LOCAL);
- set_option_value("bh", 0L, "hide", OPT_LOCAL);
+ set_option_value_give_err("swf", 0L, NULL, OPT_LOCAL);
+ set_option_value_give_err("bt", 0L, "quickfix", OPT_LOCAL);
+ set_option_value_give_err("bh", 0L, "hide", OPT_LOCAL);
RESET_BINDING(curwin);
curwin->w_p_diff = false;
- set_option_value("fdm", 0L, "manual", OPT_LOCAL);
+ set_option_value_give_err("fdm", 0L, "manual", OPT_LOCAL);
}
// Open a new quickfix or location list window, load the quickfix buffer and
@@ -3710,7 +3710,7 @@ static void qf_win_goto(win_T *win, linenr_T lnum)
curwin->w_cursor.coladd = 0;
curwin->w_curswant = 0;
update_topline(curwin); // scroll to show the line
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
curwin->w_redr_status = true; // update ruler
curwin = old_curwin;
curbuf = curwin->w_buffer;
@@ -3747,7 +3747,7 @@ linenr_T qf_current_entry(win_T *wp)
}
/// Update the cursor position in the quickfix window to the current error.
-/// Return TRUE if there is a quickfix window.
+/// Return true if there is a quickfix window.
///
/// @param old_qf_index previous qf_index or zero
static bool qf_win_pos_update(qf_info_T *qi, int old_qf_index)
@@ -3834,7 +3834,7 @@ static buf_T *qf_find_buf(qf_info_T *qi)
/// @return OK or FAIL
int qf_process_qftf_option(void)
{
- return option_set_callback_func(p_qftf, &qftf_cb);
+ return option_set_callback_func((char_u *)p_qftf, &qftf_cb);
}
/// Update the w:quickfix_title variable in the quickfix/location list window in
@@ -3898,7 +3898,7 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
// Only redraw when added lines are visible. This avoids flickering when
// the added lines are not visible.
if ((win = qf_find_win(qi)) != NULL && old_line_count < win->w_botline) {
- redraw_buf_later(buf, NOT_VALID);
+ redraw_buf_later(buf, UPD_NOT_VALID);
}
}
}
@@ -4108,7 +4108,7 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int q
// resembles reading a file into a buffer, it's more logical when using
// autocommands.
curbuf->b_ro_locked++;
- set_option_value("ft", 0L, "qf", OPT_LOCAL);
+ set_option_value_give_err("ft", 0L, "qf", OPT_LOCAL);
curbuf->b_p_ma = false;
keep_filetype = true; // don't detect 'filetype'
@@ -4118,7 +4118,7 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int q
curbuf->b_ro_locked--;
// make sure it will be redrawn
- redraw_curbuf_later(NOT_VALID);
+ redraw_curbuf_later(UPD_NOT_VALID);
}
// Restore KeyTyped, setting 'filetype' may reset it.
@@ -4175,7 +4175,7 @@ static void qf_jump_first(qf_info_T *qi, unsigned save_qfid, int forceit)
}
}
-// Return TRUE when using ":vimgrep" for ":grep".
+// Return true when using ":vimgrep" for ":grep".
int grep_internal(cmdidx_T cmdidx)
{
return (cmdidx == CMD_grep
@@ -4183,7 +4183,7 @@ int grep_internal(cmdidx_T cmdidx)
|| cmdidx == CMD_grepadd
|| cmdidx == CMD_lgrepadd)
&& STRCMP("internal",
- *curbuf->b_p_gp == NUL ? p_gp : curbuf->b_p_gp) == 0;
+ *curbuf->b_p_gp == NUL ? p_gp : (char_u *)curbuf->b_p_gp) == 0;
}
// Return the make/grep autocmd name.
@@ -4222,7 +4222,7 @@ static char *make_get_fullcmd(const char *makecmd, const char *fname)
// If 'shellpipe' empty: don't redirect to 'errorfile'.
if (*p_sp != NUL) {
- append_redir(cmd, len, (char *)p_sp, (char *)fname);
+ append_redir(cmd, len, p_sp, (char *)fname);
}
// Display the fully formed command. Output a newline if there's something
@@ -4241,7 +4241,7 @@ static char *make_get_fullcmd(const char *makecmd, const char *fname)
// Used for ":make", ":lmake", ":grep", ":lgrep", ":grepadd", and ":lgrepadd"
void ex_make(exarg_T *eap)
{
- char *enc = (*curbuf->b_p_menc != NUL) ? (char *)curbuf->b_p_menc : (char *)p_menc;
+ char *enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc;
// Redirect ":grep" to ":vimgrep" if 'grepprg' is "internal".
if (grep_internal(eap->cmdidx)) {
@@ -4328,7 +4328,7 @@ static char *get_mef_name(void)
char *p;
- for (p = p_mef; *p; ++p) {
+ for (p = p_mef; *p; p++) {
if (p[0] == '#' && p[1] == '#') {
break;
}
@@ -4832,7 +4832,7 @@ static void qf_get_nth_below_entry(qfline_T *entry_arg, linenr_T n, bool linewis
}
/// Get the nth quickfix entry above the specified entry. Searches backwards in
-/// the list. If linewise is TRUE, then treat multiple entries on a single line
+/// the list. If linewise is true, then treat multiple entries on a single line
/// as one.
static void qf_get_nth_above_entry(qfline_T *entry, linenr_T n, bool linewise, int *errornr)
FUNC_ATTR_NONNULL_ALL
@@ -4898,7 +4898,7 @@ void ex_cbelow(exarg_T *eap)
|| eap->cmdidx == CMD_cafter) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY;
if (!(curbuf->b_has_qf_entry & buf_has_flag)) {
- emsg(_(e_quickfix));
+ emsg(_(e_no_errors));
return;
}
@@ -4910,7 +4910,7 @@ void ex_cbelow(exarg_T *eap)
qf_list_T *qfl = qf_get_curlist(qi);
// check if the list has valid errors
if (!qf_list_has_valid_entries(qfl)) {
- emsg(_(e_quickfix));
+ emsg(_(e_no_errors));
return;
}
@@ -4981,7 +4981,7 @@ void ex_cfile(exarg_T *eap)
set_string_option_direct("ef", -1, eap->arg, OPT_FREE, 0);
}
- char *enc = (*curbuf->b_p_menc != NUL) ? (char *)curbuf->b_p_menc : (char *)p_menc;
+ char *enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc;
if (is_loclist_cmd(eap->cmdidx)) {
wp = curwin;
@@ -5140,6 +5140,7 @@ static bool vgr_match_buflines(qf_list_T *qfl, char *fname, buf_T *buf, char *sp
FUNC_ATTR_NONNULL_ARG(1, 3, 4, 5, 6)
{
bool found_match = false;
+ const size_t pat_len = STRLEN(spat);
for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count && *tomatch > 0; lnum++) {
colnr_T col = 0;
@@ -5181,7 +5182,6 @@ static bool vgr_match_buflines(qf_list_T *qfl, char *fname, buf_T *buf, char *sp
}
}
} else {
- const size_t pat_len = STRLEN(spat);
char *const str = (char *)ml_get_buf(buf, lnum, false);
int score;
uint32_t matches[MAX_FUZZY_MATCHES];
@@ -5305,7 +5305,7 @@ static int vgr_process_args(exarg_T *eap, vgr_args_T *args)
}
// Parse the list of arguments, wildcards have already been expanded.
- if (get_arglist_exp((char_u *)p, &args->fcount, &args->fnames, true) == FAIL) {
+ if (get_arglist_exp(p, &args->fcount, &args->fnames, true) == FAIL) {
return FAIL;
}
if (args->fcount == 0) {
@@ -5429,7 +5429,7 @@ static int vgr_process_files(win_T *wp, qf_info_T *qi, vgr_args_T *cmd_args, boo
// options!
aco_save_T aco;
aucmd_prepbuf(&aco, buf);
- apply_autocmds(EVENT_FILETYPE, (char *)buf->b_p_ft, buf->b_fname, true, buf);
+ apply_autocmds(EVENT_FILETYPE, buf->b_p_ft, buf->b_fname, true, buf);
do_modelines(OPT_NOWIN);
aucmd_restbuf(&aco);
}
@@ -5609,7 +5609,7 @@ static buf_T *load_dummy_buffer(char *fname, char *dirname_start, char *resultin
if (readfile_result == OK
&& !got_int
&& !(curbuf->b_flags & BF_NEW)) {
- failed = FALSE;
+ failed = false;
if (curbuf != newbuf) {
// Bloody autocommands changed the buffer! Can happen when
// using netrw and editing a remote file. Use the current
@@ -5677,7 +5677,7 @@ static void wipe_dummy_buffer(buf_T *buf, char *dirname_start)
cleanup_T cs;
// Reset the error/interrupt/exception state here so that aborting()
- // returns FALSE when wiping out the buffer. Otherwise it doesn't
+ // returns false when wiping out the buffer. Otherwise it doesn't
// work when got_int is set.
enter_cleanup(&cs);
@@ -7033,7 +7033,7 @@ static void hgr_search_in_rtp(qf_list_T *qfl, regmatch_T *p_regmatch, const char
FUNC_ATTR_NONNULL_ARG(1, 2)
{
// Go through all directories in 'runtimepath'
- char *p = (char *)p_rtp;
+ char *p = p_rtp;
while (*p != NUL && !got_int) {
copy_option_part(&p, (char *)NameBuff, MAXPATHL, ",");
@@ -7062,9 +7062,10 @@ void ex_helpgrep(exarg_T *eap)
}
}
+ bool updated = false;
// Make 'cpoptions' empty, the 'l' flag should not be used here.
char *const save_cpo = p_cpo;
- p_cpo = (char *)empty_option;
+ p_cpo = empty_option;
bool new_qi = false;
if (is_loclist_cmd(eap->cmdidx)) {
@@ -7092,14 +7093,24 @@ void ex_helpgrep(exarg_T *eap)
qfl->qf_ptr = qfl->qf_start;
qfl->qf_index = 1;
qf_list_changed(qfl);
- qf_update_buffer(qi, NULL);
+ updated = true;
}
- if ((char_u *)p_cpo == empty_option) {
+ if (p_cpo == empty_option) {
p_cpo = save_cpo;
} else {
- // Darn, some plugin changed the value.
- free_string_option((char_u *)save_cpo);
+ // Darn, some plugin changed the value. If it's still empty it was
+ // changed and restored, need to restore in the complicated way.
+ if (*p_cpo == NUL) {
+ set_option_value_give_err("cpo", 0L, save_cpo, 0);
+ }
+ free_string_option(save_cpo);
+ }
+
+ if (updated) {
+ // This may open a window and source scripts, do this after 'cpo' was
+ // restored.
+ qf_update_buffer(qi, NULL);
}
if (au_name != NULL) {
@@ -7158,14 +7169,14 @@ static void get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, typval_T *
}
/// "getloclist()" function
-void f_getloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_getloclist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
win_T *wp = find_win_by_nr_or_id(&argvars[0]);
get_qf_loc_list(false, wp, &argvars[1], rettv);
}
/// "getqflist()" functions
-void f_getqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_getqflist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
get_qf_loc_list(true, NULL, &argvars[0], rettv);
}
@@ -7252,7 +7263,7 @@ skip_args:
}
/// "setloclist()" function
-void f_setloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_setloclist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = -1;
@@ -7263,7 +7274,7 @@ void f_setloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "setqflist()" function
-void f_setqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_setqflist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
set_qf_ll_list(NULL, argvars, rettv);
}
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index b7ec4bf94e..a52343e28b 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -488,10 +488,10 @@ static char_u *skip_anyof(char *p)
/// When "newp" is not NULL and "dirc" is '?', make an allocated copy of the
/// expression and change "\?" to "?". If "*newp" is not NULL the expression
/// is changed in-place.
-char_u *skip_regexp(char_u *startp, int dirc, int magic, char **newp)
+char *skip_regexp(char *startp, int dirc, int magic, char **newp)
{
int mymagic;
- char_u *p = startp;
+ char *p = startp;
if (magic) {
mymagic = MAGIC_ON;
@@ -506,7 +506,7 @@ char_u *skip_regexp(char_u *startp, int dirc, int magic, char **newp)
}
if ((p[0] == '[' && mymagic >= MAGIC_ON)
|| (p[0] == '\\' && p[1] == '[' && mymagic <= MAGIC_OFF)) {
- p = skip_anyof((char *)p + 1);
+ p = (char *)skip_anyof(p + 1);
if (p[0] == NUL) {
break;
}
@@ -514,8 +514,8 @@ char_u *skip_regexp(char_u *startp, int dirc, int magic, char **newp)
if (dirc == '?' && newp != NULL && p[1] == '?') {
// change "\?" to "?", make a copy first.
if (*newp == NULL) {
- *newp = (char *)vim_strsave(startp);
- p = (char_u *)(*newp) + (p - startp);
+ *newp = xstrdup(startp);
+ p = *newp + (p - startp);
}
STRMOVE(p, p + 1);
} else {
@@ -1165,7 +1165,7 @@ static bool reg_match_visual(void)
rex.line = reg_getline(rex.lnum);
rex.input = rex.line + col;
- unsigned int cols_u = win_linetabsize(wp, rex.line, col);
+ unsigned int cols_u = win_linetabsize(wp, rex.reg_firstlnum + rex.lnum, rex.line, col);
assert(cols_u <= MAXCOL);
colnr_T cols = (colnr_T)cols_u;
if (cols < start || cols > end - (*p_sel == 'e')) {
diff --git a/src/nvim/regexp_bt.c b/src/nvim/regexp_bt.c
index 769d2ceeef..88f0d781af 100644
--- a/src/nvim/regexp_bt.c
+++ b/src/nvim/regexp_bt.c
@@ -3764,6 +3764,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
case RE_VCOL:
if (!re_num_cmp(win_linetabsize(rex.reg_win == NULL
? curwin : rex.reg_win,
+ rex.reg_firstlnum + rex.lnum,
rex.line,
(colnr_T)(rex.input - rex.line)) + 1,
scan)) {
@@ -4369,7 +4370,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
case BRACE_COMPLEX + 8:
case BRACE_COMPLEX + 9:
no = op - BRACE_COMPLEX;
- ++brace_count[no];
+ brace_count[no]++;
// If not matched enough times yet, try one more
if (brace_count[no] <= (brace_min[no] <= brace_max[no]
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index 554def5b8a..d4db710d93 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -6910,7 +6910,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
result = col > t->state->val * ts;
}
if (!result) {
- uintmax_t lts = win_linetabsize(wp, rex.line, col);
+ uintmax_t lts = win_linetabsize(wp, rex.reg_firstlnum + rex.lnum, rex.line, col);
assert(t->state->val >= 0);
result = nfa_re_num_cmp((uintmax_t)t->state->val, op, lts + 1);
}
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index 914b21bb02..e85167f8fd 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -100,10 +100,11 @@ void estack_pop(void)
}
/// Get the current value for <sfile> in allocated memory.
-/// @param which ESTACK_SFILE for <sfile> and ESTACK_STACK for <stack>.
+/// @param which ESTACK_SFILE for <sfile>, ESTACK_STACK for <stack> or
+/// ESTACK_SCRIPT for <script>.
char *estack_sfile(estack_arg_T which)
{
- estack_T *entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1;
+ const estack_T *entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1;
if (which == ESTACK_SFILE && entry->es_type != ETYPE_UFUNC) {
if (entry->es_name == NULL) {
return NULL;
@@ -111,6 +112,26 @@ char *estack_sfile(estack_arg_T which)
return xstrdup(entry->es_name);
}
+ // If evaluated in a function or autocommand, return the path of the script
+ // where it is defined, at script level the current script path is returned
+ // instead.
+ if (which == ESTACK_SCRIPT) {
+ // Walk the stack backwards, starting from the current frame.
+ for (int idx = exestack.ga_len - 1; idx >= 0; idx--, entry--) {
+ if (entry->es_type == ETYPE_UFUNC || entry->es_type == ETYPE_AUCMD) {
+ const sctx_T *const def_ctx = (entry->es_type == ETYPE_UFUNC
+ ? &entry->es_info.ufunc->uf_script_ctx
+ : &entry->es_info.aucmd->script_ctx);
+ return def_ctx->sc_sid > 0
+ ? xstrdup((SCRIPT_ITEM(def_ctx->sc_sid).sn_name))
+ : NULL;
+ } else if (entry->es_type == ETYPE_SCRIPT) {
+ return xstrdup(entry->es_name);
+ }
+ }
+ return NULL;
+ }
+
// Give information about each stack entry up to the root.
// For a function we compose the call stack, as it was done in the past:
// "function One[123]..Two[456]..Three"
@@ -171,7 +192,7 @@ void runtime_init(void)
void ex_runtime(exarg_T *eap)
{
char *arg = eap->arg;
- char *p = (char *)skiptowhite((char_u *)arg);
+ char *p = skiptowhite(arg);
ptrdiff_t len = p - arg;
int flags = eap->forceit ? DIP_ALL : 0;
@@ -205,9 +226,9 @@ static void source_callback(char *fname, void *cookie)
/// When "flags" has DIP_ERR: give an error message if there is no match.
///
/// return FAIL when no file could be sourced, OK otherwise.
-int do_in_path(char_u *path, char *name, int flags, DoInRuntimepathCB callback, void *cookie)
+int do_in_path(char *path, char *name, int flags, DoInRuntimepathCB callback, void *cookie)
{
- char_u *tail;
+ char *tail;
int num_files;
char **files;
int i;
@@ -215,17 +236,17 @@ int do_in_path(char_u *path, char *name, int flags, DoInRuntimepathCB callback,
// Make a copy of 'runtimepath'. Invoking the callback may change the
// value.
- char_u *rtp_copy = vim_strsave(path);
+ char *rtp_copy = xstrdup(path);
char *buf = xmallocz(MAXPATHL);
{
if (p_verbose > 10 && name != NULL) {
verbose_enter();
- smsg(_("Searching for \"%s\" in \"%s\""), name, (char *)path);
+ smsg(_("Searching for \"%s\" in \"%s\""), name, path);
verbose_leave();
}
// Loop over all entries in 'runtimepath'.
- char *rtp = (char *)rtp_copy;
+ char *rtp = rtp_copy;
while (*rtp != NUL && ((flags & DIP_ALL) || !did_one)) {
// Copy the path from 'runtimepath' to buf[].
copy_option_part(&rtp, buf, MAXPATHL, ",");
@@ -246,14 +267,14 @@ int do_in_path(char_u *path, char *name, int flags, DoInRuntimepathCB callback,
did_one = true;
} else if (buflen + STRLEN(name) + 2 < MAXPATHL) {
add_pathsep(buf);
- tail = (char_u *)buf + STRLEN(buf);
+ tail = buf + STRLEN(buf);
// Loop over all patterns in "name"
char *np = name;
while (*np != NUL && ((flags & DIP_ALL) || !did_one)) {
// Append the pattern from "name" to buf[].
- assert(MAXPATHL >= (tail - (char_u *)buf));
- copy_option_part(&np, (char *)tail, (size_t)(MAXPATHL - (tail - (char_u *)buf)), "\t ");
+ assert(MAXPATHL >= (tail - buf));
+ copy_option_part(&np, tail, (size_t)(MAXPATHL - (tail - buf)), "\t ");
if (p_verbose > 10) {
verbose_enter();
@@ -342,19 +363,19 @@ void runtime_search_path_unref(RuntimeSearchPath path, int *ref)
/// When "flags" has DIP_ERR: give an error message if there is no match.
///
/// return FAIL when no file could be sourced, OK otherwise.
-int do_in_cached_path(char_u *name, int flags, DoInRuntimepathCB callback, void *cookie)
+int do_in_cached_path(char *name, int flags, DoInRuntimepathCB callback, void *cookie)
{
- char_u *tail;
+ char *tail;
int num_files;
char **files;
int i;
bool did_one = false;
- char_u buf[MAXPATHL];
+ char buf[MAXPATHL];
if (p_verbose > 10 && name != NULL) {
verbose_enter();
- smsg(_("Searching for \"%s\" in runtime path"), (char *)name);
+ smsg(_("Searching for \"%s\" in runtime path"), name);
verbose_leave();
}
@@ -378,15 +399,15 @@ int do_in_cached_path(char_u *name, int flags, DoInRuntimepathCB callback, void
(*callback)(item.path, cookie);
} else if (buflen + STRLEN(name) + 2 < MAXPATHL) {
STRCPY(buf, item.path);
- add_pathsep((char *)buf);
+ add_pathsep(buf);
tail = buf + STRLEN(buf);
// Loop over all patterns in "name"
- char *np = (char *)name;
+ char *np = name;
while (*np != NUL && ((flags & DIP_ALL) || !did_one)) {
// Append the pattern from "name" to buf[].
assert(MAXPATHL >= (tail - buf));
- copy_option_part(&np, (char *)tail, (size_t)(MAXPATHL - (tail - buf)), "\t ");
+ copy_option_part(&np, tail, (size_t)(MAXPATHL - (tail - buf)), "\t ");
if (p_verbose > 10) {
verbose_enter();
@@ -398,7 +419,7 @@ int do_in_cached_path(char_u *name, int flags, DoInRuntimepathCB callback, void
| (flags & DIP_DIRFILE) ? (EW_DIR|EW_FILE) : 0;
// Expand wildcards, invoke the callback for each match.
- char *(pat[]) = { (char *)buf };
+ char *(pat[]) = { buf };
if (gen_expand_wildcards(1, pat, &num_files, &files, ew_flags) == OK) {
for (i = 0; i < num_files; i++) {
(*callback)(files[i], cookie);
@@ -478,7 +499,7 @@ ArrayOf(String) runtime_get_named_common(bool lua, Array pat, bool all,
if (lua) {
if (item->has_lua == kNone) {
size_t size = (size_t)snprintf(buf, buf_len, "%s/lua/", item->path);
- item->has_lua = (size < buf_len && os_isdir((char_u *)buf));
+ item->has_lua = (size < buf_len && os_isdir(buf));
}
if (item->has_lua == kFalse) {
continue;
@@ -513,13 +534,13 @@ done:
/// If "name" is NULL calls callback for each entry in "path". Cookie is
/// passed by reference in this case, setting it to NULL indicates that callback
/// has done its job.
-int do_in_path_and_pp(char_u *path, char_u *name, int flags, DoInRuntimepathCB callback,
- void *cookie)
+int do_in_path_and_pp(char *path, char *name, int flags, DoInRuntimepathCB callback, void *cookie)
{
int done = FAIL;
if ((flags & DIP_NORTP) == 0) {
- done |= do_in_path(path, (char *)((name && !*name) ? NULL : name), flags, callback, cookie);
+ done |= do_in_path(path, (name && !*name) ? NULL : name, flags, callback,
+ cookie);
}
if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_START)) {
@@ -604,7 +625,7 @@ static void expand_rtp_entry(RuntimeSearchPath *search_path, Map(String, handle_
}
static void expand_pack_entry(RuntimeSearchPath *search_path, Map(String, handle_T) *rtp_used,
- CharVec *after_path, char_u *pack_entry, size_t pack_entry_len)
+ CharVec *after_path, char *pack_entry, size_t pack_entry_len)
{
static char buf[MAXPATHL];
char *(start_pat[]) = { "/pack/*/start/*", "/start/*" }; // NOLINT
@@ -643,10 +664,10 @@ RuntimeSearchPath runtime_search_path_build(void)
RuntimeSearchPath search_path = KV_INITIAL_VALUE;
CharVec after_path = KV_INITIAL_VALUE;
- static char_u buf[MAXPATHL];
- for (char *entry = (char *)p_pp; *entry != NUL;) {
+ static char buf[MAXPATHL];
+ for (char *entry = p_pp; *entry != NUL;) {
char *cur_entry = entry;
- copy_option_part(&entry, (char *)buf, MAXPATHL, ",");
+ copy_option_part(&entry, buf, MAXPATHL, ",");
String the_entry = { .data = cur_entry, .size = STRLEN(buf) };
@@ -655,20 +676,20 @@ RuntimeSearchPath runtime_search_path_build(void)
}
char *rtp_entry;
- for (rtp_entry = (char *)p_rtp; *rtp_entry != NUL;) {
+ for (rtp_entry = p_rtp; *rtp_entry != NUL;) {
char *cur_entry = rtp_entry;
- copy_option_part(&rtp_entry, (char *)buf, MAXPATHL, ",");
+ copy_option_part(&rtp_entry, buf, MAXPATHL, ",");
size_t buflen = STRLEN(buf);
- if (path_is_after((char *)buf, buflen)) {
+ if (path_is_after(buf, buflen)) {
rtp_entry = cur_entry;
break;
}
// fact: &rtp entries can contain wild chars
- expand_rtp_entry(&search_path, &rtp_used, (char *)buf, false);
+ expand_rtp_entry(&search_path, &rtp_used, buf, false);
- handle_T *h = map_ref(String, handle_T)(&pack_used, cstr_as_string((char *)buf), false);
+ handle_T *h = map_ref(String, handle_T)(&pack_used, cstr_as_string(buf), false);
if (h) {
(*h)++;
expand_pack_entry(&search_path, &rtp_used, &after_path, buf, buflen);
@@ -679,7 +700,7 @@ RuntimeSearchPath runtime_search_path_build(void)
String item = kv_A(pack_entries, i);
handle_T h = map_get(String, handle_T)(&pack_used, item);
if (h == 0) {
- expand_pack_entry(&search_path, &rtp_used, &after_path, (char_u *)item.data, item.size);
+ expand_pack_entry(&search_path, &rtp_used, &after_path, item.data, item.size);
}
}
@@ -691,8 +712,8 @@ RuntimeSearchPath runtime_search_path_build(void)
// "after" dirs in rtp
for (; *rtp_entry != NUL;) {
- copy_option_part(&rtp_entry, (char *)buf, MAXPATHL, ",");
- expand_rtp_entry(&search_path, &rtp_used, (char *)buf, path_is_after((char *)buf, STRLEN(buf)));
+ copy_option_part(&rtp_entry, buf, MAXPATHL, ",");
+ expand_rtp_entry(&search_path, &rtp_used, buf, path_is_after(buf, STRLEN(buf)));
}
// strings are not owned
@@ -746,13 +767,13 @@ int do_in_runtimepath(char *name, int flags, DoInRuntimepathCB callback, void *c
{
int success = FAIL;
if (!(flags & DIP_NORTP)) {
- success |= do_in_cached_path((name && !*name) ? NULL : (char_u *)name, flags, callback, cookie);
+ success |= do_in_cached_path((name && !*name) ? NULL : name, flags, callback, cookie);
flags = (flags & ~DIP_START) | DIP_NORTP;
}
// TODO(bfredl): we could integrate disabled OPT dirs into the cached path
// which would effectivize ":packadd myoptpack" as well
if ((flags & (DIP_START|DIP_OPT)) && (success == FAIL || (flags & DIP_ALL))) {
- success |= do_in_path_and_pp(p_rtp, (char_u *)name, flags, callback, cookie);
+ success |= do_in_path_and_pp(p_rtp, name, flags, callback, cookie);
}
return success;
}
@@ -768,7 +789,7 @@ int source_runtime(char *name, int flags)
}
/// Just like source_runtime(), but use "path" instead of 'runtimepath'.
-int source_in_path(char_u *path, char_u *name, int flags)
+int source_in_path(char *path, char *name, int flags)
{
return do_in_path_and_pp(path, name, flags, source_callback, NULL);
}
@@ -792,17 +813,23 @@ static void source_all_matches(char *pat)
///
/// @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)
+static int add_pack_dir_to_rtp(char *fname, bool is_pack)
{
- char_u *p4, *p3, *p2, *p1, *p;
- char_u *buf = NULL;
+ char *p;
+ char *buf = NULL;
char *afterdir = NULL;
int retval = FAIL;
- p4 = p3 = p2 = p1 = get_past_head(fname);
+ char *p1 = get_past_head(fname);
+ char *p2 = p1;
+ char *p3 = p1;
+ char *p4 = p1;
for (p = p1; *p; MB_PTR_ADV(p)) {
if (vim_ispathsep_nocolon(*p)) {
- p4 = p3; p3 = p2; p2 = p1; p1 = p;
+ p4 = p3;
+ p3 = p2;
+ p2 = p1;
+ p1 = p;
}
}
@@ -812,9 +839,9 @@ static int add_pack_dir_to_rtp(char_u *fname, bool is_pack)
//
// find the part up to "pack" in 'runtimepath'
p4++; // append pathsep in order to expand symlink
- char_u c = *p4;
+ char c = *p4;
*p4 = NUL;
- char *const ffname = fix_fname((char *)fname);
+ char *const ffname = fix_fname(fname);
*p4 = c;
if (ffname == NULL) {
@@ -833,10 +860,10 @@ static int add_pack_dir_to_rtp(char_u *fname, bool is_pack)
for (const char *entry = (const char *)p_rtp; *entry != NUL;) {
const char *cur_entry = entry;
- copy_option_part((char **)&entry, (char *)buf, MAXPATHL, ",");
+ copy_option_part((char **)&entry, buf, MAXPATHL, ",");
if (insp == NULL) {
- add_pathsep((char *)buf);
- char *const rtp_ffname = fix_fname((char *)buf);
+ add_pathsep(buf);
+ char *const rtp_ffname = fix_fname(buf);
if (rtp_ffname == NULL) {
goto theend;
}
@@ -848,7 +875,7 @@ static int add_pack_dir_to_rtp(char_u *fname, bool is_pack)
}
}
- if ((p = (char_u *)strstr((char *)buf, "after")) != NULL
+ if ((p = strstr(buf, "after")) != NULL
&& p > buf
&& vim_ispathsep(p[-1])
&& (vim_ispathsep(p[5]) || p[5] == NUL || p[5] == ',')) {
@@ -868,9 +895,9 @@ static int add_pack_dir_to_rtp(char_u *fname, bool is_pack)
}
// check if rtp/pack/name/start/name/after exists
- afterdir = concat_fnames((char *)fname, "after", true);
+ afterdir = concat_fnames(fname, "after", true);
size_t afterlen = 0;
- if (is_pack ? pack_has_entries((char_u *)afterdir) : os_isdir((char_u *)afterdir)) {
+ if (is_pack ? pack_has_entries(afterdir) : os_isdir(afterdir)) {
afterlen = strlen(afterdir) + 1; // add one for comma
}
@@ -923,7 +950,7 @@ static int add_pack_dir_to_rtp(char_u *fname, bool is_pack)
xstrlcat(new_rtp, afterdir, new_rtp_capacity);
}
- set_option_value("rtp", 0L, new_rtp, 0);
+ set_option_value_give_err("rtp", 0L, new_rtp, 0);
xfree(new_rtp);
retval = OK;
@@ -937,29 +964,29 @@ theend:
/// Load scripts in "plugin" directory of the package.
/// For opt packages, also load scripts in "ftdetect" (start packages already
/// load these from filetype.vim)
-static int load_pack_plugin(bool opt, char_u *fname)
+static int load_pack_plugin(bool opt, char *fname)
{
static const char *ftpat = "%s/ftdetect/*.vim"; // NOLINT
- char *const ffname = fix_fname((char *)fname);
+ char *const ffname = fix_fname(fname);
size_t len = strlen(ffname) + STRLEN(ftpat);
- char_u *pat = xmallocz(len);
+ char *pat = xmallocz(len);
- vim_snprintf((char *)pat, len, "%s/plugin/**/*.vim", ffname); // NOLINT
- source_all_matches((char *)pat);
- vim_snprintf((char *)pat, len, "%s/plugin/**/*.lua", ffname); // NOLINT
- source_all_matches((char *)pat);
+ vim_snprintf(pat, len, "%s/plugin/**/*.vim", ffname); // NOLINT
+ source_all_matches(pat);
+ vim_snprintf(pat, len, "%s/plugin/**/*.lua", ffname); // NOLINT
+ source_all_matches(pat);
- char_u *cmd = vim_strsave((char_u *)"g:did_load_filetypes");
+ char *cmd = xstrdup("g:did_load_filetypes");
// If runtime/filetype.vim wasn't loaded yet, the scripts will be
// found when it loads.
- if (opt && eval_to_number((char *)cmd) > 0) {
+ if (opt && eval_to_number(cmd) > 0) {
do_cmdline_cmd("augroup filetypedetect");
- vim_snprintf((char *)pat, len, ftpat, ffname);
- source_all_matches((char *)pat);
+ vim_snprintf(pat, len, ftpat, ffname);
+ source_all_matches(pat);
vim_snprintf((char *)pat, len, "%s/ftdetect/*.lua", ffname); // NOLINT
- source_all_matches((char *)pat);
+ source_all_matches(pat);
do_cmdline_cmd("augroup END");
}
xfree(cmd);
@@ -974,7 +1001,7 @@ static int APP_ADD_DIR;
static int APP_LOAD;
static int APP_BOTH;
-static void add_pack_plugin(bool opt, char_u *fname, void *cookie)
+static void add_pack_plugin(bool opt, char *fname, void *cookie)
{
if (cookie != &APP_LOAD) {
char *buf = xmalloc(MAXPATHL);
@@ -983,7 +1010,7 @@ static void add_pack_plugin(bool opt, char_u *fname, void *cookie)
const char *p = (const char *)p_rtp;
while (*p != NUL) {
copy_option_part((char **)&p, buf, MAXPATHL, ",");
- if (path_fnamecmp(buf, (char *)fname) == 0) {
+ if (path_fnamecmp(buf, fname) == 0) {
found = true;
break;
}
@@ -1004,12 +1031,12 @@ static void add_pack_plugin(bool opt, char_u *fname, void *cookie)
static void add_start_pack_plugin(char *fname, void *cookie)
{
- add_pack_plugin(false, (char_u *)fname, cookie);
+ add_pack_plugin(false, fname, cookie);
}
static void add_opt_pack_plugin(char *fname, void *cookie)
{
- add_pack_plugin(true, (char_u *)fname, cookie);
+ add_pack_plugin(true, fname, cookie);
}
/// Add all packages in the "start" directory to 'runtimepath'.
@@ -1018,11 +1045,11 @@ 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)
+static bool pack_has_entries(char *buf)
{
int num_files;
char **files;
- char *(pat[]) = { (char *)buf };
+ char *(pat[]) = { buf };
if (gen_expand_wildcards(1, pat, &num_files, &files, EW_DIR) == OK) {
FreeWild(num_files, files);
}
@@ -1031,7 +1058,7 @@ static bool pack_has_entries(char_u *buf)
static void add_pack_start_dir(char *fname, void *cookie)
{
- static char_u buf[MAXPATHL];
+ static char 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) {
@@ -1072,12 +1099,12 @@ void ex_packloadall(exarg_T *eap)
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
+ char *rtp_copy = p_rtp;
+ char *const plugin_pattern_vim = "plugin/**/*.vim"; // NOLINT
+ char *const plugin_pattern_lua = "plugin/**/*.lua"; // NOLINT
if (!did_source_packages) {
- rtp_copy = vim_strsave(p_rtp);
+ rtp_copy = xstrdup(p_rtp);
add_pack_start_dirs();
}
@@ -1094,8 +1121,8 @@ void load_plugins(void)
}
TIME_MSG("loading packages");
- source_runtime((char *)plugin_pattern_vim, DIP_ALL | DIP_AFTER);
- source_runtime((char *)plugin_pattern_lua, DIP_ALL | DIP_AFTER);
+ source_runtime(plugin_pattern_vim, DIP_ALL | DIP_AFTER);
+ source_runtime(plugin_pattern_lua, DIP_ALL | DIP_AFTER);
TIME_MSG("loading after plugins");
}
}
@@ -1118,9 +1145,10 @@ void ex_packadd(exarg_T *eap)
vim_snprintf(pat, len, plugpat, round == 1 ? "start" : "opt", eap->arg);
// The first round don't give a "not found" error, in the second round
// only when nothing was found in the first round.
- res = do_in_path(p_pp, pat, DIP_ALL + DIP_DIR + (round == 2 && res == FAIL ? DIP_ERR : 0),
- round == 1 ? add_start_pack_plugin : add_opt_pack_plugin,
- eap->forceit ? &APP_ADD_DIR : &APP_BOTH);
+ res =
+ do_in_path(p_pp, pat, DIP_ALL + DIP_DIR + (round == 2 && res == FAIL ? DIP_ERR : 0),
+ round == 1 ? add_start_pack_plugin : add_opt_pack_plugin,
+ eap->forceit ? &APP_ADD_DIR : &APP_BOTH);
xfree(pat);
}
}
@@ -1134,7 +1162,7 @@ void ex_packadd(exarg_T *eap)
/// 'packpath'/pack/ * /opt/ * /{dirnames}/{pat}.vim
/// When "flags" has DIP_LUA: search also performed for .lua files
/// "dirnames" is an array with one or more directory names.
-int ExpandRTDir(char_u *pat, int flags, int *num_file, char ***file, char *dirnames[])
+int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirnames[])
{
*num_file = 0;
*file = NULL;
@@ -1146,12 +1174,12 @@ int ExpandRTDir(char_u *pat, int flags, int *num_file, char ***file, char *dirna
// TODO(bfredl): this is bullshit, exandpath should not reinvent path logic.
for (int i = 0; dirnames[i] != NULL; i++) {
size_t size = STRLEN(dirnames[i]) + pat_len + 7;
- char_u *s = xmalloc(size);
- snprintf((char *)s, size, "%s/%s*.vim", dirnames[i], pat);
- globpath((char *)p_rtp, s, &ga, 0);
+ char *s = xmalloc(size);
+ snprintf(s, size, "%s/%s*.vim", dirnames[i], pat);
+ globpath(p_rtp, s, &ga, 0);
if (flags & DIP_LUA) {
- snprintf((char *)s, size, "%s/%s*.lua", dirnames[i], pat);
- globpath((char *)p_rtp, s, &ga, 0);
+ snprintf(s, size, "%s/%s*.lua", dirnames[i], pat);
+ globpath(p_rtp, s, &ga, 0);
}
xfree(s);
}
@@ -1159,24 +1187,24 @@ int ExpandRTDir(char_u *pat, int flags, int *num_file, char ***file, char *dirna
if (flags & DIP_START) {
for (int i = 0; dirnames[i] != NULL; i++) {
size_t size = STRLEN(dirnames[i]) + pat_len + 22;
- char_u *s = xmalloc(size);
- snprintf((char *)s, size, "pack/*/start/*/%s/%s*.vim", dirnames[i], pat); // NOLINT
- globpath((char *)p_pp, s, &ga, 0);
+ char *s = xmalloc(size);
+ snprintf(s, size, "pack/*/start/*/%s/%s*.vim", dirnames[i], pat); // NOLINT
+ globpath(p_pp, s, &ga, 0);
if (flags & DIP_LUA) {
- snprintf((char *)s, size, "pack/*/start/*/%s/%s*.lua", dirnames[i], pat); // NOLINT
- globpath((char *)p_pp, s, &ga, 0);
+ snprintf(s, size, "pack/*/start/*/%s/%s*.lua", dirnames[i], pat); // NOLINT
+ globpath(p_pp, s, &ga, 0);
}
xfree(s);
}
for (int i = 0; dirnames[i] != NULL; i++) {
size_t size = STRLEN(dirnames[i]) + pat_len + 22;
- char_u *s = xmalloc(size);
- snprintf((char *)s, size, "start/*/%s/%s*.vim", dirnames[i], pat); // NOLINT
- globpath((char *)p_pp, s, &ga, 0);
+ char *s = xmalloc(size);
+ snprintf(s, size, "start/*/%s/%s*.vim", dirnames[i], pat); // NOLINT
+ globpath(p_pp, s, &ga, 0);
if (flags & DIP_LUA) {
- snprintf((char *)s, size, "start/*/%s/%s*.lua", dirnames[i], pat); // NOLINT
- globpath((char *)p_pp, s, &ga, 0);
+ snprintf(s, size, "start/*/%s/%s*.lua", dirnames[i], pat); // NOLINT
+ globpath(p_pp, s, &ga, 0);
}
xfree(s);
}
@@ -1185,33 +1213,33 @@ int ExpandRTDir(char_u *pat, int flags, int *num_file, char ***file, char *dirna
if (flags & DIP_OPT) {
for (int i = 0; dirnames[i] != NULL; i++) {
size_t size = STRLEN(dirnames[i]) + pat_len + 20;
- char_u *s = xmalloc(size);
- snprintf((char *)s, size, "pack/*/opt/*/%s/%s*.vim", dirnames[i], pat); // NOLINT
- globpath((char *)p_pp, s, &ga, 0);
+ char *s = xmalloc(size);
+ snprintf(s, size, "pack/*/opt/*/%s/%s*.vim", dirnames[i], pat); // NOLINT
+ globpath(p_pp, s, &ga, 0);
if (flags & DIP_LUA) {
- snprintf((char *)s, size, "pack/*/opt/*/%s/%s*.lua", dirnames[i], pat); // NOLINT
- globpath((char *)p_pp, s, &ga, 0);
+ snprintf(s, size, "pack/*/opt/*/%s/%s*.lua", dirnames[i], pat); // NOLINT
+ globpath(p_pp, s, &ga, 0);
}
xfree(s);
}
for (int i = 0; dirnames[i] != NULL; i++) {
size_t size = STRLEN(dirnames[i]) + pat_len + 20;
- char_u *s = xmalloc(size);
- snprintf((char *)s, size, "opt/*/%s/%s*.vim", dirnames[i], pat); // NOLINT
- globpath((char *)p_pp, s, &ga, 0);
+ char *s = xmalloc(size);
+ snprintf(s, size, "opt/*/%s/%s*.vim", dirnames[i], pat); // NOLINT
+ globpath(p_pp, s, &ga, 0);
if (flags & DIP_LUA) {
- snprintf((char *)s, size, "opt/*/%s/%s*.lua", dirnames[i], pat); // NOLINT
- globpath((char *)p_pp, s, &ga, 0);
+ snprintf(s, size, "opt/*/%s/%s*.lua", dirnames[i], pat); // NOLINT
+ globpath(p_pp, s, &ga, 0);
}
xfree(s);
}
}
for (int i = 0; i < ga.ga_len; i++) {
- char_u *match = ((char_u **)ga.ga_data)[i];
- char_u *s = match;
- char_u *e = s + STRLEN(s);
+ char *match = ((char **)ga.ga_data)[i];
+ char *s = match;
+ char *e = s + STRLEN(s);
if (e - s > 4 && (STRNICMP(e - 4, ".vim", 4) == 0
|| ((flags & DIP_LUA)
&& STRNICMP(e - 4, ".lua", 4) == 0))) {
@@ -1243,7 +1271,7 @@ int ExpandRTDir(char_u *pat, int flags, int *num_file, char ***file, char *dirna
/// Expand loadplugin names:
/// 'packpath'/pack/ * /opt/{pat}
-int ExpandPackAddDir(char_u *pat, int *num_file, char ***file)
+int ExpandPackAddDir(char *pat, int *num_file, char ***file)
{
garray_T ga;
@@ -1253,16 +1281,16 @@ int ExpandPackAddDir(char_u *pat, int *num_file, char ***file)
ga_init(&ga, (int)sizeof(char *), 10);
size_t buflen = pat_len + 26;
- char_u *s = xmalloc(buflen);
- snprintf((char *)s, buflen, "pack/*/opt/%s*", pat); // NOLINT
- globpath((char *)p_pp, s, &ga, 0);
- snprintf((char *)s, buflen, "opt/%s*", pat); // NOLINT
- globpath((char *)p_pp, s, &ga, 0);
+ char *s = xmalloc(buflen);
+ snprintf(s, buflen, "pack/*/opt/%s*", pat); // NOLINT
+ globpath(p_pp, s, &ga, 0);
+ snprintf(s, buflen, "opt/%s*", pat); // NOLINT
+ globpath(p_pp, s, &ga, 0);
xfree(s);
for (int i = 0; i < ga.ga_len; i++) {
- char_u *match = ((char_u **)ga.ga_data)[i];
- s = (char_u *)path_tail((char *)match);
+ char *match = ((char **)ga.ga_data)[i];
+ s = path_tail(match);
memmove(match, s, STRLEN(s) + 1);
}
@@ -1451,7 +1479,7 @@ char *get_lib_dir(void)
// TODO(bfredl): too fragile? Ideally default_lib_dir would be made empty
// in an appimage build
if (strlen(default_lib_dir) != 0
- && os_isdir((const char_u *)default_lib_dir)) {
+ && os_isdir(default_lib_dir)) {
return xstrdup(default_lib_dir);
}
@@ -1583,7 +1611,7 @@ static void cmd_source(char *fname, exarg_T *eap)
// - after ":argdo", ":windo" or ":bufdo"
// - another command follows
// - inside a loop
- openscript((char_u *)fname, global_busy || listcmd_busy || eap->nextcmd != NULL
+ openscript(fname, global_busy || listcmd_busy || eap->nextcmd != NULL
|| eap->cstack->cs_idx >= 0);
// ":source" read ex commands
@@ -1663,12 +1691,12 @@ static FILE *fopen_noinh_readbin(char *filename)
///
/// @return true if this line did begin with a continuation (the next line
/// should also be considered, if it exists); false otherwise
-static bool concat_continued_line(garray_T *const ga, const int init_growsize,
- const char_u *const p, size_t len)
+static bool concat_continued_line(garray_T *const ga, const int init_growsize, const char *const p,
+ size_t len)
FUNC_ATTR_NONNULL_ALL
{
- const char *const line = (char *)skipwhite_len(p, len);
- len -= (size_t)((char_u *)line - p);
+ const char *const line = skipwhite_len((char *)p, len);
+ len -= (size_t)(line - p);
// Skip lines starting with '\" ', concat lines starting with '\'
if (len >= 3 && STRNCMP(line, "\"\\ ", 3) == 0) {
return true;
@@ -1704,15 +1732,15 @@ static char *get_str_line(int c, void *cookie, int indent, bool do_concat)
return NULL;
}
const char *line = p->buf + p->offset;
- const char *eol = (char *)skip_to_newline((char_u *)line);
+ const char *eol = skip_to_newline(line);
garray_T ga;
- ga_init(&ga, sizeof(char_u), 400);
+ ga_init(&ga, sizeof(char), 400);
ga_concat_len(&ga, line, (size_t)(eol - line));
if (do_concat && vim_strchr(p_cpo, CPO_CONCAT) == NULL) {
while (eol[0] != NUL) {
line = eol + 1;
- const char_u *const next_eol = skip_to_newline((char_u *)line);
- if (!concat_continued_line(&ga, 400, (char_u *)line, (size_t)(next_eol - (char_u *)line))) {
+ const char *const next_eol = skip_to_newline(line);
+ if (!concat_continued_line(&ga, 400, line, (size_t)(next_eol - line))) {
break;
}
eol = (char *)next_eol;
@@ -1742,7 +1770,7 @@ scriptitem_T *new_script_item(char *const name, scid_T *const sid_out)
SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
SCRIPT_ITEM(script_items.ga_len).sn_prof_on = false;
}
- SCRIPT_ITEM(sid).sn_name = (char_u *)name;
+ SCRIPT_ITEM(sid).sn_name = name;
new_script_vars(sid); // Allocate the local script variables to use for this script.
return &SCRIPT_ITEM(sid);
}
@@ -1786,7 +1814,7 @@ static void cmd_source_buffer(const exarg_T *const eap)
return;
}
garray_T ga;
- ga_init(&ga, sizeof(char_u), 400);
+ ga_init(&ga, sizeof(char), 400);
const linenr_T final_lnum = eap->line2;
// Copy the contents to be executed.
for (linenr_T curr_lnum = eap->line1; curr_lnum <= final_lnum; curr_lnum++) {
@@ -1797,7 +1825,7 @@ static void cmd_source_buffer(const exarg_T *const eap)
ga_concat(&ga, (char *)ml_get(curr_lnum));
ga_append(&ga, NL);
}
- ((char_u *)ga.ga_data)[ga.ga_len - 1] = NUL;
+ ((char *)ga.ga_data)[ga.ga_len - 1] = NUL;
const GetStrLineCookie cookie = {
.buf = ga.ga_data,
.offset = 0,
@@ -1858,7 +1886,7 @@ int do_source(char *fname, int check_other, int is_vimrc)
if (fname_exp == NULL) {
return retval;
}
- if (os_isdir((char_u *)fname_exp)) {
+ if (os_isdir(fname_exp)) {
smsg(_("Cannot source a directory: \"%s\""), fname);
goto theend;
}
@@ -1935,7 +1963,7 @@ int do_source(char *fname, int check_other, int is_vimrc)
cookie.finished = false;
// Check if this script has a breakpoint.
- cookie.breakpoint = dbg_find_breakpoint(true, (char_u *)fname_exp, (linenr_T)0);
+ cookie.breakpoint = dbg_find_breakpoint(true, fname_exp, (linenr_T)0);
cookie.fname = fname_exp;
cookie.dbg_tick = debug_tick;
@@ -1964,7 +1992,7 @@ int do_source(char *fname, int check_other, int is_vimrc)
si = get_current_script_id(&fname_exp, &current_sctx);
// Keep the sourcing name/lnum, for recursive calls.
- estack_push(ETYPE_SCRIPT, (char *)si->sn_name, 0);
+ estack_push(ETYPE_SCRIPT, si->sn_name, 0);
if (l_do_profiling == PROF_YES) {
bool forceit = false;
@@ -1996,8 +2024,8 @@ int do_source(char *fname, int check_other, int is_vimrc)
if (firstline != NULL && STRLEN(firstline) >= 3 && firstline[0] == 0xef
&& firstline[1] == 0xbb && firstline[2] == 0xbf) {
// Found BOM; setup conversion, skip over BOM and recode the line.
- convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc);
- p = (char *)string_convert(&cookie.conv, (char_u *)firstline + 3, NULL);
+ convert_setup(&cookie.conv, "utf-8", p_enc);
+ p = string_convert(&cookie.conv, (char *)firstline + 3, NULL);
if (p == NULL) {
p = xstrdup((char *)firstline + 3);
}
@@ -2100,7 +2128,7 @@ scriptitem_T *get_current_script_id(char **fnamep, sctx_T *ret_sctx)
}
if (script_sctx.sc_sid == 0) {
si = new_script_item(*fnamep, &script_sctx.sc_sid);
- *fnamep = xstrdup((char *)si->sn_name);
+ *fnamep = xstrdup(si->sn_name);
}
if (ret_sctx != NULL) {
*ret_sctx = script_sctx;
@@ -2117,7 +2145,7 @@ void ex_scriptnames(exarg_T *eap)
if (eap->line2 < 1 || eap->line2 > script_items.ga_len) {
emsg(_(e_invarg));
} else {
- eap->arg = (char *)SCRIPT_ITEM(eap->line2).sn_name;
+ eap->arg = SCRIPT_ITEM(eap->line2).sn_name;
do_exedit(eap, NULL);
}
return;
@@ -2125,9 +2153,9 @@ void ex_scriptnames(exarg_T *eap)
for (int i = 1; i <= script_items.ga_len && !got_int; i++) {
if (SCRIPT_ITEM(i).sn_name != NULL) {
- home_replace(NULL, (char *)SCRIPT_ITEM(i).sn_name, (char *)NameBuff, MAXPATHL, true);
+ home_replace(NULL, SCRIPT_ITEM(i).sn_name, (char *)NameBuff, MAXPATHL, true);
vim_snprintf((char *)IObuff, IOSIZE, "%3d: %s", i, NameBuff);
- if (!message_filtered(IObuff)) {
+ if (!message_filtered((char *)IObuff)) {
msg_putchar('\n');
msg_outtrans((char *)IObuff);
line_breakcheck();
@@ -2151,40 +2179,40 @@ void scriptnames_slash_adjust(void)
/// Get a pointer to a script name. Used for ":verbose set".
/// Message appended to "Last set from "
-char_u *get_scriptname(LastSet last_set, bool *should_free)
+char *get_scriptname(LastSet last_set, bool *should_free)
{
*should_free = false;
switch (last_set.script_ctx.sc_sid) {
case SID_MODELINE:
- return (char_u *)_("modeline");
+ return _("modeline");
case SID_CMDARG:
- return (char_u *)_("--cmd argument");
+ return _("--cmd argument");
case SID_CARG:
- return (char_u *)_("-c argument");
+ return _("-c argument");
case SID_ENV:
- return (char_u *)_("environment variable");
+ return _("environment variable");
case SID_ERROR:
- return (char_u *)_("error handler");
+ return _("error handler");
case SID_WINLAYOUT:
- return (char_u *)_("changed window size");
+ return _("changed window size");
case SID_LUA:
- return (char_u *)_("Lua");
+ return _("Lua");
case SID_API_CLIENT:
snprintf((char *)IObuff, IOSIZE, _("API client (channel id %" PRIu64 ")"), last_set.channel_id);
- return IObuff;
+ return (char *)IObuff;
case SID_STR:
- return (char_u *)_("anonymous :source");
+ return _("anonymous :source");
default: {
- char *const sname = (char *)SCRIPT_ITEM(last_set.script_ctx.sc_sid).sn_name;
+ char *const sname = SCRIPT_ITEM(last_set.script_ctx.sc_sid).sn_name;
if (sname == NULL) {
snprintf((char *)IObuff, IOSIZE, _("anonymous :source (script id %d)"),
last_set.script_ctx.sc_sid);
- return IObuff;
+ return (char *)IObuff;
}
*should_free = true;
- return (char_u *)home_replace_save(NULL, sname);
+ return home_replace_save(NULL, sname);
}
}
}
@@ -2220,7 +2248,7 @@ char *getsourceline(int c, void *cookie, int indent, bool do_concat)
// If breakpoints have been added/deleted need to check for it.
if (sp->dbg_tick < debug_tick) {
- sp->breakpoint = dbg_find_breakpoint(true, (char_u *)sp->fname, SOURCING_LNUM);
+ sp->breakpoint = dbg_find_breakpoint(true, sp->fname, SOURCING_LNUM);
sp->dbg_tick = debug_tick;
}
if (do_profiling == PROF_YES) {
@@ -2259,11 +2287,10 @@ char *getsourceline(int c, void *cookie, int indent, bool do_concat)
|| (p[0] == '"' && p[1] == '\\' && p[2] == ' '))) {
garray_T ga;
- ga_init(&ga, (int)sizeof(char_u), 400);
+ ga_init(&ga, (int)sizeof(char), 400);
ga_concat(&ga, line);
while (sp->nextline != NULL
- && concat_continued_line(&ga, 400, (char_u *)sp->nextline,
- STRLEN(sp->nextline))) {
+ && concat_continued_line(&ga, 400, sp->nextline, STRLEN(sp->nextline))) {
xfree(sp->nextline);
sp->nextline = get_one_sourceline(sp);
}
@@ -2277,7 +2304,7 @@ char *getsourceline(int c, void *cookie, int indent, bool do_concat)
char *s;
// Convert the encoding of the script line.
- s = (char *)string_convert(&sp->conv, (char_u *)line, NULL);
+ s = string_convert(&sp->conv, line, NULL);
if (s != NULL) {
xfree(line);
line = s;
@@ -2286,9 +2313,9 @@ char *getsourceline(int c, void *cookie, int indent, bool do_concat)
// Did we encounter a breakpoint?
if (sp->breakpoint != 0 && sp->breakpoint <= SOURCING_LNUM) {
- dbg_breakpoint((char_u *)sp->fname, SOURCING_LNUM);
+ dbg_breakpoint(sp->fname, SOURCING_LNUM);
// Find next breakpoint.
- sp->breakpoint = dbg_find_breakpoint(true, (char_u *)sp->fname, SOURCING_LNUM);
+ sp->breakpoint = dbg_find_breakpoint(true, sp->fname, SOURCING_LNUM);
sp->dbg_tick = debug_tick;
}
@@ -2410,14 +2437,14 @@ void ex_scriptencoding(exarg_T *eap)
}
if (*eap->arg != NUL) {
- name = (char *)enc_canonize((char_u *)eap->arg);
+ name = enc_canonize(eap->arg);
} else {
name = eap->arg;
}
// Setup for conversion from the specified encoding to 'encoding'.
sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie);
- convert_setup(&sp->conv, (char_u *)name, p_enc);
+ convert_setup(&sp->conv, name, p_enc);
if (name != eap->arg) {
xfree(name);
diff --git a/src/nvim/runtime.h b/src/nvim/runtime.h
index a255c6c096..053c71212e 100644
--- a/src/nvim/runtime.h
+++ b/src/nvim/runtime.h
@@ -47,10 +47,11 @@ typedef enum {
ESTACK_NONE,
ESTACK_SFILE,
ESTACK_STACK,
+ ESTACK_SCRIPT,
} estack_arg_T;
typedef struct scriptitem_S {
- char_u *sn_name;
+ char *sn_name;
bool sn_prof_on; ///< true when script is/was profiled
bool sn_pr_force; ///< forceit: profile functions in this script
proftime_T sn_pr_child; ///< time set when going into first child
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 49aed19666..222285fdc8 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -69,7 +69,7 @@ bool conceal_cursor_line(const win_T *wp)
} else {
return false;
}
- return vim_strchr((char *)wp->w_p_cocu, c) != NULL;
+ return vim_strchr(wp->w_p_cocu, c) != NULL;
}
/// Whether cursorline is drawn in a special way
@@ -277,7 +277,7 @@ static int wildmenu_match_len(expand_T *xp, char_u *s)
/// These are backslashes used for escaping. Do show backslashes in help tags.
static int skip_wildmenu_char(expand_T *xp, char_u *s)
{
- if ((rem_backslash(s) && xp->xp_context != EXPAND_HELP)
+ if ((rem_backslash((char *)s) && xp->xp_context != EXPAND_HELP)
|| ((xp->xp_context == EXPAND_MENUS
|| xp->xp_context == EXPAND_MENUNAMES)
&& (s[0] == '\t'
@@ -469,10 +469,10 @@ void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int match, i
ScreenGrid *grid = (wild_menu_showing == WM_SCROLLED)
? &msg_grid_adj : &default_grid;
- grid_puts(grid, buf, row, 0, attr);
+ grid_puts(grid, (char *)buf, row, 0, attr);
if (selstart != NULL && highlight) {
*selend = NUL;
- grid_puts(grid, selstart, row, selstart_col, HL_ATTR(HLF_WM));
+ grid_puts(grid, (char *)selstart, row, selstart_col, HL_ATTR(HLF_WM));
}
grid_fill(grid, row, row + 1, clen, Columns,
@@ -535,7 +535,7 @@ bool get_keymap_str(win_T *wp, char *fmt, char *buf, int len)
curwin = old_curwin;
if (p == NULL || *p == NUL) {
if (wp->w_buffer->b_kmap_state & KEYMAP_LOADED) {
- p = (char *)wp->w_buffer->b_p_keymap;
+ p = wp->w_buffer->b_p_keymap;
} else {
p = "lang";
}
@@ -734,13 +734,13 @@ int showmode(void)
length = (Rows - msg_row) * Columns - 3;
}
if (edit_submode_extra != NULL) {
- length -= vim_strsize((char *)edit_submode_extra);
+ length -= vim_strsize(edit_submode_extra);
}
if (length > 0) {
if (edit_submode_pre != NULL) {
- length -= vim_strsize((char *)edit_submode_pre);
+ length -= vim_strsize(edit_submode_pre);
}
- if (length - vim_strsize((char *)edit_submode) > 0) {
+ if (length - vim_strsize(edit_submode) > 0) {
if (edit_submode_pre != NULL) {
msg_puts_attr((const char *)edit_submode_pre, attr);
}
@@ -1013,7 +1013,7 @@ void draw_tabline(void)
modified = false;
- for (wincount = 0; wp != NULL; wp = wp->w_next, ++wincount) {
+ for (wincount = 0; wp != NULL; wp = wp->w_next, wincount++) {
if (bufIsChanged(wp->w_buffer)) {
modified = true;
}
@@ -1031,7 +1031,7 @@ void draw_tabline(void)
col += len;
}
if (modified) {
- grid_puts_len(&default_grid, (char_u *)"+", 1, 0, col++, attr);
+ grid_puts_len(&default_grid, "+", 1, 0, col++, attr);
}
grid_putchar(&default_grid, ' ', 0, col++, attr);
}
@@ -1042,7 +1042,7 @@ void draw_tabline(void)
get_trans_bufname(cwp->w_buffer);
shorten_dir(NameBuff);
len = vim_strsize((char *)NameBuff);
- p = NameBuff;
+ p = (char_u *)NameBuff;
while (len > room) {
len -= ptr2cells((char *)p);
MB_PTR_ADV(p);
@@ -1051,7 +1051,7 @@ void draw_tabline(void)
len = Columns - col - 1;
}
- grid_puts_len(&default_grid, p, (int)STRLEN(p), 0, col, attr);
+ grid_puts_len(&default_grid, (char *)p, (int)STRLEN(p), 0, col, attr);
col += len;
}
grid_putchar(&default_grid, ' ', 0, col++, attr);
@@ -1094,7 +1094,6 @@ void draw_tabline(void)
static void ui_ext_tabline_update(void)
{
Arena arena = ARENA_EMPTY;
- arena_start(&arena, &ui_ext_fixblk);
size_t n_tabs = 0;
FOR_ALL_TABS(tp) {
@@ -1135,7 +1134,7 @@ static void ui_ext_tabline_update(void)
}
ui_call_tabline_update(curtab->handle, tabs, curbuf->handle, buffers);
- arena_mem_free(arena_finish(&arena), &ui_ext_fixblk);
+ arena_mem_free(arena_finish(&arena));
}
void get_trans_bufname(buf_T *buf)
@@ -1263,17 +1262,15 @@ int number_width(win_T *wp)
/// Calls mb_cptr2char_adv(p) and returns the character.
/// If "p" starts with "\x", "\u" or "\U" the hex or unicode value is used.
/// Returns 0 for invalid hex or invalid UTF-8 byte.
-static int get_encoded_char_adv(char_u **p)
+static int get_encoded_char_adv(const char_u **p)
{
- char_u *s = *p;
+ const char_u *s = *p;
if (s[0] == '\\' && (s[1] == 'x' || s[1] == 'u' || s[1] == 'U')) {
int64_t num = 0;
- int bytes;
- int n;
- for (bytes = s[1] == 'x' ? 1 : s[1] == 'u' ? 2 : 4; bytes > 0; bytes--) {
+ for (int bytes = s[1] == 'x' ? 1 : s[1] == 'u' ? 2 : 4; bytes > 0; bytes--) {
*p += 2;
- n = hexhex2nr(*p);
+ int n = hexhex2nr((char *)(*p));
if (n < 0) {
return 0;
}
@@ -1284,8 +1281,8 @@ static int get_encoded_char_adv(char_u **p)
}
// TODO(bfredl): use schar_T representation and utfc_ptr2len
- int clen = utf_ptr2len((char *)s);
- int c = mb_cptr2char_adv((const char_u **)p);
+ int clen = utf_ptr2len((const char *)s);
+ int c = mb_cptr2char_adv(p);
if (clen == 1 && c > 127) { // Invalid UTF-8 byte
return 0;
}
@@ -1295,26 +1292,22 @@ static int get_encoded_char_adv(char_u **p)
/// Handle setting 'listchars' or 'fillchars'.
/// Assume monocell characters
///
-/// @param varp either &curwin->w_p_lcs or &curwin->w_p_fcs
+/// @param varp either the global or the window-local value.
+/// @param apply if false, do not store the flags, only check for errors.
/// @return error message, NULL if it's OK.
-char *set_chars_option(win_T *wp, char_u **varp, bool set)
+char *set_chars_option(win_T *wp, char **varp, bool apply)
{
- int round, i, len, len2, entries;
- char_u *p, *s;
- int c1;
- int c2 = 0;
- int c3 = 0;
- char_u *last_multispace = NULL; // Last occurrence of "multispace:"
- char_u *last_lmultispace = NULL; // Last occurrence of "leadmultispace:"
+ const char_u *last_multispace = NULL; // Last occurrence of "multispace:"
+ const char_u *last_lmultispace = NULL; // Last occurrence of "leadmultispace:"
int multispace_len = 0; // Length of lcs-multispace string
int lead_multispace_len = 0; // Length of lcs-leadmultispace string
+ const bool is_listchars = (varp == &p_lcs || varp == &wp->w_p_lcs);
struct chars_tab {
- int *cp; ///< char value
+ int *cp; ///< char value
char *name; ///< char id
- int def; ///< default value
+ int def; ///< default value
};
- struct chars_tab *tab;
// XXX: Characters taking 2 columns is forbidden (TUI limitation?). Set old defaults in this case.
struct chars_tab fcs_tab[] = {
@@ -1336,6 +1329,7 @@ char *set_chars_option(win_T *wp, char_u **varp, bool set)
{ &wp->w_p_fcs_chars.msgsep, "msgsep", ' ' },
{ &wp->w_p_fcs_chars.eob, "eob", '~' },
};
+
struct chars_tab lcs_tab[] = {
{ &wp->w_p_lcs_chars.eol, "eol", NUL },
{ &wp->w_p_lcs_chars.ext, "extends", NUL },
@@ -1348,30 +1342,33 @@ char *set_chars_option(win_T *wp, char_u **varp, bool set)
{ &wp->w_p_lcs_chars.conceal, "conceal", NUL },
};
- if (varp == &p_lcs || varp == &wp->w_p_lcs) {
+ struct chars_tab *tab;
+ int entries;
+ const char_u *value = (char_u *)(*varp);
+ if (is_listchars) {
tab = lcs_tab;
entries = ARRAY_SIZE(lcs_tab);
if (varp == &wp->w_p_lcs && wp->w_p_lcs[0] == NUL) {
- varp = &p_lcs;
+ value = (char_u *)p_lcs; // local value is empty, use the global value
}
} else {
tab = fcs_tab;
entries = ARRAY_SIZE(fcs_tab);
if (varp == &wp->w_p_fcs && wp->w_p_fcs[0] == NUL) {
- varp = &p_fcs;
+ value = (char_u *)p_fcs; // local value is empty, use the global value
}
}
// first round: check for valid value, second round: assign values
- for (round = 0; round <= (set ? 1 : 0); round++) {
+ for (int round = 0; round <= (apply ? 1 : 0); round++) {
if (round > 0) {
// After checking that the value is valid: set defaults
- for (i = 0; i < entries; i++) {
+ for (int i = 0; i < entries; i++) {
if (tab[i].cp != NULL) {
*(tab[i].cp) = tab[i].def;
}
}
- if (varp == &p_lcs || varp == &wp->w_p_lcs) {
+ if (is_listchars) {
wp->w_p_lcs_chars.tab1 = NUL;
wp->w_p_lcs_chars.tab3 = NUL;
@@ -1393,19 +1390,20 @@ char *set_chars_option(win_T *wp, char_u **varp, bool set)
}
}
}
- p = *varp;
+ const char_u *p = value;
while (*p) {
+ int i;
for (i = 0; i < entries; i++) {
- len = (int)STRLEN(tab[i].name);
+ const size_t len = STRLEN(tab[i].name);
if (STRNCMP(p, tab[i].name, len) == 0
&& p[len] == ':'
&& p[len + 1] != NUL) {
- c2 = c3 = 0;
- s = p + len + 1;
- c1 = get_encoded_char_adv(&s);
+ const char_u *s = p + len + 1;
+ int c1 = get_encoded_char_adv(&s);
if (c1 == 0 || char2cells(c1) > 1) {
return e_invarg;
}
+ int c2 = 0, c3 = 0;
if (tab[i].cp == &wp->w_p_lcs_chars.tab2) {
if (*s == NUL) {
return e_invarg;
@@ -1438,19 +1436,19 @@ char *set_chars_option(win_T *wp, char_u **varp, bool set)
}
if (i == entries) {
- len = (int)STRLEN("multispace");
- len2 = (int)STRLEN("leadmultispace");
- if ((varp == &p_lcs || varp == &wp->w_p_lcs)
+ const size_t len = STRLEN("multispace");
+ const size_t len2 = STRLEN("leadmultispace");
+ if (is_listchars
&& STRNCMP(p, "multispace", len) == 0
&& p[len] == ':'
&& p[len + 1] != NUL) {
- s = p + len + 1;
+ const char_u *s = p + len + 1;
if (round == 0) {
// Get length of lcs-multispace string in the first round
last_multispace = p;
multispace_len = 0;
while (*s != NUL && *s != ',') {
- c1 = get_encoded_char_adv(&s);
+ int c1 = get_encoded_char_adv(&s);
if (c1 == 0 || char2cells(c1) > 1) {
return e_invarg;
}
@@ -1464,24 +1462,24 @@ char *set_chars_option(win_T *wp, char_u **varp, bool set)
} else {
int multispace_pos = 0;
while (*s != NUL && *s != ',') {
- c1 = get_encoded_char_adv(&s);
+ int c1 = get_encoded_char_adv(&s);
if (p == last_multispace) {
wp->w_p_lcs_chars.multispace[multispace_pos++] = c1;
}
}
p = s;
}
- } else if ((varp == &p_lcs || varp == &wp->w_p_lcs)
+ } else if (is_listchars
&& STRNCMP(p, "leadmultispace", len2) == 0
&& p[len2] == ':'
&& p[len2 + 1] != NUL) {
- s = p + len2 + 1;
+ const char_u *s = p + len2 + 1;
if (round == 0) {
// get length of lcs-leadmultispace string in first round
last_lmultispace = p;
lead_multispace_len = 0;
while (*s != NUL && *s != ',') {
- c1 = get_encoded_char_adv(&s);
+ int c1 = get_encoded_char_adv(&s);
if (c1 == 0 || char2cells(c1) > 1) {
return e_invarg;
}
@@ -1495,7 +1493,7 @@ char *set_chars_option(win_T *wp, char_u **varp, bool set)
} else {
int multispace_pos = 0;
while (*s != NUL && *s != ',') {
- c1 = get_encoded_char_adv(&s);
+ int c1 = get_encoded_char_adv(&s);
if (p == last_lmultispace) {
wp->w_p_lcs_chars.leadmultispace[multispace_pos++] = c1;
}
@@ -1506,6 +1504,7 @@ char *set_chars_option(win_T *wp, char_u **varp, bool set)
return e_invarg;
}
}
+
if (*p == ',') {
p++;
}
diff --git a/src/nvim/search.c b/src/nvim/search.c
index c53d955974..e995081df8 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -170,7 +170,7 @@ int search_regcomp(char_u *pat, int pat_save, int pat_use, int options, regmmatc
}
if (curwin->w_p_rl && *curwin->w_p_rlc == 's') {
- mr_pattern = reverse_text(pat);
+ mr_pattern = (char_u *)reverse_text((char *)pat);
mr_pattern_alloced = true;
} else {
mr_pattern = pat;
@@ -220,7 +220,7 @@ void save_re_pat(int idx, char_u *pat, int magic)
last_idx = idx;
// If 'hlsearch' set and search pat changed: need redraw.
if (p_hls) {
- redraw_all_later(SOME_VALID);
+ redraw_all_later(UPD_SOME_VALID);
}
set_no_hlsearch(false);
}
@@ -354,10 +354,8 @@ char_u *last_search_pattern(void)
return spats[RE_SEARCH].pat;
}
-/*
- * Return TRUE when case should be ignored for search pattern "pat".
- * Uses the 'ignorecase' and 'smartcase' options.
- */
+/// Return true when case should be ignored for search pattern "pat".
+/// Uses the 'ignorecase' and 'smartcase' options.
int ignorecase(char_u *pat)
{
return ignorecase_opt(pat, p_ic, p_scs);
@@ -423,7 +421,7 @@ int last_csearch_forward(void)
int last_csearch_until(void)
{
- return last_t_cmd == TRUE;
+ return last_t_cmd == true;
}
void set_last_csearch(int c, char_u *s, int len)
@@ -480,8 +478,8 @@ void set_last_search_pat(const char_u *s, int idx, int magic, int setlast)
spats[idx].no_scs = false;
spats[idx].off.dir = '/';
set_vv_searchforward();
- spats[idx].off.line = FALSE;
- spats[idx].off.end = FALSE;
+ spats[idx].off.line = false;
+ spats[idx].off.end = false;
spats[idx].off.off = 0;
if (setlast) {
last_idx = idx;
@@ -498,7 +496,7 @@ void set_last_search_pat(const char_u *s, int idx, int magic, int setlast)
}
// If 'hlsearch' set and search pat changed: need redraw.
if (p_hls && idx == last_idx && !no_hlsearch) {
- redraw_all_later(SOME_VALID);
+ redraw_all_later(UPD_SOME_VALID);
}
}
@@ -513,7 +511,7 @@ void last_pat_prog(regmmatch_T *regmatch)
regmatch->regprog = NULL;
return;
}
- ++emsg_off; // So it doesn't beep if bad expr
+ emsg_off++; // So it doesn't beep if bad expr
(void)search_regcomp((char_u *)"", 0, last_idx, SEARCH_KEEP, regmatch);
emsg_off--;
}
@@ -610,11 +608,11 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
start_pos = *pos; // remember start pos for detecting no match
found = 0; // default: not found
- at_first_line = TRUE; // default: start in first line
+ at_first_line = true; // default: start in first line
if (pos->lnum == 0) { // correct lnum for when starting in line 0
pos->lnum = 1;
pos->col = 0;
- at_first_line = FALSE; // not in first line now
+ at_first_line = false; // not in first line now
}
/*
@@ -627,14 +625,14 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
if (dir == BACKWARD && start_pos.col == 0
&& (options & SEARCH_START) == 0) {
lnum = pos->lnum - 1;
- at_first_line = FALSE;
+ at_first_line = false;
} else {
lnum = pos->lnum;
}
- for (loop = 0; loop <= 1; ++loop) { // loop twice if 'wrapscan' set
+ for (loop = 0; loop <= 1; loop++) { // loop twice if 'wrapscan' set
for (; lnum > 0 && lnum <= buf->b_ml.ml_line_count;
- lnum += dir, at_first_line = FALSE) {
+ lnum += dir, at_first_line = false) {
// Stop after checking "stop_lnum", if it's set.
if (stop_lnum != 0 && (dir == FORWARD
? lnum > stop_lnum : lnum < stop_lnum)) {
@@ -901,7 +899,7 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
break; // if second loop, stop where started
}
}
- at_first_line = FALSE;
+ at_first_line = false;
// vim_regexec_multi() may clear "regprog"
if (regmatch.regprog == NULL) {
@@ -991,7 +989,7 @@ static int first_submatch(regmmatch_T *rp)
{
int submatch;
- for (submatch = 1;; ++submatch) {
+ for (submatch = 1;; submatch++) {
if (rp->startpos[submatch].lnum >= 0) {
break;
}
@@ -1006,22 +1004,22 @@ static int first_submatch(regmmatch_T *rp)
/// Highest level string search function.
/// Search for the 'count'th occurrence of pattern 'pat' in direction 'dirc'
///
-/// Careful: If spats[0].off.line == TRUE and spats[0].off.off == 0 this
+/// Careful: If spats[0].off.line == true and spats[0].off.off == 0 this
/// makes the movement linewise without moving the match position.
///
/// @param dirc if 0: use previous dir.
/// @param pat NULL or empty : use previous string.
-/// @param options if TRUE and
-/// SEARCH_REV == TRUE : go in reverse of previous dir.
-/// SEARCH_ECHO == TRUE : echo the search command and handle options
-/// SEARCH_MSG == TRUE : may give error message
-/// SEARCH_OPT == TRUE : interpret optional flags
-/// SEARCH_HIS == TRUE : put search pattern in history
-/// SEARCH_NOOF == TRUE : don't add offset to position
-/// SEARCH_MARK == TRUE : set previous context mark
-/// SEARCH_KEEP == TRUE : keep previous search pattern
-/// SEARCH_START == TRUE : accept match at curpos itself
-/// SEARCH_PEEK == TRUE : check for typed char, cancel search
+/// @param options if true and
+/// SEARCH_REV == true : go in reverse of previous dir.
+/// SEARCH_ECHO == true : echo the search command and handle options
+/// SEARCH_MSG == true : may give error message
+/// SEARCH_OPT == true : interpret optional flags
+/// SEARCH_HIS == true : put search pattern in history
+/// SEARCH_NOOF == true : don't add offset to position
+/// SEARCH_MARK == true : set previous context mark
+/// SEARCH_KEEP == true : keep previous search pattern
+/// SEARCH_START == true : accept match at curpos itself
+/// SEARCH_PEEK == true : check for typed char, cancel search
/// @param oap can be NULL
/// @param dirc '/' or '?'
/// @param search_delim delimiter for search, e.g. '%' in s%regex%replacement
@@ -1093,7 +1091,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count,
* Turn 'hlsearch' highlighting back on.
*/
if (no_hlsearch && !(options & SEARCH_KEEP)) {
- redraw_all_later(SOME_VALID);
+ redraw_all_later(UPD_SOME_VALID);
set_no_hlsearch(false);
}
@@ -1126,7 +1124,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count,
* If there is a matching '/' or '?', toss it.
*/
ps = (char_u *)strcopy;
- p = skip_regexp(pat, search_delim, p_magic, &strcopy);
+ p = (char_u *)skip_regexp((char *)pat, search_delim, p_magic, &strcopy);
if (strcopy != (char *)ps) {
// made a copy of "pat" to change "\?" to "?"
searchcmdlen += (int)(STRLEN(pat) - STRLEN(strcopy));
@@ -1137,8 +1135,8 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count,
dircp = p; // remember where we put the NUL
*p++ = NUL;
}
- spats[0].off.line = FALSE;
- spats[0].off.end = FALSE;
+ spats[0].off.line = false;
+ spats[0].off.end = false;
spats[0].off.off = 0;
// Check for a line offset or a character offset.
// For get_address (echo off) we don't check for a character
@@ -1263,7 +1261,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count,
// it would be blanked out again very soon. Show it on the
// left, but do reverse the text.
if (curwin->w_p_rl && *curwin->w_p_rlc == 's') {
- char_u *r = reverse_text(trunc != NULL ? trunc : msgbuf);
+ char_u *r = (char_u *)reverse_text(trunc != NULL ? (char *)trunc : (char *)msgbuf);
xfree(msgbuf);
msgbuf = r;
// move reversed text to beginning of buffer
@@ -1298,7 +1296,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count,
*/
if (!spats[0].off.line && spats[0].off.off && pos.col < MAXCOL - 2) {
if (spats[0].off.off > 0) {
- for (c = spats[0].off.off; c; --c) {
+ for (c = spats[0].off.off; c; c--) {
if (decl(&pos) == -1) {
break;
}
@@ -1308,7 +1306,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count,
pos.col = MAXCOL;
}
} else {
- for (c = spats[0].off.off; c; ++c) {
+ for (c = spats[0].off.off; c; c++) {
if (incl(&pos) == -1) {
break;
}
@@ -1435,7 +1433,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count,
setpcmark();
}
curwin->w_cursor = pos;
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
end_do_search:
if ((options & SEARCH_KEEP) || (cmdmod.cmod_flags & CMOD_KEEPPATTERNS)) {
@@ -1499,16 +1497,15 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, Direction dir, char_u *pat)
// when adding lines the matching line may be empty but it is not
// ignored because we are interested in the next line -- Acevedo
- if ((compl_cont_status & CONT_ADDING)
- && !(compl_cont_status & CONT_SOL)) {
+ if (compl_status_adding() && !compl_status_sol()) {
if (mb_strcmp_ic((bool)p_ic, (const char *)p, (const char *)pat) == 0) {
return OK;
}
} else if (*p != NUL) { // Ignore empty lines.
// Expanding lines or words.
- assert(compl_length >= 0);
- if ((p_ic ? mb_strnicmp(p, pat, (size_t)compl_length)
- : STRNCMP(p, pat, compl_length)) == 0) {
+ assert(ins_compl_len() >= 0);
+ if ((p_ic ? mb_strnicmp(p, pat, (size_t)ins_compl_len())
+ : STRNCMP(p, pat, ins_compl_len())) == 0) {
return OK;
}
}
@@ -1520,12 +1517,10 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, Direction dir, char_u *pat)
* Character Searches
*/
-/*
- * Search for a character in a line. If "t_cmd" is FALSE, move to the
- * position of the character, otherwise move to just before the char.
- * Do this "cap->count1" times.
- * Return FAIL or OK.
- */
+/// Search for a character in a line. If "t_cmd" is false, move to the
+/// position of the character, otherwise move to just before the char.
+/// Do this "cap->count1" times.
+/// Return FAIL or OK.
int searchc(cmdarg_T *cap, int t_cmd)
FUNC_ATTR_NONNULL_ALL
{
@@ -1697,34 +1692,34 @@ static bool find_rawstring_end(char_u *linep, pos_T *startpos, pos_T *endpos)
static void find_mps_values(int *initc, int *findc, bool *backwards, bool switchit)
FUNC_ATTR_NONNULL_ALL
{
- char_u *ptr = curbuf->b_p_mps;
+ char *ptr = curbuf->b_p_mps;
while (*ptr != NUL) {
- if (utf_ptr2char((char *)ptr) == *initc) {
+ if (utf_ptr2char(ptr) == *initc) {
if (switchit) {
*findc = *initc;
- *initc = utf_ptr2char((char *)ptr + utfc_ptr2len((char *)ptr) + 1);
+ *initc = utf_ptr2char(ptr + utfc_ptr2len(ptr) + 1);
*backwards = true;
} else {
- *findc = utf_ptr2char((char *)ptr + utfc_ptr2len((char *)ptr) + 1);
+ *findc = utf_ptr2char(ptr + utfc_ptr2len(ptr) + 1);
*backwards = false;
}
return;
}
- char_u *prev = ptr;
- ptr += utfc_ptr2len((char *)ptr) + 1;
- if (utf_ptr2char((char *)ptr) == *initc) {
+ char *prev = ptr;
+ ptr += utfc_ptr2len(ptr) + 1;
+ if (utf_ptr2char(ptr) == *initc) {
if (switchit) {
*findc = *initc;
- *initc = utf_ptr2char((char *)prev);
+ *initc = utf_ptr2char(prev);
*backwards = false;
} else {
- *findc = utf_ptr2char((char *)prev);
+ *findc = utf_ptr2char(prev);
*backwards = true;
}
return;
}
- ptr += utfc_ptr2len((char *)ptr);
+ ptr += utfc_ptr2len(ptr);
if (*ptr == ',') {
ptr++;
}
@@ -1868,7 +1863,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
* the line.
*/
if (linep[pos.col] == NUL && pos.col) {
- --pos.col;
+ pos.col--;
}
for (;;) {
initc = utf_ptr2char((char *)linep + pos.col);
@@ -1982,7 +1977,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
// backward search: Check if this line contains a single-line comment
if ((backwards && comment_dir) || lisp) {
- comment_col = check_linecomment(linep);
+ comment_col = check_linecomment((char *)linep);
}
if (lisp && comment_col != MAXCOL && pos.col > (colnr_T)comment_col) {
lispcomm = true; // find match inside this comment
@@ -2002,7 +1997,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
if (pos.lnum == 1) { // start of file
break;
}
- --pos.lnum;
+ pos.lnum--;
if (maxtravel > 0 && ++traveled > maxtravel) {
break;
@@ -2015,7 +2010,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
// Check if this line contains a single-line comment
if (comment_dir || lisp) {
- comment_col = check_linecomment(linep);
+ comment_col = check_linecomment((char *)linep);
}
// skip comment
if (lisp && comment_col != MAXCOL) {
@@ -2037,7 +2032,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
|| lispcomm) {
break;
}
- ++pos.lnum;
+ pos.lnum++;
if (maxtravel && traveled++ > maxtravel) {
break;
@@ -2048,7 +2043,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
do_quotes = -1;
line_breakcheck();
if (lisp) { // find comment pos in new line
- comment_col = check_linecomment(linep);
+ comment_col = check_linecomment((char *)linep);
}
} else {
pos.col += utfc_ptr2len((char *)linep + pos.col);
@@ -2132,7 +2127,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
* Watch out for "\\".
*/
at_start = do_quotes;
- for (ptr = linep; *ptr; ++ptr) {
+ for (ptr = linep; *ptr; ptr++) {
if (ptr == linep + pos.col + backwards) {
at_start = (do_quotes & 1);
}
@@ -2212,7 +2207,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
if (do_quotes) {
int col;
- for (col = pos.col - 1; col >= 0; --col) {
+ for (col = pos.col - 1; col >= 0; col--) {
if (linep[col] != '\\') {
break;
}
@@ -2306,15 +2301,15 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
/// Check if line[] contains a / / comment.
/// @returns MAXCOL if not, otherwise return the column.
-int check_linecomment(const char_u *line)
+int check_linecomment(const char *line)
{
- const char_u *p = line; // scan from start
+ const char *p = line; // scan from start
// skip Lispish one-line comments
if (curbuf->b_p_lisp) {
if (vim_strchr((char *)p, ';') != NULL) { // there may be comments
bool in_str = false; // inside of string
- while ((p = (char_u *)strpbrk((char *)p, "\";")) != NULL) {
+ while ((p = strpbrk((char *)p, "\";")) != NULL) {
if (*p == '"') {
if (in_str) {
if (*(p - 1) != '\\') { // skip escaped quote
@@ -2327,7 +2322,7 @@ int check_linecomment(const char_u *line)
}
} else if (!in_str && ((p - line) < 2
|| (*(p - 1) != '\\' && *(p - 2) != '#'))
- && !is_pos_in_string(line, (colnr_T)(p - line))) {
+ && !is_pos_in_string((char_u *)line, (colnr_T)(p - line))) {
break; // found!
}
p++;
@@ -2336,12 +2331,12 @@ int check_linecomment(const char_u *line)
p = NULL;
}
} else {
- while ((p = (char_u *)vim_strchr((char *)p, '/')) != NULL) {
+ while ((p = vim_strchr((char *)p, '/')) != NULL) {
// Accept a double /, unless it's preceded with * and followed by *,
// because * / / * is an end and start of a C comment. Only
// accept the position if it is not inside a string.
if (p[1] == '/' && (p == line || p[-1] != '*' || p[2] != '*')
- && !is_pos_in_string(line, (colnr_T)(p - line))) {
+ && !is_pos_in_string((char_u *)line, (colnr_T)(p - line))) {
break;
}
p++;
@@ -2377,7 +2372,7 @@ void showmatch(int c)
* Only show match for chars in the 'matchpairs' option.
*/
// 'matchpairs' is "x:y,x:y"
- for (p = curbuf->b_p_mps; *p != NUL; p++) {
+ for (p = (char_u *)curbuf->b_p_mps; *p != NUL; p++) {
if (utf_ptr2char((char *)p) == c && (curwin->w_p_rl ^ p_ri)) {
break;
}
@@ -2414,7 +2409,7 @@ void showmatch(int c)
dollar_vcol = -1;
}
curwin->w_virtcol++; // do display ')' just before "$"
- update_screen(VALID); // show the new char first
+ update_screen(UPD_VALID); // show the new char first
save_dollar_vcol = dollar_vcol;
save_state = State;
@@ -2449,1814 +2444,6 @@ void showmatch(int c)
}
}
-// Find the start of the next sentence, searching in the direction specified
-// by the "dir" argument. The cursor is positioned on the start of the next
-// sentence when found. If the next sentence is found, return OK. Return FAIL
-// otherwise. See ":h sentence" for the precise definition of a "sentence"
-// text object.
-int findsent(Direction dir, long count)
-{
- pos_T pos, tpos;
- int c;
- int (*func)(pos_T *);
- bool noskip = false; // do not skip blanks
-
- pos = curwin->w_cursor;
- if (dir == FORWARD) {
- func = incl;
- } else {
- func = decl;
- }
-
- while (count--) {
- const pos_T prev_pos = pos;
-
- // if on an empty line, skip up to a non-empty line
- if (gchar_pos(&pos) == NUL) {
- do {
- if ((*func)(&pos) == -1) {
- break;
- }
- } while (gchar_pos(&pos) == NUL);
- if (dir == FORWARD) {
- goto found;
- }
- // if on the start of a paragraph or a section and searching forward,
- // go to the next line
- } else if (dir == FORWARD && pos.col == 0
- && startPS(pos.lnum, NUL, false)) {
- if (pos.lnum == curbuf->b_ml.ml_line_count) {
- return FAIL;
- }
- pos.lnum++;
- goto found;
- } else if (dir == BACKWARD) {
- decl(&pos);
- }
-
- // go back to the previous non-white non-punctuation character
- bool found_dot = false;
- while (c = gchar_pos(&pos), ascii_iswhite(c)
- || vim_strchr(".!?)]\"'", c) != NULL) {
- tpos = pos;
- if (decl(&tpos) == -1 || (LINEEMPTY(tpos.lnum) && dir == FORWARD)) {
- break;
- }
- if (found_dot) {
- break;
- }
- if (vim_strchr(".!?", c) != NULL) {
- found_dot = true;
- }
- if (vim_strchr(")]\"'", c) != NULL
- && vim_strchr(".!?)]\"'", gchar_pos(&tpos)) == NULL) {
- break;
- }
- decl(&pos);
- }
-
- // remember the line where the search started
- const int startlnum = pos.lnum;
- const bool cpo_J = vim_strchr(p_cpo, CPO_ENDOFSENT) != NULL;
-
- for (;;) { // find end of sentence
- c = gchar_pos(&pos);
- if (c == NUL || (pos.col == 0 && startPS(pos.lnum, NUL, FALSE))) {
- if (dir == BACKWARD && pos.lnum != startlnum) {
- ++pos.lnum;
- }
- break;
- }
- if (c == '.' || c == '!' || c == '?') {
- tpos = pos;
- do {
- if ((c = inc(&tpos)) == -1) {
- break;
- }
- } while (vim_strchr(")]\"'", c = gchar_pos(&tpos))
- != NULL);
- if (c == -1 || (!cpo_J && (c == ' ' || c == '\t')) || c == NUL
- || (cpo_J && (c == ' ' && inc(&tpos) >= 0
- && gchar_pos(&tpos) == ' '))) {
- pos = tpos;
- if (gchar_pos(&pos) == NUL) { // skip NUL at EOL
- inc(&pos);
- }
- break;
- }
- }
- if ((*func)(&pos) == -1) {
- if (count) {
- return FAIL;
- }
- noskip = true;
- break;
- }
- }
-found:
- // skip white space
- while (!noskip && ((c = gchar_pos(&pos)) == ' ' || c == '\t')) {
- if (incl(&pos) == -1) {
- break;
- }
- }
-
- if (equalpos(prev_pos, pos)) {
- // didn't actually move, advance one character and try again
- if ((*func)(&pos) == -1) {
- if (count) {
- return FAIL;
- }
- break;
- }
- count++;
- }
- }
-
- setpcmark();
- curwin->w_cursor = pos;
- return OK;
-}
-
-/// Find the next paragraph or section in direction 'dir'.
-/// Paragraphs are currently supposed to be separated by empty lines.
-/// If 'what' is NUL we go to the next paragraph.
-/// If 'what' is '{' or '}' we go to the next section.
-/// If 'both' is TRUE also stop at '}'.
-///
-/// @param pincl Return: true if last char is to be included
-///
-/// @return TRUE if the next paragraph or section was found.
-bool findpar(bool *pincl, int dir, long count, int what, int both)
-{
- linenr_T curr;
- bool did_skip; // true after separating lines have been skipped
- bool first; // true on first line
- linenr_T fold_first; // first line of a closed fold
- linenr_T fold_last; // last line of a closed fold
- bool fold_skipped; // true if a closed fold was skipped this
- // iteration
-
- curr = curwin->w_cursor.lnum;
-
- while (count--) {
- did_skip = false;
- for (first = true;; first = false) {
- if (*ml_get(curr) != NUL) {
- did_skip = true;
- }
-
- // skip folded lines
- fold_skipped = false;
- if (first && hasFolding(curr, &fold_first, &fold_last)) {
- curr = ((dir > 0) ? fold_last : fold_first) + dir;
- fold_skipped = true;
- }
-
- if (!first && did_skip && startPS(curr, what, both)) {
- break;
- }
-
- if (fold_skipped) {
- curr -= dir;
- }
- if ((curr += dir) < 1 || curr > curbuf->b_ml.ml_line_count) {
- if (count) {
- return false;
- }
- curr -= dir;
- break;
- }
- }
- }
- setpcmark();
- if (both && *ml_get(curr) == '}') { // include line with '}'
- curr++;
- }
- curwin->w_cursor.lnum = curr;
- if (curr == curbuf->b_ml.ml_line_count && what != '}') {
- char_u *line = ml_get(curr);
-
- // Put the cursor on the last character in the last line and make the
- // motion inclusive.
- if ((curwin->w_cursor.col = (colnr_T)STRLEN(line)) != 0) {
- curwin->w_cursor.col--;
- curwin->w_cursor.col -= utf_head_off(line, line + curwin->w_cursor.col);
- *pincl = true;
- }
- } else {
- curwin->w_cursor.col = 0;
- }
- return true;
-}
-
-/*
- * check if the string 's' is a nroff macro that is in option 'opt'
- */
-static int inmacro(char_u *opt, char_u *s)
-{
- char_u *macro;
-
- for (macro = opt; macro[0]; macro++) {
- // Accept two characters in the option being equal to two characters
- // in the line. A space in the option matches with a space in the
- // line or the line having ended.
- if ((macro[0] == s[0]
- || (macro[0] == ' '
- && (s[0] == NUL || s[0] == ' ')))
- && (macro[1] == s[1]
- || ((macro[1] == NUL || macro[1] == ' ')
- && (s[0] == NUL || s[1] == NUL || s[1] == ' ')))) {
- break;
- }
- macro++;
- if (macro[0] == NUL) {
- break;
- }
- }
- return macro[0] != NUL;
-}
-
-/*
- * startPS: return TRUE if line 'lnum' is the start of a section or paragraph.
- * If 'para' is '{' or '}' only check for sections.
- * If 'both' is TRUE also stop at '}'
- */
-int startPS(linenr_T lnum, int para, int both)
-{
- char_u *s;
-
- s = ml_get(lnum);
- if (*s == para || *s == '\f' || (both && *s == '}')) {
- return true;
- }
- if (*s == '.' && (inmacro(p_sections, s + 1)
- || (!para && inmacro(p_para, s + 1)))) {
- return true;
- }
- return false;
-}
-
-/*
- * The following routines do the word searches performed by the 'w', 'W',
- * 'b', 'B', 'e', and 'E' commands.
- */
-
-/*
- * To perform these searches, characters are placed into one of three
- * classes, and transitions between classes determine word boundaries.
- *
- * The classes are:
- *
- * 0 - white space
- * 1 - punctuation
- * 2 or higher - keyword characters (letters, digits and underscore)
- */
-
-static int cls_bigword; // TRUE for "W", "B" or "E"
-
-/*
- * cls() - returns the class of character at curwin->w_cursor
- *
- * If a 'W', 'B', or 'E' motion is being done (cls_bigword == TRUE), chars
- * from class 2 and higher are reported as class 1 since only white space
- * boundaries are of interest.
- */
-static int cls(void)
-{
- int c;
-
- c = gchar_cursor();
- if (c == ' ' || c == '\t' || c == NUL) {
- return 0;
- }
-
- c = utf_class(c);
-
- // If cls_bigword is TRUE, report all non-blanks as class 1.
- if (c != 0 && cls_bigword) {
- return 1;
- }
- return c;
-}
-
-/// fwd_word(count, type, eol) - move forward one word
-///
-/// @return FAIL if the cursor was already at the end of the file.
-/// If eol is TRUE, last word stops at end of line (for operators).
-///
-/// @param bigword "W", "E" or "B"
-int fwd_word(long count, int bigword, int eol)
-{
- int sclass; // starting class
- int i;
- int last_line;
-
- curwin->w_cursor.coladd = 0;
- cls_bigword = bigword;
- while (--count >= 0) {
- // When inside a range of folded lines, move to the last char of the
- // last line.
- if (hasFolding(curwin->w_cursor.lnum, NULL, &curwin->w_cursor.lnum)) {
- coladvance(MAXCOL);
- }
- sclass = cls();
-
- /*
- * We always move at least one character, unless on the last
- * character in the buffer.
- */
- last_line = (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count);
- i = inc_cursor();
- if (i == -1 || (i >= 1 && last_line)) { // started at last char in file
- return FAIL;
- }
- if (i >= 1 && eol && count == 0) { // started at last char in line
- return OK;
- }
-
- /*
- * Go one char past end of current word (if any)
- */
- if (sclass != 0) {
- while (cls() == sclass) {
- i = inc_cursor();
- if (i == -1 || (i >= 1 && eol && count == 0)) {
- return OK;
- }
- }
- }
-
- /*
- * go to next non-white
- */
- while (cls() == 0) {
- /*
- * We'll stop if we land on a blank line
- */
- if (curwin->w_cursor.col == 0 && *get_cursor_line_ptr() == NUL) {
- break;
- }
-
- i = inc_cursor();
- if (i == -1 || (i >= 1 && eol && count == 0)) {
- return OK;
- }
- }
- }
- return OK;
-}
-
-/*
- * bck_word() - move backward 'count' words
- *
- * If stop is TRUE and we are already on the start of a word, move one less.
- *
- * Returns FAIL if top of the file was reached.
- */
-int bck_word(long count, int bigword, int stop)
-{
- int sclass; // starting class
-
- curwin->w_cursor.coladd = 0;
- cls_bigword = bigword;
- while (--count >= 0) {
- /* When inside a range of folded lines, move to the first char of the
- * first line. */
- if (hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum, NULL)) {
- curwin->w_cursor.col = 0;
- }
- sclass = cls();
- if (dec_cursor() == -1) { // started at start of file
- return FAIL;
- }
-
- if (!stop || sclass == cls() || sclass == 0) {
- /*
- * Skip white space before the word.
- * Stop on an empty line.
- */
- while (cls() == 0) {
- if (curwin->w_cursor.col == 0
- && LINEEMPTY(curwin->w_cursor.lnum)) {
- goto finished;
- }
- if (dec_cursor() == -1) { // hit start of file, stop here
- return OK;
- }
- }
-
- /*
- * Move backward to start of this word.
- */
- if (skip_chars(cls(), BACKWARD)) {
- return OK;
- }
- }
-
- inc_cursor(); // overshot - forward one
-finished:
- stop = FALSE;
- }
- return OK;
-}
-
-/*
- * end_word() - move to the end of the word
- *
- * There is an apparent bug in the 'e' motion of the real vi. At least on the
- * System V Release 3 version for the 80386. Unlike 'b' and 'w', the 'e'
- * motion crosses blank lines. When the real vi crosses a blank line in an
- * 'e' motion, the cursor is placed on the FIRST character of the next
- * non-blank line. The 'E' command, however, works correctly. Since this
- * appears to be a bug, I have not duplicated it here.
- *
- * Returns FAIL if end of the file was reached.
- *
- * If stop is TRUE and we are already on the end of a word, move one less.
- * If empty is TRUE stop on an empty line.
- */
-int end_word(long count, int bigword, int stop, int empty)
-{
- int sclass; // starting class
-
- curwin->w_cursor.coladd = 0;
- cls_bigword = bigword;
- while (--count >= 0) {
- /* When inside a range of folded lines, move to the last char of the
- * last line. */
- if (hasFolding(curwin->w_cursor.lnum, NULL, &curwin->w_cursor.lnum)) {
- coladvance(MAXCOL);
- }
- sclass = cls();
- if (inc_cursor() == -1) {
- return FAIL;
- }
-
- /*
- * If we're in the middle of a word, we just have to move to the end
- * of it.
- */
- if (cls() == sclass && sclass != 0) {
- /*
- * Move forward to end of the current word
- */
- if (skip_chars(sclass, FORWARD)) {
- return FAIL;
- }
- } else if (!stop || sclass == 0) {
- /*
- * We were at the end of a word. Go to the end of the next word.
- * First skip white space, if 'empty' is TRUE, stop at empty line.
- */
- while (cls() == 0) {
- if (empty && curwin->w_cursor.col == 0
- && LINEEMPTY(curwin->w_cursor.lnum)) {
- goto finished;
- }
- if (inc_cursor() == -1) { // hit end of file, stop here
- return FAIL;
- }
- }
-
- /*
- * Move forward to the end of this word.
- */
- if (skip_chars(cls(), FORWARD)) {
- return FAIL;
- }
- }
- dec_cursor(); // overshot - one char backward
-finished:
- stop = FALSE; // we move only one word less
- }
- return OK;
-}
-
-/// Move back to the end of the word.
-///
-/// @param bigword TRUE for "B"
-/// @param eol if true, then stop at end of line.
-///
-/// @return FAIL if start of the file was reached.
-int bckend_word(long count, int bigword, bool eol)
-{
- int sclass; // starting class
- int i;
-
- curwin->w_cursor.coladd = 0;
- cls_bigword = bigword;
- while (--count >= 0) {
- sclass = cls();
- if ((i = dec_cursor()) == -1) {
- return FAIL;
- }
- if (eol && i == 1) {
- return OK;
- }
-
- /*
- * Move backward to before the start of this word.
- */
- if (sclass != 0) {
- while (cls() == sclass) {
- if ((i = dec_cursor()) == -1 || (eol && i == 1)) {
- return OK;
- }
- }
- }
-
- /*
- * Move backward to end of the previous word
- */
- while (cls() == 0) {
- if (curwin->w_cursor.col == 0 && LINEEMPTY(curwin->w_cursor.lnum)) {
- break;
- }
- if ((i = dec_cursor()) == -1 || (eol && i == 1)) {
- return OK;
- }
- }
- }
- return OK;
-}
-
-/// Skip a row of characters of the same class.
-///
-/// @return true when end-of-file reached, false otherwise.
-static bool skip_chars(int cclass, int dir)
-{
- while (cls() == cclass) {
- if ((dir == FORWARD ? inc_cursor() : dec_cursor()) == -1) {
- return true;
- }
- }
- return false;
-}
-
-/*
- * Go back to the start of the word or the start of white space
- */
-static void back_in_line(void)
-{
- int sclass; // starting class
-
- sclass = cls();
- for (;;) {
- if (curwin->w_cursor.col == 0) { // stop at start of line
- break;
- }
- dec_cursor();
- if (cls() != sclass) { // stop at start of word
- inc_cursor();
- break;
- }
- }
-}
-
-static void find_first_blank(pos_T *posp)
-{
- int c;
-
- while (decl(posp) != -1) {
- c = gchar_pos(posp);
- if (!ascii_iswhite(c)) {
- incl(posp);
- break;
- }
- }
-}
-
-/// Skip count/2 sentences and count/2 separating white spaces.
-///
-/// @param at_start_sent cursor is at start of sentence
-static void findsent_forward(long count, bool at_start_sent)
-{
- while (count--) {
- findsent(FORWARD, 1L);
- if (at_start_sent) {
- find_first_blank(&curwin->w_cursor);
- }
- if (count == 0 || at_start_sent) {
- decl(&curwin->w_cursor);
- }
- at_start_sent = !at_start_sent;
- }
-}
-
-/// Find word under cursor, cursor at end.
-/// Used while an operator is pending, and in Visual mode.
-///
-/// @param include TRUE: include word and white space
-/// @param bigword FALSE == word, TRUE == WORD
-int current_word(oparg_T *oap, long count, int include, int bigword)
-{
- pos_T start_pos;
- pos_T pos;
- bool inclusive = true;
- int include_white = FALSE;
-
- cls_bigword = bigword;
- clearpos(&start_pos);
-
- // Correct cursor when 'selection' is exclusive
- if (VIsual_active && *p_sel == 'e' && lt(VIsual, curwin->w_cursor)) {
- dec_cursor();
- }
-
- /*
- * When Visual mode is not active, or when the VIsual area is only one
- * character, select the word and/or white space under the cursor.
- */
- if (!VIsual_active || equalpos(curwin->w_cursor, VIsual)) {
- /*
- * Go to start of current word or white space.
- */
- back_in_line();
- start_pos = curwin->w_cursor;
-
- /*
- * If the start is on white space, and white space should be included
- * (" word"), or start is not on white space, and white space should
- * not be included ("word"), find end of word.
- */
- if ((cls() == 0) == include) {
- if (end_word(1L, bigword, TRUE, TRUE) == FAIL) {
- return FAIL;
- }
- } else {
- /*
- * If the start is not on white space, and white space should be
- * included ("word "), or start is on white space and white
- * space should not be included (" "), find start of word.
- * If we end up in the first column of the next line (single char
- * word) back up to end of the line.
- */
- fwd_word(1L, bigword, TRUE);
- if (curwin->w_cursor.col == 0) {
- decl(&curwin->w_cursor);
- } else {
- oneleft();
- }
-
- if (include) {
- include_white = TRUE;
- }
- }
-
- if (VIsual_active) {
- // should do something when inclusive == false !
- VIsual = start_pos;
- redraw_curbuf_later(INVERTED); // update the inversion
- } else {
- oap->start = start_pos;
- oap->motion_type = kMTCharWise;
- }
- count--;
- }
-
- /*
- * When count is still > 0, extend with more objects.
- */
- while (count > 0) {
- inclusive = true;
- if (VIsual_active && lt(curwin->w_cursor, VIsual)) {
- /*
- * In Visual mode, with cursor at start: move cursor back.
- */
- if (decl(&curwin->w_cursor) == -1) {
- return FAIL;
- }
- if (include != (cls() != 0)) {
- if (bck_word(1L, bigword, TRUE) == FAIL) {
- return FAIL;
- }
- } else {
- if (bckend_word(1L, bigword, true) == FAIL) {
- return FAIL;
- }
- (void)incl(&curwin->w_cursor);
- }
- } else {
- /*
- * Move cursor forward one word and/or white area.
- */
- if (incl(&curwin->w_cursor) == -1) {
- return FAIL;
- }
- if (include != (cls() == 0)) {
- if (fwd_word(1L, bigword, TRUE) == FAIL && count > 1) {
- return FAIL;
- }
- /*
- * If end is just past a new-line, we don't want to include
- * the first character on the line.
- * Put cursor on last char of white.
- */
- if (oneleft() == FAIL) {
- inclusive = false;
- }
- } else {
- if (end_word(1L, bigword, TRUE, TRUE) == FAIL) {
- return FAIL;
- }
- }
- }
- count--;
- }
-
- if (include_white && (cls() != 0
- || (curwin->w_cursor.col == 0 && !inclusive))) {
- /*
- * If we don't include white space at the end, move the start
- * to include some white space there. This makes "daw" work
- * better on the last word in a sentence (and "2daw" on last-but-one
- * word). Also when "2daw" deletes "word." at the end of the line
- * (cursor is at start of next line).
- * But don't delete white space at start of line (indent).
- */
- pos = curwin->w_cursor; // save cursor position
- curwin->w_cursor = start_pos;
- if (oneleft() == OK) {
- back_in_line();
- if (cls() == 0 && curwin->w_cursor.col > 0) {
- if (VIsual_active) {
- VIsual = curwin->w_cursor;
- } else {
- oap->start = curwin->w_cursor;
- }
- }
- }
- curwin->w_cursor = pos; // put cursor back at end
- }
-
- if (VIsual_active) {
- if (*p_sel == 'e' && inclusive && ltoreq(VIsual, curwin->w_cursor)) {
- inc_cursor();
- }
- if (VIsual_mode == 'V') {
- VIsual_mode = 'v';
- redraw_cmdline = true; // show mode later
- }
- } else {
- oap->inclusive = inclusive;
- }
-
- return OK;
-}
-
-/*
- * Find sentence(s) under the cursor, cursor at end.
- * When Visual active, extend it by one or more sentences.
- */
-int current_sent(oparg_T *oap, long count, int include)
-{
- pos_T start_pos;
- pos_T pos;
- bool start_blank;
- int c;
- bool at_start_sent;
- long ncount;
-
- start_pos = curwin->w_cursor;
- pos = start_pos;
- findsent(FORWARD, 1L); // Find start of next sentence.
-
- /*
- * When the Visual area is bigger than one character: Extend it.
- */
- if (VIsual_active && !equalpos(start_pos, VIsual)) {
-extend:
- if (lt(start_pos, VIsual)) {
- /*
- * Cursor at start of Visual area.
- * Find out where we are:
- * - in the white space before a sentence
- * - in a sentence or just after it
- * - at the start of a sentence
- */
- at_start_sent = true;
- decl(&pos);
- while (lt(pos, curwin->w_cursor)) {
- c = gchar_pos(&pos);
- if (!ascii_iswhite(c)) {
- at_start_sent = false;
- break;
- }
- incl(&pos);
- }
- if (!at_start_sent) {
- findsent(BACKWARD, 1L);
- if (equalpos(curwin->w_cursor, start_pos)) {
- at_start_sent = true; // exactly at start of sentence
- } else {
- // inside a sentence, go to its end (start of next)
- findsent(FORWARD, 1L);
- }
- }
- if (include) { // "as" gets twice as much as "is"
- count *= 2;
- }
- while (count--) {
- if (at_start_sent) {
- find_first_blank(&curwin->w_cursor);
- }
- c = gchar_cursor();
- if (!at_start_sent || (!include && !ascii_iswhite(c))) {
- findsent(BACKWARD, 1L);
- }
- at_start_sent = !at_start_sent;
- }
- } else {
- /*
- * Cursor at end of Visual area.
- * Find out where we are:
- * - just before a sentence
- * - just before or in the white space before a sentence
- * - in a sentence
- */
- incl(&pos);
- at_start_sent = true;
- if (!equalpos(pos, curwin->w_cursor)) { // not just before a sentence
- at_start_sent = false;
- while (lt(pos, curwin->w_cursor)) {
- c = gchar_pos(&pos);
- if (!ascii_iswhite(c)) {
- at_start_sent = true;
- break;
- }
- incl(&pos);
- }
- if (at_start_sent) { // in the sentence
- findsent(BACKWARD, 1L);
- } else { // in/before white before a sentence
- curwin->w_cursor = start_pos;
- }
- }
-
- if (include) { // "as" gets twice as much as "is"
- count *= 2;
- }
- findsent_forward(count, at_start_sent);
- if (*p_sel == 'e') {
- ++curwin->w_cursor.col;
- }
- }
- return OK;
- }
-
- /*
- * If the cursor started on a blank, check if it is just before the start
- * of the next sentence.
- */
- while (c = gchar_pos(&pos), ascii_iswhite(c)) {
- incl(&pos);
- }
- if (equalpos(pos, curwin->w_cursor)) {
- start_blank = true;
- find_first_blank(&start_pos); // go back to first blank
- } else {
- start_blank = false;
- findsent(BACKWARD, 1L);
- start_pos = curwin->w_cursor;
- }
- if (include) {
- ncount = count * 2;
- } else {
- ncount = count;
- if (start_blank) {
- ncount--;
- }
- }
- if (ncount > 0) {
- findsent_forward(ncount, true);
- } else {
- decl(&curwin->w_cursor);
- }
-
- if (include) {
- /*
- * If the blank in front of the sentence is included, exclude the
- * blanks at the end of the sentence, go back to the first blank.
- * If there are no trailing blanks, try to include leading blanks.
- */
- if (start_blank) {
- find_first_blank(&curwin->w_cursor);
- c = gchar_pos(&curwin->w_cursor);
- if (ascii_iswhite(c)) {
- decl(&curwin->w_cursor);
- }
- } else if (c = gchar_cursor(), !ascii_iswhite(c)) {
- find_first_blank(&start_pos);
- }
- }
-
- if (VIsual_active) {
- // Avoid getting stuck with "is" on a single space before a sentence.
- if (equalpos(start_pos, curwin->w_cursor)) {
- goto extend;
- }
- if (*p_sel == 'e') {
- ++curwin->w_cursor.col;
- }
- VIsual = start_pos;
- VIsual_mode = 'v';
- redraw_cmdline = true; // show mode later
- redraw_curbuf_later(INVERTED); // update the inversion
- } else {
- // include a newline after the sentence, if there is one
- if (incl(&curwin->w_cursor) == -1) {
- oap->inclusive = true;
- } else {
- oap->inclusive = false;
- }
- oap->start = start_pos;
- oap->motion_type = kMTCharWise;
- }
- return OK;
-}
-
-/// Find block under the cursor, cursor at end.
-/// "what" and "other" are two matching parenthesis/brace/etc.
-///
-/// @param include TRUE == include white space
-/// @param what '(', '{', etc.
-/// @param other ')', '}', etc.
-int current_block(oparg_T *oap, long count, int include, int what, int other)
-{
- pos_T old_pos;
- pos_T *pos = NULL;
- pos_T start_pos;
- pos_T *end_pos;
- pos_T old_start, old_end;
- char *save_cpo;
- bool sol = false; // '{' at start of line
-
- old_pos = curwin->w_cursor;
- old_end = curwin->w_cursor; // remember where we started
- old_start = old_end;
-
- /*
- * If we start on '(', '{', ')', '}', etc., use the whole block inclusive.
- */
- if (!VIsual_active || equalpos(VIsual, curwin->w_cursor)) {
- setpcmark();
- if (what == '{') { // ignore indent
- while (inindent(1)) {
- if (inc_cursor() != 0) {
- break;
- }
- }
- }
- if (gchar_cursor() == what) {
- // cursor on '(' or '{', move cursor just after it
- ++curwin->w_cursor.col;
- }
- } else if (lt(VIsual, curwin->w_cursor)) {
- old_start = VIsual;
- curwin->w_cursor = VIsual; // cursor at low end of Visual
- } else {
- old_end = VIsual;
- }
-
- // Search backwards for unclosed '(', '{', etc..
- // Put this position in start_pos.
- // Ignore quotes here. Keep the "M" flag in 'cpo', as that is what the
- // user wants.
- save_cpo = p_cpo;
- p_cpo = vim_strchr(p_cpo, CPO_MATCHBSL) != NULL ? "%M" : "%";
- if ((pos = findmatch(NULL, what)) != NULL) {
- while (count-- > 0) {
- if ((pos = findmatch(NULL, what)) == NULL) {
- break;
- }
- curwin->w_cursor = *pos;
- start_pos = *pos; // the findmatch for end_pos will overwrite *pos
- }
- } else {
- while (count-- > 0) {
- if ((pos = findmatchlimit(NULL, what, FM_FORWARD, 0)) == NULL) {
- break;
- }
- curwin->w_cursor = *pos;
- start_pos = *pos; // the findmatch for end_pos will overwrite *pos
- }
- }
- p_cpo = save_cpo;
-
- /*
- * Search for matching ')', '}', etc.
- * Put this position in curwin->w_cursor.
- */
- if (pos == NULL || (end_pos = findmatch(NULL, other)) == NULL) {
- curwin->w_cursor = old_pos;
- return FAIL;
- }
- curwin->w_cursor = *end_pos;
-
- // Try to exclude the '(', '{', ')', '}', etc. when "include" is FALSE.
- // If the ending '}', ')' or ']' is only preceded by indent, skip that
- // indent. But only if the resulting area is not smaller than what we
- // started with.
- while (!include) {
- incl(&start_pos);
- sol = (curwin->w_cursor.col == 0);
- decl(&curwin->w_cursor);
- while (inindent(1)) {
- sol = true;
- if (decl(&curwin->w_cursor) != 0) {
- break;
- }
- }
-
- // In Visual mode, when the resulting area is not bigger than what we
- // started with, extend it to the next block, and then exclude again.
- // Don't try to expand the area if the area is empty.
- if (!lt(start_pos, old_start) && !lt(old_end, curwin->w_cursor)
- && !equalpos(start_pos, curwin->w_cursor)
- && VIsual_active) {
- curwin->w_cursor = old_start;
- decl(&curwin->w_cursor);
- if ((pos = findmatch(NULL, what)) == NULL) {
- curwin->w_cursor = old_pos;
- return FAIL;
- }
- start_pos = *pos;
- curwin->w_cursor = *pos;
- if ((end_pos = findmatch(NULL, other)) == NULL) {
- curwin->w_cursor = old_pos;
- return FAIL;
- }
- curwin->w_cursor = *end_pos;
- } else {
- break;
- }
- }
-
- if (VIsual_active) {
- if (*p_sel == 'e') {
- inc(&curwin->w_cursor);
- }
- if (sol && gchar_cursor() != NUL) {
- inc(&curwin->w_cursor); // include the line break
- }
- VIsual = start_pos;
- VIsual_mode = 'v';
- redraw_curbuf_later(INVERTED); // update the inversion
- showmode();
- } else {
- oap->start = start_pos;
- oap->motion_type = kMTCharWise;
- oap->inclusive = false;
- if (sol) {
- incl(&curwin->w_cursor);
- } else if (ltoreq(start_pos, curwin->w_cursor)) {
- // Include the character under the cursor.
- oap->inclusive = true;
- } else {
- // End is before the start (no text in between <>, [], etc.): don't
- // operate on any text.
- curwin->w_cursor = start_pos;
- }
- }
-
- return OK;
-}
-
-/// @param end_tag when true, return true if the cursor is on "</aaa>".
-///
-/// @return true if the cursor is on a "<aaa>" tag. Ignore "<aaa/>".
-static bool in_html_tag(bool end_tag)
-{
- char_u *line = get_cursor_line_ptr();
- char_u *p;
- int c;
- int lc = NUL;
- pos_T pos;
-
- for (p = line + curwin->w_cursor.col; p > line;) {
- if (*p == '<') { // find '<' under/before cursor
- break;
- }
- MB_PTR_BACK(line, p);
- if (*p == '>') { // find '>' before cursor
- break;
- }
- }
- if (*p != '<') {
- return false;
- }
-
- pos.lnum = curwin->w_cursor.lnum;
- pos.col = (colnr_T)(p - line);
-
- MB_PTR_ADV(p);
- if (end_tag) {
- // check that there is a '/' after the '<'
- return *p == '/';
- }
-
- // check that there is no '/' after the '<'
- if (*p == '/') {
- return false;
- }
-
- // check that the matching '>' is not preceded by '/'
- for (;;) {
- if (inc(&pos) < 0) {
- return false;
- }
- c = *ml_get_pos(&pos);
- if (c == '>') {
- break;
- }
- lc = c;
- }
- return lc != '/';
-}
-
-/// Find tag block under the cursor, cursor at end.
-///
-/// @param include true == include white space
-int current_tagblock(oparg_T *oap, long count_arg, bool include)
-{
- long count = count_arg;
- pos_T old_pos;
- pos_T start_pos;
- pos_T end_pos;
- pos_T old_start, old_end;
- char_u *p;
- char_u *cp;
- int len;
- bool do_include = include;
- bool save_p_ws = p_ws;
- int retval = FAIL;
- int is_inclusive = true;
-
- p_ws = false;
-
- old_pos = curwin->w_cursor;
- old_end = curwin->w_cursor; // remember where we started
- old_start = old_end;
- if (!VIsual_active || *p_sel == 'e') {
- decl(&old_end); // old_end is inclusive
- }
- /*
- * If we start on "<aaa>" select that block.
- */
- if (!VIsual_active || equalpos(VIsual, curwin->w_cursor)) {
- setpcmark();
-
- // ignore indent
- while (inindent(1)) {
- if (inc_cursor() != 0) {
- break;
- }
- }
-
- if (in_html_tag(false)) {
- // cursor on start tag, move to its '>'
- while (*get_cursor_pos_ptr() != '>') {
- if (inc_cursor() < 0) {
- break;
- }
- }
- } else if (in_html_tag(true)) {
- // cursor on end tag, move to just before it
- while (*get_cursor_pos_ptr() != '<') {
- if (dec_cursor() < 0) {
- break;
- }
- }
- dec_cursor();
- old_end = curwin->w_cursor;
- }
- } else if (lt(VIsual, curwin->w_cursor)) {
- old_start = VIsual;
- curwin->w_cursor = VIsual; // cursor at low end of Visual
- } else {
- old_end = VIsual;
- }
-
-again:
- /*
- * Search backwards for unclosed "<aaa>".
- * Put this position in start_pos.
- */
- for (long n = 0; n < count; n++) {
- if (do_searchpair("<[^ \t>/!]\\+\\%(\\_s\\_[^>]\\{-}[^/]>\\|$\\|\\_s\\=>\\)",
- "",
- "</[^>]*>", BACKWARD, NULL, 0,
- NULL, (linenr_T)0, 0L) <= 0) {
- curwin->w_cursor = old_pos;
- goto theend;
- }
- }
- start_pos = curwin->w_cursor;
-
- /*
- * Search for matching "</aaa>". First isolate the "aaa".
- */
- inc_cursor();
- p = get_cursor_pos_ptr();
- for (cp = p;
- *cp != NUL && *cp != '>' && !ascii_iswhite(*cp);
- MB_PTR_ADV(cp)) {}
- len = (int)(cp - p);
- if (len == 0) {
- curwin->w_cursor = old_pos;
- goto theend;
- }
- const size_t spat_len = (size_t)len + 39;
- char *const spat = xmalloc(spat_len);
- const size_t epat_len = (size_t)len + 9;
- char *const epat = xmalloc(epat_len);
- snprintf(spat, spat_len,
- "<%.*s\\>\\%%(\\_s\\_[^>]\\{-}\\_[^/]>\\|\\_s\\?>\\)\\c", len, p);
- snprintf(epat, epat_len, "</%.*s>\\c", len, p);
-
- const int r = (int)do_searchpair(spat, "", epat, FORWARD, NULL, 0, NULL, (linenr_T)0, 0L);
-
- xfree(spat);
- xfree(epat);
-
- if (r < 1 || lt(curwin->w_cursor, old_end)) {
- // Can't find other end or it's before the previous end. Could be a
- // HTML tag that doesn't have a matching end. Search backwards for
- // another starting tag.
- count = 1;
- curwin->w_cursor = start_pos;
- goto again;
- }
-
- if (do_include) {
- // Include up to the '>'.
- while (*get_cursor_pos_ptr() != '>') {
- if (inc_cursor() < 0) {
- break;
- }
- }
- } else {
- char_u *c = get_cursor_pos_ptr();
- // Exclude the '<' of the end tag.
- // If the closing tag is on new line, do not decrement cursor, but make
- // operation exclusive, so that the linefeed will be selected
- if (*c == '<' && !VIsual_active && curwin->w_cursor.col == 0) {
- // do not decrement cursor
- is_inclusive = false;
- } else if (*c == '<') {
- dec_cursor();
- }
- }
- end_pos = curwin->w_cursor;
-
- if (!do_include) {
- // Exclude the start tag.
- curwin->w_cursor = start_pos;
- while (inc_cursor() >= 0) {
- if (*get_cursor_pos_ptr() == '>') {
- inc_cursor();
- start_pos = curwin->w_cursor;
- break;
- }
- }
- curwin->w_cursor = end_pos;
-
- // If we are in Visual mode and now have the same text as before set
- // "do_include" and try again.
- if (VIsual_active
- && equalpos(start_pos, old_start)
- && equalpos(end_pos, old_end)) {
- do_include = true;
- curwin->w_cursor = old_start;
- count = count_arg;
- goto again;
- }
- }
-
- if (VIsual_active) {
- // If the end is before the start there is no text between tags, select
- // the char under the cursor.
- if (lt(end_pos, start_pos)) {
- curwin->w_cursor = start_pos;
- } else if (*p_sel == 'e') {
- inc_cursor();
- }
- VIsual = start_pos;
- VIsual_mode = 'v';
- redraw_curbuf_later(INVERTED); // update the inversion
- showmode();
- } else {
- oap->start = start_pos;
- oap->motion_type = kMTCharWise;
- if (lt(end_pos, start_pos)) {
- // End is before the start: there is no text between tags; operate
- // on an empty area.
- curwin->w_cursor = start_pos;
- oap->inclusive = false;
- } else {
- oap->inclusive = is_inclusive;
- }
- }
- retval = OK;
-
-theend:
- p_ws = save_p_ws;
- return retval;
-}
-
-/// @param include TRUE == include white space
-/// @param type 'p' for paragraph, 'S' for section
-int current_par(oparg_T *oap, long count, int include, int type)
-{
- linenr_T start_lnum;
- linenr_T end_lnum;
- int white_in_front;
- int dir;
- int start_is_white;
- int prev_start_is_white;
- int retval = OK;
- int do_white = FALSE;
- int t;
- int i;
-
- if (type == 'S') { // not implemented yet
- return FAIL;
- }
-
- start_lnum = curwin->w_cursor.lnum;
-
- /*
- * When visual area is more than one line: extend it.
- */
- if (VIsual_active && start_lnum != VIsual.lnum) {
-extend:
- if (start_lnum < VIsual.lnum) {
- dir = BACKWARD;
- } else {
- dir = FORWARD;
- }
- for (i = (int)count; --i >= 0;) {
- if (start_lnum ==
- (dir == BACKWARD ? 1 : curbuf->b_ml.ml_line_count)) {
- retval = FAIL;
- break;
- }
-
- prev_start_is_white = -1;
- for (t = 0; t < 2; ++t) {
- start_lnum += dir;
- start_is_white = linewhite(start_lnum);
- if (prev_start_is_white == start_is_white) {
- start_lnum -= dir;
- break;
- }
- for (;;) {
- if (start_lnum == (dir == BACKWARD
- ? 1 : curbuf->b_ml.ml_line_count)) {
- break;
- }
- if (start_is_white != linewhite(start_lnum + dir)
- || (!start_is_white
- && startPS(start_lnum + (dir > 0
- ? 1 : 0), 0, 0))) {
- break;
- }
- start_lnum += dir;
- }
- if (!include) {
- break;
- }
- if (start_lnum == (dir == BACKWARD
- ? 1 : curbuf->b_ml.ml_line_count)) {
- break;
- }
- prev_start_is_white = start_is_white;
- }
- }
- curwin->w_cursor.lnum = start_lnum;
- curwin->w_cursor.col = 0;
- return retval;
- }
-
- /*
- * First move back to the start_lnum of the paragraph or white lines
- */
- white_in_front = linewhite(start_lnum);
- while (start_lnum > 1) {
- if (white_in_front) { // stop at first white line
- if (!linewhite(start_lnum - 1)) {
- break;
- }
- } else { // stop at first non-white line of start of paragraph
- if (linewhite(start_lnum - 1) || startPS(start_lnum, 0, 0)) {
- break;
- }
- }
- start_lnum--;
- }
-
- /*
- * Move past the end of any white lines.
- */
- end_lnum = start_lnum;
- while (end_lnum <= curbuf->b_ml.ml_line_count && linewhite(end_lnum)) {
- end_lnum++;
- }
-
- end_lnum--;
- i = (int)count;
- if (!include && white_in_front) {
- i--;
- }
- while (i--) {
- if (end_lnum == curbuf->b_ml.ml_line_count) {
- return FAIL;
- }
-
- if (!include) {
- do_white = linewhite(end_lnum + 1);
- }
-
- if (include || !do_white) {
- end_lnum++;
- // skip to end of paragraph
- while (end_lnum < curbuf->b_ml.ml_line_count
- && !linewhite(end_lnum + 1)
- && !startPS(end_lnum + 1, 0, 0)) {
- end_lnum++;
- }
- }
-
- if (i == 0 && white_in_front && include) {
- break;
- }
-
- /*
- * skip to end of white lines after paragraph
- */
- if (include || do_white) {
- while (end_lnum < curbuf->b_ml.ml_line_count
- && linewhite(end_lnum + 1)) {
- end_lnum++;
- }
- }
- }
-
- /*
- * If there are no empty lines at the end, try to find some empty lines at
- * the start (unless that has been done already).
- */
- if (!white_in_front && !linewhite(end_lnum) && include) {
- while (start_lnum > 1 && linewhite(start_lnum - 1)) {
- start_lnum--;
- }
- }
-
- if (VIsual_active) {
- // Problem: when doing "Vipipip" nothing happens in a single white
- // line, we get stuck there. Trap this here.
- if (VIsual_mode == 'V' && start_lnum == curwin->w_cursor.lnum) {
- goto extend;
- }
- if (VIsual.lnum != start_lnum) {
- VIsual.lnum = start_lnum;
- VIsual.col = 0;
- }
- VIsual_mode = 'V';
- redraw_curbuf_later(INVERTED); // update the inversion
- showmode();
- } else {
- oap->start.lnum = start_lnum;
- oap->start.col = 0;
- oap->motion_type = kMTLineWise;
- }
- curwin->w_cursor.lnum = end_lnum;
- curwin->w_cursor.col = 0;
-
- return OK;
-}
-
-/// Search quote char from string line[col].
-/// Quote character escaped by one of the characters in "escape" is not counted
-/// as a quote.
-///
-/// @param escape escape characters, can be NULL
-///
-/// @return column number of "quotechar" or -1 when not found.
-static int find_next_quote(char_u *line, int col, int quotechar, char_u *escape)
-{
- int c;
-
- for (;;) {
- c = line[col];
- if (c == NUL) {
- return -1;
- } else if (escape != NULL && vim_strchr((char *)escape, c)) {
- col++;
- if (line[col] == NUL) {
- return -1;
- }
- } else if (c == quotechar) {
- break;
- }
- col += utfc_ptr2len((char *)line + col);
- }
- return col;
-}
-
-/// Search backwards in "line" from column "col_start" to find "quotechar".
-/// Quote character escaped by one of the characters in "escape" is not counted
-/// as a quote.
-///
-/// @param escape escape characters, can be NULL
-///
-/// @return the found column or zero.
-static int find_prev_quote(char_u *line, int col_start, int quotechar, char_u *escape)
-{
- int n;
-
- while (col_start > 0) {
- col_start--;
- col_start -= utf_head_off(line, line + col_start);
- n = 0;
- if (escape != NULL) {
- while (col_start - n > 0 && vim_strchr((char *)escape,
- line[col_start - n - 1]) != NULL) {
- n++;
- }
- }
- if (n & 1) {
- col_start -= n; // uneven number of escape chars, skip it
- } else if (line[col_start] == quotechar) {
- break;
- }
- }
- return col_start;
-}
-
-/// Find quote under the cursor, cursor at end.
-///
-/// @param include true == include quote char
-/// @param quotechar Quote character
-///
-/// @return true if found, else false.
-bool current_quote(oparg_T *oap, long count, bool include, int quotechar)
- FUNC_ATTR_NONNULL_ALL
-{
- char_u *line = get_cursor_line_ptr();
- int col_end;
- int col_start = curwin->w_cursor.col;
- bool inclusive = false;
- bool vis_empty = true; // Visual selection <= 1 char
- bool vis_bef_curs = false; // Visual starts before cursor
- bool did_exclusive_adj = false; // adjusted pos for 'selection'
- bool inside_quotes = false; // Looks like "i'" done before
- bool selected_quote = false; // Has quote inside selection
- int i;
- bool restore_vis_bef = false; // resotre VIsual on abort
-
- // When 'selection' is "exclusive" move the cursor to where it would be
- // with 'selection' "inclusive", so that the logic is the same for both.
- // The cursor then is moved forward after adjusting the area.
- if (VIsual_active) {
- // this only works within one line
- if (VIsual.lnum != curwin->w_cursor.lnum) {
- return false;
- }
-
- vis_bef_curs = lt(VIsual, curwin->w_cursor);
- vis_empty = equalpos(VIsual, curwin->w_cursor);
- if (*p_sel == 'e') {
- if (vis_bef_curs) {
- dec_cursor();
- did_exclusive_adj = true;
- } else if (!vis_empty) {
- dec(&VIsual);
- did_exclusive_adj = true;
- }
- vis_empty = equalpos(VIsual, curwin->w_cursor);
- if (!vis_bef_curs && !vis_empty) {
- // VIsual needs to be start of Visual selection.
- pos_T t = curwin->w_cursor;
-
- curwin->w_cursor = VIsual;
- VIsual = t;
- vis_bef_curs = true;
- restore_vis_bef = true;
- }
- }
- }
-
- if (!vis_empty) {
- // Check if the existing selection exactly spans the text inside
- // quotes.
- if (vis_bef_curs) {
- inside_quotes = VIsual.col > 0
- && line[VIsual.col - 1] == quotechar
- && line[curwin->w_cursor.col] != NUL
- && line[curwin->w_cursor.col + 1] == quotechar;
- i = VIsual.col;
- col_end = curwin->w_cursor.col;
- } else {
- inside_quotes = curwin->w_cursor.col > 0
- && line[curwin->w_cursor.col - 1] == quotechar
- && line[VIsual.col] != NUL
- && line[VIsual.col + 1] == quotechar;
- i = curwin->w_cursor.col;
- col_end = VIsual.col;
- }
-
- // Find out if we have a quote in the selection.
- while (i <= col_end) {
- // check for going over the end of the line, which can happen if
- // the line was changed after the Visual area was selected.
- if (line[i] == NUL) {
- break;
- }
- if (line[i++] == quotechar) {
- selected_quote = true;
- break;
- }
- }
- }
-
- if (!vis_empty && line[col_start] == quotechar) {
- // Already selecting something and on a quote character. Find the
- // next quoted string.
- if (vis_bef_curs) {
- // Assume we are on a closing quote: move to after the next
- // opening quote.
- col_start = find_next_quote(line, col_start + 1, quotechar, NULL);
- if (col_start < 0) {
- goto abort_search;
- }
- col_end = find_next_quote(line, col_start + 1, quotechar,
- curbuf->b_p_qe);
- if (col_end < 0) {
- // We were on a starting quote perhaps?
- col_end = col_start;
- col_start = curwin->w_cursor.col;
- }
- } else {
- col_end = find_prev_quote(line, col_start, quotechar, NULL);
- if (line[col_end] != quotechar) {
- goto abort_search;
- }
- col_start = find_prev_quote(line, col_end, quotechar,
- curbuf->b_p_qe);
- if (line[col_start] != quotechar) {
- // We were on an ending quote perhaps?
- col_start = col_end;
- col_end = curwin->w_cursor.col;
- }
- }
- } else if (line[col_start] == quotechar || !vis_empty) {
- int first_col = col_start;
-
- if (!vis_empty) {
- if (vis_bef_curs) {
- first_col = find_next_quote(line, col_start, quotechar, NULL);
- } else {
- first_col = find_prev_quote(line, col_start, quotechar, NULL);
- }
- }
- // The cursor is on a quote, we don't know if it's the opening or
- // closing quote. Search from the start of the line to find out.
- // Also do this when there is a Visual area, a' may leave the cursor
- // in between two strings.
- col_start = 0;
- for (;;) {
- // Find open quote character.
- col_start = find_next_quote(line, col_start, quotechar, NULL);
- if (col_start < 0 || col_start > first_col) {
- goto abort_search;
- }
- // Find close quote character.
- col_end = find_next_quote(line, col_start + 1, quotechar,
- curbuf->b_p_qe);
- if (col_end < 0) {
- goto abort_search;
- }
- // If is cursor between start and end quote character, it is
- // target text object.
- if (col_start <= first_col && first_col <= col_end) {
- break;
- }
- col_start = col_end + 1;
- }
- } else {
- // Search backward for a starting quote.
- col_start = find_prev_quote(line, col_start, quotechar, curbuf->b_p_qe);
- if (line[col_start] != quotechar) {
- // No quote before the cursor, look after the cursor.
- col_start = find_next_quote(line, col_start, quotechar, NULL);
- if (col_start < 0) {
- goto abort_search;
- }
- }
-
- // Find close quote character.
- col_end = find_next_quote(line, col_start + 1, quotechar,
- curbuf->b_p_qe);
- if (col_end < 0) {
- goto abort_search;
- }
- }
-
- // When "include" is true, include spaces after closing quote or before
- // the starting quote.
- if (include) {
- if (ascii_iswhite(line[col_end + 1])) {
- while (ascii_iswhite(line[col_end + 1])) {
- col_end++;
- }
- } else {
- while (col_start > 0 && ascii_iswhite(line[col_start - 1])) {
- col_start--;
- }
- }
- }
-
- // Set start position. After vi" another i" must include the ".
- // For v2i" include the quotes.
- if (!include && count < 2 && (vis_empty || !inside_quotes)) {
- col_start++;
- }
- curwin->w_cursor.col = col_start;
- if (VIsual_active) {
- // Set the start of the Visual area when the Visual area was empty, we
- // were just inside quotes or the Visual area didn't start at a quote
- // and didn't include a quote.
- if (vis_empty
- || (vis_bef_curs
- && !selected_quote
- && (inside_quotes
- || (line[VIsual.col] != quotechar
- && (VIsual.col == 0
- || line[VIsual.col - 1] != quotechar))))) {
- VIsual = curwin->w_cursor;
- redraw_curbuf_later(INVERTED);
- }
- } else {
- oap->start = curwin->w_cursor;
- oap->motion_type = kMTCharWise;
- }
-
- // Set end position.
- curwin->w_cursor.col = col_end;
- if ((include || count > 1
- // After vi" another i" must include the ".
- || (!vis_empty && inside_quotes)
- ) && inc_cursor() == 2) {
- inclusive = true;
- }
- if (VIsual_active) {
- if (vis_empty || vis_bef_curs) {
- // decrement cursor when 'selection' is not exclusive
- if (*p_sel != 'e') {
- dec_cursor();
- }
- } else {
- // Cursor is at start of Visual area. Set the end of the Visual
- // area when it was just inside quotes or it didn't end at a
- // quote.
- if (inside_quotes
- || (!selected_quote
- && line[VIsual.col] != quotechar
- && (line[VIsual.col] == NUL
- || line[VIsual.col + 1] != quotechar))) {
- dec_cursor();
- VIsual = curwin->w_cursor;
- }
- curwin->w_cursor.col = col_start;
- }
- if (VIsual_mode == 'V') {
- VIsual_mode = 'v';
- redraw_cmdline = true; // show mode later
- }
- } else {
- // Set inclusive and other oap's flags.
- oap->inclusive = inclusive;
- }
-
- return true;
-
-abort_search:
- if (VIsual_active && *p_sel == 'e') {
- if (did_exclusive_adj) {
- inc_cursor();
- }
- if (restore_vis_bef) {
- pos_T t = curwin->w_cursor;
-
- curwin->w_cursor = VIsual;
- VIsual = t;
- }
- }
- return false;
-}
-
/// Find next search match under cursor, cursor at end.
/// Used while an operator is pending, and in Visual mode.
///
@@ -4389,7 +2576,7 @@ int current_search(long count, bool forward)
may_start_select('c');
setmouse();
- redraw_curbuf_later(INVERTED);
+ redraw_curbuf_later(UPD_INVERTED);
showmode();
return OK;
@@ -4399,7 +2586,7 @@ int current_search(long count, bool forward)
/// If move is true, check from the beginning of the buffer,
/// else from position "cur".
/// "direction" is FORWARD or BACKWARD.
-/// Returns TRUE, FALSE or -1 for failure.
+/// Returns true, false or -1 for failure.
static int is_zero_width(char_u *pattern, int move, pos_T *cur, Direction direction)
{
regmmatch_T regmatch;
@@ -4456,9 +2643,7 @@ static int is_zero_width(char_u *pattern, int move, pos_T *cur, Direction direct
return result;
}
-/*
- * return TRUE if line 'lnum' is empty or has white chars only.
- */
+/// return true if line 'lnum' is empty or has white chars only.
int linewhite(linenr_T lnum)
{
char_u *p;
@@ -4637,7 +2822,7 @@ static void update_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, searchst
}
// "searchcount()" function
-void f_searchcount(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_searchcount(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
pos_T pos = curwin->w_cursor;
char_u *pattern = NULL;
@@ -4869,7 +3054,7 @@ static int fuzzy_match_compute_score(const char_u *const str, const int strSz,
if (currIdx > 0) {
// Camel case
const char_u *p = str;
- int neighbor;
+ int neighbor = ' ';
for (uint32_t sidx = 0; sidx < currIdx; sidx++) {
neighbor = utf_ptr2char((char *)p);
@@ -5287,13 +3472,13 @@ static void do_fuzzymatch(const typval_T *const argvars, typval_T *const rettv,
}
/// "matchfuzzy()" function
-void f_matchfuzzy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_matchfuzzy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
do_fuzzymatch(argvars, rettv, false);
}
/// "matchfuzzypos()" function
-void f_matchfuzzypos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_matchfuzzypos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
do_fuzzymatch(argvars, rettv, true);
}
@@ -5309,7 +3494,7 @@ static char_u *get_line_and_copy(linenr_T lnum, char_u *buf)
}
/// Find identifiers or defines in included files.
-/// If p_ic && (compl_cont_status & CONT_SOL) then ptr must be in lowercase.
+/// If p_ic && compl_status_sol() then ptr must be in lowercase.
///
/// @param ptr pointer to search pattern
/// @param dir direction of expansion
@@ -5351,7 +3536,6 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
int i;
char_u *already = NULL;
char_u *startp = NULL;
- char_u *inc_opt = NULL;
win_T *curwin_save = NULL;
const int l_g_do_tagpreview = g_do_tagpreview;
@@ -5362,9 +3546,9 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
file_line = xmalloc(LSIZE);
if (type != CHECK_PATH && type != FIND_DEFINE
- // when CONT_SOL is set compare "ptr" with the beginning of the line
- // is faster than quote_meta/regcomp/regexec "ptr" -- Acevedo
- && !(compl_cont_status & CONT_SOL)) {
+ // when CONT_SOL is set compare "ptr" with the beginning of the
+ // line is faster than quote_meta/regcomp/regexec "ptr" -- Acevedo
+ && !compl_status_sol()) {
pat = xmalloc(len + 5);
assert(len <= INT_MAX);
sprintf((char *)pat, whole ? "\\<%.*s\\>" : "%.*s", (int)len, ptr);
@@ -5376,22 +3560,22 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
goto fpip_end;
}
}
- inc_opt = (*curbuf->b_p_inc == NUL) ? p_inc : curbuf->b_p_inc;
+ char *inc_opt = (*curbuf->b_p_inc == NUL) ? p_inc : curbuf->b_p_inc;
if (*inc_opt != NUL) {
- incl_regmatch.regprog = vim_regcomp((char *)inc_opt, p_magic ? RE_MAGIC : 0);
+ incl_regmatch.regprog = vim_regcomp(inc_opt, p_magic ? RE_MAGIC : 0);
if (incl_regmatch.regprog == NULL) {
goto fpip_end;
}
- incl_regmatch.rm_ic = FALSE; // don't ignore case in incl. pat.
+ incl_regmatch.rm_ic = false; // don't ignore case in incl. pat.
}
if (type == FIND_DEFINE && (*curbuf->b_p_def != NUL || *p_def != NUL)) {
def_regmatch.regprog = vim_regcomp(*curbuf->b_p_def == NUL
- ? (char *)p_def : (char *)curbuf->b_p_def,
+ ? p_def : curbuf->b_p_def,
p_magic ? RE_MAGIC : 0);
if (def_regmatch.regprog == NULL) {
goto fpip_end;
}
- def_regmatch.rm_ic = FALSE; // don't ignore case in define pat.
+ def_regmatch.rm_ic = false; // don't ignore case in define pat.
}
files = xcalloc((size_t)max_path_depth, sizeof(SearchedFile));
old_files = max_path_depth;
@@ -5412,7 +3596,7 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
char_u *p_fname = (curr_fname == (char_u *)curbuf->b_fname)
? (char_u *)curbuf->b_ffname : curr_fname;
- if (inc_opt != NULL && strstr((char *)inc_opt, "\\zs") != NULL) {
+ if (inc_opt != NULL && strstr(inc_opt, "\\zs") != NULL) {
// Use text from '\zs' to '\ze' (or end) of 'include'.
new_fname = find_file_name_in_path(incl_regmatch.startp[0],
(size_t)(incl_regmatch.endp[0]
@@ -5424,7 +3608,7 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
new_fname = file_name_in_line(incl_regmatch.endp[0], 0,
FNAME_EXP|FNAME_INCL|FNAME_REL, 1L, p_fname, NULL);
}
- already_searched = FALSE;
+ already_searched = false;
if (new_fname != NULL) {
// Check whether we have already searched in this file
for (i = 0;; i++) {
@@ -5482,14 +3666,14 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
if (new_fname != NULL) {
// using "new_fname" is more reliable, e.g., when
// 'includeexpr' is set.
- msg_outtrans_attr(new_fname, HL_ATTR(HLF_D));
+ msg_outtrans_attr((char *)new_fname, HL_ATTR(HLF_D));
} else {
/*
* Isolate the file name.
* Include the surrounding "" or <> if present.
*/
if (inc_opt != NULL
- && strstr((char *)inc_opt, "\\zs") != NULL) {
+ && strstr(inc_opt, "\\zs") != NULL) {
// pattern contains \zs, use the match
p = incl_regmatch.startp[0];
i = (int)(incl_regmatch.endp[0]
@@ -5518,7 +3702,7 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
}
save_char = p[i];
p[i] = NUL;
- msg_outtrans_attr(p, HL_ATTR(HLF_D));
+ msg_outtrans_attr((char *)p, HL_ATTR(HLF_D));
p[i] = save_char;
}
@@ -5544,7 +3728,7 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
bigger[i].fp = NULL;
bigger[i].name = NULL;
bigger[i].lnum = 0;
- bigger[i].matched = FALSE;
+ bigger[i].matched = false;
}
for (i = old_files; i < max_path_depth; i++) {
bigger[i + max_path_depth] = files[i];
@@ -5565,7 +3749,7 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
}
files[depth].name = curr_fname = new_fname;
files[depth].lnum = 0;
- files[depth].matched = FALSE;
+ files[depth].matched = false;
if (action == ACTION_EXPAND) {
msg_hist_off = true; // reset in msg_trunc_attr()
vim_snprintf((char *)IObuff, IOSIZE,
@@ -5604,8 +3788,7 @@ search_line:
* define and this line didn't match define_prog above.
*/
if (def_regmatch.regprog == NULL || define_matched) {
- if (define_matched
- || (compl_cont_status & CONT_SOL)) {
+ if (define_matched || compl_status_sol()) {
// compare the first "len" chars from "ptr"
startp = (char_u *)skipwhite((char *)p);
if (p_ic) {
@@ -5640,7 +3823,7 @@ search_line:
p = (char_u *)skipwhite((char *)line);
if (matched
|| (p[0] == '/' && p[1] == '*') || p[0] == '*') {
- for (p = line; *p && p < startp; ++p) {
+ for (p = line; *p && p < startp; p++) {
if (matched
&& p[0] == '/'
&& (p[1] == '*' || p[1] == '/')) {
@@ -5671,8 +3854,8 @@ search_line:
}
found = true;
aux = p = startp;
- if (compl_cont_status & CONT_ADDING) {
- p += compl_length;
+ if (compl_status_adding()) {
+ p += ins_compl_len();
if (vim_iswordp(p)) {
goto exit_matched;
}
@@ -5681,7 +3864,7 @@ search_line:
p = find_word_end(p);
i = (int)(p - aux);
- if ((compl_cont_status & CONT_ADDING) && i == compl_length) {
+ if (compl_status_adding() && i == ins_compl_len()) {
// IOSIZE > compl_length, so the STRNCPY works
STRNCPY(IObuff, aux, i);
@@ -5728,7 +3911,7 @@ search_line:
IObuff[i] = NUL;
aux = IObuff;
- if (i == compl_length) {
+ if (i == ins_compl_len()) {
goto exit_matched;
}
}
@@ -5820,14 +4003,14 @@ search_line:
}
if (action != ACTION_SHOW) {
curwin->w_cursor.col = (colnr_T)(startp - line);
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
}
if (l_g_do_tagpreview != 0
&& curwin != curwin_save && win_valid(curwin_save)) {
// Return cursor to where we were
validate_cursor();
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
win_enter(curwin_save, true);
}
break;
@@ -5838,7 +4021,7 @@ exit_matched:
// are not at the end of it already
if (def_regmatch.regprog == NULL
&& action == ACTION_EXPAND
- && !(compl_cont_status & CONT_SOL)
+ && !compl_status_sol()
&& *startp != NUL
&& *(p = startp + utfc_ptr2len((char *)startp)) != NUL) {
goto search_line;
@@ -5963,7 +4146,7 @@ static void show_pat_in_path(char_u *line, int type, bool did_show, int action,
msg_puts_attr((const char *)IObuff, HL_ATTR(HLF_N));
msg_puts(" ");
}
- msg_prt_line(line, FALSE);
+ msg_prt_line(line, false);
ui_flush(); // show one line at a time
// Definition continues until line that doesn't end with '\'
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index 0927473be0..927d1fa181 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -1477,7 +1477,7 @@ static char *shada_filename(const char *file)
// because various expansions must have already be done by the shell.
// If shell is not performing them then they should be done in main.c
// where arguments are parsed, *not here*.
- expand_env((char_u *)file, &(NameBuff[0]), MAXPATHL);
+ expand_env((char *)file, &(NameBuff[0]), MAXPATHL);
file = (const char *)&(NameBuff[0]);
}
}
@@ -3023,7 +3023,7 @@ shada_write_file_nomerge: {}
if (tail != fname) {
const char tail_save = *tail;
*tail = NUL;
- if (!os_isdir((char_u *)fname)) {
+ if (!os_isdir(fname)) {
int ret;
char *failed_dir;
if ((ret = os_mkdir_recurse(fname, 0700, &failed_dir)) != 0) {
@@ -3996,7 +3996,7 @@ static bool shada_removable(const char *name)
bool retval = false;
char *new_name = home_replace_save(NULL, (char *)name);
- for (p = (char *)p_shada; *p;) {
+ for (p = p_shada; *p;) {
(void)copy_option_part(&p, part, ARRAY_SIZE(part), ", ");
if (part[0] == 'r') {
home_replace(NULL, part + 1, (char *)NameBuff, MAXPATHL, true);
diff --git a/src/nvim/sign.c b/src/nvim/sign.c
index f1ddbfd147..ed7f53d3ba 100644
--- a/src/nvim/sign.c
+++ b/src/nvim/sign.c
@@ -203,7 +203,7 @@ static void insert_sign(buf_T *buf, sign_entry_T *prev, sign_entry_T *next, int
// When adding first sign need to redraw the windows to create the
// column for signs.
if (buf->b_signlist == NULL) {
- redraw_buf_later(buf, NOT_VALID);
+ redraw_buf_later(buf, UPD_NOT_VALID);
changed_line_abv_curs();
}
@@ -576,7 +576,7 @@ static linenr_T buf_delsign(buf_T *buf, linenr_T atlnum, int id, char_u *group)
// When deleting the last sign the cursor position may change, because the
// sign columns no longer shows. And the 'signcolumn' may be hidden.
if (buf->b_signlist == NULL) {
- redraw_buf_later(buf, NOT_VALID);
+ redraw_buf_later(buf, UPD_NOT_VALID);
changed_line_abv_curs();
}
@@ -858,7 +858,7 @@ static void sign_define_init_icon(sign_T *sp, char_u *icon)
{
xfree(sp->sn_icon);
sp->sn_icon = vim_strsave(icon);
- backslash_halve(sp->sn_icon);
+ backslash_halve((char *)sp->sn_icon);
}
/// Initialize the text for a new sign
@@ -934,7 +934,7 @@ static int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_
// non-empty sign list.
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_buffer->b_signlist != NULL) {
- redraw_buf_later(wp->w_buffer, NOT_VALID);
+ redraw_buf_later(wp->w_buffer, UPD_NOT_VALID);
}
}
}
@@ -1084,7 +1084,7 @@ static int sign_unplace(int sign_id, char_u *sign_group, buf_T *buf, linenr_T at
}
if (sign_id == 0) {
// Delete all the signs in the specified buffer
- redraw_buf_later(buf, NOT_VALID);
+ redraw_buf_later(buf, UPD_NOT_VALID);
buf_delete_signs(buf, (char *)sign_group);
} else {
linenr_T lnum;
@@ -1353,7 +1353,7 @@ static int parse_sign_cmd_args(int cmd, char_u *arg, char_u **sign_name, int *si
if (STRNCMP(arg, "line=", 5) == 0) {
arg += 5;
*lnum = atoi((char *)arg);
- arg = skiptowhite(arg);
+ arg = (char_u *)skiptowhite((char *)arg);
lnum_arg = true;
} else if (STRNCMP(arg, "*", 1) == 0 && cmd == SIGNCMD_UNPLACE) {
if (*signid != -1) {
@@ -1361,11 +1361,11 @@ static int parse_sign_cmd_args(int cmd, char_u *arg, char_u **sign_name, int *si
return FAIL;
}
*signid = -2;
- arg = skiptowhite(arg + 1);
+ arg = (char_u *)skiptowhite((char *)arg + 1);
} else if (STRNCMP(arg, "name=", 5) == 0) {
arg += 5;
name = arg;
- arg = skiptowhite(arg);
+ arg = (char_u *)skiptowhite((char *)arg);
if (*arg != NUL) {
*arg++ = NUL;
}
@@ -1376,14 +1376,14 @@ static int parse_sign_cmd_args(int cmd, char_u *arg, char_u **sign_name, int *si
} else if (STRNCMP(arg, "group=", 6) == 0) {
arg += 6;
*group = arg;
- arg = skiptowhite(arg);
+ arg = (char_u *)skiptowhite((char *)arg);
if (*arg != NUL) {
*arg++ = NUL;
}
} else if (STRNCMP(arg, "priority=", 9) == 0) {
arg += 9;
*prio = atoi((char *)arg);
- arg = skiptowhite(arg);
+ arg = (char_u *)skiptowhite((char *)arg);
} else if (STRNCMP(arg, "file=", 5) == 0) {
arg += 5;
filename = arg;
@@ -1427,7 +1427,7 @@ void ex_sign(exarg_T *eap)
sign_T *sp;
// Parse the subcommand.
- p = skiptowhite(arg);
+ p = (char_u *)skiptowhite((char *)arg);
idx = sign_cmd_idx(arg, p);
if (idx == SIGNCMD_LAST) {
semsg(_("E160: Unknown sign command: %s"), arg);
@@ -1449,7 +1449,7 @@ void ex_sign(exarg_T *eap)
// Isolate the sign name. If it's a number skip leading zeroes,
// so that "099" and "99" are the same sign. But keep "0".
- p = skiptowhite(arg);
+ p = (char_u *)skiptowhite((char *)arg);
if (*p != NUL) {
*p++ = NUL;
}
@@ -1789,7 +1789,7 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg)
expand_what = EXP_SUBCMD;
xp->xp_pattern = (char *)arg;
- end_subcmd = skiptowhite(arg);
+ end_subcmd = (char_u *)skiptowhite((char *)arg);
if (*end_subcmd == NUL) {
// expand subcmd name
// :sign {subcmd}<CTRL-D>
@@ -1814,7 +1814,7 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg)
do {
p = (char_u *)skipwhite((char *)p);
last = p;
- p = skiptowhite(p);
+ p = (char_u *)skiptowhite((char *)p);
} while (*p != NUL);
p = (char_u *)vim_strchr((char *)last, '=');
@@ -1964,7 +1964,7 @@ static void sign_define_multiple(list_T *l, list_T *retlist)
}
/// "sign_define()" function
-void f_sign_define(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_sign_define(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *name;
@@ -1995,7 +1995,7 @@ void f_sign_define(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "sign_getdefined()" function
-void f_sign_getdefined(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_sign_getdefined(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *name = NULL;
@@ -2009,7 +2009,7 @@ void f_sign_getdefined(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "sign_getplaced()" function
-void f_sign_getplaced(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_sign_getplaced(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
buf_T *buf = NULL;
dict_T *dict;
@@ -2067,7 +2067,7 @@ void f_sign_getplaced(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "sign_jump()" function
-void f_sign_jump(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_sign_jump(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int sign_id;
char *sign_group = NULL;
@@ -2225,7 +2225,7 @@ cleanup:
}
/// "sign_place()" function
-void f_sign_place(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_sign_place(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
dict_T *dict = NULL;
@@ -2243,7 +2243,7 @@ void f_sign_place(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "sign_placelist()" function. Place multiple signs.
-void f_sign_placelist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_sign_placelist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int sign_id;
@@ -2283,7 +2283,7 @@ static void sign_undefine_multiple(list_T *l, list_T *retlist)
}
/// "sign_undefine()" function
-void f_sign_undefine(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_sign_undefine(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *name;
@@ -2373,7 +2373,7 @@ cleanup:
}
/// "sign_unplace()" function
-void f_sign_unplace(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_sign_unplace(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
dict_T *dict = NULL;
@@ -2396,7 +2396,7 @@ void f_sign_unplace(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "sign_unplacelist()" function
-void f_sign_unplacelist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_sign_unplacelist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int retval;
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 1e44d328b3..1259736e0e 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -56,50 +56,59 @@
// Use DEBUG_TRIEWALK to print the changes made in suggest_trie_walk() for a
// specific word.
-#include <assert.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wctype.h>
-
-// for offsetof()
-#include <stddef.h>
-
-#include "nvim/ascii.h"
-#include "nvim/buffer.h"
-#include "nvim/change.h"
-#include "nvim/charset.h"
-#include "nvim/cursor.h"
-#include "nvim/drawscreen.h"
-#include "nvim/edit.h"
-#include "nvim/ex_cmds.h"
-#include "nvim/ex_docmd.h"
-#include "nvim/func_attr.h"
-#include "nvim/garray.h"
-#include "nvim/hashtab.h"
-#include "nvim/input.h"
-#include "nvim/insexpand.h"
-#include "nvim/mark.h"
-#include "nvim/mbyte.h"
-#include "nvim/memline.h"
-#include "nvim/memory.h"
-#include "nvim/message.h"
-#include "nvim/normal.h"
-#include "nvim/option.h"
-#include "nvim/os/input.h"
-#include "nvim/os/os.h"
-#include "nvim/os_unix.h"
-#include "nvim/path.h"
-#include "nvim/regexp.h"
-#include "nvim/search.h"
-#include "nvim/spell.h"
-#include "nvim/spellfile.h"
-#include "nvim/spellsuggest.h"
-#include "nvim/strings.h"
-#include "nvim/syntax.h"
-#include "nvim/undo.h"
+#include <assert.h> // for assert
+#include <inttypes.h> // for uint32_t, uint16_t, uint8_t
+#include <limits.h> // for INT_MAX
+#include <stdbool.h> // for false, true, bool
+#include <stddef.h> // for NULL, size_t, ptrdiff_t
+#include <stdio.h> // for snprintf
+#include <string.h> // for memmove, strstr, memcpy, memset
+
+#include "nvim/ascii.h" // for NUL, ascii_isdigit, ascii_iswhite
+#include "nvim/autocmd.h" // for apply_autocmds
+#include "nvim/buffer.h" // for bufref_valid, set_bufref, buf_is_empty
+#include "nvim/buffer_defs.h" // for win_T, synblock_T, buf_T, w_p_...
+#include "nvim/change.h" // for changed_bytes
+#include "nvim/charset.h" // for skipwhite, getwhitecols, skipbin
+#include "nvim/cursor.h" // for get_cursor_line_ptr
+#include "nvim/drawscreen.h" // for NOT_VALID, redraw_later
+#include "nvim/eval/typval.h" // for semsg
+#include "nvim/ex_cmds.h" // for do_sub_msg
+#include "nvim/ex_cmds_defs.h" // for exarg_T
+#include "nvim/ex_docmd.h" // for do_cmdline_cmd
+#include "nvim/garray.h" // for garray_T, GA_EMPTY, GA_APPEND_...
+#include "nvim/gettext.h" // for _, N_
+#include "nvim/hashtab.h" // for hash_clear_all, hash_init, has...
+#include "nvim/highlight_defs.h" // for HLF_COUNT, hlf_T, HLF_SPB, HLF...
+#include "nvim/insexpand.h" // for ins_compl_add_infercase, ins_c...
+#include "nvim/log.h" // for ELOG
+#include "nvim/macros.h" // for MB_PTR_ADV, MB_PTR_BACK, ASCII...
+#include "nvim/mark.h" // for clearpos
+#include "nvim/mbyte.h" // for utf_ptr2char, utf_char2bytes
+#include "nvim/memline.h" // for ml_append, ml_get_buf, ml_close
+#include "nvim/memline_defs.h" // for memline_T
+#include "nvim/memory.h" // for xfree, xmalloc, xcalloc, xstrdup
+#include "nvim/message.h" // for emsg, msg_puts, give_warning
+#include "nvim/option.h" // for copy_option_part, set_option_v...
+#include "nvim/option_defs.h" // for p_ws, OPT_LOCAL, p_enc, SHM_SE...
+#include "nvim/os/fs.h" // for os_remove
+#include "nvim/os/input.h" // for line_breakcheck
+#include "nvim/os/os_defs.h" // for MAXPATHL
+#include "nvim/path.h" // for path_full_compare, path_tail...
+#include "nvim/pos.h" // for pos_T, colnr_T, linenr_T
+#include "nvim/regexp.h" // for vim_regfree, vim_regexec, vim_...
+#include "nvim/regexp_defs.h" // for regmatch_T, regprog_T
+#include "nvim/runtime.h" // for DIP_ALL, do_in_runtimepath
+#include "nvim/search.h" // for SEARCH_KEEP, for do_search
+#include "nvim/spell.h" // for FUNC_ATTR_NONNULL_ALL, FUNC_AT...
+#include "nvim/spell_defs.h" // for slang_T, langp_T, MAXWLEN, sal...
+#include "nvim/spellfile.h" // for spell_load_file
+#include "nvim/spellsuggest.h" // for spell_suggest_list
+#include "nvim/strings.h" // for vim_strchr, vim_snprintf, conc...
+#include "nvim/syntax.h" // for syn_get_id, syntax_present
+#include "nvim/types.h" // for char_u
+#include "nvim/undo.h" // for u_save_cursor
+#include "nvim/vim.h" // for curwin, STRLEN, STRLCPY, STRNCMP
// Result values. Lower number is accepted over higher one.
#define SP_BANNED (-1)
@@ -209,9 +218,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
matchinf_T mi; // Most things are put in "mi" so that it can
// be passed to functions quickly.
size_t nrlen = 0; // found a number first
- int c;
size_t wrongcaplen = 0;
- int lpi;
bool count_word = docount;
bool use_camel_case = *wp->w_s->b_p_spo != NUL;
bool camel_case = false;
@@ -236,7 +243,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
if (*ptr == '0' && (ptr[1] == 'b' || ptr[1] == 'B')) {
mi.mi_end = (char_u *)skipbin((char *)ptr + 2);
} else if (*ptr == '0' && (ptr[1] == 'x' || ptr[1] == 'X')) {
- mi.mi_end = skiphex(ptr + 2);
+ mi.mi_end = (char_u *)skiphex((char *)ptr + 2);
} else {
mi.mi_end = (char_u *)skipdigits((char *)ptr);
}
@@ -250,7 +257,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
bool this_upper = false; // init for gcc
if (use_camel_case) {
- c = utf_ptr2char((char *)mi.mi_fend);
+ int c = utf_ptr2char((char *)mi.mi_fend);
this_upper = SPELL_ISUPPER(c);
}
@@ -258,7 +265,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
MB_PTR_ADV(mi.mi_fend);
if (use_camel_case) {
const bool prev_upper = this_upper;
- c = utf_ptr2char((char *)mi.mi_fend);
+ int c = utf_ptr2char((char *)mi.mi_fend);
this_upper = SPELL_ISUPPER(c);
camel_case = !prev_upper && this_upper;
}
@@ -267,7 +274,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
if (capcol != NULL && *capcol == 0 && wp->w_s->b_cap_prog != NULL) {
// Check word starting with capital letter.
- c = utf_ptr2char((char *)ptr);
+ int c = utf_ptr2char((char *)ptr);
if (!SPELL_ISUPPER(c)) {
wrongcaplen = (size_t)(mi.mi_fend - ptr);
}
@@ -308,7 +315,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
// Loop over the languages specified in 'spelllang'.
// We check them all, because a word may be matched longer in another
// language.
- for (lpi = 0; lpi < wp->w_s->b_langp.ga_len; ++lpi) {
+ for (int lpi = 0; lpi < wp->w_s->b_langp.ga_len; lpi++) {
mi.mi_lp = LANGP_ENTRY(wp->w_s->b_langp, lpi);
// If reloading fails the language is still in the list but everything
@@ -468,7 +475,6 @@ static void find_word(matchinf_T *mip, int mode)
int endlen[MAXWLEN]; // length at possible word endings
idx_T endidx[MAXWLEN]; // possible word endings
int endidxcnt = 0;
- int len;
int c;
// Repeat advancing in the tree until:
@@ -480,7 +486,7 @@ static void find_word(matchinf_T *mip, int mode)
flen = fold_more(mip);
}
- len = byts[arridx++];
+ int len = byts[arridx++];
// If the first possible byte is a zero the word could end here.
// Remember this index, we first check for the longest word.
@@ -597,7 +603,7 @@ static void find_word(matchinf_T *mip, int mode)
// prefix ID.
// Repeat this if there are more flags/region alternatives until there
// is a match.
- for (len = byts[arridx - 1]; len > 0 && byts[arridx] == 0; len--, arridx++) {
+ for (int len = byts[arridx - 1]; len > 0 && byts[arridx] == 0; len--, arridx++) {
uint32_t flags = (uint32_t)idxs[arridx];
// For the fold-case tree check that the case of the checked word
@@ -616,11 +622,10 @@ static void find_word(matchinf_T *mip, int mode)
|| !spell_valid_case(mip->mi_capflags, (int)flags)) {
continue;
}
- }
- // When mode is FIND_PREFIX the word must support the prefix:
- // check the prefix ID and the condition. Do that for the list at
- // mip->mi_prefarridx that find_prefix() filled.
- else if (mode == FIND_PREFIX && !prefix_found) {
+ } else if (mode == FIND_PREFIX && !prefix_found) {
+ // When mode is FIND_PREFIX the word must support the prefix:
+ // check the prefix ID and the condition. Do that for the list at
+ // mip->mi_prefarridx that find_prefix() filled.
c = valid_word_prefix(mip->mi_prefcnt, mip->mi_prefarridx,
(int)flags,
mip->mi_word + mip->mi_cprefixlen, slang,
@@ -752,9 +757,8 @@ static void find_word(matchinf_T *mip, int mode)
// COMPOUNDRULE, discard the compounded word.
continue;
}
- }
- // Check NEEDCOMPOUND: can't use word without compounding.
- else if (flags & WF_NEEDCOMP) {
+ } else if (flags & WF_NEEDCOMP) {
+ // skip if word is only valid in a compound
continue;
}
@@ -792,14 +796,14 @@ static void find_word(matchinf_T *mip, int mode)
#if 0
c = mip->mi_compoff;
#endif
- ++mip->mi_complen;
+ mip->mi_complen++;
if (flags & WF_COMPROOT) {
- ++mip->mi_compextra;
+ mip->mi_compextra++;
}
// For NOBREAK we need to try all NOBREAK languages, at least
// to find the ".add" file(s).
- for (int lpi = 0; lpi < mip->mi_win->w_s->b_langp.ga_len; ++lpi) {
+ for (int lpi = 0; lpi < mip->mi_win->w_s->b_langp.ga_len; lpi++) {
if (slang->sl_nobreak) {
mip->mi_lp = LANGP_ENTRY(mip->mi_win->w_s->b_langp, lpi);
if (mip->mi_lp->lp_slang->sl_fidxs == NULL
@@ -833,9 +837,9 @@ static void find_word(matchinf_T *mip, int mode)
break;
}
}
- --mip->mi_complen;
+ mip->mi_complen--;
if (flags & WF_COMPROOT) {
- --mip->mi_compextra;
+ mip->mi_compextra--;
}
mip->mi_lp = save_lp;
@@ -905,16 +909,13 @@ static void find_word(matchinf_T *mip, int mode)
/// @param gap &sl_comppat
bool match_checkcompoundpattern(char_u *ptr, int wlen, garray_T *gap)
{
- char_u *p;
- int len;
-
for (int i = 0; i + 1 < gap->ga_len; i += 2) {
- p = ((char_u **)gap->ga_data)[i + 1];
+ char_u *p = ((char_u **)gap->ga_data)[i + 1];
if (STRNCMP(ptr + wlen, p, STRLEN(p)) == 0) {
// Second part matches at start of following compound word, now
// check if first part matches at end of previous word.
p = ((char_u **)gap->ga_data)[i];
- len = (int)STRLEN(p);
+ int len = (int)STRLEN(p);
if (len <= wlen && STRNCMP(ptr + wlen - len, p, len) == 0) {
return true;
}
@@ -960,16 +961,12 @@ bool can_compound(slang_T *slang, const char_u *word, const char_u *flags)
// Caller must check that slang->sl_comprules is not NULL.
bool match_compoundrule(slang_T *slang, char_u *compflags)
{
- char_u *p;
- int i;
- int c;
-
// loop over all the COMPOUNDRULE entries
- for (p = slang->sl_comprules; *p != NUL; ++p) {
+ for (char_u *p = slang->sl_comprules; *p != NUL; p++) {
// loop over the flags in the compound word we have made, match
// them against the current rule entry
- for (i = 0;; ++i) {
- c = compflags[i];
+ for (int i = 0;; i++) {
+ int c = compflags[i];
if (c == NUL) {
// found a rule that matches for the flags we have so far
return true;
@@ -1018,12 +1015,9 @@ bool match_compoundrule(slang_T *slang, char_u *compflags)
int valid_word_prefix(int totprefcnt, int arridx, int flags, char_u *word, slang_T *slang,
bool cond_req)
{
- int prefcnt;
- int pidx;
-
int prefid = (int)((unsigned)flags >> 24);
- for (prefcnt = totprefcnt - 1; prefcnt >= 0; prefcnt--) {
- pidx = slang->sl_pidxs[arridx + prefcnt];
+ for (int prefcnt = totprefcnt - 1; prefcnt >= 0; prefcnt--) {
+ int pidx = slang->sl_pidxs[arridx + prefcnt];
// Check the prefix ID.
if (prefid != (pidx & 0xff)) {
@@ -1063,30 +1057,23 @@ int valid_word_prefix(int totprefcnt, int arridx, int flags, char_u *word, slang
static void find_prefix(matchinf_T *mip, int mode)
{
idx_T arridx = 0;
- int len;
int wlen = 0;
- int flen;
- int c;
- char_u *ptr;
- idx_T lo, hi, m;
slang_T *slang = mip->mi_lp->lp_slang;
- char_u *byts;
- idx_T *idxs;
- byts = slang->sl_pbyts;
+ char_u *byts = slang->sl_pbyts;
if (byts == NULL) {
return; // array is empty
}
// We use the case-folded word here, since prefixes are always
// case-folded.
- ptr = mip->mi_fword;
- flen = mip->mi_fwordlen; // available case-folded bytes
+ char_u *ptr = mip->mi_fword;
+ int flen = mip->mi_fwordlen; // available case-folded bytes
if (mode == FIND_COMPOUND) {
// Skip over the previously found word(s).
ptr += mip->mi_compoff;
flen -= mip->mi_compoff;
}
- idxs = slang->sl_pidxs;
+ idx_T *idxs = slang->sl_pidxs;
// Repeat advancing in the tree until:
// - there is a byte that doesn't match,
@@ -1097,7 +1084,7 @@ static void find_prefix(matchinf_T *mip, int mode)
flen = fold_more(mip);
}
- len = byts[arridx++];
+ int len = byts[arridx++];
// If the first possible byte is a zero the prefix could end here.
// Check if the following word matches and supports the prefix.
@@ -1137,11 +1124,11 @@ static void find_prefix(matchinf_T *mip, int mode)
}
// Perform a binary search in the list of accepted bytes.
- c = ptr[wlen];
- lo = arridx;
- hi = arridx + len - 1;
+ int c = ptr[wlen];
+ idx_T lo = arridx;
+ idx_T hi = arridx + len - 1;
while (lo < hi) {
- m = (lo + hi) / 2;
+ idx_T m = (lo + hi) / 2;
if (byts[m] > c) {
hi = m - 1;
} else if (byts[m] < c) {
@@ -1169,10 +1156,7 @@ static void find_prefix(matchinf_T *mip, int mode)
// Return the length of the folded chars in bytes.
static int fold_more(matchinf_T *mip)
{
- int flen;
- char_u *p;
-
- p = mip->mi_fend;
+ char_u *p = mip->mi_fend;
do {
MB_PTR_ADV(mip->mi_fend);
} while (*mip->mi_fend != NUL && spell_iswordp(mip->mi_fend, mip->mi_win));
@@ -1185,7 +1169,7 @@ static int fold_more(matchinf_T *mip)
(void)spell_casefold(mip->mi_win, p, (int)(mip->mi_fend - p),
mip->mi_fword + mip->mi_fwordlen,
MAXWLEN - mip->mi_fwordlen);
- flen = (int)STRLEN(mip->mi_fword + mip->mi_fwordlen);
+ int flen = (int)STRLEN(mip->mi_fword + mip->mi_fwordlen);
mip->mi_fwordlen += flen;
return flen;
}
@@ -1227,17 +1211,12 @@ bool no_spell_checking(win_T *wp)
/// @return 0 if not found, length of the badly spelled word otherwise.
size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *attrp)
{
- linenr_T lnum;
pos_T found_pos;
size_t found_len = 0;
- char_u *line;
- char_u *p;
- char_u *endp;
hlf_T attr = HLF_COUNT;
size_t len;
int has_syntax = syntax_present(wp);
int col;
- bool can_spell;
char_u *buf = NULL;
size_t buflen = 0;
int skip = 0;
@@ -1258,11 +1237,11 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
// We concatenate the start of the next line, so that wrapped words work
// (e.g. "et<line-break>cetera"). Doesn't work when searching backwards
// though...
- lnum = wp->w_cursor.lnum;
+ linenr_T lnum = wp->w_cursor.lnum;
clearpos(&found_pos);
while (!got_int) {
- line = ml_get_buf(wp->w_buffer, lnum, false);
+ char_u *line = ml_get_buf(wp->w_buffer, lnum, false);
len = STRLEN(line);
if (buflen < len + MAXWLEN + 2) {
@@ -1279,10 +1258,10 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
// For checking first word with a capital skip white space.
if (capcol == 0) {
- capcol = (int)getwhitecols(line);
+ capcol = (int)getwhitecols((char *)line);
} else if (curline && wp == curwin) {
// For spellbadword(): check if first word needs a capital.
- col = (int)getwhitecols(line);
+ col = (int)getwhitecols((char *)line);
if (check_need_cap(lnum, col)) {
capcol = col;
}
@@ -1302,8 +1281,8 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
ml_get_buf(wp->w_buffer, lnum + 1, false),
MAXWLEN);
}
- p = buf + skip;
- endp = buf + len;
+ char_u *p = buf + skip;
+ char_u *endp = buf + len;
while (p < endp) {
// When searching backward don't search after the cursor. Unless
// we wrapped around the end of the buffer.
@@ -1329,10 +1308,11 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
|| ((colnr_T)(curline
? p - buf + (ptrdiff_t)len
: p - buf) > wp->w_cursor.col)) {
+ bool can_spell;
if (has_syntax) {
col = (int)(p - buf);
(void)syn_get_id(wp, lnum, (colnr_T)col,
- FALSE, &can_spell, FALSE);
+ false, &can_spell, false);
if (!can_spell) {
attr = HLF_COUNT;
}
@@ -1342,9 +1322,11 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
if (can_spell) {
found_one = true;
- found_pos.lnum = lnum;
- found_pos.col = (int)(p - buf);
- found_pos.coladd = 0;
+ found_pos = (pos_T) {
+ .lnum = lnum,
+ .col = (int)(p - buf),
+ .coladd = 0
+ };
if (dir == FORWARD) {
// No need to search further.
wp->w_cursor = found_pos;
@@ -1457,10 +1439,7 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
// to skip those bytes if the word was OK.
void spell_cat_line(char_u *buf, char_u *line, int maxlen)
{
- char_u *p;
- int n;
-
- p = (char_u *)skipwhite((char *)line);
+ char_u *p = (char_u *)skipwhite((char *)line);
while (vim_strchr("*#/\"\t", *p) != NULL) {
p = (char_u *)skipwhite((char *)p + 1);
}
@@ -1468,7 +1447,7 @@ void spell_cat_line(char_u *buf, char_u *line, int maxlen)
if (*p != NUL) {
// Only worth concatenating if there is something else than spaces to
// concatenate.
- n = (int)(p - line) + 1;
+ int n = (int)(p - line) + 1;
if (n < maxlen - 1) {
memset(buf, ' ', (size_t)n);
STRLCPY(buf + n, p, maxlen - n);
@@ -1483,7 +1462,6 @@ static void spell_load_lang(char_u *lang)
char fname_enc[85];
int r;
spelload_T sl;
- int round;
// Copy the language name to pass it to spell_load_cb() as a cookie.
// It's truncated when an error is detected.
@@ -1493,7 +1471,7 @@ static void spell_load_lang(char_u *lang)
// We may retry when no spell file is found for the language, an
// autocommand may load it then.
- for (round = 1; round <= 2; ++round) {
+ for (int round = 1; round <= 2; round++) {
// Find the first spell file for "lang" in 'runtimepath' and load it.
vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5,
"spell/%s.%s.spl", lang, spell_enc());
@@ -1540,7 +1518,7 @@ static void spell_load_lang(char_u *lang)
char_u *spell_enc(void)
{
if (STRLEN(p_enc) < 60 && STRCMP(p_enc, "iso-8859-15") != 0) {
- return p_enc;
+ return (char_u *)p_enc;
}
return (char_u *)"latin1";
}
@@ -1624,7 +1602,7 @@ void slang_clear(slang_T *lp)
GA_DEEP_CLEAR(gap, salitem_T, free_salitem);
}
- for (int i = 0; i < lp->sl_prefixcnt; ++i) {
+ for (int i = 0; i < lp->sl_prefixcnt; i++) {
vim_regfree(lp->sl_prefprog[i]);
}
lp->sl_prefixcnt = 0;
@@ -1673,9 +1651,7 @@ void slang_clear_sug(slang_T *lp)
static void spell_load_cb(char *fname, void *cookie)
{
spelload_T *slp = (spelload_T *)cookie;
- slang_T *slang;
-
- slang = spell_load_file((char_u *)fname, slp->sl_lang, NULL, false);
+ slang_T *slang = spell_load_file((char_u *)fname, slp->sl_lang, NULL, false);
if (slang != NULL) {
// When a previously loaded file has NOBREAK also use it for the
// ".add" files.
@@ -1698,9 +1674,6 @@ static void spell_load_cb(char *fname, void *cookie)
/// @param[in] count 1 to count once, 10 to init
void count_common_word(slang_T *lp, char_u *word, int len, uint8_t count)
{
- hash_T hash;
- hashitem_T *hi;
- wordcount_T *wc;
char_u buf[MAXWLEN];
char_u *p;
@@ -1713,9 +1686,10 @@ void count_common_word(slang_T *lp, char_u *word, int len, uint8_t count)
p = buf;
}
- hash = hash_hash(p);
+ wordcount_T *wc;
+ hash_T hash = hash_hash(p);
const size_t p_len = STRLEN(p);
- hi = hash_lookup(&lp->sl_wordcount, (const char *)p, p_len, hash);
+ hashitem_T *hi = hash_lookup(&lp->sl_wordcount, (const char *)p, p_len, hash);
if (HASHITEM_EMPTY(hi)) {
wc = xmalloc(sizeof(wordcount_T) + p_len);
memcpy(wc->wc_word, p, p_len + 1);
@@ -1734,9 +1708,7 @@ void count_common_word(slang_T *lp, char_u *word, int len, uint8_t count)
// Like strchr() but independent of locale.
bool byte_in_str(char_u *str, int n)
{
- char_u *p;
-
- for (p = str; *p != NUL; ++p) {
+ for (char_u *p = str; *p != NUL; p++) {
if (*p == n) {
return true;
}
@@ -1748,19 +1720,16 @@ bool byte_in_str(char_u *str, int n)
// in "slang->sl_syl_items".
int init_syl_tab(slang_T *slang)
{
- char_u *p;
- char_u *s;
- int l;
-
ga_init(&slang->sl_syl_items, sizeof(syl_item_T), 4);
- p = (char_u *)vim_strchr((char *)slang->sl_syllable, '/');
+ char_u *p = (char_u *)vim_strchr((char *)slang->sl_syllable, '/');
while (p != NULL) {
*p++ = NUL;
if (*p == NUL) { // trailing slash
break;
}
- s = p;
+ char_u *s = p;
p = (char_u *)vim_strchr((char *)p, '/');
+ int l;
if (p == NULL) {
l = (int)STRLEN(s);
} else {
@@ -1786,8 +1755,6 @@ static int count_syllables(slang_T *slang, const char_u *word)
int cnt = 0;
bool skip = false;
int len;
- syl_item_T *syl;
- int c;
if (slang->sl_syllable == NULL) {
return 0;
@@ -1803,8 +1770,8 @@ static int count_syllables(slang_T *slang, const char_u *word)
// Find longest match of syllable items.
len = 0;
- for (int i = 0; i < slang->sl_syl_items.ga_len; ++i) {
- syl = ((syl_item_T *)slang->sl_syl_items.ga_data) + i;
+ for (int i = 0; i < slang->sl_syl_items.ga_len; i++) {
+ syl_item_T *syl = ((syl_item_T *)slang->sl_syl_items.ga_data) + i;
if (syl->sy_len > len
&& STRNCMP(p, syl->sy_chars, syl->sy_len) == 0) {
len = syl->sy_len;
@@ -1815,12 +1782,12 @@ static int count_syllables(slang_T *slang, const char_u *word)
skip = false;
} else {
// No recognized syllable item, at least a syllable char then?
- c = utf_ptr2char((char *)p);
+ int c = utf_ptr2char((char *)p);
len = utfc_ptr2len((char *)p);
if (vim_strchr((char *)slang->sl_syllable, c) == NULL) {
skip = false; // No, search for next syllable
} else if (!skip) {
- ++cnt; // Yes, count it
+ cnt++; // Yes, count it
skip = true; // don't count following syllable chars
}
}
@@ -1828,8 +1795,8 @@ static int count_syllables(slang_T *slang, const char_u *word)
return cnt;
}
-// Parse 'spelllang' and set w_s->b_langp accordingly.
-// Returns NULL if it's OK, an error message otherwise.
+/// Parse 'spelllang' and set w_s->b_langp accordingly.
+/// @return NULL if it's OK, an untranslated error message otherwise.
char *did_set_spelllang(win_T *wp)
{
garray_T ga;
@@ -1870,7 +1837,7 @@ char *did_set_spelllang(win_T *wp)
// Make a copy of 'spelllang', the SpellFileMissing autocommands may change
// it under our fingers.
- spl_copy = vim_strsave(wp->w_s->b_p_spl);
+ spl_copy = vim_strsave((char_u *)wp->w_s->b_p_spl);
wp->w_s->b_cjk = 0;
@@ -1881,7 +1848,7 @@ char *did_set_spelllang(win_T *wp)
region = NULL;
len = (int)STRLEN(lang);
- if (!valid_spelllang(lang)) {
+ if (!valid_spelllang((char *)lang)) {
continue;
}
@@ -1909,7 +1876,7 @@ char *did_set_spelllang(win_T *wp)
// Check if we loaded this language before.
for (slang = first_lang; slang != NULL; slang = slang->sl_next) {
- if (path_full_compare((char *)lang, (char *)slang->sl_fname, false, true)
+ if (path_full_compare((char *)lang, slang->sl_fname, false, true)
== kEqualFiles) {
break;
}
@@ -1958,7 +1925,7 @@ char *did_set_spelllang(win_T *wp)
// Loop over the languages, there can be several files for "lang".
for (slang = first_lang; slang != NULL; slang = slang->sl_next) {
if (filename
- ? path_full_compare((char *)lang, (char *)slang->sl_fname, false, true) == kEqualFiles
+ ? path_full_compare((char *)lang, slang->sl_fname, false, true) == kEqualFiles
: STRICMP(lang, slang->sl_name) == 0) {
region_mask = REGION_ALL;
if (!filename && region != NULL) {
@@ -1999,7 +1966,7 @@ char *did_set_spelllang(win_T *wp)
// round 1: load first name in 'spellfile'.
// round 2: load second name in 'spellfile.
// etc.
- spf = (char *)curwin->w_s->b_p_spf;
+ spf = curwin->w_s->b_p_spf;
for (round = 0; round == 0 || *spf != NUL; round++) {
if (round == 0) {
// Internal wordlist, if there is one.
@@ -2013,8 +1980,8 @@ char *did_set_spelllang(win_T *wp)
STRCAT(spf_name, ".spl");
// If it was already found above then skip it.
- for (c = 0; c < ga.ga_len; ++c) {
- p = LANGP_ENTRY(ga, c)->lp_slang->sl_fname;
+ for (c = 0; c < ga.ga_len; c++) {
+ p = (char_u *)LANGP_ENTRY(ga, c)->lp_slang->sl_fname;
if (p != NULL
&& path_full_compare((char *)spf_name, (char *)p, false, true) == kEqualFiles) {
break;
@@ -2027,7 +1994,7 @@ char *did_set_spelllang(win_T *wp)
// Check if it was loaded already.
for (slang = first_lang; slang != NULL; slang = slang->sl_next) {
- if (path_full_compare((char *)spf_name, (char *)slang->sl_fname, false, true)
+ if (path_full_compare((char *)spf_name, slang->sl_fname, false, true)
== kEqualFiles) {
break;
}
@@ -2085,7 +2052,7 @@ char *did_set_spelllang(win_T *wp)
// For each language figure out what language to use for sound folding and
// REP items. If the language doesn't support it itself use another one
// with the same name. E.g. for "en-math" use "en".
- for (int i = 0; i < ga.ga_len; ++i) {
+ for (int i = 0; i < ga.ga_len; i++) {
lp = LANGP_ENTRY(ga, i);
// sound folding
@@ -2094,7 +2061,7 @@ char *did_set_spelllang(win_T *wp)
lp->lp_sallang = lp->lp_slang;
} else {
// find first similar language that does sound folding
- for (int j = 0; j < ga.ga_len; ++j) {
+ for (int j = 0; j < ga.ga_len; j++) {
lp2 = LANGP_ENTRY(ga, j);
if (!GA_EMPTY(&lp2->lp_slang->sl_sal)
&& STRNCMP(lp->lp_slang->sl_name,
@@ -2111,7 +2078,7 @@ char *did_set_spelllang(win_T *wp)
lp->lp_replang = lp->lp_slang;
} else {
// find first similar language that has REP items
- for (int j = 0; j < ga.ga_len; ++j) {
+ for (int j = 0; j < ga.ga_len; j++) {
lp2 = LANGP_ENTRY(ga, j);
if (!GA_EMPTY(&lp2->lp_slang->sl_rep)
&& STRNCMP(lp->lp_slang->sl_name,
@@ -2122,7 +2089,7 @@ char *did_set_spelllang(win_T *wp)
}
}
}
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
theend:
xfree(spl_copy);
@@ -2153,13 +2120,13 @@ static void use_midword(slang_T *lp, win_T *wp)
wp->w_s->b_spell_ismw[c] = true;
} else if (wp->w_s->b_spell_ismw_mb == NULL) {
// First multi-byte char in "b_spell_ismw_mb".
- wp->w_s->b_spell_ismw_mb = vim_strnsave(p, (size_t)l);
+ wp->w_s->b_spell_ismw_mb = (char *)vim_strnsave(p, (size_t)l);
} else {
// Append multi-byte chars to "b_spell_ismw_mb".
const int n = (int)STRLEN(wp->w_s->b_spell_ismw_mb);
- char_u *bp = vim_strnsave(wp->w_s->b_spell_ismw_mb, (size_t)n + (size_t)l);
+ char_u *bp = vim_strnsave((char_u *)wp->w_s->b_spell_ismw_mb, (size_t)n + (size_t)l);
xfree(wp->w_s->b_spell_ismw_mb);
- wp->w_s->b_spell_ismw_mb = bp;
+ wp->w_s->b_spell_ismw_mb = (char *)bp;
STRLCPY(bp + n, p, l + 1);
}
p += l;
@@ -2198,9 +2165,6 @@ int captype(char_u *word, char_u *end)
FUNC_ATTR_NONNULL_ARG(1)
{
char_u *p;
- int firstcap;
- bool allcap;
- bool past_second = false; // past second word char
// find first letter
for (p = word; !spell_iswordp_nmw(p, curwin); MB_PTR_ADV(p)) {
@@ -2209,7 +2173,9 @@ int captype(char_u *word, char_u *end)
}
}
int c = mb_ptr2char_adv((const char_u **)&p);
- firstcap = allcap = SPELL_ISUPPER(c);
+ bool allcap;
+ bool firstcap = allcap = SPELL_ISUPPER(c);
+ bool past_second = false; // past second word char
// Need to check all letters to find a word with mixed upper/lower.
// But a word with an upper char only at start is a ONECAP.
@@ -2242,9 +2208,8 @@ int captype(char_u *word, char_u *end)
// Delete the internal wordlist and its .spl file.
void spell_delete_wordlist(void)
{
- char_u fname[MAXPATHL] = { 0 };
-
if (int_wordlist != NULL) {
+ char_u fname[MAXPATHL] = { 0 };
os_remove((char *)int_wordlist);
int_wordlist_spl(fname);
os_remove((char *)fname);
@@ -2255,15 +2220,13 @@ void spell_delete_wordlist(void)
// Free all languages.
void spell_free_all(void)
{
- slang_T *slang;
-
// Go through all buffers and handle 'spelllang'. <VN>
FOR_ALL_BUFFERS(buf) {
ga_clear(&buf->b_s.b_langp);
}
while (first_lang != NULL) {
- slang = first_lang;
+ slang_T *slang = first_lang;
first_lang = slang->sl_next;
slang_free(slang);
}
@@ -2320,7 +2283,7 @@ buf_T *open_spellbuf(void)
void close_spellbuf(buf_T *buf)
{
if (buf != NULL) {
- ml_close(buf, TRUE);
+ ml_close(buf, true);
xfree(buf);
}
}
@@ -2328,28 +2291,26 @@ void close_spellbuf(buf_T *buf)
// Init the chartab used for spelling for ASCII.
void clear_spell_chartab(spelltab_T *sp)
{
- int i;
-
// Init everything to false (zero).
CLEAR_FIELD(sp->st_isw);
CLEAR_FIELD(sp->st_isu);
- for (i = 0; i < 256; i++) {
+ for (int i = 0; i < 256; i++) {
sp->st_fold[i] = (char_u)i;
sp->st_upper[i] = (char_u)i;
}
// We include digits. A word shouldn't start with a digit, but handling
// that is done separately.
- for (i = '0'; i <= '9'; ++i) {
+ for (int i = '0'; i <= '9'; i++) {
sp->st_isw[i] = true;
}
- for (i = 'A'; i <= 'Z'; ++i) {
+ for (int i = 'A'; i <= 'Z'; i++) {
sp->st_isw[i] = true;
sp->st_isu[i] = true;
sp->st_fold[i] = (char_u)(i + 0x20);
}
- for (i = 'a'; i <= 'z'; ++i) {
+ for (int i = 'a'; i <= 'z'; i++) {
sp->st_isw[i] = true;
sp->st_upper[i] = (char_u)(i - 0x20);
}
@@ -2361,11 +2322,9 @@ void clear_spell_chartab(spelltab_T *sp)
// locale. For utf-8 we don't use isalpha() but our own functions.
void init_spell_chartab(void)
{
- int i;
-
did_set_spelltab = false;
clear_spell_chartab(&spelltab);
- for (i = 128; i < 256; i++) {
+ for (int i = 128; i < 256; i++) {
int f = utf_fold(i);
int u = mb_toupper(i);
@@ -2388,8 +2347,6 @@ void init_spell_chartab(void)
bool spell_iswordp(const char_u *p, const win_T *wp)
FUNC_ATTR_NONNULL_ALL
{
- int c;
-
const int l = utfc_ptr2len((char *)p);
const char_u *s = p;
if (l == 1) {
@@ -2398,16 +2355,16 @@ bool spell_iswordp(const char_u *p, const win_T *wp)
s = p + 1; // skip a mid-word character
}
} else {
- c = utf_ptr2char((char *)p);
+ int c = utf_ptr2char((char *)p);
if (c < 256
? wp->w_s->b_spell_ismw[c]
: (wp->w_s->b_spell_ismw_mb != NULL
- && vim_strchr((char *)wp->w_s->b_spell_ismw_mb, c) != NULL)) {
+ && vim_strchr(wp->w_s->b_spell_ismw_mb, c) != NULL)) {
s = p + l;
}
}
- c = utf_ptr2char((char *)s);
+ int c = utf_ptr2char((char *)s);
if (c > 255) {
return spell_mb_isword_class(mb_get_class(s), wp);
}
@@ -2448,7 +2405,7 @@ static bool spell_iswordp_w(const int *p, const win_T *wp)
if (*p <
256 ? wp->w_s->b_spell_ismw[*p] : (wp->w_s->b_spell_ismw_mb != NULL
- && vim_strchr((char *)wp->w_s->b_spell_ismw_mb,
+ && vim_strchr(wp->w_s->b_spell_ismw_mb,
*p) != NULL)) {
s = p + 1;
} else {
@@ -2508,19 +2465,15 @@ int spell_casefold(const win_T *wp, char_u *str, int len, char_u *buf, int bufle
bool check_need_cap(linenr_T lnum, colnr_T col)
{
bool need_cap = false;
- char_u *line;
- char_u *line_copy = NULL;
- char_u *p;
- colnr_T endcol;
- regmatch_T regmatch;
if (curwin->w_s->b_cap_prog == NULL) {
return false;
}
- line = get_cursor_line_ptr();
- endcol = 0;
- if (getwhitecols(line) >= (int)col) {
+ char_u *line = get_cursor_line_ptr();
+ char_u *line_copy = NULL;
+ colnr_T endcol = 0;
+ if (getwhitecols((char *)line) >= (int)col) {
// At start of line, check if previous line is empty or sentence
// ends there.
if (lnum == 1) {
@@ -2531,7 +2484,7 @@ bool check_need_cap(linenr_T lnum, colnr_T col)
need_cap = true;
} else {
// Append a space in place of the line break.
- line_copy = concat_str(line, (char_u *)" ");
+ line_copy = (char_u *)concat_str((char *)line, " ");
line = line_copy;
endcol = (colnr_T)STRLEN(line);
}
@@ -2542,9 +2495,11 @@ bool check_need_cap(linenr_T lnum, colnr_T col)
if (endcol > 0) {
// Check if sentence ends before the bad word.
- regmatch.regprog = curwin->w_s->b_cap_prog;
- regmatch.rm_ic = FALSE;
- p = line + endcol;
+ regmatch_T regmatch = {
+ .regprog = curwin->w_s->b_cap_prog,
+ .rm_ic = false
+ };
+ char_u *p = line + endcol;
for (;;) {
MB_PTR_BACK(line, p);
if (p == line || spell_iswordp_nmw(p, curwin)) {
@@ -2568,10 +2523,6 @@ bool check_need_cap(linenr_T lnum, colnr_T col)
void ex_spellrepall(exarg_T *eap)
{
pos_T pos = curwin->w_cursor;
- char_u *frompat;
- int addlen;
- char_u *line;
- char_u *p;
bool save_ws = p_ws;
linenr_T prev_lnum = 0;
@@ -2579,10 +2530,11 @@ void ex_spellrepall(exarg_T *eap)
emsg(_("E752: No previous spell replacement"));
return;
}
- addlen = (int)(STRLEN(repl_to) - STRLEN(repl_from));
+ int addlen = (int)(STRLEN(repl_to) - STRLEN(repl_from));
- frompat = xmalloc(STRLEN(repl_from) + 7);
- sprintf((char *)frompat, "\\V\\<%s\\>", repl_from);
+ size_t frompatlen = STRLEN(repl_from) + 7;
+ char_u *frompat = xmalloc(frompatlen);
+ snprintf((char *)frompat, frompatlen, "\\V\\<%s\\>", repl_from);
p_ws = false;
sub_nsubs = 0;
@@ -2596,10 +2548,10 @@ void ex_spellrepall(exarg_T *eap)
// Only replace when the right word isn't there yet. This happens
// when changing "etc" to "etc.".
- line = get_cursor_line_ptr();
+ char_u *line = get_cursor_line_ptr();
if (addlen <= 0 || STRNCMP(line + curwin->w_cursor.col,
repl_to, STRLEN(repl_to)) != 0) {
- p = xmalloc(STRLEN(line) + (size_t)addlen + 1);
+ char_u *p = xmalloc(STRLEN(line) + (size_t)addlen + 1);
memmove(p, line, (size_t)curwin->w_cursor.col);
STRCPY(p + curwin->w_cursor.col, repl_to);
STRCAT(p, line + curwin->w_cursor.col + STRLEN(repl_from));
@@ -2747,13 +2699,12 @@ char *eval_soundfold(const char *const word)
/// @param[in,out] res destination for soundfolded word
void spell_soundfold(slang_T *slang, char_u *inword, bool folded, char_u *res)
{
- char_u fword[MAXWLEN];
- char_u *word;
-
if (slang->sl_sofo) {
// SOFOFROM and SOFOTO used
spell_soundfold_sofo(slang, inword, res);
} else {
+ char_u fword[MAXWLEN];
+ char_u *word;
// SAL items used. Requires the word to be case-folded.
if (folded) {
word = inword;
@@ -2820,29 +2771,26 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
salitem_T *smp = (salitem_T *)slang->sl_sal.ga_data;
int word[MAXWLEN] = { 0 };
int wres[MAXWLEN] = { 0 };
- int l;
int *ws;
int *pf;
- int i, j, z;
+ int j, z;
int reslen;
- int n, k = 0;
+ int k = 0;
int z0;
int k0;
int n0;
- int c;
int pri;
int p0 = -333;
int c0;
bool did_white = false;
- int wordlen;
// Convert the multi-byte string to a wide-character string.
// Remove accents, if wanted. We actually remove all non-word characters.
// But keep white space.
- wordlen = 0;
+ int wordlen = 0;
for (const char_u *s = inword; *s != NUL;) {
const char_u *t = s;
- c = mb_cptr2char_adv(&s);
+ int c = mb_cptr2char_adv(&s);
if (slang->sl_rem_accents) {
if (utf_class(c) == 0) {
if (did_white) {
@@ -2861,13 +2809,14 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
}
word[wordlen] = NUL;
+ int c;
// This algorithm comes from Aspell phonet.cpp.
// Converted from C++ to C. Added support for multi-byte chars.
// Changed to keep spaces.
- i = reslen = z = 0;
+ int i = reslen = z = 0;
while ((c = word[i]) != NUL) {
// Start with the first rule that has the character in the word.
- n = slang->sl_sal_first[c & 0xff];
+ int n = slang->sl_sal_first[c & 0xff];
z0 = 0;
if (n >= 0) {
@@ -2875,7 +2824,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
// If c is 0x300 need extra check for the end of the array, as
// (c & 0xff) is NUL.
for (; ((ws = smp[n].sm_lead_w)[0] & 0xff) == (c & 0xff)
- && ws[0] != NUL; ++n) {
+ && ws[0] != NUL; n++) {
// Quickly skip entries that don't match the word. Most
// entries are less than three chars, optimize for that.
if (c != ws[0]) {
@@ -2887,7 +2836,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
continue;
}
if (k > 2) {
- for (j = 2; j < k; ++j) {
+ for (j = 2; j < k; j++) {
if (word[i + j] != ws[j]) {
break;
}
@@ -2948,7 +2897,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
// Test follow-up rule for "word[i + k]"; loop over
// all entries with the same index byte.
for (; ((ws = smp[n0].sm_lead_w)[0] & 0xff)
- == (c0 & 0xff); ++n0) {
+ == (c0 & 0xff); n0++) {
// Quickly skip entries that don't match the word.
if (c0 != ws[0]) {
continue;
@@ -2960,7 +2909,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
}
if (k0 > 2) {
pf = word + i + k + 1;
- for (j = 2; j < k0; ++j) {
+ for (j = 2; j < k0; j++) {
if (*pf++ != ws[j]) {
break;
}
@@ -3102,8 +3051,8 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
}
// Convert wide characters in "wres" to a multi-byte string in "res".
- l = 0;
- for (n = 0; n < reslen; n++) {
+ int l = 0;
+ for (int n = 0; n < reslen; n++) {
l += utf_char2bytes(wres[n], (char *)res + l);
if (l + MB_MAXBYTES > MAXWLEN) {
break;
@@ -3143,20 +3092,19 @@ void ex_spellinfo(exarg_T *eap)
// ":spelldump"
void ex_spelldump(exarg_T *eap)
{
- char *spl;
- long dummy;
-
if (no_spell_checking(curwin)) {
return;
}
+ char *spl;
+ long dummy;
(void)get_option_value("spl", &dummy, &spl, OPT_LOCAL);
// Create a new empty buffer in a new window.
do_cmdline_cmd("new");
// enable spelling locally in the new window
- set_option_value("spell", true, "", OPT_LOCAL);
- set_option_value("spl", dummy, spl, OPT_LOCAL);
+ set_option_value_give_err("spell", true, "", OPT_LOCAL);
+ set_option_value_give_err("spl", dummy, spl, OPT_LOCAL);
xfree(spl);
if (!buf_is_empty(curbuf)) {
@@ -3169,7 +3117,7 @@ void ex_spelldump(exarg_T *eap)
if (curbuf->b_ml.ml_line_count > 1) {
ml_delete(curbuf->b_ml.ml_line_count, false);
}
- redraw_later(curwin, NOT_VALID);
+ redraw_later(curwin, UPD_NOT_VALID);
}
/// Go through all possible words and:
@@ -3192,7 +3140,6 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg)
char_u *byts;
idx_T *idxs;
linenr_T lnum = 0;
- int round;
int depth;
int n;
int flags;
@@ -3220,7 +3167,7 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg)
// Find out if we can support regions: All languages must support the same
// regions or none at all.
- for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) {
+ for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; lpi++) {
lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
p = lp->lp_slang->sl_regions;
if (p[0] != 0) {
@@ -3243,7 +3190,7 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg)
}
// Loop over all files loaded for the entries in 'spelllang'.
- for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) {
+ for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; lpi++) {
lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
slang = lp->lp_slang;
if (slang->sl_fbyts == NULL) { // reloading failed
@@ -3265,7 +3212,7 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg)
// round 1: case-folded tree
// round 2: keep-case tree
- for (round = 1; round <= 2; ++round) {
+ for (int round = 1; round <= 2; round++) {
if (round == 1) {
dumpflags &= ~DUMPFLAG_KEEPCASE;
byts = slang->sl_fbyts;
@@ -3291,7 +3238,7 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg)
} else {
// Do one more byte at this node.
n = arridx[depth] + curi[depth];
- ++curi[depth];
+ curi[depth]++;
c = byts[n];
if (c == 0 || depth >= MAXWLEN - 1) {
// End of word or reached maximum length, deal with the
@@ -3359,10 +3306,8 @@ static void dump_word(slang_T *slang, char_u *word, char_u *pat, Direction *dir,
{
bool keepcap = false;
char_u *p;
- char_u *tw;
char_u cword[MAXWLEN];
char_u badword[MAXWLEN + 10];
- int i;
int flags = wordflags;
if (dumpflags & DUMPFLAG_ONECAP) {
@@ -3384,7 +3329,7 @@ static void dump_word(slang_T *slang, char_u *word, char_u *pat, Direction *dir,
keepcap = true;
}
}
- tw = p;
+ char_u *tw = p;
if (pat == NULL) {
// Add flags and regions after a slash.
@@ -3400,7 +3345,7 @@ static void dump_word(slang_T *slang, char_u *word, char_u *pat, Direction *dir,
STRCAT(badword, "?");
}
if (flags & WF_REGION) {
- for (i = 0; i < 7; i++) {
+ for (int i = 0; i < 7; i++) {
if (flags & (0x10000 << i)) {
const size_t badword_len = STRLEN(badword);
snprintf((char *)badword + badword_len,
@@ -3451,34 +3396,27 @@ static linenr_T dump_prefixes(slang_T *slang, char_u *word, char_u *pat, Directi
char_u prefix[MAXWLEN];
char_u word_up[MAXWLEN];
bool has_word_up = false;
- int c;
- char_u *byts;
- idx_T *idxs;
linenr_T lnum = startlnum;
- int depth;
- int n;
- int len;
- int i;
// If the word starts with a lower-case letter make the word with an
// upper-case letter in word_up[].
- c = utf_ptr2char((char *)word);
+ int c = utf_ptr2char((char *)word);
if (SPELL_TOUPPER(c) != c) {
onecap_copy(word, word_up, true);
has_word_up = true;
}
- byts = slang->sl_pbyts;
- idxs = slang->sl_pidxs;
+ char_u *byts = slang->sl_pbyts;
+ idx_T *idxs = slang->sl_pidxs;
if (byts != NULL) { // array not is empty
// Loop over all prefixes, building them byte-by-byte in prefix[].
// When at the end of a prefix check that it supports "flags".
- depth = 0;
+ int depth = 0;
arridx[0] = 0;
curi[0] = 1;
while (depth >= 0 && !got_int) {
- n = arridx[depth];
- len = byts[n];
+ int n = arridx[depth];
+ int len = byts[n];
if (curi[depth] > len) {
// Done all bytes at this node, go up one level.
depth--;
@@ -3486,11 +3424,12 @@ static linenr_T dump_prefixes(slang_T *slang, char_u *word, char_u *pat, Directi
} else {
// Do one more byte at this node.
n += curi[depth];
- ++curi[depth];
+ curi[depth]++;
c = byts[n];
if (c == 0) {
// End of prefix, find out how many IDs there are.
- for (i = 1; i < len; ++i) {
+ int i;
+ for (i = 1; i < len; i++) {
if (byts[n + i] != 0) {
break;
}
@@ -3501,8 +3440,7 @@ static linenr_T dump_prefixes(slang_T *slang, char_u *word, char_u *pat, Directi
if (c != 0) {
STRLCPY(prefix + depth, word, MAXWLEN - depth);
dump_word(slang, prefix, pat, dir, dumpflags,
- (c & WF_RAREPFX) ? (flags | WF_RARE)
- : flags, lnum);
+ (c & WF_RAREPFX) ? (flags | WF_RARE) : flags, lnum);
if (lnum != 0) {
lnum++;
}
@@ -3517,8 +3455,7 @@ static linenr_T dump_prefixes(slang_T *slang, char_u *word, char_u *pat, Directi
if (c != 0) {
STRLCPY(prefix + depth, word_up, MAXWLEN - depth);
dump_word(slang, prefix, pat, dir, dumpflags,
- (c & WF_RAREPFX) ? (flags | WF_RARE)
- : flags, lnum);
+ (c & WF_RAREPFX) ? (flags | WF_RARE) : flags, lnum);
if (lnum != 0) {
lnum++;
}
@@ -3556,16 +3493,14 @@ char_u *spell_to_word_end(char_u *start, win_T *win)
// Returns the column number of the word.
int spell_word_start(int startcol)
{
- char_u *line;
- char_u *p;
- int col = 0;
-
if (no_spell_checking(curwin)) {
return startcol;
}
+ char_u *line = get_cursor_line_ptr();
+ char_u *p;
+
// Find a word character before "startcol".
- line = get_cursor_line_ptr();
for (p = line + startcol; p > line;) {
MB_PTR_BACK(line, p);
if (spell_iswordp_nmw(p, curwin)) {
@@ -3573,6 +3508,8 @@ int spell_word_start(int startcol)
}
}
+ int col = 0;
+
// Go back to start of the word.
while (p > line) {
col = (int)(p - line);
@@ -3608,18 +3545,18 @@ int expand_spelling(linenr_T lnum, char_u *pat, char ***matchp)
return ga.ga_len;
}
-/// Return true if "val" is a valid 'spelllang' value.
-bool valid_spelllang(const char_u *val)
+/// @return true if "val" is a valid 'spelllang' value.
+bool valid_spelllang(const char *val)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return valid_name(val, ".-_,@");
}
-/// Return true if "val" is a valid 'spellfile' value.
-bool valid_spellfile(const char_u *val)
+/// @return true if "val" is a valid 'spellfile' value.
+bool valid_spellfile(const char *val)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- for (const char_u *s = val; *s != NUL; s++) {
+ for (const char_u *s = (char_u *)val; *s != NUL; s++) {
if (!vim_isfilec(*s) && *s != ',' && *s != ' ') {
return false;
}
@@ -3657,14 +3594,13 @@ char *compile_cap_prog(synblock_T *synblock)
FUNC_ATTR_NONNULL_ALL
{
regprog_T *rp = synblock->b_cap_prog;
- char_u *re;
if (synblock->b_p_spc == NULL || *synblock->b_p_spc == NUL) {
synblock->b_cap_prog = NULL;
} else {
// Prepend a ^ so that we only match at one column
- re = concat_str((char_u *)"^", synblock->b_p_spc);
- synblock->b_cap_prog = vim_regcomp((char *)re, RE_MAGIC);
+ char *re = concat_str("^", synblock->b_p_spc);
+ synblock->b_cap_prog = vim_regcomp(re, RE_MAGIC);
xfree(re);
if (synblock->b_cap_prog == NULL) {
synblock->b_cap_prog = rp; // restore the previous program
diff --git a/src/nvim/spell_defs.h b/src/nvim/spell_defs.h
index 61f722b9ee..27b9777dc2 100644
--- a/src/nvim/spell_defs.h
+++ b/src/nvim/spell_defs.h
@@ -115,9 +115,9 @@ typedef struct slang_S slang_T;
struct slang_S {
slang_T *sl_next; // next language
- char_u *sl_name; // language name "en", "en.rare", "nl", etc.
- char_u *sl_fname; // name of .spl file
- bool sl_add; // true if it's a .add file.
+ char_u *sl_name; // language name "en", "en.rare", "nl", etc.
+ char *sl_fname; // name of .spl file
+ bool sl_add; // true if it's a .add file.
char_u *sl_fbyts; // case-folded word bytes
long sl_fbyts_len; // length of sl_fbyts
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index be1373f617..0f8034312e 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -440,7 +440,7 @@ typedef struct spellinfo_S {
sblock_T *si_blocks; // memory blocks used
long si_blocks_cnt; // memory blocks allocated
- int si_did_emsg; // TRUE when ran out of memory
+ int si_did_emsg; // true when ran out of memory
long si_compress_cnt; // words to add before lowering
// compression limit
@@ -454,7 +454,7 @@ typedef struct spellinfo_S {
int si_ascii; // handling only ASCII words
int si_add; // addition file
- int si_clear_chartab; // when TRUE clear char tables
+ int si_clear_chartab; // when true clear char tables
int si_region; // region mask
vimconv_T si_conv; // for conversion to 'encoding'
int si_memtot; // runtime memory used
@@ -604,7 +604,7 @@ slang_T *spell_load_file(char_u *fname, char_u *lang, slang_T *old_lp, bool sile
lp = slang_alloc(lang);
// Remember the file name, used to reload the file when it's updated.
- lp->sl_fname = vim_strsave(fname);
+ lp->sl_fname = (char *)vim_strsave(fname);
// Check for .add.spl.
lp->sl_add = strstr(path_tail((char *)fname), SPL_FNAME_ADD) != NULL;
@@ -845,12 +845,12 @@ static void tree_count_words(char_u *byts, idx_T *idxs)
} else {
// Do one more byte at this node.
n = arridx[depth] + curi[depth];
- ++curi[depth];
+ curi[depth]++;
c = byts[n];
if (c == 0) {
// End of word, count it.
- ++wordcount[depth];
+ wordcount[depth]++;
// Skip over any other NUL bytes (same word with different
// flags).
@@ -869,12 +869,12 @@ static void tree_count_words(char_u *byts, idx_T *idxs)
}
}
-// Load the .sug files for languages that have one and weren't loaded yet.
+/// Load the .sug files for languages that have one and weren't loaded yet.
void suggest_load_files(void)
{
langp_T *lp;
slang_T *slang;
- char_u *dotp;
+ char *dotp;
FILE *fd;
char_u buf[MAXWLEN];
int i;
@@ -885,7 +885,7 @@ void suggest_load_files(void)
int c;
// Do this for all languages that support sound folding.
- for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) {
+ for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; lpi++) {
lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
slang = lp->lp_slang;
if (slang->sl_sugtime != 0 && !slang->sl_sugloaded) {
@@ -894,12 +894,12 @@ void suggest_load_files(void)
// don't try again and again.
slang->sl_sugloaded = true;
- dotp = STRRCHR(slang->sl_fname, '.');
+ dotp = strrchr(slang->sl_fname, '.');
if (dotp == NULL || FNAMECMP(dotp, ".spl") != 0) {
continue;
}
STRCPY(dotp, ".sug");
- fd = os_fopen((char *)slang->sl_fname, "r");
+ fd = os_fopen(slang->sl_fname, "r");
if (fd == NULL) {
goto nextone;
}
@@ -960,7 +960,7 @@ someerror:
// Read all the wordnr lists into the buffer, one NUL terminated
// list per line.
ga_init(&ga, 1, 100);
- for (wordnr = 0; wordnr < wcount; ++wordnr) {
+ for (wordnr = 0; wordnr < wcount; wordnr++) {
ga.ga_len = 0;
for (;;) {
c = getc(fd); // <sugline>
@@ -1142,10 +1142,10 @@ static int read_rep_section(FILE *fd, garray_T *gap, int16_t *first)
}
// Fill the first-index table.
- for (int i = 0; i < 256; ++i) {
+ for (int i = 0; i < 256; i++) {
first[i] = -1;
}
- for (int i = 0; i < gap->ga_len; ++i) {
+ for (int i = 0; i < gap->ga_len; i++) {
ftp = &((fromto_T *)gap->ga_data)[i];
if (first[*ftp->ft_from] == -1) {
first[*ftp->ft_from] = (int16_t)i;
@@ -1200,7 +1200,7 @@ static int read_sal_section(FILE *fd, slang_T *slang)
// Read up to the first special char into sm_lead.
int i = 0;
- for (; i < ccnt; ++i) {
+ for (; i < ccnt; i++) {
c = getc(fd); // <salfrom>
if (vim_strchr("0123456789(-<^$", c) != NULL) {
break;
@@ -1213,7 +1213,7 @@ static int read_sal_section(FILE *fd, slang_T *slang)
// Put (abc) chars in sm_oneof, if any.
if (c == '(') {
smp->sm_oneof = p;
- for (++i; i < ccnt; ++i) {
+ for (++i; i < ccnt; i++) {
c = getc(fd); // <salfrom>
if (c == ')') {
break;
@@ -1299,7 +1299,7 @@ static int read_words_section(FILE *fd, slang_T *lp, int len)
while (done < len) {
// Read one word at a time.
- for (i = 0;; ++i) {
+ for (i = 0;; i++) {
c = getc(fd);
if (c == EOF) {
return SP_TRUNCERROR;
@@ -1597,7 +1597,7 @@ static void set_sal_first(slang_T *lp)
garray_T *gap = &lp->sl_sal;
sfirst = lp->sl_sal_first;
- for (int i = 0; i < 256; ++i) {
+ for (int i = 0; i < 256; i++) {
sfirst[i] = -1;
}
smp = (salitem_T *)gap->ga_data;
@@ -1732,7 +1732,7 @@ static idx_T read_tree_node(FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx
byts[idx++] = (char_u)len;
// Read the byte values, flag/region bytes and shared indexes.
- for (i = 1; i <= len; ++i) {
+ for (i = 1; i <= len; i++) {
c = getc(fd); // <byte>
if (c < 0) {
return SP_TRUNCERROR;
@@ -1795,7 +1795,7 @@ static idx_T read_tree_node(FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx
// Recursively read the children for non-shared siblings.
// Skip the end-of-word ones (zero byte value) and the shared ones (and
// remove SHARED_MASK)
- for (i = 1; i <= len; ++i) {
+ for (i = 1; i <= len; i++) {
if (byts[startidx + i] != 0) {
if (idxs[startidx + i] & SHARED_MASK) {
idxs[startidx + i] &= ~SHARED_MASK;
@@ -1822,13 +1822,13 @@ static void spell_reload_one(char_u *fname, bool added_word)
bool didit = false;
for (slang = first_lang; slang != NULL; slang = slang->sl_next) {
- if (path_full_compare((char *)fname, (char *)slang->sl_fname, false, true) == kEqualFiles) {
+ if (path_full_compare((char *)fname, slang->sl_fname, false, true) == kEqualFiles) {
slang_clear(slang);
if (spell_load_file(fname, NULL, slang, false) == NULL) {
// reloading failed, clear the language
slang_clear(slang);
}
- redraw_all_later(SOME_VALID);
+ redraw_all_later(UPD_SOME_VALID);
didit = true;
}
}
@@ -1863,7 +1863,7 @@ static long compress_added = 500000; // word count
// Sets "sps_flags".
int spell_check_msm(void)
{
- char *p = (char *)p_msm;
+ char *p = p_msm;
long start = 0;
long incr = 0;
long added = 0;
@@ -1924,7 +1924,7 @@ static void spell_clear_flags(wordnode_T *node)
wordnode_T *np;
for (np = node; np != NULL; np = np->wn_sibling) {
- np->wn_u1.index = FALSE;
+ np->wn_u1.index = false;
spell_clear_flags(np->wn_child);
}
}
@@ -1940,7 +1940,7 @@ static void spell_print_node(wordnode_T *node, int depth)
msg((char_u *)line2);
msg((char_u *)line3);
} else {
- node->wn_u1.index = TRUE;
+ node->wn_u1.index = true;
if (node->wn_byte != NUL) {
if (node->wn_child != NULL) {
@@ -2042,7 +2042,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
}
vim_snprintf((char *)IObuff, IOSIZE, _("Reading affix file %s..."), fname);
- spell_message(spin, IObuff);
+ spell_message(spin, (char *)IObuff);
// Only do REP lines when not done in another .aff file already.
do_rep = GA_EMPTY(&spin->si_rep);
@@ -2075,7 +2075,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// Convert from "SET" to 'encoding' when needed.
xfree(pc);
if (spin->si_conv.vc_type != CONV_NONE) {
- pc = string_convert(&spin->si_conv, rline, NULL);
+ pc = (char_u *)string_convert(&spin->si_conv, (char *)rline, NULL);
if (pc == NULL) {
smsg(_("Conversion failure for word in %s line %d: %s"),
fname, lnum, rline);
@@ -2121,10 +2121,9 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
if (itemcnt > 0) {
if (is_aff_rule(items, itemcnt, "SET", 2) && aff->af_enc == NULL) {
// Setup for conversion from "ENC" to 'encoding'.
- aff->af_enc = enc_canonize(items[1]);
+ aff->af_enc = (char_u *)enc_canonize((char *)items[1]);
if (!spin->si_ascii
- && convert_setup(&spin->si_conv, aff->af_enc,
- p_enc) == FAIL) {
+ && convert_setup(&spin->si_conv, (char *)aff->af_enc, p_enc) == FAIL) {
smsg(_("Conversion in %s not supported: from %s to %s"),
fname, aff->af_enc, p_enc);
}
@@ -2168,9 +2167,8 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
STRCAT(p, " ");
STRCAT(p, items[1]);
spin->si_info = p;
- } else if (is_aff_rule(items, itemcnt, "MIDWORD", 2)
- && midword == NULL) {
- midword = getroom_save(spin, items[1]);
+ } else if (is_aff_rule(items, itemcnt, "MIDWORD", 2) && midword == NULL) {
+ midword = (char_u *)getroom_save(spin, items[1]);
} else if (is_aff_rule(items, itemcnt, "TRY", 2)) {
// ignored, we look in the tree for what chars may appear
}
@@ -2308,12 +2306,12 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
}
if (i >= gap->ga_len) {
ga_grow(gap, 2);
- ((char **)(gap->ga_data))[gap->ga_len++] = (char *)getroom_save(spin, items[1]);
- ((char **)(gap->ga_data))[gap->ga_len++] = (char *)getroom_save(spin, items[2]);
+ ((char **)(gap->ga_data))[gap->ga_len++] = getroom_save(spin, items[1]);
+ ((char **)(gap->ga_data))[gap->ga_len++] = getroom_save(spin, items[2]);
}
} else if (is_aff_rule(items, itemcnt, "SYLLABLE", 2)
&& syllable == NULL) {
- syllable = getroom_save(spin, items[1]);
+ syllable = (char_u *)getroom_save(spin, items[1]);
} else if (is_aff_rule(items, itemcnt, "NOBREAK", 1)) {
spin->si_nobreak = true;
} else if (is_aff_rule(items, itemcnt, "NOSPLITSUGS", 1)) {
@@ -2446,10 +2444,10 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
aff_entry = getroom(spin, sizeof(*aff_entry), true);
if (STRCMP(items[2], "0") != 0) {
- aff_entry->ae_chop = getroom_save(spin, items[2]);
+ aff_entry->ae_chop = (char_u *)getroom_save(spin, items[2]);
}
if (STRCMP(items[3], "0") != 0) {
- aff_entry->ae_add = getroom_save(spin, items[3]);
+ aff_entry->ae_add = (char_u *)getroom_save(spin, items[3]);
// Recognize flags on the affix: abcd/XYZ
aff_entry->ae_flags = (char_u *)vim_strchr((char *)aff_entry->ae_add, '/');
@@ -2469,7 +2467,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
if (STRCMP(items[4], ".") != 0) {
char_u buf[MAXLINELEN];
- aff_entry->ae_cond = getroom_save(spin, items[4]);
+ aff_entry->ae_cond = (char_u *)getroom_save(spin, items[4]);
if (*items[0] == 'P') {
sprintf((char *)buf, "^%s", items[4]);
} else {
@@ -2518,7 +2516,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
if (aff_entry->ae_cond != NULL) {
char_u buf[MAXLINELEN];
onecap_copy(items[4], buf, true);
- aff_entry->ae_cond = getroom_save(spin, buf);
+ aff_entry->ae_cond = (char_u *)getroom_save(spin, buf);
if (aff_entry->ae_cond != NULL) {
sprintf((char *)buf, "^%s",
aff_entry->ae_cond);
@@ -2548,7 +2546,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
idx = spin->si_prefcond.ga_len;
pp = GA_APPEND_VIA_PTR(char_u *, &spin->si_prefcond);
*pp = (aff_entry->ae_cond == NULL) ?
- NULL : getroom_save(spin, aff_entry->ae_cond);
+ NULL : (char_u *)getroom_save(spin, aff_entry->ae_cond);
}
// Add the prefix to the prefix tree.
@@ -2580,7 +2578,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// Didn't actually use ah_newID, backup si_newprefID.
if (aff_todo == 0 && !did_postpone_prefix) {
- --spin->si_newprefID;
+ spin->si_newprefID--;
cur_aff->ah_newID = 0;
}
}
@@ -2674,10 +2672,10 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
}
} else if (is_aff_rule(items, itemcnt, "SOFOFROM", 2)
&& sofofrom == NULL) {
- sofofrom = getroom_save(spin, items[1]);
+ sofofrom = (char_u *)getroom_save(spin, items[1]);
} else if (is_aff_rule(items, itemcnt, "SOFOTO", 2)
&& sofoto == NULL) {
- sofoto = getroom_save(spin, items[1]);
+ sofoto = (char_u *)getroom_save(spin, items[1]);
} else if (STRCMP(items[0], "COMMON") == 0) {
int i;
@@ -3043,9 +3041,9 @@ static void add_fromto(spellinfo_T *spin, garray_T *gap, char_u *from, char_u *t
fromto_T *ftp = GA_APPEND_VIA_PTR(fromto_T, gap);
(void)spell_casefold(curwin, from, (int)STRLEN(from), word, MAXWLEN);
- ftp->ft_from = getroom_save(spin, word);
+ ftp->ft_from = (char_u *)getroom_save(spin, word);
(void)spell_casefold(curwin, to, (int)STRLEN(to), word, MAXWLEN);
- ftp->ft_to = getroom_save(spin, word);
+ ftp->ft_to = (char_u *)getroom_save(spin, word);
}
// Converts a boolean argument in a SAL line to true or false;
@@ -3068,7 +3066,7 @@ static void spell_free_aff(afffile_T *aff)
// All this trouble to free the "ae_prog" items...
for (ht = &aff->af_pref;; ht = &aff->af_suff) {
todo = (int)ht->ht_used;
- for (hi = ht->ht_array; todo > 0; ++hi) {
+ for (hi = ht->ht_array; todo > 0; hi++) {
if (!HASHITEM_EMPTY(hi)) {
todo--;
ah = HI2AH(hi);
@@ -3125,7 +3123,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
vim_snprintf((char *)IObuff, IOSIZE,
_("Reading dictionary file %s..."), fname);
- spell_message(spin, IObuff);
+ spell_message(spin, (char *)IObuff);
// start with a message for the first line
spin->si_msg_count = 999999;
@@ -3157,7 +3155,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
// Convert from "SET" to 'encoding' when needed.
if (spin->si_conv.vc_type != CONV_NONE) {
- pc = string_convert(&spin->si_conv, line, NULL);
+ pc = (char_u *)string_convert(&spin->si_conv, (char *)line, NULL);
if (pc == NULL) {
smsg(_("Conversion failure for word in %s line %d: %s"),
fname, lnum, line);
@@ -3208,7 +3206,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
}
// Store the word in the hashtable to be able to find duplicates.
- dw = getroom_save(spin, w);
+ dw = (char_u *)getroom_save(spin, w);
if (dw == NULL) {
retval = FAIL;
xfree(pc);
@@ -3434,7 +3432,7 @@ static int store_aff_word(spellinfo_T *spin, char_u *word, char_u *afflist, afff
int use_condit;
todo = (int)ht->ht_used;
- for (hi = ht->ht_array; todo > 0 && retval == OK; ++hi) {
+ for (hi = ht->ht_array; todo > 0 && retval == OK; hi++) {
if (!HASHITEM_EMPTY(hi)) {
todo--;
ah = HI2AH(hi);
@@ -3540,8 +3538,8 @@ static int store_aff_word(spellinfo_T *spin, char_u *word, char_u *afflist, afff
// Combine the prefix IDs. Avoid adding the
// same ID twice.
- for (i = 0; i < pfxlen; ++i) {
- for (j = 0; j < use_pfxlen; ++j) {
+ for (i = 0; i < pfxlen; i++) {
+ for (j = 0; j < use_pfxlen; j++) {
if (pfxlist[i] == use_pfxlist[j]) {
break;
}
@@ -3562,9 +3560,8 @@ static int store_aff_word(spellinfo_T *spin, char_u *word, char_u *afflist, afff
// Combine the list of compound flags.
// Concatenate them to the prefix IDs list.
// Avoid adding the same ID twice.
- for (i = pfxlen; pfxlist[i] != NUL; ++i) {
- for (j = use_pfxlen;
- use_pfxlist[j] != NUL; ++j) {
+ for (i = pfxlen; pfxlist[i] != NUL; i++) {
+ for (j = use_pfxlen; use_pfxlist[j] != NUL; j++) {
if (pfxlist[i] == use_pfxlist[j]) {
break;
}
@@ -3679,7 +3676,7 @@ static int spell_read_wordfile(spellinfo_T *spin, char_u *fname)
}
vim_snprintf((char *)IObuff, IOSIZE, _("Reading word file %s..."), fname);
- spell_message(spin, IObuff);
+ spell_message(spin, (char *)IObuff);
// Read all the lines in the file one by one.
while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int) {
@@ -3704,7 +3701,7 @@ static int spell_read_wordfile(spellinfo_T *spin, char_u *fname)
// Convert from "/encoding={encoding}" to 'encoding' when needed.
xfree(pc);
if (spin->si_conv.vc_type != CONV_NONE) {
- pc = string_convert(&spin->si_conv, rline, NULL);
+ pc = (char_u *)string_convert(&spin->si_conv, (char *)rline, NULL);
if (pc == NULL) {
smsg(_("Conversion failure for word in %s line %ld: %s"),
fname, lnum, rline);
@@ -3726,14 +3723,13 @@ static int spell_read_wordfile(spellinfo_T *spin, char_u *fname)
smsg(_("/encoding= line after word ignored in %s line %ld: %s"),
fname, lnum, line - 1);
} else {
- char_u *enc;
+ char *enc;
// Setup for conversion to 'encoding'.
line += 9;
- enc = enc_canonize(line);
+ enc = enc_canonize((char *)line);
if (!spin->si_ascii
- && convert_setup(&spin->si_conv, enc,
- p_enc) == FAIL) {
+ && convert_setup(&spin->si_conv, enc, p_enc) == FAIL) {
smsg(_("Conversion in %s not supported: from %s to %s"),
fname, line, p_enc);
}
@@ -3824,7 +3820,7 @@ static int spell_read_wordfile(spellinfo_T *spin, char_u *fname)
if (spin->si_ascii && non_ascii > 0) {
vim_snprintf((char *)IObuff, IOSIZE,
_("Ignored %d words with non-ASCII characters"), non_ascii);
- spell_message(spin, IObuff);
+ spell_message(spin, (char *)IObuff);
}
return retval;
@@ -3858,7 +3854,7 @@ static void *getroom(spellinfo_T *spin, size_t len, bool align)
bl->sb_next = spin->si_blocks;
spin->si_blocks = bl;
bl->sb_used = 0;
- ++spin->si_blocks_cnt;
+ spin->si_blocks_cnt++;
}
p = bl->sb_data + bl->sb_used;
@@ -3867,9 +3863,10 @@ static void *getroom(spellinfo_T *spin, size_t len, bool align)
return p;
}
-// Make a copy of a string into memory allocated with getroom().
-// Returns NULL when out of memory.
-static char_u *getroom_save(spellinfo_T *spin, char_u *s)
+/// Make a copy of a string into memory allocated with getroom().
+///
+/// @return NULL when out of memory.
+static char *getroom_save(spellinfo_T *spin, char_u *s)
{
const size_t s_size = STRLEN(s) + 1;
return memcpy(getroom(spin, s_size, false), s, s_size);
@@ -3897,13 +3894,13 @@ static wordnode_T *wordtree_alloc(spellinfo_T *spin)
/// Return true if "word" contains valid word characters.
/// Control characters and trailing '/' are invalid. Space is OK.
-static bool valid_spell_word(const char_u *word, const char_u *end)
+static bool valid_spell_word(const char *word, const char *end)
{
- if (!utf_valid_string(word, end)) {
+ if (!utf_valid_string((char_u *)word, (char_u *)end)) {
return false;
}
- for (const char_u *p = word; *p != NUL && p < end; p += utfc_ptr2len((const char *)p)) {
- if (*p < ' ' || (p[0] == '/' && p[1] == NUL)) {
+ for (const char *p = word; *p != NUL && p < end; p += utfc_ptr2len(p)) {
+ if ((uint8_t)(*p) < ' ' || (p[0] == '/' && p[1] == NUL)) {
return false;
}
}
@@ -3931,7 +3928,7 @@ static int store_word(spellinfo_T *spin, char_u *word, int flags, int region, co
int res = OK;
// Avoid adding illegal bytes to the word tree.
- if (!valid_spell_word(word, word + len)) {
+ if (!valid_spell_word((char *)word, (char *)word + len)) {
return FAIL;
}
@@ -3945,7 +3942,7 @@ static int store_word(spellinfo_T *spin, char_u *word, int flags, int region, co
break;
}
}
- ++spin->si_foldwcount;
+ spin->si_foldwcount++;
if (res == OK && (ct == WF_KEEPCAP || (flags & WF_KEEPCAP))) {
for (const char_u *p = pfxlist; res == OK; p++) {
@@ -3957,7 +3954,7 @@ static int store_word(spellinfo_T *spin, char_u *word, int flags, int region, co
break;
}
}
- ++spin->si_keepwcount;
+ spin->si_keepwcount++;
}
return res;
}
@@ -3976,12 +3973,12 @@ static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int
int i;
// Add each byte of the word to the tree, including the NUL at the end.
- for (i = 0;; ++i) {
+ for (i = 0;; i++) {
// When there is more than one reference to this node we need to make
// a copy, so that we can modify it. Copy the whole list of siblings
// (we don't optimize for a partly shared list of siblings).
if (node != NULL && node->wn_refs > 1) {
- --node->wn_refs;
+ node->wn_refs--;
copyprev = prev;
for (copyp = node; copyp != NULL; copyp = copyp->wn_sibling) {
// Allocate a new node and copy the info.
@@ -3991,7 +3988,7 @@ static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int
}
np->wn_child = copyp->wn_child;
if (np->wn_child != NULL) {
- ++np->wn_child->wn_refs; // child gets extra ref
+ np->wn_child->wn_refs++; // child gets extra ref
}
np->wn_byte = copyp->wn_byte;
if (np->wn_byte == NUL) {
@@ -4078,7 +4075,7 @@ static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int
#endif
// count nr of words added since last message
- ++spin->si_msg_count;
+ spin->si_msg_count++;
if (spin->si_compress_cnt > 1) {
if (--spin->si_compress_cnt == 1) {
@@ -4173,7 +4170,7 @@ static int deref_wordnode(spellinfo_T *spin, wordnode_T *node)
free_wordnode(spin, np);
cnt++;
}
- ++cnt; // length field
+ cnt++; // length field
}
return cnt;
}
@@ -4185,7 +4182,7 @@ static void free_wordnode(spellinfo_T *spin, wordnode_T *n)
{
n->wn_child = spin->si_first_free;
spin->si_first_free = n;
- ++spin->si_free_count;
+ spin->si_free_count++;
}
// Compress a tree: find tails that are identical and can be shared.
@@ -4216,7 +4213,7 @@ static void wordtree_compress(spellinfo_T *spin, wordnode_T *root, const char *n
vim_snprintf((char *)IObuff, IOSIZE,
_("Compressed %s of %ld nodes; %ld (%ld%%) remaining"),
name, tot, tot - n, perc);
- spell_message(spin, IObuff);
+ spell_message(spin, (char *)IObuff);
}
#ifdef SPELL_PRINTTREE
spell_print_tree(root->wn_sibling);
@@ -4264,7 +4261,7 @@ static long node_compress(spellinfo_T *spin, wordnode_T *node, hashtab_T *ht, lo
// Found one! Now use that child in place of the
// current one. This means the current child and all
// its siblings is unlinked from the tree.
- ++tp->wn_refs;
+ tp->wn_refs++;
compressed += deref_wordnode(spin, child);
np->wn_child = tp;
break;
@@ -4350,14 +4347,15 @@ static int rep_compare(const void *s1, const void *s2)
return STRCMP(p1->ft_from, p2->ft_from);
}
-// Write the Vim .spl file "fname".
-// Return OK/FAIL.
-static int write_vim_spell(spellinfo_T *spin, char_u *fname)
+/// Write the Vim .spl file "fname".
+///
+/// @return OK/FAIL.
+static int write_vim_spell(spellinfo_T *spin, char *fname)
{
int retval = OK;
int regionmask;
- FILE *fd = os_fopen((char *)fname, "w");
+ FILE *fd = os_fopen(fname, "w");
if (fd == NULL) {
semsg(_(e_notopen), fname);
return FAIL;
@@ -4422,7 +4420,7 @@ static int write_vim_spell(spellinfo_T *spin, char_u *fname)
put_bytes(fd, 1 + 128 + 2 + l, 4); // <sectionlen>
fputc(128, fd); // <charflagslen>
- for (size_t i = 128; i < 256; ++i) {
+ for (size_t i = 128; i < 256; i++) {
flags = 0;
if (spelltab.st_isw[i]) {
flags |= CF_WORD;
@@ -4466,7 +4464,7 @@ static int write_vim_spell(spellinfo_T *spin, char_u *fname)
// round 1: SN_REP section
// round 2: SN_SAL section (unless SN_SOFO is used)
// round 3: SN_REPSAL section
- for (unsigned int round = 1; round <= 3; ++round) {
+ for (unsigned int round = 1; round <= 3; round++) {
garray_T *gap;
if (round == 1) {
gap = &spin->si_rep;
@@ -4500,13 +4498,13 @@ static int write_vim_spell(spellinfo_T *spin, char_u *fname)
// Compute the length of what follows.
size_t l = 2; // count <repcount> or <salcount>
assert(gap->ga_len >= 0);
- for (size_t i = 0; i < (size_t)gap->ga_len; ++i) {
+ for (size_t i = 0; i < (size_t)gap->ga_len; i++) {
fromto_T *ftp = &((fromto_T *)gap->ga_data)[i];
l += 1 + STRLEN(ftp->ft_from); // count <*fromlen> and <*from>
l += 1 + STRLEN(ftp->ft_to); // count <*tolen> and <*to>
}
if (round == 2) {
- ++l; // count <salflags>
+ l++; // count <salflags>
}
put_bytes(fd, l, 4); // <sectionlen>
@@ -4525,11 +4523,11 @@ static int write_vim_spell(spellinfo_T *spin, char_u *fname)
}
put_bytes(fd, (uintmax_t)gap->ga_len, 2); // <repcount> or <salcount>
- for (size_t i = 0; i < (size_t)gap->ga_len; ++i) {
+ for (size_t i = 0; i < (size_t)gap->ga_len; i++) {
// <rep> : <repfromlen> <repfrom> <reptolen> <repto>
// <sal> : <salfromlen> <salfrom> <saltolen> <salto>
fromto_T *ftp = &((fromto_T *)gap->ga_data)[i];
- for (unsigned int rr = 1; rr <= 2; ++rr) {
+ for (unsigned int rr = 1; rr <= 2; rr++) {
char_u *p = rr == 1 ? ftp->ft_from : ftp->ft_to;
l = STRLEN(p);
assert(l < INT_MAX);
@@ -4566,13 +4564,13 @@ static int write_vim_spell(spellinfo_T *spin, char_u *fname)
// round 1: count the bytes
// round 2: write the bytes
- for (unsigned int round = 1; round <= 2; ++round) {
+ for (unsigned int round = 1; round <= 2; round++) {
size_t todo;
size_t len = 0;
hashitem_T *hi;
todo = spin->si_commonwords.ht_used;
- for (hi = spin->si_commonwords.ht_array; todo > 0; ++hi) {
+ for (hi = spin->si_commonwords.ht_array; todo > 0; hi++) {
if (!HASHITEM_EMPTY(hi)) {
size_t l = STRLEN(hi->hi_key) + 1;
len += l;
@@ -4689,7 +4687,7 @@ static int write_vim_spell(spellinfo_T *spin, char_u *fname)
// <LWORDTREE> <KWORDTREE> <PREFIXTREE>
spin->si_memtot = 0;
- for (unsigned int round = 1; round <= 3; ++round) {
+ for (unsigned int round = 1; round <= 3; round++) {
wordnode_T *tree;
if (round == 1) {
tree = spin->si_foldroot->wn_sibling;
@@ -4878,12 +4876,12 @@ void ex_mkspell(exarg_T *eap)
{
int fcount;
char **fnames;
- char_u *arg = (char_u *)eap->arg;
+ char *arg = eap->arg;
bool ascii = false;
if (STRNCMP(arg, "-ascii", 6) == 0) {
ascii = true;
- arg = (char_u *)skipwhite((char *)arg + 6);
+ arg = skipwhite(arg + 6);
}
// Expand all the remaining arguments (e.g., $VIMRUNTIME).
@@ -4896,7 +4894,7 @@ void ex_mkspell(exarg_T *eap)
// Create the .sug file.
// Uses the soundfold info in "spin".
// Writes the file with the name "wfname", with ".spl" changed to ".sug".
-static void spell_make_sugfile(spellinfo_T *spin, char_u *wfname)
+static void spell_make_sugfile(spellinfo_T *spin, char *wfname)
{
char_u *fname = NULL;
int len;
@@ -4909,14 +4907,14 @@ static void spell_make_sugfile(spellinfo_T *spin, char_u *wfname)
// of the code for the soundfolding stuff.
// It might have been done already by spell_reload_one().
for (slang = first_lang; slang != NULL; slang = slang->sl_next) {
- if (path_full_compare((char *)wfname, (char *)slang->sl_fname, false, true)
+ if (path_full_compare(wfname, slang->sl_fname, false, true)
== kEqualFiles) {
break;
}
}
if (slang == NULL) {
- spell_message(spin, (char_u *)_("Reading back spell file..."));
- slang = spell_load_file(wfname, NULL, NULL, false);
+ spell_message(spin, _("Reading back spell file..."));
+ slang = spell_load_file((char_u *)wfname, NULL, NULL, false);
if (slang == NULL) {
return;
}
@@ -4933,7 +4931,7 @@ static void spell_make_sugfile(spellinfo_T *spin, char_u *wfname)
// Go through the trie of good words, soundfold each word and add it to
// the soundfold trie.
- spell_message(spin, (char_u *)_("Performing soundfolding..."));
+ spell_message(spin, _("Performing soundfolding..."));
if (sug_filltree(spin, slang) == FAIL) {
goto theend;
}
@@ -4950,7 +4948,7 @@ static void spell_make_sugfile(spellinfo_T *spin, char_u *wfname)
(int64_t)spin->si_spellbuf->b_ml.ml_line_count);
// Compress the soundfold trie.
- spell_message(spin, (char_u *)_(msg_compressing));
+ spell_message(spin, _(msg_compressing));
wordtree_compress(spin, spin->si_foldroot, "case-folded");
// Write the .sug file.
@@ -5015,7 +5013,7 @@ static int sug_filltree(spellinfo_T *spin, slang_T *slang)
} else {
// Do one more byte at this node.
n = arridx[depth] + curi[depth];
- ++curi[depth];
+ curi[depth]++;
c = byts[n];
if (c == 0) {
@@ -5196,7 +5194,7 @@ static void sug_write(spellinfo_T *spin, char_u *fname)
vim_snprintf((char *)IObuff, IOSIZE,
_("Writing suggestion file %s..."), fname);
- spell_message(spin, IObuff);
+ spell_message(spin, (char *)IObuff);
// <SUGHEADER>: <fileID> <versionnr> <timestamp>
if (fwrite(VIMSUGMAGIC, VIMSUGMAGICL, (size_t)1, fd) != 1) { // <fileID>
@@ -5233,7 +5231,7 @@ static void sug_write(spellinfo_T *spin, char_u *fname)
assert(wcount >= 0);
put_bytes(fd, (uintmax_t)wcount, 4); // <sugwcount>
- for (linenr_T lnum = 1; lnum <= wcount; ++lnum) {
+ for (linenr_T lnum = 1; lnum <= wcount; lnum++) {
// <sugline>: <sugnr> ... NUL
char_u *line = ml_get_buf(spin->si_spellbuf, lnum, false);
size_t len = STRLEN(line) + 1;
@@ -5252,7 +5250,7 @@ static void sug_write(spellinfo_T *spin, char_u *fname)
vim_snprintf((char *)IObuff, IOSIZE,
_("Estimated runtime memory use: %d bytes"), spin->si_memtot);
- spell_message(spin, IObuff);
+ spell_message(spin, (char *)IObuff);
theend:
// close the file
@@ -5271,7 +5269,6 @@ theend:
static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool added_word)
{
char_u *fname = NULL;
- char_u *wfname;
char **innames;
int incount;
afffile_T *(afile[MAXREGIONS]);
@@ -5299,7 +5296,7 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
innames = &fnames[fcount == 1 ? 0 : 1];
incount = fcount - 1;
- wfname = xmalloc(MAXPATHL);
+ char *wfname = xmalloc(MAXPATHL);
if (fcount >= 1) {
len = (int)STRLEN(fnames[0]);
@@ -5307,42 +5304,42 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
// For ":mkspell path/en.latin1.add" output file is
// "path/en.latin1.add.spl".
incount = 1;
- vim_snprintf((char *)wfname, MAXPATHL, "%s.spl", fnames[0]);
+ vim_snprintf(wfname, MAXPATHL, "%s.spl", fnames[0]);
} else if (fcount == 1) {
// For ":mkspell path/vim" output file is "path/vim.latin1.spl".
incount = 1;
- vim_snprintf((char *)wfname, MAXPATHL, SPL_FNAME_TMPL,
+ vim_snprintf(wfname, MAXPATHL, SPL_FNAME_TMPL,
fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc());
} else if (len > 4 && STRCMP(fnames[0] + len - 4, ".spl") == 0) {
// Name ends in ".spl", use as the file name.
STRLCPY(wfname, fnames[0], MAXPATHL);
} else {
// Name should be language, make the file name from it.
- vim_snprintf((char *)wfname, MAXPATHL, SPL_FNAME_TMPL,
+ vim_snprintf(wfname, MAXPATHL, SPL_FNAME_TMPL,
fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc());
}
// Check for .ascii.spl.
- if (strstr(path_tail((char *)wfname), SPL_FNAME_ASCII) != NULL) {
+ if (strstr(path_tail(wfname), SPL_FNAME_ASCII) != NULL) {
spin.si_ascii = true;
}
// Check for .add.spl.
- if (strstr(path_tail((char *)wfname), SPL_FNAME_ADD) != NULL) {
+ if (strstr(path_tail(wfname), SPL_FNAME_ADD) != NULL) {
spin.si_add = true;
}
}
if (incount <= 0) {
emsg(_(e_invarg)); // need at least output and input names
- } else if (vim_strchr(path_tail((char *)wfname), '_') != NULL) {
+ } else if (vim_strchr(path_tail(wfname), '_') != NULL) {
emsg(_("E751: Output file name must not have region name"));
} else if (incount > MAXREGIONS) {
semsg(_("E754: Only up to %d regions supported"), MAXREGIONS);
} else {
// Check for overwriting before doing things that may take a lot of
// time.
- if (!over_write && os_path_exists(wfname)) {
+ if (!over_write && os_path_exists((char_u *)wfname)) {
emsg(_(e_exists));
goto theend;
}
@@ -5355,7 +5352,7 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
// Init the aff and dic pointers.
// Get the region names if there are more than 2 arguments.
- for (i = 0; i < incount; ++i) {
+ for (i = 0; i < incount; i++) {
afile[i] = NULL;
if (incount > 1) {
@@ -5387,7 +5384,7 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
// Read all the .aff and .dic files.
// Text is converted to 'encoding'.
// Words are stored in the case-folded and keep-case trees.
- for (i = 0; i < incount && !error; ++i) {
+ for (i = 0; i < incount && !error; i++) {
spin.si_conv.vc_type = CONV_NONE;
spin.si_region = 1 << i;
@@ -5424,7 +5421,7 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
if (!error && !got_int) {
// Combine tails in the tree.
- spell_message(&spin, (char_u *)_(msg_compressing));
+ spell_message(&spin, _(msg_compressing));
wordtree_compress(&spin, spin.si_foldroot, "case-folded");
wordtree_compress(&spin, spin.si_keeproot, "keep-case");
wordtree_compress(&spin, spin.si_prefroot, "prefixes");
@@ -5434,18 +5431,18 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
// Write the info in the spell file.
vim_snprintf((char *)IObuff, IOSIZE,
_("Writing spell file %s..."), wfname);
- spell_message(&spin, IObuff);
+ spell_message(&spin, (char *)IObuff);
error = write_vim_spell(&spin, wfname) == FAIL;
- spell_message(&spin, (char_u *)_("Done!"));
+ spell_message(&spin, _("Done!"));
vim_snprintf((char *)IObuff, IOSIZE,
_("Estimated runtime memory use: %d bytes"), spin.si_memtot);
- spell_message(&spin, IObuff);
+ spell_message(&spin, (char *)IObuff);
// If the file is loaded need to reload it.
if (!error) {
- spell_reload_one(wfname, added_word);
+ spell_reload_one((char_u *)wfname, added_word);
}
}
@@ -5459,7 +5456,7 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
hash_clear_all(&spin.si_commonwords, 0);
// Free the .aff file structures.
- for (i = 0; i < incount; ++i) {
+ for (i = 0; i < incount; i++) {
if (afile[i] != NULL) {
spell_free_aff(afile[i]);
}
@@ -5482,14 +5479,14 @@ theend:
// Display a message for spell file processing when 'verbose' is set or using
// ":mkspell". "str" can be IObuff.
-static void spell_message(const spellinfo_T *spin, char_u *str)
+static void spell_message(const spellinfo_T *spin, char *str)
FUNC_ATTR_NONNULL_ALL
{
if (spin->si_verbose || p_verbose > 2) {
if (!spin->si_verbose) {
verbose_enter();
}
- msg((char *)str);
+ msg(str);
ui_flush();
if (!spin->si_verbose) {
verbose_leave();
@@ -5527,7 +5524,7 @@ void spell_add_word(char_u *word, int len, SpellAddType what, int idx, bool undo
int i;
char_u *spf;
- if (!valid_spell_word(word, word + len)) {
+ if (!valid_spell_word((char *)word, (char *)word + len)) {
emsg(_(e_illegal_character_in_word));
return;
}
@@ -5553,7 +5550,7 @@ void spell_add_word(char_u *word, int len, SpellAddType what, int idx, bool undo
}
fnamebuf = xmalloc(MAXPATHL);
- for (spf = curwin->w_s->b_p_spf, i = 1; *spf != NUL; i++) {
+ for (spf = (char_u *)curwin->w_s->b_p_spf, i = 1; *spf != NUL; i++) {
copy_option_part((char **)&spf, (char *)fnamebuf, MAXPATHL, ",");
if (i == idx) {
break;
@@ -5667,7 +5664,7 @@ void spell_add_word(char_u *word, int len, SpellAddType what, int idx, bool undo
buf_reload(buf, buf->b_orig_mode, false);
}
- redraw_all_later(SOME_VALID);
+ redraw_all_later(UPD_SOME_VALID);
}
xfree(fnamebuf);
}
@@ -5681,14 +5678,14 @@ static void init_spellfile(void)
char_u *rtp;
char_u *lend;
bool aspath = false;
- char_u *lstart = curbuf->b_s.b_p_spl;
+ char_u *lstart = (char_u *)curbuf->b_s.b_p_spl;
if (*curwin->w_s->b_p_spl != NUL && !GA_EMPTY(&curwin->w_s->b_langp)) {
buf = xmalloc(MAXPATHL);
// Find the end of the language name. Exclude the region. If there
// is a path separator remember the start of the tail.
- for (lend = curwin->w_s->b_p_spl; *lend != NUL
+ for (lend = (char_u *)curwin->w_s->b_p_spl; *lend != NUL
&& vim_strchr(",._", *lend) == NULL; lend++) {
if (vim_ispathsep(*lend)) {
aspath = true;
@@ -5698,13 +5695,12 @@ static void init_spellfile(void)
// Loop over all entries in 'runtimepath'. Use the first one where we
// are allowed to write.
- rtp = p_rtp;
+ rtp = (char_u *)p_rtp;
while (*rtp != NUL) {
if (aspath) {
// Use directory of an entry with path, e.g., for
// "/dir/lg.utf-8.spl" use "/dir".
- STRLCPY(buf, curbuf->b_s.b_p_spl,
- lstart - curbuf->b_s.b_p_spl);
+ STRLCPY(buf, curbuf->b_s.b_p_spl, lstart - (char_u *)curbuf->b_s.b_p_spl);
} else {
// Copy the path from 'runtimepath' to buf[].
copy_option_part((char **)&rtp, (char *)buf, MAXPATHL, ",");
@@ -5713,8 +5709,7 @@ static void init_spellfile(void)
// Use the first language name from 'spelllang' and the
// encoding used in the first loaded .spl file.
if (aspath) {
- STRLCPY(buf, curbuf->b_s.b_p_spl,
- lend - curbuf->b_s.b_p_spl + 1);
+ STRLCPY(buf, curbuf->b_s.b_p_spl, lend - (char_u *)curbuf->b_s.b_p_spl + 1);
} else {
// Create the "spell" directory if it doesn't exist yet.
l = (int)STRLEN(buf);
@@ -5728,14 +5723,14 @@ static void init_spellfile(void)
"/%.*s", (int)(lend - lstart), lstart);
}
l = (int)STRLEN(buf);
- fname = LANGP_ENTRY(curwin->w_s->b_langp, 0)
+ fname = (char_u *)LANGP_ENTRY(curwin->w_s->b_langp, 0)
->lp_slang->sl_fname;
vim_snprintf((char *)buf + l, MAXPATHL - (size_t)l, ".%s.add",
((fname != NULL
&& strstr(path_tail((char *)fname), ".ascii.") != NULL)
? "ascii"
: (const char *)spell_enc()));
- set_option_value("spellfile", 0L, (const char *)buf, OPT_LOCAL);
+ set_option_value_give_err("spellfile", 0L, (const char *)buf, OPT_LOCAL);
break;
}
aspath = false;
@@ -5759,7 +5754,7 @@ static void set_spell_charflags(char_u *flags, int cnt, char_u *fol)
clear_spell_chartab(&new_st);
- for (i = 0; i < 128; ++i) {
+ for (i = 0; i < 128; i++) {
if (i < cnt) {
new_st.st_isw[i + 128] = (flags[i] & CF_WORD) != 0;
new_st.st_isu[i + 128] = (flags[i] & CF_UPPER) != 0;
@@ -5783,7 +5778,7 @@ static int set_spell_finish(spelltab_T *new_st)
if (did_set_spelltab) {
// check that it's the same table
- for (i = 0; i < 256; ++i) {
+ for (i = 0; i < 256; i++) {
if (spelltab.st_isw[i] != new_st->st_isw[i]
|| spelltab.st_isu[i] != new_st->st_isu[i]
|| spelltab.st_fold[i] != new_st->st_fold[i]
@@ -5846,7 +5841,7 @@ static void set_map_str(slang_T *lp, char_u *map)
lp->sl_has_map = true;
// Init the array and hash tables empty.
- for (i = 0; i < 256; ++i) {
+ for (i = 0; i < 256; i++) {
lp->sl_map_array[i] = 0;
}
hash_init(&lp->sl_map_hash);
diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c
index b4a9bed437..23c8c621b5 100644
--- a/src/nvim/spellsuggest.c
+++ b/src/nvim/spellsuggest.c
@@ -360,7 +360,7 @@ int spell_check_sps(void)
sps_flags = 0;
sps_limit = 9999;
- for (p = (char *)p_sps; *p != NUL;) {
+ for (p = p_sps; *p != NUL;) {
copy_option_part(&p, (char *)buf, MAXPATHL, ",");
f = 0;
@@ -758,7 +758,7 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma
}
// Make a copy of 'spellsuggest', because the expression may change it.
- sps_copy = vim_strsave(p_sps);
+ sps_copy = vim_strsave((char_u *)p_sps);
// Loop over the items in 'spellsuggest'.
for (p = (char *)sps_copy; *p != NUL;) {
@@ -972,7 +972,7 @@ static void suggest_try_special(suginfo_T *su)
char_u word[MAXWLEN];
// Recognize a word that is repeated: "the the".
- char_u *p = skiptowhite(su->su_fbadword);
+ char_u *p = (char_u *)skiptowhite((char *)su->su_fbadword);
size_t len = (size_t)(p - su->su_fbadword);
p = (char_u *)skipwhite((char *)p);
if (STRLEN(p) == len && STRNCMP(su->su_fbadword, p, len) == 0) {
@@ -1369,8 +1369,8 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
if (compound_ok) {
p = preword;
- while (*skiptowhite(p) != NUL) {
- p = (char_u *)skipwhite((char *)skiptowhite(p));
+ while (*skiptowhite((char *)p) != NUL) {
+ p = (char_u *)skipwhite(skiptowhite((char *)p));
}
if (fword_ends && !can_compound(slang, p,
compflags + sp->ts_compsplit)) {
@@ -1590,8 +1590,8 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
break;
}
p = preword;
- while (*skiptowhite(p) != NUL) {
- p = (char_u *)skipwhite((char *)skiptowhite(p));
+ while (*skiptowhite((char *)p) != NUL) {
+ p = (char_u *)skipwhite(skiptowhite((char *)p));
}
if (sp->ts_complen > sp->ts_compsplit
&& !can_compound(slang, p,
@@ -2636,8 +2636,8 @@ static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char_u *
// removing the space. Don't do it when the good word also contains a
// space.
if (ascii_iswhite(su->su_badptr[su->su_badlen])
- && *skiptowhite(stp->st_word) == NUL) {
- for (p = fword; *(p = skiptowhite(p)) != NUL;) {
+ && *skiptowhite((char *)stp->st_word) == NUL) {
+ for (p = fword; *(p = (char_u *)skiptowhite((char *)p)) != NUL;) {
STRMOVE(p, p + 1);
}
}
@@ -3100,7 +3100,7 @@ static void add_suggestion(suginfo_T *su, garray_T *gap, const char_u *goodword,
// being replaced "thes," -> "these" is a different suggestion from
// "thes" -> "these".
stp = &SUG(*gap, 0);
- for (i = gap->ga_len; --i >= 0; ++stp) {
+ for (i = gap->ga_len; --i >= 0; stp++) {
if (stp->st_wordlen == goodlen
&& stp->st_orglen == badlen
&& STRNCMP(stp->st_word, goodword, goodlen) == 0) {
diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c
index e868a79b9a..9b441ba0a9 100644
--- a/src/nvim/statusline.c
+++ b/src/nvim/statusline.c
@@ -77,7 +77,7 @@ void win_redr_status(win_T *wp)
width = is_stl_global ? Columns : wp->w_width;
get_trans_bufname(wp->w_buffer);
- p = NameBuff;
+ p = (char_u *)NameBuff;
len = (int)STRLEN(p);
if (bt_help(wp->w_buffer)
@@ -132,7 +132,7 @@ void win_redr_status(win_T *wp)
row = is_stl_global ? (Rows - (int)p_ch - 1) : W_ENDROW(wp);
col = is_stl_global ? 0 : wp->w_wincol;
- grid_puts(&default_grid, p, row, col, attr);
+ grid_puts(&default_grid, (char *)p, row, col, attr);
grid_fill(&default_grid, row, row + 1, len + col,
this_ru_col + col, fillchar, fillchar, attr);
@@ -342,7 +342,7 @@ void win_redr_ruler(win_T *wp, bool always)
}
ScreenGrid *grid = part_of_status ? &default_grid : &msg_grid_adj;
- grid_puts(grid, (char_u *)buffer, row, this_ru_col + off, attr);
+ grid_puts(grid, buffer, row, this_ru_col + off, attr);
grid_fill(grid, row, row + 1,
this_ru_col + off + (int)STRLEN(buffer), off + width, fillchar,
fillchar, attr);
@@ -448,7 +448,7 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
// setup environment for the task at hand
if (wp == NULL) {
// Use 'tabline'. Always at the first line of the screen.
- stl = p_tal;
+ stl = (char_u *)p_tal;
row = 0;
fillchar = ' ';
attr = HL_ATTR(HLF_TPF);
@@ -491,7 +491,7 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
}
if (draw_ruler) {
- stl = p_ruf;
+ stl = (char_u *)p_ruf;
// advance past any leading group spec - implicit in ru_col
if (*stl == '%') {
if (*++stl == '-') {
@@ -503,7 +503,7 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
}
}
if (*stl++ != '(') {
- stl = p_ruf;
+ stl = (char_u *)p_ruf;
}
}
col = ru_col - (Columns - maxwidth);
@@ -522,9 +522,9 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
use_sandbox = was_set_insecurely(wp, "rulerformat", 0);
} else {
if (*wp->w_p_stl != NUL) {
- stl = wp->w_p_stl;
+ stl = (char_u *)wp->w_p_stl;
} else {
- stl = p_stl;
+ stl = (char_u *)p_stl;
}
use_sandbox = was_set_insecurely(wp, "statusline", *wp->w_p_stl == NUL ? 0 : OPT_LOCAL);
}
@@ -571,8 +571,8 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
p = buf;
for (n = 0; hltab[n].start != NULL; n++) {
int textlen = (int)(hltab[n].start - p);
- grid_puts_len(grid, (char_u *)p, textlen, row, col, curattr);
- col += vim_strnsize((char_u *)p, textlen);
+ grid_puts_len(grid, p, textlen, row, col, curattr);
+ col += vim_strnsize(p, textlen);
p = hltab[n].start;
if (hltab[n].userhl == 0) {
@@ -586,8 +586,7 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
}
}
// Make sure to use an empty string instead of p, if p is beyond buf + len.
- grid_puts(grid, p >= buf + len ? (char_u *)"" : (char_u *)p, row, col,
- curattr);
+ grid_puts(grid, p >= buf + len ? "" : p, row, col, curattr);
grid_puts_line_flush(false);
@@ -608,7 +607,7 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
.type = kStlClickDisabled,
};
for (n = 0; tabtab[n].start != NULL; n++) {
- len += vim_strnsize((char_u *)p, (int)(tabtab[n].start - p));
+ len += vim_strnsize(p, (int)(tabtab[n].start - p));
while (col < len) {
click_defs[col++] = cur_click_def;
}
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index 78312c738c..16691d0ded 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -104,10 +104,10 @@ char_u *vim_strsave_escaped_ext(const char_u *string, const char_u *esc_chars, c
p += l - 1;
continue;
}
- if (vim_strchr((char *)esc_chars, *p) != NULL || (bsl && rem_backslash(p))) {
+ if (vim_strchr((char *)esc_chars, *p) != NULL || (bsl && rem_backslash((char *)p))) {
length++; // count a backslash
}
- ++length; // count an ordinary char
+ length++; // count an ordinary char
}
char_u *escaped_string = xmalloc(length);
@@ -120,7 +120,7 @@ char_u *vim_strsave_escaped_ext(const char_u *string, const char_u *esc_chars, c
p += l - 1; // skip multibyte char
continue;
}
- if (vim_strchr((char *)esc_chars, *p) != NULL || (bsl && rem_backslash(p))) {
+ if (vim_strchr((char *)esc_chars, *p) != NULL || (bsl && rem_backslash((char *)p))) {
*p2++ = cc;
}
*p2++ = *p;
@@ -222,13 +222,13 @@ char_u *vim_strsave_shellescape(const char_u *string, bool do_special, bool do_n
}
if ((*p == '\n' && (csh_like || do_newline))
|| (*p == '!' && (csh_like || do_special))) {
- ++length; // insert backslash
+ length++; // insert backslash
if (csh_like && do_special) {
- ++length; // insert backslash
+ 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) {
@@ -503,7 +503,7 @@ static int sort_compare(const void *s1, const void *s2)
void sort_strings(char **files, int count)
{
- qsort((void *)files, (size_t)count, sizeof(char_u *), sort_compare);
+ qsort((void *)files, (size_t)count, sizeof(char *), sort_compare);
}
/*
@@ -516,7 +516,7 @@ bool has_non_ascii(const char_u *s)
const char_u *p;
if (s != NULL) {
- for (p = s; *p != NUL; ++p) {
+ for (p = s; *p != NUL; p++) {
if (*p >= 128) {
return true;
}
@@ -540,14 +540,12 @@ bool has_non_ascii_len(const char *const s, const size_t len)
return false;
}
-/*
- * Concatenate two strings and return the result in allocated memory.
- */
-char_u *concat_str(const char_u *restrict str1, const char_u *restrict str2)
+/// Concatenate two strings and return the result in allocated memory.
+char *concat_str(const char *restrict str1, const char *restrict str2)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
size_t l = STRLEN(str1);
- char_u *dest = xmalloc(l + STRLEN(str2) + 1);
+ char *dest = xmalloc(l + STRLEN(str2) + 1);
STRCPY(dest, str1);
STRCPY(dest + l, str2);
return dest;
@@ -1511,15 +1509,15 @@ int kv_do_printf(StringBuilder *str, const char *fmt, ...)
/// Reverse text into allocated memory.
///
/// @return the allocated string.
-char_u *reverse_text(char_u *s)
+char *reverse_text(char *s)
FUNC_ATTR_NONNULL_RET
{
// Reverse the pattern.
size_t len = STRLEN(s);
- char_u *rev = xmalloc(len + 1);
+ char *rev = xmalloc(len + 1);
size_t rev_i = len;
for (size_t s_i = 0; s_i < len; s_i++) {
- const int mb_len = utfc_ptr2len((char *)s + s_i);
+ const int mb_len = utfc_ptr2len(s + s_i);
rev_i -= (size_t)mb_len;
memmove(rev + rev_i, s + s_i, (size_t)mb_len);
s_i += (size_t)mb_len - 1;
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 2a3ec56451..f055cc9b0e 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -609,7 +609,7 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
/*
* Skip lines that end in a backslash.
*/
- for (; start_lnum > 1; --start_lnum) {
+ for (; start_lnum > 1; start_lnum--) {
line = ml_get(start_lnum - 1);
if (*line == NUL || *(line + STRLEN(line) - 1) != '\\') {
break;
@@ -687,7 +687,7 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
*/
validate_current_state();
- for (current_lnum = lnum; current_lnum < end_lnum; ++current_lnum) {
+ for (current_lnum = lnum; current_lnum < end_lnum; current_lnum++) {
syn_start_line();
for (;;) {
had_sync_point = syn_finish_line(true);
@@ -812,9 +812,7 @@ static void restore_chartab(char_u *chartab)
}
}
-/*
- * Return TRUE if the line-continuation pattern matches in line "lnum".
- */
+/// Return true if the line-continuation pattern matches in line "lnum".
static int syn_match_linecont(linenr_T lnum)
{
if (syn_block->b_syn_linecont_prog != NULL) {
@@ -832,7 +830,7 @@ static int syn_match_linecont(linenr_T lnum)
restore_chartab(buf_chartab);
return r;
}
- return FALSE;
+ return false;
}
/*
@@ -878,7 +876,7 @@ static void syn_update_ends(bool startofline)
cur_si->si_m_endpos.lnum = 0;
cur_si->si_m_endpos.col = 0;
cur_si->si_h_endpos = cur_si->si_m_endpos;
- cur_si->si_ends = TRUE;
+ cur_si->si_ends = true;
}
}
}
@@ -894,7 +892,7 @@ static void syn_update_ends(bool startofline)
*/
int i = current_state.ga_len - 1;
if (keepend_level >= 0) {
- for (; i > keepend_level; --i) {
+ for (; i > keepend_level; i--) {
if (CUR_STATE(i).si_flags & HL_EXTEND) {
break;
}
@@ -1186,7 +1184,7 @@ static void syn_stack_free_entry(synblock_T *block, synstate_T *p)
clear_syn_state(p);
p->sst_next = block->b_sst_firstfree;
block->b_sst_firstfree = p;
- ++block->b_sst_freecount;
+ block->b_sst_freecount++;
}
/*
@@ -1225,7 +1223,7 @@ static synstate_T *store_current_state(void)
* If the current state contains a start or end pattern that continues
* from the previous line, we can't use it. Don't store it then.
*/
- for (i = current_state.ga_len - 1; i >= 0; --i) {
+ for (i = current_state.ga_len - 1; i >= 0; i--) {
cur_si = &CUR_STATE(i);
if (cur_si->si_h_startpos.lnum >= current_lnum
|| cur_si->si_m_endpos.lnum >= current_lnum
@@ -1273,7 +1271,7 @@ static synstate_T *store_current_state(void)
// list, after *sp
p = syn_block->b_sst_firstfree;
syn_block->b_sst_firstfree = p->sst_next;
- --syn_block->b_sst_freecount;
+ syn_block->b_sst_freecount--;
if (sp == NULL) {
// Insert in front of the list
p->sst_next = syn_block->b_sst_first;
@@ -1302,7 +1300,7 @@ static synstate_T *store_current_state(void)
} else {
bp = sp->sst_union.sst_stack;
}
- for (i = 0; i < sp->sst_stacksize; ++i) {
+ for (i = 0; i < sp->sst_stacksize; i++) {
bp[i].bs_idx = CUR_STATE(i).si_idx;
bp[i].bs_flags = (int)CUR_STATE(i).si_flags;
bp[i].bs_seqnr = CUR_STATE(i).si_seqnr;
@@ -1336,7 +1334,7 @@ static void load_current_state(synstate_T *from)
} else {
bp = from->sst_union.sst_stack;
}
- for (i = 0; i < from->sst_stacksize; ++i) {
+ for (i = 0; i < from->sst_stacksize; i++) {
CUR_STATE(i).si_idx = bp[i].bs_idx;
CUR_STATE(i).si_flags = bp[i].bs_flags;
CUR_STATE(i).si_seqnr = bp[i].bs_seqnr;
@@ -1345,7 +1343,7 @@ static void load_current_state(synstate_T *from)
if (keepend_level < 0 && (CUR_STATE(i).si_flags & HL_KEEPEND)) {
keepend_level = i;
}
- CUR_STATE(i).si_ends = FALSE;
+ CUR_STATE(i).si_ends = false;
CUR_STATE(i).si_m_lnum = 0;
if (CUR_STATE(i).si_idx >= 0) {
CUR_STATE(i).si_next_list =
@@ -1551,7 +1549,7 @@ static bool syn_finish_line(const bool syncing)
/// "col" is normally 0 for the first use in a line, and increments by one each
/// time. It's allowed to skip characters and to stop before the end of the
/// line. But only a "col" after a previously used column is allowed.
-/// When "can_spell" is not NULL set it to TRUE when spell-checking should be
+/// When "can_spell" is not NULL set it to true when spell-checking should be
/// done.
///
/// @param keep_state keep state of char at "col"
@@ -1636,11 +1634,9 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
bool zero_width_next_list = false;
garray_T zero_width_next_ga;
- /*
- * No character, no attributes! Past end of line?
- * Do try matching with an empty line (could be the start of a region).
- */
- line = syn_getcurline();
+ // No character, no attributes! Past end of line?
+ // Do try matching with an empty line (could be the start of a region).
+ line = (char_u *)syn_getcurline();
if (line[current_col] == NUL && current_col != 0) {
/*
* If we found a match after the last column, use it.
@@ -1708,12 +1704,10 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
if (syn_block->b_syn_containedin || cur_si == NULL
|| cur_si->si_cont_list != NULL) {
- /*
- * 2. Check for keywords, if on a keyword char after a non-keyword
- * char. Don't do this when syncing.
- */
+ // 2. Check for keywords, if on a keyword char after a non-keyword
+ // char. Don't do this when syncing.
if (do_keywords) {
- line = syn_getcurline();
+ line = (char_u *)syn_getcurline();
const char_u *cur_pos = line + current_col;
if (vim_iswordp_buf(cur_pos, syn_buf)
&& (current_col == 0
@@ -1732,7 +1726,7 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
cur_si->si_m_endpos.col = endcol;
cur_si->si_h_endpos.lnum = current_lnum;
cur_si->si_h_endpos.col = endcol;
- cur_si->si_ends = TRUE;
+ cur_si->si_ends = true;
cur_si->si_end_idx = 0;
cur_si->si_flags = flags;
cur_si->si_seqnr = next_seqnr++;
@@ -1981,13 +1975,11 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
* Handle searching for nextgroup match.
*/
if (current_next_list != NULL && !keep_next_list) {
- /*
- * If a nextgroup was not found, continue looking for one if:
- * - this is an empty line and the "skipempty" option was given
- * - we are on white space and the "skipwhite" option was given
- */
+ // If a nextgroup was not found, continue looking for one if:
+ // - this is an empty line and the "skipempty" option was given
+ // - we are on white space and the "skipwhite" option was given
if (!found_match) {
- line = syn_getcurline();
+ line = (char_u *)syn_getcurline();
if (((current_next_flags & HL_SKIPWHITE)
&& ascii_iswhite(line[current_col]))
|| ((current_next_flags & HL_SKIPEMPTY)
@@ -2024,7 +2016,7 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
current_flags = 0;
current_seqnr = 0;
if (cur_si != NULL) {
- for (int idx = current_state.ga_len - 1; idx >= 0; --idx) {
+ for (int idx = current_state.ga_len - 1; idx >= 0; idx--) {
sip = &CUR_STATE(idx);
if ((current_lnum > sip->si_h_startpos.lnum
|| (current_lnum == sip->si_h_startpos.lnum
@@ -2046,10 +2038,8 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
if (can_spell != NULL) {
struct sp_syn sps;
- /*
- * set "can_spell" to TRUE if spell checking is supposed to be
- * done in the current item.
- */
+ // set "can_spell" to true if spell checking is supposed to be
+ // done in the current item.
if (syn_block->b_spell_cluster_id == 0) {
// There is no @Spell cluster: Do spelling for items without
// @NoSpell cluster.
@@ -2112,7 +2102,7 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
// nextgroup ends at end of line, unless "skipnl" or "skipempty" present
if (current_next_list != NULL
- && (line = syn_getcurline())[current_col] != NUL
+ && (line = (char_u *)syn_getcurline())[current_col] != NUL
&& line[current_col + 1] == NUL
&& !(current_next_flags & (HL_SKIPNL | HL_SKIPEMPTY))) {
current_next_list = NULL;
@@ -2192,7 +2182,7 @@ static stateitem_T *push_next_match(void)
} else {
cur_si->si_m_endpos = next_match_m_endpos;
cur_si->si_h_endpos = next_match_h_endpos;
- cur_si->si_ends = TRUE;
+ cur_si->si_ends = true;
cur_si->si_flags |= next_match_flags;
cur_si->si_eoe_pos = next_match_eoe_pos;
cur_si->si_end_idx = next_match_end_idx;
@@ -2216,7 +2206,7 @@ static stateitem_T *push_next_match(void)
cur_si->si_m_lnum = current_lnum;
cur_si->si_m_endpos = next_match_eos_pos;
cur_si->si_h_endpos = next_match_eos_pos;
- cur_si->si_ends = TRUE;
+ cur_si->si_ends = true;
cur_si->si_end_idx = 0;
cur_si->si_flags = HL_MATCH;
cur_si->si_seqnr = next_seqnr++;
@@ -2406,7 +2396,7 @@ static void check_keepend(void)
* won't do anything. If there is no "extend" item "i" will be
* "keepend_level" and all "keepend" items will work normally.
*/
- for (i = current_state.ga_len - 1; i > keepend_level; --i) {
+ for (i = current_state.ga_len - 1; i > keepend_level; i--) {
if (CUR_STATE(i).si_flags & HL_EXTEND) {
break;
}
@@ -2416,13 +2406,13 @@ static void check_keepend(void)
maxpos.col = 0;
maxpos_h.lnum = 0;
maxpos_h.col = 0;
- for (; i < current_state.ga_len; ++i) {
+ for (; i < current_state.ga_len; i++) {
sip = &CUR_STATE(i);
if (maxpos.lnum != 0) {
limit_pos_zero(&sip->si_m_endpos, &maxpos);
limit_pos_zero(&sip->si_h_endpos, &maxpos_h);
limit_pos_zero(&sip->si_eoe_pos, &maxpos);
- sip->si_ends = TRUE;
+ sip->si_ends = true;
}
if (sip->si_ends && (sip->si_flags & HL_KEEPEND)) {
if (maxpos.lnum == 0
@@ -2482,12 +2472,12 @@ static void update_si_end(stateitem_T *sip, int startcol, bool force)
// No end pattern matched.
if (SYN_ITEMS(syn_block)[sip->si_idx].sp_flags & HL_ONELINE) {
// a "oneline" never continues in the next line
- sip->si_ends = TRUE;
+ sip->si_ends = true;
sip->si_m_endpos.lnum = current_lnum;
sip->si_m_endpos.col = (colnr_T)STRLEN(syn_getcurline());
} else {
// continues in the next line
- sip->si_ends = FALSE;
+ sip->si_ends = false;
sip->si_m_endpos.lnum = 0;
}
sip->si_h_endpos = sip->si_m_endpos;
@@ -2496,7 +2486,7 @@ static void update_si_end(stateitem_T *sip, int startcol, bool force)
sip->si_m_endpos = endpos;
sip->si_h_endpos = hl_endpos;
sip->si_eoe_pos = end_endpos;
- sip->si_ends = TRUE;
+ sip->si_ends = true;
sip->si_end_idx = end_idx;
}
}
@@ -2519,7 +2509,7 @@ static void pop_current_state(void)
{
if (!GA_EMPTY(&current_state)) {
unref_extmatch(CUR_STATE(current_state.ga_len - 1).si_extmatch);
- --current_state.ga_len;
+ current_state.ga_len--;
}
// after the end of a pattern, try matching a keyword or pattern
next_match_idx = -1;
@@ -2613,7 +2603,7 @@ static void find_endpos(int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_
* Find end pattern that matches first after "matchcol".
*/
best_idx = -1;
- for (idx = start_idx; idx < syn_block->b_syn_patterns.ga_len; ++idx) {
+ for (idx = start_idx; idx < syn_block->b_syn_patterns.ga_len; idx++) {
int lc_col = matchcol;
spp = &(SYN_ITEMS(syn_block)[idx]);
@@ -2878,17 +2868,15 @@ static void syn_add_start_off(lpos_T *result, regmmatch_T *regmatch, synpat_T *s
result->col = col;
}
-/*
- * Get current line in syntax buffer.
- */
-static char_u *syn_getcurline(void)
+/// Get current line in syntax buffer.
+static char *syn_getcurline(void)
{
- return ml_get_buf(syn_buf, current_lnum, false);
+ return (char *)ml_get_buf(syn_buf, current_lnum, false);
}
/*
* Call vim_regexec() to find a match with "rmp" in "syn_buf".
- * Returns TRUE when there is a match.
+ * Returns true when there is a match.
*/
static int syn_regexec(regmmatch_T *rmp, linenr_T lnum, colnr_T col, syn_time_T *st)
{
@@ -2916,9 +2904,9 @@ static int syn_regexec(regmmatch_T *rmp, linenr_T lnum, colnr_T col, syn_time_T
if (profile_cmp(pt, st->slowest) < 0) {
st->slowest = pt;
}
- ++st->count;
+ st->count++;
if (r > 0) {
- ++st->match;
+ st->match++;
}
}
if (timed_out && !syn_win->w_s->b_syn_slow) {
@@ -2929,9 +2917,9 @@ static int syn_regexec(regmmatch_T *rmp, linenr_T lnum, colnr_T col, syn_time_T
if (r > 0) {
rmp->startpos[0].lnum += lnum;
rmp->endpos[0].lnum += lnum;
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
/// Check one position in a line for a matching keyword.
@@ -3020,12 +3008,12 @@ static void syn_cmd_conceal(exarg_T *eap, int syncing)
char_u *arg = (char_u *)eap->arg;
char_u *next;
- eap->nextcmd = (char *)find_nextcmd(arg);
+ eap->nextcmd = find_nextcmd((char *)arg);
if (eap->skip) {
return;
}
- next = skiptowhite(arg);
+ next = (char_u *)skiptowhite((char *)arg);
if (*arg == NUL) {
if (curwin->w_s->b_syn_conceal) {
msg("syntax conceal on");
@@ -3049,12 +3037,12 @@ static void syn_cmd_case(exarg_T *eap, int syncing)
char_u *arg = (char_u *)eap->arg;
char_u *next;
- eap->nextcmd = (char *)find_nextcmd(arg);
+ eap->nextcmd = find_nextcmd((char *)arg);
if (eap->skip) {
return;
}
- next = skiptowhite(arg);
+ next = (char_u *)skiptowhite((char *)arg);
if (*arg == NUL) {
if (curwin->w_s->b_syn_ic) {
msg("syntax case ignore");
@@ -3076,7 +3064,7 @@ static void syn_cmd_foldlevel(exarg_T *eap, int syncing)
char_u *arg = (char_u *)eap->arg;
char_u *arg_end;
- eap->nextcmd = (char *)find_nextcmd(arg);
+ eap->nextcmd = find_nextcmd((char *)arg);
if (eap->skip) {
return;
}
@@ -3093,7 +3081,7 @@ static void syn_cmd_foldlevel(exarg_T *eap, int syncing)
return;
}
- arg_end = skiptowhite(arg);
+ arg_end = (char_u *)skiptowhite((char *)arg);
if (STRNICMP(arg, "start", 5) == 0 && arg_end - arg == 5) {
curwin->w_s->b_syn_foldlevel = SYNFLD_START;
} else if (STRNICMP(arg, "minimum", 7) == 0 && arg_end - arg == 7) {
@@ -3117,12 +3105,12 @@ static void syn_cmd_spell(exarg_T *eap, int syncing)
char_u *arg = (char_u *)eap->arg;
char_u *next;
- eap->nextcmd = (char *)find_nextcmd(arg);
+ eap->nextcmd = find_nextcmd((char *)arg);
if (eap->skip) {
return;
}
- next = skiptowhite(arg);
+ next = (char_u *)skiptowhite((char *)arg);
if (*arg == NUL) {
if (curwin->w_s->b_syn_spell == SYNSPL_TOP) {
msg("syntax spell toplevel");
@@ -3143,7 +3131,7 @@ static void syn_cmd_spell(exarg_T *eap, int syncing)
}
// assume spell checking changed, force a redraw
- redraw_later(curwin, NOT_VALID);
+ redraw_later(curwin, UPD_NOT_VALID);
}
/// Handle ":syntax iskeyword" command.
@@ -3162,7 +3150,7 @@ static void syn_cmd_iskeyword(exarg_T *eap, int syncing)
msg_puts("\n");
if (curwin->w_s->b_syn_isk != empty_option) {
msg_puts("syntax iskeyword ");
- msg_outtrans((char *)curwin->w_s->b_syn_isk);
+ msg_outtrans(curwin->w_s->b_syn_isk);
} else {
msg_outtrans(_("syntax iskeyword not set"));
}
@@ -3172,18 +3160,18 @@ static void syn_cmd_iskeyword(exarg_T *eap, int syncing)
clear_string_option(&curwin->w_s->b_syn_isk);
} else {
memmove(save_chartab, curbuf->b_chartab, (size_t)32);
- save_isk = curbuf->b_p_isk;
- curbuf->b_p_isk = vim_strsave(arg);
+ save_isk = (char_u *)curbuf->b_p_isk;
+ curbuf->b_p_isk = (char *)vim_strsave(arg);
buf_init_chartab(curbuf, false);
memmove(curwin->w_s->b_syn_chartab, curbuf->b_chartab, (size_t)32);
memmove(curbuf->b_chartab, save_chartab, (size_t)32);
clear_string_option(&curwin->w_s->b_syn_isk);
curwin->w_s->b_syn_isk = curbuf->b_p_isk;
- curbuf->b_p_isk = save_isk;
+ curbuf->b_p_isk = (char *)save_isk;
}
}
- redraw_later(curwin, NOT_VALID);
+ redraw_later(curwin, UPD_NOT_VALID);
}
/*
@@ -3282,7 +3270,7 @@ static void syn_remove_pattern(synblock_T *block, int idx)
spp = &(SYN_ITEMS(block)[idx]);
if (spp->sp_flags & HL_FOLD) {
- --block->b_syn_folditems;
+ block->b_syn_folditems--;
}
syn_clear_pattern(block, idx);
memmove(spp, spp + 1, sizeof(synpat_T) * (size_t)(block->b_syn_patterns.ga_len - idx - 1));
@@ -3324,7 +3312,7 @@ static void syn_cmd_clear(exarg_T *eap, int syncing)
char_u *arg_end;
int id;
- eap->nextcmd = (char *)find_nextcmd(arg);
+ eap->nextcmd = find_nextcmd((char *)arg);
if (eap->skip) {
return;
}
@@ -3357,7 +3345,7 @@ static void syn_cmd_clear(exarg_T *eap, int syncing)
* Clear the group IDs that are in the argument.
*/
while (!ends_excmd(*arg)) {
- arg_end = skiptowhite(arg);
+ arg_end = (char_u *)skiptowhite((char *)arg);
if (*arg == '@') {
id = syn_scl_namen2id(arg + 1, (int)(arg_end - arg - 1));
if (id == 0) {
@@ -3383,7 +3371,7 @@ static void syn_cmd_clear(exarg_T *eap, int syncing)
arg = (char_u *)skipwhite((char *)arg_end);
}
}
- redraw_curbuf_later(SOME_VALID);
+ redraw_curbuf_later(UPD_SOME_VALID);
syn_stack_free_all(curwin->w_s); // Need to recompute all syntax.
}
@@ -3471,13 +3459,13 @@ void syn_maybe_enable(void)
/// Handle ":syntax [list]" command: list current syntax words.
///
-/// @param syncing when TRUE: list syncing items
+/// @param syncing when true: list syncing items
static void syn_cmd_list(exarg_T *eap, int syncing)
{
char_u *arg = (char_u *)eap->arg;
char_u *arg_end;
- eap->nextcmd = (char *)find_nextcmd(arg);
+ eap->nextcmd = find_nextcmd((char *)arg);
if (eap->skip) {
return;
}
@@ -3526,7 +3514,7 @@ static void syn_cmd_list(exarg_T *eap, int syncing)
for (int id = 1; id <= highlight_num_groups() && !got_int; id++) {
syn_list_one(id, syncing, false);
}
- for (int id = 0; id < curwin->w_s->b_syn_clusters.ga_len && !got_int; ++id) {
+ for (int id = 0; id < curwin->w_s->b_syn_clusters.ga_len && !got_int; id++) {
syn_list_cluster(id);
}
} else {
@@ -3534,7 +3522,7 @@ static void syn_cmd_list(exarg_T *eap, int syncing)
* List the group IDs and syntax clusters that are in the argument.
*/
while (!ends_excmd(*arg) && !got_int) {
- arg_end = skiptowhite(arg);
+ arg_end = (char_u *)skiptowhite((char *)arg);
if (*arg == '@') {
int id = syn_scl_namen2id(arg + 1, (int)(arg_end - arg - 1));
if (id == 0) {
@@ -3702,7 +3690,7 @@ static void syn_list_flags(struct name_list *nlist, int flags, int attr)
{
int i;
- for (i = 0; nlist[i].flag != 0; ++i) {
+ for (i = 0; nlist[i].flag != 0; i++) {
if (flags & nlist[i].flag) {
msg_puts_attr(nlist[i].name, attr);
msg_putchar(' ');
@@ -3925,7 +3913,7 @@ static void syn_clear_keyword(int id, hashtab_T *ht)
hash_lock(ht);
todo = (int)ht->ht_used;
- for (hi = ht->ht_array; todo > 0; ++hi) {
+ for (hi = ht->ht_array; todo > 0; hi++) {
if (HASHITEM_EMPTY(hi)) {
continue;
}
@@ -3967,7 +3955,7 @@ static void clear_keywtab(hashtab_T *ht)
keyentry_T *kp_next;
todo = (int)ht->ht_used;
- for (hi = ht->ht_array; todo > 0; ++hi) {
+ for (hi = ht->ht_array; todo > 0; hi++) {
if (!HASHITEM_EMPTY(hi)) {
todo--;
for (kp = HI2KE(hi); kp != NULL; kp = kp_next) {
@@ -4006,7 +3994,7 @@ static void add_keyword(char_u *const name, const int id, const int flags,
kp->k_char = conceal_char;
kp->k_syn.cont_in_list = copy_id_list(cont_in_list);
if (cont_in_list != NULL) {
- curwin->w_s->b_syn_containedin = TRUE;
+ curwin->w_s->b_syn_containedin = true;
}
kp->next_list = copy_id_list(next_list);
@@ -4039,17 +4027,13 @@ static void add_keyword(char_u *const name, const int id, const int flags,
///
/// @return a pointer to the first argument.
/// Return NULL if the end of the command was found instead of further args.
-static char_u *get_group_name(char_u *arg, char_u **name_end)
+static char *get_group_name(char *arg, char **name_end)
{
- char_u *rest;
-
*name_end = skiptowhite(arg);
- rest = (char_u *)skipwhite((char *)(*name_end));
+ char *rest = skipwhite(*name_end);
- /*
- * Check if there are enough arguments. The first argument may be a
- * pattern, where '|' is allowed, so only check for NUL.
- */
+ // Check if there are enough arguments. The first argument may be a
+ // pattern, where '|' is allowed, so only check for NUL.
if (ends_excmd(*arg) || *rest == NUL) {
return NULL;
}
@@ -4063,11 +4047,11 @@ static char_u *get_group_name(char_u *arg, char_u **name_end)
///
/// @param arg next argument to be checked
/// @param opt various things
-/// @param skip TRUE if skipping over command
+/// @param skip true if skipping over command
///
/// @return a pointer to the next argument (which isn't an option).
/// Return NULL for any error;
-static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_char, int skip)
+static char *get_syn_options(char *arg, syn_opt_arg_T *opt, int *conceal_char, int skip)
{
char_u *gname_start, *gname;
int syn_id;
@@ -4120,8 +4104,8 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha
for (fidx = ARRAY_SIZE(flagtab); --fidx >= 0;) {
p = flagtab[fidx].name;
int i;
- for (i = 0, len = 0; p[i] != NUL; i += 2, ++len) {
- if (arg[len] != (char_u)p[i] && arg[len] != (char_u)p[i + 1]) {
+ for (i = 0, len = 0; p[i] != NUL; i += 2, len++) {
+ if (arg[len] != p[i] && arg[len] != p[i + 1]) {
break;
}
}
@@ -4161,16 +4145,16 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha
}
} else if (flagtab[fidx].argtype == 11 && arg[5] == '=') {
// cchar=?
- *conceal_char = utf_ptr2char((char *)arg + 6);
- arg += utfc_ptr2len((char *)arg + 6) - 1;
+ *conceal_char = utf_ptr2char(arg + 6);
+ arg += utfc_ptr2len(arg + 6) - 1;
if (!vim_isprintc_strict(*conceal_char)) {
emsg(_("E844: invalid cchar value"));
return NULL;
}
- arg = (char_u *)skipwhite((char *)arg + 7);
+ arg = skipwhite(arg + 7);
} else {
opt->flags |= flagtab[fidx].flags;
- arg = (char_u *)skipwhite((char *)arg + len);
+ arg = skipwhite(arg + len);
if (flagtab[fidx].flags == HL_SYNC_HERE
|| flagtab[fidx].flags == HL_SYNC_THERE) {
@@ -4178,12 +4162,12 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha
emsg(_("E393: group[t]here not accepted here"));
return NULL;
}
- gname_start = arg;
+ gname_start = (char_u *)arg;
arg = skiptowhite(arg);
- if (gname_start == arg) {
+ if (gname_start == (char_u *)arg) {
return NULL;
}
- gname = vim_strnsave(gname_start, (size_t)(arg - gname_start));
+ gname = vim_strnsave(gname_start, (size_t)((char_u *)arg - gname_start));
if (STRCMP(gname, "NONE") == 0) {
*opt->sync_idx = NONE_IDX;
} else {
@@ -4204,7 +4188,7 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha
}
xfree(gname);
- arg = (char_u *)skipwhite((char *)arg);
+ arg = skipwhite(arg);
} else if (flagtab[fidx].flags == HL_FOLD
&& foldmethodIsSyntax(curwin)) {
// Need to update folds later.
@@ -4244,16 +4228,16 @@ static void syn_incl_toplevel(int id, int *flagsp)
*/
static void syn_cmd_include(exarg_T *eap, int syncing)
{
- char_u *arg = (char_u *)eap->arg;
+ char *arg = eap->arg;
int sgl_id = 1;
- char_u *group_name_end;
- char_u *rest;
+ char *group_name_end;
+ char *rest;
char *errormsg = NULL;
int prev_toplvl_grp;
int prev_syn_inc_tag;
bool source = false;
- eap->nextcmd = (char *)find_nextcmd(arg);
+ eap->nextcmd = find_nextcmd(arg);
if (eap->skip) {
return;
}
@@ -4265,12 +4249,12 @@ static void syn_cmd_include(exarg_T *eap, int syncing)
emsg(_("E397: Filename required"));
return;
}
- sgl_id = syn_check_cluster(arg, (int)(group_name_end - arg));
+ sgl_id = syn_check_cluster((char_u *)arg, (int)(group_name_end - arg));
if (sgl_id == 0) {
return;
}
// separate_nextcmd() and expand_filename() depend on this
- eap->arg = (char *)rest;
+ eap->arg = rest;
}
/*
@@ -4318,13 +4302,13 @@ static void syn_cmd_include(exarg_T *eap, int syncing)
*/
static void syn_cmd_keyword(exarg_T *eap, int syncing)
{
- char_u *arg = (char_u *)eap->arg;
- char_u *group_name_end;
+ char *arg = eap->arg;
+ char *group_name_end;
int syn_id;
- char_u *rest;
- char_u *keyword_copy = NULL;
- char_u *p;
- char_u *kw;
+ char *rest;
+ char *keyword_copy = NULL;
+ char *p;
+ char *kw;
syn_opt_arg_T syn_opt_arg;
int cnt;
int conceal_char = NUL;
@@ -4335,7 +4319,7 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing)
if (eap->skip) {
syn_id = -1;
} else {
- syn_id = syn_check_group((char *)arg, (size_t)(group_name_end - arg));
+ syn_id = syn_check_group(arg, (size_t)(group_name_end - arg));
}
if (syn_id != 0) {
// Allocate a buffer, for removing backslashes in the keyword.
@@ -4354,7 +4338,7 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing)
// 1: collect the options and copy the keywords to keyword_copy.
cnt = 0;
p = keyword_copy;
- for (; rest != NULL && !ends_excmd(*rest); rest = (char_u *)skipwhite((char *)rest)) {
+ for (; rest != NULL && !ends_excmd(*rest); rest = skipwhite(rest)) {
rest = get_syn_options(rest, &syn_opt_arg, &conceal_char, eap->skip);
if (rest == NULL || ends_excmd(*rest)) {
break;
@@ -4376,11 +4360,11 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing)
// 2: Add an entry for each keyword.
for (kw = keyword_copy; --cnt >= 0; kw += STRLEN(kw) + 1) {
- for (p = (char_u *)vim_strchr((char *)kw, '[');;) {
+ for (p = vim_strchr(kw, '[');;) {
if (p != NULL) {
*p = NUL;
}
- add_keyword(kw, syn_id, syn_opt_arg.flags,
+ add_keyword((char_u *)kw, syn_id, syn_opt_arg.flags,
syn_opt_arg.cont_in_list,
syn_opt_arg.next_list, conceal_char);
if (p == NULL) {
@@ -4399,7 +4383,7 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing)
kw = p + 1;
break; // skip over the "]"
}
- const int l = utfc_ptr2len((char *)p + 1);
+ const int l = utfc_ptr2len(p + 1);
memmove(p, p + 1, (size_t)l);
p += l;
@@ -4415,12 +4399,12 @@ error:
}
if (rest != NULL) {
- eap->nextcmd = (char *)check_nextcmd(rest);
+ eap->nextcmd = (char *)check_nextcmd((char_u *)rest);
} else {
semsg(_(e_invarg2), arg);
}
- redraw_curbuf_later(SOME_VALID);
+ redraw_curbuf_later(UPD_SOME_VALID);
syn_stack_free_all(curwin->w_s); // Need to recompute all syntax.
}
@@ -4428,12 +4412,11 @@ error:
///
/// Also ":syntax sync match {name} [[grouphere | groupthere] {group-name}] .."
///
-/// @param syncing TRUE for ":syntax sync match .. "
+/// @param syncing true for ":syntax sync match .. "
static void syn_cmd_match(exarg_T *eap, int syncing)
{
- char_u *arg = (char_u *)eap->arg;
- char_u *group_name_end;
- char_u *rest;
+ char *arg = eap->arg;
+ char *group_name_end;
synpat_T item; // the item found in the line
int syn_id;
syn_opt_arg_T syn_opt_arg;
@@ -4441,7 +4424,7 @@ static void syn_cmd_match(exarg_T *eap, int syncing)
int conceal_char = NUL;
// Isolate the group name, check for validity
- rest = get_group_name(arg, &group_name_end);
+ char *rest = get_group_name(arg, &group_name_end);
// Get options before the pattern
syn_opt_arg.flags = 0;
@@ -4456,7 +4439,7 @@ static void syn_cmd_match(exarg_T *eap, int syncing)
// get the pattern.
init_syn_patterns();
CLEAR_FIELD(item);
- rest = get_syn_pattern(rest, &item);
+ rest = get_syn_pattern((char_u *)rest, &item);
if (vim_regcomp_had_eol() && !(syn_opt_arg.flags & HL_EXCLUDENL)) {
syn_opt_arg.flags |= HL_HAS_EOL;
}
@@ -4468,11 +4451,11 @@ static void syn_cmd_match(exarg_T *eap, int syncing)
/*
* Check for trailing command and illegal trailing arguments.
*/
- eap->nextcmd = (char *)check_nextcmd(rest);
+ eap->nextcmd = (char *)check_nextcmd((char_u *)rest);
if (!ends_excmd(*rest) || eap->skip) {
rest = NULL;
} else {
- if ((syn_id = syn_check_group((char *)arg, (size_t)(group_name_end - arg))) != 0) {
+ if ((syn_id = syn_check_group(arg, (size_t)(group_name_end - arg))) != 0) {
syn_incl_toplevel(syn_id, &syn_opt_arg.flags);
/*
* Store the pattern in the syn_items list
@@ -4490,7 +4473,7 @@ static void syn_cmd_match(exarg_T *eap, int syncing)
spp->sp_syn.cont_in_list = syn_opt_arg.cont_in_list;
spp->sp_cchar = conceal_char;
if (syn_opt_arg.cont_in_list != NULL) {
- curwin->w_s->b_syn_containedin = TRUE;
+ curwin->w_s->b_syn_containedin = true;
}
spp->sp_next_list = syn_opt_arg.next_list;
@@ -4499,10 +4482,10 @@ static void syn_cmd_match(exarg_T *eap, int syncing)
curwin->w_s->b_syn_sync_flags |= SF_MATCH;
}
if (syn_opt_arg.flags & HL_FOLD) {
- ++curwin->w_s->b_syn_folditems;
+ curwin->w_s->b_syn_folditems++;
}
- redraw_curbuf_later(SOME_VALID);
+ redraw_curbuf_later(UPD_SOME_VALID);
syn_stack_free_all(curwin->w_s); // Need to recompute all syntax.
return; // don't free the progs and patterns now
}
@@ -4526,15 +4509,15 @@ static void syn_cmd_match(exarg_T *eap, int syncing)
/// Handle ":syntax region {group-name} [matchgroup={group-name}]
/// start {start} .. [skip {skip}] end {end} .. [{options}]".
///
-/// @param syncing TRUE for ":syntax sync region .."
+/// @param syncing true for ":syntax sync region .."
static void syn_cmd_region(exarg_T *eap, int syncing)
{
- char_u *arg = (char_u *)eap->arg;
- char_u *group_name_end;
- char_u *rest; // next arg, NULL on error
- char_u *key_end;
- char_u *key = NULL;
- char_u *p;
+ char *arg = eap->arg;
+ char *group_name_end;
+ char *rest; // next arg, NULL on error
+ char *key_end;
+ char *key = NULL;
+ char *p;
int item;
#define ITEM_START 0
#define ITEM_SKIP 1
@@ -4588,7 +4571,7 @@ static void syn_cmd_region(exarg_T *eap, int syncing)
key_end++;
}
xfree(key);
- key = vim_strnsave_up(rest, (size_t)(key_end - rest));
+ key = (char *)vim_strnsave_up((char_u *)rest, (size_t)(key_end - rest));
if (STRCMP(key, "MATCHGROUP") == 0) {
item = ITEM_MATCHGROUP;
} else if (STRCMP(key, "START") == 0) {
@@ -4604,13 +4587,13 @@ static void syn_cmd_region(exarg_T *eap, int syncing)
} else {
break;
}
- rest = (char_u *)skipwhite((char *)key_end);
+ rest = skipwhite(key_end);
if (*rest != '=') {
rest = NULL;
semsg(_("E398: Missing '=': %s"), arg);
break;
}
- rest = (char_u *)skipwhite((char *)rest + 1);
+ rest = skipwhite(rest + 1);
if (*rest == NUL) {
not_enough = true;
break;
@@ -4621,13 +4604,13 @@ static void syn_cmd_region(exarg_T *eap, int syncing)
if ((p - rest == 4 && STRNCMP(rest, "NONE", 4) == 0) || eap->skip) {
matchgroup_id = 0;
} else {
- matchgroup_id = syn_check_group((char *)rest, (size_t)(p - rest));
+ matchgroup_id = syn_check_group(rest, (size_t)(p - rest));
if (matchgroup_id == 0) {
illegal = true;
break;
}
}
- rest = (char_u *)skipwhite((char *)p);
+ rest = skipwhite(p);
} else {
/*
* Allocate room for a syn_pattern, and link it in the list of
@@ -4648,7 +4631,7 @@ static void syn_cmd_region(exarg_T *eap, int syncing)
assert(item == ITEM_SKIP || item == ITEM_END);
reg_do_extmatch = REX_USE;
}
- rest = get_syn_pattern(rest, ppp->pp_synp);
+ rest = get_syn_pattern((char_u *)rest, ppp->pp_synp);
reg_do_extmatch = 0;
if (item == ITEM_END && vim_regcomp_had_eol()
&& !(syn_opt_arg.flags & HL_EXCLUDENL)) {
@@ -4675,18 +4658,18 @@ static void syn_cmd_region(exarg_T *eap, int syncing)
* Check for trailing garbage or command.
* If OK, add the item.
*/
- eap->nextcmd = (char *)check_nextcmd(rest);
+ eap->nextcmd = (char *)check_nextcmd((char_u *)rest);
if (!ends_excmd(*rest) || eap->skip) {
rest = NULL;
} else {
ga_grow(&(curwin->w_s->b_syn_patterns), pat_count);
- if ((syn_id = syn_check_group((char *)arg, (size_t)(group_name_end - arg))) != 0) {
+ if ((syn_id = syn_check_group(arg, (size_t)(group_name_end - arg))) != 0) {
syn_incl_toplevel(syn_id, &syn_opt_arg.flags);
/*
* Store the start/skip/end in the syn_items list
*/
int idx = curwin->w_s->b_syn_patterns.ga_len;
- for (item = ITEM_START; item <= ITEM_END; ++item) {
+ for (item = ITEM_START; item <= ITEM_END; item++) {
for (ppp = pat_ptrs[item]; ppp != NULL; ppp = ppp->pp_next) {
SYN_ITEMS(curwin->w_s)[idx] = *(ppp->pp_synp);
SYN_ITEMS(curwin->w_s)[idx].sp_syncing = syncing;
@@ -4705,7 +4688,7 @@ static void syn_cmd_region(exarg_T *eap, int syncing)
SYN_ITEMS(curwin->w_s)[idx].sp_syn.cont_in_list =
syn_opt_arg.cont_in_list;
if (syn_opt_arg.cont_in_list != NULL) {
- curwin->w_s->b_syn_containedin = TRUE;
+ curwin->w_s->b_syn_containedin = true;
}
SYN_ITEMS(curwin->w_s)[idx].sp_next_list =
syn_opt_arg.next_list;
@@ -4713,12 +4696,12 @@ static void syn_cmd_region(exarg_T *eap, int syncing)
curwin->w_s->b_syn_patterns.ga_len++;
idx++;
if (syn_opt_arg.flags & HL_FOLD) {
- ++curwin->w_s->b_syn_folditems;
+ curwin->w_s->b_syn_folditems++;
}
}
}
- redraw_curbuf_later(SOME_VALID);
+ redraw_curbuf_later(UPD_SOME_VALID);
syn_stack_free_all(curwin->w_s); // Need to recompute all syntax.
success = true; // don't free the progs and patterns now
}
@@ -4728,7 +4711,7 @@ static void syn_cmd_region(exarg_T *eap, int syncing)
/*
* Free the allocated memory.
*/
- for (item = ITEM_START; item <= ITEM_END; ++item) {
+ for (item = ITEM_START; item <= ITEM_END; item++) {
for (ppp = pat_ptrs[item]; ppp != NULL; ppp = ppp_next) {
if (!success && ppp->pp_synp != NULL) {
vim_regfree(ppp->pp_synp->sp_prog);
@@ -4968,14 +4951,14 @@ static int syn_add_cluster(char_u *name)
*/
static void syn_cmd_cluster(exarg_T *eap, int syncing)
{
- char_u *arg = (char_u *)eap->arg;
- char_u *group_name_end;
- char_u *rest;
+ char *arg = eap->arg;
+ char *group_name_end;
+ char *rest;
bool got_clstr = false;
int opt_len;
int list_op;
- eap->nextcmd = (char *)find_nextcmd(arg);
+ eap->nextcmd = find_nextcmd(arg);
if (eap->skip) {
return;
}
@@ -4983,7 +4966,7 @@ static void syn_cmd_cluster(exarg_T *eap, int syncing)
rest = get_group_name(arg, &group_name_end);
if (rest != NULL) {
- int scl_id = syn_check_cluster(arg, (int)(group_name_end - arg));
+ int scl_id = syn_check_cluster((char_u *)arg, (int)(group_name_end - arg));
if (scl_id == 0) {
return;
}
@@ -5021,7 +5004,7 @@ static void syn_cmd_cluster(exarg_T *eap, int syncing)
}
if (got_clstr) {
- redraw_curbuf_later(SOME_VALID);
+ redraw_curbuf_later(UPD_SOME_VALID);
syn_stack_free_all(curwin->w_s); // Need to recompute all.
}
}
@@ -5043,12 +5026,11 @@ static void init_syn_patterns(void)
ga_set_growsize(&curwin->w_s->b_syn_patterns, 10);
}
-/*
- * Get one pattern for a ":syntax match" or ":syntax region" command.
- * Stores the pattern and program in a synpat_T.
- * Returns a pointer to the next argument, or NULL in case of an error.
- */
-static char_u *get_syn_pattern(char_u *arg, synpat_T *ci)
+/// Get one pattern for a ":syntax match" or ":syntax region" command.
+/// Stores the pattern and program in a synpat_T.
+///
+/// @return a pointer to the next argument, or NULL in case of an error.
+static char *get_syn_pattern(char_u *arg, synpat_T *ci)
{
char *end;
int *p;
@@ -5060,7 +5042,7 @@ static char_u *get_syn_pattern(char_u *arg, synpat_T *ci)
return NULL;
}
- end = (char *)skip_regexp(arg + 1, *arg, true, NULL);
+ end = skip_regexp((char *)arg + 1, *arg, true, NULL);
if (*end != (char)(*arg)) { // end delimiter not found
semsg(_("E401: Pattern delimiter not found: %s"), arg);
return NULL;
@@ -5070,7 +5052,7 @@ static char_u *get_syn_pattern(char_u *arg, synpat_T *ci)
// Make 'cpoptions' empty, to avoid the 'l' flag
cpo_save = p_cpo;
- p_cpo = "";
+ p_cpo = empty_option;
ci->sp_prog = vim_regcomp((char *)ci->sp_pattern, RE_MAGIC);
p_cpo = cpo_save;
@@ -5137,7 +5119,7 @@ static char_u *get_syn_pattern(char_u *arg, synpat_T *ci)
semsg(_("E402: Garbage after pattern: %s"), arg);
return NULL;
}
- return (char_u *)skipwhite(end);
+ return skipwhite(end);
}
/*
@@ -5154,12 +5136,12 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
char *cpo_save;
if (ends_excmd(*arg_start)) {
- syn_cmd_list(eap, TRUE);
+ syn_cmd_list(eap, true);
return;
}
while (!ends_excmd(*arg_start)) {
- arg_end = (char *)skiptowhite(arg_start);
+ arg_end = skiptowhite((char *)arg_start);
next_arg = (char_u *)skipwhite(arg_end);
xfree(key);
key = vim_strnsave_up(arg_start, (size_t)(arg_end - (char *)arg_start));
@@ -5168,7 +5150,7 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
curwin->w_s->b_syn_sync_flags |= SF_CCOMMENT;
}
if (!ends_excmd(*next_arg)) {
- arg_end = (char *)skiptowhite(next_arg);
+ arg_end = skiptowhite((char *)next_arg);
if (!eap->skip) {
curwin->w_s->b_syn_sync_id =
(int16_t)syn_check_group((char *)next_arg, (size_t)(arg_end - (char *)next_arg));
@@ -5189,7 +5171,7 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
arg_end = (char *)key + 9;
}
if (arg_end[-1] != '=' || !ascii_isdigit(*arg_end)) {
- illegal = TRUE;
+ illegal = true;
break;
}
linenr_T n = getdigits_int32(&arg_end, false, 0);
@@ -5214,10 +5196,10 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
}
if (curwin->w_s->b_syn_linecont_pat != NULL) {
emsg(_("E403: syntax sync: line continuations pattern specified twice"));
- finished = TRUE;
+ finished = true;
break;
}
- arg_end = (char *)skip_regexp(next_arg + 1, *next_arg, true, NULL);
+ arg_end = skip_regexp((char *)next_arg + 1, *next_arg, true, NULL);
if (*arg_end != (char)(*next_arg)) { // end delimiter not found
illegal = true;
break;
@@ -5226,14 +5208,14 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
if (!eap->skip) {
// store the pattern and compiled regexp program
curwin->w_s->b_syn_linecont_pat =
- vim_strnsave(next_arg + 1, (size_t)(arg_end - (char *)next_arg) - 1);
+ (char *)vim_strnsave(next_arg + 1, (size_t)(arg_end - (char *)next_arg) - 1);
curwin->w_s->b_syn_linecont_ic = curwin->w_s->b_syn_ic;
// Make 'cpoptions' empty, to avoid the 'l' flag
cpo_save = p_cpo;
- p_cpo = "";
+ p_cpo = empty_option;
curwin->w_s->b_syn_linecont_prog =
- vim_regcomp((char *)curwin->w_s->b_syn_linecont_pat, RE_MAGIC);
+ vim_regcomp(curwin->w_s->b_syn_linecont_pat, RE_MAGIC);
p_cpo = cpo_save;
syn_clear_time(&curwin->w_s->b_syn_linecont_time);
@@ -5247,15 +5229,15 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
} else {
eap->arg = (char *)next_arg;
if (STRCMP(key, "MATCH") == 0) {
- syn_cmd_match(eap, TRUE);
+ syn_cmd_match(eap, true);
} else if (STRCMP(key, "REGION") == 0) {
- syn_cmd_region(eap, TRUE);
+ syn_cmd_region(eap, true);
} else if (STRCMP(key, "CLEAR") == 0) {
- syn_cmd_clear(eap, TRUE);
+ syn_cmd_clear(eap, true);
} else {
- illegal = TRUE;
+ illegal = true;
}
- finished = TRUE;
+ finished = true;
break;
}
arg_start = next_arg;
@@ -5265,7 +5247,7 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
semsg(_("E404: Illegal arguments: %s"), arg_start);
} else if (!finished) {
eap->nextcmd = (char *)check_nextcmd(arg_start);
- redraw_curbuf_later(SOME_VALID);
+ redraw_curbuf_later(UPD_SOME_VALID);
syn_stack_free_all(curwin->w_s); // Need to recompute all syntax.
}
}
@@ -5279,7 +5261,7 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
/// @param list where to store the resulting list, if not NULL, the list is silently skipped!
///
/// @return FAIL for some error, OK for success.
-static int get_id_list(char_u **const arg, const int keylen, int16_t **const list, const bool skip)
+static int get_id_list(char **const arg, const int keylen, int16_t **const list, const bool skip)
{
char *p = NULL;
char *end;
@@ -5296,7 +5278,7 @@ static int get_id_list(char_u **const arg, const int keylen, int16_t **const lis
// grow when a regexp is used. In that case round 1 is done once again.
for (int round = 1; round <= 2; round++) {
// skip "contains"
- p = skipwhite((char *)(*arg) + keylen);
+ p = skipwhite(*arg + keylen);
if (*p != '=') {
semsg(_("E405: Missing equal sign: %s"), *arg);
break;
@@ -5364,7 +5346,7 @@ static int get_id_list(char_u **const arg, const int keylen, int16_t **const lis
break;
}
- regmatch.rm_ic = TRUE;
+ regmatch.rm_ic = true;
id = 0;
for (int i = highlight_num_groups(); --i >= 0;) {
if (vim_regexec(&regmatch, (char *)highlight_group_name(i), (colnr_T)0)) {
@@ -5421,7 +5403,7 @@ static int get_id_list(char_u **const arg, const int keylen, int16_t **const lis
}
}
- *arg = (char_u *)p;
+ *arg = p;
if (failed || retval == NULL) {
xfree(retval);
return FAIL;
@@ -5472,7 +5454,7 @@ static int in_id_list(stateitem_T *cur_si, int16_t *list, struct sp_syn *ssp, in
static int depth = 0;
int r;
- // If ssp has a "containedin" list and "cur_si" is in it, return TRUE.
+ // If ssp has a "containedin" list and "cur_si" is in it, return true.
if (cur_si != NULL && ssp->cont_in_list != NULL
&& !(cur_si->si_flags & HL_MATCH)) {
// Ignore transparent items without a contains argument. Double check
@@ -5486,12 +5468,12 @@ static int in_id_list(stateitem_T *cur_si, int16_t *list, struct sp_syn *ssp, in
&(SYN_ITEMS(syn_block)[cur_si->si_idx].sp_syn),
SYN_ITEMS(syn_block)[cur_si->si_idx].sp_flags &
HL_CONTAINED)) {
- return TRUE;
+ return true;
}
}
if (list == NULL) {
- return FALSE;
+ return false;
}
/*
@@ -5502,33 +5484,31 @@ static int in_id_list(stateitem_T *cur_si, int16_t *list, struct sp_syn *ssp, in
return !contained;
}
- /*
- * If the first item is "ALLBUT", return TRUE if "id" is NOT in the
- * contains list. We also require that "id" is at the same ":syn include"
- * level as the list.
- */
+ // If the first item is "ALLBUT", return true if "id" is NOT in the
+ // contains list. We also require that "id" is at the same ":syn include"
+ // level as the list.
item = *list;
if (item >= SYNID_ALLBUT && item < SYNID_CLUSTER) {
if (item < SYNID_TOP) {
// ALL or ALLBUT: accept all groups in the same file
if (item - SYNID_ALLBUT != ssp->inc_tag) {
- return FALSE;
+ return false;
}
} else if (item < SYNID_CONTAINED) {
// TOP: accept all not-contained groups in the same file
if (item - SYNID_TOP != ssp->inc_tag || contained) {
- return FALSE;
+ return false;
}
} else {
// CONTAINED: accept all contained groups in the same file
if (item - SYNID_CONTAINED != ssp->inc_tag || !contained) {
- return FALSE;
+ return false;
}
}
item = *++list;
- retval = FALSE;
+ retval = false;
} else {
- retval = TRUE;
+ retval = true;
}
/*
@@ -5675,7 +5655,8 @@ static enum {
EXP_SUBCMD, // expand ":syn" sub-commands
EXP_CASE, // expand ":syn case" arguments
EXP_SPELL, // expand ":syn spell" arguments
- EXP_SYNC, // expand ":syn sync" arguments
+ EXP_SYNC, // expand ":syn sync" arguments
+ EXP_CLUSTER, // expand ":syn list @cluster" arguments
} expand_what;
/*
@@ -5712,10 +5693,10 @@ void set_context_in_syntax_cmd(expand_T *xp, const char *arg)
// (part of) subcommand already typed
if (*arg != NUL) {
- const char *p = (const char *)skiptowhite((const char_u *)arg);
+ const char *p = (const char *)skiptowhite(arg);
if (*p != NUL) { // Past first word.
xp->xp_pattern = skipwhite(p);
- if (*skiptowhite((char_u *)xp->xp_pattern) != NUL) {
+ if (*skiptowhite(xp->xp_pattern) != NUL) {
xp->xp_context = EXPAND_NOTHING;
} else if (STRNICMP(arg, "case", p - arg) == 0) {
expand_what = EXP_CASE;
@@ -5723,10 +5704,16 @@ void set_context_in_syntax_cmd(expand_T *xp, const char *arg)
expand_what = EXP_SPELL;
} else if (STRNICMP(arg, "sync", p - arg) == 0) {
expand_what = EXP_SYNC;
+ } else if (STRNICMP(arg, "list", p - arg) == 0) {
+ p = skipwhite(p);
+ if (*p == '@') {
+ expand_what = EXP_CLUSTER;
+ } else {
+ xp->xp_context = EXPAND_HIGHLIGHT;
+ }
} else if (STRNICMP(arg, "keyword", p - arg) == 0
|| STRNICMP(arg, "region", p - arg) == 0
- || STRNICMP(arg, "match", p - arg) == 0
- || STRNICMP(arg, "list", p - arg) == 0) {
+ || STRNICMP(arg, "match", p - arg) == 0) {
xp->xp_context = EXPAND_HIGHLIGHT;
} else {
xp->xp_context = EXPAND_NOTHING;
@@ -5760,6 +5747,14 @@ char *get_syntax_name(expand_T *xp, int idx)
"maxlines=", "minlines=", "region", NULL };
return sync_args[idx];
}
+ case EXP_CLUSTER:
+ if (idx < curwin->w_s->b_syn_clusters.ga_len) {
+ vim_snprintf(xp->xp_buf, EXPAND_BUF_LEN, "@%s",
+ SYN_CLSTR(curwin->w_s)[idx].scl_name);
+ return xp->xp_buf;
+ } else {
+ return NULL;
+ }
}
return NULL;
}
@@ -5832,7 +5827,7 @@ int syn_get_stack_item(int i)
{
if (i >= current_state.ga_len) {
// Need to invalidate the state, because we didn't properly finish it
- // for the last character, "keep_state" was TRUE.
+ // for the last character, "keep_state" was true.
invalidate_current_state();
current_col = MAXCOL;
return -1;
@@ -5927,7 +5922,7 @@ static void syntime_clear(void)
msg(_(msg_no_items));
return;
}
- for (int idx = 0; idx < curwin->w_s->b_syn_patterns.ga_len; ++idx) {
+ for (int idx = 0; idx < curwin->w_s->b_syn_patterns.ga_len; idx++) {
spp = &(SYN_ITEMS(curwin->w_s)[idx]);
syn_clear_time(&spp->sp_time);
}
@@ -5976,7 +5971,7 @@ static void syntime_report(void)
proftime_T total_total = profile_zero();
int total_count = 0;
time_entry_T *p;
- for (int idx = 0; idx < curwin->w_s->b_syn_patterns.ga_len; ++idx) {
+ for (int idx = 0; idx < curwin->w_s->b_syn_patterns.ga_len; idx++) {
synpat_T *spp = &(SYN_ITEMS(curwin->w_s)[idx]);
if (spp->sp_time.count > 0) {
p = GA_APPEND_VIA_PTR(time_entry_T, &ga);
@@ -6002,7 +5997,7 @@ static void syntime_report(void)
msg_puts_title(_(" TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN"));
msg_puts("\n");
- for (int idx = 0; idx < ga.ga_len && !got_int; ++idx) {
+ for (int idx = 0; idx < ga.ga_len && !got_int; idx++) {
p = ((time_entry_T *)ga.ga_data) + idx;
msg_puts(profile_msg(p->total));
@@ -6033,7 +6028,7 @@ static void syntime_report(void)
if (len > (int)STRLEN(p->pattern)) {
len = (int)STRLEN(p->pattern);
}
- msg_outtrans_len(p->pattern, len);
+ msg_outtrans_len((char *)p->pattern, len);
msg_puts("\n");
}
ga_clear(&ga);
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 65c56bf01b..5270412382 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -57,6 +57,7 @@
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
@@ -202,7 +203,7 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
}
prev_num_matches = num_matches;
- free_string_option(nofile_fname);
+ free_string_option((char *)nofile_fname);
nofile_fname = NULL;
clearpos(&saved_fmark.mark); // shutup gcc 4.0
@@ -215,7 +216,7 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
new_tag = true;
if (g_do_tagpreview != 0) {
tagstack_clear_entry(&ptag_entry);
- ptag_entry.tagname = vim_strsave(tag);
+ ptag_entry.tagname = (char *)vim_strsave(tag);
}
} else {
if (g_do_tagpreview != 0) {
@@ -239,7 +240,7 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
cur_fnum = ptag_entry.cur_fnum;
} else {
tagstack_clear_entry(&ptag_entry);
- ptag_entry.tagname = vim_strsave(tag);
+ ptag_entry.tagname = (char *)vim_strsave(tag);
}
} else {
/*
@@ -261,7 +262,7 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
}
// put the tag name in the tag stack
- tagstack[tagstackidx].tagname = vim_strsave(tag);
+ tagstack[tagstackidx].tagname = (char *)vim_strsave(tag);
curwin->w_tagstacklen = tagstacklen;
@@ -440,9 +441,9 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
// When desired match not found yet, try to find it (and others).
if (use_tagstack) {
- name = tagstack[tagstackidx].tagname;
+ name = (char_u *)tagstack[tagstackidx].tagname;
} else if (g_do_tagpreview != 0) {
- name = ptag_entry.tagname;
+ name = (char_u *)ptag_entry.tagname;
} else {
name = tag;
}
@@ -483,8 +484,8 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
flags |= TAG_NO_TAGFUNC;
}
- if (find_tags(name, &new_num_matches, &new_matches, flags,
- max_num_matches, buf_ffname) == OK
+ if (find_tags((char *)name, &new_num_matches, &new_matches, flags,
+ max_num_matches, (char *)buf_ffname) == OK
&& new_num_matches < max_num_matches) {
max_num_matches = MAXCOL; // If less than max_num_matches
// found: all matches found.
@@ -587,9 +588,9 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
if (use_tfu && parse_match((char_u *)matches[cur_match], &tagp2) == OK
&& tagp2.user_data) {
XFREE_CLEAR(tagstack[tagstackidx].user_data);
- tagstack[tagstackidx].user_data = vim_strnsave(tagp2.user_data,
- (size_t)(tagp2.user_data_end -
- tagp2.user_data));
+ tagstack[tagstackidx].user_data = (char *)vim_strnsave(tagp2.user_data,
+ (size_t)(tagp2.user_data_end -
+ tagp2.user_data));
}
tagstackidx++;
@@ -737,7 +738,7 @@ static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char
mt_names[matches[i][0] & MT_MASK]);
msg_puts((char *)IObuff);
if (tagp.tagkind != NULL) {
- msg_outtrans_len(tagp.tagkind,
+ msg_outtrans_len((char *)tagp.tagkind,
(int)(tagp.tagkind_end - tagp.tagkind));
}
msg_advance(13);
@@ -751,7 +752,7 @@ static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char
// it and put "..." in the middle
p = tag_full_fname(&tagp);
if (p != NULL) {
- msg_outtrans_attr(p, HL_ATTR(HLF_D));
+ msg_outtrans_attr((char *)p, HL_ATTR(HLF_D));
XFREE_CLEAR(p);
}
if (msg_col > 0) {
@@ -793,7 +794,7 @@ static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char
}
msg_advance(15);
}
- p = msg_outtrans_one(p, attr);
+ p = (char_u *)msg_outtrans_one((char *)p, attr);
if (*p == TAB) {
msg_puts_attr(" ", attr);
break;
@@ -851,7 +852,7 @@ static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char
msg_putchar(' ');
p++;
} else {
- p = msg_outtrans_one(p, 0);
+ p = (char_u *)msg_outtrans_one((char *)p, 0);
}
// don't display the "$/;\"" and "$?;\""
@@ -1036,7 +1037,7 @@ void do_tags(exarg_T *eap)
// Highlight title
msg_puts_title(_("\n # TO tag FROM line in file/text"));
- for (i = 0; i < tagstacklen; ++i) {
+ 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
@@ -1051,7 +1052,7 @@ void do_tags(exarg_T *eap)
tagstack[i].tagname,
tagstack[i].fmark.mark.lnum);
msg_outtrans((char *)IObuff);
- msg_outtrans_attr(name, tagstack[i].fmark.fnum == curbuf->b_fnum
+ msg_outtrans_attr((char *)name, tagstack[i].fmark.fnum == curbuf->b_fnum
? HL_ATTR(HLF_D) : 0);
xfree(name);
}
@@ -1184,7 +1185,7 @@ static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int fl
flags & TAG_REGEXP ? "r": "");
save_pos = curwin->w_cursor;
- result = call_vim_function((char *)curbuf->b_p_tfu, 3, args, &rettv);
+ result = call_vim_function(curbuf->b_p_tfu, 3, args, &rettv);
curwin->w_cursor = save_pos; // restore the cursor position
d->dv_refcount--;
@@ -1365,8 +1366,8 @@ static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int fl
/// @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 ***matchesp, int flags, int mincount,
- char_u *buf_ffname)
+int find_tags(char *pat, int *num_matches, char ***matchesp, int flags, int mincount,
+ char *buf_ffname)
{
FILE *fp;
char_u *lbuf; // line buffer
@@ -1409,7 +1410,7 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
int cmplen;
int match; // matches
- int match_no_ic = 0; // matches with rm_ic == FALSE
+ int match_no_ic = 0; // matches with rm_ic == false
int match_re; // match with regexp
int matchoff = 0;
int save_emsg_off;
@@ -1441,7 +1442,7 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
int help_only = (flags & TAG_HELP);
int name_only = (flags & TAG_NAMES);
int noic = (flags & TAG_NOIC);
- int get_it_again = FALSE;
+ int get_it_again = false;
int use_cscope = (flags & TAG_CSCOPE);
int verbose = (flags & TAG_VERBOSE);
int use_tfu = ((flags & TAG_NO_TAGFUNC) == 0);
@@ -1459,17 +1460,17 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
p_ic = false;
break;
case TC_FOLLOWSCS:
- p_ic = ignorecase(pat);
+ p_ic = ignorecase((char_u *)pat);
break;
case TC_SMART:
- p_ic = ignorecase_opt(pat, true, true);
+ p_ic = ignorecase_opt((char_u *)pat, true, true);
break;
default:
abort();
}
help_save = curbuf->b_help;
- orgpat.pat = pat;
+ orgpat.pat = (char_u *)pat;
orgpat.regmatch.regprog = NULL;
vimconv.vc_type = CONV_NONE;
@@ -1503,8 +1504,8 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
if (orgpat.len > 3 && pat[orgpat.len - 3] == '@'
&& ASCII_ISALPHA(pat[orgpat.len - 2])
&& ASCII_ISALPHA(pat[orgpat.len - 1])) {
- saved_pat = vim_strnsave(pat, (size_t)orgpat.len - 3);
- help_lang_find = &pat[orgpat.len - 2];
+ saved_pat = vim_strnsave((char_u *)pat, (size_t)orgpat.len - 3);
+ help_lang_find = (char_u *)&pat[orgpat.len - 2];
orgpat.pat = saved_pat;
orgpat.len -= 3;
}
@@ -1514,7 +1515,7 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
}
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) {
@@ -1527,8 +1528,8 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
if (*curbuf->b_p_tfu != NUL && use_tfu && !tfu_in_use) {
tfu_in_use = true;
- retval = find_tagfunc_tags(pat, &ga_match[0], &match_count,
- flags, buf_ffname);
+ retval = find_tagfunc_tags((char_u *)pat, &ga_match[0], &match_count, flags,
+ (char_u *)buf_ffname);
tfu_in_use = false;
if (retval != NOTDONE) {
goto findtag_end;
@@ -1555,12 +1556,12 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
}
orgpat.regmatch.rm_ic = ((p_ic || !noic)
&& (findall || orgpat.headlen == 0 || !p_tbs));
- for (round = 1; round <= 2; ++round) {
+ for (round = 1; round <= 2; round++) {
linear = (orgpat.headlen == 0 || !p_tbs || round == 2);
// Try tag file names from tags option one by one.
for (first_file = true;
- use_cscope || get_tagfname(&tn, first_file, tag_fname) == OK;
+ use_cscope || get_tagfname(&tn, first_file, (char *)tag_fname) == OK;
first_file = false) {
// A file that doesn't exist is silently ignored. Only when not a
// single file is found, an error message is given (further on).
@@ -1601,7 +1602,7 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
help_pri = 0;
} else {
help_pri = 1;
- for (s = p_hlg; *s != NUL; ++s) {
+ for (s = p_hlg; *s != NUL; s++) {
if (STRNICMP(s, help_lang, 2) == 0) {
break;
}
@@ -1704,7 +1705,7 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
eof = vim_fgets(lbuf, lbuf_size, fp);
}
// skip empty and blank lines
- while (!eof && vim_isblankline(lbuf)) {
+ while (!eof && vim_isblankline((char *)lbuf)) {
search_info.curr_offset = vim_ftell(fp);
eof = vim_fgets(lbuf, lbuf_size, fp);
}
@@ -1725,7 +1726,7 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
eof = use_cscope
? cs_fgets(lbuf, lbuf_size)
: vim_fgets(lbuf, lbuf_size, fp);
- } while (!eof && vim_isblankline(lbuf));
+ } while (!eof && vim_isblankline((char *)lbuf));
if (eof) {
break; // end of file
@@ -1740,7 +1741,7 @@ line_read_in:
// Convert every line. Converting the pattern from 'enc' to
// the tags file encoding doesn't work, because characters are
// not recognized.
- conv_line = string_convert(&vimconv, lbuf, NULL);
+ conv_line = (char_u *)string_convert(&vimconv, (char *)lbuf, NULL);
if (conv_line != NULL) {
// Copy or swap lbuf and conv_line.
len = (int)STRLEN(conv_line) + 1;
@@ -1780,7 +1781,7 @@ line_read_in:
// encoding to 'encoding'.
for (p = lbuf + 20; *p > ' ' && *p < 127; p++) {}
*p = NUL;
- convert_setup(&vimconv, lbuf + 20, p_enc);
+ convert_setup(&vimconv, (char *)lbuf + 20, p_enc);
}
// Read the next line. Unrecognized flags are ignored.
@@ -2009,7 +2010,7 @@ parse_line:
}
// if tag length does not match, don't try comparing
if (orgpat.len != cmplen) {
- match = FALSE;
+ match = false;
} else {
if (orgpat.regmatch.rm_ic) {
assert(cmplen >= 0);
@@ -2026,7 +2027,7 @@ parse_line:
/*
* Has a regexp: Also find tags matching regexp.
*/
- match_re = FALSE;
+ match_re = false;
if (!match && orgpat.regmatch.regprog != NULL) {
int cc;
@@ -2054,7 +2055,8 @@ parse_line:
mtt = MT_GL_OTH;
} else {
// Decide in which array to store this match.
- is_current = test_for_current(tagp.fname, tagp.fname_end, tag_fname,
+ is_current = test_for_current((char *)tagp.fname, (char *)tagp.fname_end,
+ (char *)tag_fname,
buf_ffname);
is_static = test_for_static(&tagp);
@@ -2236,7 +2238,7 @@ parse_line:
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) {
@@ -2334,14 +2336,14 @@ void free_tag_stuff(void)
/// For help files, use "tags" file only.
///
/// @param tnp holds status info
-/// @param first TRUE when first file name is wanted
+/// @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)
+int get_tagfname(tagname_T *tnp, int first, char *buf)
{
- char_u *fname = NULL;
- char_u *r_ptr;
+ char *fname = NULL;
+ char *r_ptr;
if (first) {
CLEAR_POINTER(tnp);
@@ -2366,13 +2368,13 @@ int get_tagfname(tagname_T *tnp, int first, char_u *buf)
if (tnp->tn_hf_idx > tag_fnames.ga_len || *p_hf == NUL) {
return FAIL;
}
- ++tnp->tn_hf_idx;
+ tnp->tn_hf_idx++;
STRCPY(buf, p_hf);
STRCPY(path_tail((char *)buf), "tags");
#ifdef BACKSLASH_IN_FILENAME
slash_adjust(buf);
#endif
- simplify_filename(buf);
+ simplify_filename((char_u *)buf);
for (int i = 0; i < tag_fnames.ga_len; i++) {
if (STRCMP(buf, ((char **)(tag_fnames.ga_data))[i]) == 0) {
@@ -2388,24 +2390,24 @@ int get_tagfname(tagname_T *tnp, int first, char_u *buf)
if (first) {
// Init. We make a copy of 'tags', because autocommands may change
// the value without notifying us.
- tnp->tn_tags = vim_strsave((*curbuf->b_p_tags != NUL) ? curbuf->b_p_tags : p_tags);
+ tnp->tn_tags = vim_strsave((*curbuf->b_p_tags != NUL) ? (char_u *)curbuf->b_p_tags : p_tags);
tnp->tn_np = (char *)tnp->tn_tags;
}
/*
* Loop until we have found a file name that can be used.
* There are two states:
- * tnp->tn_did_filefind_init == FALSE: setup for next part in 'tags'.
- * tnp->tn_did_filefind_init == TRUE: find next file in this part.
+ * tnp->tn_did_filefind_init == false: setup for next part in 'tags'.
+ * tnp->tn_did_filefind_init == true: find next file in this part.
*/
for (;;) {
if (tnp->tn_did_filefind_init) {
- fname = vim_findfile(tnp->tn_search_ctx);
+ fname = (char *)vim_findfile(tnp->tn_search_ctx);
if (fname != NULL) {
break;
}
- tnp->tn_did_filefind_init = FALSE;
+ tnp->tn_did_filefind_init = false;
} else {
char_u *filename = NULL;
@@ -2420,22 +2422,22 @@ int get_tagfname(tagname_T *tnp, int first, char_u *buf)
* Copy next file name into buf.
*/
buf[0] = NUL;
- (void)copy_option_part(&tnp->tn_np, (char *)buf, MAXPATHL - 1, " ,");
+ (void)copy_option_part(&tnp->tn_np, buf, MAXPATHL - 1, " ,");
- r_ptr = vim_findfile_stopdir(buf);
+ r_ptr = (char *)vim_findfile_stopdir((char_u *)buf);
// move the filename one char forward and truncate the
// filepath with a NUL
- filename = (char_u *)path_tail((char *)buf);
+ filename = (char_u *)path_tail(buf);
STRMOVE(filename + 1, filename);
*filename++ = NUL;
- tnp->tn_search_ctx = vim_findfile_init(buf, filename,
- r_ptr, 100,
- FALSE, // don't free visited list
+ tnp->tn_search_ctx = vim_findfile_init((char_u *)buf, filename,
+ (char_u *)r_ptr, 100,
+ false, // don't free visited list
FINDFILE_FILE, // we search for a file
tnp->tn_search_ctx, true, (char_u *)curbuf->b_ffname);
if (tnp->tn_search_ctx != NULL) {
- tnp->tn_did_filefind_init = TRUE;
+ tnp->tn_did_filefind_init = true;
}
}
}
@@ -2459,7 +2461,7 @@ void tagname_free(tagname_T *tnp)
/// 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.
+/// If is_etag is true, tagp->fname and tagp->fname_end are not set.
///
/// @param lbuf line to be parsed
///
@@ -2510,8 +2512,8 @@ static int parse_tag_line(char_u *lbuf, tagptrs_T *tagp)
* Static tags produced by the new ctags program have the format:
* '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.
+ * Return true if it is a static tag and adjust *tagname to the real tag.
+ * Return false if it is not a static tag.
*/
static bool test_for_static(tagptrs_T *tagp)
{
@@ -2522,11 +2524,11 @@ static bool test_for_static(tagptrs_T *tagp)
while ((p = (char_u *)vim_strchr((char *)p, '\t')) != NULL) {
p++;
if (STRNCMP(p, "file:", 5) == 0) {
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
// Returns the length of a matching tag line.
@@ -2640,7 +2642,7 @@ static char_u *tag_full_fname(tagptrs_T *tagp)
///
/// @param lbuf_arg line from the tags file for this tag
/// @param forceit :ta with !
-/// @param keep_help keep help flag (FALSE for cscope)
+/// @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)
@@ -2732,7 +2734,7 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
* into a fullpath
*/
if (!curwin->w_p_pvw) {
- full_fname = (char_u *)FullName_save((char *)fname, FALSE);
+ full_fname = (char_u *)FullName_save((char *)fname, false);
fname = full_fname;
/*
@@ -2825,15 +2827,15 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
*/
str = pbuf;
if (pbuf[0] == '/' || pbuf[0] == '?') {
- str = skip_regexp(pbuf + 1, pbuf[0], FALSE, NULL) + 1;
+ str = (char_u *)skip_regexp((char *)pbuf + 1, pbuf[0], false, NULL) + 1;
}
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_scs = FALSE;
+ p_ic = false; // don't ignore case now
+ p_scs = false;
save_lnum = curwin->w_cursor.lnum;
if (tagp.tagline > 0) {
// start search before line from "line:" field
@@ -2944,7 +2946,7 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
&& curwin != curwin_save && win_valid(curwin_save)) {
// Return cursor to where we were
validate_cursor();
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
win_enter(curwin_save, true);
}
@@ -3011,27 +3013,25 @@ static char_u *expand_tag_fname(char_u *fname, char_u *const tag_fname, const bo
return retval;
}
-/*
- * Check if we have a tag for the buffer with name "buf_ffname".
- * This is a bit slow, because of the full path compare in path_full_compare().
- * Return TRUE if tag for file "fname" if tag file "tag_fname" is for current
- * file.
- */
-static int test_for_current(char_u *fname, char_u *fname_end, char_u *tag_fname, char_u *buf_ffname)
+/// Check if we have a tag for the buffer with name "buf_ffname".
+/// This is a bit slow, because of the full path compare in path_full_compare().
+///
+/// @return true if tag for file "fname" if tag file "tag_fname" is for current
+/// file.
+static int test_for_current(char *fname, char *fname_end, char *tag_fname, char *buf_ffname)
{
int c;
- int retval = FALSE;
- char_u *fullname;
+ int retval = false;
if (buf_ffname != NULL) { // if the buffer has a name
{
- c = *fname_end;
+ c = (unsigned char)(*fname_end);
*fname_end = NUL;
}
- fullname = expand_tag_fname(fname, tag_fname, true);
- retval = (path_full_compare((char *)fullname, (char *)buf_ffname, true, true) & kEqualFiles);
+ char *fullname = (char *)expand_tag_fname((char_u *)fname, (char_u *)tag_fname, true);
+ retval = (path_full_compare(fullname, buf_ffname, true, true) & kEqualFiles);
xfree(fullname);
- *fname_end = (char_u)c;
+ *fname_end = (char)c;
}
return retval;
@@ -3051,7 +3051,7 @@ static int find_extra(char_u **pp)
if (ascii_isdigit(*str)) {
str = (char_u *)skipdigits((char *)str + 1);
} else if (*str == '/' || *str == '?') {
- str = skip_regexp(str + 1, *str, false, NULL);
+ str = (char_u *)skip_regexp((char *)str + 1, *str, false, NULL);
if (*str != first_char) {
str = NULL;
} else {
@@ -3107,13 +3107,13 @@ int expand_tags(int tagnames, char_u *pat, int *num_file, char ***file)
extra_flag = 0;
}
if (pat[0] == '/') {
- ret = find_tags(pat + 1, num_file, file,
+ ret = find_tags((char *)pat + 1, num_file, file,
TAG_REGEXP | extra_flag | TAG_VERBOSE | TAG_NO_TAGFUNC,
- TAG_MANY, (char_u *)curbuf->b_ffname);
+ TAG_MANY, curbuf->b_ffname);
} else {
- ret = find_tags(pat, num_file, file,
+ ret = find_tags((char *)pat, num_file, file,
TAG_REGEXP | extra_flag | TAG_VERBOSE | TAG_NO_TAGFUNC | TAG_NOIC,
- TAG_MANY, (char_u *)curbuf->b_ffname);
+ TAG_MANY, curbuf->b_ffname);
}
if (ret == OK && !tagnames) {
// Reorganize the tags for display and matching as strings of:
@@ -3150,8 +3150,7 @@ int expand_tags(int tagnames, char_u *pat, int *num_file, char ***file)
///
/// @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)
+static int add_tag_field(dict_T *dict, const char *field_name, const char *start, const char *end)
FUNC_ATTR_NONNULL_ARG(1, 2)
{
int len = 0;
@@ -3198,8 +3197,8 @@ int get_tags(list_T *list, char_u *pat, char_u *buf_fname)
tagptrs_T tp;
bool is_static;
- ret = find_tags(pat, &num_matches, &matches,
- TAG_REGEXP | TAG_NOIC, MAXCOL, buf_fname);
+ ret = find_tags((char *)pat, &num_matches, &matches,
+ TAG_REGEXP | TAG_NOIC, MAXCOL, (char *)buf_fname);
if (ret == OK && num_matches > 0) {
for (i = 0; i < num_matches; i++) {
int parse_result = parse_match((char_u *)matches[i], &tp);
@@ -3220,11 +3219,11 @@ int get_tags(list_T *list, char_u *pat, char_u *buf_fname)
tv_list_append_dict(list, dict);
full_fname = tag_full_fname(&tp);
- if (add_tag_field(dict, "name", tp.tagname, tp.tagname_end) == FAIL
- || add_tag_field(dict, "filename", full_fname, NULL) == FAIL
- || add_tag_field(dict, "cmd", tp.command, tp.command_end) == FAIL
- || add_tag_field(dict, "kind", tp.tagkind,
- tp.tagkind ? tp.tagkind_end : NULL) == FAIL
+ if (add_tag_field(dict, "name", (char *)tp.tagname, (char *)tp.tagname_end) == FAIL
+ || add_tag_field(dict, "filename", (char *)full_fname, NULL) == FAIL
+ || add_tag_field(dict, "cmd", (char *)tp.command, (char *)tp.command_end) == FAIL
+ || add_tag_field(dict, "kind", (char *)tp.tagkind,
+ tp.tagkind ? (char *)tp.tagkind_end : NULL) == FAIL
|| tv_dict_add_nr(dict, S_LEN("static"), is_static) == FAIL) {
ret = FAIL;
}
@@ -3259,7 +3258,7 @@ int get_tags(list_T *list, char_u *pat, char_u *buf_fname)
p++;
}
n[len] = NUL;
- if (add_tag_field(dict, (char *)n, s, p) == FAIL) {
+ if (add_tag_field(dict, (char *)n, (char *)s, (char *)p) == FAIL) {
ret = FAIL;
}
n[len] = ':';
@@ -3365,7 +3364,7 @@ static void tagstack_push_item(win_T *wp, char_u *tagname, int cur_fnum, int cur
}
wp->w_tagstacklen++;
- tagstack[idx].tagname = tagname;
+ tagstack[idx].tagname = (char *)tagname;
tagstack[idx].cur_fnum = cur_fnum;
tagstack[idx].cur_match = cur_match;
if (tagstack[idx].cur_match < 0) {
@@ -3373,7 +3372,7 @@ static void tagstack_push_item(win_T *wp, char_u *tagname, int cur_fnum, int cur
}
tagstack[idx].fmark.mark = mark;
tagstack[idx].fmark.fnum = fnum;
- tagstack[idx].user_data = user_data;
+ tagstack[idx].user_data = (char *)user_data;
}
// Add a list of items to the tag stack in the specified window
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 08fcefaa88..90966bcfad 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -418,7 +418,7 @@ bool terminal_enter(void)
// placed at end of buffer to "follow" output. #11072
handle_T save_curwin = curwin->handle;
bool save_w_p_cul = curwin->w_p_cul;
- char_u *save_w_p_culopt = NULL;
+ char *save_w_p_culopt = NULL;
char_u save_w_p_culopt_flags = curwin->w_p_culopt_flags;
int save_w_p_cuc = curwin->w_p_cuc;
long save_w_p_so = curwin->w_p_so;
@@ -426,7 +426,7 @@ bool terminal_enter(void)
if (curwin->w_p_cul && curwin->w_p_culopt_flags & CULOPT_NBR) {
if (STRCMP(curwin->w_p_culopt, "number")) {
save_w_p_culopt = curwin->w_p_culopt;
- curwin->w_p_culopt = (char_u *)xstrdup("number");
+ curwin->w_p_culopt = xstrdup("number");
}
curwin->w_p_culopt_flags = CULOPT_NBR;
} else {
@@ -1375,7 +1375,7 @@ static bool send_mouse_event(Terminal *term, int c)
curwin->w_redr_status = true;
curwin = save_curwin;
curbuf = curwin->w_buffer;
- redraw_later(mouse_win, NOT_VALID);
+ redraw_later(mouse_win, UPD_NOT_VALID);
invalidate_terminal(term, -1, -1);
// Only need to exit focus if the scrolled window is the terminal window
return mouse_win == curwin;
diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim
index 206f335751..ce23141c7a 100644
--- a/src/nvim/testdir/runtest.vim
+++ b/src/nvim/testdir/runtest.vim
@@ -425,7 +425,7 @@ for s:test in sort(s:tests)
set belloff=all
let prev_error = ''
let total_errors = []
- let run_nr = 1
+ let g:run_nr = 1
" A test can set g:test_is_flaky to retry running the test.
let g:test_is_flaky = 0
@@ -444,10 +444,10 @@ for s:test in sort(s:tests)
call add(s:messages, 'Found errors in ' . s:test . ':')
call extend(s:messages, v:errors)
- call add(total_errors, 'Run ' . run_nr . ':')
+ call add(total_errors, 'Run ' . g:run_nr . ':')
call extend(total_errors, v:errors)
- if run_nr == 5 || prev_error == v:errors[0]
+ if g:run_nr >= 5 || prev_error == v:errors[0]
call add(total_errors, 'Flaky test failed too often, giving up')
let v:errors = total_errors
break
@@ -462,7 +462,7 @@ for s:test in sort(s:tests)
let prev_error = v:errors[0]
let v:errors = []
- let run_nr += 1
+ let g:run_nr += 1
call RunTheTest(s:test)
diff --git a/src/nvim/testdir/setup.vim b/src/nvim/testdir/setup.vim
index 6bc3607b69..472ed4ca14 100644
--- a/src/nvim/testdir/setup.vim
+++ b/src/nvim/testdir/setup.vim
@@ -5,7 +5,7 @@ if exists('s:did_load')
set directory&
set directory^=.
set display=
- set fillchars=vert:\|,fold:-
+ set fillchars=vert:\|,foldsep:\|,fold:-
set formatoptions=tcq
set fsync
set laststatus=1
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index 716511210d..3064b199d9 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -341,6 +341,39 @@ func Test_WinScrolled_close_curwin()
call delete('Xtestout')
endfunc
+func Test_WinScrolled_long_wrapped()
+ CheckRunVimInTerminal
+
+ let lines =<< trim END
+ set scrolloff=0
+ let height = winheight(0)
+ let width = winwidth(0)
+ let g:scrolled = 0
+ au WinScrolled * let g:scrolled += 1
+ call setline(1, repeat('foo', height * width))
+ call cursor(1, height * width)
+ END
+ call writefile(lines, 'Xtest_winscrolled_long_wrapped')
+ let buf = RunVimInTerminal('-S Xtest_winscrolled_long_wrapped', {'rows': 6})
+
+ call term_sendkeys(buf, ":echo g:scrolled\<CR>")
+ call WaitForAssert({-> assert_match('^0 ', term_getline(buf, 6))}, 1000)
+
+ call term_sendkeys(buf, 'gj')
+ call term_sendkeys(buf, ":echo g:scrolled\<CR>")
+ call WaitForAssert({-> assert_match('^1 ', term_getline(buf, 6))}, 1000)
+
+ call term_sendkeys(buf, '0')
+ call term_sendkeys(buf, ":echo g:scrolled\<CR>")
+ call WaitForAssert({-> assert_match('^2 ', term_getline(buf, 6))}, 1000)
+
+ call term_sendkeys(buf, '$')
+ call term_sendkeys(buf, ":echo g:scrolled\<CR>")
+ call WaitForAssert({-> assert_match('^3 ', term_getline(buf, 6))}, 1000)
+
+ call delete('Xtest_winscrolled_long_wrapped')
+endfunc
+
func Test_WinClosed()
" Test that the pattern is matched against the closed window's ID, and both
" <amatch> and <afile> are set to it.
@@ -493,6 +526,26 @@ func Test_BufReadCmdHelpJump()
au! BufReadCmd
endfunc
+" BufReadCmd is triggered for a "nofile" buffer. Check all values.
+func Test_BufReadCmdNofile()
+ for val in ['nofile',
+ \ 'nowrite',
+ \ 'acwrite',
+ \ 'quickfix',
+ \ 'help',
+ \ 'prompt',
+ \ ]
+ new somefile
+ exe 'set buftype=' .. val
+ au BufReadCmd somefile call setline(1, 'triggered')
+ edit
+ call assert_equal('triggered', getline(1))
+
+ au! BufReadCmd
+ bwipe!
+ endfor
+endfunc
+
func Test_augroup_deleted()
" This caused a crash before E936 was introduced
augroup x
@@ -587,9 +640,26 @@ func Test_BufEnter()
" On MS-Windows we can't edit the directory, make sure we wipe the right
" buffer.
bwipe! Xdir
-
call delete('Xdir', 'd')
au! BufEnter
+
+ " Editing a "nofile" buffer doesn't read the file but does trigger BufEnter
+ " for historic reasons. Also test other 'buftype' values.
+ for val in ['nofile',
+ \ 'nowrite',
+ \ 'acwrite',
+ \ 'quickfix',
+ \ 'help',
+ \ 'prompt',
+ \ ]
+ new somefile
+ exe 'set buftype=' .. val
+ au BufEnter somefile call setline(1, 'some text')
+ edit
+ call assert_equal('some text', getline(1))
+ bwipe!
+ au! BufEnter
+ endfor
endfunc
" Closing a window might cause an endless loop
@@ -1766,6 +1836,21 @@ func Test_BufReadCmd()
au! BufWriteCmd
endfunc
+func Test_BufWriteCmd()
+ autocmd BufWriteCmd Xbufwritecmd let g:written = 1
+ new
+ file Xbufwritecmd
+ set buftype=acwrite
+ call mkdir('Xbufwritecmd')
+ write
+ " BufWriteCmd should be triggered even if a directory has the same name
+ call assert_equal(1, g:written)
+ call delete('Xbufwritecmd', 'd')
+ unlet g:written
+ au! BufWriteCmd
+ bwipe!
+endfunc
+
func SetChangeMarks(start, end)
exe a:start .. 'mark ['
exe a:end .. 'mark ]'
@@ -2724,6 +2809,30 @@ func Test_autocmd_FileReadCmd()
delfunc ReadFileCmd
endfunc
+" Test for passing invalid arguments to autocmd
+func Test_autocmd_invalid_args()
+ " Additional character after * for event
+ call assert_fails('autocmd *a Xfile set ff=unix', 'E215:')
+ augroup Test
+ augroup END
+ " Invalid autocmd event
+ call assert_fails('autocmd Bufabc Xfile set ft=vim', 'E216:')
+ " Invalid autocmd event in a autocmd group
+ call assert_fails('autocmd Test Bufabc Xfile set ft=vim', 'E216:')
+ augroup! Test
+ " Execute all autocmds
+ call assert_fails('doautocmd * BufEnter', 'E217:')
+ call assert_fails('augroup! x1a2b3', 'E367:')
+ call assert_fails('autocmd BufNew <buffer=999> pwd', 'E680:')
+endfunc
+
+" Test for deep nesting of autocmds
+func Test_autocmd_deep_nesting()
+ autocmd BufEnter Xfile doautocmd BufEnter Xfile
+ call assert_fails('doautocmd BufEnter Xfile', 'E218:')
+ autocmd! BufEnter Xfile
+endfunc
+
" Tests for SigUSR1 autocmd event, which is only available on posix systems.
func Test_autocmd_sigusr1()
CheckUnix
diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim
index af42b3857d..70529c14d5 100644
--- a/src/nvim/testdir/test_blob.vim
+++ b/src/nvim/testdir/test_blob.vim
@@ -294,7 +294,7 @@ func Test_blob_index()
call assert_equal(2, index(0zDEADBEEF, 0xBE))
call assert_equal(-1, index(0zDEADBEEF, 0))
call assert_equal(2, index(0z11111111, 0x11, 2))
- call assert_equal(3, index(0z11110111, 0x11, 2))
+ call assert_equal(3, 0z11110111->index(0x11, 2))
call assert_equal(2, index(0z11111111, 0x11, -2))
call assert_equal(3, index(0z11110111, 0x11, -2))
diff --git a/src/nvim/testdir/test_buffer.vim b/src/nvim/testdir/test_buffer.vim
index 67be3e6747..4def3b5df9 100644
--- a/src/nvim/testdir/test_buffer.vim
+++ b/src/nvim/testdir/test_buffer.vim
@@ -154,6 +154,24 @@ func Test_bdelete_cmd()
set nobuflisted
enew
call assert_fails('bdelete ' .. bnr, 'E516:')
+
+ " Deleting more than one buffer
+ new Xbuf1
+ new Xbuf2
+ exe 'bdel ' .. bufnr('Xbuf2') .. ' ' .. bufnr('Xbuf1')
+ call assert_equal(1, winnr('$'))
+ call assert_equal(0, getbufinfo('Xbuf1')[0].loaded)
+ call assert_equal(0, getbufinfo('Xbuf2')[0].loaded)
+
+ " Deleting more than one buffer and an invalid buffer
+ new Xbuf1
+ new Xbuf2
+ let cmd = "exe 'bdel ' .. bufnr('Xbuf2') .. ' xxx ' .. bufnr('Xbuf1')"
+ call assert_fails(cmd, 'E94:')
+ call assert_equal(2, winnr('$'))
+ call assert_equal(1, getbufinfo('Xbuf1')[0].loaded)
+ call assert_equal(0, getbufinfo('Xbuf2')[0].loaded)
+
%bwipe!
endfunc
@@ -168,6 +186,194 @@ func Test_buffer_error()
%bwipe
endfunc
+" Test for the status messages displayed when unloading, deleting or wiping
+" out buffers
+func Test_buffer_statusmsg()
+ CheckEnglish
+ set report=1
+ new Xbuf1
+ new Xbuf2
+ let bnr = bufnr()
+ exe "normal 2\<C-G>"
+ call assert_match('buf ' .. bnr .. ':', v:statusmsg)
+ bunload Xbuf1 Xbuf2
+ call assert_equal('2 buffers unloaded', v:statusmsg)
+ bdel Xbuf1 Xbuf2
+ call assert_equal('2 buffers deleted', v:statusmsg)
+ bwipe Xbuf1 Xbuf2
+ call assert_equal('2 buffers wiped out', v:statusmsg)
+ set report&
+endfunc
+
+" Test for quitting the 'swapfile exists' dialog with the split buffer
+" command.
+func Test_buffer_sbuf_cleanup()
+ call writefile([], 'Xfile')
+ " first open the file in a buffer
+ new Xfile
+ let bnr = bufnr()
+ close
+ " create the swap file
+ call writefile([], '.Xfile.swp')
+ " Remove the catch-all that runtest.vim adds
+ au! SwapExists
+ augroup BufTest
+ au!
+ autocmd SwapExists Xfile let v:swapchoice='q'
+ augroup END
+ exe 'sbuf ' . bnr
+ call assert_equal(1, winnr('$'))
+ call assert_equal(0, getbufinfo('Xfile')[0].loaded)
+
+ " test for :sball
+ sball
+ call assert_equal(1, winnr('$'))
+ call assert_equal(0, getbufinfo('Xfile')[0].loaded)
+
+ %bw!
+ set shortmess+=F
+ let v:statusmsg = ''
+ edit Xfile
+ call assert_equal('', v:statusmsg)
+ call assert_equal(1, winnr('$'))
+ call assert_equal(0, getbufinfo('Xfile')[0].loaded)
+ set shortmess&
+
+ call delete('Xfile')
+ call delete('.Xfile.swp')
+ augroup BufTest
+ au!
+ augroup END
+ augroup! BufTest
+endfunc
+
+" Test for deleting a modified buffer with :confirm
+func Test_bdel_with_confirm()
+ " requires a UI to be active
+ throw 'Skipped: use test/functional/legacy/buffer_spec.lua'
+ CheckUnix
+ CheckNotGui
+ CheckFeature dialog_con
+ new
+ call setline(1, 'test')
+ call assert_fails('bdel', 'E89:')
+ call feedkeys('c', 'L')
+ confirm bdel
+ call assert_equal(2, winnr('$'))
+ call assert_equal(1, &modified)
+ call feedkeys('n', 'L')
+ confirm bdel
+ call assert_equal(1, winnr('$'))
+endfunc
+
+" Test for editing another buffer from a modified buffer with :confirm
+func Test_goto_buf_with_confirm()
+ " requires a UI to be active
+ throw 'Skipped: use test/functional/legacy/buffer_spec.lua'
+ CheckUnix
+ CheckNotGui
+ CheckFeature dialog_con
+ new Xfile
+ enew
+ call setline(1, 'test')
+ call assert_fails('b Xfile', 'E37:')
+ call feedkeys('c', 'L')
+ call assert_fails('confirm b Xfile', 'E37:')
+ call assert_equal(1, &modified)
+ call assert_equal('', @%)
+ call feedkeys('y', 'L')
+ call assert_fails('confirm b Xfile', 'E37:')
+ call assert_equal(1, &modified)
+ call assert_equal('', @%)
+ call feedkeys('n', 'L')
+ confirm b Xfile
+ call assert_equal('Xfile', @%)
+ close!
+endfunc
+
+" Test for splitting buffer with 'switchbuf'
+func Test_buffer_switchbuf()
+ new Xfile
+ wincmd w
+ set switchbuf=useopen
+ sbuf Xfile
+ call assert_equal(1, winnr())
+ call assert_equal(2, winnr('$'))
+ set switchbuf=usetab
+ tabnew
+ sbuf Xfile
+ call assert_equal(1, tabpagenr())
+ call assert_equal(2, tabpagenr('$'))
+ set switchbuf&
+ %bw
+endfunc
+
+" Test for BufAdd autocommand wiping out the buffer
+func Test_bufadd_autocmd_bwipe()
+ %bw!
+ augroup BufAdd_Wipe
+ au!
+ autocmd BufAdd Xfile %bw!
+ augroup END
+ edit Xfile
+ call assert_equal('', @%)
+ call assert_equal(0, bufexists('Xfile'))
+ augroup BufAdd_Wipe
+ au!
+ augroup END
+ augroup! BufAdd_Wipe
+endfunc
+
+" Test for trying to load a buffer with text locked
+" <C-\>e in the command line is used to lock the text
+func Test_load_buf_with_text_locked()
+ new Xfile1
+ edit Xfile2
+ let cmd = ":\<C-\>eexecute(\"normal \<C-O>\")\<CR>\<C-C>"
+ call assert_fails("call feedkeys(cmd, 'xt')", 'E565:')
+ %bw!
+endfunc
+
+" Test for using CTRL-^ to edit the alternative file keeping the cursor
+" position with 'nostartofline'. Also test using the 'buf' command.
+func Test_buffer_edit_altfile()
+ call writefile(repeat(['one two'], 50), 'Xfile1')
+ call writefile(repeat(['five six'], 50), 'Xfile2')
+ set nosol
+ edit Xfile1
+ call cursor(25, 5)
+ edit Xfile2
+ call cursor(30, 4)
+ exe "normal \<C-^>"
+ call assert_equal([0, 25, 5, 0], getpos('.'))
+ exe "normal \<C-^>"
+ call assert_equal([0, 30, 4, 0], getpos('.'))
+ buf Xfile1
+ call assert_equal([0, 25, 5, 0], getpos('.'))
+ buf Xfile2
+ call assert_equal([0, 30, 4, 0], getpos('.'))
+ set sol&
+ call delete('Xfile1')
+ call delete('Xfile2')
+endfunc
+
+" Test for running the :sball command with a maximum window count and a
+" modified buffer
+func Test_sball_with_count()
+ %bw!
+ edit Xfile1
+ call setline(1, ['abc'])
+ new Xfile2
+ new Xfile3
+ new Xfile4
+ 2sball
+ call assert_equal(bufnr('Xfile4'), winbufnr(1))
+ call assert_equal(bufnr('Xfile1'), winbufnr(2))
+ call assert_equal(0, getbufinfo('Xfile2')[0].loaded)
+ call assert_equal(0, getbufinfo('Xfile3')[0].loaded)
+ %bw!
+endfunc
+
func Test_badd_options()
new SomeNewBuffer
setlocal numberwidth=3
diff --git a/src/nvim/testdir/test_bufline.vim b/src/nvim/testdir/test_bufline.vim
index 579d3a5eb5..3b5bcbce89 100644
--- a/src/nvim/testdir/test_bufline.vim
+++ b/src/nvim/testdir/test_bufline.vim
@@ -19,7 +19,7 @@ func Test_setbufline_getbufline()
let b = bufnr('%')
wincmd w
call assert_equal(1, setbufline(b, 5, ['x']))
- call assert_equal(1, setbufline(bufnr('$') + 1, 1, ['x']))
+ call assert_equal(1, ['x']->setbufline(bufnr('$') + 1, 1))
call assert_equal(0, setbufline(b, 4, ['d', 'e']))
call assert_equal(['c'], b->getbufline(3))
call assert_equal(['d'], getbufline(b, 4))
@@ -187,4 +187,24 @@ func Test_deletebufline_select_mode()
bwipe!
endfunc
+func Test_setbufline_startup_nofile()
+ let before =<< trim [CODE]
+ set shortmess+=F
+ file Xresult
+ set buftype=nofile
+ call setbufline('', 1, 'success')
+ [CODE]
+ let after =<< trim [CODE]
+ set buftype=
+ write
+ quit
+ [CODE]
+
+ if !RunVim(before, after, '--clean')
+ return
+ endif
+ call assert_equal(['success'], readfile('Xresult'))
+ call delete('Xresult')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_cd.vim b/src/nvim/testdir/test_cd.vim
index a1e53df774..d6d44d1901 100644
--- a/src/nvim/testdir/test_cd.vim
+++ b/src/nvim/testdir/test_cd.vim
@@ -113,7 +113,7 @@ func Test_chdir_func()
call assert_equal('z', fnamemodify(3->getcwd(2), ':t'))
tabnext | wincmd t
call assert_match('^\[tabpage\] .*/y$', trim(execute('verbose pwd')))
- call chdir('..')
+ eval '..'->chdir()
call assert_equal('Xdir', fnamemodify(getcwd(1, 2), ':t'))
call assert_equal('Xdir', fnamemodify(getcwd(2, 2), ':t'))
call assert_equal('z', fnamemodify(getcwd(3, 2), ':t'))
diff --git a/src/nvim/testdir/test_clientserver.vim b/src/nvim/testdir/test_clientserver.vim
index 370d0cb190..66ee776a90 100644
--- a/src/nvim/testdir/test_clientserver.vim
+++ b/src/nvim/testdir/test_clientserver.vim
@@ -2,6 +2,11 @@
source check.vim
CheckFeature job
+
+if !has('clientserver')
+ call assert_fails('call remote_startserver("local")', 'E942:')
+endif
+
CheckFeature clientserver
source shared.vim
@@ -179,6 +184,7 @@ func Test_client_server()
call assert_fails("let x = remote_peek([])", 'E730:')
call assert_fails("let x = remote_read('vim10')", 'E277:')
+ call assert_fails("call server2client('abc', 'xyz')", 'E258:')
endfunc
" Uncomment this line to get a debugging log
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index 72d2dc9cbb..4bfd22cb6c 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -3,6 +3,7 @@
source check.vim
source screendump.vim
source view_util.vim
+source shared.vim
func Test_complete_tab()
call writefile(['testfile'], 'Xtestfile')
@@ -243,7 +244,7 @@ func Test_match_completion()
return
endif
hi Aardig ctermfg=green
- call feedkeys(":match \<Tab>\<Home>\"\<CR>", 'xt')
+ call feedkeys(":match A\<Tab>\<Home>\"\<CR>", 'xt')
call assert_equal('"match Aardig', getreg(':'))
call feedkeys(":match \<S-Tab>\<Home>\"\<CR>", 'xt')
call assert_equal('"match none', getreg(':'))
@@ -254,9 +255,7 @@ func Test_highlight_completion()
return
endif
hi Aardig ctermfg=green
- call feedkeys(":hi \<Tab>\<Home>\"\<CR>", 'xt')
- call assert_equal('"hi Aardig', getreg(':'))
- call feedkeys(":hi default \<Tab>\<Home>\"\<CR>", 'xt')
+ call feedkeys(":hi default A\<Tab>\<Home>\"\<CR>", 'xt')
call assert_equal('"hi default Aardig', getreg(':'))
call feedkeys(":hi clear Aa\<Tab>\<Home>\"\<CR>", 'xt')
call assert_equal('"hi clear Aardig', getreg(':'))
@@ -514,6 +513,7 @@ func Test_getcompletion()
call delete('Xtags')
set tags&
+ call assert_fails("call getcompletion('\\\\@!\\\\@=', 'buffer')", 'E871:')
call assert_fails('call getcompletion("", "burp")', 'E475:')
call assert_fails('call getcompletion("abc", [])', 'E475:')
endfunc
@@ -1260,6 +1260,16 @@ func Test_cmdline_overstrike()
let &encoding = encoding_save
endfunc
+func Test_cmdwin_bug()
+ let winid = win_getid()
+ sp
+ try
+ call feedkeys("q::call win_gotoid(" .. winid .. ")\<CR>:q\<CR>", 'x!')
+ catch /^Vim\%((\a\+)\)\=:E11/
+ endtry
+ bw!
+endfunc
+
func Test_cmdwin_restore()
CheckScreendump
@@ -1452,6 +1462,32 @@ func Test_cmdwin_tabpage()
tabclose!
endfunc
+func Test_cmdwin_interrupted()
+ CheckScreendump
+
+ " aborting the :smile output caused the cmdline window to use the current
+ " buffer.
+ let lines =<< trim [SCRIPT]
+ au WinNew * smile
+ [SCRIPT]
+ call writefile(lines, 'XTest_cmdwin')
+
+ let buf = RunVimInTerminal('-S XTest_cmdwin', {'rows': 18})
+ " open cmdwin
+ call term_sendkeys(buf, "q:")
+ call WaitForAssert({-> assert_match('-- More --', term_getline(buf, 18))})
+ " quit more prompt for :smile command
+ call term_sendkeys(buf, "q")
+ call WaitForAssert({-> assert_match('^$', term_getline(buf, 18))})
+ " execute a simple command
+ call term_sendkeys(buf, "aecho 'done'\<CR>")
+ call VerifyScreenDump(buf, 'Test_cmdwin_interrupted', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+ call delete('XTest_cmdwin')
+endfunc
+
" Test for backtick expression in the command line
func Test_cmd_backtick()
CheckNotMSWindows " FIXME: see #19297
@@ -2159,4 +2195,57 @@ func Test_wildmenu_pum_disable_while_shown()
set wildoptions& wildmenu&
endfunc
+func Test_setcmdline()
+ func SetText(text, pos)
+ autocmd CmdlineChanged * let g:cmdtype = expand('<afile>')
+ call assert_equal(0, setcmdline(a:text))
+ call assert_equal(a:text, getcmdline())
+ call assert_equal(len(a:text) + 1, getcmdpos())
+ call assert_equal(getcmdtype(), g:cmdtype)
+ unlet g:cmdtype
+ autocmd! CmdlineChanged
+
+ call assert_equal(0, setcmdline(a:text, a:pos))
+ call assert_equal(a:text, getcmdline())
+ call assert_equal(a:pos, getcmdpos())
+
+ call assert_fails('call setcmdline("' .. a:text .. '", -1)', 'E487:')
+ call assert_fails('call setcmdline({}, 0)', 'E928:')
+ call assert_fails('call setcmdline("' .. a:text .. '", {})', 'E728:')
+
+ return ''
+ endfunc
+
+ call feedkeys(":\<C-R>=SetText('set rtp?', 2)\<CR>\<CR>", 'xt')
+ call assert_equal('set rtp?', @:)
+
+ call feedkeys(":let g:str = input('? ')\<CR>", 't')
+ call feedkeys("\<C-R>=SetText('foo', 4)\<CR>\<CR>", 'xt')
+ call assert_equal('foo', g:str)
+ unlet g:str
+
+ delfunc SetText
+
+ " setcmdline() returns 1 when not editing the command line.
+ call assert_equal(1, 'foo'->setcmdline())
+
+ " Called in custom function
+ func CustomComplete(A, L, P)
+ call assert_equal(0, setcmdline("DoCmd "))
+ return "January\nFebruary\nMars\n"
+ endfunc
+
+ com! -nargs=* -complete=custom,CustomComplete DoCmd :
+ call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"DoCmd January February Mars', @:)
+ delcom DoCmd
+ delfunc CustomComplete
+
+ " Called in <expr>
+ cnoremap <expr>a setcmdline('let foo=')
+ call feedkeys(":a\<CR>", 'tx')
+ call assert_equal('let foo=0', @:)
+ cunmap a
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_comments.vim b/src/nvim/testdir/test_comments.vim
new file mode 100644
index 0000000000..c34b85c42d
--- /dev/null
+++ b/src/nvim/testdir/test_comments.vim
@@ -0,0 +1,277 @@
+" Tests for the various flags in the 'comments' option
+
+" Test for the 'n' flag in 'comments'
+func Test_comment_nested()
+ new
+ setlocal comments=n:> fo+=ro
+ exe "normal i> B\nD\<C-C>ggOA\<C-C>joC\<C-C>Go\<BS>>>> F\nH"
+ exe "normal 5GOE\<C-C>6GoG"
+ let expected =<< trim END
+ > A
+ > B
+ > C
+ > D
+ >>>> E
+ >>>> F
+ >>>> G
+ >>>> H
+ END
+ call assert_equal(expected, getline(1, '$'))
+ close!
+endfunc
+
+" Test for the 'b' flag in 'comments'
+func Test_comment_blank()
+ new
+ setlocal comments=b:* fo+=ro
+ exe "normal i* E\nF\n\<BS>G\nH\<C-C>ggOC\<C-C>O\<BS>B\<C-C>OA\<C-C>2joD"
+ let expected =<< trim END
+ A
+ *B
+ * C
+ * D
+ * E
+ * F
+ *G
+ H
+ END
+ call assert_equal(expected, getline(1, '$'))
+ close!
+endfunc
+
+" Test for the 'f' flag in 'comments' (only the first line has a comment
+" string)
+func Test_comment_firstline()
+ new
+ setlocal comments=f:- fo+=ro
+ exe "normal i- B\nD\<C-C>ggoC\<C-C>ggOA\<C-C>"
+ call assert_equal(['A', '- B', ' C', ' D'], getline(1, '$'))
+ %d
+ setlocal comments=:-
+ exe "normal i- B\nD\<C-C>ggoC\<C-C>ggOA\<C-C>"
+ call assert_equal(['- A', '- B', '- C', '- D'], getline(1, '$'))
+ close!
+endfunc
+
+" Test for the 's', 'm' and 'e' flags in 'comments'
+" Test for automatically adding comment leaders in insert mode
+func Test_comment_threepiece()
+ new
+ setlocal expandtab
+ call setline(1, ["\t/*"])
+ setlocal formatoptions=croql
+ call cursor(1, 3)
+ call feedkeys("A\<cr>\<cr>/", 'tnix')
+ call assert_equal(["\t/*", " *", " */"], getline(1, '$'))
+
+ " If a comment ends in a single line, then don't add it in the next line
+ %d
+ call setline(1, '/* line1 */')
+ call feedkeys("A\<CR>next line", 'xt')
+ call assert_equal(['/* line1 */', 'next line'], getline(1, '$'))
+
+ %d
+ " Copy the trailing indentation from the leader comment to a new line
+ setlocal autoindent noexpandtab
+ call feedkeys("a\t/*\tone\ntwo\n/", 'xt')
+ call assert_equal(["\t/*\tone", "\t *\ttwo", "\t */"], getline(1, '$'))
+ close!
+endfunc
+
+" Test for the 'r' flag in 'comments' (right align comment)
+func Test_comment_rightalign()
+ new
+ setlocal comments=sr:/***,m:**,ex-2:******/ fo+=ro
+ exe "normal i=\<C-C>o\t /***\nD\n/"
+ exe "normal 2GOA\<C-C>joB\<C-C>jOC\<C-C>joE\<C-C>GOF\<C-C>joG"
+ let expected =<< trim END
+ =
+ A
+ /***
+ ** B
+ ** C
+ ** D
+ ** E
+ ** F
+ ******/
+ G
+ END
+ call assert_equal(expected, getline(1, '$'))
+ close!
+endfunc
+
+" Test for the 'O' flag in 'comments'
+func Test_comment_O()
+ new
+ setlocal comments=Ob:* fo+=ro
+ exe "normal i* B\nD\<C-C>kOA\<C-C>joC"
+ let expected =<< trim END
+ A
+ * B
+ * C
+ * D
+ END
+ call assert_equal(expected, getline(1, '$'))
+ close!
+endfunc
+
+" Test for using a multibyte character as a comment leader
+func Test_comment_multibyte_leader()
+ new
+ let t =<< trim END
+ {
+ X
+ Xa
+ XaY
+ XY
+ XYZ
+ X Y
+ X YZ
+ XX
+ XXa
+ XXY
+ }
+ END
+ call setline(1, t)
+ call cursor(2, 1)
+
+ set tw=2 fo=cqm comments=n:X
+ exe "normal gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgq"
+ let t =<< trim END
+ X
+ Xa
+ XaY
+ XY
+ XYZ
+ X Y
+ X YZ
+ XX
+ XXa
+ XXY
+ END
+ exe "normal o\n" . join(t, "\n")
+
+ let expected =<< trim END
+ {
+ X
+ Xa
+ Xa
+ XY
+ XY
+ XY
+ XZ
+ X Y
+ X Y
+ X Z
+ XX
+ XXa
+ XXY
+
+ X
+ Xa
+ Xa
+ XY
+ XY
+ XY
+ XZ
+ X Y
+ X Y
+ X Z
+ XX
+ XXa
+ XXY
+ }
+ END
+ call assert_equal(expected, getline(1, '$'))
+
+ set tw& fo& comments&
+ close!
+endfunc
+
+" Test for a space character in 'comments' setting
+func Test_comment_space()
+ new
+ setlocal comments=b:\ > fo+=ro
+ exe "normal i> B\nD\<C-C>ggOA\<C-C>joC"
+ exe "normal Go > F\nH\<C-C>kOE\<C-C>joG"
+ let expected =<< trim END
+ A
+ > B
+ C
+ D
+ > E
+ > F
+ > G
+ > H
+ END
+ call assert_equal(expected, getline(1, '$'))
+ close!
+endfunc
+
+" Test for formatting lines with and without comments
+func Test_comment_format_lines()
+ new
+ call setline(1, ['one', '/* two */', 'three'])
+ normal gggqG
+ call assert_equal(['one', '/* two */', 'three'], getline(1, '$'))
+ close!
+endfunc
+
+" Test for using 'a' in 'formatoptions' with comments
+func Test_comment_autoformat()
+ new
+ setlocal formatoptions+=a
+ call feedkeys("a- one\n- two\n", 'xt')
+ call assert_equal(['- one', '- two', ''], getline(1, '$'))
+
+ %d
+ call feedkeys("a\none\n", 'xt')
+ call assert_equal(['', 'one', ''], getline(1, '$'))
+
+ setlocal formatoptions+=aw
+ %d
+ call feedkeys("aone \ntwo\n", 'xt')
+ call assert_equal(['one two', ''], getline(1, '$'))
+
+ %d
+ call feedkeys("aone\ntwo\n", 'xt')
+ call assert_equal(['one', 'two', ''], getline(1, '$'))
+
+ close!
+endfunc
+
+" Test for joining lines with comments ('j' flag in 'formatoptions')
+func Test_comment_join_lines_fo_j()
+ new
+ setlocal fo+=j comments=://
+ call setline(1, ['i++; // comment1', ' // comment2'])
+ normal J
+ call assert_equal('i++; // comment1 comment2', getline(1))
+ setlocal fo-=j
+ call setline(1, ['i++; // comment1', ' // comment2'])
+ normal J
+ call assert_equal('i++; // comment1 // comment2', getline(1))
+ " Test with nested comments
+ setlocal fo+=j comments=n:>,n:)
+ call setline(1, ['i++; > ) > ) comment1', ' > ) comment2'])
+ normal J
+ call assert_equal('i++; > ) > ) comment1 comment2', getline(1))
+ close!
+endfunc
+
+" Test for formatting lines where only the first line has a comment.
+func Test_comment_format_firstline_comment()
+ new
+ setlocal formatoptions=tcq
+ call setline(1, ['- one two', 'three'])
+ normal gggqG
+ call assert_equal(['- one two three'], getline(1, '$'))
+
+ %d
+ call setline(1, ['- one', '- two'])
+ normal gggqG
+ call assert_equal(['- one', '- two'], getline(1, '$'))
+ close!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_cursor_func.vim b/src/nvim/testdir/test_cursor_func.vim
index 3b8a5f27ad..f13842edc8 100644
--- a/src/nvim/testdir/test_cursor_func.vim
+++ b/src/nvim/testdir/test_cursor_func.vim
@@ -22,7 +22,7 @@ func Test_move_cursor()
call cursor(3, 0)
call assert_equal([3, 1, 0, 1], getcurpos()[1:])
" below last line goes to last line
- call cursor(9, 1)
+ eval [9, 1]->cursor()
call assert_equal([4, 1, 0, 1], getcurpos()[1:])
" pass string arguments
call cursor('3', '3')
diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim
index ea453b7174..1cb71664bd 100644
--- a/src/nvim/testdir/test_diffmode.vim
+++ b/src/nvim/testdir/test_diffmode.vim
@@ -744,17 +744,13 @@ func Test_diff_hlID()
call diff_hlID(-1, 1)->synIDattr("name")->assert_equal("")
- call assert_equal(diff_hlID(1, 1), hlID("DiffChange"))
call diff_hlID(1, 1)->synIDattr("name")->assert_equal("DiffChange")
- call assert_equal(diff_hlID(1, 2), hlID("DiffText"))
call diff_hlID(1, 2)->synIDattr("name")->assert_equal("DiffText")
call diff_hlID(2, 1)->synIDattr("name")->assert_equal("")
- call assert_equal(diff_hlID(3, 1), hlID("DiffAdd"))
call diff_hlID(3, 1)->synIDattr("name")->assert_equal("DiffAdd")
- call diff_hlID(4, 1)->synIDattr("name")->assert_equal("")
+ eval 4->diff_hlID(1)->synIDattr("name")->assert_equal("")
wincmd w
- call assert_equal(diff_hlID(1, 1), hlID("DiffChange"))
call assert_equal(synIDattr(diff_hlID(1, 1), "name"), "DiffChange")
call assert_equal(synIDattr(diff_hlID(2, 1), "name"), "")
call assert_equal(synIDattr(diff_hlID(3, 1), "name"), "")
diff --git a/src/nvim/testdir/test_digraph.vim b/src/nvim/testdir/test_digraph.vim
index acc34e5e7c..f08dff8605 100644
--- a/src/nvim/testdir/test_digraph.vim
+++ b/src/nvim/testdir/test_digraph.vim
@@ -211,6 +211,8 @@ func Test_digraphs()
call Put_Dig("00")
call Put_Dig("el")
call assert_equal(['␀', 'ü', '∞', 'l'], getline(line('.')-3,line('.')))
+ call assert_fails('exe "digraph a\<Esc> 100"', 'E104:')
+ call assert_fails('exe "digraph \<Esc>a 100"', 'E104:')
call assert_fails('digraph xy z', 'E39:')
call assert_fails('digraph x', 'E1214:')
bw!
@@ -491,6 +493,17 @@ func Test_show_digraph_cp1251()
bwipe!
endfunc
+" Test for error in a keymap file
+func Test_loadkeymap_error()
+ if !has('keymap')
+ return
+ endif
+ call assert_fails('loadkeymap', 'E105:')
+ call writefile(['loadkeymap', 'a'], 'Xkeymap')
+ call assert_fails('source Xkeymap', 'E791:')
+ call delete('Xkeymap')
+endfunc
+
" Test for the characters displayed on the screen when entering a digraph
func Test_entering_digraph()
CheckRunVimInTerminal
diff --git a/src/nvim/testdir/test_display.vim b/src/nvim/testdir/test_display.vim
index 6938abbc28..217bb5d781 100644
--- a/src/nvim/testdir/test_display.vim
+++ b/src/nvim/testdir/test_display.vim
@@ -309,6 +309,88 @@ func Test_eob_fillchars()
close
endfunc
+" Test for 'foldopen', 'foldclose' and 'foldsep' in 'fillchars'
+func Test_fold_fillchars()
+ new
+ set fdc=2 foldenable foldmethod=manual
+ call setline(1, ['one', 'two', 'three', 'four', 'five'])
+ 2,4fold
+ " First check for the default setting for a closed fold
+ let lines = ScreenLines([1, 3], 8)
+ let expected = [
+ \ ' one ',
+ \ '+ +-- 3',
+ \ ' five '
+ \ ]
+ call assert_equal(expected, lines)
+ normal 2Gzo
+ " check the characters for an open fold
+ let lines = ScreenLines([1, 5], 8)
+ let expected = [
+ \ ' one ',
+ \ '- two ',
+ \ '| three ',
+ \ '| four ',
+ \ ' five '
+ \ ]
+ call assert_equal(expected, lines)
+
+ " change the setting
+ set fillchars=vert:\|,fold:-,eob:~,foldopen:[,foldclose:],foldsep:-
+
+ " check the characters for an open fold
+ let lines = ScreenLines([1, 5], 8)
+ let expected = [
+ \ ' one ',
+ \ '[ two ',
+ \ '- three ',
+ \ '- four ',
+ \ ' five '
+ \ ]
+ call assert_equal(expected, lines)
+
+ " check the characters for a closed fold
+ normal 2Gzc
+ let lines = ScreenLines([1, 3], 8)
+ let expected = [
+ \ ' one ',
+ \ '] +-- 3',
+ \ ' five '
+ \ ]
+ call assert_equal(expected, lines)
+
+ %bw!
+ set fillchars& fdc& foldmethod& foldenable&
+endfunc
+
+func Test_local_fillchars()
+ CheckScreendump
+
+ let lines =<< trim END
+ call setline(1, ['window 1']->repeat(3))
+ setlocal fillchars=stl:1,stlnc:a,vert:=,eob:x
+ vnew
+ call setline(1, ['window 2']->repeat(3))
+ setlocal fillchars=stl:2,stlnc:b,vert:+,eob:y
+ new
+ wincmd J
+ call setline(1, ['window 3']->repeat(3))
+ setlocal fillchars=stl:3,stlnc:c,vert:<,eob:z
+ vnew
+ call setline(1, ['window 4']->repeat(3))
+ setlocal fillchars=stl:4,stlnc:d,vert:>,eob:o
+ END
+ call writefile(lines, 'Xdisplayfillchars')
+ let buf = RunVimInTerminal('-S Xdisplayfillchars', #{rows: 12})
+ call VerifyScreenDump(buf, 'Test_display_fillchars_1', {})
+
+ call term_sendkeys(buf, ":wincmd k\r")
+ call VerifyScreenDump(buf, 'Test_display_fillchars_2', {})
+
+ call StopVimInTerminal(buf)
+ call delete('Xdisplayfillchars')
+endfunc
+
func Test_display_linebreak_breakat()
new
vert resize 25
diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim
index e26bbdc5be..679b877ef6 100644
--- a/src/nvim/testdir/test_edit.vim
+++ b/src/nvim/testdir/test_edit.vim
@@ -713,23 +713,32 @@ endfunc
func Test_edit_CTRL_N()
" Check keyword completion
- new
- set complete=.
- call setline(1, ['INFER', 'loWER', '', '', ])
- call cursor(3, 1)
- call feedkeys("Ai\<c-n>\<cr>\<esc>", "tnix")
- call feedkeys("ILO\<c-n>\<cr>\<esc>", 'tnix')
- call assert_equal(['INFER', 'loWER', 'i', 'LO', '', ''], getline(1, '$'))
- %d
- call setline(1, ['INFER', 'loWER', '', '', ])
- call cursor(3, 1)
- set ignorecase infercase
- call feedkeys("Ii\<c-n>\<cr>\<esc>", "tnix")
- call feedkeys("ILO\<c-n>\<cr>\<esc>", 'tnix')
- call assert_equal(['INFER', 'loWER', 'infer', 'LOWER', '', ''], getline(1, '$'))
-
- set noignorecase noinfercase complete&
- bw!
+ " for e in ['latin1', 'utf-8']
+ for e in ['utf-8']
+ exe 'set encoding=' .. e
+ new
+ set complete=.
+ call setline(1, ['INFER', 'loWER', '', '', ])
+ call cursor(3, 1)
+ call feedkeys("Ai\<c-n>\<cr>\<esc>", "tnix")
+ call feedkeys("ILO\<c-n>\<cr>\<esc>", 'tnix')
+ call assert_equal(['INFER', 'loWER', 'i', 'LO', '', ''], getline(1, '$'), e)
+ %d
+ call setline(1, ['INFER', 'loWER', '', '', ])
+ call cursor(3, 1)
+ set ignorecase infercase
+ call feedkeys("Ii\<c-n>\<cr>\<esc>", "tnix")
+ call feedkeys("ILO\<c-n>\<cr>\<esc>", 'tnix')
+ call assert_equal(['INFER', 'loWER', 'infer', 'LOWER', '', ''], getline(1, '$'), e)
+ set noignorecase noinfercase
+ %d
+ call setline(1, ['one word', 'two word'])
+ exe "normal! Goo\<C-P>\<C-X>\<C-P>"
+ call assert_equal('one word', getline(3))
+ %d
+ set complete&
+ bw!
+ endfor
endfunc
func Test_edit_CTRL_O()
@@ -893,6 +902,24 @@ func Test_edit_CTRL_T()
bw!
endfunc
+" Test thesaurus completion with different encodings
+func Test_thesaurus_complete_with_encoding()
+ call writefile(['angry furious mad enraged'], 'Xthesaurus')
+ set thesaurus=Xthesaurus
+ " for e in ['latin1', 'utf-8']
+ for e in ['utf-8']
+ exe 'set encoding=' .. e
+ new
+ call setline(1, 'mad')
+ call cursor(1, 1)
+ call feedkeys("A\<c-x>\<c-t>\<cr>\<esc>", 'tnix')
+ call assert_equal(['mad', ''], getline(1, '$'))
+ bw!
+ endfor
+ set thesaurus=
+ call delete('Xthesaurus')
+endfunc
+
" Test 'thesaurusfunc'
func MyThesaurus(findstart, base)
let mythesaurus = [
diff --git a/src/nvim/testdir/test_excmd.vim b/src/nvim/testdir/test_excmd.vim
index dac7a6989d..9a9e5c546b 100644
--- a/src/nvim/testdir/test_excmd.vim
+++ b/src/nvim/testdir/test_excmd.vim
@@ -568,10 +568,12 @@ endfunc
" Test for the :verbose command
func Test_verbose_cmd()
- call assert_equal([' verbose=1'], split(execute('verbose set vbs'), "\n"))
+ set verbose=3
+ call assert_match(' verbose=1\n\s*Last set from ', execute('verbose set vbs'), "\n")
call assert_equal([' verbose=0'], split(execute('0verbose set vbs'), "\n"))
- let l = execute("4verbose set verbose | set verbose")
- call assert_equal([' verbose=4', ' verbose=0'], split(l, "\n"))
+ set verbose=0
+ call assert_match(' verbose=4\n\s*Last set from .*\n verbose=0',
+ \ execute("4verbose set verbose | set verbose"))
endfunc
" Test for the :delete command and the related abbreviated commands
diff --git a/src/nvim/testdir/test_expand.vim b/src/nvim/testdir/test_expand.vim
index ce414e4b11..aa131a49ff 100644
--- a/src/nvim/testdir/test_expand.vim
+++ b/src/nvim/testdir/test_expand.vim
@@ -116,13 +116,21 @@ func Test_source_sfile()
:call assert_equal('edit <cword>', expandcmd("edit <cword>"))
:call assert_equal('edit <cexpr>', expandcmd("edit <cexpr>"))
:call assert_fails('autocmd User MyCmd echo "<sfile>"', 'E498:')
+ :
+ :call assert_equal('', expand('<script>'))
+ :verbose echo expand('<script>')
+ :call add(v:errors, v:errmsg)
+ :verbose echo expand('<sfile>')
+ :call add(v:errors, v:errmsg)
:call writefile(v:errors, 'Xresult')
:qall!
-
[SCRIPT]
call writefile(lines, 'Xscript')
if RunVim([], [], '--clean -s Xscript')
- call assert_equal([], readfile('Xresult'))
+ call assert_equal([
+ \ 'E1274: No script file name to substitute for "<script>"',
+ \ 'E498: no :source file name to substitute for "<sfile>"'],
+ \ readfile('Xresult'))
endif
call delete('Xscript')
call delete('Xresult')
@@ -147,4 +155,63 @@ func Test_expandcmd_shell_nonomatch()
call assert_equal('$*', expandcmd('$*'))
endfunc
+func Test_expand_script_source()
+ let lines0 =<< trim [SCRIPT]
+ call extend(g:script_level, [expand('<script>:t')])
+ so Xscript1
+ func F0()
+ call extend(g:func_level, [expand('<script>:t')])
+ endfunc
+
+ au User * call extend(g:au_level, [expand('<script>:t')])
+ [SCRIPT]
+
+ let lines1 =<< trim [SCRIPT]
+ call extend(g:script_level, [expand('<script>:t')])
+ so Xscript2
+ func F1()
+ call extend(g:func_level, [expand('<script>:t')])
+ endfunc
+
+ au User * call extend(g:au_level, [expand('<script>:t')])
+ [SCRIPT]
+
+ let lines2 =<< trim [SCRIPT]
+ call extend(g:script_level, [expand('<script>:t')])
+ func F2()
+ call extend(g:func_level, [expand('<script>:t')])
+ endfunc
+
+ au User * call extend(g:au_level, [expand('<script>:t')])
+ [SCRIPT]
+
+ call writefile(lines0, 'Xscript0')
+ call writefile(lines1, 'Xscript1')
+ call writefile(lines2, 'Xscript2')
+
+ " Check the expansion of <script> at different levels.
+ let g:script_level = []
+ let g:func_level = []
+ let g:au_level = []
+
+ so Xscript0
+ call F0()
+ call F1()
+ call F2()
+ doautocmd User
+
+ call assert_equal(['Xscript0', 'Xscript1', 'Xscript2'], g:script_level)
+ call assert_equal(['Xscript0', 'Xscript1', 'Xscript2'], g:func_level)
+ call assert_equal(['Xscript2', 'Xscript1', 'Xscript0'], g:au_level)
+
+ unlet g:script_level g:func_level
+ delfunc F0
+ delfunc F1
+ delfunc F2
+
+ call delete('Xscript0')
+ call delete('Xscript1')
+ call delete('Xscript2')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_expand_func.vim b/src/nvim/testdir/test_expand_func.vim
index df01d84f19..80bfdb8553 100644
--- a/src/nvim/testdir/test_expand_func.vim
+++ b/src/nvim/testdir/test_expand_func.vim
@@ -107,10 +107,15 @@ endfunc
func Test_expand()
new
- call assert_equal("", expand('%:S'))
+ call assert_equal("", expand('%:S'))
call assert_equal('3', '<slnum>'->expand())
call assert_equal(['4'], expand('<slnum>', v:false, v:true))
" Don't add any line above this, otherwise <slnum> will change.
+ call assert_equal("", expand('%'))
+ set verbose=1
+ call assert_equal("", expand('%'))
+ set verbose=0
+ call assert_equal("", expand('%:p'))
quit
endfunc
diff --git a/src/nvim/testdir/test_expr.vim b/src/nvim/testdir/test_expr.vim
index 5b10e691e5..15622cd6fe 100644
--- a/src/nvim/testdir/test_expr.vim
+++ b/src/nvim/testdir/test_expr.vim
@@ -547,6 +547,7 @@ func Test_funcref()
call assert_fails('echo funcref("{")', 'E475:')
let OneByRef = funcref("One", repeat(["foo"], 20))
call assert_fails('let OneByRef = funcref("One", repeat(["foo"], 21))', 'E118:')
+ call assert_fails('echo function("min") =~ function("min")', 'E694:')
endfunc
func Test_setmatches()
diff --git a/src/nvim/testdir/test_filechanged.vim b/src/nvim/testdir/test_filechanged.vim
index b77f02afd1..fef0eb732f 100644
--- a/src/nvim/testdir/test_filechanged.vim
+++ b/src/nvim/testdir/test_filechanged.vim
@@ -140,7 +140,8 @@ func Test_FileChangedShell_edit()
endfunc
func Test_FileChangedShell_edit_dialog()
- throw 'Skipped: requires a UI to be active'
+ " requires a UI to be active
+ throw 'Skipped: use test/functional/legacy/filechanged_spec.lua'
CheckNotGui
CheckUnix " Using low level feedkeys() does not work on MS-Windows.
@@ -190,7 +191,8 @@ func Test_FileChangedShell_edit_dialog()
endfunc
func Test_file_changed_dialog()
- throw 'Skipped: requires a UI to be active'
+ " requires a UI to be active
+ throw 'Skipped: use test/functional/legacy/filechanged_spec.lua'
CheckUnix
CheckNotGui
au! FileChangedShell
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index e3a8370661..68ce9148a4 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -209,6 +209,7 @@ let s:filename_checks = {
\ 'gdmo': ['file.mo', 'file.gdmo'],
\ 'gdresource': ['file.tscn', 'file.tres'],
\ 'gdscript': ['file.gd'],
+ \ 'gdshader': ['file.gdshader', 'file.shader'],
\ 'gedcom': ['file.ged', 'lltxxxxx.txt', '/tmp/lltmp', '/tmp/lltmp-file', 'any/tmp/lltmp', 'any/tmp/lltmp-file'],
\ 'gemtext': ['file.gmi', 'file.gemini'],
\ 'gift': ['file.gift'],
@@ -588,6 +589,9 @@ let s:filename_checks = {
\ 'usw2kagtlog': ['usw2kagt.log', 'USW2KAGT.LOG', 'usw2kagt.file.log', 'USW2KAGT.FILE.LOG', 'file.usw2kagt.log', 'FILE.USW2KAGT.LOG'],
\ 'vala': ['file.vala'],
\ 'vb': ['file.sba', 'file.vb', 'file.vbs', 'file.dsm', 'file.ctl'],
+ \ 'vdmpp': ['file.vpp', 'file.vdmpp'],
+ \ 'vdmrt': ['file.vdmrt'],
+ \ 'vdmsl': ['file.vdm', 'file.vdmsl'],
\ 'vera': ['file.vr', 'file.vri', 'file.vrh'],
\ 'verilog': ['file.v'],
\ 'verilogams': ['file.va', 'file.vams'],
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index 44b6f0373e..147eda5b0a 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -1420,12 +1420,15 @@ func Test_trim()
call assert_equal("vim", trim(" vim ", " ", 0))
call assert_equal("vim ", trim(" vim ", " ", 1))
call assert_equal(" vim", trim(" vim ", " ", 2))
- call assert_fails('call trim(" vim ", " ", [])', 'E745:')
- call assert_fails('call trim(" vim ", " ", -1)', 'E475:')
- call assert_fails('call trim(" vim ", " ", 3)', 'E475:')
+ call assert_fails('eval trim(" vim ", " ", [])', 'E745:')
+ call assert_fails('eval trim(" vim ", " ", -1)', 'E475:')
+ call assert_fails('eval trim(" vim ", " ", 3)', 'E475:')
+ call assert_fails('eval trim(" vim ", 0)', 'E475:')
let chars = join(map(range(1, 0x20) + [0xa0], {n -> n->nr2char()}), '')
call assert_equal("x", trim(chars . "x" . chars))
+
+ call assert_fails('let c=trim([])', 'E730:')
endfunc
" Test for reg_recording() and reg_executing()
@@ -1697,6 +1700,63 @@ func Test_platform_name()
endif
endfunc
+" Test confirm({msg} [, {choices} [, {default} [, {type}]]])
+func Test_confirm()
+ " requires a UI to be active
+ throw 'Skipped: use test/functional/vimscript/input_spec.lua'
+ if !has('unix') || has('gui_running')
+ return
+ endif
+
+ call feedkeys('o', 'L')
+ let a = confirm('Press O to proceed')
+ call assert_equal(1, a)
+
+ call feedkeys('y', 'L')
+ let a = 'Are you sure?'->confirm("&Yes\n&No")
+ call assert_equal(1, a)
+
+ call feedkeys('n', 'L')
+ let a = confirm('Are you sure?', "&Yes\n&No")
+ call assert_equal(2, a)
+
+ " confirm() should return 0 when pressing CTRL-C.
+ call feedkeys("\<C-c>", 'L')
+ let a = confirm('Are you sure?', "&Yes\n&No")
+ call assert_equal(0, a)
+
+ " <Esc> requires another character to avoid it being seen as the start of an
+ " escape sequence. Zero should be harmless.
+ eval "\<Esc>0"->feedkeys('L')
+ let a = confirm('Are you sure?', "&Yes\n&No")
+ call assert_equal(0, a)
+
+ " Default choice is returned when pressing <CR>.
+ call feedkeys("\<CR>", 'L')
+ let a = confirm('Are you sure?', "&Yes\n&No")
+ call assert_equal(1, a)
+
+ call feedkeys("\<CR>", 'L')
+ let a = confirm('Are you sure?', "&Yes\n&No", 2)
+ call assert_equal(2, a)
+
+ call feedkeys("\<CR>", 'L')
+ let a = confirm('Are you sure?', "&Yes\n&No", 0)
+ call assert_equal(0, a)
+
+ " Test with the {type} 4th argument
+ for type in ['Error', 'Question', 'Info', 'Warning', 'Generic']
+ call feedkeys('y', 'L')
+ let a = confirm('Are you sure?', "&Yes\n&No\n", 1, type)
+ call assert_equal(1, a)
+ endfor
+
+ call assert_fails('call confirm([])', 'E730:')
+ call assert_fails('call confirm("Are you sure?", [])', 'E730:')
+ call assert_fails('call confirm("Are you sure?", "&Yes\n&No\n", [])', 'E745:')
+ call assert_fails('call confirm("Are you sure?", "&Yes\n&No\n", 0, [])', 'E730:')
+endfunc
+
func Test_readdir()
call mkdir('Xdir')
call writefile([], 'Xdir/foo.txt')
@@ -1724,7 +1784,7 @@ func Test_readdir()
let files = readdir('Xdir', {x -> len(add(l, x)) == 2 ? -1 : 1})
call assert_equal(1, len(files))
- call delete('Xdir', 'rf')
+ eval 'Xdir'->delete('rf')
endfunc
func Test_delete_rf()
@@ -1767,6 +1827,7 @@ endfunc
func Test_char2nr()
call assert_equal(12354, char2nr('あ', 1))
+ call assert_equal(120, 'x'->char2nr())
endfunc
func Test_charclass()
@@ -1819,6 +1880,22 @@ func Test_bufadd_bufload()
exe 'bwipe ' .. buf2
call assert_equal(0, bufexists(buf2))
+ " When 'buftype' is "nofile" then bufload() does not read the file.
+ " Other values too.
+ for val in [['nofile', 0],
+ \ ['nowrite', 1],
+ \ ['acwrite', 1],
+ \ ['quickfix', 0],
+ \ ['help', 1],
+ \ ['prompt', 0],
+ \ ]
+ bwipe! XotherName
+ let buf = bufadd('XotherName')
+ call setbufvar(buf, '&bt', val[0])
+ call bufload(buf)
+ call assert_equal(val[1] ? ['some', 'text'] : [''], getbufline(buf, 1, '$'), val[0])
+ endfor
+
bwipe someName
bwipe XotherName
call assert_equal(0, bufexists('someName'))
diff --git a/src/nvim/testdir/test_highlight.vim b/src/nvim/testdir/test_highlight.vim
index efdf44a0d6..8e808a00d0 100644
--- a/src/nvim/testdir/test_highlight.vim
+++ b/src/nvim/testdir/test_highlight.vim
@@ -731,7 +731,8 @@ func Test_1_highlight_Normalgroup_exists()
endif
endfunc
-function Test_no_space_before_xxx()
+" Do this test last, sometimes restoring the columns doesn't work
+func Test_z_no_space_before_xxx()
" Note: we need to create this highlight group in the test because it does not exist in Neovim
execute('hi StatusLineTermNC ctermfg=green')
let l:org_columns = &columns
@@ -739,7 +740,7 @@ function Test_no_space_before_xxx()
let l:hi_StatusLineTermNC = join(split(execute('hi StatusLineTermNC')))
call assert_match('StatusLineTermNC xxx', l:hi_StatusLineTermNC)
let &columns = l:org_columns
-endfunction
+endfunc
" Test for :highlight command errors
func Test_highlight_cmd_errors()
diff --git a/src/nvim/testdir/test_history.vim b/src/nvim/testdir/test_history.vim
index feb521e232..f1c31dee04 100644
--- a/src/nvim/testdir/test_history.vim
+++ b/src/nvim/testdir/test_history.vim
@@ -95,6 +95,23 @@ function Test_History()
call assert_fails('call histnr([])', 'E730:')
call assert_fails('history xyz', 'E488:')
call assert_fails('history ,abc', 'E488:')
+ call assert_fails('call histdel(":", "\\%(")', 'E53:')
+endfunction
+
+function Test_history_truncates_long_entry()
+ " History entry short enough to fit on the screen should not be truncated.
+ call histadd(':', 'echo x' .. repeat('y', &columns - 17) .. 'z')
+ let a = execute('history : -1')
+
+ call assert_match("^\n # cmd history\n"
+ \ .. "> *\\d\\+ echo x" .. repeat('y', &columns - 17) .. 'z$', a)
+
+ " Long history entry should be truncated to fit on the screen, with, '...'
+ " inserted in the string to indicate the that there is truncation.
+ call histadd(':', 'echo x' .. repeat('y', &columns - 16) .. 'z')
+ let a = execute('history : -1')
+ call assert_match("^\n # cmd history\n"
+ \ .. "> *\\d\\+ echo xy\\+\.\.\.y\\+z$", a)
endfunction
function Test_Search_history_window()
diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim
index 179218e48a..3e563f29f9 100644
--- a/src/nvim/testdir/test_ins_complete.vim
+++ b/src/nvim/testdir/test_ins_complete.vim
@@ -44,11 +44,11 @@ func Test_ins_complete()
exe "normal o\<C-X>\<C-P>\<C-P>\<C-X>\<C-X>\<C-N>\<C-X>\<C-N>\<C-N>"
call assert_equal('run1 run2', getline('.'))
- set cpt=.,w,i
+ set cpt=.,\ ,w,i
" i-add-expands and switches to local
exe "normal OM\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>\<C-X>\<C-X>\<C-X>\<C-P>"
call assert_equal("Makefile\tto\trun3", getline('.'))
- " add-expands lines (it would end in an empty line if it didn't ignored
+ " add-expands lines (it would end in an empty line if it didn't ignore
" itself)
exe "normal o\<C-X>\<C-L>\<C-X>\<C-L>\<C-P>\<C-P>"
call assert_equal("Makefile\tto\trun3", getline('.'))
@@ -68,6 +68,11 @@ func Test_ins_complete()
call assert_equal('Xtest11.one', getline('.'))
normal ddk
+ " Test for expanding a non-existing filename
+ exe "normal oa1b2X3Y4\<C-X>\<C-F>"
+ call assert_equal('a1b2X3Y4', getline('.'))
+ normal ddk
+
set cpt=w
" checks make_cyclic in other window
exe "normal oST\<C-N>\<C-P>\<C-P>\<C-P>\<C-P>"
@@ -682,6 +687,21 @@ func Test_complete_func_error()
call assert_equal([], complete_info(['items']).items)
endfunc
+" Test for recursively starting completion mode using complete()
+func Test_recursive_complete_func()
+ func ListColors()
+ call complete(5, ["red", "blue"])
+ return ''
+ endfunc
+ new
+ call setline(1, ['a1', 'a2'])
+ set complete=.
+ exe "normal Goa\<C-X>\<C-L>\<C-R>=ListColors()\<CR>\<C-N>"
+ call assert_equal('a2blue', getline(3))
+ delfunc ListColors
+ bw!
+endfunc
+
" Test for completing words following a completed word in a line
func Test_complete_wrapscan()
" complete words from another buffer
@@ -721,6 +741,17 @@ func Test_complete_across_line()
close!
endfunc
+" Test for completing words with a '.' at the end of a word.
+func Test_complete_joinspaces()
+ new
+ call setline(1, ['one two.', 'three. four'])
+ set joinspaces
+ exe "normal Goon\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>"
+ call assert_equal("one two. three. four", getline(3))
+ set joinspaces&
+ bw!
+endfunc
+
" Test for using CTRL-L to add one character when completing matching
func Test_complete_add_onechar()
new
@@ -741,6 +772,39 @@ func Test_complete_add_onechar()
close!
endfunc
+" Test for using CTRL-X CTRL-L to complete whole lines lines
+func Test_complete_wholeline()
+ new
+ " complete one-line
+ call setline(1, ['a1', 'a2'])
+ exe "normal ggoa\<C-X>\<C-L>"
+ call assert_equal(['a1', 'a1', 'a2'], getline(1, '$'))
+ " go to the next match (wrapping around the buffer)
+ exe "normal 2GCa\<C-X>\<C-L>\<C-N>"
+ call assert_equal(['a1', 'a', 'a2'], getline(1, '$'))
+ " go to the next match
+ exe "normal 2GCa\<C-X>\<C-L>\<C-N>\<C-N>"
+ call assert_equal(['a1', 'a2', 'a2'], getline(1, '$'))
+ exe "normal 2GCa\<C-X>\<C-L>\<C-N>\<C-N>\<C-N>"
+ call assert_equal(['a1', 'a1', 'a2'], getline(1, '$'))
+ " repeat the test using CTRL-L
+ " go to the next match (wrapping around the buffer)
+ exe "normal 2GCa\<C-X>\<C-L>\<C-L>"
+ call assert_equal(['a1', 'a2', 'a2'], getline(1, '$'))
+ " go to the next match
+ exe "normal 2GCa\<C-X>\<C-L>\<C-L>\<C-L>"
+ call assert_equal(['a1', 'a', 'a2'], getline(1, '$'))
+ exe "normal 2GCa\<C-X>\<C-L>\<C-L>\<C-L>\<C-L>"
+ call assert_equal(['a1', 'a1', 'a2'], getline(1, '$'))
+ %d
+ " use CTRL-X CTRL-L to add one more line
+ call setline(1, ['a1', 'b1'])
+ setlocal complete=.
+ exe "normal ggOa\<C-X>\<C-L>\<C-X>\<C-L>\<C-X>\<C-L>"
+ call assert_equal(['a1', 'b1', '', 'a1', 'b1'], getline(1, '$'))
+ bw!
+endfunc
+
" Test insert completion with 'cindent' (adjust the indent)
func Test_complete_with_cindent()
new
@@ -829,6 +893,25 @@ func Test_complete_stop()
close!
endfunc
+" Test for typing CTRL-R in insert completion mode to insert a register
+" content.
+func Test_complete_reginsert()
+ new
+ call setline(1, ['a1', 'a12', 'a123', 'a1234'])
+
+ " if a valid CTRL-X mode key is returned from <C-R>=, then it should be
+ " processed. Otherwise, CTRL-X mode should be stopped and the key should be
+ " inserted.
+ exe "normal Goa\<C-P>\<C-R>=\"\\<C-P>\"\<CR>"
+ call assert_equal('a123', getline(5))
+ let @r = "\<C-P>\<C-P>"
+ exe "normal GCa\<C-P>\<C-R>r"
+ call assert_equal('a12', getline(5))
+ exe "normal GCa\<C-P>\<C-R>=\"x\"\<CR>"
+ call assert_equal('a1234x', getline(5))
+ bw!
+endfunc
+
func Test_issue_7021()
CheckMSWindows
@@ -842,6 +925,322 @@ func Test_issue_7021()
set completeslash=
endfunc
+" Test for 'longest' setting in 'completeopt' with latin1 and utf-8 encodings
+func Test_complete_longest_match()
+ " for e in ['latin1', 'utf-8']
+ for e in ['utf-8']
+ exe 'set encoding=' .. e
+ new
+ set complete=.
+ set completeopt=menu,longest
+ call setline(1, ['pfx_a1', 'pfx_a12', 'pfx_a123', 'pfx_b1'])
+ exe "normal Gopfx\<C-P>"
+ call assert_equal('pfx_', getline(5))
+ bw!
+ endfor
+
+ " Test for completing additional words with longest match set
+ new
+ call setline(1, ['abc1', 'abd2'])
+ exe "normal Goab\<C-P>\<C-X>\<C-P>"
+ call assert_equal('ab', getline(3))
+ bw!
+ set complete& completeopt&
+endfunc
+
+" Test for removing the first displayed completion match and selecting the
+" match just before that.
+func Test_complete_erase_firstmatch()
+ new
+ call setline(1, ['a12', 'a34', 'a56'])
+ set complete=.
+ exe "normal Goa\<C-P>\<BS>\<BS>3\<CR>"
+ call assert_equal('a34', getline('$'))
+ set complete&
+ bw!
+endfunc
+
+" Test for completing words from unloaded buffers
+func Test_complete_from_unloadedbuf()
+ call writefile(['abc'], "Xfile1")
+ call writefile(['def'], "Xfile2")
+ edit Xfile1
+ edit Xfile2
+ new | close
+ enew
+ bunload Xfile1 Xfile2
+ set complete=u
+ " complete from an unloaded buffer
+ exe "normal! ia\<C-P>"
+ call assert_equal('abc', getline(1))
+ exe "normal! od\<C-P>"
+ call assert_equal('def', getline(2))
+ set complete&
+ %bw!
+ call delete("Xfile1")
+ call delete("Xfile2")
+endfunc
+
+" Test for completing whole lines from unloaded buffers
+func Test_complete_wholeline_unloadedbuf()
+ call writefile(['a line1', 'a line2', 'a line3'], "Xfile1")
+ edit Xfile1
+ enew
+ set complete=u
+ exe "normal! ia\<C-X>\<C-L>\<C-P>"
+ call assert_equal('a line2', getline(1))
+ %d
+ " completing from an unlisted buffer should fail
+ bdel Xfile1
+ exe "normal! ia\<C-X>\<C-L>\<C-P>"
+ call assert_equal('a', getline(1))
+ set complete&
+ %bw!
+ call delete("Xfile1")
+endfunc
+
+" Test for completing words from unlisted buffers
+func Test_complete_from_unlistedbuf()
+ call writefile(['abc'], "Xfile1")
+ call writefile(['def'], "Xfile2")
+ edit Xfile1
+ edit Xfile2
+ new | close
+ bdel Xfile1 Xfile2
+ set complete=U
+ " complete from an unlisted buffer
+ exe "normal! ia\<C-P>"
+ call assert_equal('abc', getline(1))
+ exe "normal! od\<C-P>"
+ call assert_equal('def', getline(2))
+ set complete&
+ %bw!
+ call delete("Xfile1")
+ call delete("Xfile2")
+endfunc
+
+" Test for completing whole lines from unlisted buffers
+func Test_complete_wholeline_unlistedbuf()
+ call writefile(['a line1', 'a line2', 'a line3'], "Xfile1")
+ edit Xfile1
+ enew
+ set complete=U
+ " completing from a unloaded buffer should fail
+ exe "normal! ia\<C-X>\<C-L>\<C-P>"
+ call assert_equal('a', getline(1))
+ %d
+ bdel Xfile1
+ exe "normal! ia\<C-X>\<C-L>\<C-P>"
+ call assert_equal('a line2', getline(1))
+ set complete&
+ %bw!
+ call delete("Xfile1")
+endfunc
+
+" Test for adding a multibyte character using CTRL-L in completion mode
+func Test_complete_mbyte_char_add()
+ new
+ set complete=.
+ call setline(1, 'abė')
+ exe "normal! oa\<C-P>\<BS>\<BS>\<C-L>\<C-L>"
+ call assert_equal('abė', getline(2))
+ " Test for a leader with multibyte character
+ %d
+ call setline(1, 'abėĕ')
+ exe "normal! oabė\<C-P>"
+ call assert_equal('abėĕ', getline(2))
+ bw!
+endfunc
+
+" Test for using <C-X><C-P> for local expansion even if 'complete' is set to
+" not to complete matches from the local buffer. Also test using multiple
+" <C-X> to cancel the current completion mode.
+func Test_complete_local_expansion()
+ new
+ set complete=t
+ call setline(1, ['abc', 'def'])
+ exe "normal! Go\<C-X>\<C-P>"
+ call assert_equal("def", getline(3))
+ exe "normal! Go\<C-P>"
+ call assert_equal("", getline(4))
+ exe "normal! Go\<C-X>\<C-N>"
+ call assert_equal("abc", getline(5))
+ exe "normal! Go\<C-N>"
+ call assert_equal("", getline(6))
+
+ " use multiple <C-X> to cancel the previous completion mode
+ exe "normal! Go\<C-P>\<C-X>\<C-P>"
+ call assert_equal("", getline(7))
+ exe "normal! Go\<C-P>\<C-X>\<C-X>\<C-P>"
+ call assert_equal("", getline(8))
+ exe "normal! Go\<C-P>\<C-X>\<C-X>\<C-X>\<C-P>"
+ call assert_equal("abc", getline(9))
+
+ " interrupt the current completion mode
+ set completeopt=menu,noinsert
+ exe "normal! Go\<C-X>\<C-F>\<C-X>\<C-X>\<C-P>\<C-Y>"
+ call assert_equal("abc", getline(10))
+
+ " when only one <C-X> is used to interrupt, do normal expansion
+ exe "normal! Go\<C-X>\<C-F>\<C-X>\<C-P>"
+ call assert_equal("", getline(11))
+ set completeopt&
+
+ " using two <C-X> in non-completion mode and restarting the same mode
+ exe "normal! God\<C-X>\<C-X>\<C-P>\<C-X>\<C-X>\<C-P>\<C-Y>"
+ call assert_equal("def", getline(12))
+
+ " test for adding a match from the original empty text
+ %d
+ call setline(1, 'abc def g')
+ exe "normal! o\<C-X>\<C-P>\<C-N>\<C-X>\<C-P>"
+ call assert_equal('def', getline(2))
+ exe "normal! 0C\<C-X>\<C-N>\<C-P>\<C-X>\<C-N>"
+ call assert_equal('abc', getline(2))
+
+ bw!
+endfunc
+
+" Test for undoing changes after a insert-mode completion
+func Test_complete_undo()
+ new
+ set complete=.
+ " undo with 'ignorecase'
+ call setline(1, ['ABOVE', 'BELOW'])
+ set ignorecase
+ exe "normal! Goab\<C-G>u\<C-P>"
+ call assert_equal("ABOVE", getline(3))
+ undo
+ call assert_equal("ab", getline(3))
+ set ignorecase&
+ %d
+ " undo with longest match
+ set completeopt=menu,longest
+ call setline(1, ['above', 'about'])
+ exe "normal! Goa\<C-G>u\<C-P>"
+ call assert_equal("abo", getline(3))
+ undo
+ call assert_equal("a", getline(3))
+ set completeopt&
+ %d
+ " undo for line completion
+ call setline(1, ['above that change', 'below that change'])
+ exe "normal! Goabove\<C-G>u\<C-X>\<C-L>"
+ call assert_equal("above that change", getline(3))
+ undo
+ call assert_equal("above", getline(3))
+
+ bw!
+endfunc
+
+" Test for completing a very long word
+func Test_complete_long_word()
+ set complete&
+ new
+ call setline(1, repeat('x', 950) .. ' one two three')
+ exe "normal! Gox\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>"
+ call assert_equal(repeat('x', 950) .. ' one two three', getline(2))
+ %d
+ " should fail when more than 950 characters are in a word
+ call setline(1, repeat('x', 951) .. ' one two three')
+ exe "normal! Gox\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>"
+ call assert_equal(repeat('x', 951), getline(2))
+
+ " Test for adding a very long word to an existing completion
+ %d
+ call setline(1, ['abc', repeat('x', 1016) .. '012345'])
+ exe "normal! Goab\<C-P>\<C-X>\<C-P>"
+ call assert_equal('abc ' .. repeat('x', 1016) .. '0123', getline(3))
+ bw!
+endfunc
+
+" Test for some fields in the complete items used by complete()
+func Test_complete_items()
+ func CompleteItems(idx)
+ let items = [[#{word: "one", dup: 1, user_data: 'u1'}, #{word: "one", dup: 1, user_data: 'u2'}],
+ \ [#{word: "one", dup: 0, user_data: 'u3'}, #{word: "one", dup: 0, user_data: 'u4'}],
+ \ [#{word: "one", icase: 1, user_data: 'u7'}, #{word: "oNE", icase: 1, user_data: 'u8'}],
+ \ [#{user_data: 'u9'}],
+ \ [#{word: "", user_data: 'u10'}],
+ \ [#{word: "", empty: 1, user_data: 'u11'}]]
+ call complete(col('.'), items[a:idx])
+ return ''
+ endfunc
+ new
+ exe "normal! i\<C-R>=CompleteItems(0)\<CR>\<C-N>\<C-Y>"
+ call assert_equal('u2', v:completed_item.user_data)
+ call assert_equal('one', getline(1))
+ exe "normal! o\<C-R>=CompleteItems(1)\<CR>\<C-Y>"
+ call assert_equal('u3', v:completed_item.user_data)
+ call assert_equal('one', getline(2))
+ exe "normal! o\<C-R>=CompleteItems(1)\<CR>\<C-N>"
+ call assert_equal('', getline(3))
+ set completeopt=menu,noinsert
+ exe "normal! o\<C-R>=CompleteItems(2)\<CR>one\<C-N>\<C-Y>"
+ call assert_equal('oNE', getline(4))
+ call assert_equal('u8', v:completed_item.user_data)
+ set completeopt&
+ exe "normal! o\<C-R>=CompleteItems(3)\<CR>"
+ call assert_equal('', getline(5))
+ exe "normal! o\<C-R>=CompleteItems(4)\<CR>"
+ call assert_equal('', getline(6))
+ exe "normal! o\<C-R>=CompleteItems(5)\<CR>"
+ call assert_equal('', getline(7))
+ call assert_equal('u11', v:completed_item.user_data)
+ " pass invalid argument to complete()
+ let cmd = "normal! o\<C-R>=complete(1, [[]])\<CR>"
+ call assert_fails('exe cmd', 'E730:')
+ bw!
+ delfunc CompleteItems
+endfunc
+
+" Test for the "refresh" item in the dict returned by an insert completion
+" function
+func Test_complete_item_refresh_always()
+ let g:CallCount = 0
+ func! Tcomplete(findstart, base)
+ if a:findstart
+ " locate the start of the word
+ let line = getline('.')
+ let start = col('.') - 1
+ while start > 0 && line[start - 1] =~ '\a'
+ let start -= 1
+ endwhile
+ return start
+ else
+ let g:CallCount += 1
+ let res = ["update1", "update12", "update123"]
+ return #{words: res, refresh: 'always'}
+ endif
+ endfunc
+ new
+ set completeopt=menu,longest
+ set completefunc=Tcomplete
+ exe "normal! iup\<C-X>\<C-U>\<BS>\<BS>\<BS>\<BS>\<BS>"
+ call assert_equal('up', getline(1))
+ call assert_equal(2, g:CallCount)
+ set completeopt&
+ set completefunc&
+ bw!
+ delfunc Tcomplete
+endfunc
+
+" Test for completing from a thesaurus file without read permission
+func Test_complete_unreadable_thesaurus_file()
+ CheckUnix
+ CheckNotRoot
+
+ call writefile(['about', 'above'], 'Xfile')
+ call setfperm('Xfile', '---r--r--')
+ new
+ set complete=sXfile
+ exe "normal! ia\<C-P>"
+ call assert_equal('a', getline(1))
+ bw!
+ call delete('Xfile')
+ set complete&
+endfunc
+
" Test to ensure 'Scanning...' messages are not recorded in messages history
func Test_z1_complete_no_history()
new
@@ -884,4 +1283,52 @@ func Test_complete_smartindent()
delfunction! FooBarComplete
endfunc
+func Test_complete_overrun()
+ " this was going past the end of the copied text
+ new
+ sil norm si”0s0 
+ bwipe!
+endfunc
+
+func Test_infercase_very_long_line()
+ " this was truncating the line when inferring case
+ new
+ let longLine = "blah "->repeat(300)
+ let verylongLine = "blah "->repeat(400)
+ call setline(1, verylongLine)
+ call setline(2, longLine)
+ set ic infercase
+ exe "normal 2Go\<C-X>\<C-L>\<Esc>"
+ call assert_equal(longLine, getline(3))
+
+ " check that the too long text is NUL terminated
+ %del
+ norm o
+ norm 1987ax
+ exec "norm ox\<C-X>\<C-L>"
+ call assert_equal(repeat('x', 1987), getline(3))
+
+ bwipe!
+ set noic noinfercase
+endfunc
+
+func Test_ins_complete_add()
+ " this was reading past the end of allocated memory
+ new
+ norm o
+ norm 7o€€
+ sil! norm o
+
+ bwipe!
+endfunc
+
+func Test_ins_complete_end_of_line()
+ " this was reading past the end of the line
+ new
+ norm 8o€ý 
+ sil! norm o
+
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_lambda.vim b/src/nvim/testdir/test_lambda.vim
index c1fe47d1c9..c178c87d3e 100644
--- a/src/nvim/testdir/test_lambda.vim
+++ b/src/nvim/testdir/test_lambda.vim
@@ -308,3 +308,21 @@ func Test_lambda_error()
" This was causing a crash
call assert_fails('ec{@{->{d->()()', 'E15')
endfunc
+
+func Test_closure_error()
+ let l =<< trim END
+ func F1() closure
+ return 1
+ endfunc
+ END
+ call writefile(l, 'Xscript')
+ let caught_932 = 0
+ try
+ source Xscript
+ catch /E932:/
+ let caught_932 = 1
+ endtry
+ call assert_equal(1, caught_932)
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_listdict.vim b/src/nvim/testdir/test_listdict.vim
index 2f4e1db4a1..08c415a069 100644
--- a/src/nvim/testdir/test_listdict.vim
+++ b/src/nvim/testdir/test_listdict.vim
@@ -604,20 +604,23 @@ func Test_reverse_sort_uniq()
call assert_equal(['-0', 'A11', 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5], uniq(copy(l)))
call assert_equal([1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0'], reverse(l))
call assert_equal([1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0'], reverse(reverse(l)))
- call assert_equal(['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]], sort(l))
- call assert_equal([[0, 1, 2], [0, 1, 2], 4, 2, 2, 1.5, 'xaaa', 'x8', 'foo6', 'foo', 'foo', 'A11', '-0'], reverse(sort(l)))
- call assert_equal(['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]], sort(reverse(sort(l))))
- call assert_equal(['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 4, [0, 1, 2]], uniq(sort(l)))
-
- let l=[7, 9, 'one', 18, 12, 22, 'two', 10.0e-16, -1, 'three', 0xff, 0.22, 'four']
- call assert_equal([-1, 'one', 'two', 'three', 'four', 1.0e-15, 0.22, 7, 9, 12, 18, 22, 255], sort(copy(l), 'n'))
-
- let l=[7, 9, 18, 12, 22, 10.0e-16, -1, 0xff, 0, -0, 0.22, 'bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', {}, []]
- call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 1))
- call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 'i'))
- call assert_equal(['BAR', 'Bar', 'FOO', 'FOOBAR', 'Foo', 'bar', 'foo', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l)))
+ if has('float')
+ call assert_equal(['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]], sort(l))
+ call assert_equal([[0, 1, 2], [0, 1, 2], 4, 2, 2, 1.5, 'xaaa', 'x8', 'foo6', 'foo', 'foo', 'A11', '-0'], reverse(sort(l)))
+ call assert_equal(['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]], sort(reverse(sort(l))))
+ call assert_equal(['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 4, [0, 1, 2]], uniq(sort(l)))
+
+ let l = [7, 9, 'one', 18, 12, 22, 'two', 10.0e-16, -1, 'three', 0xff, 0.22, 'four']
+ call assert_equal([-1, 'one', 'two', 'three', 'four', 1.0e-15, 0.22, 7, 9, 12, 18, 22, 255], sort(copy(l), 'n'))
+
+ let l = [7, 9, 18, 12, 22, 10.0e-16, -1, 0xff, 0, -0, 0.22, 'bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', {}, []]
+ call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 1))
+ call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 'i'))
+ call assert_equal(['BAR', 'Bar', 'FOO', 'FOOBAR', 'Foo', 'bar', 'foo', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l)))
+ endif
call assert_fails('call reverse("")', 'E899:')
+ call assert_fails('call uniq([1, 2], {x, y -> []})', 'E882:')
endfunc
" reduce a list or a blob
diff --git a/src/nvim/testdir/test_maparg.vim b/src/nvim/testdir/test_maparg.vim
index dad4c81a7b..17c5f433ac 100644
--- a/src/nvim/testdir/test_maparg.vim
+++ b/src/nvim/testdir/test_maparg.vim
@@ -248,6 +248,8 @@ func Test_mapset()
bwipe!
call assert_fails('call mapset([], v:false, {})', 'E730:')
+ call assert_fails('call mapset("i", 0, "")', 'E715:')
+ call assert_fails('call mapset("i", 0, {})', 'E460:')
endfunc
func Check_ctrlb_map(d, check_alt)
diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim
index 2092b508ea..4f842189b6 100644
--- a/src/nvim/testdir/test_normal.vim
+++ b/src/nvim/testdir/test_normal.vim
@@ -1455,6 +1455,7 @@ func Test_normal21_nv_hat()
edit Xfoo | %bw
call assert_fails(':buffer #', 'E86')
call assert_fails(':execute "normal! \<C-^>"', 'E23')
+ call assert_fails("normal i\<C-R>#", 'E23:')
" Test for the expected behavior when switching between two named buffers.
edit Xfoo | edit Xbar
diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim
index e9a62d00a9..655d537336 100644
--- a/src/nvim/testdir/test_options.vim
+++ b/src/nvim/testdir/test_options.vim
@@ -234,6 +234,7 @@ func Test_complete()
new
call feedkeys("i\<C-N>\<Esc>", 'xt')
bwipe!
+ call assert_fails('set complete=ix', 'E535:')
set complete&
endfun
@@ -431,32 +432,37 @@ func Test_copy_context()
endfunc
func Test_set_ttytype()
- " Nvim does not support 'ttytype'.
- if !has('nvim') && !has('gui_running') && has('unix')
- " Setting 'ttytype' used to cause a double-free when exiting vim and
- " when vim is compiled with -DEXITFREE.
- set ttytype=ansi
- call assert_equal('ansi', &ttytype)
- call assert_equal(&ttytype, &term)
- set ttytype=xterm
- call assert_equal('xterm', &ttytype)
- call assert_equal(&ttytype, &term)
- try
- set ttytype=
- call assert_report('set ttytype= did not fail')
- catch /E529/
- endtry
-
- " Some systems accept any terminal name and return dumb settings,
- " check for failure of finding the entry and for missing 'cm' entry.
- try
- set ttytype=xxx
- call assert_report('set ttytype=xxx did not fail')
- catch /E522\|E437/
- endtry
-
- set ttytype&
- call assert_equal(&ttytype, &term)
+ throw "Skipped: Nvim does not support 'ttytype'"
+ CheckUnix
+ CheckNotGui
+
+ " Setting 'ttytype' used to cause a double-free when exiting vim and
+ " when vim is compiled with -DEXITFREE.
+ set ttytype=ansi
+ call assert_equal('ansi', &ttytype)
+ call assert_equal(&ttytype, &term)
+ set ttytype=xterm
+ call assert_equal('xterm', &ttytype)
+ call assert_equal(&ttytype, &term)
+ try
+ set ttytype=
+ call assert_report('set ttytype= did not fail')
+ catch /E529/
+ endtry
+
+ " Some systems accept any terminal name and return dumb settings,
+ " check for failure of finding the entry and for missing 'cm' entry.
+ try
+ set ttytype=xxx
+ call assert_report('set ttytype=xxx did not fail')
+ catch /E522\|E437/
+ endtry
+
+ set ttytype&
+ call assert_equal(&ttytype, &term)
+
+ if has('gui') && !has('gui_running')
+ call assert_fails('set term=gui', 'E531:')
endif
endfunc
diff --git a/src/nvim/testdir/test_preview.vim b/src/nvim/testdir/test_preview.vim
index 6c4ae414d3..b7b908e761 100644
--- a/src/nvim/testdir/test_preview.vim
+++ b/src/nvim/testdir/test_preview.vim
@@ -1,5 +1,8 @@
" Tests for the preview window
+source check.vim
+CheckFeature quickfix
+
func Test_Psearch()
" this used to cause ml_get errors
help
@@ -13,6 +16,8 @@ func Test_Psearch()
endfunc
func Test_window_preview()
+ CheckFeature quickfix
+
" Open a preview window
pedit Xa
call assert_equal(2, winnr('$'))
@@ -32,6 +37,8 @@ func Test_window_preview()
endfunc
func Test_window_preview_from_help()
+ CheckFeature quickfix
+
filetype on
call writefile(['/* some C code */'], 'Xpreview.c')
help
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index f6d573d76b..8c9e39570f 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -85,6 +85,12 @@ func s:setup_commands(cchar)
endif
endfunc
+" This must be run before any error lists are created.
+func Test_AA_cc_no_errors()
+ call assert_fails('cc', 'E42:')
+ call assert_fails('ll', 'E42:')
+endfunc
+
" Tests for the :clist and :llist commands
func XlistTests(cchar)
call s:setup_commands(a:cchar)
diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim
index 39fafbf7b4..880ca62685 100644
--- a/src/nvim/testdir/test_startup.vim
+++ b/src/nvim/testdir/test_startup.vim
@@ -603,7 +603,7 @@ func Test_invalid_args()
call assert_equal(0, v:shell_error)
if has('quickfix')
- " Detect invalid repeated arguments '-t foo -t foo", '-q foo -q foo'.
+ " Detect invalid repeated arguments '-t foo -t foo', '-q foo -q foo'.
for opt in ['-t', '-q']
let out = split(system(GetVimCommand() .. repeat(' ' .. opt .. ' foo', 2)), "\n")
call assert_equal(1, v:shell_error)
@@ -855,7 +855,7 @@ func Test_t_arg()
call writefile([' first', ' second', ' third'], 'Xfile1')
for t_arg in ['-t second', '-tsecond']
- if RunVim(before, after, '-t second')
+ if RunVim(before, after, t_arg)
call assert_equal(['Xfile1:L2C5'], readfile('Xtestout'), t_arg)
call delete('Xtestout')
endif
diff --git a/src/nvim/testdir/test_swap.vim b/src/nvim/testdir/test_swap.vim
index 923e1cbf50..34d1d585ce 100644
--- a/src/nvim/testdir/test_swap.vim
+++ b/src/nvim/testdir/test_swap.vim
@@ -2,6 +2,7 @@
source check.vim
source shared.vim
+source term_util.vim
func s:swapname()
return trim(execute('swapname'))
@@ -374,24 +375,26 @@ func Test_swap_prompt_splitwin()
call WaitForAssert({-> assert_match('^1$', term_getline(buf, 20))})
call StopVimInTerminal(buf)
- " This caused Vim to crash when typing "q".
- " TODO: it does not actually reproduce the crash.
- call writefile(['au BufAdd * set virtualedit=all'], 'Xvimrc')
-
- let buf = RunVimInTerminal('-u Xvimrc Xfile1', {'rows': 20, 'wait_for_ruler': 0})
- call TermWait(buf)
- call WaitForAssert({-> assert_match('^\[O\]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort:', term_getline(buf, 20))})
+ " This caused Vim to crash when typing "q" at the swap file prompt.
+ let buf = RunVimInTerminal('-c "au bufadd * let foo_w = wincol()"', {'rows': 18})
+ call term_sendkeys(buf, ":e Xfile1\<CR>")
+ call WaitForAssert({-> assert_match('More', term_getline(buf, 18))})
+ call term_sendkeys(buf, " ")
+ call WaitForAssert({-> assert_match('^\[O\]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort:', term_getline(buf, 18))})
call term_sendkeys(buf, "q")
+ call TermWait(buf)
+ " check that Vim is still running
+ call term_sendkeys(buf, ":echo 'hello'\<CR>")
+ call WaitForAssert({-> assert_match('^hello', term_getline(buf, 18))})
+ call term_sendkeys(buf, ":%bwipe!\<CR>")
+ call StopVimInTerminal(buf)
%bwipe!
call delete('Xfile1')
- call delete('Xvimrc')
endfunc
func Test_swap_symlink()
- if !has("unix")
- return
- endif
+ CheckUnix
call writefile(['text'], 'Xtestfile')
silent !ln -s -f Xtestfile Xtestlink
diff --git a/src/nvim/testdir/test_syntax.vim b/src/nvim/testdir/test_syntax.vim
index 7ba0149971..ccff01486e 100644
--- a/src/nvim/testdir/test_syntax.vim
+++ b/src/nvim/testdir/test_syntax.vim
@@ -188,22 +188,26 @@ func Test_syntax_completion()
call assert_equal('"syn sync ccomment clear fromstart linebreaks= linecont lines= match maxlines= minlines= region', @:)
" Check that clearing "Aap" avoids it showing up before Boolean.
- hi Aap ctermfg=blue
+ hi @Aap ctermfg=blue
call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_match('^"syn list Aap Boolean Character ', @:)
- hi clear Aap
+ call assert_match('^"syn list @Aap @boolean @character ', @:)
+ hi clear @Aap
call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_match('^"syn list Boolean Character ', @:)
+ call assert_match('^"syn list @boolean @character ', @:)
call feedkeys(":syn match \<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_match('^"syn match Boolean Character ', @:)
+ call assert_match('^"syn match @boolean @character ', @:)
+
+ syn cluster Aax contains=Aap
+ call feedkeys(":syn list @A\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_match('^"syn list @Aax', @:)
endfunc
func Test_echohl_completion()
call feedkeys(":echohl no\<C-A>\<C-B>\"\<CR>", 'tx')
" call assert_equal('"echohl NonText Normal none', @:)
- call assert_equal('"echohl NonText Normal NormalFloat NormalNC none', @:)
+ call assert_equal('"echohl NonText Normal NormalFloat none', @:)
endfunc
func Test_syntax_arg_skipped()
@@ -389,7 +393,7 @@ func Test_invalid_name()
syn keyword Nop yes
call assert_fails("syntax keyword Wr\x17ong bar", 'E669:')
syntax keyword @Wrong bar
- call assert_match('W18:', execute('1messages'))
+ call assert_fails("syntax keyword @#Wrong bar", 'E5248:')
syn clear
hi clear Nop
hi clear @Wrong
diff --git a/src/nvim/testdir/test_textformat.vim b/src/nvim/testdir/test_textformat.vim
index 0fc56083aa..4eb6e69adf 100644
--- a/src/nvim/testdir/test_textformat.vim
+++ b/src/nvim/testdir/test_textformat.vim
@@ -962,78 +962,6 @@ func Test_tw_2_fo_tm_noai()
bwipe!
endfunc
-func Test_tw_2_fo_cqm_com()
- new
- let t =<< trim END
- {
- X
- Xa
- XaY
- XY
- XYZ
- X Y
- X YZ
- XX
- XXa
- XXY
- }
- END
- call setline(1, t)
- call cursor(2, 1)
-
- set tw=2 fo=cqm comments=n:X
- exe "normal gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgq"
- let t =<< trim END
- X
- Xa
- XaY
- XY
- XYZ
- X Y
- X YZ
- XX
- XXa
- XXY
- END
- exe "normal o\n" . join(t, "\n")
-
- let expected =<< trim END
- {
- X
- Xa
- Xa
- XY
- XY
- XY
- XZ
- X Y
- X Y
- X Z
- XX
- XXa
- XXY
-
- X
- Xa
- Xa
- XY
- XY
- XY
- XZ
- X Y
- X Y
- X Z
- XX
- XXa
- XXY
- }
- END
- call assert_equal(expected, getline(1, '$'))
-
- set tw& fo& comments&
- bwipe!
-endfunc
-
func Test_tw_2_fo_tm_replace()
new
let t =<< trim END
@@ -1161,140 +1089,6 @@ func Test_whichwrap_multi_byte()
bwipe!
endfunc
-" Test for automatically adding comment leaders in insert mode
-func Test_threepiece_comment()
- new
- setlocal expandtab
- call setline(1, ["\t/*"])
- setlocal formatoptions=croql
- call cursor(1, 3)
- call feedkeys("A\<cr>\<cr>/", 'tnix')
- call assert_equal(["\t/*", " *", " */"], getline(1, '$'))
-
- " If a comment ends in a single line, then don't add it in the next line
- %d
- call setline(1, '/* line1 */')
- call feedkeys("A\<CR>next line", 'xt')
- call assert_equal(['/* line1 */', 'next line'], getline(1, '$'))
-
- %d
- " Copy the trailing indentation from the leader comment to a new line
- setlocal autoindent noexpandtab
- call feedkeys("a\t/*\tone\ntwo\n/", 'xt')
- call assert_equal(["\t/*\tone", "\t *\ttwo", "\t */"], getline(1, '$'))
- close!
-endfunc
-
-" Test for the 'f' flag in 'comments' (only the first line has the comment
-" string)
-func Test_firstline_comment()
- new
- setlocal comments=f:- fo+=ro
- exe "normal i- B\nD\<C-C>ggoC\<C-C>ggOA\<C-C>"
- call assert_equal(['A', '- B', ' C', ' D'], getline(1, '$'))
- %d
- setlocal comments=:-
- exe "normal i- B\nD\<C-C>ggoC\<C-C>ggOA\<C-C>"
- call assert_equal(['- A', '- B', '- C', '- D'], getline(1, '$'))
- %bw!
-endfunc
-
-" Test for the 'r' flag in 'comments' (right align comment)
-func Test_comment_rightalign()
- new
- setlocal comments=sr:/***,m:**,ex-2:******/ fo+=ro
- exe "normal i=\<C-C>o\t /***\nD\n/"
- exe "normal 2GOA\<C-C>joB\<C-C>jOC\<C-C>joE\<C-C>GOF\<C-C>joG"
- let expected =<< trim END
- =
- A
- /***
- ** B
- ** C
- ** D
- ** E
- ** F
- ******/
- G
- END
- call assert_equal(expected, getline(1, '$'))
- %bw!
-endfunc
-
-" Test for the 'b' flag in 'comments'
-func Test_comment_blank()
- new
- setlocal comments=b:* fo+=ro
- exe "normal i* E\nF\n\<BS>G\nH\<C-C>ggOC\<C-C>O\<BS>B\<C-C>OA\<C-C>2joD"
- let expected =<< trim END
- A
- *B
- * C
- * D
- * E
- * F
- *G
- H
- END
- call assert_equal(expected, getline(1, '$'))
- %bw!
-endfunc
-
-" Test for the 'n' flag in comments
-func Test_comment_nested()
- new
- setlocal comments=n:> fo+=ro
- exe "normal i> B\nD\<C-C>ggOA\<C-C>joC\<C-C>Go\<BS>>>> F\nH"
- exe "normal 5GOE\<C-C>6GoG"
- let expected =<< trim END
- > A
- > B
- > C
- > D
- >>>> E
- >>>> F
- >>>> G
- >>>> H
- END
- call assert_equal(expected, getline(1, '$'))
- %bw!
-endfunc
-
-" Test for a space character in 'comments' setting
-func Test_comment_space()
- new
- setlocal comments=b:\ > fo+=ro
- exe "normal i> B\nD\<C-C>ggOA\<C-C>joC"
- exe "normal Go > F\nH\<C-C>kOE\<C-C>joG"
- let expected =<< trim END
- A
- > B
- C
- D
- > E
- > F
- > G
- > H
- END
- call assert_equal(expected, getline(1, '$'))
- %bw!
-endfunc
-
-" Test for the 'O' flag in 'comments'
-func Test_comment_O()
- new
- setlocal comments=Ob:* fo+=ro
- exe "normal i* B\nD\<C-C>kOA\<C-C>joC"
- let expected =<< trim END
- A
- * B
- * C
- * D
- END
- call assert_equal(expected, getline(1, '$'))
- %bw!
-endfunc
-
" Test for 'a' and 'w' flags in 'formatoptions'
func Test_fo_a_w()
new
@@ -1334,25 +1128,6 @@ func Test_fo_a_w()
%bw!
endfunc
-" Test for 'j' flag in 'formatoptions'
-func Test_fo_j()
- new
- setlocal fo+=j comments=://
- call setline(1, ['i++; // comment1', ' // comment2'])
- normal J
- call assert_equal('i++; // comment1 comment2', getline(1))
- setlocal fo-=j
- call setline(1, ['i++; // comment1', ' // comment2'])
- normal J
- call assert_equal('i++; // comment1 // comment2', getline(1))
- " Test with nested comments
- setlocal fo+=j comments=n:>,n:)
- call setline(1, ['i++; > ) > ) comment1', ' > ) comment2'])
- normal J
- call assert_equal('i++; > ) > ) comment1 comment2', getline(1))
- %bw!
-endfunc
-
" Test for formatting lines using gq in visual mode
func Test_visual_gq_format()
new
@@ -1487,53 +1262,6 @@ func Test_fo_2()
close!
endfunc
-" Test for formatting lines where only the first line has a comment.
-func Test_fo_gq_with_firstline_comment()
- new
- setlocal formatoptions=tcq
- call setline(1, ['- one two', 'three'])
- normal gggqG
- call assert_equal(['- one two three'], getline(1, '$'))
-
- %d
- call setline(1, ['- one', '- two'])
- normal gggqG
- call assert_equal(['- one', '- two'], getline(1, '$'))
- close!
-endfunc
-
-" Test for trying to join a comment line with a non-comment line
-func Test_join_comments()
- new
- call setline(1, ['one', '/* two */', 'three'])
- normal gggqG
- call assert_equal(['one', '/* two */', 'three'], getline(1, '$'))
- close!
-endfunc
-
-" Test for using 'a' in 'formatoptions' with comments
-func Test_autoformat_comments()
- new
- setlocal formatoptions+=a
- call feedkeys("a- one\n- two\n", 'xt')
- call assert_equal(['- one', '- two', ''], getline(1, '$'))
-
- %d
- call feedkeys("a\none\n", 'xt')
- call assert_equal(['', 'one', ''], getline(1, '$'))
-
- setlocal formatoptions+=aw
- %d
- call feedkeys("aone \ntwo\n", 'xt')
- call assert_equal(['one two', ''], getline(1, '$'))
-
- %d
- call feedkeys("aone\ntwo\n", 'xt')
- call assert_equal(['one', 'two', ''], getline(1, '$'))
-
- close!
-endfunc
-
" This was leaving the cursor after the end of a line. Complicated way to
" have the problem show up with valgrind.
func Test_correct_cursor_position()
diff --git a/src/nvim/testdir/test_trycatch.vim b/src/nvim/testdir/test_trycatch.vim
index 646594e482..d71bb5bbb8 100644
--- a/src/nvim/testdir/test_trycatch.vim
+++ b/src/nvim/testdir/test_trycatch.vim
@@ -2027,16 +2027,179 @@ func Test_try_catch_verbose()
endtry
redir END
let expected = [
- \ 'Exception thrown: Vim(echo):E121: Undefined variable: i',
- \ '',
- \ 'Exception caught: Vim(echo):E121: Undefined variable: i',
- \ '',
- \ 'Exception finished: Vim(echo):E121: Undefined variable: i'
- \ ]
+ \ 'Exception thrown: Vim(echo):E121: Undefined variable: i', '',
+ \ 'Exception caught: Vim(echo):E121: Undefined variable: i', '',
+ \ 'Exception finished: Vim(echo):E121: Undefined variable: i']
call assert_equal(expected, split(msg, "\n"))
+
+ " Test for verbose messages displayed when an exception is discarded
+ redir => msg
+ try
+ try
+ throw 'abc'
+ finally
+ throw 'xyz'
+ endtry
+ catch
+ endtry
+ redir END
+ let expected = [
+ \ 'Exception thrown: abc', '',
+ \ 'Exception made pending: abc', '',
+ \ 'Exception thrown: xyz', '',
+ \ 'Exception discarded: abc', '',
+ \ 'Exception caught: xyz', '',
+ \ 'Exception finished: xyz']
+ call assert_equal(expected, split(msg, "\n"))
+
+ " Test for messages displayed when :throw is resumed after :finally
+ redir => msg
+ try
+ try
+ throw 'abc'
+ finally
+ endtry
+ catch
+ endtry
+ redir END
+ let expected = [
+ \ 'Exception thrown: abc', '',
+ \ 'Exception made pending: abc', '',
+ \ 'Exception resumed: abc', '',
+ \ 'Exception caught: abc', '',
+ \ 'Exception finished: abc']
+ call assert_equal(expected, split(msg, "\n"))
+
+ " Test for messages displayed when :break is resumed after :finally
+ redir => msg
+ for i in range(1)
+ try
+ break
+ finally
+ endtry
+ endfor
+ redir END
+ let expected = [':break made pending', '', ':break resumed']
+ call assert_equal(expected, split(msg, "\n"))
+
+ " Test for messages displayed when :continue is resumed after :finally
+ redir => msg
+ for i in range(1)
+ try
+ continue
+ finally
+ endtry
+ endfor
+ redir END
+ let expected = [':continue made pending', '', ':continue resumed']
+ call assert_equal(expected, split(msg, "\n"))
+
+ " Test for messages displayed when :return is resumed after :finally
+ func Xtest()
+ try
+ return 'vim'
+ finally
+ endtry
+ endfunc
+ redir => msg
+ call Xtest()
+ redir END
+ let expected = [
+ \ 'calling Xtest()', '',
+ \ ':return vim made pending', '',
+ \ ':return vim resumed', '',
+ \ 'Xtest returning ''vim''', '',
+ \ 'continuing in Test_try_catch_verbose']
+ call assert_equal(expected, split(msg, "\n"))
+ delfunc Xtest
+
+ " Test for messages displayed when :finish is resumed after :finally
+ call writefile(['try', 'finish', 'finally', 'endtry'], 'Xscript')
+ redir => msg
+ source Xscript
+ redir END
+ let expected = [
+ \ ':finish made pending', '',
+ \ ':finish resumed', '',
+ \ 'finished sourcing Xscript',
+ \ 'continuing in Test_try_catch_verbose']
+ call assert_equal(expected, split(msg, "\n")[1:])
+ call delete('Xscript')
+
+ " Test for messages displayed when a pending :continue is discarded by an
+ " exception in a finally handler
+ redir => msg
+ try
+ for i in range(1)
+ try
+ continue
+ finally
+ throw 'abc'
+ endtry
+ endfor
+ catch
+ endtry
+ redir END
+ let expected = [
+ \ ':continue made pending', '',
+ \ 'Exception thrown: abc', '',
+ \ ':continue discarded', '',
+ \ 'Exception caught: abc', '',
+ \ 'Exception finished: abc']
+ call assert_equal(expected, split(msg, "\n"))
+
set verbose&
endfunc
+" Test for throwing an exception from a BufEnter autocmd {{{1
+func Test_BufEnter_exception()
+ augroup bufenter_exception
+ au!
+ autocmd BufEnter Xfile1 throw 'abc'
+ augroup END
+
+ let caught_abc = 0
+ try
+ sp Xfile1
+ catch /^abc/
+ let caught_abc = 1
+ endtry
+ call assert_equal(1, caught_abc)
+ call assert_equal(1, winnr('$'))
+
+ augroup bufenter_exception
+ au!
+ augroup END
+ augroup! bufenter_exception
+ %bwipe!
+
+ " Test for recursively throwing exceptions in autocmds
+ augroup bufenter_exception
+ au!
+ autocmd BufEnter Xfile1 throw 'bufenter'
+ autocmd BufLeave Xfile1 throw 'bufleave'
+ augroup END
+
+ let ex_count = 0
+ try
+ try
+ sp Xfile1
+ catch /^bufenter/
+ let ex_count += 1
+ endtry
+ catch /^bufleave/
+ let ex_count += 10
+ endtry
+ call assert_equal(10, ex_count)
+ call assert_equal(2, winnr('$'))
+
+ augroup bufenter_exception
+ au!
+ augroup END
+ augroup! bufenter_exception
+ %bwipe!
+endfunc
+
" Test for using throw in a called function with following error {{{1
func Test_user_command_throw_in_function_call()
let lines =<< trim END
diff --git a/src/nvim/testdir/test_user_func.vim b/src/nvim/testdir/test_user_func.vim
index 5231ef7b4f..c14624f5b4 100644
--- a/src/nvim/testdir/test_user_func.vim
+++ b/src/nvim/testdir/test_user_func.vim
@@ -169,3 +169,10 @@ endfunc
func Test_failed_call_in_try()
try | call UnknownFunc() | catch | endtry
endfunc
+
+" Test for listing user-defined functions
+func Test_function_list()
+ call assert_fails("function Xabc", 'E123:')
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_viminfo.vim b/src/nvim/testdir/test_viminfo.vim
new file mode 100644
index 0000000000..2d6d598011
--- /dev/null
+++ b/src/nvim/testdir/test_viminfo.vim
@@ -0,0 +1,21 @@
+
+" Test for errors in setting 'viminfo'
+func Test_viminfo_option_error()
+ " Missing number
+ call assert_fails('set viminfo=\"', 'E526:')
+ for c in split("'/:<@s", '\zs')
+ call assert_fails('set viminfo=' .. c, 'E526:')
+ endfor
+
+ " Missing comma
+ call assert_fails('set viminfo=%10!', 'E527:')
+ call assert_fails('set viminfo=!%10', 'E527:')
+ call assert_fails('set viminfo=h%10', 'E527:')
+ call assert_fails('set viminfo=c%10', 'E527:')
+ call assert_fails('set viminfo=:10%10', 'E527:')
+
+ " Missing ' setting
+ call assert_fails('set viminfo=%10', 'E528:')
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim
index 0f204cdd0c..97e879c9ef 100644
--- a/src/nvim/testdir/test_vimscript.vim
+++ b/src/nvim/testdir/test_vimscript.vim
@@ -1829,6 +1829,9 @@ func Test_missing_end()
endtry
call assert_equal(1, caught_e733)
+ " Using endfunc with :if
+ call assert_fails('exe "if 1 | endfunc | endif"', 'E193:')
+
" Missing 'in' in a :for statement
call assert_fails('for i range(1) | endfor', 'E690:')
endfunc
@@ -1875,6 +1878,15 @@ func Test_deep_nest()
@a
let @a = ''
endfunc
+
+ " Deep nesting of function ... endfunction
+ func Test5()
+ let @a = join(repeat(['function X()'], 51), "\n")
+ let @a ..= "\necho v:true\n"
+ let @a ..= join(repeat(['endfunction'], 51), "\n")
+ @a
+ let @a = ''
+ endfunc
[SCRIPT]
call writefile(lines, 'Xscript')
@@ -1882,20 +1894,31 @@ func Test_deep_nest()
" Deep nesting of if ... endif
call term_sendkeys(buf, ":call Test1()\n")
+ call term_wait(buf)
call WaitForAssert({-> assert_match('^E579:', term_getline(buf, 5))})
" Deep nesting of for ... endfor
call term_sendkeys(buf, ":call Test2()\n")
+ call term_wait(buf)
call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))})
" Deep nesting of while ... endwhile
call term_sendkeys(buf, ":call Test3()\n")
+ call term_wait(buf)
call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))})
" Deep nesting of try ... endtry
call term_sendkeys(buf, ":call Test4()\n")
+ call term_wait(buf)
call WaitForAssert({-> assert_match('^E601:', term_getline(buf, 5))})
+ " Deep nesting of function ... endfunction
+ call term_sendkeys(buf, ":call Test5()\n")
+ call term_wait(buf)
+ call WaitForAssert({-> assert_match('^E1058:', term_getline(buf, 4))})
+ call term_sendkeys(buf, "\<C-C>\n")
+ call term_wait(buf)
+
"let l = ''
"for i in range(1, 6)
" let l ..= term_getline(buf, i) . "\n"
diff --git a/src/nvim/testing.c b/src/nvim/testing.c
index e70e9f2cbd..4a252dca3e 100644
--- a/src/nvim/testing.c
+++ b/src/nvim/testing.c
@@ -326,19 +326,19 @@ static int assert_beeps(typval_T *argvars, bool no_beep)
}
/// "assert_beeps(cmd [, error])" function
-void f_assert_beeps(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_assert_beeps(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_beeps(argvars, false);
}
/// "assert_nobeep(cmd [, error])" function
-void f_assert_nobeep(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_assert_nobeep(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_beeps(argvars, true);
}
/// "assert_equal(expected, actual[, msg])" function
-void f_assert_equal(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_assert_equal(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_equal_common(argvars, ASSERT_EQUAL);
}
@@ -433,19 +433,19 @@ static int assert_equalfile(typval_T *argvars)
}
/// "assert_equalfile(fname-one, fname-two[, msg])" function
-void f_assert_equalfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_assert_equalfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_equalfile(argvars);
}
/// "assert_notequal(expected, actual[, msg])" function
-void f_assert_notequal(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_assert_notequal(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_equal_common(argvars, ASSERT_NOTEQUAL);
}
/// "assert_exception(string[, msg])" function
-void f_assert_exception(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_assert_exception(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
garray_T ga;
@@ -457,7 +457,7 @@ void f_assert_exception(typval_T *argvars, typval_T *rettv, FunPtr fptr)
ga_clear(&ga);
rettv->vval.v_number = 1;
} else if (error != NULL
- && strstr((char *)get_vim_var_str(VV_EXCEPTION), error) == NULL) {
+ && strstr(get_vim_var_str(VV_EXCEPTION), error) == NULL) {
prepare_assert_error(&ga);
fill_assert_error(&ga, &argvars[1], NULL, &argvars[0],
get_vim_var_tv(VV_EXCEPTION), ASSERT_OTHER);
@@ -468,7 +468,7 @@ void f_assert_exception(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "assert_fails(cmd [, error [, msg]])" function
-void f_assert_fails(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_assert_fails(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const cmd = tv_get_string_chk(&argvars[0]);
garray_T ga;
@@ -493,7 +493,7 @@ void f_assert_fails(typval_T *argvars, typval_T *rettv, FunPtr fptr)
const char *const error = tv_get_string_buf_chk(&argvars[1], buf);
if (error == NULL
- || strstr((char *)get_vim_var_str(VV_ERRMSG), error) == NULL) {
+ || strstr(get_vim_var_str(VV_ERRMSG), error) == NULL) {
prepare_assert_error(&ga);
fill_assert_error(&ga, &argvars[2], NULL, &argvars[1],
get_vim_var_tv(VV_ERRMSG), ASSERT_OTHER);
@@ -513,7 +513,7 @@ void f_assert_fails(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
// "assert_false(actual[, msg])" function
-void f_assert_false(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_assert_false(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_bool(argvars, false);
}
@@ -574,25 +574,25 @@ static int assert_inrange(typval_T *argvars)
}
/// "assert_inrange(lower, upper[, msg])" function
-void f_assert_inrange(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_assert_inrange(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_inrange(argvars);
}
/// "assert_match(pattern, actual[, msg])" function
-void f_assert_match(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_assert_match(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_match_common(argvars, ASSERT_MATCH);
}
/// "assert_notmatch(pattern, actual[, msg])" function
-void f_assert_notmatch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_assert_notmatch(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_match_common(argvars, ASSERT_NOTMATCH);
}
/// "assert_report(msg)" function
-void f_assert_report(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_assert_report(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
garray_T ga;
@@ -604,13 +604,13 @@ void f_assert_report(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "assert_true(actual[, msg])" function
-void f_assert_true(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_assert_true(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_bool(argvars, true);
}
/// "test_garbagecollect_now()" function
-void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
// This is dangerous, any Lists and Dicts used internally may be freed
// while still in use.
@@ -618,7 +618,7 @@ void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "test_write_list_log()" function
-void f_test_write_list_log(typval_T *const argvars, typval_T *const rettv, FunPtr fptr)
+void f_test_write_list_log(typval_T *const argvars, typval_T *const rettv, EvalFuncData fptr)
{
const char *const fname = tv_get_string_chk(&argvars[0]);
if (fname == NULL) {
diff --git a/src/nvim/textformat.c b/src/nvim/textformat.c
new file mode 100644
index 0000000000..125146f712
--- /dev/null
+++ b/src/nvim/textformat.c
@@ -0,0 +1,1127 @@
+// 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
+
+// textformat.c: text formatting functions
+
+#include <stdbool.h>
+
+#include "nvim/ascii.h"
+#include "nvim/change.h"
+#include "nvim/charset.h"
+#include "nvim/cursor.h"
+#include "nvim/drawscreen.h"
+#include "nvim/edit.h"
+#include "nvim/eval.h"
+#include "nvim/getchar.h"
+#include "nvim/globals.h"
+#include "nvim/indent.h"
+#include "nvim/indent_c.h"
+#include "nvim/mbyte.h"
+#include "nvim/memline.h"
+#include "nvim/move.h"
+#include "nvim/normal.h"
+#include "nvim/ops.h"
+#include "nvim/option.h"
+#include "nvim/os/input.h"
+#include "nvim/pos.h"
+#include "nvim/search.h"
+#include "nvim/strings.h"
+#include "nvim/textformat.h"
+#include "nvim/textobject.h"
+#include "nvim/undo.h"
+#include "nvim/vim.h"
+#include "nvim/window.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "textformat.c.generated.h"
+#endif
+
+static bool did_add_space = false; ///< auto_format() added an extra space
+ ///< under the cursor
+
+#define WHITECHAR(cc) (ascii_iswhite(cc) \
+ && !utf_iscomposing(utf_ptr2char((char *)get_cursor_pos_ptr() + 1)))
+
+/// Return true if format option 'x' is in effect.
+/// Take care of no formatting when 'paste' is set.
+bool has_format_option(int x)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ if (p_paste) {
+ return false;
+ }
+ return vim_strchr(curbuf->b_p_fo, x) != NULL;
+}
+
+/// Format text at the current insert position.
+///
+/// If the INSCHAR_COM_LIST flag is present, then the value of second_indent
+/// will be the comment leader length sent to open_line().
+///
+/// @param c character to be inserted (can be NUL)
+void internal_format(int textwidth, int second_indent, int flags, bool format_only, int c)
+{
+ int cc;
+ int save_char = NUL;
+ bool haveto_redraw = false;
+ const bool fo_ins_blank = has_format_option(FO_INS_BLANK);
+ const bool fo_multibyte = has_format_option(FO_MBYTE_BREAK);
+ const bool fo_rigor_tw = has_format_option(FO_RIGOROUS_TW);
+ const bool fo_white_par = has_format_option(FO_WHITE_PAR);
+ bool first_line = true;
+ colnr_T leader_len;
+ bool no_leader = false;
+ int do_comments = (flags & INSCHAR_DO_COM);
+ int has_lbr = curwin->w_p_lbr;
+
+ // make sure win_lbr_chartabsize() counts correctly
+ curwin->w_p_lbr = false;
+
+ // When 'ai' is off we don't want a space under the cursor to be
+ // deleted. Replace it with an 'x' temporarily.
+ if (!curbuf->b_p_ai
+ && !(State & VREPLACE_FLAG)) {
+ cc = gchar_cursor();
+ if (ascii_iswhite(cc)) {
+ save_char = cc;
+ pchar_cursor('x');
+ }
+ }
+
+ // Repeat breaking lines, until the current line is not too long.
+ while (!got_int) {
+ int startcol; // Cursor column at entry
+ int wantcol; // column at textwidth border
+ int foundcol; // column for start of spaces
+ int end_foundcol = 0; // column for start of word
+ colnr_T len;
+ colnr_T virtcol;
+ int orig_col = 0;
+ char_u *saved_text = NULL;
+ colnr_T col;
+ colnr_T end_col;
+ bool did_do_comment = false;
+
+ virtcol = get_nolist_virtcol()
+ + char2cells(c != NUL ? c : gchar_cursor());
+ if (virtcol <= (colnr_T)textwidth) {
+ break;
+ }
+
+ if (no_leader) {
+ do_comments = false;
+ } else if (!(flags & INSCHAR_FORMAT)
+ && has_format_option(FO_WRAP_COMS)) {
+ do_comments = true;
+ }
+
+ // Don't break until after the comment leader
+ if (do_comments) {
+ char_u *line = get_cursor_line_ptr();
+ leader_len = get_leader_len((char *)line, NULL, false, true);
+ if (leader_len == 0 && curbuf->b_p_cin) {
+ // Check for a line comment after code.
+ int comment_start = check_linecomment((char *)line);
+ if (comment_start != MAXCOL) {
+ leader_len = get_leader_len((char *)line + comment_start, NULL, false, true);
+ if (leader_len != 0) {
+ leader_len += comment_start;
+ }
+ }
+ }
+ } else {
+ leader_len = 0;
+ }
+
+ // If the line doesn't start with a comment leader, then don't
+ // start one in a following broken line. Avoids that a %word
+ // moved to the start of the next line causes all following lines
+ // to start with %.
+ if (leader_len == 0) {
+ no_leader = true;
+ }
+ if (!(flags & INSCHAR_FORMAT)
+ && leader_len == 0
+ && !has_format_option(FO_WRAP)) {
+ break;
+ }
+ if ((startcol = curwin->w_cursor.col) == 0) {
+ break;
+ }
+
+ // find column of textwidth border
+ coladvance((colnr_T)textwidth);
+ wantcol = curwin->w_cursor.col;
+
+ curwin->w_cursor.col = startcol;
+ foundcol = 0;
+ int skip_pos = 0;
+
+ // Find position to break at.
+ // Stop at first entered white when 'formatoptions' has 'v'
+ while ((!fo_ins_blank && !has_format_option(FO_INS_VI))
+ || (flags & INSCHAR_FORMAT)
+ || curwin->w_cursor.lnum != Insstart.lnum
+ || curwin->w_cursor.col >= Insstart.col) {
+ if (curwin->w_cursor.col == startcol && c != NUL) {
+ cc = c;
+ } else {
+ cc = gchar_cursor();
+ }
+ if (WHITECHAR(cc)) {
+ // remember position of blank just before text
+ end_col = curwin->w_cursor.col;
+
+ // find start of sequence of blanks
+ int wcc = 0; // counter for whitespace chars
+ while (curwin->w_cursor.col > 0 && WHITECHAR(cc)) {
+ dec_cursor();
+ cc = gchar_cursor();
+
+ // Increment count of how many whitespace chars in this
+ // group; we only need to know if it's more than one.
+ if (wcc < 2) {
+ wcc++;
+ }
+ }
+ if (curwin->w_cursor.col == 0 && WHITECHAR(cc)) {
+ break; // only spaces in front of text
+ }
+
+ // Don't break after a period when 'formatoptions' has 'p' and
+ // there are less than two spaces.
+ if (has_format_option(FO_PERIOD_ABBR) && cc == '.' && wcc < 2) {
+ continue;
+ }
+
+ // Don't break until after the comment leader
+ if (curwin->w_cursor.col < leader_len) {
+ break;
+ }
+
+ if (has_format_option(FO_ONE_LETTER)) {
+ // do not break after one-letter words
+ if (curwin->w_cursor.col == 0) {
+ break; // one-letter word at begin
+ }
+ // do not break "#a b" when 'tw' is 2
+ if (curwin->w_cursor.col <= leader_len) {
+ break;
+ }
+ col = curwin->w_cursor.col;
+ dec_cursor();
+ cc = gchar_cursor();
+
+ if (WHITECHAR(cc)) {
+ continue; // one-letter, continue
+ }
+ curwin->w_cursor.col = col;
+ }
+
+ inc_cursor();
+
+ end_foundcol = end_col + 1;
+ foundcol = curwin->w_cursor.col;
+ if (curwin->w_cursor.col <= (colnr_T)wantcol) {
+ break;
+ }
+ } else if ((cc >= 0x100 || !utf_allow_break_before(cc)) && fo_multibyte) {
+ int ncc;
+ bool allow_break;
+
+ // Break after or before a multi-byte character.
+ if (curwin->w_cursor.col != startcol) {
+ // Don't break until after the comment leader
+ if (curwin->w_cursor.col < leader_len) {
+ break;
+ }
+ col = curwin->w_cursor.col;
+ inc_cursor();
+ ncc = gchar_cursor();
+ allow_break = utf_allow_break(cc, ncc);
+
+ // If we have already checked this position, skip!
+ if (curwin->w_cursor.col != skip_pos && allow_break) {
+ foundcol = curwin->w_cursor.col;
+ end_foundcol = foundcol;
+ if (curwin->w_cursor.col <= (colnr_T)wantcol) {
+ break;
+ }
+ }
+ curwin->w_cursor.col = col;
+ }
+
+ if (curwin->w_cursor.col == 0) {
+ break;
+ }
+
+ ncc = cc;
+ col = curwin->w_cursor.col;
+
+ dec_cursor();
+ cc = gchar_cursor();
+
+ if (WHITECHAR(cc)) {
+ continue; // break with space
+ }
+ // Don't break until after the comment leader.
+ if (curwin->w_cursor.col < leader_len) {
+ break;
+ }
+
+ curwin->w_cursor.col = col;
+ skip_pos = curwin->w_cursor.col;
+
+ allow_break = utf_allow_break(cc, ncc);
+
+ // Must handle this to respect line break prohibition.
+ if (allow_break) {
+ foundcol = curwin->w_cursor.col;
+ end_foundcol = foundcol;
+ }
+ if (curwin->w_cursor.col <= (colnr_T)wantcol) {
+ const bool ncc_allow_break = utf_allow_break_before(ncc);
+
+ if (allow_break) {
+ break;
+ }
+ if (!ncc_allow_break && !fo_rigor_tw) {
+ // Enable at most 1 punct hang outside of textwidth.
+ if (curwin->w_cursor.col == startcol) {
+ // We are inserting a non-breakable char, postpone
+ // line break check to next insert.
+ end_foundcol = foundcol = 0;
+ break;
+ }
+
+ // Neither cc nor ncc is NUL if we are here, so
+ // it's safe to inc_cursor.
+ col = curwin->w_cursor.col;
+
+ inc_cursor();
+ cc = ncc;
+ ncc = gchar_cursor();
+ // handle insert
+ ncc = (ncc != NUL) ? ncc : c;
+
+ allow_break = utf_allow_break(cc, ncc);
+
+ if (allow_break) {
+ // Break only when we are not at end of line.
+ end_foundcol = foundcol = ncc == NUL? 0 : curwin->w_cursor.col;
+ break;
+ }
+ curwin->w_cursor.col = col;
+ }
+ }
+ }
+ if (curwin->w_cursor.col == 0) {
+ break;
+ }
+ dec_cursor();
+ }
+
+ if (foundcol == 0) { // no spaces, cannot break line
+ curwin->w_cursor.col = startcol;
+ break;
+ }
+
+ // Going to break the line, remove any "$" now.
+ undisplay_dollar();
+
+ // Offset between cursor position and line break is used by replace
+ // stack functions. MODE_VREPLACE does not use this, and backspaces
+ // over the text instead.
+ if (State & VREPLACE_FLAG) {
+ orig_col = startcol; // Will start backspacing from here
+ } else {
+ replace_offset = startcol - end_foundcol;
+ }
+
+ // adjust startcol for spaces that will be deleted and
+ // characters that will remain on top line
+ curwin->w_cursor.col = foundcol;
+ while ((cc = gchar_cursor(), WHITECHAR(cc))
+ && (!fo_white_par || curwin->w_cursor.col < startcol)) {
+ inc_cursor();
+ }
+ startcol -= curwin->w_cursor.col;
+ if (startcol < 0) {
+ startcol = 0;
+ }
+
+ if (State & VREPLACE_FLAG) {
+ // In MODE_VREPLACE state, we will backspace over the text to be
+ // wrapped, so save a copy now to put on the next line.
+ saved_text = vim_strsave(get_cursor_pos_ptr());
+ curwin->w_cursor.col = orig_col;
+ saved_text[startcol] = NUL;
+
+ // Backspace over characters that will move to the next line
+ if (!fo_white_par) {
+ backspace_until_column(foundcol);
+ }
+ } else {
+ // put cursor after pos. to break line
+ if (!fo_white_par) {
+ curwin->w_cursor.col = foundcol;
+ }
+ }
+
+ // Split the line just before the margin.
+ // Only insert/delete lines, but don't really redraw the window.
+ open_line(FORWARD, OPENLINE_DELSPACES + OPENLINE_MARKFIX
+ + (fo_white_par ? OPENLINE_KEEPTRAIL : 0)
+ + (do_comments ? OPENLINE_DO_COM : 0)
+ + OPENLINE_FORMAT
+ + ((flags & INSCHAR_COM_LIST) ? OPENLINE_COM_LIST : 0),
+ ((flags & INSCHAR_COM_LIST) ? second_indent : old_indent),
+ &did_do_comment);
+ if (!(flags & INSCHAR_COM_LIST)) {
+ old_indent = 0;
+ }
+
+ // If a comment leader was inserted, may also do this on a following
+ // line.
+ if (did_do_comment) {
+ no_leader = false;
+ }
+
+ replace_offset = 0;
+ if (first_line) {
+ if (!(flags & INSCHAR_COM_LIST)) {
+ // This section is for auto-wrap of numeric lists. When not
+ // in insert mode (i.e. format_lines()), the INSCHAR_COM_LIST
+ // flag will be set and open_line() will handle it (as seen
+ // above). The code here (and in get_number_indent()) will
+ // recognize comments if needed...
+ if (second_indent < 0 && has_format_option(FO_Q_NUMBER)) {
+ second_indent = get_number_indent(curwin->w_cursor.lnum - 1);
+ }
+ if (second_indent >= 0) {
+ if (State & VREPLACE_FLAG) {
+ change_indent(INDENT_SET, second_indent, false, NUL, true);
+ } else if (leader_len > 0 && second_indent - leader_len > 0) {
+ int padding = second_indent - leader_len;
+
+ // We started at the first_line of a numbered list
+ // that has a comment. the open_line() function has
+ // inserted the proper comment leader and positioned
+ // the cursor at the end of the split line. Now we
+ // add the additional whitespace needed after the
+ // comment leader for the numbered list.
+ for (int i = 0; i < padding; i++) {
+ ins_str(" ");
+ }
+ changed_bytes(curwin->w_cursor.lnum, leader_len);
+ } else {
+ (void)set_indent(second_indent, SIN_CHANGED);
+ }
+ }
+ }
+ first_line = false;
+ }
+
+ if (State & VREPLACE_FLAG) {
+ // In MODE_VREPLACE state we have backspaced over the text to be
+ // moved, now we re-insert it into the new line.
+ ins_bytes((char *)saved_text);
+ xfree(saved_text);
+ } else {
+ // Check if cursor is not past the NUL off the line, cindent
+ // may have added or removed indent.
+ curwin->w_cursor.col += startcol;
+ len = (colnr_T)STRLEN(get_cursor_line_ptr());
+ if (curwin->w_cursor.col > len) {
+ curwin->w_cursor.col = len;
+ }
+ }
+
+ haveto_redraw = true;
+ set_can_cindent(true);
+ // moved the cursor, don't autoindent or cindent now
+ did_ai = false;
+ did_si = false;
+ can_si = false;
+ can_si_back = false;
+ line_breakcheck();
+ }
+
+ if (save_char != NUL) { // put back space after cursor
+ pchar_cursor((char_u)save_char);
+ }
+
+ curwin->w_p_lbr = has_lbr;
+
+ if (!format_only && haveto_redraw) {
+ update_topline(curwin);
+ redraw_curbuf_later(UPD_VALID);
+ }
+}
+
+/// Blank lines, and lines containing only the comment leader, are left
+/// untouched by the formatting. The function returns true in this
+/// case. It also returns true when a line starts with the end of a comment
+/// ('e' in comment flags), so that this line is skipped, and not joined to the
+/// previous line. A new paragraph starts after a blank line, or when the
+/// comment leader changes.
+static int fmt_check_par(linenr_T lnum, int *leader_len, char_u **leader_flags, bool do_comments)
+{
+ char_u *flags = NULL; // init for GCC
+ char_u *ptr;
+
+ ptr = ml_get(lnum);
+ if (do_comments) {
+ *leader_len = get_leader_len((char *)ptr, (char **)leader_flags, false, true);
+ } else {
+ *leader_len = 0;
+ }
+
+ if (*leader_len > 0) {
+ // Search for 'e' flag in comment leader flags.
+ flags = *leader_flags;
+ while (*flags && *flags != ':' && *flags != COM_END) {
+ flags++;
+ }
+ }
+
+ return *skipwhite((char *)ptr + *leader_len) == NUL
+ || (*leader_len > 0 && *flags == COM_END)
+ || startPS(lnum, NUL, false);
+}
+
+/// @return true if line "lnum" ends in a white character.
+static bool ends_in_white(linenr_T lnum)
+{
+ char_u *s = ml_get(lnum);
+ size_t l;
+
+ if (*s == NUL) {
+ return false;
+ }
+ l = STRLEN(s) - 1;
+ return ascii_iswhite(s[l]);
+}
+
+/// @return true if the two comment leaders given are the same.
+///
+/// @param lnum The first line. White-space is ignored.
+///
+/// @note the whole of 'leader1' must match 'leader2_len' characters from 'leader2'.
+static bool same_leader(linenr_T lnum, int leader1_len, char_u *leader1_flags, int leader2_len,
+ char_u *leader2_flags)
+{
+ int idx1 = 0, idx2 = 0;
+ char_u *p;
+ char_u *line1;
+ char_u *line2;
+
+ if (leader1_len == 0) {
+ return leader2_len == 0;
+ }
+
+ // If first leader has 'f' flag, the lines can be joined only if the
+ // second line does not have a leader.
+ // If first leader has 'e' flag, the lines can never be joined.
+ // If first leader has 's' flag, the lines can only be joined if there is
+ // some text after it and the second line has the 'm' flag.
+ if (leader1_flags != NULL) {
+ for (p = leader1_flags; *p && *p != ':'; p++) {
+ if (*p == COM_FIRST) {
+ return leader2_len == 0;
+ }
+ if (*p == COM_END) {
+ return false;
+ }
+ if (*p == COM_START) {
+ if (*(ml_get(lnum) + leader1_len) == NUL) {
+ return false;
+ }
+ if (leader2_flags == NULL || leader2_len == 0) {
+ return false;
+ }
+ for (p = leader2_flags; *p && *p != ':'; p++) {
+ if (*p == COM_MIDDLE) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+ }
+
+ // Get current line and next line, compare the leaders.
+ // The first line has to be saved, only one line can be locked at a time.
+ line1 = vim_strsave(ml_get(lnum));
+ for (idx1 = 0; ascii_iswhite(line1[idx1]); idx1++) {}
+ line2 = ml_get(lnum + 1);
+ for (idx2 = 0; idx2 < leader2_len; idx2++) {
+ if (!ascii_iswhite(line2[idx2])) {
+ if (line1[idx1++] != line2[idx2]) {
+ break;
+ }
+ } else {
+ while (ascii_iswhite(line1[idx1])) {
+ idx1++;
+ }
+ }
+ }
+ xfree(line1);
+
+ return idx2 == leader2_len && idx1 == leader1_len;
+}
+
+/// Used for auto-formatting.
+///
+/// @return true when a paragraph starts in line "lnum".
+/// false when the previous line is in the same paragraph.
+static bool paragraph_start(linenr_T lnum)
+{
+ char_u *p;
+ int leader_len = 0; // leader len of current line
+ char_u *leader_flags = NULL; // flags for leader of current line
+ int next_leader_len = 0; // leader len of next line
+ char_u *next_leader_flags = NULL; // flags for leader of next line
+
+ if (lnum <= 1) {
+ return true; // start of the file
+ }
+ p = ml_get(lnum - 1);
+ if (*p == NUL) {
+ return true; // after empty line
+ }
+ const bool do_comments = has_format_option(FO_Q_COMS); // format comments
+ if (fmt_check_par(lnum - 1, &leader_len, &leader_flags, do_comments)) {
+ return true; // after non-paragraph line
+ }
+
+ if (fmt_check_par(lnum, &next_leader_len, &next_leader_flags, do_comments)) {
+ return true; // "lnum" is not a paragraph line
+ }
+
+ if (has_format_option(FO_WHITE_PAR) && !ends_in_white(lnum - 1)) {
+ return true; // missing trailing space in previous line.
+ }
+ if (has_format_option(FO_Q_NUMBER) && (get_number_indent(lnum) > 0)) {
+ return true; // numbered item starts in "lnum".
+ }
+ if (!same_leader(lnum - 1, leader_len, leader_flags,
+ next_leader_len, next_leader_flags)) {
+ return true; // change of comment leader.
+ }
+ return false;
+}
+
+/// Called after inserting or deleting text: When 'formatoptions' includes the
+/// 'a' flag format from the current line until the end of the paragraph.
+/// Keep the cursor at the same position relative to the text.
+/// The caller must have saved the cursor line for undo, following ones will be
+/// saved here.
+///
+/// @param trailblank when true also format with trailing blank
+/// @param prev_line may start in previous line
+void auto_format(bool trailblank, bool prev_line)
+{
+ pos_T pos;
+ colnr_T len;
+ char_u *old;
+ char_u *new, *pnew;
+ int wasatend;
+ int cc;
+
+ if (!has_format_option(FO_AUTO)) {
+ return;
+ }
+
+ pos = curwin->w_cursor;
+ old = get_cursor_line_ptr();
+
+ // may remove added space
+ check_auto_format(false);
+
+ // Don't format in Insert mode when the cursor is on a trailing blank, the
+ // user might insert normal text next. Also skip formatting when "1" is
+ // in 'formatoptions' and there is a single character before the cursor.
+ // Otherwise the line would be broken and when typing another non-white
+ // next they are not joined back together.
+ wasatend = (pos.col == (colnr_T)STRLEN(old));
+ if (*old != NUL && !trailblank && wasatend) {
+ dec_cursor();
+ cc = gchar_cursor();
+ if (!WHITECHAR(cc) && curwin->w_cursor.col > 0
+ && has_format_option(FO_ONE_LETTER)) {
+ dec_cursor();
+ }
+ cc = gchar_cursor();
+ if (WHITECHAR(cc)) {
+ curwin->w_cursor = pos;
+ return;
+ }
+ curwin->w_cursor = pos;
+ }
+
+ // With the 'c' flag in 'formatoptions' and 't' missing: only format
+ // comments.
+ if (has_format_option(FO_WRAP_COMS) && !has_format_option(FO_WRAP)
+ && get_leader_len((char *)old, NULL, false, true) == 0) {
+ return;
+ }
+
+ // May start formatting in a previous line, so that after "x" a word is
+ // moved to the previous line if it fits there now. Only when this is not
+ // the start of a paragraph.
+ if (prev_line && !paragraph_start(curwin->w_cursor.lnum)) {
+ curwin->w_cursor.lnum--;
+ if (u_save_cursor() == FAIL) {
+ return;
+ }
+ }
+
+ // Do the formatting and restore the cursor position. "saved_cursor" will
+ // be adjusted for the text formatting.
+ saved_cursor = pos;
+ format_lines((linenr_T) - 1, false);
+ curwin->w_cursor = saved_cursor;
+ saved_cursor.lnum = 0;
+
+ if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {
+ // "cannot happen"
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ coladvance(MAXCOL);
+ } else {
+ check_cursor_col();
+ }
+
+ // Insert mode: If the cursor is now after the end of the line while it
+ // previously wasn't, the line was broken. Because of the rule above we
+ // need to add a space when 'w' is in 'formatoptions' to keep a paragraph
+ // formatted.
+ if (!wasatend && has_format_option(FO_WHITE_PAR)) {
+ new = get_cursor_line_ptr();
+ len = (colnr_T)STRLEN(new);
+ if (curwin->w_cursor.col == len) {
+ pnew = vim_strnsave(new, (size_t)len + 2);
+ pnew[len] = ' ';
+ pnew[len + 1] = NUL;
+ ml_replace(curwin->w_cursor.lnum, (char *)pnew, false);
+ // remove the space later
+ did_add_space = true;
+ } else {
+ // may remove added space
+ check_auto_format(false);
+ }
+ }
+
+ check_cursor();
+}
+
+/// When an extra space was added to continue a paragraph for auto-formatting,
+/// delete it now. The space must be under the cursor, just after the insert
+/// position.
+///
+/// @param end_insert true when ending Insert mode
+void check_auto_format(bool end_insert)
+{
+ int c = ' ';
+ int cc;
+
+ if (did_add_space) {
+ cc = gchar_cursor();
+ if (!WHITECHAR(cc)) {
+ // Somehow the space was removed already.
+ did_add_space = false;
+ } else {
+ if (!end_insert) {
+ inc_cursor();
+ c = gchar_cursor();
+ dec_cursor();
+ }
+ if (c != NUL) {
+ // The space is no longer at the end of the line, delete it.
+ del_char(false);
+ did_add_space = false;
+ }
+ }
+ }
+}
+
+/// Find out textwidth to be used for formatting:
+/// if 'textwidth' option is set, use it
+/// else if 'wrapmargin' option is set, use curwin->w_width_inner-'wrapmargin'
+/// if invalid value, use 0.
+/// Set default to window width (maximum 79) for "gq" operator.
+///
+/// @param ff force formatting (for "gq" command)
+int comp_textwidth(bool ff)
+{
+ int textwidth = (int)curbuf->b_p_tw;
+ if (textwidth == 0 && curbuf->b_p_wm) {
+ // The width is the window width minus 'wrapmargin' minus all the
+ // things that add to the margin.
+ textwidth = curwin->w_width_inner - (int)curbuf->b_p_wm;
+ if (cmdwin_type != 0) {
+ textwidth -= 1;
+ }
+ textwidth -= win_fdccol_count(curwin);
+ textwidth -= win_signcol_count(curwin);
+
+ if (curwin->w_p_nu || curwin->w_p_rnu) {
+ textwidth -= 8;
+ }
+ }
+ if (textwidth < 0) {
+ textwidth = 0;
+ }
+ if (ff && textwidth == 0) {
+ textwidth = curwin->w_width_inner - 1;
+ if (textwidth > 79) {
+ textwidth = 79;
+ }
+ }
+ return textwidth;
+}
+
+/// Implementation of the format operator 'gq'.
+///
+/// @param keep_cursor keep cursor on same text char
+void op_format(oparg_T *oap, bool keep_cursor)
+{
+ linenr_T old_line_count = curbuf->b_ml.ml_line_count;
+
+ // Place the cursor where the "gq" or "gw" command was given, so that "u"
+ // can put it back there.
+ curwin->w_cursor = oap->cursor_start;
+
+ if (u_save((linenr_T)(oap->start.lnum - 1),
+ (linenr_T)(oap->end.lnum + 1)) == FAIL) {
+ return;
+ }
+ curwin->w_cursor = oap->start;
+
+ if (oap->is_VIsual) {
+ // When there is no change: need to remove the Visual selection
+ redraw_curbuf_later(UPD_INVERTED);
+ }
+
+ if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ // Set '[ mark at the start of the formatted area
+ curbuf->b_op_start = oap->start;
+ }
+
+ // For "gw" remember the cursor position and put it back below (adjusted
+ // for joined and split lines).
+ if (keep_cursor) {
+ saved_cursor = oap->cursor_start;
+ }
+
+ format_lines((linenr_T)oap->line_count, keep_cursor);
+
+ // Leave the cursor at the first non-blank of the last formatted line.
+ // If the cursor was moved one line back (e.g. with "Q}") go to the next
+ // line, so "." will do the next lines.
+ if (oap->end_adjusted && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
+ curwin->w_cursor.lnum++;
+ }
+ beginline(BL_WHITE | BL_FIX);
+ old_line_count = curbuf->b_ml.ml_line_count - old_line_count;
+ msgmore(old_line_count);
+
+ if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ // put '] mark on the end of the formatted area
+ curbuf->b_op_end = curwin->w_cursor;
+ }
+
+ if (keep_cursor) {
+ curwin->w_cursor = saved_cursor;
+ saved_cursor.lnum = 0;
+
+ // formatting may have made the cursor position invalid
+ check_cursor();
+ }
+
+ if (oap->is_VIsual) {
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (wp->w_old_cursor_lnum != 0) {
+ // When lines have been inserted or deleted, adjust the end of
+ // the Visual area to be redrawn.
+ if (wp->w_old_cursor_lnum > wp->w_old_visual_lnum) {
+ wp->w_old_cursor_lnum += old_line_count;
+ } else {
+ wp->w_old_visual_lnum += old_line_count;
+ }
+ }
+ }
+ }
+}
+
+/// Implementation of the format operator 'gq' for when using 'formatexpr'.
+void op_formatexpr(oparg_T *oap)
+{
+ if (oap->is_VIsual) {
+ // When there is no change: need to remove the Visual selection
+ redraw_curbuf_later(UPD_INVERTED);
+ }
+
+ if (fex_format(oap->start.lnum, oap->line_count, NUL) != 0) {
+ // As documented: when 'formatexpr' returns non-zero fall back to
+ // internal formatting.
+ op_format(oap, false);
+ }
+}
+
+/// @param c character to be inserted
+int fex_format(linenr_T lnum, long count, int c)
+{
+ int use_sandbox = was_set_insecurely(curwin, "formatexpr", OPT_LOCAL);
+ int r;
+
+ // Set v:lnum to the first line number and v:count to the number of lines.
+ // Set v:char to the character to be inserted (can be NUL).
+ set_vim_var_nr(VV_LNUM, (varnumber_T)lnum);
+ set_vim_var_nr(VV_COUNT, (varnumber_T)count);
+ set_vim_var_char(c);
+
+ // Make a copy, the option could be changed while calling it.
+ char *fex = xstrdup(curbuf->b_p_fex);
+ // Evaluate the function.
+ if (use_sandbox) {
+ sandbox++;
+ }
+ r = (int)eval_to_number(fex);
+ if (use_sandbox) {
+ sandbox--;
+ }
+
+ set_vim_var_string(VV_CHAR, NULL, -1);
+ xfree(fex);
+
+ return r;
+}
+
+/// @param line_count number of lines to format, starting at the cursor position.
+/// when negative, format until the end of the paragraph.
+///
+/// Lines after the cursor line are saved for undo, caller must have saved the
+/// first line.
+///
+/// @param avoid_fex don't use 'formatexpr'
+void format_lines(linenr_T line_count, bool avoid_fex)
+{
+ bool is_not_par; // current line not part of parag.
+ bool next_is_not_par; // next line not part of paragraph
+ bool is_end_par; // at end of paragraph
+ bool prev_is_end_par = false; // prev. line not part of parag.
+ bool next_is_start_par = false;
+ int leader_len = 0; // leader len of current line
+ int next_leader_len; // leader len of next line
+ char_u *leader_flags = NULL; // flags for leader of current line
+ char_u *next_leader_flags = NULL; // flags for leader of next line
+ bool advance = true;
+ int second_indent = -1; // indent for second line (comment aware)
+ bool first_par_line = true;
+ int smd_save;
+ long count;
+ bool need_set_indent = true; // set indent of next paragraph
+ linenr_T first_line = curwin->w_cursor.lnum;
+ bool force_format = false;
+ const int old_State = State;
+
+ // length of a line to force formatting: 3 * 'tw'
+ const int max_len = comp_textwidth(true) * 3;
+
+ // check for 'q', '2' and '1' in 'formatoptions'
+ const bool do_comments = has_format_option(FO_Q_COMS); // format comments
+ int do_comments_list = 0; // format comments with 'n' or '2'
+ const bool do_second_indent = has_format_option(FO_Q_SECOND);
+ const bool do_number_indent = has_format_option(FO_Q_NUMBER);
+ const bool do_trail_white = has_format_option(FO_WHITE_PAR);
+
+ // Get info about the previous and current line.
+ if (curwin->w_cursor.lnum > 1) {
+ is_not_par = fmt_check_par(curwin->w_cursor.lnum - 1,
+ &leader_len, &leader_flags, do_comments);
+ } else {
+ is_not_par = true;
+ }
+ next_is_not_par = fmt_check_par(curwin->w_cursor.lnum,
+ &next_leader_len, &next_leader_flags, do_comments);
+ is_end_par = (is_not_par || next_is_not_par);
+ if (!is_end_par && do_trail_white) {
+ is_end_par = !ends_in_white(curwin->w_cursor.lnum - 1);
+ }
+
+ curwin->w_cursor.lnum--;
+ for (count = line_count; count != 0 && !got_int; count--) {
+ // Advance to next paragraph.
+ if (advance) {
+ curwin->w_cursor.lnum++;
+ prev_is_end_par = is_end_par;
+ is_not_par = next_is_not_par;
+ leader_len = next_leader_len;
+ leader_flags = next_leader_flags;
+ }
+
+ // The last line to be formatted.
+ if (count == 1 || curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count) {
+ next_is_not_par = true;
+ next_leader_len = 0;
+ next_leader_flags = NULL;
+ } else {
+ next_is_not_par = fmt_check_par(curwin->w_cursor.lnum + 1,
+ &next_leader_len, &next_leader_flags, do_comments);
+ if (do_number_indent) {
+ next_is_start_par =
+ (get_number_indent(curwin->w_cursor.lnum + 1) > 0);
+ }
+ }
+ advance = true;
+ is_end_par = (is_not_par || next_is_not_par || next_is_start_par);
+ if (!is_end_par && do_trail_white) {
+ is_end_par = !ends_in_white(curwin->w_cursor.lnum);
+ }
+
+ // Skip lines that are not in a paragraph.
+ if (is_not_par) {
+ if (line_count < 0) {
+ break;
+ }
+ } else {
+ // For the first line of a paragraph, check indent of second line.
+ // Don't do this for comments and empty lines.
+ if (first_par_line
+ && (do_second_indent || do_number_indent)
+ && prev_is_end_par
+ && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
+ if (do_second_indent && !LINEEMPTY(curwin->w_cursor.lnum + 1)) {
+ if (leader_len == 0 && next_leader_len == 0) {
+ // no comment found
+ second_indent =
+ get_indent_lnum(curwin->w_cursor.lnum + 1);
+ } else {
+ second_indent = next_leader_len;
+ do_comments_list = 1;
+ }
+ } else if (do_number_indent) {
+ if (leader_len == 0 && next_leader_len == 0) {
+ // no comment found
+ second_indent =
+ get_number_indent(curwin->w_cursor.lnum);
+ } else {
+ // get_number_indent() is now "comment aware"...
+ second_indent =
+ get_number_indent(curwin->w_cursor.lnum);
+ do_comments_list = 1;
+ }
+ }
+ }
+
+ // When the comment leader changes, it's the end of the paragraph.
+ if (curwin->w_cursor.lnum >= curbuf->b_ml.ml_line_count
+ || !same_leader(curwin->w_cursor.lnum,
+ leader_len, leader_flags,
+ next_leader_len,
+ next_leader_flags)) {
+ // Special case: If the next line starts with a line comment
+ // and this line has a line comment after some text, the
+ // paragraph doesn't really end.
+ if (next_leader_flags == NULL
+ || STRNCMP(next_leader_flags, "://", 3) != 0
+ || check_linecomment((char *)get_cursor_line_ptr()) == MAXCOL) {
+ is_end_par = true;
+ }
+ }
+
+ // If we have got to the end of a paragraph, or the line is
+ // getting long, format it.
+ if (is_end_par || force_format) {
+ if (need_set_indent) {
+ int indent = 0; // amount of indent needed
+
+ // Replace indent in first line of a paragraph with minimal
+ // number of tabs and spaces, according to current options.
+ // For the very first formatted line keep the current
+ // indent.
+ if (curwin->w_cursor.lnum == first_line) {
+ indent = get_indent();
+ } else if (curbuf->b_p_lisp) {
+ indent = get_lisp_indent();
+ } else {
+ if (cindent_on()) {
+ indent = *curbuf->b_p_inde != NUL ? get_expr_indent() : get_c_indent();
+ } else {
+ indent = get_indent();
+ }
+ }
+ (void)set_indent(indent, SIN_CHANGED);
+ }
+
+ // put cursor on last non-space
+ State = MODE_NORMAL; // don't go past end-of-line
+ coladvance(MAXCOL);
+ while (curwin->w_cursor.col && ascii_isspace(gchar_cursor())) {
+ dec_cursor();
+ }
+
+ // do the formatting, without 'showmode'
+ State = MODE_INSERT; // for open_line()
+ smd_save = p_smd;
+ p_smd = false;
+ insertchar(NUL, INSCHAR_FORMAT
+ + (do_comments ? INSCHAR_DO_COM : 0)
+ + (do_comments && do_comments_list ? INSCHAR_COM_LIST : 0)
+ + (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent);
+ State = old_State;
+ p_smd = smd_save;
+ second_indent = -1;
+ // at end of par.: need to set indent of next par.
+ need_set_indent = is_end_par;
+ if (is_end_par) {
+ // When called with a negative line count, break at the
+ // end of the paragraph.
+ if (line_count < 0) {
+ break;
+ }
+ first_par_line = true;
+ }
+ force_format = false;
+ }
+
+ // When still in same paragraph, join the lines together. But
+ // first delete the leader from the second line.
+ if (!is_end_par) {
+ advance = false;
+ curwin->w_cursor.lnum++;
+ curwin->w_cursor.col = 0;
+ if (line_count < 0 && u_save_cursor() == FAIL) {
+ break;
+ }
+ if (next_leader_len > 0) {
+ (void)del_bytes(next_leader_len, false, false);
+ mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L,
+ (long)-next_leader_len, 0);
+ } else if (second_indent > 0) { // the "leader" for FO_Q_SECOND
+ int indent = (int)getwhitecols_curline();
+
+ if (indent > 0) {
+ (void)del_bytes(indent, false, false);
+ mark_col_adjust(curwin->w_cursor.lnum,
+ (colnr_T)0, 0L, (long)-indent, 0);
+ }
+ }
+ curwin->w_cursor.lnum--;
+ if (do_join(2, true, false, false, false) == FAIL) {
+ beep_flush();
+ break;
+ }
+ first_par_line = false;
+ // If the line is getting long, format it next time
+ if (STRLEN(get_cursor_line_ptr()) > (size_t)max_len) {
+ force_format = true;
+ } else {
+ force_format = false;
+ }
+ }
+ }
+ line_breakcheck();
+ }
+}
diff --git a/src/nvim/textformat.h b/src/nvim/textformat.h
new file mode 100644
index 0000000000..3c918a028b
--- /dev/null
+++ b/src/nvim/textformat.h
@@ -0,0 +1,10 @@
+#ifndef NVIM_TEXTFORMAT_H
+#define NVIM_TEXTFORMAT_H
+
+#include "nvim/normal.h" // for oparg_T
+#include "nvim/pos.h" // for linenr_T
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "textformat.h.generated.h"
+#endif
+#endif // NVIM_TEXTFORMAT_H
diff --git a/src/nvim/textobject.c b/src/nvim/textobject.c
new file mode 100644
index 0000000000..02174edeb1
--- /dev/null
+++ b/src/nvim/textobject.c
@@ -0,0 +1,1742 @@
+// 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
+
+// textobject.c: functions for text objects
+
+#include <stdbool.h>
+
+#include "nvim/ascii.h"
+#include "nvim/cursor.h"
+#include "nvim/drawscreen.h"
+#include "nvim/edit.h"
+#include "nvim/eval/funcs.h"
+#include "nvim/fold.h"
+#include "nvim/globals.h"
+#include "nvim/indent.h"
+#include "nvim/mark.h"
+#include "nvim/mbyte.h"
+#include "nvim/memline.h"
+#include "nvim/normal.h"
+#include "nvim/pos.h"
+#include "nvim/search.h"
+#include "nvim/textformat.h"
+#include "nvim/textobject.h"
+#include "nvim/vim.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "textobject.c.generated.h"
+#endif
+
+/// Find the start of the next sentence, searching in the direction specified
+/// by the "dir" argument. The cursor is positioned on the start of the next
+/// sentence when found. If the next sentence is found, return OK. Return FAIL
+/// otherwise. See ":h sentence" for the precise definition of a "sentence"
+/// text object.
+int findsent(Direction dir, long count)
+{
+ pos_T pos, tpos;
+ int c;
+ int (*func)(pos_T *);
+ bool noskip = false; // do not skip blanks
+
+ pos = curwin->w_cursor;
+ if (dir == FORWARD) {
+ func = incl;
+ } else {
+ func = decl;
+ }
+
+ while (count--) {
+ const pos_T prev_pos = pos;
+
+ // if on an empty line, skip up to a non-empty line
+ if (gchar_pos(&pos) == NUL) {
+ do {
+ if ((*func)(&pos) == -1) {
+ break;
+ }
+ } while (gchar_pos(&pos) == NUL);
+ if (dir == FORWARD) {
+ goto found;
+ }
+ // if on the start of a paragraph or a section and searching forward,
+ // go to the next line
+ } else if (dir == FORWARD && pos.col == 0
+ && startPS(pos.lnum, NUL, false)) {
+ if (pos.lnum == curbuf->b_ml.ml_line_count) {
+ return FAIL;
+ }
+ pos.lnum++;
+ goto found;
+ } else if (dir == BACKWARD) {
+ decl(&pos);
+ }
+
+ // go back to the previous non-white non-punctuation character
+ bool found_dot = false;
+ while (c = gchar_pos(&pos), ascii_iswhite(c)
+ || vim_strchr(".!?)]\"'", c) != NULL) {
+ tpos = pos;
+ if (decl(&tpos) == -1 || (LINEEMPTY(tpos.lnum) && dir == FORWARD)) {
+ break;
+ }
+ if (found_dot) {
+ break;
+ }
+ if (vim_strchr(".!?", c) != NULL) {
+ found_dot = true;
+ }
+ if (vim_strchr(")]\"'", c) != NULL
+ && vim_strchr(".!?)]\"'", gchar_pos(&tpos)) == NULL) {
+ break;
+ }
+ decl(&pos);
+ }
+
+ // remember the line where the search started
+ const int startlnum = pos.lnum;
+ const bool cpo_J = vim_strchr(p_cpo, CPO_ENDOFSENT) != NULL;
+
+ for (;;) { // find end of sentence
+ c = gchar_pos(&pos);
+ if (c == NUL || (pos.col == 0 && startPS(pos.lnum, NUL, false))) {
+ if (dir == BACKWARD && pos.lnum != startlnum) {
+ pos.lnum++;
+ }
+ break;
+ }
+ if (c == '.' || c == '!' || c == '?') {
+ tpos = pos;
+ do {
+ if ((c = inc(&tpos)) == -1) {
+ break;
+ }
+ } while (vim_strchr(")]\"'", c = gchar_pos(&tpos))
+ != NULL);
+ if (c == -1 || (!cpo_J && (c == ' ' || c == '\t')) || c == NUL
+ || (cpo_J && (c == ' ' && inc(&tpos) >= 0
+ && gchar_pos(&tpos) == ' '))) {
+ pos = tpos;
+ if (gchar_pos(&pos) == NUL) { // skip NUL at EOL
+ inc(&pos);
+ }
+ break;
+ }
+ }
+ if ((*func)(&pos) == -1) {
+ if (count) {
+ return FAIL;
+ }
+ noskip = true;
+ break;
+ }
+ }
+found:
+ // skip white space
+ while (!noskip && ((c = gchar_pos(&pos)) == ' ' || c == '\t')) {
+ if (incl(&pos) == -1) {
+ break;
+ }
+ }
+
+ if (equalpos(prev_pos, pos)) {
+ // didn't actually move, advance one character and try again
+ if ((*func)(&pos) == -1) {
+ if (count) {
+ return FAIL;
+ }
+ break;
+ }
+ count++;
+ }
+ }
+
+ setpcmark();
+ curwin->w_cursor = pos;
+ return OK;
+}
+
+/// Find the next paragraph or section in direction 'dir'.
+/// Paragraphs are currently supposed to be separated by empty lines.
+/// If 'what' is NUL we go to the next paragraph.
+/// If 'what' is '{' or '}' we go to the next section.
+/// If 'both' is true also stop at '}'.
+///
+/// @param pincl Return: true if last char is to be included
+///
+/// @return true if the next paragraph or section was found.
+bool findpar(bool *pincl, int dir, long count, int what, bool both)
+{
+ linenr_T curr;
+ bool did_skip; // true after separating lines have been skipped
+ bool first; // true on first line
+ linenr_T fold_first; // first line of a closed fold
+ linenr_T fold_last; // last line of a closed fold
+ bool fold_skipped; // true if a closed fold was skipped this
+ // iteration
+
+ curr = curwin->w_cursor.lnum;
+
+ while (count--) {
+ did_skip = false;
+ for (first = true;; first = false) {
+ if (*ml_get(curr) != NUL) {
+ did_skip = true;
+ }
+
+ // skip folded lines
+ fold_skipped = false;
+ if (first && hasFolding(curr, &fold_first, &fold_last)) {
+ curr = ((dir > 0) ? fold_last : fold_first) + dir;
+ fold_skipped = true;
+ }
+
+ if (!first && did_skip && startPS(curr, what, both)) {
+ break;
+ }
+
+ if (fold_skipped) {
+ curr -= dir;
+ }
+ if ((curr += dir) < 1 || curr > curbuf->b_ml.ml_line_count) {
+ if (count) {
+ return false;
+ }
+ curr -= dir;
+ break;
+ }
+ }
+ }
+ setpcmark();
+ if (both && *ml_get(curr) == '}') { // include line with '}'
+ curr++;
+ }
+ curwin->w_cursor.lnum = curr;
+ if (curr == curbuf->b_ml.ml_line_count && what != '}') {
+ char_u *line = ml_get(curr);
+
+ // Put the cursor on the last character in the last line and make the
+ // motion inclusive.
+ if ((curwin->w_cursor.col = (colnr_T)STRLEN(line)) != 0) {
+ curwin->w_cursor.col--;
+ curwin->w_cursor.col -= utf_head_off(line, line + curwin->w_cursor.col);
+ *pincl = true;
+ }
+ } else {
+ curwin->w_cursor.col = 0;
+ }
+ return true;
+}
+
+/// check if the string 's' is a nroff macro that is in option 'opt'
+static bool inmacro(char_u *opt, char_u *s)
+{
+ char_u *macro;
+
+ for (macro = opt; macro[0]; macro++) {
+ // Accept two characters in the option being equal to two characters
+ // in the line. A space in the option matches with a space in the
+ // line or the line having ended.
+ if ((macro[0] == s[0]
+ || (macro[0] == ' '
+ && (s[0] == NUL || s[0] == ' ')))
+ && (macro[1] == s[1]
+ || ((macro[1] == NUL || macro[1] == ' ')
+ && (s[0] == NUL || s[1] == NUL || s[1] == ' ')))) {
+ break;
+ }
+ macro++;
+ if (macro[0] == NUL) {
+ break;
+ }
+ }
+ return macro[0] != NUL;
+}
+
+/// startPS: return true if line 'lnum' is the start of a section or paragraph.
+/// If 'para' is '{' or '}' only check for sections.
+/// If 'both' is true also stop at '}'
+bool startPS(linenr_T lnum, int para, bool both)
+{
+ char_u *s;
+
+ s = ml_get(lnum);
+ if (*s == para || *s == '\f' || (both && *s == '}')) {
+ return true;
+ }
+ if (*s == '.' && (inmacro((char_u *)p_sections, s + 1)
+ || (!para && inmacro(p_para, s + 1)))) {
+ return true;
+ }
+ return false;
+}
+
+// The following routines do the word searches performed by the 'w', 'W',
+// 'b', 'B', 'e', and 'E' commands.
+
+// To perform these searches, characters are placed into one of three
+// classes, and transitions between classes determine word boundaries.
+//
+// The classes are:
+//
+// 0 - white space
+// 1 - punctuation
+// 2 or higher - keyword characters (letters, digits and underscore)
+
+static bool cls_bigword; ///< true for "W", "B" or "E"
+
+/// cls() - returns the class of character at curwin->w_cursor
+///
+/// If a 'W', 'B', or 'E' motion is being done (cls_bigword == true), chars
+/// from class 2 and higher are reported as class 1 since only white space
+/// boundaries are of interest.
+static int cls(void)
+{
+ int c;
+
+ c = gchar_cursor();
+ if (c == ' ' || c == '\t' || c == NUL) {
+ return 0;
+ }
+
+ c = utf_class(c);
+
+ // If cls_bigword is true, report all non-blanks as class 1.
+ if (c != 0 && cls_bigword) {
+ return 1;
+ }
+ return c;
+}
+
+/// fwd_word(count, type, eol) - move forward one word
+///
+/// @return FAIL if the cursor was already at the end of the file.
+/// If eol is true, last word stops at end of line (for operators).
+///
+/// @param bigword "W", "E" or "B"
+int fwd_word(long count, bool bigword, bool eol)
+{
+ int sclass; // starting class
+ int i;
+ int last_line;
+
+ curwin->w_cursor.coladd = 0;
+ cls_bigword = bigword;
+ while (--count >= 0) {
+ // When inside a range of folded lines, move to the last char of the
+ // last line.
+ if (hasFolding(curwin->w_cursor.lnum, NULL, &curwin->w_cursor.lnum)) {
+ coladvance(MAXCOL);
+ }
+ sclass = cls();
+
+ // We always move at least one character, unless on the last
+ // character in the buffer.
+ last_line = (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count);
+ i = inc_cursor();
+ if (i == -1 || (i >= 1 && last_line)) { // started at last char in file
+ return FAIL;
+ }
+ if (i >= 1 && eol && count == 0) { // started at last char in line
+ return OK;
+ }
+
+ // Go one char past end of current word (if any)
+ if (sclass != 0) {
+ while (cls() == sclass) {
+ i = inc_cursor();
+ if (i == -1 || (i >= 1 && eol && count == 0)) {
+ return OK;
+ }
+ }
+ }
+
+ // go to next non-white
+ while (cls() == 0) {
+ // We'll stop if we land on a blank line
+ if (curwin->w_cursor.col == 0 && *get_cursor_line_ptr() == NUL) {
+ break;
+ }
+
+ i = inc_cursor();
+ if (i == -1 || (i >= 1 && eol && count == 0)) {
+ return OK;
+ }
+ }
+ }
+ return OK;
+}
+
+/// bck_word() - move backward 'count' words
+///
+/// If stop is true and we are already on the start of a word, move one less.
+///
+/// Returns FAIL if top of the file was reached.
+int bck_word(long count, bool bigword, bool stop)
+{
+ int sclass; // starting class
+
+ curwin->w_cursor.coladd = 0;
+ cls_bigword = bigword;
+ while (--count >= 0) {
+ // When inside a range of folded lines, move to the first char of the
+ // first line.
+ if (hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum, NULL)) {
+ curwin->w_cursor.col = 0;
+ }
+ sclass = cls();
+ if (dec_cursor() == -1) { // started at start of file
+ return FAIL;
+ }
+
+ if (!stop || sclass == cls() || sclass == 0) {
+ // Skip white space before the word.
+ // Stop on an empty line.
+ while (cls() == 0) {
+ if (curwin->w_cursor.col == 0
+ && LINEEMPTY(curwin->w_cursor.lnum)) {
+ goto finished;
+ }
+ if (dec_cursor() == -1) { // hit start of file, stop here
+ return OK;
+ }
+ }
+
+ // Move backward to start of this word.
+ if (skip_chars(cls(), BACKWARD)) {
+ return OK;
+ }
+ }
+
+ inc_cursor(); // overshot - forward one
+finished:
+ stop = false;
+ }
+ return OK;
+}
+
+/// end_word() - move to the end of the word
+///
+/// There is an apparent bug in the 'e' motion of the real vi. At least on the
+/// System V Release 3 version for the 80386. Unlike 'b' and 'w', the 'e'
+/// motion crosses blank lines. When the real vi crosses a blank line in an
+/// 'e' motion, the cursor is placed on the FIRST character of the next
+/// non-blank line. The 'E' command, however, works correctly. Since this
+/// appears to be a bug, I have not duplicated it here.
+///
+/// Returns FAIL if end of the file was reached.
+///
+/// If stop is true and we are already on the end of a word, move one less.
+/// If empty is true stop on an empty line.
+int end_word(long count, bool bigword, bool stop, bool empty)
+{
+ int sclass; // starting class
+
+ curwin->w_cursor.coladd = 0;
+ cls_bigword = bigword;
+ while (--count >= 0) {
+ // When inside a range of folded lines, move to the last char of the
+ // last line.
+ if (hasFolding(curwin->w_cursor.lnum, NULL, &curwin->w_cursor.lnum)) {
+ coladvance(MAXCOL);
+ }
+ sclass = cls();
+ if (inc_cursor() == -1) {
+ return FAIL;
+ }
+
+ // If we're in the middle of a word, we just have to move to the end
+ // of it.
+ if (cls() == sclass && sclass != 0) {
+ // Move forward to end of the current word
+ if (skip_chars(sclass, FORWARD)) {
+ return FAIL;
+ }
+ } else if (!stop || sclass == 0) {
+ // We were at the end of a word. Go to the end of the next word.
+ // First skip white space, if 'empty' is true, stop at empty line.
+ while (cls() == 0) {
+ if (empty && curwin->w_cursor.col == 0
+ && LINEEMPTY(curwin->w_cursor.lnum)) {
+ goto finished;
+ }
+ if (inc_cursor() == -1) { // hit end of file, stop here
+ return FAIL;
+ }
+ }
+
+ // Move forward to the end of this word.
+ if (skip_chars(cls(), FORWARD)) {
+ return FAIL;
+ }
+ }
+ dec_cursor(); // overshot - one char backward
+finished:
+ stop = false; // we move only one word less
+ }
+ return OK;
+}
+
+/// Move back to the end of the word.
+///
+/// @param bigword true for "B"
+/// @param eol if true, then stop at end of line.
+///
+/// @return FAIL if start of the file was reached.
+int bckend_word(long count, bool bigword, bool eol)
+{
+ int sclass; // starting class
+ int i;
+
+ curwin->w_cursor.coladd = 0;
+ cls_bigword = bigword;
+ while (--count >= 0) {
+ sclass = cls();
+ if ((i = dec_cursor()) == -1) {
+ return FAIL;
+ }
+ if (eol && i == 1) {
+ return OK;
+ }
+
+ // Move backward to before the start of this word.
+ if (sclass != 0) {
+ while (cls() == sclass) {
+ if ((i = dec_cursor()) == -1 || (eol && i == 1)) {
+ return OK;
+ }
+ }
+ }
+
+ // Move backward to end of the previous word
+ while (cls() == 0) {
+ if (curwin->w_cursor.col == 0 && LINEEMPTY(curwin->w_cursor.lnum)) {
+ break;
+ }
+ if ((i = dec_cursor()) == -1 || (eol && i == 1)) {
+ return OK;
+ }
+ }
+ }
+ return OK;
+}
+
+/// Skip a row of characters of the same class.
+///
+/// @return true when end-of-file reached, false otherwise.
+static bool skip_chars(int cclass, int dir)
+{
+ while (cls() == cclass) {
+ if ((dir == FORWARD ? inc_cursor() : dec_cursor()) == -1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/// Go back to the start of the word or the start of white space
+static void back_in_line(void)
+{
+ int sclass; // starting class
+
+ sclass = cls();
+ for (;;) {
+ if (curwin->w_cursor.col == 0) { // stop at start of line
+ break;
+ }
+ dec_cursor();
+ if (cls() != sclass) { // stop at start of word
+ inc_cursor();
+ break;
+ }
+ }
+}
+
+static void find_first_blank(pos_T *posp)
+{
+ int c;
+
+ while (decl(posp) != -1) {
+ c = gchar_pos(posp);
+ if (!ascii_iswhite(c)) {
+ incl(posp);
+ break;
+ }
+ }
+}
+
+/// Skip count/2 sentences and count/2 separating white spaces.
+///
+/// @param at_start_sent cursor is at start of sentence
+static void findsent_forward(long count, bool at_start_sent)
+{
+ while (count--) {
+ findsent(FORWARD, 1L);
+ if (at_start_sent) {
+ find_first_blank(&curwin->w_cursor);
+ }
+ if (count == 0 || at_start_sent) {
+ decl(&curwin->w_cursor);
+ }
+ at_start_sent = !at_start_sent;
+ }
+}
+
+/// Find word under cursor, cursor at end.
+/// Used while an operator is pending, and in Visual mode.
+///
+/// @param include true: include word and white space
+/// @param bigword false == word, true == WORD
+int current_word(oparg_T *oap, long count, bool include, bool bigword)
+{
+ pos_T start_pos;
+ pos_T pos;
+ bool inclusive = true;
+ int include_white = false;
+
+ cls_bigword = bigword;
+ clearpos(&start_pos);
+
+ // Correct cursor when 'selection' is exclusive
+ if (VIsual_active && *p_sel == 'e' && lt(VIsual, curwin->w_cursor)) {
+ dec_cursor();
+ }
+
+ // When Visual mode is not active, or when the VIsual area is only one
+ // character, select the word and/or white space under the cursor.
+ if (!VIsual_active || equalpos(curwin->w_cursor, VIsual)) {
+ // Go to start of current word or white space.
+ back_in_line();
+ start_pos = curwin->w_cursor;
+
+ // If the start is on white space, and white space should be included
+ // (" word"), or start is not on white space, and white space should
+ // not be included ("word"), find end of word.
+ if ((cls() == 0) == include) {
+ if (end_word(1L, bigword, true, true) == FAIL) {
+ return FAIL;
+ }
+ } else {
+ // If the start is not on white space, and white space should be
+ // included ("word "), or start is on white space and white
+ // space should not be included (" "), find start of word.
+ // If we end up in the first column of the next line (single char
+ // word) back up to end of the line.
+ fwd_word(1L, bigword, true);
+ if (curwin->w_cursor.col == 0) {
+ decl(&curwin->w_cursor);
+ } else {
+ oneleft();
+ }
+
+ if (include) {
+ include_white = true;
+ }
+ }
+
+ if (VIsual_active) {
+ // should do something when inclusive == false !
+ VIsual = start_pos;
+ redraw_curbuf_later(UPD_INVERTED); // update the inversion
+ } else {
+ oap->start = start_pos;
+ oap->motion_type = kMTCharWise;
+ }
+ count--;
+ }
+
+ // When count is still > 0, extend with more objects.
+ while (count > 0) {
+ inclusive = true;
+ if (VIsual_active && lt(curwin->w_cursor, VIsual)) {
+ // In Visual mode, with cursor at start: move cursor back.
+ if (decl(&curwin->w_cursor) == -1) {
+ return FAIL;
+ }
+ if (include != (cls() != 0)) {
+ if (bck_word(1L, bigword, true) == FAIL) {
+ return FAIL;
+ }
+ } else {
+ if (bckend_word(1L, bigword, true) == FAIL) {
+ return FAIL;
+ }
+ (void)incl(&curwin->w_cursor);
+ }
+ } else {
+ // Move cursor forward one word and/or white area.
+ if (incl(&curwin->w_cursor) == -1) {
+ return FAIL;
+ }
+ if (include != (cls() == 0)) {
+ if (fwd_word(1L, bigword, true) == FAIL && count > 1) {
+ return FAIL;
+ }
+ // If end is just past a new-line, we don't want to include
+ // the first character on the line.
+ // Put cursor on last char of white.
+ if (oneleft() == FAIL) {
+ inclusive = false;
+ }
+ } else {
+ if (end_word(1L, bigword, true, true) == FAIL) {
+ return FAIL;
+ }
+ }
+ }
+ count--;
+ }
+
+ if (include_white && (cls() != 0
+ || (curwin->w_cursor.col == 0 && !inclusive))) {
+ // If we don't include white space at the end, move the start
+ // to include some white space there. This makes "daw" work
+ // better on the last word in a sentence (and "2daw" on last-but-one
+ // word). Also when "2daw" deletes "word." at the end of the line
+ // (cursor is at start of next line).
+ // But don't delete white space at start of line (indent).
+ pos = curwin->w_cursor; // save cursor position
+ curwin->w_cursor = start_pos;
+ if (oneleft() == OK) {
+ back_in_line();
+ if (cls() == 0 && curwin->w_cursor.col > 0) {
+ if (VIsual_active) {
+ VIsual = curwin->w_cursor;
+ } else {
+ oap->start = curwin->w_cursor;
+ }
+ }
+ }
+ curwin->w_cursor = pos; // put cursor back at end
+ }
+
+ if (VIsual_active) {
+ if (*p_sel == 'e' && inclusive && ltoreq(VIsual, curwin->w_cursor)) {
+ inc_cursor();
+ }
+ if (VIsual_mode == 'V') {
+ VIsual_mode = 'v';
+ redraw_cmdline = true; // show mode later
+ }
+ } else {
+ oap->inclusive = inclusive;
+ }
+
+ return OK;
+}
+
+/// Find sentence(s) under the cursor, cursor at end.
+/// When Visual active, extend it by one or more sentences.
+int current_sent(oparg_T *oap, long count, bool include)
+{
+ pos_T start_pos;
+ pos_T pos;
+ bool start_blank;
+ int c;
+ bool at_start_sent;
+ long ncount;
+
+ start_pos = curwin->w_cursor;
+ pos = start_pos;
+ findsent(FORWARD, 1L); // Find start of next sentence.
+
+ // When the Visual area is bigger than one character: Extend it.
+ if (VIsual_active && !equalpos(start_pos, VIsual)) {
+extend:
+ if (lt(start_pos, VIsual)) {
+ // Cursor at start of Visual area.
+ // Find out where we are:
+ // - in the white space before a sentence
+ // - in a sentence or just after it
+ // - at the start of a sentence
+ at_start_sent = true;
+ decl(&pos);
+ while (lt(pos, curwin->w_cursor)) {
+ c = gchar_pos(&pos);
+ if (!ascii_iswhite(c)) {
+ at_start_sent = false;
+ break;
+ }
+ incl(&pos);
+ }
+ if (!at_start_sent) {
+ findsent(BACKWARD, 1L);
+ if (equalpos(curwin->w_cursor, start_pos)) {
+ at_start_sent = true; // exactly at start of sentence
+ } else {
+ // inside a sentence, go to its end (start of next)
+ findsent(FORWARD, 1L);
+ }
+ }
+ if (include) { // "as" gets twice as much as "is"
+ count *= 2;
+ }
+ while (count--) {
+ if (at_start_sent) {
+ find_first_blank(&curwin->w_cursor);
+ }
+ c = gchar_cursor();
+ if (!at_start_sent || (!include && !ascii_iswhite(c))) {
+ findsent(BACKWARD, 1L);
+ }
+ at_start_sent = !at_start_sent;
+ }
+ } else {
+ // Cursor at end of Visual area.
+ // Find out where we are:
+ // - just before a sentence
+ // - just before or in the white space before a sentence
+ // - in a sentence
+ incl(&pos);
+ at_start_sent = true;
+ if (!equalpos(pos, curwin->w_cursor)) { // not just before a sentence
+ at_start_sent = false;
+ while (lt(pos, curwin->w_cursor)) {
+ c = gchar_pos(&pos);
+ if (!ascii_iswhite(c)) {
+ at_start_sent = true;
+ break;
+ }
+ incl(&pos);
+ }
+ if (at_start_sent) { // in the sentence
+ findsent(BACKWARD, 1L);
+ } else { // in/before white before a sentence
+ curwin->w_cursor = start_pos;
+ }
+ }
+
+ if (include) { // "as" gets twice as much as "is"
+ count *= 2;
+ }
+ findsent_forward(count, at_start_sent);
+ if (*p_sel == 'e') {
+ curwin->w_cursor.col++;
+ }
+ }
+ return OK;
+ }
+
+ // If the cursor started on a blank, check if it is just before the start
+ // of the next sentence.
+ while (c = gchar_pos(&pos), ascii_iswhite(c)) {
+ incl(&pos);
+ }
+ if (equalpos(pos, curwin->w_cursor)) {
+ start_blank = true;
+ find_first_blank(&start_pos); // go back to first blank
+ } else {
+ start_blank = false;
+ findsent(BACKWARD, 1L);
+ start_pos = curwin->w_cursor;
+ }
+ if (include) {
+ ncount = count * 2;
+ } else {
+ ncount = count;
+ if (start_blank) {
+ ncount--;
+ }
+ }
+ if (ncount > 0) {
+ findsent_forward(ncount, true);
+ } else {
+ decl(&curwin->w_cursor);
+ }
+
+ if (include) {
+ // If the blank in front of the sentence is included, exclude the
+ // blanks at the end of the sentence, go back to the first blank.
+ // If there are no trailing blanks, try to include leading blanks.
+ if (start_blank) {
+ find_first_blank(&curwin->w_cursor);
+ c = gchar_pos(&curwin->w_cursor);
+ if (ascii_iswhite(c)) {
+ decl(&curwin->w_cursor);
+ }
+ } else if (c = gchar_cursor(), !ascii_iswhite(c)) {
+ find_first_blank(&start_pos);
+ }
+ }
+
+ if (VIsual_active) {
+ // Avoid getting stuck with "is" on a single space before a sentence.
+ if (equalpos(start_pos, curwin->w_cursor)) {
+ goto extend;
+ }
+ if (*p_sel == 'e') {
+ curwin->w_cursor.col++;
+ }
+ VIsual = start_pos;
+ VIsual_mode = 'v';
+ redraw_cmdline = true; // show mode later
+ redraw_curbuf_later(UPD_INVERTED); // update the inversion
+ } else {
+ // include a newline after the sentence, if there is one
+ if (incl(&curwin->w_cursor) == -1) {
+ oap->inclusive = true;
+ } else {
+ oap->inclusive = false;
+ }
+ oap->start = start_pos;
+ oap->motion_type = kMTCharWise;
+ }
+ return OK;
+}
+
+/// Find block under the cursor, cursor at end.
+/// "what" and "other" are two matching parenthesis/brace/etc.
+///
+/// @param include true == include white space
+/// @param what '(', '{', etc.
+/// @param other ')', '}', etc.
+int current_block(oparg_T *oap, long count, bool include, int what, int other)
+{
+ pos_T old_pos;
+ pos_T *pos = NULL;
+ pos_T start_pos;
+ pos_T *end_pos;
+ pos_T old_start, old_end;
+ char *save_cpo;
+ bool sol = false; // '{' at start of line
+
+ old_pos = curwin->w_cursor;
+ old_end = curwin->w_cursor; // remember where we started
+ old_start = old_end;
+
+ // If we start on '(', '{', ')', '}', etc., use the whole block inclusive.
+ if (!VIsual_active || equalpos(VIsual, curwin->w_cursor)) {
+ setpcmark();
+ if (what == '{') { // ignore indent
+ while (inindent(1)) {
+ if (inc_cursor() != 0) {
+ break;
+ }
+ }
+ }
+ if (gchar_cursor() == what) {
+ // cursor on '(' or '{', move cursor just after it
+ curwin->w_cursor.col++;
+ }
+ } else if (lt(VIsual, curwin->w_cursor)) {
+ old_start = VIsual;
+ curwin->w_cursor = VIsual; // cursor at low end of Visual
+ } else {
+ old_end = VIsual;
+ }
+
+ // Search backwards for unclosed '(', '{', etc..
+ // Put this position in start_pos.
+ // Ignore quotes here. Keep the "M" flag in 'cpo', as that is what the
+ // user wants.
+ save_cpo = p_cpo;
+ p_cpo = vim_strchr(p_cpo, CPO_MATCHBSL) != NULL ? "%M" : "%";
+ if ((pos = findmatch(NULL, what)) != NULL) {
+ while (count-- > 0) {
+ if ((pos = findmatch(NULL, what)) == NULL) {
+ break;
+ }
+ curwin->w_cursor = *pos;
+ start_pos = *pos; // the findmatch for end_pos will overwrite *pos
+ }
+ } else {
+ while (count-- > 0) {
+ if ((pos = findmatchlimit(NULL, what, FM_FORWARD, 0)) == NULL) {
+ break;
+ }
+ curwin->w_cursor = *pos;
+ start_pos = *pos; // the findmatch for end_pos will overwrite *pos
+ }
+ }
+ p_cpo = save_cpo;
+
+ // Search for matching ')', '}', etc.
+ // Put this position in curwin->w_cursor.
+ if (pos == NULL || (end_pos = findmatch(NULL, other)) == NULL) {
+ curwin->w_cursor = old_pos;
+ return FAIL;
+ }
+ curwin->w_cursor = *end_pos;
+
+ // Try to exclude the '(', '{', ')', '}', etc. when "include" is false.
+ // If the ending '}', ')' or ']' is only preceded by indent, skip that
+ // indent. But only if the resulting area is not smaller than what we
+ // started with.
+ while (!include) {
+ incl(&start_pos);
+ sol = (curwin->w_cursor.col == 0);
+ decl(&curwin->w_cursor);
+ while (inindent(1)) {
+ sol = true;
+ if (decl(&curwin->w_cursor) != 0) {
+ break;
+ }
+ }
+
+ // In Visual mode, when the resulting area is not bigger than what we
+ // started with, extend it to the next block, and then exclude again.
+ // Don't try to expand the area if the area is empty.
+ if (!lt(start_pos, old_start) && !lt(old_end, curwin->w_cursor)
+ && !equalpos(start_pos, curwin->w_cursor)
+ && VIsual_active) {
+ curwin->w_cursor = old_start;
+ decl(&curwin->w_cursor);
+ if ((pos = findmatch(NULL, what)) == NULL) {
+ curwin->w_cursor = old_pos;
+ return FAIL;
+ }
+ start_pos = *pos;
+ curwin->w_cursor = *pos;
+ if ((end_pos = findmatch(NULL, other)) == NULL) {
+ curwin->w_cursor = old_pos;
+ return FAIL;
+ }
+ curwin->w_cursor = *end_pos;
+ } else {
+ break;
+ }
+ }
+
+ if (VIsual_active) {
+ if (*p_sel == 'e') {
+ inc(&curwin->w_cursor);
+ }
+ if (sol && gchar_cursor() != NUL) {
+ inc(&curwin->w_cursor); // include the line break
+ }
+ VIsual = start_pos;
+ VIsual_mode = 'v';
+ redraw_curbuf_later(UPD_INVERTED); // update the inversion
+ showmode();
+ } else {
+ oap->start = start_pos;
+ oap->motion_type = kMTCharWise;
+ oap->inclusive = false;
+ if (sol) {
+ incl(&curwin->w_cursor);
+ } else if (ltoreq(start_pos, curwin->w_cursor)) {
+ // Include the character under the cursor.
+ oap->inclusive = true;
+ } else {
+ // End is before the start (no text in between <>, [], etc.): don't
+ // operate on any text.
+ curwin->w_cursor = start_pos;
+ }
+ }
+
+ return OK;
+}
+
+/// @param end_tag when true, return true if the cursor is on "</aaa>".
+///
+/// @return true if the cursor is on a "<aaa>" tag. Ignore "<aaa/>".
+static bool in_html_tag(bool end_tag)
+{
+ char_u *line = get_cursor_line_ptr();
+ char_u *p;
+ int c;
+ int lc = NUL;
+ pos_T pos;
+
+ for (p = line + curwin->w_cursor.col; p > line;) {
+ if (*p == '<') { // find '<' under/before cursor
+ break;
+ }
+ MB_PTR_BACK(line, p);
+ if (*p == '>') { // find '>' before cursor
+ break;
+ }
+ }
+ if (*p != '<') {
+ return false;
+ }
+
+ pos.lnum = curwin->w_cursor.lnum;
+ pos.col = (colnr_T)(p - line);
+
+ MB_PTR_ADV(p);
+ if (end_tag) {
+ // check that there is a '/' after the '<'
+ return *p == '/';
+ }
+
+ // check that there is no '/' after the '<'
+ if (*p == '/') {
+ return false;
+ }
+
+ // check that the matching '>' is not preceded by '/'
+ for (;;) {
+ if (inc(&pos) < 0) {
+ return false;
+ }
+ c = *ml_get_pos(&pos);
+ if (c == '>') {
+ break;
+ }
+ lc = c;
+ }
+ return lc != '/';
+}
+
+/// Find tag block under the cursor, cursor at end.
+///
+/// @param include true == include white space
+int current_tagblock(oparg_T *oap, long count_arg, bool include)
+{
+ long count = count_arg;
+ pos_T old_pos;
+ pos_T start_pos;
+ pos_T end_pos;
+ pos_T old_start, old_end;
+ char_u *p;
+ char_u *cp;
+ int len;
+ bool do_include = include;
+ bool save_p_ws = p_ws;
+ int retval = FAIL;
+ int is_inclusive = true;
+
+ p_ws = false;
+
+ old_pos = curwin->w_cursor;
+ old_end = curwin->w_cursor; // remember where we started
+ old_start = old_end;
+ if (!VIsual_active || *p_sel == 'e') {
+ decl(&old_end); // old_end is inclusive
+ }
+
+ // If we start on "<aaa>" select that block.
+ if (!VIsual_active || equalpos(VIsual, curwin->w_cursor)) {
+ setpcmark();
+
+ // ignore indent
+ while (inindent(1)) {
+ if (inc_cursor() != 0) {
+ break;
+ }
+ }
+
+ if (in_html_tag(false)) {
+ // cursor on start tag, move to its '>'
+ while (*get_cursor_pos_ptr() != '>') {
+ if (inc_cursor() < 0) {
+ break;
+ }
+ }
+ } else if (in_html_tag(true)) {
+ // cursor on end tag, move to just before it
+ while (*get_cursor_pos_ptr() != '<') {
+ if (dec_cursor() < 0) {
+ break;
+ }
+ }
+ dec_cursor();
+ old_end = curwin->w_cursor;
+ }
+ } else if (lt(VIsual, curwin->w_cursor)) {
+ old_start = VIsual;
+ curwin->w_cursor = VIsual; // cursor at low end of Visual
+ } else {
+ old_end = VIsual;
+ }
+
+again:
+ // Search backwards for unclosed "<aaa>".
+ // Put this position in start_pos.
+ for (long n = 0; n < count; n++) {
+ if (do_searchpair("<[^ \t>/!]\\+\\%(\\_s\\_[^>]\\{-}[^/]>\\|$\\|\\_s\\=>\\)",
+ "",
+ "</[^>]*>", BACKWARD, NULL, 0,
+ NULL, (linenr_T)0, 0L) <= 0) {
+ curwin->w_cursor = old_pos;
+ goto theend;
+ }
+ }
+ start_pos = curwin->w_cursor;
+
+ // Search for matching "</aaa>". First isolate the "aaa".
+ inc_cursor();
+ p = get_cursor_pos_ptr();
+ for (cp = p;
+ *cp != NUL && *cp != '>' && !ascii_iswhite(*cp);
+ MB_PTR_ADV(cp)) {}
+ len = (int)(cp - p);
+ if (len == 0) {
+ curwin->w_cursor = old_pos;
+ goto theend;
+ }
+ const size_t spat_len = (size_t)len + 39;
+ char *const spat = xmalloc(spat_len);
+ const size_t epat_len = (size_t)len + 9;
+ char *const epat = xmalloc(epat_len);
+ snprintf(spat, spat_len,
+ "<%.*s\\>\\%%(\\_s\\_[^>]\\{-}\\_[^/]>\\|\\_s\\?>\\)\\c", len, p);
+ snprintf(epat, epat_len, "</%.*s>\\c", len, p);
+
+ const int r = (int)do_searchpair(spat, "", epat, FORWARD, NULL, 0, NULL, (linenr_T)0, 0L);
+
+ xfree(spat);
+ xfree(epat);
+
+ if (r < 1 || lt(curwin->w_cursor, old_end)) {
+ // Can't find other end or it's before the previous end. Could be a
+ // HTML tag that doesn't have a matching end. Search backwards for
+ // another starting tag.
+ count = 1;
+ curwin->w_cursor = start_pos;
+ goto again;
+ }
+
+ if (do_include) {
+ // Include up to the '>'.
+ while (*get_cursor_pos_ptr() != '>') {
+ if (inc_cursor() < 0) {
+ break;
+ }
+ }
+ } else {
+ char_u *c = get_cursor_pos_ptr();
+ // Exclude the '<' of the end tag.
+ // If the closing tag is on new line, do not decrement cursor, but make
+ // operation exclusive, so that the linefeed will be selected
+ if (*c == '<' && !VIsual_active && curwin->w_cursor.col == 0) {
+ // do not decrement cursor
+ is_inclusive = false;
+ } else if (*c == '<') {
+ dec_cursor();
+ }
+ }
+ end_pos = curwin->w_cursor;
+
+ if (!do_include) {
+ // Exclude the start tag.
+ curwin->w_cursor = start_pos;
+ while (inc_cursor() >= 0) {
+ if (*get_cursor_pos_ptr() == '>') {
+ inc_cursor();
+ start_pos = curwin->w_cursor;
+ break;
+ }
+ }
+ curwin->w_cursor = end_pos;
+
+ // If we are in Visual mode and now have the same text as before set
+ // "do_include" and try again.
+ if (VIsual_active
+ && equalpos(start_pos, old_start)
+ && equalpos(end_pos, old_end)) {
+ do_include = true;
+ curwin->w_cursor = old_start;
+ count = count_arg;
+ goto again;
+ }
+ }
+
+ if (VIsual_active) {
+ // If the end is before the start there is no text between tags, select
+ // the char under the cursor.
+ if (lt(end_pos, start_pos)) {
+ curwin->w_cursor = start_pos;
+ } else if (*p_sel == 'e') {
+ inc_cursor();
+ }
+ VIsual = start_pos;
+ VIsual_mode = 'v';
+ redraw_curbuf_later(UPD_INVERTED); // update the inversion
+ showmode();
+ } else {
+ oap->start = start_pos;
+ oap->motion_type = kMTCharWise;
+ if (lt(end_pos, start_pos)) {
+ // End is before the start: there is no text between tags; operate
+ // on an empty area.
+ curwin->w_cursor = start_pos;
+ oap->inclusive = false;
+ } else {
+ oap->inclusive = is_inclusive;
+ }
+ }
+ retval = OK;
+
+theend:
+ p_ws = save_p_ws;
+ return retval;
+}
+
+/// @param include true == include white space
+/// @param type 'p' for paragraph, 'S' for section
+int current_par(oparg_T *oap, long count, bool include, int type)
+{
+ linenr_T start_lnum;
+ linenr_T end_lnum;
+ int white_in_front;
+ int dir;
+ int start_is_white;
+ int prev_start_is_white;
+ int retval = OK;
+ int do_white = false;
+ int t;
+ int i;
+
+ if (type == 'S') { // not implemented yet
+ return FAIL;
+ }
+
+ start_lnum = curwin->w_cursor.lnum;
+
+ // When visual area is more than one line: extend it.
+ if (VIsual_active && start_lnum != VIsual.lnum) {
+extend:
+ if (start_lnum < VIsual.lnum) {
+ dir = BACKWARD;
+ } else {
+ dir = FORWARD;
+ }
+ for (i = (int)count; --i >= 0;) {
+ if (start_lnum ==
+ (dir == BACKWARD ? 1 : curbuf->b_ml.ml_line_count)) {
+ retval = FAIL;
+ break;
+ }
+
+ prev_start_is_white = -1;
+ for (t = 0; t < 2; t++) {
+ start_lnum += dir;
+ start_is_white = linewhite(start_lnum);
+ if (prev_start_is_white == start_is_white) {
+ start_lnum -= dir;
+ break;
+ }
+ for (;;) {
+ if (start_lnum == (dir == BACKWARD
+ ? 1 : curbuf->b_ml.ml_line_count)) {
+ break;
+ }
+ if (start_is_white != linewhite(start_lnum + dir)
+ || (!start_is_white
+ && startPS(start_lnum + (dir > 0
+ ? 1 : 0), 0, 0))) {
+ break;
+ }
+ start_lnum += dir;
+ }
+ if (!include) {
+ break;
+ }
+ if (start_lnum == (dir == BACKWARD
+ ? 1 : curbuf->b_ml.ml_line_count)) {
+ break;
+ }
+ prev_start_is_white = start_is_white;
+ }
+ }
+ curwin->w_cursor.lnum = start_lnum;
+ curwin->w_cursor.col = 0;
+ return retval;
+ }
+
+ // First move back to the start_lnum of the paragraph or white lines
+ white_in_front = linewhite(start_lnum);
+ while (start_lnum > 1) {
+ if (white_in_front) { // stop at first white line
+ if (!linewhite(start_lnum - 1)) {
+ break;
+ }
+ } else { // stop at first non-white line of start of paragraph
+ if (linewhite(start_lnum - 1) || startPS(start_lnum, 0, 0)) {
+ break;
+ }
+ }
+ start_lnum--;
+ }
+
+ // Move past the end of any white lines.
+ end_lnum = start_lnum;
+ while (end_lnum <= curbuf->b_ml.ml_line_count && linewhite(end_lnum)) {
+ end_lnum++;
+ }
+
+ end_lnum--;
+ i = (int)count;
+ if (!include && white_in_front) {
+ i--;
+ }
+ while (i--) {
+ if (end_lnum == curbuf->b_ml.ml_line_count) {
+ return FAIL;
+ }
+
+ if (!include) {
+ do_white = linewhite(end_lnum + 1);
+ }
+
+ if (include || !do_white) {
+ end_lnum++;
+ // skip to end of paragraph
+ while (end_lnum < curbuf->b_ml.ml_line_count
+ && !linewhite(end_lnum + 1)
+ && !startPS(end_lnum + 1, 0, 0)) {
+ end_lnum++;
+ }
+ }
+
+ if (i == 0 && white_in_front && include) {
+ break;
+ }
+
+ // skip to end of white lines after paragraph
+ if (include || do_white) {
+ while (end_lnum < curbuf->b_ml.ml_line_count
+ && linewhite(end_lnum + 1)) {
+ end_lnum++;
+ }
+ }
+ }
+
+ // If there are no empty lines at the end, try to find some empty lines at
+ // the start (unless that has been done already).
+ if (!white_in_front && !linewhite(end_lnum) && include) {
+ while (start_lnum > 1 && linewhite(start_lnum - 1)) {
+ start_lnum--;
+ }
+ }
+
+ if (VIsual_active) {
+ // Problem: when doing "Vipipip" nothing happens in a single white
+ // line, we get stuck there. Trap this here.
+ if (VIsual_mode == 'V' && start_lnum == curwin->w_cursor.lnum) {
+ goto extend;
+ }
+ if (VIsual.lnum != start_lnum) {
+ VIsual.lnum = start_lnum;
+ VIsual.col = 0;
+ }
+ VIsual_mode = 'V';
+ redraw_curbuf_later(UPD_INVERTED); // update the inversion
+ showmode();
+ } else {
+ oap->start.lnum = start_lnum;
+ oap->start.col = 0;
+ oap->motion_type = kMTLineWise;
+ }
+ curwin->w_cursor.lnum = end_lnum;
+ curwin->w_cursor.col = 0;
+
+ return OK;
+}
+
+/// Search quote char from string line[col].
+/// Quote character escaped by one of the characters in "escape" is not counted
+/// as a quote.
+///
+/// @param escape escape characters, can be NULL
+///
+/// @return column number of "quotechar" or -1 when not found.
+static int find_next_quote(char_u *line, int col, int quotechar, char_u *escape)
+{
+ int c;
+
+ for (;;) {
+ c = line[col];
+ if (c == NUL) {
+ return -1;
+ } else if (escape != NULL && vim_strchr((char *)escape, c)) {
+ col++;
+ if (line[col] == NUL) {
+ return -1;
+ }
+ } else if (c == quotechar) {
+ break;
+ }
+ col += utfc_ptr2len((char *)line + col);
+ }
+ return col;
+}
+
+/// Search backwards in "line" from column "col_start" to find "quotechar".
+/// Quote character escaped by one of the characters in "escape" is not counted
+/// as a quote.
+///
+/// @param escape escape characters, can be NULL
+///
+/// @return the found column or zero.
+static int find_prev_quote(char_u *line, int col_start, int quotechar, char_u *escape)
+{
+ int n;
+
+ while (col_start > 0) {
+ col_start--;
+ col_start -= utf_head_off(line, line + col_start);
+ n = 0;
+ if (escape != NULL) {
+ while (col_start - n > 0 && vim_strchr((char *)escape,
+ line[col_start - n - 1]) != NULL) {
+ n++;
+ }
+ }
+ if (n & 1) {
+ col_start -= n; // uneven number of escape chars, skip it
+ } else if (line[col_start] == quotechar) {
+ break;
+ }
+ }
+ return col_start;
+}
+
+/// Find quote under the cursor, cursor at end.
+///
+/// @param include true == include quote char
+/// @param quotechar Quote character
+///
+/// @return true if found, else false.
+bool current_quote(oparg_T *oap, long count, bool include, int quotechar)
+ FUNC_ATTR_NONNULL_ALL
+{
+ char_u *line = get_cursor_line_ptr();
+ int col_end;
+ int col_start = curwin->w_cursor.col;
+ bool inclusive = false;
+ bool vis_empty = true; // Visual selection <= 1 char
+ bool vis_bef_curs = false; // Visual starts before cursor
+ bool did_exclusive_adj = false; // adjusted pos for 'selection'
+ bool inside_quotes = false; // Looks like "i'" done before
+ bool selected_quote = false; // Has quote inside selection
+ int i;
+ bool restore_vis_bef = false; // resotre VIsual on abort
+
+ // When 'selection' is "exclusive" move the cursor to where it would be
+ // with 'selection' "inclusive", so that the logic is the same for both.
+ // The cursor then is moved forward after adjusting the area.
+ if (VIsual_active) {
+ // this only works within one line
+ if (VIsual.lnum != curwin->w_cursor.lnum) {
+ return false;
+ }
+
+ vis_bef_curs = lt(VIsual, curwin->w_cursor);
+ vis_empty = equalpos(VIsual, curwin->w_cursor);
+ if (*p_sel == 'e') {
+ if (vis_bef_curs) {
+ dec_cursor();
+ did_exclusive_adj = true;
+ } else if (!vis_empty) {
+ dec(&VIsual);
+ did_exclusive_adj = true;
+ }
+ vis_empty = equalpos(VIsual, curwin->w_cursor);
+ if (!vis_bef_curs && !vis_empty) {
+ // VIsual needs to be start of Visual selection.
+ pos_T t = curwin->w_cursor;
+
+ curwin->w_cursor = VIsual;
+ VIsual = t;
+ vis_bef_curs = true;
+ restore_vis_bef = true;
+ }
+ }
+ }
+
+ if (!vis_empty) {
+ // Check if the existing selection exactly spans the text inside
+ // quotes.
+ if (vis_bef_curs) {
+ inside_quotes = VIsual.col > 0
+ && line[VIsual.col - 1] == quotechar
+ && line[curwin->w_cursor.col] != NUL
+ && line[curwin->w_cursor.col + 1] == quotechar;
+ i = VIsual.col;
+ col_end = curwin->w_cursor.col;
+ } else {
+ inside_quotes = curwin->w_cursor.col > 0
+ && line[curwin->w_cursor.col - 1] == quotechar
+ && line[VIsual.col] != NUL
+ && line[VIsual.col + 1] == quotechar;
+ i = curwin->w_cursor.col;
+ col_end = VIsual.col;
+ }
+
+ // Find out if we have a quote in the selection.
+ while (i <= col_end) {
+ // check for going over the end of the line, which can happen if
+ // the line was changed after the Visual area was selected.
+ if (line[i] == NUL) {
+ break;
+ }
+ if (line[i++] == quotechar) {
+ selected_quote = true;
+ break;
+ }
+ }
+ }
+
+ if (!vis_empty && line[col_start] == quotechar) {
+ // Already selecting something and on a quote character. Find the
+ // next quoted string.
+ if (vis_bef_curs) {
+ // Assume we are on a closing quote: move to after the next
+ // opening quote.
+ col_start = find_next_quote(line, col_start + 1, quotechar, NULL);
+ if (col_start < 0) {
+ goto abort_search;
+ }
+ col_end = find_next_quote(line, col_start + 1, quotechar, (char_u *)curbuf->b_p_qe);
+ if (col_end < 0) {
+ // We were on a starting quote perhaps?
+ col_end = col_start;
+ col_start = curwin->w_cursor.col;
+ }
+ } else {
+ col_end = find_prev_quote(line, col_start, quotechar, NULL);
+ if (line[col_end] != quotechar) {
+ goto abort_search;
+ }
+ col_start = find_prev_quote(line, col_end, quotechar, (char_u *)curbuf->b_p_qe);
+ if (line[col_start] != quotechar) {
+ // We were on an ending quote perhaps?
+ col_start = col_end;
+ col_end = curwin->w_cursor.col;
+ }
+ }
+ } else if (line[col_start] == quotechar || !vis_empty) {
+ int first_col = col_start;
+
+ if (!vis_empty) {
+ if (vis_bef_curs) {
+ first_col = find_next_quote(line, col_start, quotechar, NULL);
+ } else {
+ first_col = find_prev_quote(line, col_start, quotechar, NULL);
+ }
+ }
+ // The cursor is on a quote, we don't know if it's the opening or
+ // closing quote. Search from the start of the line to find out.
+ // Also do this when there is a Visual area, a' may leave the cursor
+ // in between two strings.
+ col_start = 0;
+ for (;;) {
+ // Find open quote character.
+ col_start = find_next_quote(line, col_start, quotechar, NULL);
+ if (col_start < 0 || col_start > first_col) {
+ goto abort_search;
+ }
+ // Find close quote character.
+ col_end = find_next_quote(line, col_start + 1, quotechar, (char_u *)curbuf->b_p_qe);
+ if (col_end < 0) {
+ goto abort_search;
+ }
+ // If is cursor between start and end quote character, it is
+ // target text object.
+ if (col_start <= first_col && first_col <= col_end) {
+ break;
+ }
+ col_start = col_end + 1;
+ }
+ } else {
+ // Search backward for a starting quote.
+ col_start = find_prev_quote(line, col_start, quotechar, (char_u *)curbuf->b_p_qe);
+ if (line[col_start] != quotechar) {
+ // No quote before the cursor, look after the cursor.
+ col_start = find_next_quote(line, col_start, quotechar, NULL);
+ if (col_start < 0) {
+ goto abort_search;
+ }
+ }
+
+ // Find close quote character.
+ col_end = find_next_quote(line, col_start + 1, quotechar, (char_u *)curbuf->b_p_qe);
+ if (col_end < 0) {
+ goto abort_search;
+ }
+ }
+
+ // When "include" is true, include spaces after closing quote or before
+ // the starting quote.
+ if (include) {
+ if (ascii_iswhite(line[col_end + 1])) {
+ while (ascii_iswhite(line[col_end + 1])) {
+ col_end++;
+ }
+ } else {
+ while (col_start > 0 && ascii_iswhite(line[col_start - 1])) {
+ col_start--;
+ }
+ }
+ }
+
+ // Set start position. After vi" another i" must include the ".
+ // For v2i" include the quotes.
+ if (!include && count < 2 && (vis_empty || !inside_quotes)) {
+ col_start++;
+ }
+ curwin->w_cursor.col = col_start;
+ if (VIsual_active) {
+ // Set the start of the Visual area when the Visual area was empty, we
+ // were just inside quotes or the Visual area didn't start at a quote
+ // and didn't include a quote.
+ if (vis_empty
+ || (vis_bef_curs
+ && !selected_quote
+ && (inside_quotes
+ || (line[VIsual.col] != quotechar
+ && (VIsual.col == 0
+ || line[VIsual.col - 1] != quotechar))))) {
+ VIsual = curwin->w_cursor;
+ redraw_curbuf_later(UPD_INVERTED);
+ }
+ } else {
+ oap->start = curwin->w_cursor;
+ oap->motion_type = kMTCharWise;
+ }
+
+ // Set end position.
+ curwin->w_cursor.col = col_end;
+ if ((include || count > 1
+ // After vi" another i" must include the ".
+ || (!vis_empty && inside_quotes)) && inc_cursor() == 2) {
+ inclusive = true;
+ }
+ if (VIsual_active) {
+ if (vis_empty || vis_bef_curs) {
+ // decrement cursor when 'selection' is not exclusive
+ if (*p_sel != 'e') {
+ dec_cursor();
+ }
+ } else {
+ // Cursor is at start of Visual area. Set the end of the Visual
+ // area when it was just inside quotes or it didn't end at a
+ // quote.
+ if (inside_quotes
+ || (!selected_quote
+ && line[VIsual.col] != quotechar
+ && (line[VIsual.col] == NUL
+ || line[VIsual.col + 1] != quotechar))) {
+ dec_cursor();
+ VIsual = curwin->w_cursor;
+ }
+ curwin->w_cursor.col = col_start;
+ }
+ if (VIsual_mode == 'V') {
+ VIsual_mode = 'v';
+ redraw_cmdline = true; // show mode later
+ }
+ } else {
+ // Set inclusive and other oap's flags.
+ oap->inclusive = inclusive;
+ }
+
+ return true;
+
+abort_search:
+ if (VIsual_active && *p_sel == 'e') {
+ if (did_exclusive_adj) {
+ inc_cursor();
+ }
+ if (restore_vis_bef) {
+ pos_T t = curwin->w_cursor;
+
+ curwin->w_cursor = VIsual;
+ VIsual = t;
+ }
+ }
+ return false;
+}
diff --git a/src/nvim/textobject.h b/src/nvim/textobject.h
new file mode 100644
index 0000000000..26f88613fd
--- /dev/null
+++ b/src/nvim/textobject.h
@@ -0,0 +1,11 @@
+#ifndef NVIM_TEXTOBJECT_H
+#define NVIM_TEXTOBJECT_H
+
+#include "nvim/normal.h" // for oparg_T
+#include "nvim/pos.h" // for linenr_T
+#include "nvim/vim.h" // for Direction
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "textobject.h.generated.h"
+#endif
+#endif // NVIM_TEXTOBJECT_H
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 61a59bcf06..d269878f46 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -233,12 +233,12 @@ static void tinput_wait_enqueue(void **argv)
if (ui_client_channel_id) {
Array args = ARRAY_DICT_INIT;
Error err = ERROR_INIT;
- ADD(args, STRING_OBJ(copy_string(keys)));
+ ADD(args, STRING_OBJ(copy_string(keys, NULL)));
// TODO(bfredl): could be non-blocking now with paste?
ArenaMem res_mem = NULL;
Object result = rpc_send_call(ui_client_channel_id, "nvim_input", args, &res_mem, &err);
consumed = result.type == kObjectTypeInteger ? (size_t)result.data.integer : 0;
- arena_mem_free(res_mem, NULL);
+ arena_mem_free(res_mem);
} else {
consumed = input_enqueue(keys);
}
@@ -398,6 +398,14 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key)
button = last_pressed_button;
}
+ if (ev == TERMKEY_MOUSE_UNKNOWN && !(key->code.mouse[0] & 0x20)) {
+ int code = key->code.mouse[0] & ~0x3c;
+ if (code == 66 || code == 67) {
+ ev = TERMKEY_MOUSE_PRESS;
+ button = code - 60;
+ }
+ }
+
if (button == 0 || (ev != TERMKEY_MOUSE_PRESS && ev != TERMKEY_MOUSE_DRAG
&& ev != TERMKEY_MOUSE_RELEASE)) {
return;
@@ -431,8 +439,11 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key)
if (button == 4) {
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "ScrollWheelUp");
} else if (button == 5) {
- len += (size_t)snprintf(buf + len, sizeof(buf) - len,
- "ScrollWheelDown");
+ len += (size_t)snprintf(buf + len, sizeof(buf) - len, "ScrollWheelDown");
+ } else if (button == 6) {
+ len += (size_t)snprintf(buf + len, sizeof(buf) - len, "ScrollWheelLeft");
+ } else if (button == 7) {
+ len += (size_t)snprintf(buf + len, sizeof(buf) - len, "ScrollWheelRight");
} else {
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "Mouse");
last_pressed_button = button;
diff --git a/src/nvim/types.h b/src/nvim/types.h
index 477102276c..fb10bf21d9 100644
--- a/src/nvim/types.h
+++ b/src/nvim/types.h
@@ -22,7 +22,16 @@ typedef int handle_T;
// absent callback etc.
typedef int LuaRef;
-typedef void (*FunPtr)(void);
+/// Type used for VimL VAR_FLOAT values
+typedef double float_T;
+
+typedef struct MsgpackRpcRequestHandler MsgpackRpcRequestHandler;
+
+typedef union {
+ float_T (*float_func)(float_T);
+ const MsgpackRpcRequestHandler *api_handler;
+ void *nullptr;
+} EvalFuncData;
typedef handle_T NS;
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index da671a3ad1..46f4d137c4 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -336,7 +336,7 @@ void vim_beep(unsigned val)
// When 'debug' contains "beep" produce a message. If we are sourcing
// a script or executing a function give the user a hint where the beep
// comes from.
- if (vim_strchr((char *)p_debug, 'e') != NULL) {
+ if (vim_strchr(p_debug, 'e') != NULL) {
msg_source(HL_ATTR(HLF_W));
msg_attr(_("Beep!"), HL_ATTR(HLF_W));
}
@@ -517,11 +517,10 @@ void ui_flush(void)
}
if (pending_mode_info_update) {
Arena arena = ARENA_EMPTY;
- arena_start(&arena, &ui_ext_fixblk);
Array style = mode_style_array(&arena);
bool enabled = (*p_guicursor != NUL);
ui_call_mode_info_set(enabled, style);
- arena_mem_free(arena_finish(&arena), &ui_ext_fixblk);
+ arena_mem_free(arena_finish(&arena));
pending_mode_info_update = false;
}
if (pending_mode_update && !starting) {
@@ -566,7 +565,7 @@ void ui_check_mouse(void)
// - 'a' is in 'mouse' and "c" is in MOUSE_A, or
// - the current buffer is a help file and 'h' is in 'mouse' and we are in a
// normal editing mode (not at hit-return message).
- for (char_u *p = p_mouse; *p; p++) {
+ for (char_u *p = (char_u *)p_mouse; *p; p++) {
switch (*p) {
case 'a':
if (vim_strchr(MOUSE_A, checkfor) != NULL) {
diff --git a/src/nvim/ui.h b/src/nvim/ui.h
index 7dd2f5bce3..996b3467a6 100644
--- a/src/nvim/ui.h
+++ b/src/nvim/ui.h
@@ -47,8 +47,6 @@ enum {
typedef int LineFlags;
-EXTERN ArenaMem ui_ext_fixblk INIT(= NULL);
-
struct ui_t {
bool rgb;
bool override; ///< Force highest-requested UI capabilities.
diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c
index 84098e9476..809d278029 100644
--- a/src/nvim/ui_bridge.c
+++ b/src/nvim/ui_bridge.c
@@ -194,9 +194,9 @@ static void ui_bridge_suspend_event(void **argv)
static void ui_bridge_option_set(UI *ui, String name, Object value)
{
- String copy_name = copy_string(name);
+ String copy_name = copy_string(name, NULL);
Object *copy_value = xmalloc(sizeof(Object));
- *copy_value = copy_object(value);
+ *copy_value = copy_object(value, NULL);
UI_BRIDGE_CALL(ui, option_set, 4, ui, copy_name.data,
INT2PTR(copy_name.size), copy_value);
// TODO(bfredl): when/if TUI/bridge teardown is refactored to use events, the
diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c
index a586fec3bf..265c54f72d 100644
--- a/src/nvim/ui_client.c
+++ b/src/nvim/ui_client.c
@@ -55,7 +55,7 @@ UIClientHandler ui_client_get_redraw_handler(const char *name, size_t name_len,
/// async 'redraw' events, which are expected when nvim acts as an ui client.
/// get handled in msgpack_rpc/unpacker.c and directly dispatched to handlers
/// of specific ui events, like ui_client_event_grid_resize and so on.
-Object handle_ui_client_redraw(uint64_t channel_id, Array args, Error *error)
+Object handle_ui_client_redraw(uint64_t channel_id, Array args, Arena *arena, Error *error)
{
api_set_error(error, kErrorTypeValidation, "'redraw' cannot be sent as a request");
return NIL;
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 75a09b244c..97a925f3ad 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -685,7 +685,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
*p-- = NUL;
}
- bool has_directory = os_isdir((char_u *)dir_name);
+ bool has_directory = os_isdir(dir_name);
if (!has_directory && *dirp == NUL && !reading) {
// Last directory in the list does not exist, create it.
int ret;
@@ -773,7 +773,7 @@ static bool serialize_header(bufinfo_T *bi, char_u *hash)
undo_write_bytes(bi, (uintmax_t)buf->b_ml.ml_line_count, 4);
size_t len = buf->b_u_line_ptr ? STRLEN(buf->b_u_line_ptr) : 0;
undo_write_bytes(bi, len, 4);
- if (len > 0 && !undo_write(bi, buf->b_u_line_ptr, len)) {
+ if (len > 0 && !undo_write(bi, (char_u *)buf->b_u_line_ptr, len)) {
return false;
}
undo_write_bytes(bi, (uintmax_t)buf->b_u_line_lnum, 4);
@@ -1593,7 +1593,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT
curbuf->b_u_oldhead = old_idx < 0 ? NULL : uhp_table[old_idx];
curbuf->b_u_newhead = new_idx < 0 ? NULL : uhp_table[new_idx];
curbuf->b_u_curhead = cur_idx < 0 ? NULL : uhp_table[cur_idx];
- curbuf->b_u_line_ptr = line_ptr;
+ curbuf->b_u_line_ptr = (char *)line_ptr;
curbuf->b_u_line_lnum = line_lnum;
curbuf->b_u_line_colnr = line_colnr;
curbuf->b_u_numhead = num_head;
@@ -2305,7 +2305,7 @@ static void u_undoredo(int undo, bool do_buf_event)
// delete backwards, it goes faster in most cases
long i;
linenr_T lnum;
- for (lnum = bot - 1, i = oldsize; --i >= 0; --lnum) {
+ for (lnum = bot - 1, i = oldsize; --i >= 0; lnum--) {
// 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
@@ -2560,7 +2560,7 @@ static void u_undo_end(bool did_undo, bool absolute, bool quiet)
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_buffer == curbuf && wp->w_p_cole > 0) {
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
}
}
}
@@ -2960,7 +2960,7 @@ void u_saveline(linenr_T lnum)
} else {
curbuf->b_u_line_colnr = 0;
}
- curbuf->b_u_line_ptr = u_save_line(lnum);
+ curbuf->b_u_line_ptr = (char *)u_save_line(lnum);
}
/// clear the line saved for the "U" command
@@ -2992,12 +2992,12 @@ void u_undoline(void)
}
char_u *oldp = u_save_line(curbuf->b_u_line_lnum);
- ml_replace(curbuf->b_u_line_lnum, (char *)curbuf->b_u_line_ptr, true);
+ ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, true);
changed_bytes(curbuf->b_u_line_lnum, 0);
extmark_splice_cols(curbuf, (int)curbuf->b_u_line_lnum - 1, 0, (colnr_T)STRLEN(oldp),
(colnr_T)STRLEN(curbuf->b_u_line_ptr), kExtmarkUndo);
xfree(curbuf->b_u_line_ptr);
- curbuf->b_u_line_ptr = oldp;
+ curbuf->b_u_line_ptr = (char *)oldp;
colnr_T t = curbuf->b_u_line_colnr;
if (curwin->w_cursor.lnum == curbuf->b_u_line_lnum) {
diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c
index 59b8d10200..5b2101587f 100644
--- a/src/nvim/usercmd.c
+++ b/src/nvim/usercmd.c
@@ -106,7 +106,7 @@ static struct {
/// Return NULL if there is no matching command.
///
/// @param *p end of the command (possibly including count)
-/// @param full set to TRUE for a full match
+/// @param full set to true for a full match
/// @param xp used for completion, NULL otherwise
/// @param complp completion flags or NULL
char *find_ucmd(exarg_T *eap, char *p, int *full, expand_T *xp, int *complp)
@@ -127,7 +127,7 @@ char *find_ucmd(exarg_T *eap, char *p, int *full, expand_T *xp, int *complp)
for (j = 0; j < gap->ga_len; j++) {
uc = USER_CMD_GA(gap, j);
cp = eap->cmd;
- np = (char *)uc->uc_name;
+ np = uc->uc_name;
k = 0;
while (k < len && *np != NUL && *cp++ == *np++) {
k++;
@@ -167,7 +167,7 @@ char *find_ucmd(exarg_T *eap, char *p, int *full, expand_T *xp, int *complp)
}
if (xp != NULL) {
xp->xp_luaref = uc->uc_compl_luaref;
- xp->xp_arg = (char *)uc->uc_compl_arg;
+ xp->xp_arg = uc->uc_compl_arg;
xp->xp_script_ctx = uc->uc_script_ctx;
xp->xp_script_ctx.sc_lnum += SOURCING_LNUM;
}
@@ -216,7 +216,7 @@ const char *set_context_in_user_cmd(expand_T *xp, const char *arg_in)
// Check for attributes
while (*arg == '-') {
arg++; // Skip "-".
- p = (const char *)skiptowhite((const char_u *)arg);
+ p = (const char *)skiptowhite(arg);
if (*p == NUL) {
// Cursor is still in the attribute.
p = strchr(arg, '=');
@@ -248,7 +248,7 @@ const char *set_context_in_user_cmd(expand_T *xp, const char *arg_in)
}
// After the attributes comes the new command name.
- p = (const char *)skiptowhite((const char_u *)arg);
+ p = (const char *)skiptowhite(arg);
if (*p == NUL) {
xp->xp_context = EXPAND_USER_COMMANDS;
xp->xp_pattern = (char *)arg;
@@ -272,12 +272,12 @@ char *get_user_commands(expand_T *xp FUNC_ATTR_UNUSED, int idx)
const buf_T *const buf = prevwin_curwin()->w_buffer;
if (idx < buf->b_ucmds.ga_len) {
- return (char *)USER_CMD_GA(&buf->b_ucmds, idx)->uc_name;
+ return USER_CMD_GA(&buf->b_ucmds, idx)->uc_name;
}
idx -= buf->b_ucmds.ga_len;
if (idx < ucmds.ga_len) {
- char *name = (char *)USER_CMD(idx)->uc_name;
+ char *name = USER_CMD(idx)->uc_name;
for (int i = 0; i < buf->b_ucmds.ga_len; i++) {
if (STRCMP(name, USER_CMD_GA(&buf->b_ucmds, i)->uc_name) == 0) {
@@ -297,14 +297,14 @@ char *get_user_commands(expand_T *xp FUNC_ATTR_UNUSED, int idx)
char *get_user_command_name(int idx, int cmdidx)
{
if (cmdidx == CMD_USER && idx < ucmds.ga_len) {
- return (char *)USER_CMD(idx)->uc_name;
+ return USER_CMD(idx)->uc_name;
}
if (cmdidx == CMD_USER_BUF) {
// In cmdwin, the alternative buffer should be used.
const buf_T *const buf = prevwin_curwin()->w_buffer;
if (idx < buf->b_ucmds.ga_len) {
- return (char *)USER_CMD_GA(&buf->b_ucmds, idx)->uc_name;
+ return USER_CMD_GA(&buf->b_ucmds, idx)->uc_name;
}
}
return NULL;
@@ -531,7 +531,7 @@ static void uc_list(char *name, size_t name_len)
}
}
- msg_outtrans_special(cmd->uc_rep, false,
+ msg_outtrans_special((char_u *)cmd->uc_rep, false,
name_len == 0 ? Columns - 47 : 0);
if (p_verbose > 0) {
last_set_msg(cmd->uc_script_ctx);
@@ -883,17 +883,17 @@ int uc_add_command(char *name, size_t name_len, const char *rep, uint32_t argt,
gap->ga_len++;
- cmd->uc_name = (char_u *)p;
+ cmd->uc_name = p;
}
- cmd->uc_rep = (char_u *)rep_buf;
+ cmd->uc_rep = rep_buf;
cmd->uc_argt = argt;
cmd->uc_def = def;
cmd->uc_compl = compl;
cmd->uc_script_ctx = current_sctx;
cmd->uc_script_ctx.sc_lnum += SOURCING_LNUM;
nlua_set_sctx(&cmd->uc_script_ctx);
- cmd->uc_compl_arg = (char_u *)compl_arg;
+ cmd->uc_compl_arg = compl_arg;
cmd->uc_compl_luaref = compl_luaref;
cmd->uc_preview_luaref = preview_luaref;
cmd->uc_addr_type = addr_type;
@@ -930,7 +930,7 @@ void ex_command(exarg_T *eap)
// Check for attributes
while (*p == '-') {
p++;
- end = (char *)skiptowhite((char_u *)p);
+ end = skiptowhite(p);
if (uc_scan_attr(p, (size_t)(end - p), &argt, &def, &flags, &compl, (char_u **)&compl_arg,
&addr_type_arg) == FAIL) {
return;
@@ -1061,11 +1061,11 @@ bool uc_split_args_iter(const char *arg, size_t arglen, size_t *end, char *buf,
buf[l++] = arg[++pos];
} else {
buf[l++] = arg[pos];
- if (ascii_iswhite(arg[pos + 1])) {
- *end = pos + 1;
- *len = l;
- return false;
- }
+ }
+ if (ascii_iswhite(arg[pos + 1])) {
+ *end = pos + 1;
+ *len = l;
+ return false;
}
}
@@ -1569,7 +1569,7 @@ int do_ucmd(exarg_T *eap, bool preview)
// Second round: copy result into "buf".
buf = NULL;
for (;;) {
- p = (char *)cmd->uc_rep; // source
+ p = cmd->uc_rep; // source
q = buf; // destination
totlen = 0;
diff --git a/src/nvim/usercmd.h b/src/nvim/usercmd.h
index 637862b216..4d2cf0d9de 100644
--- a/src/nvim/usercmd.h
+++ b/src/nvim/usercmd.h
@@ -4,14 +4,14 @@
#include "nvim/ex_cmds_defs.h"
typedef struct ucmd {
- char_u *uc_name; // The command name
+ char *uc_name; // The command name
uint32_t uc_argt; // The argument type
- char_u *uc_rep; // The command's replacement string
+ char *uc_rep; // The command's replacement string
long uc_def; // The default value for a range/count
int uc_compl; // completion type
cmd_addr_T uc_addr_type; // The command's address type
sctx_T uc_script_ctx; // SCTX where the command was defined
- char_u *uc_compl_arg; // completion argument if any
+ char *uc_compl_arg; // completion argument if any
LuaRef uc_compl_luaref; // Reference to Lua completion function
LuaRef uc_preview_luaref; // Reference to Lua preview function
LuaRef uc_luaref; // Reference to Lua function
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 0667243bc3..5888d4614e 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -2016,7 +2016,7 @@ void ex_version(exarg_T *eap)
/// Output a string for the version message. If it's going to wrap, output a
/// newline, unless the message is too long to fit on the screen anyway.
-/// When "wrap" is TRUE wrap the string in [].
+/// When "wrap" is true wrap the string in [].
/// @param s
/// @param wrap
static void version_msg_wrap(char *s, int wrap)
@@ -2072,7 +2072,7 @@ void list_in_columns(char **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 = vim_strsize((char *)items[i]) + (i == current ? 2 : 0);
+ int l = vim_strsize(items[i]) + (i == current ? 2 : 0);
if (l > width) {
width = l;
@@ -2084,7 +2084,7 @@ void list_in_columns(char **items, int size, int current)
if (Columns < width) {
// Not enough screen columns - show one per line
for (i = 0; i < item_count; i++) {
- version_msg_wrap((char *)items[i], i == current);
+ version_msg_wrap(items[i], i == current);
if (msg_col > 0 && i < item_count - 1) {
msg_putchar('\n');
}
@@ -2106,7 +2106,7 @@ void list_in_columns(char **items, int size, int current)
if (idx == current) {
msg_putchar('[');
}
- msg_puts((char *)items[idx]);
+ msg_puts(items[idx]);
if (idx == current) {
msg_putchar(']');
}
@@ -2200,7 +2200,7 @@ void maybe_intro_message(void)
if (buf_is_empty(curbuf)
&& (curbuf->b_fname == NULL)
&& (firstwin->w_next == NULL)
- && (vim_strchr((char *)p_shm, SHM_INTRO) == NULL)) {
+ && (vim_strchr(p_shm, SHM_INTRO) == NULL)) {
intro_message(false);
}
}
@@ -2209,7 +2209,7 @@ void maybe_intro_message(void)
/// Only used when starting Vim on an empty file, without a file name.
/// Or with the ":intro" command (for Sven :-).
///
-/// @param colon TRUE for ":intro"
+/// @param colon true for ":intro"
void intro_message(int colon)
{
int i;
@@ -2256,7 +2256,7 @@ void intro_message(int colon)
row = blanklines / 2;
if (((row >= 2) && (Columns >= 50)) || colon) {
- for (i = 0; i < (int)ARRAY_SIZE(lines); ++i) {
+ for (i = 0; i < (int)ARRAY_SIZE(lines); i++) {
p = lines[i];
if (sponsor != 0) {
@@ -2274,7 +2274,7 @@ void intro_message(int colon)
}
if (*p != NUL) {
- do_intro_line(row, (char_u *)_(p), 0);
+ do_intro_line(row, _(p), 0);
}
row++;
}
@@ -2287,15 +2287,14 @@ void intro_message(int colon)
}
}
-static void do_intro_line(long row, char_u *mesg, int attr)
+static void do_intro_line(long row, char *mesg, int attr)
{
- long col;
- char_u *p;
+ char *p;
int l;
int clen;
// Center the message horizontally.
- col = vim_strsize((char *)mesg);
+ long col = vim_strsize(mesg);
col = (Columns - col) / 2;
@@ -2310,8 +2309,8 @@ static void do_intro_line(long row, char_u *mesg, int attr)
for (l = 0;
p[l] != NUL && (l == 0 || (p[l] != '<' && p[l - 1] != '>'));
l++) {
- clen += ptr2cells((char *)p + l);
- l += utfc_ptr2len((char *)p + l) - 1;
+ clen += ptr2cells(p + l);
+ l += utfc_ptr2len(p + l) - 1;
}
assert(row <= INT_MAX && col <= INT_MAX);
grid_puts_len(&default_grid, p, l, (int)row, (int)col,
@@ -2326,6 +2325,6 @@ static void do_intro_line(long row, char_u *mesg, int attr)
void ex_intro(exarg_T *eap)
{
screenclear();
- intro_message(TRUE);
- wait_return(TRUE);
+ intro_message(true);
+ wait_return(true);
}
diff --git a/src/nvim/vim.h b/src/nvim/vim.h
index 09b949bb20..ec8d6ab153 100644
--- a/src/nvim/vim.h
+++ b/src/nvim/vim.h
@@ -167,15 +167,6 @@ enum {
#define MIN_SWAP_PAGE_SIZE 1048
#define MAX_SWAP_PAGE_SIZE 50000
-// Boolean constants
-
-#ifndef TRUE
-# define FALSE 0 // note: this is an int, not a long!
-# define TRUE 1
-#endif
-
-#define MAYBE 2 // sometimes used for a variant on TRUE
-
#define STATUS_HEIGHT 1 // height of a status line under a window
#define QF_WINHEIGHT 10 // default height for quickfix window
@@ -239,10 +230,7 @@ enum { FOLD_TEXT_LEN = 51, }; //!< buffer size for get_foldtext()
# endif
#endif
-#define STRRCHR(s, c) (char_u *)strrchr((const char *)(s), (c))
-
-#define STRCAT(d, s) strcat((char *)(d), (char *)(s))
-#define STRNCAT(d, s, n) strncat((char *)(d), (char *)(s), (size_t)(n))
+#define STRCAT(d, s) strcat((char *)(d), (char *)(s)) // NOLINT(runtime/printf)
#define STRLCAT(d, s, n) xstrlcat((char *)(d), (char *)(s), (size_t)(n))
// Character used as separated in autoload function/variable names.
diff --git a/src/nvim/viml/parser/parser.h b/src/nvim/viml/parser/parser.h
index b8835127e7..55f54cedbe 100644
--- a/src/nvim/viml/parser/parser.h
+++ b/src/nvim/viml/parser/parser.h
@@ -142,9 +142,7 @@ static inline void viml_preader_get_line(ParserInputReader *const preader,
.allocated = true,
.size = pline.size,
};
- cpline.data = (char *)string_convert(&preader->conv,
- (char_u *)pline.data,
- &cpline.size);
+ cpline.data = string_convert(&preader->conv, (char *)pline.data, &cpline.size);
if (pline.allocated) {
xfree((void *)pline.data);
}
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 68c5b42e30..74ea1172ee 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -215,7 +215,7 @@ newwindow:
case Ctrl_Q:
case 'q':
reset_VIsual_and_resel(); // stop Visual mode
- cmd_with_count("quit", (char_u *)cbuf, sizeof(cbuf), Prenum);
+ cmd_with_count("quit", cbuf, sizeof(cbuf), Prenum);
do_cmdline_cmd(cbuf);
break;
@@ -223,7 +223,7 @@ newwindow:
case Ctrl_C:
case 'c':
reset_VIsual_and_resel(); // stop Visual mode
- cmd_with_count("close", (char_u *)cbuf, sizeof(cbuf), Prenum);
+ cmd_with_count("close", cbuf, sizeof(cbuf), Prenum);
do_cmdline_cmd(cbuf);
break;
@@ -256,7 +256,7 @@ newwindow:
case 'o':
CHECK_CMDWIN;
reset_VIsual_and_resel(); // stop Visual mode
- cmd_with_count("only", (char_u *)cbuf, sizeof(cbuf), Prenum);
+ cmd_with_count("only", cbuf, sizeof(cbuf), Prenum);
do_cmdline_cmd(cbuf);
break;
@@ -622,12 +622,12 @@ wingotofile:
}
}
-static void cmd_with_count(char *cmd, char_u *bufp, size_t bufsize, int64_t Prenum)
+static void cmd_with_count(char *cmd, char *bufp, size_t bufsize, int64_t Prenum)
{
size_t len = STRLCPY(bufp, cmd, bufsize);
if (Prenum > 0 && len < bufsize) {
- vim_snprintf((char *)bufp + len, bufsize - len, "%" PRId64, Prenum);
+ vim_snprintf(bufp + len, bufsize - len, "%" PRId64, Prenum);
}
}
@@ -712,7 +712,7 @@ win_T *win_new_float(win_T *wp, bool last, FloatConfig fconfig, Error *err)
win_config_float(wp, fconfig);
win_set_inner_size(wp, true);
wp->w_pos_changed = true;
- redraw_later(wp, VALID);
+ redraw_later(wp, UPD_VALID);
return wp;
}
@@ -727,38 +727,38 @@ void win_set_minimal_style(win_T *wp)
// Hide EOB region: use " " fillchar and cleared highlighting
if (wp->w_p_fcs_chars.eob != ' ') {
- char_u *old = wp->w_p_fcs;
+ char_u *old = (char_u *)wp->w_p_fcs;
wp->w_p_fcs = ((*old == NUL)
- ? (char_u *)xstrdup("eob: ")
- : concat_str(old, (char_u *)",eob: "));
- free_string_option(old);
+ ? xstrdup("eob: ")
+ : concat_str((char *)old, ",eob: "));
+ free_string_option((char *)old);
}
// TODO(bfredl): this could use a highlight namespace directly,
// and avoid pecularities around window options
- char_u *old = wp->w_p_winhl;
+ char_u *old = (char_u *)wp->w_p_winhl;
wp->w_p_winhl = ((*old == NUL)
- ? (char_u *)xstrdup("EndOfBuffer:")
- : concat_str(old, (char_u *)",EndOfBuffer:"));
- free_string_option(old);
+ ? xstrdup("EndOfBuffer:")
+ : concat_str((char *)old, ",EndOfBuffer:"));
+ free_string_option((char *)old);
parse_winhl_opt(wp);
// signcolumn: use 'auto'
if (wp->w_p_scl[0] != 'a' || STRLEN(wp->w_p_scl) >= 8) {
free_string_option(wp->w_p_scl);
- wp->w_p_scl = (char_u *)xstrdup("auto");
+ wp->w_p_scl = xstrdup("auto");
}
// foldcolumn: use '0'
if (wp->w_p_fdc[0] != '0') {
free_string_option(wp->w_p_fdc);
- wp->w_p_fdc = (char_u *)xstrdup("0");
+ wp->w_p_fdc = xstrdup("0");
}
// colorcolumn: cleared
if (wp->w_p_cc != NULL && *wp->w_p_cc != NUL) {
free_string_option(wp->w_p_cc);
- wp->w_p_cc = (char_u *)xstrdup("");
+ wp->w_p_cc = xstrdup("");
}
}
@@ -797,12 +797,12 @@ void win_config_float(win_T *wp, FloatConfig fconfig)
}
win_set_inner_size(wp, true);
- must_redraw = MAX(must_redraw, VALID);
+ must_redraw = MAX(must_redraw, UPD_VALID);
wp->w_pos_changed = true;
if (change_external || change_border) {
wp->w_hl_needs_update = true;
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
}
// compute initial position
@@ -839,7 +839,7 @@ void win_config_float(win_T *wp, FloatConfig fconfig)
// changing border style while keeping border only requires redrawing border
if (fconfig.border) {
wp->w_redr_border = true;
- redraw_later(wp, VALID);
+ redraw_later(wp, UPD_VALID);
}
}
@@ -928,7 +928,7 @@ void ui_ext_win_position(win_T *wp)
wp->w_grid_alloc.focusable = wp->w_float_config.focusable;
if (!valid) {
wp->w_grid_alloc.valid = false;
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
}
}
} else {
@@ -1299,9 +1299,9 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
} else {
curfrp = oldwin->w_frame;
if (flags & WSP_BELOW) {
- before = FALSE;
+ before = false;
} else if (flags & WSP_ABOVE) {
- before = TRUE;
+ before = true;
} else if (flags & WSP_VERT) {
before = !p_spr;
} else {
@@ -1474,8 +1474,8 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
// Both windows need redrawing. Update all status lines, in case they
// show something related to the window count or position.
- redraw_later(wp, NOT_VALID);
- redraw_later(oldwin, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
+ redraw_later(oldwin, UPD_NOT_VALID);
status_redraw_all();
if (need_status) {
@@ -1570,10 +1570,10 @@ static void win_init(win_T *newp, win_T *oldp, int flags)
taggy_T *tag = &newp->w_tagstack[i];
*tag = oldp->w_tagstack[i];
if (tag->tagname != NULL) {
- tag->tagname = vim_strsave(tag->tagname);
+ tag->tagname = xstrdup(tag->tagname);
}
if (tag->user_data != NULL) {
- tag->user_data = vim_strsave(tag->user_data);
+ tag->user_data = xstrdup(tag->user_data);
}
}
newp->w_tagstackidx = oldp->w_tagstackidx;
@@ -1597,7 +1597,7 @@ static void win_init_some(win_T *newp, win_T *oldp)
{
// Use the same argument list.
newp->w_alist = oldp->w_alist;
- ++newp->w_alist->al_refcount;
+ newp->w_alist->al_refcount++;
newp->w_arg_idx = oldp->w_arg_idx;
// copy options from existing window
@@ -1723,7 +1723,7 @@ int make_windows(int count, bool vertical)
block_autocmds();
// todo is number of windows left to create
- for (todo = count - 1; todo > 0; --todo) {
+ for (todo = count - 1; todo > 0; todo--) {
if (vertical) {
if (win_split(curwin->w_width - (curwin->w_width - todo)
/ (todo + 1) - 1, WSP_VERT | WSP_ABOVE) == FAIL) {
@@ -1837,8 +1837,8 @@ static void win_exchange(long Prenum)
}
win_enter(wp, true);
- redraw_later(curwin, NOT_VALID);
- redraw_later(wp, NOT_VALID);
+ redraw_later(curwin, UPD_NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
}
// rotate windows: if upwards true the second window becomes the first one
@@ -1922,7 +1922,7 @@ static void win_rotate(bool upwards, int count)
wp1->w_pos_changed = true;
wp2->w_pos_changed = true;
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
}
/*
@@ -2034,7 +2034,7 @@ void win_move_after(win_T *win1, win_T *win2)
frame_append(win2->w_frame, win1->w_frame);
(void)win_comp_pos(); // recompute w_winrow for all windows
- redraw_later(curwin, NOT_VALID);
+ redraw_later(curwin, UPD_NOT_VALID);
}
win_enter(win1, false);
@@ -2082,7 +2082,7 @@ static int get_maximum_wincount(frame_T *fr, int height)
void win_equal(win_T *next_curwin, bool current, int dir)
{
if (dir == 0) {
- dir = *p_ead;
+ dir = (unsigned char)(*p_ead);
}
win_equal_rec(next_curwin == NULL ? curwin : next_curwin, current,
topframe, dir, 0, tabline_height(),
@@ -2125,7 +2125,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
frame_new_height(topfr, height, false, false);
topfr->fr_win->w_wincol = col;
frame_new_width(topfr, width, false, false);
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
}
} else if (topfr->fr_layout == FR_ROW) {
topfr->fr_width = width;
@@ -2200,7 +2200,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
}
if (has_next_curwin) {
- --totwincount; // don't count curwin
+ totwincount--; // don't count curwin
}
}
@@ -2330,7 +2330,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
}
if (has_next_curwin) {
- --totwincount; // don't count curwin
+ totwincount--; // don't count curwin
}
}
@@ -2436,7 +2436,7 @@ void entering_window(win_T *const win)
void win_init_empty(win_T *wp)
{
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
wp->w_lines_valid = 0;
wp->w_cursor.lnum = 1;
wp->w_curswant = wp->w_cursor.col = 0;
@@ -2935,7 +2935,7 @@ int win_close(win_T *win, bool free_buf, bool force)
}
curwin->w_pos_changed = true;
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
return OK;
}
@@ -3096,7 +3096,7 @@ void win_free_all(void)
cmdwin_type = 0;
while (first_tabpage->tp_next != NULL) {
- tabpage_close(TRUE);
+ tabpage_close(true);
}
while (lastwin != NULL && lastwin->w_floating) {
@@ -3695,7 +3695,7 @@ static void frame_add_vsep(const frame_T *frp)
wp = frp->fr_win;
if (wp->w_vsep_width == 0) {
if (wp->w_width > 0) { // don't make it negative
- --wp->w_width;
+ wp->w_width--;
}
wp->w_vsep_width = 1;
}
@@ -4025,7 +4025,7 @@ static tabpage_T *alloc_tabpage(void)
// Init t: variables.
tp->tp_vars = tv_dict_alloc();
init_var_dict(tp->tp_vars, &tp->tp_winvar, VAR_SCOPE);
- tp->tp_diff_invalid = TRUE;
+ tp->tp_diff_invalid = true;
tp->tp_ch_used = p_ch;
return tp;
@@ -4037,7 +4037,7 @@ void free_tabpage(tabpage_T *tp)
pmap_del(handle_T)(&tabpage_handles, tp->handle);
diff_clear(tp);
- for (idx = 0; idx < SNAP_COUNT; ++idx) {
+ for (idx = 0; idx < SNAP_COUNT; idx++) {
clear_snapshot(tp, idx);
}
vars_clear(&tp->tp_vars->dv_hashtab); // free all t: variables
@@ -4115,7 +4115,7 @@ int win_new_tabpage(int after, char_u *filename)
newtp->tp_topframe = topframe;
last_status(false);
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
tabpage_check_windows(old_curtab);
@@ -4173,7 +4173,7 @@ int make_tabpages(int maxcount)
*/
block_autocmds();
- for (todo = count - 1; todo > 0; --todo) {
+ for (todo = count - 1; todo > 0; todo--) {
if (win_new_tabpage(0, NULL) == FAIL) {
break;
}
@@ -4343,6 +4343,11 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, bool trigger_enter_a
// Use the stored value of p_ch, so that it can be different for each tab page.
if (p_ch != curtab->tp_ch_used) {
clear_cmdline = true;
+ if (msg_grid.chars && p_ch < curtab->tp_ch_used) {
+ // TODO(bfredl): a bit expensive, should be enough to invalidate the
+ // region between the old and the new p_ch.
+ grid_invalidate(&msg_grid);
+ }
}
p_ch = curtab->tp_ch_used;
@@ -4373,7 +4378,7 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, bool trigger_enter_a
}
}
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
}
/// tells external UI that windows and inline floats in old_curtab are invisible
@@ -4440,7 +4445,7 @@ void goto_tabpage(int n)
// "gT": go to previous tab page, wrap around end. "N gT" repeats
// this N times.
ttp = curtab;
- for (i = n; i < 0; ++i) {
+ for (i = n; i < 0; i++) {
for (tp = first_tabpage; tp->tp_next != ttp && tp->tp_next != NULL;
tp = tp->tp_next) {}
ttp = tp;
@@ -4836,7 +4841,7 @@ static void win_enter_ext(win_T *const wp, const int flags)
}
if (!curwin_invalid) {
prevwin = curwin; // remember for CTRL-W p
- curwin->w_redr_status = TRUE;
+ curwin->w_redr_status = true;
}
curwin = wp;
curbuf = wp->w_buffer;
@@ -4867,7 +4872,7 @@ static void win_enter_ext(win_T *const wp, const int flags)
curwin->w_redr_status = true;
redraw_tabline = true;
if (restart_edit) {
- redraw_later(curwin, VALID); // causes status line redraw
+ redraw_later(curwin, UPD_VALID); // causes status line redraw
}
// change background color according to NormalNC,
@@ -4875,11 +4880,11 @@ static void win_enter_ext(win_T *const wp, const int flags)
if (curwin->w_hl_attr_normal != curwin->w_hl_attr_normalnc) {
// TODO(bfredl): eventually we should be smart enough
// to only recompose the window, not redraw it.
- redraw_later(curwin, NOT_VALID);
+ redraw_later(curwin, UPD_NOT_VALID);
}
if (prevwin) {
if (prevwin->w_hl_attr_normal != prevwin->w_hl_attr_normalnc) {
- redraw_later(prevwin, NOT_VALID);
+ redraw_later(prevwin, UPD_NOT_VALID);
}
}
@@ -5362,6 +5367,7 @@ void may_trigger_winscrolled(void)
win_T *wp = curwin;
if (wp->w_last_topline != wp->w_topline
|| wp->w_last_leftcol != wp->w_leftcol
+ || wp->w_last_skipcol != wp->w_skipcol
|| wp->w_last_width != wp->w_width
|| wp->w_last_height != wp->w_height) {
char winid[NUMBUFLEN];
@@ -5375,6 +5381,7 @@ void may_trigger_winscrolled(void)
if (win_valid_any_tab(wp)) {
wp->w_last_topline = wp->w_topline;
wp->w_last_leftcol = wp->w_leftcol;
+ wp->w_last_skipcol = wp->w_skipcol;
wp->w_last_width = wp->w_width;
wp->w_last_height = wp->w_height;
}
@@ -5470,7 +5477,7 @@ static void frame_comp_pos(frame_T *topfrp, int *row, int *col)
// position changed, redraw
wp->w_winrow = *row;
wp->w_wincol = *col;
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
wp->w_redr_status = true;
wp->w_pos_changed = true;
}
@@ -5513,7 +5520,7 @@ void win_setheight_win(int height, win_T *win)
if (win->w_floating) {
win->w_float_config.height = height;
win_config_float(win, win->w_float_config);
- redraw_later(win, NOT_VALID);
+ redraw_later(win, UPD_NOT_VALID);
} else {
frame_setheight(win->w_frame, height + win->w_hsep_height + win->w_status_height);
@@ -5533,7 +5540,7 @@ void win_setheight_win(int height, win_T *win)
curtab->tp_ch_used = p_ch;
msg_row = row;
msg_col = 0;
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
redraw_cmdline = true;
}
}
@@ -5596,7 +5603,7 @@ static void frame_setheight(frame_T *curfrp, int height)
* 2: compute the room available and adjust the height to it.
* Try not to reduce the height of a window with 'winfixheight' set.
*/
- for (run = 1; run <= 2; ++run) {
+ for (run = 1; run <= 2; run++) {
room = 0;
room_reserved = 0;
FOR_ALL_FRAMES(frp, curfrp->fr_parent->fr_child) {
@@ -5669,7 +5676,7 @@ static void frame_setheight(frame_T *curfrp, int height)
* that is not enough, takes lines from frames above the current
* frame.
*/
- for (run = 0; run < 2; ++run) {
+ for (run = 0; run < 2; run++) {
if (run == 0) {
frp = curfrp->fr_next; // 1st run: start with next window
} else {
@@ -5735,13 +5742,13 @@ void win_setwidth_win(int width, win_T *wp)
if (wp->w_floating) {
wp->w_float_config.width = width;
win_config_float(wp, wp->w_float_config);
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
} else {
frame_setwidth(wp->w_frame, width + wp->w_vsep_width);
// recompute the window positions
(void)win_comp_pos();
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
}
}
@@ -5788,7 +5795,7 @@ static void frame_setwidth(frame_T *curfrp, int width)
* containing frame.
* 2: compute the room available and adjust the width to it.
*/
- for (run = 1; run <= 2; ++run) {
+ for (run = 1; run <= 2; run++) {
room = 0;
room_reserved = 0;
FOR_ALL_FRAMES(frp, curfrp->fr_parent->fr_child) {
@@ -5841,7 +5848,7 @@ static void frame_setwidth(frame_T *curfrp, int width)
* that is not enough, takes lines from frames left of the current
* frame.
*/
- for (run = 0; run < 2; ++run) {
+ for (run = 0; run < 2; run++) {
if (run == 0) {
frp = curfrp->fr_next; // 1st run: start with next window
} else {
@@ -6046,7 +6053,7 @@ void win_drag_status_line(win_T *dragwin, int offset)
cmdline_row = row;
p_ch = MAX(Rows - cmdline_row, p_ch_was_zero ? 0 : 1);
curtab->tp_ch_used = p_ch;
- redraw_all_later(SOME_VALID);
+ redraw_all_later(UPD_SOME_VALID);
showmode();
}
@@ -6153,7 +6160,7 @@ void win_drag_vsep_line(win_T *dragwin, int offset)
}
}
(void)win_comp_pos();
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
}
#define FRACTION_MULT 16384L
@@ -6291,7 +6298,7 @@ void scroll_to_fraction(win_T *wp, int prev_height)
}
win_comp_scroll(wp);
- redraw_later(wp, SOME_VALID);
+ redraw_later(wp, UPD_SOME_VALID);
wp->w_redr_status = true;
invalidate_botline_win(wp);
}
@@ -6332,7 +6339,7 @@ void win_set_inner_size(win_T *wp, bool valid_cursor)
if (!exiting && !made_cmdheight_nonzero && valid_cursor) {
scroll_to_fraction(wp, prev_height);
}
- redraw_later(wp, NOT_VALID); // SOME_VALID??
+ redraw_later(wp, UPD_NOT_VALID); // UPD_SOME_VALID??
}
if (width != wp->w_width_inner) {
@@ -6346,7 +6353,7 @@ void win_set_inner_size(win_T *wp, bool valid_cursor)
curs_columns(wp, true); // validate w_wrow
}
}
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
}
if (wp->w_buffer->terminal) {
@@ -6582,7 +6589,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u
/*
* Search forward for the last char of the file name.
- * Also allow "://" when ':' is not in 'isfname'.
+ * Also allow ":/" when ':' is not in 'isfname'.
*/
len = 0;
while (vim_isfilec(ptr[len]) || (ptr[len] == '\\' && ptr[len + 1] == ' ')
@@ -6766,7 +6773,7 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global)
wp->w_hsep_height = 0;
comp_col();
}
- redraw_all_later(SOME_VALID);
+ redraw_all_later(UPD_SOME_VALID);
} else {
// For a column or row frame, recursively call this function for all child frames
FOR_ALL_FRAMES(fp, fr->fr_child) {
@@ -7066,7 +7073,7 @@ void restore_snapshot(int idx, int close_curwin)
if (wp != NULL && close_curwin) {
win_goto(wp);
}
- redraw_all_later(NOT_VALID);
+ redraw_all_later(UPD_NOT_VALID);
}
clear_snapshot(curtab, idx);
}
@@ -7291,7 +7298,7 @@ char *check_colorcolumn(win_T *wp)
return NULL; // buffer was closed
}
- for (s = (char *)wp->w_p_cc; *s != NUL && count < 255;) {
+ for (s = wp->w_p_cc; *s != NUL && count < 255;) {
if (*s == '-' || *s == '+') {
// -N and +N: add to 'textwidth'
col = (*s == '-') ? -1 : 1;
@@ -7389,19 +7396,6 @@ int win_getid(typval_T *argvars)
return 0;
}
-int win_gotoid(typval_T *argvars)
-{
- int id = (int)tv_get_number(&argvars[0]);
-
- FOR_ALL_TAB_WINDOWS(tp, wp) {
- if (wp->handle == id) {
- goto_tabpage_win(tp, wp);
- return 1;
- }
- }
- return 0;
-}
-
void win_get_tabwin(handle_T id, int *tabnr, int *winnr)
{
*tabnr = 0;
diff --git a/test/functional/api/command_spec.lua b/test/functional/api/command_spec.lua
index 890710b6e6..440e93da0e 100644
--- a/test/functional/api/command_spec.lua
+++ b/test/functional/api/command_spec.lua
@@ -114,8 +114,8 @@ describe('nvim_create_user_command', function()
]]
eq({
- args = [[this is a\ test]],
- fargs = {"this", "is", "a test"},
+ args = [[this\ is a\ test]],
+ fargs = {"this ", "is", "a test"},
bang = false,
line1 = 1,
line2 = 1,
@@ -144,7 +144,7 @@ describe('nvim_create_user_command', function()
count = 2,
reg = "",
}, exec_lua [=[
- vim.api.nvim_command([[CommandWithLuaCallback this is a\ test]])
+ vim.api.nvim_command([[CommandWithLuaCallback this\ is a\ test]])
return result
]=])
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 72a03c409a..24d0b6da45 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -3668,6 +3668,55 @@ describe('API', function()
:^ |
]])
end)
+ it('does not move cursor or change search history/pattern #19878 #19890', function()
+ meths.buf_set_lines(0, 0, -1, true, {'foo', 'bar', 'foo', 'bar'})
+ eq({1, 0}, meths.win_get_cursor(0))
+ eq('', funcs.getreg('/'))
+ eq('', funcs.histget('search'))
+ feed(':') -- call the API in cmdline mode to test whether it changes search history
+ eq({
+ cmd = 'normal',
+ args = {'x'},
+ bang = true,
+ range = {3, 4},
+ count = -1,
+ reg = '',
+ addr = 'line',
+ magic = {
+ file = false,
+ bar = false,
+ },
+ nargs = '+',
+ nextcmd = '',
+ mods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ filter = {
+ pattern = "",
+ force = false,
+ },
+ hide = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = "",
+ tab = 0,
+ unsilent = false,
+ verbose = -1,
+ vertical = false,
+ }
+ }, meths.parse_cmd('+2;/bar/normal! x', {}))
+ eq({1, 0}, meths.win_get_cursor(0))
+ eq('', funcs.getreg('/'))
+ eq('', funcs.histget('search'))
+ end)
end)
describe('nvim_cmd', function()
it('works', function ()
diff --git a/test/functional/autocmd/winscrolled_spec.lua b/test/functional/autocmd/winscrolled_spec.lua
index 5c1b758961..12b8e7c42d 100644
--- a/test/functional/autocmd/winscrolled_spec.lua
+++ b/test/functional/autocmd/winscrolled_spec.lua
@@ -61,6 +61,20 @@ describe('WinScrolled', function()
eq(3, eval('g:scrolled'))
end)
+ it('is triggered by scrolling on a long wrapped line #19968', function()
+ local height = meths.win_get_height(0)
+ local width = meths.win_get_width(0)
+ meths.buf_set_lines(0, 0, -1, true, {('foo'):rep(height * width)})
+ meths.win_set_cursor(0, {1, height * width - 1})
+ eq(0, eval('g:scrolled'))
+ feed('gj')
+ eq(1, eval('g:scrolled'))
+ feed('0')
+ eq(2, eval('g:scrolled'))
+ feed('$')
+ eq(3, eval('g:scrolled'))
+ end)
+
it('is triggered when the window scrolls in Insert mode', function()
local height = meths.win_get_height(0)
local lines = {}
diff --git a/test/functional/editor/K_spec.lua b/test/functional/editor/K_spec.lua
index 8ad81ac3d6..3b5580540f 100644
--- a/test/functional/editor/K_spec.lua
+++ b/test/functional/editor/K_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
-local eq, clear, eval, feed, retry =
- helpers.eq, helpers.clear, helpers.eval, helpers.feed, helpers.retry
+local eq, clear, eval, feed, meths, retry =
+ helpers.eq, helpers.clear, helpers.eval, helpers.feed, helpers.meths, helpers.retry
describe('K', function()
local test_file = 'K_spec_out'
@@ -58,4 +58,11 @@ describe('K', function()
helpers.neq(bufnr, eval('bufnr()'))
end)
+ it('empty string falls back to :help #19298', function()
+ meths.set_option('keywordprg', '')
+ meths.buf_set_lines(0, 0, -1, true, {'doesnotexist'})
+ feed('K')
+ eq('E149: Sorry, no help for doesnotexist', meths.get_vvar('errmsg'))
+ end)
+
end)
diff --git a/test/functional/editor/mode_insert_spec.lua b/test/functional/editor/mode_insert_spec.lua
index e3d3cdbd85..cd51a65be3 100644
--- a/test/functional/editor/mode_insert_spec.lua
+++ b/test/functional/editor/mode_insert_spec.lua
@@ -6,12 +6,20 @@ local expect = helpers.expect
local command = helpers.command
local eq = helpers.eq
local eval = helpers.eval
+local curbuf_contents = helpers.curbuf_contents
describe('insert-mode', function()
before_each(function()
clear()
end)
+ it('indents only once after "!" keys #12894', function()
+ command('let counter = []')
+ command('set indentexpr=len(add(counter,0))')
+ feed('i<C-F>x')
+ eq(' x', curbuf_contents())
+ end)
+
it('CTRL-@', function()
-- Inserts last-inserted text, leaves insert-mode.
insert('hello')
diff --git a/test/functional/ex_cmds/normal_spec.lua b/test/functional/ex_cmds/normal_spec.lua
index f6e7dd2b3a..009f1d6516 100644
--- a/test/functional/ex_cmds/normal_spec.lua
+++ b/test/functional/ex_cmds/normal_spec.lua
@@ -1,6 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local command = helpers.command
+local funcs = helpers.funcs
local feed = helpers.feed
local expect = helpers.expect
local eq = helpers.eq
@@ -8,20 +9,30 @@ local eval = helpers.eval
before_each(clear)
-describe(':normal', function()
+describe(':normal!', function()
it('can get out of Insert mode if called from Ex mode #17924', function()
feed('gQnormal! Ifoo<CR>')
expect('foo')
end)
- it('normal! does not execute command in Ex mode when running out of characters', function()
+ it('does not execute command in Ex mode when running out of characters', function()
command('let g:var = 0')
command('normal! gQlet g:var = 1')
eq(0, eval('g:var'))
end)
- it('normal! gQinsert does not hang #17980', function()
+ it('gQinsert does not hang #17980', function()
command('normal! gQinsert')
expect('')
end)
+
+ it('can stop Visual mode without closing cmdwin vim-patch:9.0.0234', function()
+ feed('q:')
+ feed('v')
+ eq('v', funcs.mode(1))
+ eq(':', funcs.getcmdwintype())
+ command('normal! \027')
+ eq('n', funcs.mode(1))
+ eq(':', funcs.getcmdwintype())
+ end)
end)
diff --git a/test/functional/ex_cmds/source_spec.lua b/test/functional/ex_cmds/source_spec.lua
index 163ded43f9..cd1f43f9fd 100644
--- a/test/functional/ex_cmds/source_spec.lua
+++ b/test/functional/ex_cmds/source_spec.lua
@@ -166,6 +166,7 @@ describe(':source', function()
vim.g.sourced_lua = 1
vim.g.sfile_value = vim.fn.expand('<sfile>')
vim.g.stack_value = vim.fn.expand('<stack>')
+ vim.g.script_value = vim.fn.expand('<script>')
]])
command('set shellslash')
@@ -173,6 +174,7 @@ describe(':source', function()
eq(1, eval('g:sourced_lua'))
matches([[/test%.lua$]], meths.get_var('sfile_value'))
matches([[/test%.lua$]], meths.get_var('stack_value'))
+ matches([[/test%.lua$]], meths.get_var('script_value'))
os.remove(test_file)
end)
@@ -214,6 +216,7 @@ describe(':source', function()
"\ 2]=]
vim.g.sfile_value = vim.fn.expand('<sfile>')
vim.g.stack_value = vim.fn.expand('<stack>')
+ vim.g.script_value = vim.fn.expand('<script>')
]])
command('edit '..test_file)
@@ -223,6 +226,7 @@ describe(':source', function()
eq(' \\ 1\n "\\ 2', exec_lua('return _G.a'))
eq(':source (no file)', meths.get_var('sfile_value'))
eq(':source (no file)', meths.get_var('stack_value'))
+ eq(':source (no file)', meths.get_var('script_value'))
os.remove(test_file)
end)
diff --git a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
index 4d984af41e..69404039ff 100644
--- a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
+++ b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
@@ -1,8 +1,8 @@
local Screen = require('test.functional.ui.screen')
local helpers = require('test.functional.helpers')(after_each)
local lfs = require('lfs')
-local eq, eval, expect, source =
- helpers.eq, helpers.eval, helpers.expect, helpers.source
+local eq, eval, expect, exec =
+ helpers.eq, helpers.eval, helpers.expect, helpers.exec
local assert_alive = helpers.assert_alive
local clear = helpers.clear
local command = helpers.command
@@ -10,6 +10,8 @@ local feed = helpers.feed
local nvim_prog = helpers.nvim_prog
local ok = helpers.ok
local rmdir = helpers.rmdir
+local new_argv = helpers.new_argv
+local pesc = helpers.pesc
local os_kill = helpers.os_kill
local set_session = helpers.set_session
local spawn = helpers.spawn
@@ -55,11 +57,11 @@ describe(':preserve', function()
set swapfile fileformat=unix undolevels=-1
]]
- source(init)
+ exec(init)
command('edit! '..testfile)
feed('isometext<esc>')
command('preserve')
- source('redir => g:swapname | silent swapname | redir END')
+ exec('redir => g:swapname | silent swapname | redir END')
local swappath1 = eval('g:swapname')
@@ -69,12 +71,12 @@ describe(':preserve', function()
true)
set_session(nvim2)
- source(init)
+ exec(init)
-- Use the "SwapExists" event to choose the (R)ecover choice at the dialog.
command('autocmd SwapExists * let v:swapchoice = "r"')
command('silent edit! '..testfile)
- source('redir => g:swapname | silent swapname | redir END')
+ exec('redir => g:swapname | silent swapname | redir END')
local swappath2 = eval('g:swapname')
@@ -92,25 +94,28 @@ end)
describe('swapfile detection', function()
local swapdir = lfs.currentdir()..'/Xtest_swapdialog_dir'
+ local nvim0
+ -- Put swapdir at the start of the 'directory' list. #1836
+ -- Note: `set swapfile` *must* go after `set directory`: otherwise it may
+ -- attempt to create a swapfile in different directory.
+ local init = [[
+ set directory^=]]..swapdir:gsub([[\]], [[\\]])..[[//
+ set swapfile fileformat=unix undolevels=-1 hidden
+ ]]
before_each(function()
- clear()
+ nvim0 = spawn(new_argv())
+ set_session(nvim0)
rmdir(swapdir)
lfs.mkdir(swapdir)
end)
after_each(function()
+ set_session(nvim0)
command('%bwipeout!')
rmdir(swapdir)
end)
it('always show swapfile dialog #8840 #9027', function()
local testfile = 'Xtest_swapdialog_file1'
- -- Put swapdir at the start of the 'directory' list. #1836
- -- Note: `set swapfile` *must* go after `set directory`: otherwise it may
- -- attempt to create a swapfile in different directory.
- local init = [[
- set directory^=]]..swapdir:gsub([[\]], [[\\]])..[[//
- set swapfile fileformat=unix undolevels=-1 hidden
- ]]
local expected_no_dialog = '^'..(' '):rep(256)..'|\n'
for _=1,37 do
@@ -119,19 +124,17 @@ describe('swapfile detection', function()
expected_no_dialog = expected_no_dialog..testfile..(' '):rep(216)..'0,0-1 All|\n'
expected_no_dialog = expected_no_dialog..(' '):rep(256)..'|\n'
- source(init)
+ exec(init)
command('edit! '..testfile)
feed('isometext<esc>')
command('preserve')
- os_kill(eval('getpid()'))
-- Start another Nvim instance.
- local nvim2 = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed'},
- true)
+ local nvim2 = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed'}, true, nil, true)
set_session(nvim2)
local screen2 = Screen.new(256, 40)
screen2:attach()
- source(init)
+ exec(init)
-- With shortmess+=F
command('set shortmess+=F')
@@ -176,5 +179,88 @@ describe('swapfile detection', function()
}
})
feed('<cr>')
+
+ nvim2:close()
+ end)
+
+ -- oldtest: Test_swap_prompt_splitwin()
+ it('selecting "q" in the attention prompt', function()
+ exec(init)
+ command('edit Xfile1')
+ command('preserve') -- should help to make sure the swap file exists
+
+ local screen = Screen.new(75, 18)
+ screen:set_default_attr_ids({
+ [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
+ [1] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg
+ })
+
+ local nvim1 = spawn(new_argv(), true, nil, true)
+ set_session(nvim1)
+ screen:attach()
+ exec(init)
+ feed(':split Xfile1\n')
+ screen:expect({
+ any = pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^')
+ })
+ feed('q')
+ feed(':<CR>')
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ : |
+ ]])
+ nvim1:close()
+
+ local nvim2 = spawn(new_argv(), true, nil, true)
+ set_session(nvim2)
+ screen:attach()
+ exec(init)
+ command('set more')
+ command('au bufadd * let foo_w = wincol()')
+ feed(':e Xfile1<CR>')
+ screen:expect({any = pesc('{1:-- More --}^')})
+ feed('<Space>')
+ screen:expect({
+ any = pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^')
+ })
+ feed('q')
+ command([[echo 'hello']])
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ hello |
+ ]])
+ nvim2:close()
end)
end)
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 981cfc306e..93fb0f245e 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -761,6 +761,7 @@ function module.pending_c_parser(pending_fn)
pending_fn 'no C parser, skipping'
return true
end
+ module.exec_lua [[vim._ts_remove_language 'c']]
return false
end
diff --git a/test/functional/legacy/buffer_spec.lua b/test/functional/legacy/buffer_spec.lua
new file mode 100644
index 0000000000..acaa9a51f1
--- /dev/null
+++ b/test/functional/legacy/buffer_spec.lua
@@ -0,0 +1,59 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear, source = helpers.clear, helpers.source
+local call, eq, meths = helpers.call, helpers.eq, helpers.meths
+
+local function expected_empty()
+ eq({}, meths.get_vvar('errors'))
+end
+
+describe('buffer', function()
+ before_each(function()
+ clear()
+ meths.ui_attach(80, 24, {})
+ meths.set_option('hidden', false)
+ end)
+
+ it('deleting a modified buffer with :confirm', function()
+ source([[
+ func Test_bdel_with_confirm()
+ new
+ call setline(1, 'test')
+ call assert_fails('bdel', 'E89:')
+ call nvim_input('c')
+ confirm bdel
+ call assert_equal(2, winnr('$'))
+ call assert_equal(1, &modified)
+ call nvim_input('n')
+ confirm bdel
+ call assert_equal(1, winnr('$'))
+ endfunc
+ ]])
+ call('Test_bdel_with_confirm')
+ expected_empty()
+ end)
+
+ it('editing another buffer from a modified buffer with :confirm', function()
+ source([[
+ func Test_goto_buf_with_confirm()
+ new Xfile
+ enew
+ call setline(1, 'test')
+ call assert_fails('b Xfile', 'E37:')
+ call nvim_input('c')
+ call assert_fails('confirm b Xfile', 'E37:')
+ call assert_equal(1, &modified)
+ call assert_equal('', @%)
+ call nvim_input('y')
+ call assert_fails('confirm b Xfile', 'E37:')
+ call assert_equal(1, &modified)
+ call assert_equal('', @%)
+ call nvim_input('n')
+ confirm b Xfile
+ call assert_equal('Xfile', @%)
+ close!
+ endfunc
+ ]])
+ call('Test_goto_buf_with_confirm')
+ expected_empty()
+ end)
+end)
diff --git a/test/functional/legacy/cmdline_spec.lua b/test/functional/legacy/cmdline_spec.lua
index cf02636890..99d2d0f30e 100644
--- a/test/functional/legacy/cmdline_spec.lua
+++ b/test/functional/legacy/cmdline_spec.lua
@@ -1,9 +1,11 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
+local command = helpers.command
local feed = helpers.feed
local feed_command = helpers.feed_command
local exec = helpers.exec
+local pesc = helpers.pesc
describe('cmdline', function()
before_each(clear)
@@ -18,8 +20,6 @@ describe('cmdline', function()
[3] = {reverse = true};
[4] = {bold = true, foreground = Screen.colors.Blue1};
}
- -- TODO(bfredl): redraw with tabs is severly broken. fix it
- feed_command [[ set display-=msgsep ]]
feed_command([[call setline(1, range(30))]])
screen:expect([[
@@ -60,7 +60,7 @@ describe('cmdline', function()
{4:~ }|
|
|
- :tabnew |
+ |
]]}
feed [[gt]]
@@ -141,3 +141,81 @@ describe('cmdline', function()
]])
end)
end)
+
+describe('cmdwin', function()
+ before_each(clear)
+
+ -- oldtest: Test_cmdwin_interrupted()
+ it('still uses a new buffer when interrupting more prompt on open', function()
+ local screen = Screen.new(30, 16)
+ screen:set_default_attr_ids({
+ [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
+ [1] = {bold = true, reverse = true}, -- StatusLine
+ [2] = {reverse = true}, -- StatusLineNC
+ [3] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg
+ [4] = {bold = true}, -- ModeMsg
+ })
+ screen:attach()
+ command('set more')
+ command('autocmd WinNew * highlight')
+ feed('q:')
+ screen:expect({any = pesc('{3:-- More --}^')})
+ feed('q')
+ screen:expect([[
+ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {2:[No Name] }|
+ {0::}^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {1:[Command Line] }|
+ |
+ ]])
+ feed([[aecho 'done']])
+ screen:expect([[
+ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {2:[No Name] }|
+ {0::}echo 'done'^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {1:[Command Line] }|
+ {4:-- INSERT --} |
+ ]])
+ feed('<CR>')
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ done |
+ ]])
+ end)
+end)
diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua
index f9647f5b6a..4226bcebac 100644
--- a/test/functional/lua/diagnostic_spec.lua
+++ b/test/functional/lua/diagnostic_spec.lua
@@ -128,6 +128,28 @@ describe('vim.diagnostic', function()
eq('Diagnostic #1', result[1].message)
end)
+ it('removes diagnostics from the cache when a buffer is removed', function()
+ eq(2, exec_lua [[
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ local other_bufnr = vim.fn.bufadd('test | test')
+ local lines = vim.api.nvim_buf_get_lines(diagnostic_bufnr, 0, -1, true)
+ vim.api.nvim_buf_set_lines(other_bufnr, 0, 1, false, lines)
+ vim.cmd('bunload! ' .. other_bufnr)
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ make_error('Diagnostic #2', 2, 1, 2, 1),
+ })
+ vim.diagnostic.set(diagnostic_ns, other_bufnr, {
+ make_error('Diagnostic #3', 3, 1, 3, 1),
+ })
+ vim.api.nvim_set_current_buf(other_bufnr)
+ vim.opt_local.buflisted = true
+ vim.cmd('bwipeout!')
+ return #vim.diagnostic.get()
+ ]])
+ end)
+
it('resolves buffer number 0 to the current buffer', function()
eq(2, exec_lua [[
vim.api.nvim_set_current_buf(diagnostic_bufnr)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 2b249b7a69..f2fb661b70 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -2721,6 +2721,39 @@ describe('lua stdlib', function()
]]
end)
end)
+
+ describe('vim.iconv', function()
+ it('can convert strings', function()
+ eq('hello', exec_lua[[
+ return vim.iconv('hello', 'latin1', 'utf-8')
+ ]])
+ end)
+
+ it('can validate arguments', function()
+ eq({false, 'Expected at least 3 arguments'}, exec_lua[[
+ return {pcall(vim.iconv, 'hello')}
+ ]])
+
+ eq({false, 'bad argument #3 to \'?\' (expected string)'}, exec_lua[[
+ return {pcall(vim.iconv, 'hello', 'utf-8', true)}
+ ]])
+ end)
+
+ it('can handle bad encodings', function()
+ eq(NIL, exec_lua[[
+ return vim.iconv('hello', 'foo', 'bar')
+ ]])
+ end)
+
+ it('can handle strings with NUL bytes', function()
+ eq(7, exec_lua[[
+ local a = string.char(97, 98, 99, 0, 100, 101, 102) -- abc\0def
+ return string.len(vim.iconv(a, 'latin1', 'utf-8'))
+ ]])
+ end)
+
+ end)
+
end)
describe('lua: builtin modules', function()
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index cd7415de90..fa731f6faf 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -3181,4 +3181,32 @@ describe('LSP', function()
}
end)
end)
+
+ describe('cmd', function()
+ it('can connect to lsp server via rpc.connect', function()
+ local result = exec_lua [[
+ local uv = vim.loop
+ local server = uv.new_tcp()
+ local init = nil
+ server:bind('127.0.0.1', 0)
+ server:listen(127, function(err)
+ assert(not err, err)
+ local socket = uv.new_tcp()
+ server:accept(socket)
+ socket:read_start(require('vim.lsp.rpc').create_read_loop(function(body)
+ init = body
+ socket:close()
+ end))
+ end)
+ local port = server:getsockname().port
+ vim.lsp.start({ name = 'dummy', cmd = vim.lsp.rpc.connect('127.0.0.1', port) })
+ vim.wait(1000, function() return init ~= nil end)
+ assert(init, "server must receive `initialize` request")
+ server:close()
+ server:shutdown()
+ return vim.json.decode(init)
+ ]]
+ eq(result.method, "initialize")
+ end)
+ end)
end)
diff --git a/test/functional/plugin/man_spec.lua b/test/functional/plugin/man_spec.lua
index c8da5a711f..9304aa6da9 100644
--- a/test/functional/plugin/man_spec.lua
+++ b/test/functional/plugin/man_spec.lua
@@ -6,6 +6,12 @@ local funcs = helpers.funcs
local nvim_prog = helpers.nvim_prog
local matches = helpers.matches
+clear()
+if funcs.executable('man') == 0 then
+ pending('missing "man" command', function() end)
+ return
+end
+
describe(':Man', function()
before_each(function()
clear()
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 99f69ef556..4f444316c3 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -297,6 +297,199 @@ describe('TUI', function()
]], attrs)
end)
+ it('accepts mouse wheel events #19992', function()
+ child_session:request('nvim_command', [[
+ set number nostartofline nowrap mousescroll=hor:1,ver:1
+ call setline(1, repeat([join(range(10), '----')], 10))
+ vsplit
+ ]])
+ screen:expect([[
+ {11: 1 }{1:0}----1----2----3----4│{11: 1 }0----1----2----3----|
+ {11: 2 }0----1----2----3----4│{11: 2 }0----1----2----3----|
+ {11: 3 }0----1----2----3----4│{11: 3 }0----1----2----3----|
+ {11: 4 }0----1----2----3----4│{11: 4 }0----1----2----3----|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ -- <ScrollWheelDown> in active window
+ feed_data('\027[<65;8;1M')
+ screen:expect([[
+ {11: 2 }{1:0}----1----2----3----4│{11: 1 }0----1----2----3----|
+ {11: 3 }0----1----2----3----4│{11: 2 }0----1----2----3----|
+ {11: 4 }0----1----2----3----4│{11: 3 }0----1----2----3----|
+ {11: 5 }0----1----2----3----4│{11: 4 }0----1----2----3----|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ -- <ScrollWheelDown> in inactive window
+ feed_data('\027[<65;48;1M')
+ screen:expect([[
+ {11: 2 }{1:0}----1----2----3----4│{11: 2 }0----1----2----3----|
+ {11: 3 }0----1----2----3----4│{11: 3 }0----1----2----3----|
+ {11: 4 }0----1----2----3----4│{11: 4 }0----1----2----3----|
+ {11: 5 }0----1----2----3----4│{11: 5 }0----1----2----3----|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ -- <ScrollWheelRight> in active window
+ feed_data('\027[<67;8;1M')
+ screen:expect([[
+ {11: 2 }{1:-}---1----2----3----4-│{11: 2 }0----1----2----3----|
+ {11: 3 }----1----2----3----4-│{11: 3 }0----1----2----3----|
+ {11: 4 }----1----2----3----4-│{11: 4 }0----1----2----3----|
+ {11: 5 }----1----2----3----4-│{11: 5 }0----1----2----3----|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ -- <ScrollWheelRight> in inactive window
+ feed_data('\027[<67;48;1M')
+ screen:expect([[
+ {11: 2 }{1:-}---1----2----3----4-│{11: 2 }----1----2----3----4|
+ {11: 3 }----1----2----3----4-│{11: 3 }----1----2----3----4|
+ {11: 4 }----1----2----3----4-│{11: 4 }----1----2----3----4|
+ {11: 5 }----1----2----3----4-│{11: 5 }----1----2----3----4|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ -- <S-ScrollWheelDown> in active window
+ feed_data('\027[<69;8;1M')
+ screen:expect([[
+ {11: 5 }{1:-}---1----2----3----4-│{11: 2 }----1----2----3----4|
+ {11: 6 }----1----2----3----4-│{11: 3 }----1----2----3----4|
+ {11: 7 }----1----2----3----4-│{11: 4 }----1----2----3----4|
+ {11: 8 }----1----2----3----4-│{11: 5 }----1----2----3----4|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ -- <S-ScrollWheelDown> in inactive window
+ feed_data('\027[<69;48;1M')
+ screen:expect([[
+ {11: 5 }{1:-}---1----2----3----4-│{11: 5 }----1----2----3----4|
+ {11: 6 }----1----2----3----4-│{11: 6 }----1----2----3----4|
+ {11: 7 }----1----2----3----4-│{11: 7 }----1----2----3----4|
+ {11: 8 }----1----2----3----4-│{11: 8 }----1----2----3----4|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ -- <S-ScrollWheelRight> in active window
+ feed_data('\027[<71;8;1M')
+ screen:expect([[
+ {11: 5 }{1:-}---6----7----8----9 │{11: 5 }----1----2----3----4|
+ {11: 6 }----6----7----8----9 │{11: 6 }----1----2----3----4|
+ {11: 7 }----6----7----8----9 │{11: 7 }----1----2----3----4|
+ {11: 8 }----6----7----8----9 │{11: 8 }----1----2----3----4|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ -- <S-ScrollWheelRight> in inactive window
+ feed_data('\027[<71;48;1M')
+ screen:expect([[
+ {11: 5 }{1:-}---6----7----8----9 │{11: 5 }5----6----7----8----|
+ {11: 6 }----6----7----8----9 │{11: 6 }5----6----7----8----|
+ {11: 7 }----6----7----8----9 │{11: 7 }5----6----7----8----|
+ {11: 8 }----6----7----8----9 │{11: 8 }5----6----7----8----|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ -- <ScrollWheelUp> in active window
+ feed_data('\027[<64;8;1M')
+ screen:expect([[
+ {11: 4 }----6----7----8----9 │{11: 5 }5----6----7----8----|
+ {11: 5 }{1:-}---6----7----8----9 │{11: 6 }5----6----7----8----|
+ {11: 6 }----6----7----8----9 │{11: 7 }5----6----7----8----|
+ {11: 7 }----6----7----8----9 │{11: 8 }5----6----7----8----|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ -- <ScrollWheelUp> in inactive window
+ feed_data('\027[<64;48;1M')
+ screen:expect([[
+ {11: 4 }----6----7----8----9 │{11: 4 }5----6----7----8----|
+ {11: 5 }{1:-}---6----7----8----9 │{11: 5 }5----6----7----8----|
+ {11: 6 }----6----7----8----9 │{11: 6 }5----6----7----8----|
+ {11: 7 }----6----7----8----9 │{11: 7 }5----6----7----8----|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ -- <ScrollWheelLeft> in active window
+ feed_data('\027[<66;8;1M')
+ screen:expect([[
+ {11: 4 }5----6----7----8----9│{11: 4 }5----6----7----8----|
+ {11: 5 }5{1:-}---6----7----8----9│{11: 5 }5----6----7----8----|
+ {11: 6 }5----6----7----8----9│{11: 6 }5----6----7----8----|
+ {11: 7 }5----6----7----8----9│{11: 7 }5----6----7----8----|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ -- <ScrollWheelLeft> in inactive window
+ feed_data('\027[<66;48;1M')
+ screen:expect([[
+ {11: 4 }5----6----7----8----9│{11: 4 }-5----6----7----8---|
+ {11: 5 }5{1:-}---6----7----8----9│{11: 5 }-5----6----7----8---|
+ {11: 6 }5----6----7----8----9│{11: 6 }-5----6----7----8---|
+ {11: 7 }5----6----7----8----9│{11: 7 }-5----6----7----8---|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ -- <S-ScrollWheelUp> in active window
+ feed_data('\027[<68;8;1M')
+ screen:expect([[
+ {11: 1 }5----6----7----8----9│{11: 4 }-5----6----7----8---|
+ {11: 2 }5----6----7----8----9│{11: 5 }-5----6----7----8---|
+ {11: 3 }5----6----7----8----9│{11: 6 }-5----6----7----8---|
+ {11: 4 }5{1:-}---6----7----8----9│{11: 7 }-5----6----7----8---|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ -- <S-ScrollWheelUp> in inactive window
+ feed_data('\027[<68;48;1M')
+ screen:expect([[
+ {11: 1 }5----6----7----8----9│{11: 1 }-5----6----7----8---|
+ {11: 2 }5----6----7----8----9│{11: 2 }-5----6----7----8---|
+ {11: 3 }5----6----7----8----9│{11: 3 }-5----6----7----8---|
+ {11: 4 }5{1:-}---6----7----8----9│{11: 4 }-5----6----7----8---|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ -- <S-ScrollWheelLeft> in active window
+ feed_data('\027[<70;8;1M')
+ screen:expect([[
+ {11: 1 }0----1----2----3----4│{11: 1 }-5----6----7----8---|
+ {11: 2 }0----1----2----3----4│{11: 2 }-5----6----7----8---|
+ {11: 3 }0----1----2----3----4│{11: 3 }-5----6----7----8---|
+ {11: 4 }0----1----2----3----{1:4}│{11: 4 }-5----6----7----8---|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ -- <S-ScrollWheelLeft> in inactive window
+ feed_data('\027[<70;48;1M')
+ screen:expect([[
+ {11: 1 }0----1----2----3----4│{11: 1 }0----1----2----3----|
+ {11: 2 }0----1----2----3----4│{11: 2 }0----1----2----3----|
+ {11: 3 }0----1----2----3----4│{11: 3 }0----1----2----3----|
+ {11: 4 }0----1----2----3----{1:4}│{11: 4 }0----1----2----3----|
+ {5:[No Name] [+] }{1:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ end)
+
it('accepts keypad keys from kitty keyboard protocol #19180', function()
feed_data('i')
feed_data(funcs.nr2char(57399)) -- KP_0
diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua
index 5ec0a8a060..4b0bd1eb50 100644
--- a/test/functional/treesitter/highlight_spec.lua
+++ b/test/functional/treesitter/highlight_spec.lua
@@ -6,11 +6,14 @@ local insert = helpers.insert
local exec_lua = helpers.exec_lua
local feed = helpers.feed
local pending_c_parser = helpers.pending_c_parser
+local command = helpers.command
+local meths = helpers.meths
+local eq = helpers.eq
before_each(clear)
local hl_query = [[
- (ERROR) @ErrorMsg
+ (ERROR) @error
"if" @keyword
"else" @keyword
@@ -23,23 +26,24 @@ local hl_query = [[
"enum" @type
"extern" @type
- (string_literal) @string.nonexistent-specializer-for-string.should-fallback-to-string
+ ; nonexistent specializer for string should fallback to string
+ (string_literal) @string.nonexistent_specializer
(number_literal) @number
(char_literal) @string
(type_identifier) @type
- ((type_identifier) @Special (#eq? @Special "LuaRef"))
+ ((type_identifier) @constant.builtin (#eq? @constant.builtin "LuaRef"))
(primitive_type) @type
(sized_type_specifier) @type
; Use lua regexes
- ((identifier) @Identifier (#contains? @Identifier "lua_"))
+ ((identifier) @function (#contains? @function "lua_"))
((identifier) @Constant (#lua-match? @Constant "^[A-Z_]+$"))
- ((identifier) @Normal (#vim-match? @Constant "^lstate$"))
+ ((identifier) @Normal (#vim-match? @Normal "^lstate$"))
- ((binary_expression left: (identifier) @WarningMsg.left right: (identifier) @WarningMsg.right) (#eq? @WarningMsg.left @WarningMsg.right))
+ ((binary_expression left: (identifier) @warning.left right: (identifier) @warning.right) (#eq? @warning.left @warning.right))
(comment) @comment
]]
@@ -103,6 +107,7 @@ describe('treesitter highlighting', function()
}
exec_lua([[ hl_query = ... ]], hl_query)
+ command [[ hi link @warning WarningMsg ]]
end)
it('is updated with edits', function()
@@ -547,7 +552,7 @@ describe('treesitter highlighting', function()
-- This will change ONLY the literal strings to look like comments
-- The only literal string is the "vim.schedule: expected function" in this test.
- exec_lua [[vim.cmd("highlight link cString comment")]]
+ exec_lua [[vim.cmd("highlight link @string.nonexistent_specializer comment")]]
screen:expect{grid=[[
{2:/// Schedule Lua callback on main loop's event queue} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
@@ -612,6 +617,11 @@ describe('treesitter highlighting', function()
-- bold will not be overwritten at the moment
[12] = {background = Screen.colors.Red, bold = true, foreground = Screen.colors.Grey100};
}}
+
+ eq({
+ {capture='Error', priority='101'};
+ {capture='type'};
+ }, exec_lua [[ return vim.treesitter.get_captures_at_position(0, 0, 2) ]])
end)
it("allows to use captures with dots (don't use fallback when specialization of foo exists)", function()
@@ -642,11 +652,13 @@ describe('treesitter highlighting', function()
|
]]}
+ command [[
+ hi link @foo.bar Type
+ hi link @foo String
+ ]]
exec_lua [[
local parser = vim.treesitter.get_parser(0, "c", {})
local highlighter = vim.treesitter.highlighter
- highlighter.hl_map['foo.bar'] = 'Type'
- highlighter.hl_map['foo'] = 'String'
test_hl = highlighter.new(parser, {queries = {c = "(primitive_type) @foo.bar (string_literal) @foo"}})
]]
@@ -670,6 +682,29 @@ describe('treesitter highlighting', function()
{1:~ }|
|
]]}
+
+ -- clearing specialization reactivates fallback
+ command [[ hi clear @foo.bar ]]
+ screen:expect{grid=[[
+ {5:char}* x = {5:"Will somebody ever read this?"}; |
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
end)
it("supports conceal attribute", function()
@@ -712,32 +747,26 @@ describe('treesitter highlighting', function()
]]}
end)
- it("hl_map has the correct fallback behavior", function()
- exec_lua [[
- local hl_map = vim.treesitter.highlighter.hl_map
- hl_map["foo"] = 1
- hl_map["foo.bar"] = 2
- hl_map["foo.bar.baz"] = 3
-
- assert(hl_map["foo"] == 1)
- assert(hl_map["foo.a.b.c.d"] == 1)
- assert(hl_map["foo.bar"] == 2)
- assert(hl_map["foo.bar.a.b.c.d"] == 2)
- assert(hl_map["foo.bar.baz"] == 3)
- assert(hl_map["foo.bar.baz.d"] == 3)
-
- hl_map["FOO"] = 1
- hl_map["FOO.BAR"] = 2
- assert(hl_map["FOO.BAR.BAZ"] == 2)
-
- hl_map["foo.missing.exists"] = 3
- assert(hl_map["foo.missing"] == 1)
- assert(hl_map["foo.missing.exists"] == 3)
- assert(hl_map["foo.missing.exists.bar"] == 3)
- assert(hl_map["total.nonsense.but.a.lot.of.dots"] == nil)
- -- It will not perform a second look up of this variable but return a sentinel value
- assert(hl_map["total.nonsense.but.a.lot.of.dots"] == "__notfound")
- ]]
-
+ it("@foo.bar groups has the correct fallback behavior", function()
+ local get_hl = function(name) return meths.get_hl_by_name(name,1).foreground end
+ meths.set_hl(0, "@foo", {fg = 1})
+ meths.set_hl(0, "@foo.bar", {fg = 2})
+ meths.set_hl(0, "@foo.bar.baz", {fg = 3})
+
+ eq(1, get_hl"@foo")
+ eq(1, get_hl"@foo.a.b.c.d")
+ eq(2, get_hl"@foo.bar")
+ eq(2, get_hl"@foo.bar.a.b.c.d")
+ eq(3, get_hl"@foo.bar.baz")
+ eq(3, get_hl"@foo.bar.baz.d")
+
+ -- lookup is case insensitive
+ eq(2, get_hl"@FOO.BAR.SPAM")
+
+ meths.set_hl(0, "@foo.missing.exists", {fg = 3})
+ eq(1, get_hl"@foo.missing")
+ eq(3, get_hl"@foo.missing.exists")
+ eq(3, get_hl"@foo.missing.exists.bar")
+ eq(nil, get_hl"@total.nonsense.but.a.lot.of.dots")
end)
end)
diff --git a/test/functional/treesitter/language_spec.lua b/test/functional/treesitter/language_spec.lua
index 30585be328..8e9941d797 100644
--- a/test/functional/treesitter/language_spec.lua
+++ b/test/functional/treesitter/language_spec.lua
@@ -7,10 +7,11 @@ local exec_lua = helpers.exec_lua
local pcall_err = helpers.pcall_err
local matches = helpers.matches
local pending_c_parser = helpers.pending_c_parser
+local insert = helpers.insert
before_each(clear)
-describe('treesitter API', function()
+describe('treesitter language API', function()
-- error tests not requiring a parser library
it('handles missing language', function()
eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
@@ -26,6 +27,11 @@ describe('treesitter API', function()
eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
pcall_err(exec_lua, "parser = vim.treesitter.inspect_language('borklang')"))
+
+ if not pending_c_parser(pending) then
+ matches("Error executing lua: Failed to load parser: uv_dlsym: .+",
+ pcall_err(exec_lua, 'vim.treesitter.require_language("c", nil, false, "borklang")'))
+ end
end)
it('inspects language', function()
@@ -79,5 +85,35 @@ describe('treesitter API', function()
eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
pcall_err(exec_lua, "new_parser = vim.treesitter.get_parser(0)"))
end)
+
+ it('retrieve the tree given a range', function ()
+ if pending_c_parser(pending) then return end
+ insert([[
+ int main() {
+ int x = 3;
+ }]])
+
+ exec_lua([[
+ langtree = vim.treesitter.get_parser(0, "c")
+ tree = langtree:tree_for_range({1, 3, 1, 3})
+ ]])
+
+ eq('<node translation_unit>', exec_lua('return tostring(tree:root())'))
+ end)
+
+ it('retrieve the node given a range', function ()
+ if pending_c_parser(pending) then return end
+ insert([[
+ int main() {
+ int x = 3;
+ }]])
+
+ exec_lua([[
+ langtree = vim.treesitter.get_parser(0, "c")
+ node = langtree:named_node_for_range({1, 3, 1, 3})
+ ]])
+
+ eq('<node primitive_type>', exec_lua('return tostring(node)'))
+ end)
end)
diff --git a/test/functional/treesitter/node_spec.lua b/test/functional/treesitter/node_spec.lua
index 21c287644e..87ce1b973c 100644
--- a/test/functional/treesitter/node_spec.lua
+++ b/test/functional/treesitter/node_spec.lua
@@ -59,4 +59,53 @@ describe('treesitter node API', function()
exec_lua 'node = node:prev_named_sibling()'
eq('int x', lua_eval('node_text(node)'))
end)
+
+ it('can retrieve the children of a node', function()
+ insert([[
+ int main() {
+ int x = 3;
+ }]])
+
+ local len = exec_lua([[
+ tree = vim.treesitter.get_parser(0, "c"):parse()[1]
+ node = tree:root():child(0)
+ children = node:named_children()
+
+ return #children
+ ]])
+
+ eq(3, len)
+ eq('<node compound_statement>', lua_eval('tostring(children[3])'))
+ end)
+
+ it('can retrieve the tree root given a node', function()
+ insert([[
+ int main() {
+ int x = 3;
+ }]])
+
+ exec_lua([[
+ tree = vim.treesitter.get_parser(0, "c"):parse()[1]
+ root = tree:root()
+ node = root:child(0):child(2)
+ ]])
+
+ eq(lua_eval('tostring(root)'), lua_eval('tostring(node:root())'))
+ end)
+
+ it('can compute the byte length of a node', function()
+ insert([[
+ int main() {
+ int x = 3;
+ }]])
+
+ exec_lua([[
+ tree = vim.treesitter.get_parser(0, "c"):parse()[1]
+ root = tree:root()
+ child = root:child(0):child(0)
+ ]])
+
+ eq(28, lua_eval('root:byte_length()'))
+ eq(3, lua_eval('child:byte_length()'))
+ end)
end)
diff --git a/test/functional/treesitter/utils_spec.lua b/test/functional/treesitter/utils_spec.lua
new file mode 100644
index 0000000000..4f4c18a748
--- /dev/null
+++ b/test/functional/treesitter/utils_spec.lua
@@ -0,0 +1,33 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local clear = helpers.clear
+local insert = helpers.insert
+local eq = helpers.eq
+local exec_lua = helpers.exec_lua
+local pending_c_parser = helpers.pending_c_parser
+
+before_each(clear)
+
+describe('treesitter utils', function()
+ before_each(clear)
+
+ it('can find an ancestor', function()
+ if pending_c_parser(pending) then return end
+
+ insert([[
+ int main() {
+ int x = 3;
+ }]])
+
+ exec_lua([[
+ parser = vim.treesitter.get_parser(0, "c")
+ tree = parser:parse()[1]
+ root = tree:root()
+ ancestor = root:child(0)
+ child = ancestor:child(0)
+ ]])
+
+ eq(true, exec_lua('return vim.treesitter.is_ancestor(ancestor, child)'))
+ eq(false, exec_lua('return vim.treesitter.is_ancestor(child, ancestor)'))
+ end)
+end)
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 4e3d62509c..5ffe9ddaad 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -2333,6 +2333,51 @@ describe("'winhighlight' highlight", function()
helpers.assert_alive()
end)
+
+ it('can redraw statusline on cursor movement', function()
+ screen:try_resize(40, 8)
+ exec [[
+ set statusline=%f%=%#Background1#%l,%c%V\ %P
+ split
+ ]]
+ insert [[
+ some text
+ more text]]
+ screen:expect{grid=[[
+ some text |
+ more tex^t |
+ {0:~ }|
+ {3:[No Name] }{1:2,9 All}|
+ some text |
+ more text |
+ {4:[No Name] }{1:1,1 All}|
+ |
+ ]]}
+
+ command 'set winhl=Background1:Background2'
+ screen:expect{grid=[[
+ some text |
+ more tex^t |
+ {0:~ }|
+ {3:[No Name] }{5:2,9 All}|
+ some text |
+ more text |
+ {4:[No Name] }{1:1,1 All}|
+ |
+ ]]}
+
+ feed 'k'
+ screen:expect{grid=[[
+ some tex^t |
+ more text |
+ {0:~ }|
+ {3:[No Name] }{5:1,9 All}|
+ some text |
+ more text |
+ {4:[No Name] }{1:1,1 All}|
+ |
+ ]]}
+ end)
end)
describe('highlight namespaces', function()
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index 2cff7c1cf4..522c9ccba2 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -1077,10 +1077,10 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
]]}
end)
- it('redraws NOT_VALID correctly after message', function()
- -- edge case: only one window was set NOT_VALID. Original report
+ it('redraws UPD_NOT_VALID correctly after message', function()
+ -- edge case: only one window was set UPD_NOT_VALID. Original report
-- used :make, but fake it using one command to set the current
- -- window NOT_VALID and another to show a long message.
+ -- window UPD_NOT_VALID and another to show a long message.
command("set more")
feed(':new<cr><c-w><c-w>')
screen:expect{grid=[[
diff --git a/test/functional/ui/multigrid_spec.lua b/test/functional/ui/multigrid_spec.lua
index b30aa67fd3..78a1e8c677 100644
--- a/test/functional/ui/multigrid_spec.lua
+++ b/test/functional/ui/multigrid_spec.lua
@@ -3,7 +3,9 @@ local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local feed, command, insert = helpers.feed, helpers.command, helpers.insert
local eq = helpers.eq
+local funcs = helpers.funcs
local meths = helpers.meths
+local curwin = helpers.curwin
local poke_eventloop = helpers.poke_eventloop
@@ -871,6 +873,15 @@ describe('ext_multigrid', function()
before_each(function()
screen:try_resize_grid(2, 60, 20)
end)
+
+ it('winwidth() winheight() getwininfo() return inner width and height #19743', function()
+ eq(60, funcs.winwidth(0))
+ eq(20, funcs.winheight(0))
+ local win_info = funcs.getwininfo(curwin().id)[1]
+ eq(60, win_info.width)
+ eq(20, win_info.height)
+ end)
+
it('gets written till grid width', function()
insert(('a'):rep(60).."\n")
diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua
index e11cd1e859..dcd4ad3d9a 100644
--- a/test/functional/ui/popupmenu_spec.lua
+++ b/test/functional/ui/popupmenu_spec.lua
@@ -1990,6 +1990,22 @@ describe('builtin popupmenu', function()
efine unplace^ |
]])
+ -- Pressing <Left> after that should move the cursor
+ feed('<Left>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {4: }|
+ :sign define jump list place und|
+ efine unplac^e |
+ ]])
+ feed('<End>')
+
-- Pressing <C-D> when the popup menu is displayed should remove the popup
-- menu
feed('<C-U>sign <Tab><C-D>')
diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua
index 98398bc7a1..58ffa3bda8 100644
--- a/test/functional/ui/wildmode_spec.lua
+++ b/test/functional/ui/wildmode_spec.lua
@@ -461,20 +461,20 @@ end)
describe('command line completion', function()
local screen
before_each(function()
+ clear()
screen = Screen.new(40, 5)
screen:set_default_attr_ids({
[1] = {bold = true, foreground = Screen.colors.Blue1},
[2] = {foreground = Screen.colors.Grey0, background = Screen.colors.Yellow},
[3] = {bold = true, reverse = true},
})
+ screen:attach()
end)
after_each(function()
os.remove('Xtest-functional-viml-compl-dir')
end)
it('lists directories with empty PATH', function()
- clear()
- screen:attach()
local tmp = funcs.tempname()
command('e '.. tmp)
command('cd %:h')
@@ -491,8 +491,6 @@ describe('command line completion', function()
end)
it('completes env var names #9681', function()
- clear()
- screen:attach()
command('let $XTEST_1 = "foo" | let $XTEST_2 = "bar"')
command('set wildmenu wildmode=full')
feed(':!echo $XTEST_<tab>')
@@ -521,6 +519,58 @@ describe('command line completion', function()
:!echo $XTEST_1AaあB^ |
]])
end)
+
+ it('does not leak memory with <S-Tab> with wildmenu and only one match #19874', function()
+ meths.set_option('wildmenu', true)
+ meths.set_option('wildmode', 'full')
+ meths.set_option('wildoptions', 'pum')
+
+ feed(':sign unpla<S-Tab>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ :sign unplace^ |
+ ]])
+
+ feed('<Space>buff<Tab>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ :sign unplace buffer=^ |
+ ]])
+ end)
+
+ it('does not show matches with <S-Tab> without wildmenu with wildmode=full', function()
+ meths.set_option('wildmenu', false)
+ meths.set_option('wildmode', 'full')
+
+ feed(':sign <S-Tab>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ :sign unplace^ |
+ ]])
+ end)
+
+ it('shows matches with <S-Tab> without wildmenu with wildmode=list', function()
+ meths.set_option('wildmenu', false)
+ meths.set_option('wildmode', 'list')
+
+ feed(':sign <S-Tab>')
+ screen:expect([[
+ {3: }|
+ :sign define |
+ define list undefine |
+ jump place unplace |
+ :sign unplace^ |
+ ]])
+ end)
end)
describe('ui/ext_wildmenu', function()
diff --git a/test/functional/ui/winbar_spec.lua b/test/functional/ui/winbar_spec.lua
index 8976c4371f..ece27ec3ff 100644
--- a/test/functional/ui/winbar_spec.lua
+++ b/test/functional/ui/winbar_spec.lua
@@ -7,6 +7,8 @@ local meths = helpers.meths
local eq = helpers.eq
local poke_eventloop = helpers.poke_eventloop
local feed = helpers.feed
+local funcs = helpers.funcs
+local curwin = helpers.curwin
local pcall_err = helpers.pcall_err
describe('winbar', function()
@@ -48,6 +50,11 @@ describe('winbar', function()
{3:~ }|
|
]])
+ -- winbar is excluded from the heights returned by winheight() and getwininfo()
+ eq(11, funcs.winheight(0))
+ local win_info = funcs.getwininfo(curwin().id)[1]
+ eq(11, win_info.height)
+ eq(1, win_info.winbar)
end)
it('works with custom \'fillchars\' value', function()
diff --git a/test/functional/vimscript/eval_spec.lua b/test/functional/vimscript/eval_spec.lua
index 0c2ca8de78..d4fa7afe89 100644
--- a/test/functional/vimscript/eval_spec.lua
+++ b/test/functional/vimscript/eval_spec.lua
@@ -10,11 +10,13 @@
-- test/functional/vimscript/functions_spec.lua
local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
local lfs = require('lfs')
local clear = helpers.clear
local eq = helpers.eq
local exc_exec = helpers.exc_exec
+local exec = helpers.exec
local eval = helpers.eval
local command = helpers.command
local write_file = helpers.write_file
@@ -144,3 +146,104 @@ describe('List support code', function()
end
end)
end)
+
+-- oldtest: Test_deep_nest()
+it('Error when if/for/while/try/function is nested too deep',function()
+ clear()
+ local screen = Screen.new(80, 24)
+ screen:attach()
+ meths.set_option('laststatus', 2)
+ exec([[
+ " Deep nesting of if ... endif
+ func Test1()
+ let @a = join(repeat(['if v:true'], 51), "\n")
+ let @a ..= "\n"
+ let @a ..= join(repeat(['endif'], 51), "\n")
+ @a
+ let @a = ''
+ endfunc
+
+ " Deep nesting of for ... endfor
+ func Test2()
+ let @a = join(repeat(['for i in [1]'], 51), "\n")
+ let @a ..= "\n"
+ let @a ..= join(repeat(['endfor'], 51), "\n")
+ @a
+ let @a = ''
+ endfunc
+
+ " Deep nesting of while ... endwhile
+ func Test3()
+ let @a = join(repeat(['while v:true'], 51), "\n")
+ let @a ..= "\n"
+ let @a ..= join(repeat(['endwhile'], 51), "\n")
+ @a
+ let @a = ''
+ endfunc
+
+ " Deep nesting of try ... endtry
+ func Test4()
+ let @a = join(repeat(['try'], 51), "\n")
+ let @a ..= "\necho v:true\n"
+ let @a ..= join(repeat(['endtry'], 51), "\n")
+ @a
+ let @a = ''
+ endfunc
+
+ " Deep nesting of function ... endfunction
+ func Test5()
+ let @a = join(repeat(['function X()'], 51), "\n")
+ let @a ..= "\necho v:true\n"
+ let @a ..= join(repeat(['endfunction'], 51), "\n")
+ @a
+ let @a = ''
+ endfunc
+ ]])
+ screen:expect({any = '%[No Name%]'})
+ feed(':call Test1()<CR>')
+ screen:expect({any = 'E579: '})
+ feed('<C-C>')
+ screen:expect({any = '%[No Name%]'})
+ feed(':call Test2()<CR>')
+ screen:expect({any = 'E585: '})
+ feed('<C-C>')
+ screen:expect({any = '%[No Name%]'})
+ feed(':call Test3()<CR>')
+ screen:expect({any = 'E585: '})
+ feed('<C-C>')
+ screen:expect({any = '%[No Name%]'})
+ feed(':call Test4()<CR>')
+ screen:expect({any = 'E601: '})
+ feed('<C-C>')
+ screen:expect({any = '%[No Name%]'})
+ feed(':call Test5()<CR>')
+ screen:expect({any = 'E1058: '})
+end)
+
+describe("uncaught exception", function()
+ before_each(clear)
+ after_each(function()
+ os.remove('throw1.vim')
+ os.remove('throw2.vim')
+ os.remove('throw3.vim')
+ end)
+
+ it('is not forgotten #13490', function()
+ command('autocmd BufWinEnter * throw "i am error"')
+ eq('i am error', exc_exec('try | new | endtry'))
+
+ -- Like Vim, throwing here aborts the processing of the script, but does not stop :runtime!
+ -- from processing the others.
+ -- Only the first thrown exception should be rethrown from the :try below, though.
+ for i = 1, 3 do
+ write_file('throw' .. i .. '.vim', ([[
+ let result ..= '%d'
+ throw 'throw%d'
+ let result ..= 'X'
+ ]]):format(i, i))
+ end
+ command('set runtimepath+=. | let result = ""')
+ eq('throw1', exc_exec('try | runtime! throw*.vim | endtry'))
+ eq('123', eval('result'))
+ end)
+end)
diff --git a/test/functional/vimscript/input_spec.lua b/test/functional/vimscript/input_spec.lua
index 554d15e550..f50b39c2c5 100644
--- a/test/functional/vimscript/input_spec.lua
+++ b/test/functional/vimscript/input_spec.lua
@@ -8,7 +8,8 @@ local clear = helpers.clear
local source = helpers.source
local command = helpers.command
local exc_exec = helpers.exc_exec
-local nvim_async = helpers.nvim_async
+local pcall_err = helpers.pcall_err
+local async_meths = helpers.async_meths
local NIL = helpers.NIL
local screen
@@ -449,6 +450,78 @@ describe('inputdialog()', function()
end)
describe('confirm()', function()
+ -- oldtest: Test_confirm()
+ it('works', function()
+ meths.set_option('more', false) -- Avoid hit-enter prompt
+ meths.set_option('laststatus', 2)
+ -- screen:expect() calls are needed to avoid feeding input too early
+ screen:expect({any = '%[No Name%]'})
+
+ async_meths.command([[let a = confirm('Press O to proceed')]])
+ screen:expect({any = '{CONFIRM:.+: }'})
+ feed('o')
+ screen:expect({any = '%[No Name%]'})
+ eq(1, meths.get_var('a'))
+
+ async_meths.command([[let a = 'Are you sure?'->confirm("&Yes\n&No")]])
+ screen:expect({any = '{CONFIRM:.+: }'})
+ feed('y')
+ screen:expect({any = '%[No Name%]'})
+ eq(1, meths.get_var('a'))
+
+ async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]])
+ screen:expect({any = '{CONFIRM:.+: }'})
+ feed('n')
+ screen:expect({any = '%[No Name%]'})
+ eq(2, meths.get_var('a'))
+
+ -- Not possible to match Vim's CTRL-C test here as CTRL-C always sets got_int in Nvim.
+
+ -- confirm() should return 0 when pressing ESC.
+ async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]])
+ screen:expect({any = '{CONFIRM:.+: }'})
+ feed('<Esc>')
+ screen:expect({any = '%[No Name%]'})
+ eq(0, meths.get_var('a'))
+
+ -- Default choice is returned when pressing <CR>.
+ async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]])
+ screen:expect({any = '{CONFIRM:.+: }'})
+ feed('<CR>')
+ screen:expect({any = '%[No Name%]'})
+ eq(1, meths.get_var('a'))
+
+ async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No", 2)]])
+ screen:expect({any = '{CONFIRM:.+: }'})
+ feed('<CR>')
+ screen:expect({any = '%[No Name%]'})
+ eq(2, meths.get_var('a'))
+
+ async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No", 0)]])
+ screen:expect({any = '{CONFIRM:.+: }'})
+ feed('<CR>')
+ screen:expect({any = '%[No Name%]'})
+ eq(0, meths.get_var('a'))
+
+ -- Test with the {type} 4th argument
+ for _, type in ipairs({'Error', 'Question', 'Info', 'Warning', 'Generic'}) do
+ async_meths.command(([[let a = confirm('Are you sure?', "&Yes\n&No", 1, '%s')]]):format(type))
+ screen:expect({any = '{CONFIRM:.+: }'})
+ feed('y')
+ screen:expect({any = '%[No Name%]'})
+ eq(1, meths.get_var('a'))
+ end
+
+ eq('Vim(call):E730: using List as a String',
+ pcall_err(command, 'call confirm([])'))
+ eq('Vim(call):E730: using List as a String',
+ pcall_err(command, 'call confirm("Are you sure?", [])'))
+ eq('Vim(call):E745: Using a List as a Number',
+ pcall_err(command, 'call confirm("Are you sure?", "&Yes\n&No\n", [])'))
+ eq('Vim(call):E730: using List as a String',
+ pcall_err(command, 'call confirm("Are you sure?", "&Yes\n&No\n", 0, [])'))
+ end)
+
it("shows dialog even if :silent #8788", function()
command("autocmd BufNewFile * call confirm('test')")
@@ -483,7 +556,7 @@ describe('confirm()', function()
feed(':call nvim_command("edit x")<cr>')
check_and_clear(':call nvim_command("edit |\n')
- nvim_async('command', 'edit x')
+ async_meths.command('edit x')
check_and_clear(' |\n')
end)
end)
diff --git a/test/unit/path_spec.lua b/test/unit/path_spec.lua
index fb476397e6..eb23a3cff1 100644
--- a/test/unit/path_spec.lua
+++ b/test/unit/path_spec.lua
@@ -640,6 +640,10 @@ describe('path.c', function()
eq(2, path_with_url([[test-abc:\\xyz\foo\b3]]))
eq(0, path_with_url([[-test://xyz/foo/b4]]))
eq(0, path_with_url([[test-://xyz/foo/b5]]))
+ eq(1, path_with_url([[test-C:/xyz/foo/b5]]))
+ eq(1, path_with_url([[test-custom:/xyz/foo/b5]]))
+ eq(0, path_with_url([[c:/xyz/foo/b5]]))
+ eq(0, path_with_url([[C:/xyz/foo/b5]]))
end)
end)
end)